@playcademy/sdk 0.16.1-beta.8 → 0.17.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.
@@ -142,6 +142,19 @@ interface DashboardThemeConfig {
142
142
  /** Secondary/accent color as a hex string, e.g. '#ffd166' */
143
143
  secondary?: string;
144
144
  }
145
+ /**
146
+ * Child-catalog contract generation (see @playcademy/sdk/contracts).
147
+ * The extractor is a repo-local script (run with the CLI's runtime) that
148
+ * prints `{ generatedFrom, deliveries }` as JSON on stdout; the CLI
149
+ * validates, stamps the contract fields, and writes
150
+ * `.playcademy/catalog.json` deterministically. The document carries no
151
+ * app identity — consuming repos assign the namespace key from sync
152
+ * provenance.
153
+ */
154
+ interface CatalogConfig {
155
+ /** Path to the extractor script, relative to the config file. */
156
+ extractor: string;
157
+ }
145
158
  /**
146
159
  * Unified Playcademy configuration
147
160
  * Used for playcademy.config.{js,json}
@@ -174,6 +187,8 @@ interface PlaycademyConfig {
174
187
  dashboard?: DashboardConfig | boolean;
175
188
  /** Integrations (database, custom routes, external services) */
176
189
  integrations?: IntegrationsConfig;
190
+ /** Child-catalog contract generation (`playcademy catalog`) */
191
+ catalog?: CatalogConfig;
177
192
  }
178
193
 
179
194
  /**
@@ -359,7 +374,8 @@ declare class PlaycademyClient {
359
374
  latest: (studentId: string, options: _playcademy_types.GetLatestAssessmentOptions) => Promise<_playcademy_types.LatestAssessmentResult | null>;
360
375
  get: (studentId: string, attemptId: string) => Promise<_playcademy_types.AssessmentAttemptSnapshot>;
361
376
  save: (studentId: string, attemptId: string, input: _playcademy_types.SaveAssessmentInput) => Promise<_playcademy_types.AssessmentSaveResult>;
362
- submit: (studentId: string, attemptId: string, input: _playcademy_types.SubmitAssessmentInput, context: {
377
+ submitItem: (studentId: string, attemptId: string, input: _playcademy_types.SubmitAssessmentItemInput) => Promise<_playcademy_types.SubmitAssessmentItemResult>;
378
+ submit: (studentId: string, attemptId: string, input: _playcademy_types.SubmitAssessmentRequest, context: {
363
379
  sensorUrl: string;
364
380
  }) => Promise<_playcademy_types.AssessmentSubmitResult>;
365
381
  };
@@ -18,6 +18,8 @@ var DEFAULT_PERSONAL_API_KEY_PERMISSIONS = {
18
18
  };
19
19
  // ../constants/src/platform.ts
20
20
  var PLAYCADEMY_BROWSER_TIME_ZONE_HEADER = "x-playcademy-browser-time-zone";
21
+ var PLAYCADEMY_ASSESSMENT_ASSET_SHA256_HEADER = "x-playcademy-content-sha256";
22
+ var ASSESSMENT_ASSET_MAX_BYTES = 4 * 1024 * 1024;
21
23
  // ../constants/src/timeback.ts
22
24
  var TIMEBACK_ROUTES = {
23
25
  END_ACTIVITY: "/integrations/timeback/end-activity",
@@ -41,10 +43,10 @@ var TIMEBACK_SUBJECTS = [
41
43
  "Math",
42
44
  "None"
43
45
  ];
44
- var ASSESSMENT_PURPOSES = ["end_of_course", "diagnostic", "review"];
46
+ var ASSESSMENT_PURPOSES = ["end_of_course", "diagnostic", "review", "mastery"];
45
47
  var TIMEBACK_ASSESSMENT_REVIEW_REQUEST_LIMITS = {
46
48
  standards: 20,
47
- itemsPerStandard: 5,
49
+ candidateItemsPerStandard: 2,
48
50
  standardFieldLength: 128
49
51
  };
50
52
  var VALID_E_LEVELS = ["E1", "E2", "E3", "E4"];
@@ -97,6 +99,10 @@ function createTimebackNamespace(client) {
97
99
  if (options.grade !== undefined) {
98
100
  params.set("grade", String(options.grade));
99
101
  }
102
+ if (options.purpose === "mastery") {
103
+ params.set("standardFramework", options.standard.framework);
104
+ params.set("standardIdentifier", options.standard.identifier);
105
+ }
100
106
  return client["request"](`/api/timeback/assessments/latest?${params.toString()}`, "GET");
101
107
  },
102
108
  get: (studentId, attemptId) => {
@@ -104,6 +110,7 @@ function createTimebackNamespace(client) {
104
110
  return client["request"](`/api/timeback/assessments/${encodeURIComponent(attemptId)}?${params.toString()}`, "GET");
105
111
  },
106
112
  save: (studentId, attemptId, input) => client["request"](`/api/timeback/assessments/${encodeURIComponent(attemptId)}/save`, "POST", { ...input, gameId: client.gameId, studentId }),
113
+ submitItem: (studentId, attemptId, input) => client["request"](`/api/timeback/assessments/${encodeURIComponent(attemptId)}/submit-item`, "POST", { ...input, gameId: client.gameId, studentId }),
107
114
  submit: (studentId, attemptId, input, context) => client["request"](`/api/timeback/assessments/${encodeURIComponent(attemptId)}/submit`, "POST", {
108
115
  ...input,
109
116
  gameId: client.gameId,
@@ -308,7 +315,7 @@ function extractApiErrorInfo(error) {
308
315
  }
309
316
 
310
317
  // src/version.ts
311
- var SDK_VERSION = "0.16.1-beta.8";
318
+ var SDK_VERSION = "0.17.0";
312
319
 
313
320
  // src/server/request.ts
314
321
  async function makeApiRequest(opts) {
package/dist/server.d.ts CHANGED
@@ -142,6 +142,19 @@ interface DashboardThemeConfig {
142
142
  /** Secondary/accent color as a hex string, e.g. '#ffd166' */
