@timeback/core 0.1.7-beta.20260309215937 → 0.1.7-beta.20260311174536

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.
@@ -6,5 +6,6 @@ var CALIPER_ENV_VARS = {
6
6
  clientSecret: ["TIMEBACK_API_CLIENT_SECRET", "TIMEBACK_CLIENT_SECRET", "CALIPER_CLIENT_SECRET"]
7
7
  };
8
8
  var CALIPER_DATA_VERSION = "http://purl.imsglobal.org/ctx/caliper/v1p2";
9
+ var QUESTION_RESULT_SCORE_TYPE = "QUESTION_RESULT";
9
10
 
10
- export { CALIPER_ENV_VARS, CALIPER_DATA_VERSION };
11
+ export { CALIPER_ENV_VARS, CALIPER_DATA_VERSION, QUESTION_RESULT_SCORE_TYPE };
@@ -7,7 +7,7 @@ import {
7
7
  validateNonEmptyString,
8
8
  validateUuid,
9
9
  validateWithSchema
10
- } from "./chunk-j1vhg225.js";
10
+ } from "./chunk-k030r9e8.js";
11
11
 
12
12
  // ../edubridge/src/utils.ts
13
13
  var log = createScopedLogger("edubridge");
@@ -22,21 +22,6 @@ function normalizeUser(user) {
22
22
  enabledUser: normalizeBoolean(user.enabledUser)
23
23
  };
24
24
  }
