playcademy 0.27.0 → 0.27.1-beta.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bucket.d.ts +30 -0
- package/dist/bucket.js +39 -60
- package/dist/cli.js +131 -79
- package/dist/constants.d.ts +26 -10
- package/dist/constants.js +21 -12
- package/dist/db.d.ts +295 -3
- package/dist/db.js +5005 -738
- package/dist/index.d.ts +234 -71
- package/dist/index.js +14702 -6636
- package/dist/runtime/dashboard-runtime/index.js +4165 -0
- package/dist/runtime/dashboard-runtime/manifest.json +7 -0
- package/dist/runtime/{backend-runtime → game-runtime}/index.js +2563 -2517
- package/dist/runtime/game-runtime/manifest.json +7 -0
- package/dist/templates/dashboard-env.d.ts.template +63 -0
- package/dist/templates/dashboard-sample-route.ts.template +21 -0
- package/dist/utils.d.ts +163 -4
- package/dist/utils.js +3647 -643
- package/dist/version.js +1 -1
- package/package.json +2 -1
- package/dist/runtime/backend-runtime/manifest.json +0 -7
package/dist/bucket.d.ts
CHANGED
|
@@ -109,6 +109,34 @@ interface IntegrationsConfig {
|
|
|
109
109
|
/** Queues (optional) */
|
|
110
110
|
queues?: Record<string, QueueConfig | boolean>;
|
|
111
111
|
}
|
|
112
|
+
/**
|
|
113
|
+
* Developer dashboard configuration.
|
|
114
|
+
*
|
|
115
|
+
* The dashboard is a separate app in the game's repo, deployed as a sibling
|
|
116
|
+
* worker with `playcademy dashboard deploy`. Auth and session plumbing are
|
|
117
|
+
* platform-managed; the dashboard app itself is just a static SPA build.
|
|
118
|
+
*/
|
|
119
|
+
interface DashboardConfig {
|
|
120
|
+
/** Path to the dashboard app, relative to the config file (default: './dashboard') */
|
|
121
|
+
directory?: string;
|
|
122
|
+
/** Build command run inside the dashboard directory (defaults to the workspace package manager's build script) */
|
|
123
|
+
buildCommand?: string[];
|
|
124
|
+
/** Path to the dashboard build output, relative to the dashboard directory (default: 'dist') */
|
|
125
|
+
buildPath?: string;
|
|
126
|
+
/** Colors for the platform-managed login/invite page (hex); unset uses the built-in palette */
|
|
127
|
+
theme?: DashboardThemeConfig;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Login-page theming. Two seeds — a primary (button, focus, background
|
|
131
|
+
* wash) and a secondary accent — the platform derives the full palette
|
|
132
|
+
* from. Either may be omitted to keep that half of the built-in palette.
|
|
133
|
+
*/
|
|
134
|
+
interface DashboardThemeConfig {
|
|
135
|
+
/** Primary color as a hex string, e.g. '#e0245e' */
|
|
136
|
+
primary?: string;
|
|
137
|
+
/** Secondary/accent color as a hex string, e.g. '#ffd166' */
|
|
138
|
+
secondary?: string;
|
|
139
|
+
}
|
|
112
140
|
/**
|
|
113
141
|
* Unified Playcademy configuration
|
|
114
142
|
* Used for playcademy.config.{js,json}
|
|
@@ -130,6 +158,8 @@ interface PlaycademyConfig {
|
|
|
130
158
|
externalUrl?: string;
|
|
131
159
|
/** Game platform */
|
|
132
160
|
platform?: 'web' | 'godot';
|
|
161
|
+
/** Developer dashboard app (optional) — `true` uses defaults */
|
|
162
|
+
dashboard?: DashboardConfig | boolean;
|
|
133
163
|
/** Integrations (database, custom routes, external services) */
|
|
134
164
|
integrations?: IntegrationsConfig;
|
|
135
165
|
}
|
package/dist/bucket.js
CHANGED
|
@@ -22,62 +22,12 @@ var init_file_loader = __esm({
|
|
|
22
22
|
import { existsSync } from "fs";
|
|
23
23
|
import { join as join8 } from "path";
|
|
24
24
|
|
|
25
|
-
// ../
|
|
26
|
-
var TIMEBACK_ROUTES = {
|
|
27
|
-
END_ACTIVITY: "/integrations/timeback/end-activity",
|
|
28
|
-
GET_XP: "/integrations/timeback/xp",
|
|
29
|
-
GET_MASTERY: "/integrations/timeback/mastery",
|
|
30
|
-
GET_HIGHEST_GRADE_MASTERED: "/integrations/timeback/highest-grade-mastered",
|
|
31
|
-
HEARTBEAT: "/integrations/timeback/heartbeat",
|
|
32
|
-
ADVANCE_COURSE: "/integrations/timeback/advance-course",
|
|
33
|
-
UNENROLL_COURSE: "/integrations/timeback/unenroll-course"
|
|
34
|
-
};
|
|
35
|
-
var TIMEBACK_GAME_METRIC_DECIMAL_PLACES = {
|
|
36
|
-
xp: 1,
|
|
37
|
-
mastery: 0,
|
|
38
|
-
score: 2
|
|
39
|
-
};
|
|
40
|
-
var TIMEBACK_GAME_METRIC_COMPARISON_TOLERANCE = {
|
|
41
|
-
xp: 0.5 / 10 ** TIMEBACK_GAME_METRIC_DECIMAL_PLACES.xp,
|
|
42
|
-
mastery: 0,
|
|
43
|
-
time: 60,
|
|
44
|
-
score: 0.5 / 10 ** TIMEBACK_GAME_METRIC_DECIMAL_PLACES.score
|
|
45
|
-
};
|
|
46
|
-
|
|
47
|
-
// ../constants/src/cloudflare.ts
|
|
48
|
-
var CLOUDFLARE_COMPATIBILITY_DATE = "2025-10-11";
|
|
49
|
-
|
|
50
|
-
// ../edge-play/src/constants.ts
|
|
25
|
+
// ../edge-play/src/lib/constants.ts
|
|
51
26
|
var ASSET_PREFIX = "_assets/";
|
|
52
27
|
var MANIFEST_KEY = "_manifest.json";
|
|
53
28
|
var ASSET_ROUTE_PREFIX = "/api/assets/";
|
|
54
|
-
var ROUTES = {
|
|
55
|
-
/** Route index (lists available routes) */
|
|
56
|
-
INDEX: "/api",
|
|
57
|
-
/** Health check endpoint */
|
|
58
|
-
HEALTH: "/api/health",
|
|
59
|
-
/**
|
|
60
|
-
* Built-in content-addressable asset serving.
|
|
61
|
-
*
|
|
62
|
-
* Serves files from the game's BUCKET (R2) binding under their
|
|
63
|
-
* content-hashed keys, with immutable caching. Registered in the
|
|
64
|
-
* terminal tier so a game's own `server/api/assets/[...path].ts`
|
|
65
|
-
* route supersedes it.
|
|
66
|
-
*/
|
|
67
|
-
ASSETS: `${ASSET_ROUTE_PREFIX}*`,
|
|
68
|
-
/** TimeBack integration routes */
|
|
69
|
-
TIMEBACK: {
|
|
70
|
-
END_ACTIVITY: `/api${TIMEBACK_ROUTES.END_ACTIVITY}`,
|
|
71
|
-
GET_XP: `/api${TIMEBACK_ROUTES.GET_XP}`,
|
|
72
|
-
GET_MASTERY: `/api${TIMEBACK_ROUTES.GET_MASTERY}`,
|
|
73
|
-
GET_HIGHEST_GRADE_MASTERED: `/api${TIMEBACK_ROUTES.GET_HIGHEST_GRADE_MASTERED}`,
|
|
74
|
-
HEARTBEAT: `/api${TIMEBACK_ROUTES.HEARTBEAT}`,
|
|
75
|
-
ADVANCE_COURSE: `/api${TIMEBACK_ROUTES.ADVANCE_COURSE}`,
|
|
76
|
-
UNENROLL_COURSE: `/api${TIMEBACK_ROUTES.UNENROLL_COURSE}`
|
|
77
|
-
}
|
|
78
|
-
};
|
|
79
29
|
|
|
80
|
-
// src/lib/bundle/backend.ts
|
|
30
|
+
// src/lib/bundle/game-backend.ts
|
|
81
31
|
import { join as join6 } from "node:path";
|
|
82
32
|
|
|
83
33
|
// src/constants/api.ts
|
|
@@ -85,11 +35,11 @@ import { join as join2 } from "node:path";
|
|
|
85
35
|
|
|
86
36
|
// src/constants/server.ts
|
|
87
37
|
import { join } from "node:path";
|
|
88
|
-
var
|
|
89
|
-
var
|
|
38
|
+
var GAME_SERVER_ROOT_DIRECTORY = "server";
|
|
39
|
+
var GAME_SERVER_LIB_DIRECTORY = join(GAME_SERVER_ROOT_DIRECTORY, "lib");
|
|
90
40
|
|
|
91
41
|
// src/constants/api.ts
|
|
92
|
-
var
|
|
42
|
+
var GAME_API_ROUTES_DIRECTORY = join2(GAME_SERVER_ROOT_DIRECTORY, "api");
|
|
93
43
|
|
|
94
44
|
// ../better-auth/package.json
|
|
95
45
|
var package_default = {
|
|
@@ -200,6 +150,22 @@ var CLI_DEFAULT_OUTPUTS = {
|
|
|
200
150
|
WORKER_BUNDLE: join5(WORKSPACE_NAME, "worker-bundle.js")
|
|
201
151
|
};
|
|
202
152
|
|
|
153
|
+
// ../constants/src/timeback.ts
|
|
154
|
+
var TIMEBACK_GAME_METRIC_DECIMAL_PLACES = {
|
|
155
|
+
xp: 1,
|
|
156
|
+
mastery: 0,
|
|
157
|
+
score: 2
|
|
158
|
+
};
|
|
159
|
+
var TIMEBACK_GAME_METRIC_COMPARISON_TOLERANCE = {
|
|
160
|
+
xp: 0.5 / 10 ** TIMEBACK_GAME_METRIC_DECIMAL_PLACES.xp,
|
|
161
|
+
mastery: 0,
|
|
162
|
+
time: 60,
|
|
163
|
+
score: 0.5 / 10 ** TIMEBACK_GAME_METRIC_DECIMAL_PLACES.score
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
// ../constants/src/cloudflare.ts
|
|
167
|
+
var CLOUDFLARE_COMPATIBILITY_DATE = "2025-10-11";
|
|
168
|
+
|
|
203
169
|
// src/lib/core/client.ts
|
|
204
170
|
import { PlaycademyClient } from "@playcademy/sdk/internal";
|
|
205
171
|
|
|
@@ -309,6 +275,17 @@ var TIMEBACK_DISCREPANCY_QUEUE_WINDOWS = [
|
|
|
309
275
|
"custom"
|
|
310
276
|
];
|
|
311
277
|
var TIMEBACK_DISCREPANCY_QUEUE_METRICS = ["xp", "mastery", "time", "score"];
|
|
278
|
+
var PLAYCADEMY_SUPPORTED_QTI_INTERACTION_TYPES = [
|
|
279
|
+
"choice",
|
|
280
|
+
"inline-choice",
|
|
281
|
+
"text-entry",
|
|
282
|
+
"order",
|
|
283
|
+
"match",
|
|
284
|
+
"hottext"
|
|
285
|
+
];
|
|
286
|
+
var PLAYCADEMY_SUPPORTED_QTI_INTERACTION_TYPE_SET = new Set(
|
|
287
|
+
PLAYCADEMY_SUPPORTED_QTI_INTERACTION_TYPES
|
|
288
|
+
);
|
|
312
289
|
var TIMEBACK_DISCREPANCY_QUEUE_WINDOW_VALUES = new Set(TIMEBACK_DISCREPANCY_QUEUE_WINDOWS);
|
|
313
290
|
var TIMEBACK_DISCREPANCY_QUEUE_METRIC_VALUES = new Set(TIMEBACK_DISCREPANCY_QUEUE_METRICS);
|
|
314
291
|
|
|
@@ -327,11 +304,13 @@ import {
|
|
|
327
304
|
// src/lib/core/transpile.ts
|
|
328
305
|
import * as esbuild2 from "esbuild";
|
|
329
306
|
|
|
330
|
-
// src/lib/bundle/backend.ts
|
|
331
|
-
function
|
|
307
|
+
// src/lib/bundle/game-backend.ts
|
|
308
|
+
function resolveGameRoutesDir(config) {
|
|
332
309
|
const customRoutes = config?.integrations?.customRoutes;
|
|
333
|
-
|
|
334
|
-
|
|
310
|
+
return typeof customRoutes === "object" && customRoutes.directory || GAME_API_ROUTES_DIRECTORY;
|
|
311
|
+
}
|
|
312
|
+
function getGameRoutesDirectory(projectPath, config) {
|
|
313
|
+
return join6(projectPath, resolveGameRoutesDir(config));
|
|
335
314
|
}
|
|
336
315
|
|
|
337
316
|
// src/lib/bucket/local.ts
|
|
@@ -354,7 +333,7 @@ async function openLocalBucket() {
|
|
|
354
333
|
// src/lib/bucket/dev.ts
|
|
355
334
|
var ASSET_DEV_ROUTE_PREFIX = ASSET_ROUTE_PREFIX;
|
|
356
335
|
function hasCustomAssetsRoute(projectRoot, config) {
|
|
357
|
-
const routesDir =
|
|
336
|
+
const routesDir = getGameRoutesDirectory(projectRoot, config);
|
|
358
337
|
return existsSync(join8(routesDir, "assets")) || existsSync(join8(routesDir, "assets.ts"));
|
|
359
338
|
}
|
|
360
339
|
function openLocalAssetBucket() {
|