@playcademy/sdk 0.16.1-beta.9 → 0.17.1-beta.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.
@@ -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,9 +374,13 @@ 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>;
381
+ finalize: (studentId: string, attemptId: string, input: _playcademy_types.FinalizeAssessmentInput, context: {
382
+ sensorUrl: string;
383
+ }) => Promise<_playcademy_types.AssessmentFinalizeResult>;
365
384
  };
366
385
  endActivity: (studentId: string, payload: _playcademy_types.EndActivityPayload) => Promise<_playcademy_types.EndActivityResponse>;
367
386
  getStudentXp: (studentId: string, options?: {
@@ -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",
@@ -44,7 +46,7 @@ var TIMEBACK_SUBJECTS = [
44
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"];
@@ -108,12 +110,20 @@ function createTimebackNamespace(client) {
108
110
  return client["request"](`/api/timeback/assessments/${encodeURIComponent(attemptId)}?${params.toString()}`, "GET");
109
111
  },
110
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 }),
111
114
  submit: (studentId, attemptId, input, context) => client["request"](`/api/timeback/assessments/${encodeURIComponent(attemptId)}/submit`, "POST", {
112
115
  ...input,
113
116
  gameId: client.gameId,
114
117
  studentId,
115
118
  appName: client.config.name,
116
119
  sensorUrl: context.sensorUrl
120
+ }),
121
+ finalize: (studentId, attemptId, input, context) => client["request"](`/api/timeback/assessments/${encodeURIComponent(attemptId)}/finalize`, "POST", {
122
+ ...input,
123
+ gameId: client.gameId,
124
+ studentId,
125
+ appName: client.config.name,
126
+ sensorUrl: context.sensorUrl
117
127
  })
118
128
  },
119
129
  endActivity: async (studentId, payload) => {
@@ -312,7 +322,7 @@ function extractApiErrorInfo(error) {
312
322
  }
313
323
 
314
324
  // src/version.ts
315
- var SDK_VERSION = "0.16.1-beta.9";
325
+ var SDK_VERSION = "0.17.1-beta.1";
316
326
 
317
327
  // src/server/request.ts
318
328
  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,9 +374,13 @@ 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>;
381
+ finalize: (studentId: string, attemptId: string, input: _playcademy_types.FinalizeAssessmentInput, context: {
382
+ sensorUrl: string;
383
+ }) => Promise<_playcademy_types.AssessmentFinalizeResult>;
365
384
  };
366
385
  endActivity: (studentId: string, payload: _playcademy_types.EndActivityPayload) => Promise<_playcademy_types.EndActivityResponse>;
367
386
  getStudentXp: (studentId: string, options?: {
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",
@@ -233,7 +235,7 @@ var TIMEBACK_SUBJECTS = [
233
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"];
@@ -297,12 +299,20 @@ function createTimebackNamespace(client) {
297
299
  return client["request"](`/api/timeback/assessments/${encodeURIComponent(attemptId)}?${params.toString()}`, "GET");
298
300
  },
299
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 }),
300
303
  submit: (studentId, attemptId, input, context) => client["request"](`/api/timeback/assessments/${encodeURIComponent(attemptId)}/submit`, "POST", {
301
304
  ...input,
302
305
  gameId: client.gameId,
303
306
  studentId,
304
307
  appName: client.config.name,
305
308
  sensorUrl: context.sensorUrl
309
+ }),
310
+ finalize: (studentId, attemptId, input, context) => client["request"](`/api/timeback/assessments/${encodeURIComponent(attemptId)}/finalize`, "POST", {
311
+ ...input,
312
+ gameId: client.gameId,
313
+ studentId,
314
+ appName: client.config.name,
315
+ sensorUrl: context.sensorUrl
306
316
  })
307
317
  },
