playcademy 0.32.1-beta.2 → 0.33.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/dist/bucket.d.ts CHANGED
@@ -1,7 +1,237 @@
1
- import { GamePermission } from '@playcademy/constants';
2
- import { TimebackCourseConfig, CourseConfig, OrganizationConfig, ComponentConfig, ResourceConfig, ComponentResourceConfig } from '@playcademy/types/timeback';
3
1
  import { Miniflare } from 'miniflare';
4
2
 
3
+ /**
4
+ * Browser permissions a game may declare and the hub may delegate to its
5
+ * iframe. Opt-in per game because a delegated grant keys to the hub's
6
+ * top-level origin: one player grant would otherwise reach every embedded
7
+ * game. Baseline features (fullscreen, autoplay, gamepad) are delegated to
8
+ * all games and are not part of this set.
9
+ */
10
+ declare const GAME_PERMISSIONS: readonly ['microphone', 'camera'];
11
+ type GamePermission = (typeof GAME_PERMISSIONS)[number];
12
+
13
+ /**
14
+ * Valid grade levels per AE OneRoster GradeEnum.
15
+ * -1 = Pre-K, 0 = Kindergarten, 1-12 = Grades 1-12, 13 = AP
16
+ */
17
+ declare const TIMEBACK_GRADES: readonly [-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13];
18
+ /**
19
+ * The TimeBack subject vocabulary, carried on courses, activity data, and
20
+ * Caliper events alike. 'None' is canonical: TimeBack accepts it as a course
21
+ * subject and uses it as the fallback for unknown or missing subjects.
22
+ */
23
+ declare const TIMEBACK_SUBJECTS: readonly ['Reading', 'Language', 'Vocabulary', 'Social Studies', 'Writing', 'Science', 'FastMath', 'Math', 'None'];
24
+
25
+ /**
26
+ * TimeBack Enums & Literal Types
27
+ *
28
+ * Basic type definitions used throughout the TimeBack integration. Unions
29
+ * derive from the canonical value lists in @playcademy/constants (type-only
30
+ * imports, so this package ships no runtime code).
31
+ *
32
+ * @module types/timeback/types
33
+ */
34
+
35
+ /**
36
+ * The TimeBack subject vocabulary. 'None' is canonical: TimeBack accepts it
37
+ * on courses and uses it as the fallback for unknown or missing subjects.
38
+ */
39
+ type TimebackSubject = (typeof TIMEBACK_SUBJECTS)[number];
40
+ /**
41
+ * Grade levels per AE OneRoster GradeEnum.
42
+ * -1 = Pre-K, 0 = Kindergarten, 1-12 = Grades 1-12, 13 = AP
43
+ */
44
+ type TimebackGrade = (typeof TIMEBACK_GRADES)[number];
45
+ /**
46
+ * OneRoster organization types.
47
+ */
48
+ type OrganizationType = 'department' | 'school' | 'district' | 'local' | 'state' | 'national';
49
+ /**
50
+ * Lesson types for PowerPath integration.
51
+ */
52
+ type LessonType = 'powerpath-100' | 'quiz' | 'test-out' | 'placement' | 'unit-test' | 'alpha-read-article' | null;
53
+
54
+ /**
55
+ * TimeBack Configuration Types
56
+ *
57
+ * Configuration interfaces for Organization, Course, Component,
58
+ * Resource, and complete TimeBack setup.
59
+ *
60
+ * @module types/timeback/config
61
+ */
62
+
63
+ /**
64
+ * Organization configuration for TimeBack (user input - optionals allowed)
65
+ */
66
+ interface OrganizationConfig {
67
+ /** Display name for your organization */
68
+ name?: string;
69
+ /** Organization type */
70
+ type?: OrganizationType;
71
+ /** Unique identifier (defaults to Playcademy's org) */
72
+ identifier?: string;
73
+ }
74
+ /**
75
+ * Course goals for daily student targets
76
+ */
77
+ interface CourseGoals {
78
+ /** Target XP students should earn per day */
79
+ dailyXp?: number;
80
+ /** Target lessons per day */
81
+ dailyLessons?: number;
82
+ /** Target active minutes per day */
83
+ dailyActiveMinutes?: number;
84
+ /** Target accuracy percentage */
85
+ dailyAccuracy?: number;
86
+ /** Target mastered units per day */
87
+ dailyMasteredUnits?: number;
88
+ }
89
+ /**
90
+ * Course metrics and totals
91
+ */
92
+ interface CourseMetrics {
93
+ /** Total XP available in the course */
94
+ totalXp?: number;
95
+ /** Total lessons/activities in the course */
96
+ totalLessons?: number;
97
+ /** Total number of grade levels covered by this course */
98
+ totalGrades?: number;
99
+ /** The type of course (e.g. 'optional', 'hole-filling', 'base') */
100
+ courseType?: 'base' | 'hole-filling' | 'optional' | 'Base' | 'Hole-Filling' | 'Optional';
101
+ /** Indicates whether the course is supplemental content */
102
+ isSupplemental?: boolean;
103
+ }
104
+ /**
105
+ * Complete course metadata structure
106
+ */
107
+ interface CourseMetadata {
108
+ /** Define the type of course and priority for the student */
109
+ courseType?: 'base' | 'hole-filling' | 'optional';
110
+ /** Boolean value to determine if a course is supplemental to a base course */
111
+ isSupplemental?: boolean;
112
+ /** Boolean value to determine if a course is custom to an individual student */
113
+ isCustom?: boolean;
114
+ /** Signals whether a course is in production with students */
115
+ publishStatus?: 'draft' | 'testing' | 'published' | 'deactivated';
116
+ /** Whether this course appears in the TimeBack catalog for teachers and parents */
117
+ timebackVisible?: boolean;
118
+ /** Who to contact when issues reported with questions */
119
+ contactEmail?: string;
120
+ /** Primary app identifier */
121
+ primaryApp?: string;
122
+ /** Learning goals for students */
123
+ goals?: CourseGoals;
124
+ /** Course metrics and totals */
125
+ metrics?: CourseMetrics;
126
+ /** Vendor-specific metadata (e.g., AlphaLearn) */
127
+ [key: string]: unknown;
128
+ }
129
+ /**
130
+ * Course configuration for TimeBack (user input)
131
+ */
132
+ interface CourseConfig {
133
+ /** Allocated OneRoster sourcedId (set after creation) */
134
+ sourcedId?: string;
135
+ /** Course title (defaults to game name) */
136
+ title?: string;
137
+ /** Subjects (REQUIRED for TimeBack integration) */
138
+ subjects: TimebackSubject[];
139
+ /** Used when recording progress/sessions if not explicitly specified per event. */
140
+ defaultSubject?: TimebackSubject;
141
+ /** Grade levels (REQUIRED for TimeBack integration) */
142
+ grades: TimebackGrade[];
143
+ /** Short course code (optional, auto-generated) */
144
+ courseCode?: string;
145
+ /** Course level (auto-derived from grades) */
146
+ level?: 'Elementary' | 'Middle' | 'High' | 'AP' | string;
147
+ /** Grading system */
148
+ gradingScheme?: 'STANDARD';
149
+ /** Total XP available in this course (REQUIRED before setup) */
150
+ totalXp?: number | null;
151
+ /** Total masterable units in this course (REQUIRED before setup) */
152
+ masterableUnits?: number | null;
153
+ /** Custom Playcademy metadata */
154
+ metadata?: CourseMetadata;
155
+ }
156
+ /**
157
+ * Component configuration for TimeBack (user input)
158
+ */
159
+ interface ComponentConfig {
160
+ /** Component title (defaults to "{course.title} Activities") */
161
+ title?: string;
162
+ /** Display order */
163
+ sortOrder?: number;
164
+ /** Required prior components */
165
+ prerequisites?: string[];
166
+ /** How prerequisites work */
167
+ prerequisiteCriteria?: 'ALL' | 'ANY';
168
+ }
169
+ /**
170
+ * Playcademy-specific resource extensions
171
+ */
172
+ interface PlaycademyResourceMetadata {
173
+ /** Mastery configuration for tracking discrete learning units */
174
+ mastery?: {
175
+ /** Total number of masterable units in the resource */
176
+ masterableUnits: number;
177
+ /** Type of mastery unit for semantic clarity */
178
+ unitType?: 'level' | 'rank' | 'skill' | 'module';
179
+ };
180
+ }
181
+ /**
182
+ * Resource configuration for TimeBack (user input)
183
+ */
184
+ interface ResourceConfig {
185
+ /** Resource title (defaults to "{course.title} Game") */
186
+ title?: string;
187
+ /** Internal resource ID (auto-generated from package.json) */
188
+ vendorResourceId?: string;
189
+ /** Vendor identifier */
190
+ vendorId?: string;
191
+ /** Application identifier */
192
+ applicationId?: string;
193
+ /** Resource roles */
194
+ roles?: ('primary' | 'secondary')[];
195
+ /** Resource importance */
196
+ importance?: 'primary' | 'secondary';
197
+ /** Interactive resource metadata */
198
+ metadata?: {
199
+ /** Resource type */
200
+ type?: 'interactive';
201
+ /** Launch URL (defaults to Playcademy game URL) */
202
+ launchUrl?: string;
203
+ /** Platform name */
204
+ toolProvider?: string;
205
+ /** Teaching method */
206
+ instructionalMethod?: 'exploratory' | 'direct-instruction';
207
+ /** Subject area */
208
+ subject?: TimebackSubject;
209
+ /** Target grades */
210
+ grades?: TimebackGrade[];
211
+ /** Content language */
212
+ language?: string;
213
+ /** Base XP for completion */
214
+ xp?: number;
215
+ /** Playcademy-specific extensions */
216
+ playcademy?: PlaycademyResourceMetadata;
217
+ };
218
+ }
219
+ /**
220
+ * Component Resource link configuration (user input)
221
+ */
222
+ interface ComponentResourceConfig {
223
+ /** Link title (defaults to "{resource.title} Activity") */
224
+ title?: string;
225
+ /** Display order */
226
+ sortOrder?: number;
227
+ /** Lesson type for PowerPath integration */
228
+ lessonType?: LessonType;
229
+ }
230
+ interface TimebackCourseConfig {
231
+ subject: string;
232
+ grade: number;
233
+ }
234
+
5
235
  /**
6
236
  * @fileoverview Server SDK Type Definitions
7
237
  *
package/dist/bucket.js CHANGED
@@ -42,7 +42,7 @@ var GAME_API_ROUTES_DIRECTORY = `${GAME_SERVER_ROOT_DIRECTORY}/api`;
42
42
  // ../better-auth/package.json
43
43
  var package_default = {
44
44
  name: "@playcademy/better-auth",
45
- version: "0.0.25-beta.2",
45
+ version: "0.0.25",
46
46
  type: "module",
47
47
  exports: {
48
48
  "./server": {
package/dist/cli.js CHANGED
@@ -1208,7 +1208,7 @@ var SAMPLE_BUCKET_FILENAME = "bucket.ts";
1208
1208
  // ../better-auth/package.json
1209
1209
  var package_default = {
1210
1210
  name: "@playcademy/better-auth",
1211
- version: "0.0.25-beta.2",
1211
+ version: "0.0.25",
1212
1212
  type: "module",
1213
1213
  exports: {
1214
1214
  "./server": {
@@ -3045,7 +3045,7 @@ import { existsSync as existsSync11, mkdirSync as mkdirSync5, readFileSync as re
3045
3045
  import { join as join12 } from "node:path";
3046
3046
 
3047
3047
  // src/version.ts
3048
- var cliVersion = false ? "0.0.0-dev" : "0.32.1-beta.2";
3048
+ var cliVersion = false ? "0.0.0-dev" : "0.33.0";
3049
3049
 
3050
3050
  // src/lib/init/database.ts
3051
3051
  var drizzleConfigTemplate = loadTemplateString("database/drizzle-config.ts");
package/dist/constants.js CHANGED
@@ -21,7 +21,7 @@ var SAMPLE_BUCKET_FILENAME = "bucket.ts";
21
21
  // ../better-auth/package.json
22
22
  var package_default = {
23
23
  name: "@playcademy/better-auth",
24
- version: "0.0.25-beta.2",
24
+ version: "0.0.25",
25
25
  type: "module",
26
26
  exports: {
27
27
  "./server": {
package/dist/db.d.ts CHANGED
@@ -1,4 +1,3 @@
1
- import { DeployMigration, DeploymentStateResponse, DeployBaseline, BaselineMigrationEvidence, DeploymentStateBaselineRequest, MigrationResolution, GameRestorePoint, DatabaseRestoreResponse, SeedLogEntry } from '@playcademy/types';
2
1
  import { Miniflare } from 'miniflare';
3
2
 
4
3
  /**
@@ -30,6 +29,244 @@ import { Miniflare } from 'miniflare';
30
29
  */