25
- function normalizeDate(date) {
26
- if (date === undefined) {
27
- return;
28
- }
29
- if (date instanceof Date) {
30
- return date.toISOString();
31
- }
32
- if (date.includes("T")) {
33
- return date;
34
- }
35
- if (/^\d{4}-\d{2}-\d{2}$/.test(date)) {
36
- return `${date}T00:00:00.000Z`;
37
- }
38
- return date;
39
- }
40
25
  function aggregateActivityMetrics(data) {
41
26
  const result = {
42
27
  totalXp: 0,
@@ -247,6 +232,7 @@ var IMSErrorResponse = z.object({
247
232
  });
248
233
  // ../../types/src/zod/caliper.ts
249
234
  import { z as z2 } from "zod/v4";
235
+ var CaliperIri = z2.union([z2.url(), z2.string().regex(/^urn:/, "Must be a URL or URN")]);
250
236
  var TimebackUser = z2.object({
251
237
  id: z2.url(),
252
238
  type: z2.literal("TimebackUser"),
@@ -356,11 +342,10 @@ var CaliperProfile = z2.enum([
356
342
  ]);
357
343
  var CaliperEntity = z2.union([z2.string(), z2.record(z2.string(), z2.unknown())]);
358
344
  var CaliperActor = z2.object({
359
- id: z2.url(),
345
+ id: CaliperIri,
360
346
  type: z2.string(),
361
- extensions: z2.object({
362
- email: z2.email()
363
- }).loose()
347
+ name: z2.string().optional(),
348
+ extensions: z2.record(z2.string(), z2.unknown()).optional()
364
349
  }).strict();
365
350
  var CaliperEvent = z2.object({
366
351
  "@context": z2.string().optional(),
@@ -400,6 +385,57 @@ var CaliperListEventsParams = z2.object({
400
385
  actorId: z2.string().min(1).optional(),
401
386
  actorEmail: z2.email().optional()
402
387
  }).strict();
388
+ var AssessmentItemObject = z2.object({
389
+ id: z2.string(),
390
+ name: z2.string().optional(),
391
+ isPartOf: CaliperEntity.optional(),
392
+ extensions: z2.record(z2.string(), z2.unknown()).optional()
393
+ });
394
+ var ResponseGenerated = z2.object({
395
+ id: z2.string(),
396
+ attempt: z2.union([z2.string(), z2.record(z2.string(), z2.unknown())]).optional(),
397
+ startedAtTime: IsoDateTimeString.optional(),
398
+ endedAtTime: IsoDateTimeString.optional(),
399
+ duration: z2.string().optional(),
400
+ extensions: z2.record(z2.string(), z2.unknown()).optional()
401
+ });
402
+ var ScoreGenerated = z2.object({
403
+ id: z2.string().optional(),
404
+ scoreGiven: z2.number(),
405
+ maxScore: z2.number().optional(),
406
+ attempt: z2.union([z2.string(), z2.record(z2.string(), z2.unknown())]).optional(),
407
+ comment: z2.string().optional(),
408
+ extensions: z2.record(z2.string(), z2.unknown()).optional()
409
+ });
410
+ var QuestionSeenInput = z2.object({
411
+ actor: z2.union([z2.string(), CaliperActor, TimebackUser]),
412
+ object: AssessmentItemObject,
413
+ edApp: CaliperEntity,
414
+ id: z2.string().optional(),
415
+ eventTime: IsoDateTimeString.optional(),
416
+ session: CaliperEntity.optional(),
417
+ extensions: z2.record(z2.string(), z2.unknown()).optional()
418
+ }).strict();
419
+ var QuestionAnsweredInput = z2.object({
420
+ actor: z2.union([z2.string(), CaliperActor, TimebackUser]),
421
+ object: AssessmentItemObject,
422
+ edApp: CaliperEntity,
423
+ generated: ResponseGenerated.optional(),
424
+ id: z2.string().optional(),
425
+ eventTime: IsoDateTimeString.optional(),
426
+ session: CaliperEntity.optional(),
427
+ extensions: z2.record(z2.string(), z2.unknown()).optional()
428
+ }).strict();
429
+ var QuestionGradedInput = z2.object({
430
+ actor: z2.union([z2.string(), CaliperActor, TimebackUser]),
431
+ object: z2.string(),
432
+ generated: ScoreGenerated,
433
+ edApp: CaliperEntity,
434
+ id: z2.string().optional(),
435
+ eventTime: IsoDateTimeString.optional(),
436
+ session: CaliperEntity.optional(),
437
+ extensions: z2.record(z2.string(), z2.unknown()).optional()
438
+ }).strict();
403
439
  // ../../types/src/zod/webhooks.ts
404
440
  import { z as z3 } from "zod/v4";
405
441
  var WebhookCreateInput = z3.object({
@@ -738,6 +774,7 @@ var TimebackConfig = z6.object({
738
774
  // ../../types/src/zod/edubridge.ts
739
775
  import { z as z7 } from "zod/v4";
740
776
  var EdubridgeDateString = z7.union([IsoDateTimeString, IsoDateString]);
777
+ var EdubridgeDateStringInput = EdubridgeDateString.transform((date) => date.includes("T") ? date : `${date}T00:00:00.000Z`);
741
778
  var EduBridgeEnrollment = z7.object({
742
779
  id: z7.string(),
743
780
  role: z7.string(),
@@ -827,18 +864,18 @@ var EdubridgeUsersListParams = z7.object({
827
864
  orgSourcedIds: z7.array(NonEmptyString2).optional()
828
865
  });
829
866
  var EdubridgeActivityParams = EmailOrStudentId.extend({
830
- startDate: EdubridgeDateString,
831
- endDate: EdubridgeDateString,
867
+ startDate: EdubridgeDateStringInput,
868
+ endDate: EdubridgeDateStringInput,
832
869
  timezone: z7.string().optional()
833
870
  });
834
871
  var EdubridgeWeeklyFactsParams = EmailOrStudentId.extend({
835
- weekDate: EdubridgeDateString,
872
+ weekDate: EdubridgeDateStringInput,
836
873
  timezone: z7.string().optional()
837
874
  });
838
875
  var EdubridgeEnrollmentFactsParams = z7.object({
839
876
  enrollmentId: NonEmptyString2,
840
- startDate: EdubridgeDateString.optional(),
841
- endDate: EdubridgeDateString.optional(),
877
+ startDate: EdubridgeDateStringInput.optional(),
878
+ endDate: EdubridgeDateStringInput.optional(),
842
879
  timezone: z7.string().optional()
843
880
  });
844
881
  // ../../types/src/zod/masterytrack.ts
@@ -929,7 +966,7 @@ var Ref = z9.object({
929
966
  type: z9.string().optional(),
930
967
  href: z9.string().optional()
931
968
  }).strict();
932
- var OneRosterDateString = z9.union([IsoDateString, IsoDateTimeString]);
969
+ var OneRosterDateString = z9.union([IsoDateString, IsoDateTimeString]).transform((date) => date.includes("T") ? date : `${date}T00:00:00Z`);
933
970
  var OneRosterUserRoleInput = z9.object({
934
971
  roleType: z9.enum(["primary", "secondary"]),
935
972
  role: OneRosterUserRole,
@@ -1015,8 +1052,8 @@ var OneRosterLineItemCreateInput = z9.object({
1015
1052
  class: Ref,
1016
1053
  school: Ref,
1017
1054
  category: Ref,
1018
- assignDate: IsoDateTimeString,
1019
- dueDate: IsoDateTimeString,
1055
+ assignDate: OneRosterDateString,
1056
+ dueDate: OneRosterDateString,
1020
1057
  status: Status,
1021
1058
  description: z9.string().optional(),
1022
1059
  resultValueMin: z9.number().nullable().optional(),
@@ -1029,7 +1066,7 @@ var OneRosterResultCreateInput = z9.object({
1029
1066
  lineItem: Ref,
1030
1067
  student: Ref,
1031
1068
  class: Ref.optional(),
1032
- scoreDate: IsoDateTimeString,
1069
+ scoreDate: OneRosterDateString,
1033
1070
  scoreStatus: z9.enum([
1034
1071
  "exempt",
1035
1072
  "fully graded",
@@ -1098,7 +1135,7 @@ var OneRosterAssessmentResultCreateInput = z9.object({
1098
1135
  student: Ref,
1099
1136
  score: z9.number().nullable().optional(),
1100
1137
  textScore: z9.string().nullable().optional(),
1101
- scoreDate: z9.string().datetime(),
1138
+ scoreDate: OneRosterDateString,
1102
1139
  scoreScale: Ref.nullable().optional(),
1103
1140
  scorePercentile: z9.number().nullable().optional(),
1104
1141
  scoreStatus: z9.enum([
@@ -1829,37 +1866,37 @@ class AnalyticsResource {
1829
1866
  this.transport = transport;
1830
1867
  }
1831
1868
  async getActivity(params) {
1832
- validateWithSchema(EdubridgeActivityParams, params, "activity params");
1869
+ const validated = validateWithSchema(EdubridgeActivityParams, params, "activity params");
1833
1870
  const response = await this.transport.request(`${this.transport.paths.base}/analytics/activity`, {
1834
1871
  params: {
1835
- email: params.email,
1836
- studentId: params.studentId,
1837
- startDate: normalizeDate(params.startDate),
1838
- endDate: normalizeDate(params.endDate),
1839
- timezone: params.timezone
1872
+ email: validated.email,
1873
+ studentId: validated.studentId,
1874
+ startDate: validated.startDate,
1875
+ endDate: validated.endDate,
1876
+ timezone: validated.timezone
1840
1877
  }
1841
1878
  });
1842
1879
  return response.facts;
1843
1880
  }
1844
1881
  async getWeeklyFacts(params) {
1845
- validateWithSchema(EdubridgeWeeklyFactsParams, params, "weekly facts params");
1882
+ const validated = validateWithSchema(EdubridgeWeeklyFactsParams, params, "weekly facts params");
1846
1883
  const response = await this.transport.request(`${this.transport.paths.base}/analytics/facts/weekly`, {
1847
1884
  params: {
1848
- email: params.email,
1849
- studentId: params.studentId,
1850
- weekDate: normalizeDate(params.weekDate),
1851
- timezone: params.timezone
1885
+ email: validated.email,
1886
+ studentId: validated.studentId,
1887
+ weekDate: validated.weekDate,
1888
+ timezone: validated.timezone
1852
1889
  }
1853
1890
  });
1854
1891
  return response.facts;
1855
1892
  }
1856
1893
  async getEnrollmentFacts(params) {
1857
- validateWithSchema(EdubridgeEnrollmentFactsParams, params, "enrollment facts params");
1858
- const response = await this.transport.request(`${this.transport.paths.base}/analytics/enrollment/${encodeURIComponent(params.enrollmentId)}`, {
1894
+ const validated = validateWithSchema(EdubridgeEnrollmentFactsParams, params, "enrollment facts params");
1895
+ const response = await this.transport.request(`${this.transport.paths.base}/analytics/enrollment/${encodeURIComponent(validated.enrollmentId)}`, {
1859
1896
  params: {
1860
- startDate: normalizeDate(params.startDate),
1861
- endDate: normalizeDate(params.endDate),
1862
- timezone: params.timezone
1897
+ startDate: validated.startDate,
1898
+ endDate: validated.endDate,
1899
+ timezone: validated.timezone
1863
1900
  }
1864
1901
  });
1865
1902
  return response.facts;
@@ -2086,4 +2123,4 @@ function createEdubridgeClient(registry = DEFAULT_PROVIDER_REGISTRY) {
2086
2123
 
2087
2124
  // ../edubridge/src/client.ts
2088
2125
  var EdubridgeClient = createEdubridgeClient();
2089
- export { ActivityCompletedInput, TimeSpentInput, CaliperEnvelopeInput, CaliperSendEventsInput, CaliperListEventsParams, WebhookCreateInput, WebhookUpdateInput, WebhookFilterCreateInput, WebhookFilterUpdateInput, CasePackageInput, ClrCredentialInput, OneRosterUserCreateInput, OneRosterCourseCreateInput, OneRosterClassCreateInput, OneRosterEnrollmentCreateInput, OneRosterCategoryCreateInput, OneRosterLineItemCreateInput, OneRosterResultCreateInput, OneRosterScoreScaleCreateInput, OneRosterAssessmentLineItemCreateInput, OneRosterAssessmentResultCreateInput, OneRosterOrgCreateInput, OneRosterSchoolCreateInput, OneRosterAcademicSessionCreateInput, OneRosterComponentResourceCreateInput, OneRosterCourseComponentCreateInput, OneRosterEnrollInput, OneRosterAgentInput, OneRosterCredentialInput, OneRosterDemographicsCreateInput, OneRosterResourceCreateInput, OneRosterCourseStructureInput, OneRosterBulkResultsInput, PowerPathCreateExternalPlacementTestInput, PowerPathCreateExternalTestOutInput, PowerPathCreateInternalTestInput, PowerPathCreateNewAttemptInput, PowerPathFinalStudentAssessmentResponseInput, PowerPathLessonPlansCreateInput, PowerPathLessonPlanOperationsInput, PowerPathLessonPlanUpdateStudentItemResponseInput, PowerPathMakeExternalTestAssignmentInput, PowerPathPlacementResetUserPlacementInput, PowerPathResetAttemptInput, PowerPathScreeningResetSessionInput, PowerPathScreeningAssignTestInput, PowerPathTestAssignmentsCreateInput, PowerPathTestAssignmentsUpdateInput, PowerPathTestAssignmentsBulkInput, PowerPathTestAssignmentsImportInput, PowerPathTestAssignmentsListParams, PowerPathTestAssignmentsAdminParams, PowerPathUpdateStudentQuestionResponseInput, PowerPathGetAssessmentProgressParams, PowerPathGetNextQuestionParams, PowerPathGetAttemptsParams, PowerPathTestOutParams, PowerPathImportExternalTestAssignmentResultsParams, PowerPathPlacementQueryParams, PowerPathSyllabusQueryParams, QtiAssessmentItemXmlCreateInput, QtiAssessmentItemJsonCreateInput, QtiAssessmentItemCreateInput, QtiAssessmentItemUpdateInput, QtiAssessmentItemProcessResponseInput, QtiAssessmentItemRef, QtiAssessmentSection, QtiTestPart, QtiReorderItemsInput, QtiAssessmentTestMetadataUpdateInput, QtiAssessmentTestCreateInput, QtiAssessmentTestUpdateInput, QtiStimulusCreateInput, QtiStimulusUpdateInput, QtiValidateInput, QtiValidateBatchInput, QtiLessonFeedbackInput, aggregateActivityMetrics, EdubridgeClient };
2126
+ export { ActivityCompletedInput, TimeSpentInput, CaliperEnvelopeInput, CaliperSendEventsInput, CaliperListEventsParams, QuestionSeenInput, QuestionAnsweredInput, QuestionGradedInput, WebhookCreateInput, WebhookUpdateInput, WebhookFilterCreateInput, WebhookFilterUpdateInput, CasePackageInput, ClrCredentialInput, OneRosterUserCreateInput, OneRosterCourseCreateInput, OneRosterClassCreateInput, OneRosterEnrollmentCreateInput, OneRosterCategoryCreateInput, OneRosterLineItemCreateInput, OneRosterResultCreateInput, OneRosterScoreScaleCreateInput, OneRosterAssessmentLineItemCreateInput, OneRosterAssessmentResultCreateInput, OneRosterOrgCreateInput, OneRosterSchoolCreateInput, OneRosterAcademicSessionCreateInput, OneRosterComponentResourceCreateInput, OneRosterCourseComponentCreateInput, OneRosterEnrollInput, OneRosterAgentInput, OneRosterCredentialInput, OneRosterDemographicsCreateInput, OneRosterResourceCreateInput, OneRosterCourseStructureInput, OneRosterBulkResultsInput, PowerPathCreateExternalPlacementTestInput, PowerPathCreateExternalTestOutInput, PowerPathCreateInternalTestInput, PowerPathCreateNewAttemptInput, PowerPathFinalStudentAssessmentResponseInput, PowerPathLessonPlansCreateInput, PowerPathLessonPlanOperationsInput, PowerPathLessonPlanUpdateStudentItemResponseInput, PowerPathMakeExternalTestAssignmentInput, PowerPathPlacementResetUserPlacementInput, PowerPathResetAttemptInput, PowerPathScreeningResetSessionInput, PowerPathScreeningAssignTestInput, PowerPathTestAssignmentsCreateInput, PowerPathTestAssignmentsUpdateInput, PowerPathTestAssignmentsBulkInput, PowerPathTestAssignmentsImportInput, PowerPathTestAssignmentsListParams, PowerPathTestAssignmentsAdminParams, PowerPathUpdateStudentQuestionResponseInput, PowerPathGetAssessmentProgressParams, PowerPathGetNextQuestionParams, PowerPathGetAttemptsParams, PowerPathTestOutParams, PowerPathImportExternalTestAssignmentResultsParams, PowerPathPlacementQueryParams, PowerPathSyllabusQueryParams, QtiAssessmentItemXmlCreateInput, QtiAssessmentItemJsonCreateInput, QtiAssessmentItemCreateInput, QtiAssessmentItemUpdateInput, QtiAssessmentItemProcessResponseInput, QtiAssessmentItemRef, QtiAssessmentSection, QtiTestPart, QtiReorderItemsInput, QtiAssessmentTestMetadataUpdateInput, QtiAssessmentTestCreateInput, QtiAssessmentTestUpdateInput, QtiStimulusCreateInput, QtiStimulusUpdateInput, QtiValidateInput, QtiValidateBatchInput, QtiLessonFeedbackInput, aggregateActivityMetrics, EdubridgeClient };
@@ -193,12 +193,14 @@ var LEARNWITHAI_QTI_URLS = {
193
193
  var PLATFORM_ENDPOINTS = {
194
194
  BEYOND_AI: {
195
195
  token: BEYONDAI_TOKEN_URLS,
196
+ tokenScope: undefined,
196
197
  api: BEYONDAI_API_URLS,
197
198
  caliper: BEYONDAI_CALIPER_URLS,
198
199
  qti: BEYONDAI_QTI_URLS
199
200
  },
200
201
  LEARNWITH_AI: {
201
202
  token: LEARNWITHAI_TOKEN_URLS,
203
+ tokenScope: "https://purl.imsglobal.org/spec/caliper/v1p2/scope/events.write",
202
204
  api: LEARNWITHAI_API_URLS,
203
205
  caliper: LEARNWITHAI_CALIPER_URLS,
204
206
  qti: LEARNWITHAI_QTI_URLS
@@ -582,7 +584,7 @@ class TokenManager {
582
584
  Authorization: `Basic ${credentials}`,
583
585
  "Content-Type": "application/x-www-form-urlencoded"
584
586
  },
585
- body: "grant_type=client_credentials"
587
+ body: this.config.scope ? `grant_type=client_credentials&scope=${encodeURIComponent(this.config.scope)}` : "grant_type=client_credentials"
586
588
  });
587
589
  const duration = Math.round(performance.now() - start);
588
590
  if (!response.ok) {
@@ -646,7 +648,7 @@ var BEYONDAI_PATHS = {
646
648
  };
647
649
  var LEARNWITHAI_PATHS = {
648
650
  caliper: {
649
- send: "/events/1.0/",
651
+ send: "/caliper/v1p2",
650
652
  validate: null,
651
653
  list: null,
652
654
  get: null,
@@ -661,7 +663,9 @@ var LEARNWITHAI_PATHS = {
661
663
  edubridge: null,
662
664
  powerpath: null,
663
665
  clr: null,
664
- case: null
666
+ case: {
667
+ base: "/case/1.1"
668
+ }
665
669
  };
666
670
  var PLATFORM_PATHS = {
667
671
  BEYOND_AI: BEYONDAI_PATHS,
@@ -698,6 +702,7 @@ class TimebackProvider {
698
702
  timeout;
699
703
  endpoints;
700
704
  authUrl;
705
+ tokenScope;
701
706
  pathProfiles;
702
707
  tokenManagers = new Map;
703
708
  constructor(config) {
@@ -713,6 +718,7 @@ class TimebackProvider {
713
718
  throw new Error(`Unknown platform: ${platform}`);
714
719
  }
715
720
  this.authUrl = platformEndpoints.token[env];
721
+ this.tokenScope = platformEndpoints.tokenScope ?? undefined;
716
722
  this.pathProfiles = PLATFORM_PATHS[platform] ?? BEYONDAI_PATHS;
717
723
  this.endpoints = {
718
724
  oneroster: {
@@ -838,7 +844,8 @@ class TimebackProvider {
838
844
  credentials: {
839
845
  clientId: this.auth.clientId,
840
846
  clientSecret: this.auth.clientSecret
841
- }
847
+ },
848
+ scope: this.tokenScope
842
849
  });
843
850
  this.tokenManagers.set(authUrl, manager);
844
851
  }
@@ -856,7 +863,8 @@ class TimebackProvider {
856
863
  credentials: {
857
864
  clientId: this.auth.clientId,
858
865
  clientSecret: this.auth.clientSecret
859
- }
866
+ },
867
+ scope: this.tokenScope
860
868
  });
861
869
  this.tokenManagers.set(this.authUrl, manager);
862
870
  }
@@ -1540,7 +1548,7 @@ function issue(path, message) {
1540
1548
  function validateWithSchema(schema, data, context) {
1541
1549
  const result = schema.safeParse(data);
1542
1550
  if (result.success) {
1543
- return;
1551
+ return result.data;
1544
1552
  }
1545
1553
  const issues = result.error.issues.map((errorIssue) => ({
1546
1554
  path: errorIssue.path.join(".") || "(root)",
package/dist/errors.js CHANGED
@@ -4,7 +4,7 @@ import {
4
4
  NotFoundError,
5
5
  UnauthorizedError,
6
6
  ValidationError
7
- } from "./chunk-j1vhg225.js";
7
+ } from "./chunk-k030r9e8.js";
8
8
  import"./chunk-3j7jywnx.js";
9
9
  export {
10
10
  ValidationError,
package/dist/index.js CHANGED
@@ -72,12 +72,15 @@ import {
72
72
  QtiTestPart,
73
73
  QtiValidateBatchInput,
74
74
  QtiValidateInput,
75
+ QuestionAnsweredInput,
76
+ QuestionGradedInput,
77
+ QuestionSeenInput,
75
78
  TimeSpentInput,
76
79
  WebhookCreateInput,
77
80
  WebhookFilterCreateInput,
78
81
  WebhookFilterUpdateInput,
79
82
  WebhookUpdateInput
80
- } from "./chunk-5g1cbkry.js";
83
+ } from "./chunk-f69gqv7m.js";
81
84
  import {
82
85
  ApiError,
83
86
  BaseTransport,
@@ -103,20 +106,153 @@ import {
103
106
  validateUuid,
104
107
  validateWithSchema,
105
108
  whereToFilter
106
- } from "./chunk-j1vhg225.js";
109
+ } from "./chunk-k030r9e8.js";
107
110
  import {
108
111
  CALIPER_DATA_VERSION,
109
- CALIPER_ENV_VARS
110
- } from "./chunk-rjcapq41.js";
112
+ CALIPER_ENV_VARS,
113
+ QUESTION_RESULT_SCORE_TYPE
114
+ } from "./chunk-858qz9cb.js";
111
115
  import"./chunk-3j7jywnx.js";
112
116
 
113
- // ../caliper/src/lib/resolve.ts
114
- function resolveToProvider2(config, registry = DEFAULT_PROVIDER_REGISTRY) {
115
- return resolveToProvider(config, CALIPER_ENV_VARS, registry);
116
- }
117
+ // ../caliper/src/utils.ts
118
+ var log = createScopedLogger("caliper");
117
119
 
120
+ // ../caliper/src/lib/transport.ts
121
+ class Transport extends BaseTransport {
122
+ paths;
123
+ constructor(config) {
124
+ super({ config, logger: log });
125
+ this.paths = config.paths;
126
+ }
127
+ async requestPaginated(path, options = {}) {
128
+ const response = await this.request(path, options);
129
+ const { events, pagination } = response;
130
+ const offset = options.params?.offset ?? 0;
131
+ const hasMore = offset + events.length < pagination.total;
132
+ return {
133
+ data: events,
134
+ hasMore,
135
+ total: pagination.total
136
+ };
137
+ }
138
+ }
139
+ // ../caliper/src/lib/pagination.ts
140
+ class Paginator2 extends Paginator {
141
+ constructor(transport, path, params = {}) {
142
+ validateOffsetListParams(params);
143
+ const { max, ...requestParams } = params;
144
+ super({
145
+ fetcher: (p, opts) => transport.requestPaginated(p, opts),
146
+ path,
147
+ params: requestParams,
148
+ max,
149
+ logger: log
150
+ });
151
+ }
152
+ }
153
+ // ../caliper/src/lib/event-factories.ts
154
+ function createActivityEvent(input) {
155
+ const eventId = input.id ?? `urn:uuid:${crypto.randomUUID()}`;
156
+ const metricsId = input.metricsId ?? `urn:uuid:${crypto.randomUUID()}`;
157
+ return {
158
+ "@context": CALIPER_DATA_VERSION,
159
+ id: eventId,
160
+ type: "ActivityEvent",
161
+ action: "Completed",
162
+ actor: input.actor,
163
+ object: input.object,
164
+ eventTime: input.eventTime ?? new Date().toISOString(),
165
+ profile: "TimebackProfile",
166
+ generated: {
167
+ id: metricsId,
168
+ type: "TimebackActivityMetricsCollection",
169
+ items: input.metrics,
170
+ ...input.attempt === undefined ? {} : { attempt: input.attempt },
171
+ ...input.generatedExtensions ? { extensions: input.generatedExtensions } : {}
172
+ },
173
+ extensions: input.extensions,
174
+ ...input.edApp === undefined ? {} : { edApp: input.edApp },
175
+ ...input.session === undefined ? {} : { session: input.session }
176
+ };
177
+ }
178
+ function createTimeSpentEvent(input) {
179
+ const eventId = input.id ?? `urn:uuid:${crypto.randomUUID()}`;
180
+ const metricsId = input.metricsId ?? `urn:uuid:${crypto.randomUUID()}`;
181
+ return {
182
+ "@context": CALIPER_DATA_VERSION,
183
+ id: eventId,
184
+ type: "TimeSpentEvent",
185
+ action: "SpentTime",
186
+ actor: input.actor,
187
+ object: input.object,
188
+ eventTime: input.eventTime ?? new Date().toISOString(),
189
+ profile: "TimebackProfile",
190
+ generated: {
191
+ id: metricsId,
192
+ type: "TimebackTimeSpentMetricsCollection",
193
+ items: input.metrics
194
+ },
195
+ extensions: input.extensions,
196
+ ...input.edApp === undefined ? {} : { edApp: input.edApp },
197
+ ...input.session === undefined ? {} : { session: input.session }
198
+ };
199
+ }
200
+ function createQuestionSeenEvent(input) {
201
+ return {
202
+ "@context": CALIPER_DATA_VERSION,
203
+ id: input.id ?? `urn:uuid:${crypto.randomUUID()}`,
204
+ type: "AssessmentItemEvent",
205
+ action: "Started",
206
+ profile: "AssessmentProfile",
207
+ actor: input.actor,
208
+ object: { ...input.object, type: "AssessmentItem" },
209
+ eventTime: input.eventTime ?? new Date().toISOString(),
210
+ edApp: input.edApp,
211
+ ...input.session === undefined ? {} : { session: input.session },
212
+ ...input.extensions === undefined ? {} : { extensions: input.extensions }
213
+ };
214
+ }
215
+ function createQuestionAnsweredEvent(input) {
216
+ return {
217
+ "@context": CALIPER_DATA_VERSION,
218
+ id: input.id ?? `urn:uuid:${crypto.randomUUID()}`,
219
+ type: "AssessmentItemEvent",
220
+ action: "Completed",
221
+ profile: "AssessmentProfile",
222
+ actor: input.actor,
223
+ object: { ...input.object, type: "AssessmentItem" },
224
+ eventTime: input.eventTime ?? new Date().toISOString(),
225
+ edApp: input.edApp,
226
+ ...input.generated === undefined ? {} : { generated: { ...input.generated, type: "Response" } },
227
+ ...input.session === undefined ? {} : { session: input.session },
228
+ ...input.extensions === undefined ? {} : { extensions: input.extensions }
229
+ };
230
+ }
231
+ function createQuestionGradedEvent(input) {
232
+ const { id: scoreId, ...scoreRest } = input.generated;
233
+ return {
234
+ "@context": CALIPER_DATA_VERSION,
235
+ id: input.id ?? `urn:uuid:${crypto.randomUUID()}`,
236
+ type: "GradeEvent",
237
+ action: "Graded",
238
+ profile: "GradingProfile",
239
+ actor: input.actor,
240
+ object: input.object,
241
+ eventTime: input.eventTime ?? new Date().toISOString(),
242
+ edApp: input.edApp,
243
+ generated: {
244
+ ...scoreRest,
245
+ id: scoreId ?? `urn:uuid:${crypto.randomUUID()}`,
246
+ type: "Score",
247
+ scoreType: QUESTION_RESULT_SCORE_TYPE
248
+ },
249
+ ...input.session === undefined ? {} : { session: input.session },
250
+ ...input.extensions === undefined ? {} : { extensions: input.extensions }
251
+ };
252
+ }
118
253
  // ../caliper/src/lib/lwai-event-transformer.ts
119
254
  var CALIPER_CONTEXT = "http://purl.imsglobal.org/ctx/caliper/v1p2";
255
+ var SESSION_AUTO_ATTACH = "urn:tag:auto-attach";
120
256
  var CALIPER_TYPE = {
121
257
  PERSON: "Person",
122
258
  ASSIGNABLE_DIGITAL_RESOURCE: "AssignableDigitalResource",
@@ -151,7 +287,7 @@ function transformEvent(event) {
151
287
  if (transformed.profile === "TimebackProfile") {
152
288
  transformed.profile = "AggregationProfile";
153
289
  }
154
- if (isDict(transformed.actor)) {
290
+ if (isDict(transformed.actor) && transformed.actor.type === "TimebackUser") {
155
291
  transformed.actor = transformActor(transformed.actor);
156
292
  }
157
293
  if (isDict(transformed.object)) {
@@ -165,6 +301,9 @@ function transformEvent(event) {
165
301
  transformed.generated = transformTimeSpentMetrics(transformed.generated);
166
302
  }
167
303
  }
304
+ if (!transformed.session) {
305
+ transformed.session = SESSION_AUTO_ATTACH;
306
+ }
168
307
  return transformed;
169
308
  }
170
309
  function transformActor(actor) {
@@ -234,91 +373,9 @@ function transformTimeSpentMetrics(collection) {
234
373
  function isDict(value) {
235
374
  return typeof value === "object" && value !== null && !Array.isArray(value);
236
375
  }
237
-
238
- // ../caliper/src/utils.ts
239
- var log = createScopedLogger("caliper");
240
-
241
- // ../caliper/src/lib/transport.ts
242
- class Transport extends BaseTransport {
243
- paths;
244
- constructor(config) {
245
- super({ config, logger: log });
246
- this.paths = config.paths;
247
- }
248
- async requestPaginated(path, options = {}) {
249
- const response = await this.request(path, options);
250
- const { events, pagination } = response;
251
- const offset = options.params?.offset ?? 0;
252
- const hasMore = offset + events.length < pagination.total;
253
- return {
254
- data: events,
255
- hasMore,
256
- total: pagination.total
257
- };
258
- }
259
- }
260
-
261
- // ../caliper/src/lib/event-factories.ts
262
- function createActivityEvent(input) {
263
- const eventId = input.id ?? `urn:uuid:${crypto.randomUUID()}`;
264
- const metricsId = input.metricsId ?? `urn:uuid:${crypto.randomUUID()}`;
265
- return {
266
- "@context": CALIPER_DATA_VERSION,
267
- id: eventId,
268
- type: "ActivityEvent",
269
- action: "Completed",
270
- actor: input.actor,
271
- object: input.object,
272
- eventTime: input.eventTime ?? new Date().toISOString(),
273
- profile: "TimebackProfile",
274
- generated: {
275
- id: metricsId,
276
- type: "TimebackActivityMetricsCollection",
277
- items: input.metrics,
278
- ...input.attempt === undefined ? {} : { attempt: input.attempt },
279
- ...input.generatedExtensions ? { extensions: input.generatedExtensions } : {}
280
- },
281
- extensions: input.extensions,
282
- ...input.edApp === undefined ? {} : { edApp: input.edApp },
283
- ...input.session === undefined ? {} : { session: input.session }
284
- };
285
- }
286
- function createTimeSpentEvent(input) {
287
- const eventId = input.id ?? `urn:uuid:${crypto.randomUUID()}`;
288
- const metricsId = input.metricsId ?? `urn:uuid:${crypto.randomUUID()}`;
289
- return {
290
- "@context": CALIPER_DATA_VERSION,
291
- id: eventId,
292
- type: "TimeSpentEvent",
293
- action: "SpentTime",
294
- actor: input.actor,
295
- object: input.object,
296
- eventTime: input.eventTime ?? new Date().toISOString(),
297
- profile: "TimebackProfile",
298
- generated: {
299
- id: metricsId,
300
- type: "TimebackTimeSpentMetricsCollection",
301
- items: input.metrics
302
- },
303
- extensions: input.extensions,
304
- ...input.edApp === undefined ? {} : { edApp: input.edApp },
305
- ...input.session === undefined ? {} : { session: input.session }
306
- };
307
- }
308
-
309
- // ../caliper/src/lib/pagination.ts
310
- class Paginator2 extends Paginator {
311
- constructor(transport, path, params = {}) {
312
- validateOffsetListParams(params);
313
- const { max, ...requestParams } = params;
314
- super({
315
- fetcher: (p, opts) => transport.requestPaginated(p, opts),
316
- path,
317
- params: requestParams,
318
- max,
319
- logger: log
320
- });
321
- }
376
+ // ../caliper/src/lib/resolve.ts
377
+ function resolveToProvider2(config, registry = DEFAULT_PROVIDER_REGISTRY) {
378
+ return resolveToProvider(config, CALIPER_ENV_VARS, registry);
322
379
  }
323
380
 
324
381
  // ../caliper/src/resources/events.ts
@@ -347,8 +404,9 @@ class EventsResource {
347
404
  });
348
405
  const body = this.eventTransformer ? this.eventTransformer.transformEnvelope(envelope) : envelope;
349
406
  const response = await this.transport.request(this.transport.paths.send, { method: "POST", body });
350
- log.debug("Events queued for processing", { jobId: response.jobId });
351
- return { jobId: response.jobId };
407
+ const jobId = response?.jobId;
408
+ log.debug("Events sent", { jobId: jobId ?? "(none)" });
409
+ return { jobId };
352
410
  }
353
411
  async validate(envelope) {
354
412
  const validatePath = this.transport.paths.validate;
@@ -461,6 +519,37 @@ class EventsResource {
461
519
  });
462
520
  return this.send(sensor, [event]);
463
521
  }
522
+ sendQuestionSeen(sensor, input) {
523
+ validateWithSchema(QuestionSeenInput, input, "question seen event");
524
+ const event = createQuestionSeenEvent(input);
525
+ log.debug("Sending AssessmentItemEvent.Started", {
526
+ eventId: event.id,
527
+ actor: input.actor,
528
+ object: input.object.id
529
+ });
530
+ return this.send(sensor, [event]);
531
+ }
532
+ sendQuestionAnswered(sensor, input) {
533
+ validateWithSchema(QuestionAnsweredInput, input, "question answered event");
534
+ const event = createQuestionAnsweredEvent(input);
535
+ log.debug("Sending AssessmentItemEvent.Completed", {
536
+ eventId: event.id,
537
+ actor: input.actor,
538
+ object: input.object.id
539
+ });
540
+ return this.send(sensor, [event]);
541
+ }
542
+ sendQuestionGraded(sensor, input) {
543
+ validateWithSchema(QuestionGradedInput, input, "question graded event");
544
+ const event = createQuestionGradedEvent(input);
545
+ log.debug("Sending GradeEvent.Graded", {
546
+ eventId: event.id,
547
+ actor: input.actor,
548
+ object: input.object,
549
+ scoreGiven: input.generated.scoreGiven
550
+ });
551
+ return this.send(sensor, [event]);
552
+ }
464
553
  }
465
554
  // ../caliper/src/resources/jobs.ts
466
555
  class JobsResource {
@@ -964,10 +1053,8 @@ class BaseResource {
964
1053
  }
965
1054
  create(data) {
966
1055
  const schema = this.createSchema;
967
- if (schema) {
968
- validateWithSchema(schema, data, this.resourceName);
969
- }
970
- const body = this.wrapBody(data);
1056
+ const validated = schema ? validateWithSchema(schema, data, this.resourceName) : data;
1057
+ const body = this.wrapBody(validated);
971
1058
  return this.transport.request(this.basePath, {
972
1059
  method: "POST",
973
1060
  body
@@ -993,10 +1080,8 @@ class BaseResource {
993
1080
  }
994
1081
  async sendUpdate(sourcedId, data) {
995
1082
  const schema = this.updateSchema;
996
- if (schema) {
997
- validateWithSchema(schema, data, `update ${this.resourceName}`);
998
- }
999
- const body = this.wrapBody(data);
1083
+ const validated = schema ? validateWithSchema(schema, data, `update ${this.resourceName}`) : data;
1084
+ const body = this.wrapBody(validated);
1000
1085
  await this.transport.request(`${this.basePath}/${sourcedId}`, {
1001
1086
  method: "PUT",
1002
1087
  body
@@ -1005,10 +1090,8 @@ class BaseResource {
1005
1090
  }
1006
1091
  async sendUpdateAndReturn(sourcedId, data) {
1007
1092
  const schema = this.updateSchema;
1008
- if (schema) {
1009
- validateWithSchema(schema, data, `update ${this.resourceName}`);
1010
- }
1011
- const body = this.wrapBody(data);
1093
+ const validated = schema ? validateWithSchema(schema, data, `update ${this.resourceName}`) : data;
1094
+ const body = this.wrapBody(validated);
1012
1095
  const response = await this.transport.request(`${this.basePath}/${sourcedId}`, {
1013
1096
  method: "PUT",
1014
1097
  body
@@ -1861,10 +1944,10 @@ class ScopedSchoolResource {
1861
1944
  return new Paginator3(this.transport, `${this.gradebookPath}/lineItems`, params, "lineItems");
1862
1945
  }
1863
1946
  createLineItem(data) {
1864
- validateWithSchema(OneRosterLineItemCreateInput, data, "line item");
1947
+ const validated = validateWithSchema(OneRosterLineItemCreateInput, data, "line item");
1865
1948
  return this.transport.request(`${this.gradebookPath}/lineItems`, {
1866
1949
  method: "POST",
1867
- body: { lineItems: [data] }
1950
+ body: { lineItems: [validated] }
1868
1951
  });
1869
1952
  }
1870
1953
  scoreScales(params) {
@@ -1918,10 +2001,10 @@ class ScopedClassAcademicSessionResource {
1918
2001
  this.gradebookPath = `${transport.paths.gradebook}/classes/${classId}/academicSessions/${sessionId}`;
1919
2002
  }
1920
2003
  createResult(result) {
1921
- validateWithSchema(OneRosterResultCreateInput, result, "result");
2004
+ const validated = validateWithSchema(OneRosterResultCreateInput, result, "result");
1922
2005
  return this.transport.request(`${this.gradebookPath}/results`, {
1923
2006
  method: "POST",
1924
- body: { results: [result] }
2007
+ body: { results: [validated] }
1925
2008
  });
1926
2009
  }
1927
2010
  }
@@ -2013,10 +2096,10 @@ class ScopedClassResource {
2013
2096
  return new Paginator3(this.transport, `${this.gradebookPath}/lineItems`, params, "lineItems");
2014
2097
  }
2015
2098
  createLineItem(data) {
2016
- validateWithSchema(OneRosterLineItemCreateInput, data, "line item");
2099
+ const validated = validateWithSchema(OneRosterLineItemCreateInput, data, "line item");
2017
2100
  return this.transport.request(`${this.gradebookPath}/lineItems`, {
2018
2101
  method: "POST",
2019
- body: { lineItems: [data] }
2102
+ body: { lineItems: [validated] }
2020
2103
  });
2021
2104
  }
2022
2105
  results(params) {
@@ -2347,10 +2430,10 @@ class ScopedTermResource {
2347
2430
  return new Paginator3(this.transport, `${this.basePath}/gradingPeriods`, params, "gradingPeriods");
2348
2431
  }
2349
2432
  createGradingPeriod(data) {
2350
- validateWithSchema(OneRosterAcademicSessionCreateInput, data, "grading period");
2433
+ const validated = validateWithSchema(OneRosterAcademicSessionCreateInput, data, "grading period");
2351
2434
  return this.transport.request(`${this.basePath}/gradingPeriods`, {
2352
2435
  method: "POST",
2353
- body: { academicSession: data }
2436
+ body: { academicSession: validated }
2354
2437
  });
2355
2438
  }
2356
2439
  }
package/dist/types.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  CALIPER_DATA_VERSION
3
- } from "./chunk-rjcapq41.js";
3
+ } from "./chunk-858qz9cb.js";
4
4
  import {
5
5
  __export
6
6
  } from "./chunk-3j7jywnx.js";
package/dist/utils.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  aggregateActivityMetrics
3
- } from "./chunk-5g1cbkry.js";
4
- import"./chunk-j1vhg225.js";
3
+ } from "./chunk-f69gqv7m.js";
4
+ import"./chunk-k030r9e8.js";
5
5
  import"./chunk-3j7jywnx.js";
6
6
  export {
7
7
  aggregateActivityMetrics
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@timeback/core",
3
- "version": "0.1.7-beta.20260309215937",
3
+ "version": "0.1.7-beta.20260311174536",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": {