308
318
  endActivity: async (studentId, payload) => {
@@ -501,7 +511,7 @@ function extractApiErrorInfo(error) {
501
511
  }
502
512
 
503
513
  // src/version.ts
504
- var SDK_VERSION = "0.16.1-beta.9";
514
+ var SDK_VERSION = "0.17.1-beta.1";
505
515
 
506
516
  // src/server/request.ts
507
517
  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, AssessmentFinalizeResult, AssessmentFlow, AssessmentItemSubmission, AssessmentResponseUpdate, AssessmentResponseValue, AssessmentResponses, AssessmentSaveResult, AssessmentScore, AssessmentStandardRef, AssessmentSubmitResult, ConventionalAssessmentAttemptSnapshot, ConventionalAssessmentSubmitResult, DiagnosticAssessmentItemReceipt, DiagnosticAssessmentSubmitResult, DiagnosticRoutingSnapshot, DiagnosticRoutingTrackSnapshot, ELevel, FinalizeAssessmentInput, PlatformRoutedDiagnosticAttemptSnapshot, PlatformRoutedDiagnosticSelectionContext, PlayableAssessment, PlayableAssessmentAttemptSnapshot, PlayableAssessmentChoice, PlayableAssessmentGraphic, PlayableAssessmentHotspot, PlayableAssessmentInteraction, PlayableAssessmentItem, PlayableContentNode, SaveAssessmentInput, SettledAssessmentAttemptSnapshot, 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,8 +2014,13 @@ 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>;
2023
+ finalize: (attemptId: string, input: _playcademy_types.FinalizeAssessmentInput) => Promise<_playcademy_types.AssessmentFinalizeResult>;
2004
2024
  };
2005
2025
  readonly user: TimebackUser;
2006
2026
  readonly currentRunId: string | undefined;
@@ -2339,6 +2359,15 @@ type EmbedActivity = EmbedActivityCompleted | EmbedActivityAbandoned | EmbedActi
2339
2359
  /** The child called `endActivity()` and its report was relayed. */
2340
2360
  interface EmbedActivityCompleted {
2341
2361
  status: 'completed';
2362
+ /**
2363
+ * The platform run this completion records under. One run ends in at
2364
+ * most one completion (the server dedupes on it), and a resumed launch
2365
+ * keeps the interrupted run's id — so this doubles as the completion's
2366
+ * attempt identity: feed it to whatever consumes the result and drop
2367
+ * anything you have seen before. Absent only for pure UX embeds
2368
+ * (launched without `timeback`), which record nothing.
2369
+ */
2370
+ runId?: string;
2342
2371
  /** Correct answers, from the child's report. */
2343
2372
  correct: number;
2344
2373
  /** Total questions, from the child's report. */
@@ -2367,6 +2396,12 @@ interface EmbedActivityCompleted {
2367
2396
  */
2368
2397
  interface EmbedActivityAbandoned {
2369
2398
  status: 'abandoned';
2399
+ /**
2400
+ * The platform run the launch was recording under, when one had
2401
+ * opened. Absent when the child never started an activity or the
2402
+ * launch was a pure UX embed.
2403
+ */
2404
+ runId?: string;
2370
2405
  timing: EmbedSessionTiming;
2371
2406
  /**
2372
2407
  * The final resume envelope, when the child checkpointed during the
@@ -2388,6 +2423,13 @@ interface EmbedActivityFailed {
2388
2423
  interface EmbedSession {
2389
2424
  /** The mounted child iframe. Useful for focus management. */
2390
2425
  readonly iframe: HTMLIFrameElement;
2426
+ /**
2427
+ * The platform run this launch records under, or null before the run
2428
+ * opens (the child's first activity) and for pure UX embeds. Stable
2429
+ * once set; also echoed on the finished record, which is where most
2430
+ * callers should read it.
2431
+ */
2432
+ readonly runId: string | null;
2391
2433
  /**
2392
2434
  * The latest resume envelope, live during play; null until the child
2393
2435
  * 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.9",
3
+ "version": "0.17.1-beta.1",
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",