@playcademy/sandbox 0.1.0-beta.9 → 0.1.1
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 +340 -6
- package/dist/cli.js +114018 -67555
- package/dist/config/index.d.ts +10 -0
- package/dist/config/index.js +150 -0
- package/dist/config/mutators.d.ts +4 -0
- package/dist/config/timeback.d.ts +10 -0
- package/dist/config/types.d.ts +23 -0
- package/dist/constants.d.ts +164 -4
- package/dist/database/seed.d.ts +15 -13
- package/dist/lib/auth.d.ts +10 -2
- package/dist/lib/error-handler.d.ts +20 -0
- package/dist/lib/realtime.d.ts +17 -0
- package/dist/pglite.data +0 -0
- package/dist/pglite.wasm +0 -0
- package/dist/routes/achievements.d.ts +3 -0
- package/dist/routes/character.d.ts +3 -0
- package/dist/routes/index.d.ts +8 -0
- package/dist/routes/leaderboard.d.ts +3 -0
- package/dist/routes/lti.d.ts +3 -0
- package/dist/routes/notifications.d.ts +3 -0
- package/dist/routes/realtime.d.ts +3 -0
- package/dist/routes/sprite.d.ts +3 -0
- package/dist/routes/timeback.d.ts +3 -0
- package/dist/server.d.ts +6 -2
- package/dist/server.js +115003 -68564
- package/dist/types.d.ts +13 -2
- package/dist/utils/port.d.ts +17 -0
- package/dist/utils/port.js +54 -0
- package/package.json +21 -7
- package/dist/types.js +0 -1
package/README.md
CHANGED
|
@@ -1,15 +1,349 @@
|
|
|
1
|
-
# sandbox
|
|
1
|
+
# @playcademy/sandbox
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
**Local development server for isolated Playcademy game development.**
|
|
4
|
+
|
|
5
|
+
The Playcademy sandbox provides a complete local simulation of the Playcademy platform, including API services and a real-time server, for development and testing.
|
|
6
|
+
|
|
7
|
+
## What is the Sandbox?
|
|
8
|
+
|
|
9
|
+
The sandbox is a local development server that lets you:
|
|
10
|
+
|
|
11
|
+
- **Develop games locally** with full platform integration.
|
|
12
|
+
- **Test SDK functionality** without needing the live platform.
|
|
13
|
+
- **Simulate user accounts** and game data in a controlled environment.
|
|
14
|
+
- **Work offline** without an internet connection.
|
|
15
|
+
|
|
16
|
+
It's a "mock Playcademy platform" running on your machine that behaves just like the real thing.
|
|
17
|
+
|
|
18
|
+
### Key Benefits
|
|
19
|
+
|
|
20
|
+
- **Isolated Environment**: Completely local execution with no external dependencies.
|
|
21
|
+
- **Zero Configuration**: Automatic database setup and seeding.
|
|
22
|
+
- **Full API Compatibility**: All Playcademy APIs available locally.
|
|
23
|
+
- **Integrated Real-time Server**: Built-in WebSocket server for multiplayer features.
|
|
24
|
+
- **Fast Development Cycle**: Quick startup with an in-memory database.
|
|
25
|
+
|
|
26
|
+
## How It Works
|
|
27
|
+
|
|
28
|
+
The sandbox runs two local servers to provide a complete development environment. When using our Vite templates, this is handled automatically.
|
|
29
|
+
|
|
30
|
+
```mermaid
|
|
31
|
+
graph TD
|
|
32
|
+
subgraph "Your Machine"
|
|
33
|
+
A["Your Game (in browser)"] --> B["@playcademy/sdk"];
|
|
34
|
+
B --> C["API Server (localhost:4321)"];
|
|
35
|
+
B --> D["Real-time Server (localhost:4322)"];
|
|
36
|
+
C --> E["In-Memory Database"];
|
|
37
|
+
D --> E;
|
|
38
|
+
end
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Usage
|
|
42
|
+
|
|
43
|
+
The easiest way to use the sandbox is with our official Vite templates, which handle everything automatically via the `@playcademy/vite-plugin`. You can also run it manually as a standalone CLI for advanced use cases.
|
|
44
|
+
|
|
45
|
+
### Automatic Setup (Recommended)
|
|
46
|
+
|
|
47
|
+
When you start your development server with `bun dev`, the Vite plugin will launch the sandbox in the background.
|
|
48
|
+
|
|
49
|
+
::: code-group
|
|
50
|
+
|
|
51
|
+
```bash [bun]
|
|
52
|
+
bun dev
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
```bash [pnpm]
|
|
56
|
+
pnpm dev
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
```bash [yarn]
|
|
60
|
+
yarn dev
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
```bash [npm]
|
|
64
|
+
npm run dev
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
:::
|
|
68
|
+
|
|
69
|
+
You'll see output confirming that both the API and real-time servers are running:
|
|
70
|
+
|
|
71
|
+
```
|
|
72
|
+
VITE v6.3.5
|
|
73
|
+
|
|
74
|
+
➜ Local: http://localhost:5173/
|
|
75
|
+
➜ Network: use --host to expose
|
|
76
|
+
|
|
77
|
+
PLAYCADEMY v0.1.0
|
|
78
|
+
|
|
79
|
+
➜ Game: playground
|
|
80
|
+
➜ API: http://localhost:4321/api
|
|
81
|
+
➜ Realtime: ws://localhost:4322
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
```typescript
|
|
85
|
+
// vite.config.ts
|
|
86
|
+
import { defineConfig } from 'vite'
|
|
87
|
+
|
|
88
|
+
import { playcademy } from '@playcademy/vite-plugin'
|
|
89
|
+
|
|
90
|
+
export default defineConfig({
|
|
91
|
+
plugins: [
|
|
92
|
+
playcademy({
|
|
93
|
+
sandbox: {
|
|
94
|
+
autoStart: true,
|
|
95
|
+
url: 'http://localhost:4321/api',
|
|
96
|
+
realtime: {
|
|
97
|
+
enabled: true,
|
|
98
|
+
port: 4322,
|
|
99
|
+
},
|
|
100
|
+
},
|
|
101
|
+
}),
|
|
102
|
+
],
|
|
103
|
+
})
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### Manual Setup
|
|
107
|
+
|
|
108
|
+
You can run the sandbox as a standalone process from the command line.
|
|
109
|
+
|
|
110
|
+
::: code-group
|
|
111
|
+
|
|
112
|
+
```bash [bun]
|
|
113
|
+
# Run with defaults
|
|
114
|
+
bunx @playcademy/sandbox
|
|
115
|
+
|
|
116
|
+
# Run with custom ports and verbose logging
|
|
117
|
+
bunx @playcademy/sandbox --port 8080 --realtime --realtime-port 8081 --verbose
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
```bash [pnpm]
|
|
121
|
+
pnpm dlx @playcademy/sandbox --port 8080 --realtime --realtime-port 8081
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
```bash [yarn]
|
|
125
|
+
yarn dlx @playcademy/sandbox --port 8080 --realtime --realtime-port 8081
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
```bash [npm]
|
|
129
|
+
npx @playcademy/sandbox --port 8080 --realtime --realtime-port 8081
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
:::
|
|
133
|
+
|
|
134
|
+
#### Command-Line Options
|
|
135
|
+
|
|
136
|
+
| Option | Alias | Description | Default |
|
|
137
|
+
| :------------------------- | :---- | :--------------------------------------- | :----------- |
|
|
138
|
+
| `--port <number>` | `-p` | Port for the main API server. | `4321` |
|
|
139
|
+
| `--realtime` | | Enables the real-time WebSocket server. | `false` |
|
|
140
|
+
| `--realtime-port <number>` | | Port for the real-time WebSocket server. | API port + 1 |
|
|
141
|
+
| `--verbose` | `-v` | Enables verbose logging for debugging. | `false` |
|
|
142
|
+
| `--no-seed` | | Disables seeding of demo data. | `false` |
|
|
143
|
+
| `--project-name <name>` | | Sets the project name for game seeding. | `undefined` |
|
|
144
|
+
| `--project-slug <slug>` | | Sets the project slug for game seeding. | `undefined` |
|
|
145
|
+
|
|
146
|
+
#### Manual SDK Configuration
|
|
147
|
+
|
|
148
|
+
If you run the sandbox manually, you'll need to configure the SDK client to point to it.
|
|
149
|
+
|
|
150
|
+
```typescript
|
|
151
|
+
import { PlaycademyClient } from '@playcademy/sdk'
|
|
152
|
+
|
|
153
|
+
const client = await PlaycademyClient.init({
|
|
154
|
+
baseUrl: 'http://localhost:4321/api',
|
|
155
|
+
realtimeUrl: 'ws://localhost:4322',
|
|
156
|
+
// In manual mode, you must provide a mock token
|
|
157
|
+
token: 'mock-dev-token',
|
|
158
|
+
})
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
## Sandbox Features
|
|
162
|
+
|
|
163
|
+
| Feature | Description |
|
|
164
|
+
| :------------------- | :-------------------------------------------------------------------------------------------- |
|
|
165
|
+
| **API Simulation** | Emulates the entire Playcademy backend API for users, games, inventory, etc. |
|
|
166
|
+
| **Real-time Server** | Provides WebSocket-based real-time channels for multiplayer communication. |
|
|
167
|
+
| **Data Persistence** | Uses an in-memory database. Data persists until the sandbox is restarted. |
|
|
168
|
+
| **Mock Data** | Automatically seeds with a mock user (`developer@example.com`) and other demo data. |
|
|
169
|
+
| **Game Context** | When run via the Vite plugin, it automatically registers your current project as a mock game. |
|
|
170
|
+
|
|
171
|
+
## Server Endpoints
|
|
172
|
+
|
|
173
|
+
Once running, the sandbox provides several key endpoints:
|
|
174
|
+
|
|
175
|
+
- **Health Check**: `GET /health`
|
|
176
|
+
- **API Base URL**: `/api`
|
|
177
|
+
- **Real-time URL**: `ws://localhost:{realtimePort}`
|
|
178
|
+
|
|
179
|
+
All production Playcademy APIs are available under the `/api` prefix, including `/users`, `/games`, `/inventory`, and more.
|
|
180
|
+
|
|
181
|
+
## TimeBack Integration Testing
|
|
182
|
+
|
|
183
|
+
The sandbox supports three TimeBack modes for flexible development and testing.
|
|
184
|
+
|
|
185
|
+
### Mode 1: Local TimeBack (Recommended for Development)
|
|
186
|
+
|
|
187
|
+
**Use local TimeBack Docker instance for offline development:**
|
|
188
|
+
|
|
189
|
+
```bash
|
|
190
|
+
# Enable local mode
|
|
191
|
+
TIMEBACK_LOCAL=true
|
|
192
|
+
|
|
193
|
+
# Set local TimeBack URLs (different ports)
|
|
194
|
+
TIMEBACK_ONEROSTER_API_URL=http://localhost:9000
|
|
195
|
+
TIMEBACK_CALIPER_API_URL=http://localhost:9001
|
|
196
|
+
|
|
197
|
+
# Optional: pre-seed with course/student IDs
|
|
198
|
+
SANDBOX_TIMEBACK_COURSE_ID=local-dev-course
|
|
199
|
+
SANDBOX_TIMEBACK_STUDENT_ID=local-dev-student
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
**Benefits:**
|
|
203
|
+
|
|
204
|
+
- ✅ No external API dependencies
|
|
205
|
+
- ✅ Works offline
|
|
206
|
+
- ✅ Fast iteration
|
|
207
|
+
- ✅ No real credentials needed
|
|
208
|
+
|
|
209
|
+
**Requirements:**
|
|
210
|
+
|
|
211
|
+
- Install and run `@superbuilders/timeback-local` Docker container
|
|
212
|
+
|
|
213
|
+
### Mode 2: Remote TimeBack (Staging/Production)
|
|
214
|
+
|
|
215
|
+
**Connect to real TimeBack for end-to-end testing:**
|
|
216
|
+
|
|
217
|
+
```bash
|
|
218
|
+
# Required: TimeBack API credentials
|
|
219
|
+
TIMEBACK_ONEROSTER_API_URL=https://api.timeback.org/ims/oneroster
|
|
220
|
+
TIMEBACK_API_CLIENT_ID=your-client-id
|
|
221
|
+
TIMEBACK_API_CLIENT_SECRET=your-client-secret
|
|
222
|
+
TIMEBACK_API_AUTH_URL=https://auth.timeback.org
|
|
223
|
+
|
|
224
|
+
# Optional: pre-seed with existing course/student
|
|
225
|
+
SANDBOX_TIMEBACK_COURSE_ID=your-existing-course-id
|
|
226
|
+
SANDBOX_TIMEBACK_STUDENT_ID=your-student-sourcedId
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
**Benefits:**
|
|
230
|
+
|
|
231
|
+
- ✅ Tests against real TimeBack
|
|
232
|
+
- ✅ See actual events in TimeBack dashboard
|
|
233
|
+
- ✅ Full production simulation
|
|
234
|
+
|
|
235
|
+
**Pre-Seeding (Required for Local Testing):**
|
|
236
|
+
|
|
237
|
+
```bash
|
|
238
|
+
SANDBOX_TIMEBACK_COURSE_ID=your-existing-course-id
|
|
239
|
+
SANDBOX_TIMEBACK_STUDENT_ID=your-existing-student-sourcedId
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
These are **required** (not optional) for local TimeBack testing because the sandbox uses mock authentication. CLI commands like `playcademy timeback setup` won't work against the sandbox - you must use existing TimeBack resources.
|
|
243
|
+
|
|
244
|
+
**How to get these IDs:**
|
|
245
|
+
|
|
246
|
+
1. Run `playcademy timeback setup` against the **platform** once (not sandbox)
|
|
247
|
+
2. Get `courseId` from the output or your TimeBack dashboard
|
|
248
|
+
3. Get `studentId` (sourcedId) from your TimeBack student roster
|
|
249
|
+
4. Set them in `.env` for future local development
|
|
250
|
+
|
|
251
|
+
What they do:
|
|
252
|
+
|
|
253
|
+
- `SANDBOX_TIMEBACK_COURSE_ID` - Links your game to an existing TimeBack course
|
|
254
|
+
- `SANDBOX_TIMEBACK_STUDENT_ID` - Links the sandbox demo user to a real TimeBack student
|
|
255
|
+
|
|
256
|
+
### Mode 3: Disabled (Default)
|
|
257
|
+
|
|
258
|
+
No TimeBack integration. TimeBack routes return errors. This is the default when no TimeBack environment variables are set.
|
|
259
|
+
|
|
260
|
+
### Runtime Testing Workflow
|
|
261
|
+
|
|
262
|
+
Once you have TimeBack credentials and IDs configured:
|
|
4
263
|
|
|
5
264
|
```bash
|
|
6
|
-
|
|
265
|
+
# 1. Start dev server
|
|
266
|
+
bun dev
|
|
267
|
+
|
|
268
|
+
# 2. Test in your game - TimeBack just works!
|
|
269
|
+
client.timeback.endActivity({
|
|
270
|
+
activityData: { activityId: 'test-1' },
|
|
271
|
+
scoreData: { correctQuestions: 8, totalQuestions: 10 },
|
|
272
|
+
timingData: { durationSeconds: 300 }
|
|
273
|
+
})
|
|
274
|
+
|
|
275
|
+
# 3. Check your TimeBack dashboard - events appear in real-time!
|
|
7
276
|
```
|
|
8
277
|
|
|
9
|
-
|
|
278
|
+
**Note on CLI Commands:**
|
|
279
|
+
The sandbox provides TimeBack management endpoints, but CLI commands (`playcademy timeback setup`, `verify`) require Better Auth authentication and won't work against the sandbox. These commands should be run against the platform. Once you have a course/student ID from the platform, set them in your `.env` for local testing.
|
|
280
|
+
|
|
281
|
+
### Available TimeBack Endpoints
|
|
282
|
+
|
|
283
|
+
The sandbox provides these TimeBack endpoints (matching production platform):
|
|
284
|
+
|
|
285
|
+
**Management:**
|
|
286
|
+
|
|
287
|
+
- `GET /api/timeback/integrations/:gameId` - Get integration details
|
|
288
|
+
- `POST /api/timeback/setup` - Create TimeBack integration
|
|
289
|
+
- `DELETE /api/timeback/integrations/:gameId` - Delete integration
|
|
290
|
+
- `GET /api/timeback/verify/:gameId` - Verify OneRoster resources
|
|
291
|
+
- `GET /api/timeback/config/:gameId` - Get TimeBack configuration
|
|
292
|
+
|
|
293
|
+
**Runtime:**
|
|
294
|
+
|
|
295
|
+
- `POST /api/timeback/end-activity` - Submit activity results
|
|
296
|
+
|
|
297
|
+
**XP Queries:**
|
|
298
|
+
|
|
299
|
+
- `GET /api/timeback/xp/today` - Get today's XP
|
|
300
|
+
- `PUT /api/timeback/xp/today` - Update today's XP
|
|
301
|
+
- `GET /api/timeback/xp/total` - Get total XP
|
|
302
|
+
- `GET /api/timeback/xp/history` - Get XP history
|
|
303
|
+
|
|
304
|
+
These use the same api-core handlers as the production platform, ensuring consistency.
|
|
305
|
+
|
|
306
|
+
When properly configured, your game can call `client.timeback.endActivity()` during local development and see real events appear in your TimeBack dashboard.
|
|
307
|
+
|
|
308
|
+
## Debugging
|
|
309
|
+
|
|
310
|
+
### Health Check
|
|
311
|
+
|
|
312
|
+
You can verify the sandbox API server is running by sending a request to its `/health` endpoint.
|
|
10
313
|
|
|
11
314
|
```bash
|
|
12
|
-
|
|
315
|
+
curl -sSL http://localhost:4321/health | jq
|
|
13
316
|
```
|
|
14
317
|
|
|
15
|
-
This
|
|
318
|
+
This should return a JSON object with the status:
|
|
319
|
+
|
|
320
|
+
```json
|
|
321
|
+
{
|
|
322
|
+
"status": "ok",
|
|
323
|
+
"timestamp": "2023-10-27T00:00:00.000Z"
|
|
324
|
+
}
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
### Common Issues
|
|
328
|
+
|
|
329
|
+
| Issue | Solution |
|
|
330
|
+
| :----------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
331
|
+
| **Sandbox doesn't start** | When using Vite, check that `autoStart: true` in `vite.config.ts` and `@playcademy/vite-plugin` is installed. Check terminal for errors. |
|
|
332
|
+
| **API calls return HTML** | This indicates the API server isn't running or is on a different port. Check your sandbox `url` configuration. |
|
|
333
|
+
| **WebSocket connection fails** | Verify the real-time server is enabled (`--realtime` flag or Vite config) and check its port in the console output. |
|
|
334
|
+
| **Port conflicts** | Use the `--port` and `--realtime-port` options to choose different ports. The sandbox will automatically try the next available port if its default is taken. |
|
|
335
|
+
| **Data doesn't persist** | This is expected. The sandbox uses an in-memory database that resets on every restart to ensure a clean state for development. |
|
|
336
|
+
|
|
337
|
+
## Production vs. Sandbox
|
|
338
|
+
|
|
339
|
+
The SDK is designed to work seamlessly in both environments. `PlaycademyClient.init()` automatically detects whether it's running in a production environment or against a local sandbox.
|
|
340
|
+
|
|
341
|
+
| Feature | Sandbox | Production |
|
|
342
|
+
| :----------------- | :-------------- | :-------------------- |
|
|
343
|
+
| **Data** | Mock, temporary | Real user data |
|
|
344
|
+
| **Authentication** | Mock tokens | Secure authentication |
|
|
345
|
+
| **Persistence** | Session only | Permanent |
|
|
346
|
+
|
|
347
|
+
## Contributing
|
|
348
|
+
|
|
349
|
+
The sandbox is a crucial development tool for the Playcademy ecosystem. For contribution guidelines, see the [monorepo CONTRIBUTING.md](../../CONTRIBUTING.md).
|