143
143
  secondary?: string;
144
144
  }
145
+ /**
146
+ * Child-catalog contract generation (see @playcademy/sdk/contracts).
147
+ * The extractor is a repo-local script (run with the CLI's runtime) that
148
+ * prints `{ generatedFrom, deliveries }` as JSON on stdout; the CLI
149
+ * validates, stamps the contract fields, and writes
150
+ * `.playcademy/catalog.json` deterministically. The document carries no
151
+ * app identity — consuming repos assign the namespace key from sync
152
+ * provenance.
153
+ */
154
+ interface CatalogConfig {
155
+ /** Path to the extractor script, relative to the config file. */
156
+ extractor: string;
157
+ }
145
158
  /**
146
159
  * Unified Playcademy configuration
147
160
  * Used for playcademy.config.{js,json}
@@ -174,6 +187,8 @@ interface PlaycademyConfig {
174
187
  dashboard?: DashboardConfig | boolean;
175
188
  /** Integrations (database, custom routes, external services) */
176
189
  integrations?: IntegrationsConfig;
190
+ /** Child-catalog contract generation (`playcademy catalog`) */
191
+ catalog?: CatalogConfig;
177
192
  }
178
193
 
179
194
  /**
@@ -359,7 +374,8 @@ declare class PlaycademyClient$1 {
359
374
  latest: (studentId: string, options: _playcademy_types.GetLatestAssessmentOptions) => Promise<_playcademy_types.LatestAssessmentResult | null>;
360
375
  get: (studentId: string, attemptId: string) => Promise<_playcademy_types.AssessmentAttemptSnapshot>;
361
376
  save: (studentId: string, attemptId: string, input: _playcademy_types.SaveAssessmentInput) => Promise<_playcademy_types.AssessmentSaveResult>;
362
- submit: (studentId: string, attemptId: string, input: _playcademy_types.SubmitAssessmentInput, context: {
377
+ submitItem: (studentId: string, attemptId: string, input: _playcademy_types.SubmitAssessmentItemInput) => Promise<_playcademy_types.SubmitAssessmentItemResult>;
378
+ submit: (studentId: string, attemptId: string, input: _playcademy_types.SubmitAssessmentRequest, context: {
363
379
  sensorUrl: string;
364
380
  }) => Promise<_playcademy_types.AssessmentSubmitResult>;
365
381
  };
package/dist/server.js CHANGED
@@ -207,6 +207,8 @@ var DEFAULT_PERSONAL_API_KEY_PERMISSIONS = {
207
207
  };
208
208
  // ../constants/src/platform.ts
209
209
  var PLAYCADEMY_BROWSER_TIME_ZONE_HEADER = "x-playcademy-browser-time-zone";
210
+ var PLAYCADEMY_ASSESSMENT_ASSET_SHA256_HEADER = "x-playcademy-content-sha256";
211
+ var ASSESSMENT_ASSET_MAX_BYTES = 4 * 1024 * 1024;
210
212
  // ../constants/src/timeback.ts
211
213
  var TIMEBACK_ROUTES = {
212
214
  END_ACTIVITY: "/integrations/timeback/end-activity",
@@ -230,10 +232,10 @@ var TIMEBACK_SUBJECTS = [
230
232
  "Math",
231
233
  "None"
232
234
  ];
233
- var ASSESSMENT_PURPOSES = ["end_of_course", "diagnostic", "review"];
235
+ var ASSESSMENT_PURPOSES = ["end_of_course", "diagnostic", "review", "mastery"];
234
236
  var TIMEBACK_ASSESSMENT_REVIEW_REQUEST_LIMITS = {
235
237
  standards: 20,
236
- itemsPerStandard: 5,
238
+ candidateItemsPerStandard: 2,
237
239
  standardFieldLength: 128
238
240
  };
239
241
  var VALID_E_LEVELS = ["E1", "E2", "E3", "E4"];
@@ -286,6 +288,10 @@ function createTimebackNamespace(client) {
286
288
  if (options.grade !== undefined) {
287
289
  params.set("grade", String(options.grade));
288
290
  }
291
+ if (options.purpose === "mastery") {
292
+ params.set("standardFramework", options.standard.framework);
293
+ params.set("standardIdentifier", options.standard.identifier);
294
+ }
289
295
  return client["request"](`/api/timeback/assessments/latest?${params.toString()}`, "GET");
290
296
  },
291
297
  get: (studentId, attemptId) => {
@@ -293,6 +299,7 @@ function createTimebackNamespace(client) {
293
299
  return client["request"](`/api/timeback/assessments/${encodeURIComponent(attemptId)}?${params.toString()}`, "GET");
294
300
  },
295
301
  save: (studentId, attemptId, input) => client["request"](`/api/timeback/assessments/${encodeURIComponent(attemptId)}/save`, "POST", { ...input, gameId: client.gameId, studentId }),
302
+ submitItem: (studentId, attemptId, input) => client["request"](`/api/timeback/assessments/${encodeURIComponent(attemptId)}/submit-item`, "POST", { ...input, gameId: client.gameId, studentId }),
296
303
  submit: (studentId, attemptId, input, context) => client["request"](`/api/timeback/assessments/${encodeURIComponent(attemptId)}/submit`, "POST", {
297
304
  ...input,
298
305
  gameId: client.gameId,
@@ -497,7 +504,7 @@ function extractApiErrorInfo(error) {
497
504
  }
498
505
 
499
506
  // src/version.ts
500
- var SDK_VERSION = "0.16.1-beta.8";
507
+ var SDK_VERSION = "0.17.0";
501
508
 
502
509
  // src/server/request.ts
503
510
  async function makeApiRequest(opts) {
package/dist/types.d.ts CHANGED
@@ -2,7 +2,7 @@ import * as _playcademy_types from '@playcademy/types';
2
2
  import { GameManifest, LocalDayContext } from '@playcademy/types';
3
3
  export { AuthenticatedUser, DeveloperStatusEnumType, DeveloperStatusResponse, DeveloperStatusValue, GameCourseMetrics, GameLeaderboardEntry, GameManifest, GameMetricComparisonKind, GameMetricComparisonMetric, GameMetricComparisonRow, GameMetricComparisonRowStatus, GameMetricsProxyResponse, GameMetricsResponse, GameMetricsUnsupportedReason, GamePlatform, GameRunMetrics, GameRunMetricsComparison, GameRunMetricsComparisonStatus, GameRunMetricsComparisonSummary, GameTimebackIntegration, GameType, GameUser, LeaderboardEntry, LeaderboardOptions, LeaderboardTimeframe, LocalDayContext, LocalDaySource, ManifestV1, ManifestV2, ManifestVersions, PopulateStudentResponse, UserEnrollment, UserInfo, UserOrganization, UserRank, UserRankResponse, UserRoleEnumType, UserScore, UserTimebackData } from '@playcademy/types';
4
4
  import { TimebackCourseConfig, CourseConfig, OrganizationConfig, ComponentConfig, ResourceConfig, ComponentResourceConfig, TimebackGrade, TimebackSubject, ELevel, EndActivityRequest, HeartbeatRequest, EndActivityScoreData, EndActivityResponse } from '@playcademy/types/timeback';
5
- export { ELevel } from '@playcademy/types/timeback';
5
+ export { AssessmentAttemptSnapshot, AssessmentFlow, AssessmentItemSubmission, AssessmentResponseUpdate, AssessmentResponseValue, AssessmentResponses, AssessmentSaveResult, AssessmentScore, AssessmentStandardRef, AssessmentSubmitResult, ConventionalAssessmentAttemptSnapshot, ConventionalAssessmentSubmitResult, DiagnosticAssessmentItemReceipt, DiagnosticAssessmentSubmitResult, DiagnosticRoutingSnapshot, DiagnosticRoutingTrackSnapshot, ELevel, PlatformRoutedDiagnosticAttemptSnapshot, PlatformRoutedDiagnosticSelectionContext, PlayableAssessment, PlayableAssessmentChoice, PlayableAssessmentGraphic, PlayableAssessmentHotspot, PlayableAssessmentInteraction, PlayableAssessmentItem, PlayableContentNode, SaveAssessmentInput, StartAssessmentInput, StartDiagnosticAssessmentInput, SubmitAssessmentInput, SubmitAssessmentItemInput, SubmitAssessmentItemResult, SubmitDiagnosticAssessmentItemInput, SubmitDiagnosticAssessmentItemResult } from '@playcademy/types/timeback';
6
6
  import { TimebackUserRole, UserEnrollment, UserOrganization, UserInfo } from '@playcademy/types/user';
7
7
  import { GamePermission, AUTH_PROVIDER_IDS } from '@playcademy/constants';
8
8
  import * as drizzle_orm_pg_core from 'drizzle-orm/pg-core';
@@ -363,6 +363,19 @@ interface DashboardThemeConfig {
363
363
  /** Secondary/accent color as a hex string, e.g. '#ffd166' */