31
30
  declare function getDevDbPath(): string;
32
31
 
32
+ /**
33
+ * Game Types
34
+ *
35
+ * Literal types and API DTOs. Database row types are in @playcademy/data/types.
36
+ *
37
+ * @module types/game
38
+ */
39
+
40
+ /** One migration in a migrate-mode deploy payload */
41
+ interface DeployMigration {
42
+ /** Journal tag, e.g. '0042_brave_hulk' */
43
+ tag: string;
44
+ /** Pre-split SQL statements (the CLI splits on drizzle statement-breakpoints) */
45
+ statements: string[];
46
+ /** sha-256 of the normalized migration SQL (sha256-v1) */
47
+ checksum: string;
48
+ }
49
+ /** Journal entry in a baseline adoption block */
50
+ interface DeployBaselineJournalEntry {
51
+ tag: string;
52
+ checksum: string;
53
+ }
54
+ /**
55
+ * Baseline adoption block (PLA-217 D7 seed-on-deploy): the client's claimed
56
+ * starting state for a game that predates server-side deployment state.
57
+ * Consumed by the deploy itself — an unadopted game gets its claimed ledger
58
+ * rows, snapshot/hash, and live fingerprint recorded before the database
59
+ * step runs; adopted games skip the block.
60
+ */
61
+ interface DeployBaseline {
62
+ lastAppliedMigrationTag?: string;
63
+ journal?: DeployBaselineJournalEntry[];
64
+ /**
65
+ * Per-migration snapshot deltas for content validation (D7): the
66
+ * seed claim is judged against the live database exactly like a
67
+ * manual `db baseline` claim — the side door uses the front door's
68
+ * checkpoint.
69
+ */
70
+ evidence?: BaselineMigrationEvidence[];
71
+ schemaSnapshot?: unknown;
72
+ schemaHash?: string;
73
+ integrationsHash?: string;
74
+ buildHash?: string;
75
+ }
76
+ /** Active game worker state served by the deployment-state endpoint */
77
+ interface DeploymentStateGame {
78
+ /** Backend bundle hash from the active deployment row */
79
+ codeHash: string | null;
80
+ /** Frontend zip hash from game_deployment_state (null when unseeded) */
81
+ buildHash: string | null;
82
+ url: string;
83
+ deployedAt: string;
84
+ }
85
+ /** Active dashboard worker state served by the deployment-state endpoint */
86
+ interface DeploymentStateDashboard {
87
+ url: string;
88
+ deployedAt: string;
89
+ }
90
+ /** Details of the last failed migration, from the failed deploy job */
91
+ interface DeploymentStateDatabaseFailure {
92
+ tag: string;
93
+ error: string;
94
+ /**
95
+ * Set only when the failing statement is known exactly (the size
96
+ * preflight names the statement it measured). Execution failures are
97
+ * null: D1's byte offset has an unverified reference frame for the
98
+ * batch array form, so it is never mapped to an index.
99
+ */
100
+ statementIndex: number | null;
101
+ at: string;
102
+ }
103
+ /** A ledger entry from the game database's applied-migrations ledger */
104
+ interface DeploymentStateAppliedMigration {
105
+ tag: string;
106
+ /** Checksum recorded at apply time (normalized SQL, see checksumAlgo) */
107
+ checksum: string;
108
+ /** Hash algorithm the checksum was recorded under (e.g. 'sha256-v1') */
109
+ checksumAlgo: string;
110
+ }
111
+ /** Database schema state served by the deployment-state endpoint */
112
+ interface DeploymentStateDatabase {
113
+ /** Applied migrations from the live in-D1 ledger (null when the game has no database) */
114
+ appliedMigrations: DeploymentStateAppliedMigration[] | null;
115
+ lastFailure: DeploymentStateDatabaseFailure | null;
116
+ /** Hash of the drizzle snapshot (push-mode baseline) */
117
+ schemaHash: string | null;
118
+ /** Hash of the normalized live sqlite_master */
119
+ schemaFingerprint: string | null;
120
+ /**
121
+ * Stored drizzle snapshot (push-mode diffing only). Present only when
122
+ * the request asked for it with `?include=schemaSnapshot` (D4).
123
+ */
124
+ schemaSnapshot?: unknown;
125
+ }
126
+ /** Secret key names partitioned by ownership — names only, never hashes */
127
+ interface DeploymentStateSecrets {
128
+ /** Keys recorded in the server-side secrets manifest */
129
+ managedKeys: string[];
130
+ /**
131
+ * Remote keys not in the manifest (set by SST, wrangler, or hand).
132
+ * Null when the server has no Cloudflare provider to list remote keys.
133
+ */
134
+ unmanagedKeys: string[] | null;
135
+ }
136
+ interface DeploymentStateLastDeploy {
137
+ at: string;
138
+ /** Who deployed: their email, or the raw user id when the account no longer resolves */
139
+ by: string;
140
+ }
141
+ /**
142
+ * Server-side deployment state for a game.
143
+ *
144
+ * Everything CLI deploy prep diffs against, fetched from
145
+ * GET /api/games/:slug/deployment-state so deploys never depend on
146
+ * local state for correctness.
147
+ */
148
+ interface DeploymentStateResponse {
149
+ gameId: string;
150
+ /** True iff a game_deployment_state row exists for the game */
151
+ seeded: boolean;
152
+ game: DeploymentStateGame | null;
153
+ dashboard: DeploymentStateDashboard | null;
154
+ database: DeploymentStateDatabase;
155
+ secrets: DeploymentStateSecrets;
156
+ /** Hash of the declared integrations config (null when unseeded) */
157
+ integrationsHash: string | null;
158
+ /** Last deployed compatibility date (null when unseeded) */
159
+ compatibilityDate: string | null;
160
+ lastDeploy: DeploymentStateLastDeploy | null;
161
+ }
162
+ /**
163
+ * Manual baseline adoption request (PLA-217 D7): the fresh-machine path for
164
+ * a game that predates server-side deployment state. Carries the claimed
165
+ * migrate-mode history (tag + journal), the push-mode snapshot, or both.
166
+ */
167
+ interface DeploymentStateBaselineRequest {
168
+ lastAppliedMigrationTag?: string;
169
+ journal?: DeployBaselineJournalEntry[];
170
+ schemaSnapshot?: unknown;
171
+ schemaHash?: string;
172
+ /**
173
+ * Per-migration schema-object evidence (creates AND drops) derived
174
+ * from drizzle's snapshot files. The server replays it up to the
175
+ * claimed tag into the expected schema and validates that against the
176
+ * live database (D7): surviving claimed objects must exist,
177
+ * beyond-claim objects must be absent unless claimed history already
178
+ * explains them. Absent evidence downgrades every migration to
179
+ * no-signal.
180
+ */
181
+ evidence?: BaselineMigrationEvidence[];
182
+ /**
183
+ * Waive refusals for no-signal migrations only (content contradictions
184
+ * are never waivable). Recorded server-side for audit.
185
+ */
186
+ allowUnverified?: boolean;
187
+ }
188
+ /**
189
+ * Schema objects one journal migration introduced and removed (snapshot
190
+ * delta). Drops are as load-bearing as creates: an object created by one
191
+ * migration and dropped by a later one must not be demanded of the live
192
+ * database, and its live presence beyond the claim must not convict a
193
+ * migration whose object is already explained by claimed history.
194
+ */
195
+ interface BaselineMigrationEvidence {
196
+ tag: string;
197
+ /** Journal generation timestamp (drizzle `when`), ISO 8601 */
198
+ generatedAt: string;
199
+ createsTables: {
200
+ name: string;
201
+ columns: string[];
202
+ }[];
203
+ addsColumns: {
204
+ table: string;
205
+ column: string;
206
+ }[];
207
+ createsIndexes: string[];
208
+ createsViews: string[];
209
+ dropsTables: string[];
210
+ dropsColumns: {
211
+ table: string;
212
+ column: string;
213
+ }[];
214
+ dropsIndexes: string[];
215
+ dropsViews: string[];
216
+ }
217
+ /** How a ledger escape-hatch resolution lands: record the row, or remove it */
218
+ type MigrationResolution = 'applied' | 'rolled-back';
219
+ /**
220
+ * A restorable pre-deploy database state (D1 Time Travel bookmark).
221
+ *
222
+ * Each schema-bearing deploy captures a bookmark of the database as it was
223
+ * the moment before that deploy's schema changes ran. Only bookmarks
224
+ * belonging to the CURRENT database and within Time Travel's retention
225
+ * window are served — a `db reset` creates a new database (bookmarks do
226
+ * not cross that boundary), and Cloudflare expires bookmarks after the
227
+ * account plan's retention period.
228
+ */
229
+ interface GameRestorePoint {
230
+ /** Deployment row id — pass to the restore endpoint (or a unique prefix to the CLI) */
231
+ id: string;
232
+ /**
233
+ * When the bookmark was captured (the exact state a restore rewinds
234
+ * to), ISO 8601. Rows from before capture times were recorded fall
235
+ * back to the deploy completion time.
236
+ */
237
+ capturedAt: string;
238
+ /** Whether the capturing deployment is the currently active one */
239
+ active: boolean;
240
+ }
241
+ /** Outcome of a Time Travel restore (PLA-217 D10) */
242
+ interface DatabaseRestoreResponse {
243
+ restorePointId: string;
244
+ /** The moment the database was rewound to (the bookmark's capture time), ISO 8601 */
245
+ restoredTo: string;
246
+ /**
247
+ * Live schema fingerprint captured after the restore: the developer's
248
+ * audited attestation that the rewound state is intended, so the next
249
+ * deploy verifies against it.
250
+ */
251
+ schemaFingerprint: string;
252
+ /** False when the game has no deployment-state row to re-attest */
253
+ fingerprintRecorded: boolean;
254
+ /**
255
+ * Bookmark of the database as it was just before this restore — the
256
+ * undo handle. Null only if Cloudflare omits it from the response.
257
+ */
258
+ previousBookmark: string | null;
259
+ }
260
+ /** Log entry captured from seed worker console output */
261
+ interface SeedLogEntry {
262
+ /** Log level (log, warn, error, info) */
263
+ level: 'log' | 'warn' | 'error' | 'info';
264
+ /** Log message content */
265
+ message: string;
266
+ /** Milliseconds since seed execution started */
267
+ timestamp: number;
268
+ }
269
+
33
270
  /**
34
271
  * Schema deployment planning (PLA-217 D5)
35
272
  *
package/dist/db.js CHANGED
@@ -2333,7 +2333,7 @@ var GAME_API_ROUTES_DIRECTORY = `${GAME_SERVER_ROOT_DIRECTORY}/api`;
2333
2333
  // ../better-auth/package.json
2334
2334
  var package_default = {
2335
2335
  name: "@playcademy/better-auth",
2336
- version: "0.0.25-beta.2",
2336
+ version: "0.0.25",
2337
2337
  type: "module",
2338
2338
  exports: {
2339
2339
  "./server": {