@playcademy/sdk 0.0.1-beta.27 → 0.0.1-beta.29
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 +500 -136
- package/dist/core/client.d.ts +104 -16
- package/dist/core/namespaces/admin.d.ts +16 -12
- package/dist/core/namespaces/character.d.ts +146 -0
- package/dist/core/namespaces/dev.d.ts +8 -8
- package/dist/core/namespaces/games.d.ts +55 -2
- package/dist/core/namespaces/index.d.ts +5 -0
- package/dist/core/namespaces/leaderboard.d.ts +48 -0
- package/dist/core/namespaces/maps.d.ts +68 -1
- package/dist/core/namespaces/realtime.d.ts +40 -0
- package/dist/core/namespaces/runtime.d.ts +180 -2
- package/dist/core/namespaces/scores.d.ts +55 -0
- package/dist/core/namespaces/sprites.d.ts +32 -0
- package/dist/core/namespaces/users.d.ts +52 -0
- package/dist/index.js +713 -265
- package/dist/messaging.d.ts +13 -1
- package/dist/types.d.ts +1 -0
- package/dist/types.js +450 -259
- package/package.json +4 -3
package/README.md
CHANGED
|
@@ -1,184 +1,548 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @playcademy/sdk
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
**Official TypeScript SDK for the Playcademy platform**
|
|
4
|
+
|
|
5
|
+
The Playcademy SDK provides a comprehensive, type-safe interface for building games on the Playcademy platform. It handles authentication, game sessions, user data, inventory management, and all platform APIs through a unified client interface.
|
|
4
6
|
|
|
5
7
|
## Overview
|
|
6
8
|
|
|
7
|
-
|
|
9
|
+
The SDK serves as the primary interface between your game and the Playcademy platform, providing:
|
|
10
|
+
|
|
11
|
+
- **Automatic Environment Detection**: Seamlessly works in development and production
|
|
12
|
+
- **Type-Safe API Access**: Full TypeScript support with comprehensive type definitions
|
|
13
|
+
- **Session Management**: Automatic game session handling and state persistence
|
|
14
|
+
- **Event System**: Real-time notifications for inventory changes, level ups, and more
|
|
15
|
+
- **Developer Tools**: Built-in support for game development and testing workflows
|
|
16
|
+
|
|
17
|
+
### Key Benefits
|
|
18
|
+
|
|
19
|
+
- **Zero Configuration**: Automatic initialization with environment detection
|
|
20
|
+
- **Production Ready**: Battle-tested API patterns with robust error handling
|
|
21
|
+
- **Real-Time Events**: Subscribe to platform events like inventory changes and level ups
|
|
22
|
+
- **Comprehensive Coverage**: Access to all Playcademy platform features
|
|
23
|
+
- **Development Experience**: Integrated with sandbox environment for local development
|
|
24
|
+
|
|
25
|
+
### Use Cases
|
|
8
26
|
|
|
9
|
-
|
|
27
|
+
- **Game Development**: Primary SDK for building games on Playcademy
|
|
28
|
+
- **Web Applications**: Frontend applications interacting with the platform
|
|
29
|
+
- **Developer Tools**: Scripts and utilities for game management
|
|
30
|
+
- **Server Integration**: Backend services integrating with Playcademy APIs
|
|
31
|
+
- **Testing & Automation**: Automated testing of platform integrations
|
|
32
|
+
|
|
33
|
+
## Installation
|
|
34
|
+
|
|
35
|
+
Install the SDK using your preferred package manager:
|
|
10
36
|
|
|
11
37
|
```bash
|
|
38
|
+
# Using Bun (recommended)
|
|
12
39
|
bun add @playcademy/sdk
|
|
13
|
-
|
|
40
|
+
|
|
41
|
+
# Using npm
|
|
14
42
|
npm install @playcademy/sdk
|
|
15
|
-
|
|
43
|
+
|
|
44
|
+
# Using yarn
|
|
16
45
|
yarn add @playcademy/sdk
|
|
17
|
-
|
|
46
|
+
|
|
47
|
+
# Using pnpm
|
|
18
48
|
pnpm add @playcademy/sdk
|
|
19
49
|
```
|
|
20
50
|
|
|
21
|
-
##
|
|
51
|
+
## Quick Start
|
|
52
|
+
|
|
53
|
+
### Automatic Initialization (Recommended)
|
|
54
|
+
|
|
55
|
+
For most game development scenarios, use automatic initialization:
|
|
56
|
+
|
|
57
|
+
```typescript
|
|
58
|
+
import { PlaycademyClient } from '@playcademy/sdk'
|
|
59
|
+
|
|
60
|
+
async function initializeGame() {
|
|
61
|
+
try {
|
|
62
|
+
// Automatic initialization - detects environment and configures appropriately
|
|
63
|
+
const client = await PlaycademyClient.init()
|
|
64
|
+
|
|
65
|
+
// Get current user
|
|
66
|
+
const user = await client.users.me()
|
|
67
|
+
console.log('Welcome,', user.name)
|
|
68
|
+
|
|
69
|
+
// The client is ready for all platform operations
|
|
70
|
+
return client
|
|
71
|
+
} catch (error) {
|
|
72
|
+
console.error('Failed to initialize Playcademy SDK:', error)
|
|
73
|
+
throw error
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### Environment Detection
|
|
79
|
+
|
|
80
|
+
The SDK automatically detects and configures for different environments:
|
|
81
|
+
|
|
82
|
+
- **Development**: Connects to local sandbox (started by `@playcademy/vite-plugin`)
|
|
83
|
+
- **Production**: Receives configuration from Playcademy platform loader
|
|
84
|
+
- **Testing**: Falls back to mock configuration for automated testing
|
|
85
|
+
|
|
86
|
+
## Core Features
|
|
87
|
+
|
|
88
|
+
### Game Session Management
|
|
89
|
+
|
|
90
|
+
```typescript
|
|
91
|
+
// Automatic session management when gameId is available
|
|
92
|
+
const client = await PlaycademyClient.init()
|
|
93
|
+
|
|
94
|
+
// Save transient game state (position, health, temporary data)
|
|
95
|
+
await client.games.saveState({
|
|
96
|
+
currentLevel: 'forest_glade',
|
|
97
|
+
playerPosition: { x: 100, y: 200 },
|
|
98
|
+
health: 85,
|
|
99
|
+
activePowerUps: ['speed_boost'],
|
|
100
|
+
})
|
|
101
|
+
|
|
102
|
+
// Load previously saved state
|
|
103
|
+
const gameState = await client.games.loadState()
|
|
104
|
+
console.log('Loaded state:', gameState)
|
|
105
|
+
|
|
106
|
+
// Exit game (automatically ends session if managed)
|
|
107
|
+
await client.runtime.exit()
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### User & Inventory Management
|
|
111
|
+
|
|
112
|
+
```typescript
|
|
113
|
+
// Get user information
|
|
114
|
+
const user = await client.users.me()
|
|
115
|
+
|
|
116
|
+
// Inventory operations (accepts UUIDs or slugs)
|
|
117
|
+
const inventory = await client.users.inventory.get()
|
|
118
|
+
await client.users.inventory.add('magic-sword', 1)
|
|
119
|
+
await client.users.inventory.remove('health-potion', 1)
|
|
120
|
+
|
|
121
|
+
// Check item quantities and ownership
|
|
122
|
+
const goldCount = await client.users.inventory.quantity('gold-coin')
|
|
123
|
+
const hasKey = await client.users.inventory.has('dungeon-key')
|
|
124
|
+
const hasEnoughGold = await client.users.inventory.has('gold-coin', 100)
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### Credits & Currency
|
|
22
128
|
|
|
23
|
-
|
|
129
|
+
```typescript
|
|
130
|
+
// Platform currency management
|
|
131
|
+
const balance = await client.credits.balance()
|
|
132
|
+
await client.credits.add(100)
|
|
133
|
+
await client.credits.spend(50)
|
|
24
134
|
|
|
25
|
-
|
|
135
|
+
// Check affordability
|
|
136
|
+
if ((await client.credits.balance()) >= 100) {
|
|
137
|
+
await client.credits.spend(100)
|
|
138
|
+
console.log('Purchase successful!')
|
|
139
|
+
}
|
|
140
|
+
```
|
|
26
141
|
|
|
27
|
-
|
|
28
|
-
import { initFromWindow } from '@playcademy/sdk'
|
|
142
|
+
### Experience & Levels
|
|
29
143
|
|
|
30
|
-
|
|
31
|
-
|
|
144
|
+
```typescript
|
|
145
|
+
// Level management
|
|
146
|
+
const userLevel = await client.levels.get()
|
|
147
|
+
const progress = await client.levels.progress()
|
|
148
|
+
console.log(`Level ${userLevel.currentLevel}, ${progress.xpToNextLevel} XP to next level`)
|
|
149
|
+
|
|
150
|
+
// Add experience points
|
|
151
|
+
const result = await client.levels.addXP(100)
|
|
152
|
+
if (result.leveledUp) {
|
|
153
|
+
console.log(`Level up! ${result.oldLevel} → ${result.newLevel}`)
|
|
154
|
+
console.log('Credits awarded:', result.creditsAwarded)
|
|
155
|
+
}
|
|
32
156
|
```
|
|
33
157
|
|
|
34
|
-
|
|
158
|
+
## API Reference
|
|
159
|
+
|
|
160
|
+
### Core Modules
|
|
161
|
+
|
|
162
|
+
#### **Authentication** (`client.auth`)
|
|
163
|
+
|
|
164
|
+
- `logout()`: Logs out user and clears authentication token
|
|
165
|
+
|
|
166
|
+
#### **Users** (`client.users`)
|
|
167
|
+
|
|
168
|
+
- `me()`: Get current user information
|
|
169
|
+
- **Inventory** (`client.users.inventory`):
|
|
170
|
+
- `get()`: Get user's inventory
|
|
171
|
+
- `add(identifier, quantity)`: Add items to inventory
|
|
172
|
+
- `remove(identifier, quantity)`: Remove items from inventory
|
|
173
|
+
- `quantity(identifier)`: Get item quantity
|
|
174
|
+
- `has(identifier, minQuantity?)`: Check item ownership
|
|
175
|
+
|
|
176
|
+
#### **Games** (`client.games`)
|
|
177
|
+
|
|
178
|
+
- `list()`: Get all available games
|
|
179
|
+
- `fetch(gameIdOrSlug)`: Get specific game details
|
|
180
|
+
- `saveState(state)`: Save transient game state
|
|
181
|
+
- `loadState()`: Load saved game state
|
|
182
|
+
- `startSession(gameId?)`: Start game session
|
|
183
|
+
- `endSession(sessionId, gameId?)`: End game session
|
|
184
|
+
|
|
185
|
+
#### **Credits** (`client.credits`)
|
|
186
|
+
|
|
187
|
+
- `balance()`: Get current credits balance
|
|
188
|
+
- `add(amount)`: Add credits to user
|
|
189
|
+
- `spend(amount)`: Spend user credits
|
|
190
|
+
|
|
191
|
+
#### **Levels** (`client.levels`)
|
|
192
|
+
|
|
193
|
+
- `get()`: Get current user level information
|
|
194
|
+
- `progress()`: Get level progress and XP to next level
|
|
195
|
+
- `addXP(amount)`: Add experience points
|
|
196
|
+
- **Config** (`client.levels.config`):
|
|
197
|
+
- `list()`: Get all level configurations
|
|
198
|
+
- `get(level)`: Get specific level configuration
|
|
199
|
+
|
|
200
|
+
#### **Maps** (`client.maps`)
|
|
201
|
+
|
|
202
|
+
- `elements(mapId)`: Get map elements and points of interest
|
|
203
|
+
|
|
204
|
+
#### **Runtime** (`client.runtime`)
|
|
205
|
+
|
|
206
|
+
- `getGameToken(gameId, options?)`: Get game-specific authentication token
|
|
207
|
+
- `exit()`: Signal platform to exit game view
|
|
208
|
+
|
|
209
|
+
#### **Leaderboard** (`client.leaderboard`) - Game-specific
|
|
210
|
+
|
|
211
|
+
- `fetch(options?)`: Get leaderboard for a specific game
|
|
212
|
+
- `options.timeframe`: Filter by time period (`'all_time'`, `'monthly'`, `'weekly'`, `'daily'`)
|
|
213
|
+
- `options.gameId`: Game ID to fetch leaderboard for (required)
|
|
214
|
+
- `options.limit`: Number of entries to return (default: 10)
|
|
215
|
+
- `options.offset`: Pagination offset (default: 0)
|
|
216
|
+
|
|
217
|
+
#### **Scores** (`client.scores`) - Platform-wide
|
|
218
|
+
|
|
219
|
+
- `submit(gameId, score, metadata?)`: Submit a score for any game
|
|
220
|
+
- `getUserScores(userId, options?)`: Get all scores for a user
|
|
221
|
+
- `options.gameId`: Filter by specific game (optional)
|
|
222
|
+
- `options.limit`: Number of scores to return (default: 50)
|
|
223
|
+
|
|
224
|
+
### Developer Tools
|
|
225
|
+
|
|
226
|
+
#### **Developer Authentication** (`client.dev.auth`)
|
|
227
|
+
|
|
228
|
+
- `applyForDeveloper()`: Apply for developer status
|
|
229
|
+
- `getDeveloperStatus()`: Check current developer status
|
|
230
|
+
|
|
231
|
+
#### **Game Management** (`client.dev.games`)
|
|
232
|
+
|
|
233
|
+
- `upsert(slug, metadata, gameFile)`: Create or update game
|
|
234
|
+
- `update(gameId, updates)`: Update game properties
|
|
235
|
+
- `delete(gameId)`: Delete game
|
|
236
|
+
|
|
237
|
+
#### **API Keys** (`client.dev.keys`)
|
|
238
|
+
|
|
239
|
+
- `createKey(gameId, name)`: Create API key for server authentication
|
|
240
|
+
- `listKeys()`: List all API keys
|
|
241
|
+
- `revokeKey(keyId)`: Revoke API key
|
|
242
|
+
|
|
243
|
+
#### **Item Management** (`client.dev.items`)
|
|
244
|
+
|
|
245
|
+
- `list(gameId)`: List all items for a game
|
|
246
|
+
- `get(gameId, slug)`: Get specific item
|
|
247
|
+
- `create(gameId, slug, data)`: Create new game item
|
|
248
|
+
- `update(gameId, itemId, updates)`: Update existing item
|
|
249
|
+
- `delete(gameId, itemId)`: Delete item
|
|
250
|
+
|
|
251
|
+
## Event System
|
|
252
|
+
|
|
253
|
+
The SDK provides real-time event notifications for important platform changes:
|
|
254
|
+
|
|
255
|
+
### Available Events
|
|
256
|
+
|
|
257
|
+
```typescript
|
|
258
|
+
// Authentication changes
|
|
259
|
+
client.on('authChange', payload => {
|
|
260
|
+
console.log('Authentication changed:', payload.token)
|
|
261
|
+
})
|
|
35
262
|
|
|
36
|
-
|
|
263
|
+
// Inventory changes
|
|
264
|
+
client.on('inventoryChange', payload => {
|
|
265
|
+
console.log(`Item ${payload.itemId}: ${payload.delta} (total: ${payload.newTotal})`)
|
|
266
|
+
})
|
|
37
267
|
|
|
38
|
-
|
|
268
|
+
// Experience gained
|
|
269
|
+
client.on('xpGained', payload => {
|
|
270
|
+
console.log(`Gained ${payload.amount} XP (total: ${payload.totalXP})`)
|
|
271
|
+
})
|
|
272
|
+
|
|
273
|
+
// Level up notifications
|
|
274
|
+
client.on('levelUp', payload => {
|
|
275
|
+
console.log(`Level up! ${payload.oldLevel} → ${payload.newLevel}`)
|
|
276
|
+
console.log('Credits awarded:', payload.creditsAwarded)
|
|
277
|
+
})
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
### Event-Driven UI Updates
|
|
281
|
+
|
|
282
|
+
```typescript
|
|
283
|
+
// Update UI in response to platform events
|
|
284
|
+
client.on('inventoryChange', payload => {
|
|
285
|
+
updateInventoryDisplay(payload.itemId, payload.newTotal)
|
|
286
|
+
})
|
|
287
|
+
|
|
288
|
+
client.on('levelUp', payload => {
|
|
289
|
+
showLevelUpAnimation(payload.newLevel)
|
|
290
|
+
showCreditsAwarded(payload.creditsAwarded)
|
|
291
|
+
})
|
|
292
|
+
|
|
293
|
+
client.on('xpGained', payload => {
|
|
294
|
+
updateXPBar(payload.totalXP, payload.leveledUp)
|
|
295
|
+
})
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
## Advanced Usage
|
|
299
|
+
|
|
300
|
+
### Manual Initialization
|
|
301
|
+
|
|
302
|
+
For server-side applications or custom environments:
|
|
303
|
+
|
|
304
|
+
```typescript
|
|
39
305
|
import { PlaycademyClient } from '@playcademy/sdk'
|
|
40
306
|
|
|
41
307
|
import type { LoginResponse } from '@playcademy/sdk'
|
|
42
308
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
309
|
+
// Step 1: Authenticate
|
|
310
|
+
const loginData: LoginResponse = await PlaycademyClient.login(
|
|
311
|
+
'https://api.playcademy.com',
|
|
312
|
+
'user@example.com',
|
|
313
|
+
'password',
|
|
314
|
+
)
|
|
315
|
+
|
|
316
|
+
// Step 2: Initialize client
|
|
317
|
+
const client = new PlaycademyClient({
|
|
318
|
+
baseUrl: 'https://api.playcademy.com',
|
|
319
|
+
token: loginData.token,
|
|
320
|
+
gameId: 'your-game-id', // Optional: enables automatic session management
|
|
321
|
+
})
|
|
322
|
+
```
|
|
46
323
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
324
|
+
### Custom Configuration
|
|
325
|
+
|
|
326
|
+
```typescript
|
|
327
|
+
const client = new PlaycademyClient({
|
|
328
|
+
baseUrl: 'https://api.playcademy.com',
|
|
329
|
+
token: 'your-auth-token',
|
|
330
|
+
gameId: 'your-game-id',
|
|
331
|
+
// Additional options
|
|
332
|
+
timeout: 10000, // Request timeout in milliseconds
|
|
333
|
+
retries: 3, // Number of retry attempts
|
|
334
|
+
})
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
### Error Handling
|
|
338
|
+
|
|
339
|
+
```typescript
|
|
340
|
+
import { PlaycademyError } from '@playcademy/sdk'
|
|
341
|
+
|
|
342
|
+
try {
|
|
343
|
+
const user = await client.users.me()
|
|
344
|
+
// Handle success
|
|
345
|
+
} catch (error) {
|
|
346
|
+
if (error instanceof PlaycademyError) {
|
|
347
|
+
console.error('Playcademy API Error:', error.message)
|
|
348
|
+
console.error('Status Code:', error.statusCode)
|
|
349
|
+
console.error('Error Code:', error.code)
|
|
350
|
+
} else {
|
|
351
|
+
console.error('Unexpected error:', error)
|
|
53
352
|
}
|
|
353
|
+
}
|
|
354
|
+
```
|
|
54
355
|
|
|
55
|
-
|
|
56
|
-
// Optionally provide a gameId to enable automatic session management for that game.
|
|
57
|
-
const client = new PlaycademyClient({
|
|
58
|
-
baseUrl: baseUrl,
|
|
59
|
-
token: loginResponse.token,
|
|
60
|
-
// gameId: 'your-game-id' // Optional: if provided, client attempts to auto-start/end session
|
|
61
|
-
})
|
|
356
|
+
## Development Environment
|
|
62
357
|
|
|
63
|
-
|
|
64
|
-
// client.dev.games.upsert(...)
|
|
65
|
-
// client.admin.items.createItem(...)
|
|
66
|
-
// Calling a method without sufficient token permissions will result in a server error.
|
|
358
|
+
### Integration with Playcademy Vite Plugin
|
|
67
359
|
|
|
68
|
-
|
|
69
|
-
client.onAuthChange(token => {
|
|
70
|
-
console.log('Authentication token changed:', token)
|
|
71
|
-
// You might want to update stored token here
|
|
72
|
-
})
|
|
360
|
+
When using the official Playcademy Vite templates, the development environment is automatically configured:
|
|
73
361
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
}
|
|
362
|
+
```typescript
|
|
363
|
+
// In your game's main file
|
|
364
|
+
import { PlaycademyClient } from '@playcademy/sdk'
|
|
77
365
|
|
|
78
|
-
|
|
366
|
+
// The vite plugin automatically starts the sandbox
|
|
367
|
+
const client = await PlaycademyClient.init()
|
|
368
|
+
// SDK automatically connects to local sandbox at http://localhost:4321
|
|
79
369
|
```
|
|
80
370
|
|
|
81
|
-
|
|
371
|
+
### Manual Sandbox Setup
|
|
82
372
|
|
|
83
|
-
|
|
84
|
-
import { initFromWindow } from '@playcademy/sdk'
|
|
373
|
+
If not using the Vite plugin, start the sandbox manually:
|
|
85
374
|
|
|
86
|
-
|
|
87
|
-
|
|
375
|
+
```bash
|
|
376
|
+
# Start sandbox server
|
|
377
|
+
bunx @playcademy/sandbox --port 4321 --verbose
|
|
378
|
+
|
|
379
|
+
# In your application
|
|
380
|
+
const client = new PlaycademyClient({
|
|
381
|
+
baseUrl: 'http://localhost:4321/api',
|
|
382
|
+
token: 'dev-token' // Sandbox provides mock authentication
|
|
383
|
+
})
|
|
384
|
+
```
|
|
88
385
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
386
|
+
## Best Practices
|
|
387
|
+
|
|
388
|
+
### Initialization & Setup
|
|
389
|
+
|
|
390
|
+
- **Always use automatic initialization** for game development with `PlaycademyClient.init()`
|
|
391
|
+
- **Handle initialization errors gracefully** with proper try-catch blocks
|
|
392
|
+
- **Store the client instance** for reuse throughout your application lifecycle
|
|
393
|
+
|
|
394
|
+
### State Management
|
|
395
|
+
|
|
396
|
+
- **Use `games.saveState()`** for transient data (current level, position, temporary status)
|
|
397
|
+
- **Use `users.inventory`** for persistent items and resources that carry between sessions
|
|
398
|
+
- **Save state periodically**, not on every frame or minor change
|
|
399
|
+
- **Load state once** at game start, then manage locally
|
|
400
|
+
|
|
401
|
+
### Performance Optimization
|
|
402
|
+
|
|
403
|
+
- **Cache frequently accessed data** like user information and inventory
|
|
404
|
+
- **Batch inventory operations** when possible instead of individual API calls
|
|
405
|
+
- **Use event listeners** to update UI reactively rather than polling
|
|
406
|
+
- **Implement proper loading states** for better user experience
|
|
407
|
+
|
|
408
|
+
### Error Handling
|
|
409
|
+
|
|
410
|
+
- **Wrap all SDK calls** in appropriate try-catch blocks
|
|
411
|
+
- **Provide fallback behavior** for network errors and API failures
|
|
412
|
+
- **Show meaningful error messages** to users when operations fail
|
|
413
|
+
- **Implement retry logic** for non-critical operations
|
|
414
|
+
|
|
415
|
+
### Development Workflow
|
|
416
|
+
|
|
417
|
+
- **Use the sandbox environment** for all local development
|
|
418
|
+
- **Test both online and offline scenarios** to ensure robust error handling
|
|
419
|
+
- **Enable verbose logging** during development for debugging
|
|
420
|
+
- **Validate API responses** and handle edge cases appropriately
|
|
421
|
+
|
|
422
|
+
## Testing
|
|
423
|
+
|
|
424
|
+
### Unit Testing
|
|
425
|
+
|
|
426
|
+
```typescript
|
|
427
|
+
// Mock the SDK for unit tests
|
|
428
|
+
import { jest } from '@jest/globals'
|
|
429
|
+
|
|
430
|
+
// Mock the entire SDK module
|
|
431
|
+
jest.mock('@playcademy/sdk', () => ({
|
|
432
|
+
PlaycademyClient: {
|
|
433
|
+
init: jest.fn().mockResolvedValue({
|
|
434
|
+
users: {
|
|
435
|
+
me: jest.fn().mockResolvedValue({ id: 'test-user', name: 'Test User' }),
|
|
436
|
+
inventory: {
|
|
437
|
+
get: jest.fn().mockResolvedValue([]),
|
|
438
|
+
add: jest.fn().mockResolvedValue(undefined),
|
|
439
|
+
},
|
|
440
|
+
},
|
|
441
|
+
}),
|
|
442
|
+
},
|
|
443
|
+
}))
|
|
444
|
+
```
|
|
445
|
+
|
|
446
|
+
### Integration Testing
|
|
447
|
+
|
|
448
|
+
```typescript
|
|
449
|
+
// Test with real sandbox
|
|
450
|
+
import { PlaycademyClient } from '@playcademy/sdk'
|
|
451
|
+
|
|
452
|
+
describe('Playcademy Integration', () => {
|
|
453
|
+
let client: PlaycademyClient
|
|
454
|
+
|
|
455
|
+
beforeAll(async () => {
|
|
456
|
+
// Initialize with sandbox
|
|
457
|
+
client = new PlaycademyClient({
|
|
458
|
+
baseUrl: 'http://localhost:4321/api',
|
|
459
|
+
token: 'test-token',
|
|
102
460
|
})
|
|
103
|
-
|
|
461
|
+
})
|
|
104
462
|
|
|
105
|
-
|
|
106
|
-
const
|
|
107
|
-
|
|
463
|
+
test('should fetch user data', async () => {
|
|
464
|
+
const user = await client.users.me()
|
|
465
|
+
expect(user).toBeDefined()
|
|
466
|
+
expect(user.name).toEqual(expect.any(String))
|
|
467
|
+
})
|
|
468
|
+
})
|
|
469
|
+
```
|
|
108
470
|
|
|
109
|
-
|
|
110
|
-
await client.games.endSession(sessionId)
|
|
111
|
-
console.log('Session ended')
|
|
471
|
+
## Troubleshooting
|
|
112
472
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
473
|
+
### Common Issues
|
|
474
|
+
|
|
475
|
+
**SDK Initialization Timeout**
|
|
476
|
+
|
|
477
|
+
```
|
|
478
|
+
Error: PLAYCADEMY_INIT not received within 5000ms
|
|
479
|
+
```
|
|
480
|
+
|
|
481
|
+
- Ensure you're running in the correct environment (development with sandbox, or production with platform)
|
|
482
|
+
- Check that the Vite plugin is properly configured
|
|
483
|
+
- Verify the sandbox is running on the expected port
|
|
484
|
+
|
|
485
|
+
**Authentication Errors**
|
|
486
|
+
|
|
487
|
+
```
|
|
488
|
+
Error: Unauthorized (401)
|
|
489
|
+
```
|
|
490
|
+
|
|
491
|
+
- Check that your authentication token is valid
|
|
492
|
+
- Ensure you have the necessary permissions for the operation
|
|
493
|
+
- Try re-authenticating with `PlaycademyClient.login()`
|
|
494
|
+
|
|
495
|
+
**Network Connection Issues**
|
|
496
|
+
|
|
497
|
+
```
|
|
498
|
+
Error: Failed to fetch
|
|
499
|
+
```
|
|
500
|
+
|
|
501
|
+
- Verify the API endpoint is accessible
|
|
502
|
+
- Check network connectivity
|
|
503
|
+
- Ensure CORS is properly configured for cross-origin requests
|
|
504
|
+
|
|
505
|
+
### Debugging
|
|
506
|
+
|
|
507
|
+
Use these debugging techniques for troubleshooting SDK issues:
|
|
508
|
+
|
|
509
|
+
```typescript
|
|
510
|
+
// Check initialization process
|
|
511
|
+
try {
|
|
512
|
+
const client = await PlaycademyClient.init()
|
|
513
|
+
console.log('SDK initialized successfully')
|
|
514
|
+
} catch (error) {
|
|
515
|
+
console.error('SDK initialization failed:', error)
|
|
118
516
|
}
|
|
119
517
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
-
|
|
131
|
-
- `logout()`: Logs out the current user and clears the token from the client instance.
|
|
132
|
-
- **`onAuthChange(callback)`**: A top-level client method to subscribe to authentication token changes (login, logout, explicit `setToken`).
|
|
133
|
-
- **`users`**:
|
|
134
|
-
- `me()`: Fetch current user details.
|
|
135
|
-
- **`inventory`**:
|
|
136
|
-
- `get()`: Get player inventory.
|
|
137
|
-
- `add(identifier, qty)`: Add item to player inventory (accepts UUID or internal name).
|
|
138
|
-
- `remove(identifier, qty)`: Remove item from player inventory (accepts UUID or internal name).
|
|
139
|
-
- `quantity(identifier)`: Get current quantity of an item (accepts UUID or internal name).
|
|
140
|
-
- `has(identifier, minQuantity?)`: Check if user has enough of an item (accepts UUID or internal name).
|
|
141
|
-
- **`progress`**: Manages persistent progress data for a game (e.g., levels completed, scores, collectibles).
|
|
142
|
-
- `get(gameId?)`: Get the entire progress state for a game. `gameId` is optional and defaults to the client's current game context.
|
|
143
|
-
- `update(data, gameId?)`: Update the progress state for a game. `gameId` is optional. The `data` object can be structured to hold progress for various internal nodes or aspects of the game.
|
|
144
|
-
- **`credits`**: Convenient methods for working with Playcademy Credits (primary platform currency).
|
|
145
|
-
- `balance()`: Get current credits balance.
|
|
146
|
-
- `add(amount)`: Add credits to user.
|
|
147
|
-
- `spend(amount)`: Spend credits from user.
|
|
148
|
-
- **`games`**: Manages game sessions and transient game state.
|
|
149
|
-
- `fetch(gameIdOrSlug)`: Fetch game details with manifest.
|
|
150
|
-
- `list()`: List all games.
|
|
151
|
-
- `saveState(state)`: Save transient game state (e.g., current position, temporary buffs) for the current game context.
|
|
152
|
-
- `loadState()`: Load transient game state for the current game context.
|
|
153
|
-
- `startSession(gameId?)`: Start a game session. `gameId` is optional and defaults to `client.gameId` if set. If the client is managing an automatic session, this can be used to start additional, distinct sessions.
|
|
154
|
-
- `endSession(sessionId, gameId?)`: End a game session. `gameId` is optional. If this ends an automatically managed session, the client will no longer attempt to auto-end it.
|
|
155
|
-
- **`runtime`**:
|
|
156
|
-
- `getGameToken(gameId, options?: { apply?: boolean })`: Fetches a game-specific token. If `options.apply` is true, it sets this token as the active token on the client instance (default is false).
|
|
157
|
-
- `exit()`: Signals the hosting environment to close the game view. If the client is managing an automatic session (because `gameId` was provided at construction), this method will attempt to end that session before signaling exit.
|
|
158
|
-
- **`maps`**:
|
|
159
|
-
- `elements(mapId)`: Fetch elements (like nodes, points of interest) for a specific map.
|
|
160
|
-
- **`dev.auth`**: Apply for developer status, get status.
|
|
161
|
-
- **`dev.games`**: Upsert, update, delete games.
|
|
162
|
-
- **`dev.keys`**: Create, list, revoke API keys for games.
|
|
163
|
-
- **`admin.games`**: Pause/resume games.
|
|
164
|
-
- **`admin.items`**: CRUD operations for items.
|
|
165
|
-
- **`admin.currencies`**: CRUD operations for currencies.
|
|
166
|
-
- **`admin.shopListings`**: CRUD operations for shop listings.
|
|
167
|
-
- **`shop`**: Player-facing shop operations.
|
|
168
|
-
- `view()`: Get shop items and currency information.
|
|
169
|
-
- **`levels`**: Player level and experience point management.
|
|
170
|
-
- `get()`: Get current user level information.
|
|
171
|
-
- `progress()`: Get level progress with XP to next level.
|
|
172
|
-
- `addXP(amount)`: Add XP to user.
|
|
173
|
-
- **`config`**:
|
|
174
|
-
- `list()`: Get all level configurations (full XP curve).
|
|
175
|
-
- `get(level)`: Get configuration for a specific level.
|
|
176
|
-
- **`telemetry`**: Push metrics.
|
|
518
|
+
// Monitor network requests in browser dev tools (Network tab)
|
|
519
|
+
// Check console for SDK error messages
|
|
520
|
+
// Verify API responses and error details
|
|
521
|
+
```
|
|
522
|
+
|
|
523
|
+
### Getting Help
|
|
524
|
+
|
|
525
|
+
- Check the [platform documentation](../../apps/docs/) for detailed guides
|
|
526
|
+
- Review the [Vite plugin configuration](../vite-plugin/) for development setup
|
|
527
|
+
- Examine the [game templates](../../templates/) for working examples
|
|
528
|
+
- Use browser dev tools to inspect network requests and responses
|
|
177
529
|
|
|
178
530
|
## Contributing
|
|
179
531
|
|
|
180
|
-
|
|
532
|
+
The SDK is a critical component of the Playcademy platform ecosystem. When contributing:
|
|
533
|
+
|
|
534
|
+
1. **Maintain Type Safety**: Ensure all new APIs are fully typed
|
|
535
|
+
2. **Update Documentation**: Keep this README and JSDoc comments current
|
|
536
|
+
3. **Add Tests**: Include both unit and integration tests for new features
|
|
537
|
+
4. **Follow Patterns**: Use consistent patterns with existing SDK methods
|
|
538
|
+
5. **Handle Errors**: Implement proper error handling and user feedback
|
|
539
|
+
|
|
540
|
+
For general contribution guidelines, see the [monorepo CONTRIBUTING.md](../../CONTRIBUTING.md).
|
|
181
541
|
|
|
182
|
-
##
|
|
542
|
+
## Related Packages
|
|
183
543
|
|
|
184
|
-
|
|
544
|
+
- [`@playcademy/api-core`](../api-core/): API handlers used by the SDK
|
|
545
|
+
- [`@playcademy/data`](../data/): Database schema and type definitions
|
|
546
|
+
- [`@playcademy/vite-plugin`](../vite-plugin/): Development environment integration
|
|
547
|
+
- [`@playcademy/sandbox`](../sandbox/): Local development server
|
|
548
|
+
- **Game Templates**: See `/templates` for example integrations
|