364
364
  secondary?: string;
365
365
  }
366
+ /**
367
+ * Child-catalog contract generation (see @playcademy/sdk/contracts).
368
+ * The extractor is a repo-local script (run with the CLI's runtime) that
369
+ * prints `{ generatedFrom, deliveries }` as JSON on stdout; the CLI
370
+ * validates, stamps the contract fields, and writes
371
+ * `.playcademy/catalog.json` deterministically. The document carries no
372
+ * app identity — consuming repos assign the namespace key from sync
373
+ * provenance.
374
+ */
375
+ interface CatalogConfig {
376
+ /** Path to the extractor script, relative to the config file. */
377
+ extractor: string;
378
+ }
366
379
  /**
367
380
  * Unified Playcademy configuration
368
381
  * Used for playcademy.config.{js,json}
@@ -395,6 +408,8 @@ interface PlaycademyConfig {
395
408
  dashboard?: DashboardConfig | boolean;
396
409
  /** Integrations (database, custom routes, external services) */
397
410
  integrations?: IntegrationsConfig;
411
+ /** Child-catalog contract generation (`playcademy catalog`) */
412
+ catalog?: CatalogConfig;
398
413
  }
399
414
 
400
415
  /**
@@ -1999,7 +2014,11 @@ declare class PlaycademyClient extends PlaycademyBaseClient {
1999
2014
  start: (input: _playcademy_types.StartAssessmentInput) => Promise<_playcademy_types.AssessmentAttemptSnapshot>;
2000
2015
  latest: (options: _playcademy_types.GetLatestAssessmentOptions) => Promise<_playcademy_types.LatestAssessmentResult | null>;
2001
2016
  get: (attemptId: string) => Promise<_playcademy_types.AssessmentAttemptSnapshot>;
2017
+ stop: (attemptId: string) => Promise<{
2018
+ attemptId: string;
2019
+ }>;
2002
2020
  save: (attemptId: string, input: _playcademy_types.SaveAssessmentInput) => Promise<_playcademy_types.AssessmentSaveResult>;
2021
+ submitItem: (attemptId: string, input: _playcademy_types.SubmitAssessmentItemInput) => Promise<_playcademy_types.SubmitAssessmentItemResult>;
2003
2022
  submit: (attemptId: string, input: _playcademy_types.SubmitAssessmentInput) => Promise<_playcademy_types.AssessmentSubmitResult>;
2004
2023
  };
2005
2024
  readonly user: TimebackUser;
@@ -2339,6 +2358,15 @@ type EmbedActivity = EmbedActivityCompleted | EmbedActivityAbandoned | EmbedActi
2339
2358
  /** The child called `endActivity()` and its report was relayed. */
