@playcademy/sdk 0.16.1-beta.22 → 0.16.1-beta.24
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 +23 -15
- package/dist/index.js +15 -3
- package/dist/internal.d.ts +10 -3
- package/dist/internal.js +16 -3
- package/dist/server/edge.js +1 -1
- package/dist/server.js +1 -1
- package/dist/types.d.ts +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -122,21 +122,25 @@ Hosted assessments use the same methods locally and when deployed:
|
|
|
122
122
|
const attempt = await client.timeback.assessments.start({
|
|
123
123
|
activityId: 'math-diagnostic',
|
|
124
124
|
purpose: 'diagnostic',
|
|
125
|
+
diagnosticKey: 'math.grade-5-placement',
|
|
125
126
|
subject: 'Math',
|
|
126
127
|
grade: 5,
|
|
127
128
|
})
|
|
128
129
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
[attempt.assessment.items[0].identifier]: { RESPONSE: 'A' },
|
|
133
|
-
},
|
|
134
|
-
})
|
|
130
|
+
if (attempt.flow !== 'platform-routed-item-submit' || !attempt.routing.next) {
|
|
131
|
+
throw new Error('Expected an active routed diagnostic')
|
|
132
|
+
}
|
|
135
133
|
|
|
136
|
-
const
|
|
137
|
-
|
|
134
|
+
const current = attempt.routing.next
|
|
135
|
+
const committed = await client.timeback.assessments.submitItem(attempt.attemptId, {
|
|
136
|
+
expectedResponseVersion: attempt.responseVersion,
|
|
138
137
|
submissionId: crypto.randomUUID(),
|
|
138
|
+
routingNodeKey: current.nodeKey,
|
|
139
|
+
itemIdentifier: current.itemIdentifier,
|
|
140
|
+
responses: { RESPONSE: 'A' },
|
|
139
141
|
})
|
|
142
|
+
|
|
143
|
+
// Repeat with committed.routing.next. When routing is ready, submit() only finalizes.
|
|
140
144
|
```
|
|
141
145
|
|
|
142
146
|
`start()` resumes a compatible unfinished attempt or selects content for a fixed test or standards
|
|
@@ -144,20 +148,24 @@ review. Save payloads merge at both the item and response levels; omitted values
|
|
|
144
148
|
and `null` clears one response. Keep the returned `responseVersion` and send it with the next
|
|
145
149
|
mutation.
|
|
146
150
|
|
|
147
|
-
The returned `flow` is authoritative and is derived from
|
|
151
|
+
The returned `flow` is authoritative and is derived from the selected assessment; callers do not configure
|
|
148
152
|
navigation, feedback, and submission independently:
|
|
149
153
|
|
|
150
|
-
- `attempt-submit` is used for
|
|
151
|
-
|
|
154
|
+
- `attempt-submit` is used for end-of-course and mastery attempts. Responses remain editable
|
|
155
|
+
through `save()` until `submit()` finalizes the whole attempt and returns feedback.
|
|
152
156
|
- `item-submit` is used for review attempts. Submit each administered item with `submitItem()`.
|
|
153
157
|
That operation atomically saves the item's responses, locks them, and returns safe immediate
|
|
154
158
|
feedback. Give each item request its own stable `submissionId` and reuse that ID for an ambiguous
|
|
155
159
|
retry; the returned canonical `itemSubmissions` ledger identifies committed items after retry or
|
|
156
160
|
resume.
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
+
- `platform-routed-item-submit` is used for adaptive diagnostics. Render only
|
|
162
|
+
`routing.next.itemIdentifier`, submit it with `routing.next.nodeKey`, and replace local state with
|
|
163
|
+
the returned canonical routing snapshot. Diagnostic receipts never reveal correctness or score,
|
|
164
|
+
and `submit()` becomes available only after routing reports `ready-to-complete`.
|
|
165
|
+
|
|
166
|
+
The host rejects the wrong mutation for each flow, rejects premature finalization, and enforces
|
|
167
|
+
`expectedResponseVersion` for every mutation. Hosted and local providers execute the same routing
|
|
168
|
+
manifest contract; game code never selects the provider.
|
|
161
169
|
|
|
162
170
|
For local development, import the current ordered catalog before starting the dev host:
|
|
163
171
|
|
package/dist/index.js
CHANGED
|
@@ -1206,8 +1206,11 @@ class ChildSession {
|
|
|
1206
1206
|
}
|
|
1207
1207
|
this.#markOpenWindowFlushable();
|
|
1208
1208
|
this.#forwardDirtyWindows();
|
|
1209
|
-
window
|
|
1210
|
-
|
|
1209
|
+
const win = globalThis.window;
|
|
1210
|
+
if (win) {
|
|
1211
|
+
win.removeEventListener("message", this.#onChildMessage);
|
|
1212
|
+
win.removeEventListener("pagehide", this.#onPageHide);
|
|
1213
|
+
}
|
|
1211
1214
|
messaging.unlisten("PLAYCADEMY_TOKEN_REFRESH" /* TOKEN_REFRESH */, this.#onTokenRefresh);
|
|
1212
1215
|
messaging.unlisten("PLAYCADEMY_PAUSE" /* PAUSE */, this.#onLauncherPause);
|
|
1213
1216
|
messaging.unlisten("PLAYCADEMY_RESUME" /* RESUME */, this.#onLauncherResume);
|
|
@@ -3150,6 +3153,12 @@ function createTimebackNamespace(client) {
|
|
|
3150
3153
|
throw new Error("activityId is required");
|
|
3151
3154
|
}
|
|
3152
3155
|
validateAssessmentFilters(input);
|
|
3156
|
+
if (input.purpose === "diagnostic" && !input.diagnosticKey?.trim()) {
|
|
3157
|
+
throw new Error("diagnosticKey is required for diagnostic assessments");
|
|
3158
|
+
}
|
|
3159
|
+
if (input.purpose === "diagnostic" && input.diagnosticKey.trim().length > 200) {
|
|
3160
|
+
throw new Error("diagnosticKey must contain at most 200 characters");
|
|
3161
|
+
}
|
|
3153
3162
|
if (input.purpose === "review") {
|
|
3154
3163
|
if (!Array.isArray(input.standards) || input.standards.length === 0) {
|
|
3155
3164
|
throw new Error("standards must contain at least one standard for review");
|
|
@@ -3232,6 +3241,9 @@ function createTimebackNamespace(client) {
|
|
|
3232
3241
|
if (!input.itemIdentifier?.trim()) {
|
|
3233
3242
|
throw new Error("itemIdentifier is required");
|
|
3234
3243
|
}
|
|
3244
|
+
if (input.routingNodeKey !== undefined && !input.routingNodeKey.trim()) {
|
|
3245
|
+
throw new Error("routingNodeKey must be non-empty when provided");
|
|
3246
|
+
}
|
|
3235
3247
|
return client["requestGameBackend"](`${ASSESSMENTS_ROUTE}/${encodeURIComponent(attemptId)}/submit-item`, "POST", input);
|
|
3236
3248
|
},
|
|
3237
3249
|
submit: async (attemptId, input) => {
|
|
@@ -3670,7 +3682,7 @@ async function request({
|
|
|
3670
3682
|
return rawText && rawText.length > 0 ? rawText : undefined;
|
|
3671
3683
|
}
|
|
3672
3684
|
// src/version.ts
|
|
3673
|
-
var SDK_VERSION = "0.16.1-beta.
|
|
3685
|
+
var SDK_VERSION = "0.16.1-beta.24";
|
|
3674
3686
|
|
|
3675
3687
|
// src/clients/base.ts
|
|
3676
3688
|
class PlaycademyBaseClient {
|
package/dist/internal.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { SchemaInfo } from '@playcademy/cloudflare';
|
|
2
2
|
import { GamePermission, AUTH_PROVIDER_IDS } from '@playcademy/constants';
|
|
3
3
|
import { TimebackGrade, TimebackSubject, ELevel, HeartbeatRequest, EndActivityRequest, EndActivityScoreData, EndActivityResponse, TimebackCourseConfig, CourseConfig, OrganizationConfig, ComponentConfig, ResourceConfig, ComponentResourceConfig } from '@playcademy/types/timeback';
|
|
4
|
-
export { AssessmentAttemptSnapshot, AssessmentFlow, AssessmentItemSubmission, AssessmentResponseUpdate, AssessmentResponseValue, AssessmentResponses, AssessmentSaveResult, AssessmentScore, AssessmentStandardRef, AssessmentSubmitResult, ELevel, PlayableAssessment, PlayableAssessmentChoice, PlayableAssessmentGraphic, PlayableAssessmentHotspot, PlayableAssessmentInteraction, PlayableAssessmentItem, PlayableContentNode, SaveAssessmentInput, StartAssessmentInput, SubmitAssessmentInput, SubmitAssessmentItemInput, SubmitAssessmentItemResult } from '@playcademy/types/timeback';
|
|
4
|
+
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';
|
|
5
5
|
import * as _playcademy_types from '@playcademy/types';
|
|
6
6
|
import { GameManifest, LocalDayContext } from '@playcademy/types';
|
|
7
7
|
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';
|
|
@@ -3659,6 +3659,11 @@ interface QtiLibraryQueryOptions {
|
|
|
3659
3659
|
page?: number;
|
|
3660
3660
|
limit?: number;
|
|
3661
3661
|
}
|
|
3662
|
+
interface ReviewMappingUpdateResult {
|
|
3663
|
+
itemCount: number;
|
|
3664
|
+
standardCount: number;
|
|
3665
|
+
sourceFingerprint: string;
|
|
3666
|
+
}
|
|
3662
3667
|
|
|
3663
3668
|
/**
|
|
3664
3669
|
* Internal Playcademy SDK client with all namespaces.
|
|
@@ -4021,7 +4026,7 @@ declare class PlaycademyInternalClient extends PlaycademyBaseClient {
|
|
|
4021
4026
|
list: (gameId: string, courseId: string) => Promise<_playcademy_types.AssessmentSummary[]>;
|
|
4022
4027
|
create: (gameId: string, courseId: string, data: {
|
|
4023
4028
|
title: string;
|
|
4024
|
-
purpose: _playcademy_types.AssessmentPurpose
|
|
4029
|
+
purpose: Exclude<_playcademy_types.AssessmentPurpose, 'diagnostic'>;
|
|
4025
4030
|
standard?: _playcademy_types.AssessmentStandardRef;
|
|
4026
4031
|
}) => Promise<_playcademy_types.AssessmentRow>;
|
|
4027
4032
|
attachExisting: (gameId: string, courseId: string, manifest: _playcademy_types.AssessmentAssociationImportManifest) => Promise<_playcademy_types.AssessmentAssociationImportResponse>;
|
|
@@ -4029,8 +4034,10 @@ declare class PlaycademyInternalClient extends PlaycademyBaseClient {
|
|
|
4029
4034
|
title?: string;
|
|
4030
4035
|
purpose?: _playcademy_types.AssessmentPurpose;
|
|
4031
4036
|
standard?: _playcademy_types.AssessmentStandardRef;
|
|
4037
|
+
diagnostic?: _playcademy_types.DiagnosticAssessmentDefinitionInput | null;
|
|
4032
4038
|
status?: _playcademy_types.AssessmentStatus;
|
|
4033
4039
|
}) => Promise<_playcademy_types.AssessmentRow>;
|
|
4040
|
+
updateReviewMapping: (gameId: string, courseId: string, testIdentifier: string) => Promise<ReviewMappingUpdateResult>;
|
|
4034
4041
|
reorder: (gameId: string, courseId: string, purpose: _playcademy_types.AssessmentPurpose, testIdentifiers: string[]) => Promise<{
|
|
4035
4042
|
success: boolean;
|
|
4036
4043
|
}>;
|
|
@@ -4038,7 +4045,7 @@ declare class PlaycademyInternalClient extends PlaycademyBaseClient {
|
|
|
4038
4045
|
action: 'discarded' | 'archived';
|
|
4039
4046
|
}>;
|
|
4040
4047
|
listTestLibrary: (gameId: string, courseId: string, options?: QtiLibraryQueryOptions) => Promise<_playcademy_types.QtiAssessmentTestListResponse>;
|
|
4041
|
-
copy: (gameId: string, courseId: string, testIdentifier: string, purpose: _playcademy_types.AssessmentPurpose, standard?: _playcademy_types.AssessmentStandardRef) => Promise<_playcademy_types.AssessmentRow>;
|
|
4048
|
+
copy: (gameId: string, courseId: string, testIdentifier: string, purpose: Exclude<_playcademy_types.AssessmentPurpose, 'diagnostic'>, standard?: _playcademy_types.AssessmentStandardRef) => Promise<_playcademy_types.AssessmentRow>;
|
|
4042
4049
|
listQuestions: (gameId: string, courseId: string, testIdentifier: string) => Promise<_playcademy_types.QtiTestQuestionsResponse>;
|
|
4043
4050
|
listQuestionLibrary: (gameId: string, courseId: string, options?: QtiLibraryQueryOptions) => Promise<_playcademy_types.QtiAssessmentItemListResponse>;
|
|
4044
4051
|
createQuestion: (gameId: string, courseId: string, testIdentifier: string, data: _playcademy_types.QtiQuestionCreateInput) => Promise<_playcademy_types.QtiTestQuestionRef>;
|
package/dist/internal.js
CHANGED
|
@@ -1206,8 +1206,11 @@ class ChildSession {
|
|
|
1206
1206
|
}
|
|
1207
1207
|
this.#markOpenWindowFlushable();
|
|
1208
1208
|
this.#forwardDirtyWindows();
|
|
1209
|
-
window
|
|
1210
|
-
|
|
1209
|
+
const win = globalThis.window;
|
|
1210
|
+
if (win) {
|
|
1211
|
+
win.removeEventListener("message", this.#onChildMessage);
|
|
1212
|
+
win.removeEventListener("pagehide", this.#onPageHide);
|
|
1213
|
+
}
|
|
1211
1214
|
messaging.unlisten("PLAYCADEMY_TOKEN_REFRESH" /* TOKEN_REFRESH */, this.#onTokenRefresh);
|
|
1212
1215
|
messaging.unlisten("PLAYCADEMY_PAUSE" /* PAUSE */, this.#onLauncherPause);
|
|
1213
1216
|
messaging.unlisten("PLAYCADEMY_RESUME" /* RESUME */, this.#onLauncherResume);
|
|
@@ -3150,6 +3153,12 @@ function createTimebackNamespace(client) {
|
|
|
3150
3153
|
throw new Error("activityId is required");
|
|
3151
3154
|
}
|
|
3152
3155
|
validateAssessmentFilters(input);
|
|
3156
|
+
if (input.purpose === "diagnostic" && !input.diagnosticKey?.trim()) {
|
|
3157
|
+
throw new Error("diagnosticKey is required for diagnostic assessments");
|
|
3158
|
+
}
|
|
3159
|
+
if (input.purpose === "diagnostic" && input.diagnosticKey.trim().length > 200) {
|
|
3160
|
+
throw new Error("diagnosticKey must contain at most 200 characters");
|
|
3161
|
+
}
|
|
3153
3162
|
if (input.purpose === "review") {
|
|
3154
3163
|
if (!Array.isArray(input.standards) || input.standards.length === 0) {
|
|
3155
3164
|
throw new Error("standards must contain at least one standard for review");
|
|
@@ -3232,6 +3241,9 @@ function createTimebackNamespace(client) {
|
|
|
3232
3241
|
if (!input.itemIdentifier?.trim()) {
|
|
3233
3242
|
throw new Error("itemIdentifier is required");
|
|
3234
3243
|
}
|
|
3244
|
+
if (input.routingNodeKey !== undefined && !input.routingNodeKey.trim()) {
|
|
3245
|
+
throw new Error("routingNodeKey must be non-empty when provided");
|
|
3246
|
+
}
|
|
3235
3247
|
return client["requestGameBackend"](`${ASSESSMENTS_ROUTE}/${encodeURIComponent(attemptId)}/submit-item`, "POST", input);
|
|
3236
3248
|
},
|
|
3237
3249
|
submit: async (attemptId, input) => {
|
|
@@ -4111,6 +4123,7 @@ function createAssessmentNamespace(client) {
|
|
|
4111
4123
|
update: (gameId, courseId, testIdentifier, data) => client["request"](assessmentPath(gameId, courseId, testIdentifier), "PATCH", {
|
|
4112
4124
|
body: data
|
|
4113
4125
|
}),
|
|
4126
|
+
updateReviewMapping: (gameId, courseId, testIdentifier) => client["request"](assessmentPath(gameId, courseId, testIdentifier, "review-mapping"), "POST"),
|
|
4114
4127
|
reorder: (gameId, courseId, purpose, testIdentifiers) => client["request"](assessmentPath(gameId, courseId, "order"), "PUT", {
|
|
4115
4128
|
body: { purpose, testIdentifiers }
|
|
4116
4129
|
}),
|
|
@@ -4549,7 +4562,7 @@ async function request({
|
|
|
4549
4562
|
return rawText && rawText.length > 0 ? rawText : undefined;
|
|
4550
4563
|
}
|
|
4551
4564
|
// src/version.ts
|
|
4552
|
-
var SDK_VERSION = "0.16.1-beta.
|
|
4565
|
+
var SDK_VERSION = "0.16.1-beta.24";
|
|
4553
4566
|
|
|
4554
4567
|
// src/clients/base.ts
|
|
4555
4568
|
class PlaycademyBaseClient {
|
package/dist/server/edge.js
CHANGED
package/dist/server.js
CHANGED
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 { AssessmentAttemptSnapshot, AssessmentFlow, AssessmentItemSubmission, AssessmentResponseUpdate, AssessmentResponseValue, AssessmentResponses, AssessmentSaveResult, AssessmentScore, AssessmentStandardRef, AssessmentSubmitResult, ELevel, PlayableAssessment, PlayableAssessmentChoice, PlayableAssessmentGraphic, PlayableAssessmentHotspot, PlayableAssessmentInteraction, PlayableAssessmentItem, PlayableContentNode, SaveAssessmentInput, StartAssessmentInput, SubmitAssessmentInput, SubmitAssessmentItemInput, SubmitAssessmentItemResult } 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';
|