2340
2359
  interface EmbedActivityCompleted {
2341
2360
  status: 'completed';
2361
+ /**
2362
+ * The platform run this completion records under. One run ends in at
2363
+ * most one completion (the server dedupes on it), and a resumed launch
2364
+ * keeps the interrupted run's id — so this doubles as the completion's
2365
+ * attempt identity: feed it to whatever consumes the result and drop
2366
+ * anything you have seen before. Absent only for pure UX embeds
2367
+ * (launched without `timeback`), which record nothing.
2368
+ */
2369
+ runId?: string;
2342
2370
  /** Correct answers, from the child's report. */
2343
2371
  correct: number;
2344
2372
  /** Total questions, from the child's report. */
@@ -2367,6 +2395,12 @@ interface EmbedActivityCompleted {
2367
2395
  */
2368
2396
  interface EmbedActivityAbandoned {
2369
2397
  status: 'abandoned';
2398
+ /**
2399
+ * The platform run the launch was recording under, when one had
2400
+ * opened. Absent when the child never started an activity or the
2401
+ * launch was a pure UX embed.
2402
+ */
2403
+ runId?: string;
2370
2404
  timing: EmbedSessionTiming;
2371
2405
  /**
2372
2406
  * The final resume envelope, when the child checkpointed during the
@@ -2388,6 +2422,13 @@ interface EmbedActivityFailed {
2388
2422
  interface EmbedSession {
2389
2423
  /** The mounted child iframe. Useful for focus management. */
2390
2424
  readonly iframe: HTMLIFrameElement;
2425
+ /**
2426
+ * The platform run this launch records under, or null before the run
2427
+ * opens (the child's first activity) and for pure UX embeds. Stable
2428
+ * once set; also echoed on the finished record, which is where most
2429
+ * callers should read it.
2430
+ */
2431
+ readonly runId: string | null;
2391
2432
  /**
2392
2433
  * The latest resume envelope, live during play; null until the child
2393
2434
  * first checkpoints. Read it on your own cadence to persist
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@playcademy/sdk",
3
- "version": "0.16.1-beta.8",
3
+ "version": "0.17.0",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": {
@@ -21,6 +21,12 @@
21
21
  "import": "./dist/types.js",
22
22
  "require": "./dist/types.js"
23
23
  },
24
+ "./contracts": {
25
+ "source": "./src/contracts.ts",
26
+ "types": "./dist/contracts.d.ts",
27
+ "import": "./dist/contracts.js",
28
+ "require": "./dist/contracts.js"
29
+ },
24
30
  "./internal": {
25
31
  "source": "./src/internal.ts",
26
32
  "types": "./dist/internal.d.ts",