@timeback/caliper 0.1.5 → 0.1.6

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.
@@ -0,0 +1,879 @@
1
+ /**
2
+ * Timeback Shared Primitives
3
+ *
4
+ * Core types used across multiple Timeback protocols.
5
+ *
6
+ * Organization:
7
+ * - Shared types (this file): Used by multiple protocols (Caliper, OneRoster, etc.)
8
+ * - Protocol-specific types: Live in their respective protocols/X/primitives.ts files
9
+ *
10
+ * What belongs here:
11
+ * - TimebackSubject - Used in OneRoster courses AND Caliper events
12
+ * - TimebackGrade - Used across OneRoster, Caliper, and QTI
13
+ * - IMSErrorResponse - IMS Global standard used by multiple 1EdTech protocols
14
+ *
15
+ * What doesn't belong here:
16
+ * - OneRoster-specific: protocols/oneroster/primitives.ts
17
+ * - QTI-specific: protocols/qti/primitives.ts
18
+ */
19
+
20
+ // ─────────────────────────────────────────────────────────────────────────────
21
+ // TIMEBACK SHARED TYPES
22
+ // ─────────────────────────────────────────────────────────────────────────────
23
+
24
+ /**
25
+ * Valid Timeback subject values.
26
+ * Used in OneRoster courses and Caliper events.
27
+ */
28
+ type TimebackSubject =
29
+ | 'Reading'
30
+ | 'Language'
31
+ | 'Vocabulary'
32
+ | 'Social Studies'
33
+ | 'Writing'
34
+ | 'Science'
35
+ | 'FastMath'
36
+ | 'Math'
37
+ | 'None'
38
+ | 'Other'
39
+
40
+ /**
41
+ * Timeback Profile Types
42
+ *
43
+ * First-class types for the Timeback Caliper profile, including
44
+ * ActivityCompletedEvent and TimeSpentEvent.
45
+ */
46
+
47
+
48
+
49
+ // ═══════════════════════════════════════════════════════════════════════════════
50
+ // TIMEBACK ACTIVITY CONTEXT
51
+ // ═══════════════════════════════════════════════════════════════════════════════
52
+
53
+ // ═══════════════════════════════════════════════════════════════════════════════
54
+ // TIMEBACK USER
55
+ // ═══════════════════════════════════════════════════════════════════════════════
56
+
57
+ /**
58
+ * User role in the Timeback platform.
59
+ */
60
+ type TimebackUserRole = 'student' | 'teacher' | 'admin' | 'guide'
61
+
62
+ /**
63
+ * Timeback user entity.
64
+ *
65
+ * Represents a user in the Timeback platform. The `id` should ideally be
66
+ * the OneRoster URL for the user when available.
67
+ *
68
+ * @example
69
+ * ```typescript
70
+ * const user: TimebackUser = {
71
+ * id: 'https://api.alpha-1edtech.ai/ims/oneroster/rostering/v1p2/users/123',
72
+ * type: 'TimebackUser',
73
+ * email: 'student@example.edu',
74
+ * name: 'Jane Doe',
75
+ * role: 'student',
76
+ * }
77
+ * ```
78
+ */
79
+ interface TimebackUser {
80
+ /** User identifier (IRI format, preferably OneRoster URL) */
81
+ id: string
82
+ /** Must be 'TimebackUser' */
83
+ type: 'TimebackUser'
84
+ /** User email address */
85
+ email: string
86
+ /** User display name */
87
+ name?: string
88
+ /** User role */
89
+ role?: TimebackUserRole
90
+ /** Additional custom attributes */
91
+ extensions?: Record<string, unknown>
92
+ /** Index signature for Caliper compatibility */
93
+ [key: string]: unknown
94
+ }
95
+
96
+ /**
97
+ * Application reference within activity context.
98
+ */
99
+ interface TimebackApp {
100
+ /** Application identifier (IRI format) */
101
+ id?: string
102
+ /** Application name */
103
+ name: string
104
+ /** Additional custom attributes */
105
+ extensions?: Record<string, unknown>
106
+ }
107
+
108
+ /**
109
+ * Course reference within activity context.
110
+ */
111
+ interface TimebackCourse {
112
+ /** Course identifier (IRI format, preferably OneRoster URL) */
113
+ id?: string
114
+ /** Course name */
115
+ name: string
116
+ /** Additional custom attributes */
117
+ extensions?: Record<string, unknown>
118
+ }
119
+
120
+ /**
121
+ * Activity reference within activity context.
122
+ */
123
+ interface TimebackActivity {
124
+ /** Activity identifier (IRI format) */
125
+ id?: string
126
+ /** Activity name */
127
+ name: string
128
+ /** Additional custom attributes */
129
+ extensions?: Record<string, unknown>
130
+ }
131
+
132
+ /**
133
+ * Timeback activity context.
134
+ *
135
+ * Represents the context where an event was recorded, including
136
+ * subject, application, course, and activity information.
137
+ *
138
+ * @example
139
+ * ```typescript
140
+ * const context: TimebackActivityContext = {
141
+ * id: 'https://myapp.example.com/activities/123',
142
+ * type: 'TimebackActivityContext',
143
+ * subject: 'Math',
144
+ * app: { name: 'My Learning App' },
145
+ * course: { name: 'Algebra 101' },
146
+ * activity: { name: 'Chapter 1 Quiz' },
147
+ * }
148
+ * ```
149
+ */
150
+ interface TimebackActivityContext {
151
+ /** Context identifier (IRI format) */
152
+ id: string
153
+ /** Must be 'TimebackActivityContext' */
154
+ type: 'TimebackActivityContext'
155
+ /** Subject area */
156
+ subject: TimebackSubject
157
+ /** Application where event was recorded */
158
+ app: TimebackApp
159
+ /** Course where event was recorded */
160
+ course?: TimebackCourse
161
+ /** Activity where event was recorded */
162
+ activity?: TimebackActivity
163
+ /** Whether to process this event */
164
+ process?: boolean
165
+ /** Index signature for Caliper compatibility */
166
+ [key: string]: unknown
167
+ }
168
+
169
+ // ═══════════════════════════════════════════════════════════════════════════════
170
+ // ACTIVITY METRICS
171
+ // ═══════════════════════════════════════════════════════════════════════════════
172
+
173
+ /**
174
+ * Types of activity metrics.
175
+ */
176
+ type ActivityMetricType =
177
+ | 'xpEarned'
178
+ | 'totalQuestions'
179
+ | 'correctQuestions'
180
+ | 'masteredUnits'
181
+
182
+ /**
183
+ * Individual activity metric.
184
+ *
185
+ * @example
186
+ * ```typescript
187
+ * const metric: TimebackActivityMetric = {
188
+ * type: 'correctQuestions',
189
+ * value: 8,
190
+ * }
191
+ * ```
192
+ */
193
+ interface TimebackActivityMetric {
194
+ /** Metric type */
195
+ type: ActivityMetricType
196
+ /** Metric value */
197
+ value: number
198
+ /** Additional custom attributes */
199
+ extensions?: Record<string, unknown>
200
+ }
201
+
202
+ /**
203
+ * Collection of activity metrics.
204
+ *
205
+ * @example
206
+ * ```typescript
207
+ * const metrics: TimebackActivityMetricsCollection = {
208
+ * id: 'https://myapp.example.com/metrics/123',
209
+ * type: 'TimebackActivityMetricsCollection',
210
+ * attempt: 1,
211
+ * items: [
212
+ * { type: 'totalQuestions', value: 10 },
213
+ * { type: 'correctQuestions', value: 8 },
214
+ * { type: 'xpEarned', value: 150 },
215
+ * ],
216
+ * extensions: { pctCompleteApp: 67 },
217
+ * }
218
+ * ```
219
+ */
220
+ interface TimebackActivityMetricsCollection {
221
+ /** Collection identifier (IRI format) */
222
+ id: string
223
+ /** Must be 'TimebackActivityMetricsCollection' */
224
+ type: 'TimebackActivityMetricsCollection'
225
+ /** Attempt number (1-based) */
226
+ attempt?: number
227
+ /** Array of metrics */
228
+ items: TimebackActivityMetric[]
229
+ /**
230
+ * Additional custom attributes.
231
+ *
232
+ * Common fields:
233
+ * - `pctCompleteApp`: App-defined course completion percentage (0–100)
234
+ */
235
+ extensions?: Record<string, unknown>
236
+ /** Index signature for Caliper compatibility */
237
+ [key: string]: unknown
238
+ }
239
+
240
+ // ═══════════════════════════════════════════════════════════════════════════════
241
+ // TIME SPENT METRICS
242
+ // ═══════════════════════════════════════════════════════════════════════════════
243
+
244
+ /**
245
+ * Types of time spent metrics.
246
+ */
247
+ type TimeSpentMetricType = 'active' | 'inactive' | 'waste' | 'unknown' | 'anti-pattern'
248
+
249
+ /**
250
+ * Individual time spent metric.
251
+ *
252
+ * @example
253
+ * ```typescript
254
+ * const metric: TimeSpentMetric = {
255
+ * type: 'active',
256
+ * value: 1800, // 30 minutes in seconds
257
+ * startDate: '2024-01-15T10:00:00Z',
258
+ * endDate: '2024-01-15T10:30:00Z',
259
+ * }
260
+ * ```
261
+ */
262
+ interface TimeSpentMetric {
263
+ /** Metric type */
264
+ type: TimeSpentMetricType
265
+ /** Time spent in seconds (max 86400 = 24 hours) */
266
+ value: number
267
+ /** Sub-type for additional categorization */
268
+ subType?: string
269
+ /** Start of the time period */
270
+ startDate?: string
271
+ /** End of the time period */
272
+ endDate?: string
273
+ /** Additional custom attributes */
274
+ extensions?: Record<string, unknown>
275
+ }
276
+
277
+ /**
278
+ * Collection of time spent metrics.
279
+ *
280
+ * @example
281
+ * ```typescript
282
+ * const metrics: TimebackTimeSpentMetricsCollection = {
283
+ * id: 'https://myapp.example.com/time-metrics/123',
284
+ * type: 'TimebackTimeSpentMetricsCollection',
285
+ * items: [
286
+ * { type: 'active', value: 1800 },
287
+ * { type: 'inactive', value: 300 },
288
+ * ],
289
+ * }
290
+ * ```
291
+ */
292
+ interface TimebackTimeSpentMetricsCollection {
293
+ /** Collection identifier (IRI format) */
294
+ id: string
295
+ /** Must be 'TimebackTimeSpentMetricsCollection' */
296
+ type: 'TimebackTimeSpentMetricsCollection'
297
+ /** Array of time spent metrics */
298
+ items: TimeSpentMetric[]
299
+ /** Additional custom attributes */
300
+ extensions?: Record<string, unknown>
301
+ /** Index signature for Caliper compatibility */
302
+ [key: string]: unknown
303
+ }
304
+
305
+ // ═══════════════════════════════════════════════════════════════════════════════
306
+ // TIMEBACK EVENTS
307
+ // ═══════════════════════════════════════════════════════════════════════════════
308
+
309
+ /**
310
+ * Base properties common to all Timeback events.
311
+ */
312
+ interface TimebackEventBase {
313
+ /** JSON-LD context */
314
+ '@context': 'http://purl.imsglobal.org/ctx/caliper/v1p2'
315
+ /** Unique identifier (URN UUID format) */
316
+ id: string
317
+ /** The user who performed the action */
318
+ actor: TimebackUser
319
+ /** The activity context */
320
+ object: TimebackActivityContext
321
+ /** ISO 8601 datetime when event occurred */
322
+ eventTime: string
323
+ /** Must be 'TimebackProfile' */
324
+ profile: 'TimebackProfile'
325
+ /** Application context (IRI or entity) */
326
+ edApp?: string | Record<string, unknown>
327
+ /** Target segment within object */
328
+ target?: string | Record<string, unknown>
329
+ /** Referring context */
330
+ referrer?: string | Record<string, unknown>
331
+ /** Organization/group context */
332
+ group?: string | Record<string, unknown>
333
+ /** User's membership/role */
334
+ membership?: string | Record<string, unknown>
335
+ /** Current user session */
336
+ session?: string | Record<string, unknown>
337
+ /** LTI session context */
338
+ federatedSession?: string | Record<string, unknown>
339
+ /** Additional custom attributes */
340
+ extensions?: Record<string, unknown>
341
+ }
342
+
343
+ /**
344
+ * Timeback Activity Completed Event.
345
+ *
346
+ * Records when a student completes an activity, along with performance metrics.
347
+ *
348
+ * @example
349
+ * ```typescript
350
+ * const event: ActivityCompletedEvent = {
351
+ * '@context': 'http://purl.imsglobal.org/ctx/caliper/v1p2',
352
+ * id: 'urn:uuid:c51570e4-f8ed-4c18-bb3a-dfe51b2cc594',
353
+ * type: 'ActivityEvent',
354
+ * action: 'Completed',
355
+ * actor: {
356
+ * id: 'https://api.example.com/users/123',
357
+ * type: 'TimebackUser',
358
+ * email: 'student@example.edu',
359
+ * },
360
+ * object: {
361
+ * id: 'https://myapp.example.com/activities/456',
362
+ * type: 'TimebackActivityContext',
363
+ * subject: 'Math',
364
+ * app: { name: 'My Learning App' },
365
+ * },
366
+ * eventTime: '2024-01-15T14:30:00Z',
367
+ * profile: 'TimebackProfile',
368
+ * generated: {
369
+ * id: 'https://myapp.example.com/metrics/789',
370
+ * type: 'TimebackActivityMetricsCollection',
371
+ * items: [
372
+ * { type: 'totalQuestions', value: 10 },
373
+ * { type: 'correctQuestions', value: 8 },
374
+ * ],
375
+ * },
376
+ * }
377
+ * ```
378
+ */
379
+ interface ActivityCompletedEvent extends TimebackEventBase {
380
+ /** Must be 'ActivityEvent' */
381
+ type: 'ActivityEvent'
382
+ /** Must be 'Completed' */
383
+ action: 'Completed'
384
+ /** Activity metrics generated from this completion */
385
+ generated: TimebackActivityMetricsCollection
386
+ }
387
+
388
+ /**
389
+ * Timeback Time Spent Event.
390
+ *
391
+ * Records time spent on an activity, categorized by engagement type.
392
+ *
393
+ * @example
394
+ * ```typescript
395
+ * const event: TimeSpentEvent = {
396
+ * '@context': 'http://purl.imsglobal.org/ctx/caliper/v1p2',
397
+ * id: 'urn:uuid:d62681f5-g9fe-5d29-cc4b-efg62c3dd695',
398
+ * type: 'TimeSpentEvent',
399
+ * action: 'SpentTime',
400
+ * actor: {
401
+ * id: 'https://api.example.com/users/123',
402
+ * type: 'TimebackUser',
403
+ * email: 'student@example.edu',
404
+ * },
405
+ * object: {
406
+ * id: 'https://myapp.example.com/activities/456',
407
+ * type: 'TimebackActivityContext',
408
+ * subject: 'Reading',
409
+ * app: { name: 'My Learning App' },
410
+ * },
411
+ * eventTime: '2024-01-15T15:00:00Z',
412
+ * profile: 'TimebackProfile',
413
+ * generated: {
414
+ * id: 'https://myapp.example.com/time-metrics/789',
415
+ * type: 'TimebackTimeSpentMetricsCollection',
416
+ * items: [
417
+ * { type: 'active', value: 1800 },
418
+ * { type: 'inactive', value: 300 },
419
+ * ],
420
+ * },
421
+ * }
422
+ * ```
423
+ */
424
+ interface TimeSpentEvent extends TimebackEventBase {
425
+ /** Must be 'TimeSpentEvent' */
426
+ type: 'TimeSpentEvent'
427
+ /** Must be 'SpentTime' */
428
+ action: 'SpentTime'
429
+ /** Time spent metrics generated from this session */
430
+ generated: TimebackTimeSpentMetricsCollection
431
+ }
432
+
433
+ /**
434
+ * Union of all Timeback event types.
435
+ */
436
+ type TimebackEvent = ActivityCompletedEvent | TimeSpentEvent
437
+
438
+ /**
439
+ * Caliper Event Types
440
+ *
441
+ * Types for Caliper Analytics events and envelopes.
442
+ */
443
+
444
+
445
+
446
+ /**
447
+ * Supported Caliper profiles.
448
+ */
449
+ type CaliperProfile =
450
+ | 'AnnotationProfile'
451
+ | 'AssessmentProfile'
452
+ | 'ToolUseProfile'
453
+ | 'GeneralProfile'
454
+ | 'FeedbackProfile'
455
+ | 'MediaProfile'
456
+ | 'SurveyProfile'
457
+ | 'ResourceManagementProfile'
458
+ | 'ForumProfile'
459
+ | 'AssignableProfile'
460
+ | 'GradingProfile'
461
+ | 'ReadingProfile'
462
+ | 'SessionProfile'
463
+ | 'SearchProfile'
464
+ | 'ToolLaunchProfile'
465
+ | 'TimebackProfile'
466
+
467
+ /**
468
+ * Base Caliper entity - can be a URI string or an object with properties.
469
+ */
470
+ type CaliperEntity = string | { [key: string]: unknown }
471
+
472
+ /**
473
+ * Caliper actor entity (for sending events).
474
+ *
475
+ * Timeback API requires actors to have extensions.email.
476
+ */
477
+ interface CaliperActor {
478
+ /** Unique identifier (IRI format) */
479
+ id: string
480
+ /** Entity type (e.g., 'Person', 'TimebackUser') */
481
+ type: string
482
+ /** Extensions - email is required by Timeback API */
483
+ extensions: {
484
+ /** Actor's email address (required by Timeback) */
485
+ email: string
486
+ /** Additional extension properties */
487
+ [key: string]: unknown
488
+ }
489
+ }
490
+
491
+ /**
492
+ * Caliper Event.
493
+ *
494
+ * Represents a learning activity event conforming to IMS Caliper v1.2.
495
+ */
496
+ interface CaliperEvent {
497
+ /** JSON-LD context */
498
+ '@context'?: string
499
+ /** Unique identifier (URN UUID format) */
500
+ id: string
501
+ /** Event type */
502
+ type: string
503
+ /** The agent who initiated the event (string URL, CaliperActor, or TimebackUser) */
504
+ actor: string | CaliperActor | TimebackUser
505
+ /** The action or predicate */
506
+ action: string
507
+ /** The object of the interaction */
508
+ object: CaliperEntity
509
+ /** ISO 8601 datetime when event occurred */
510
+ eventTime: string
511
+ /** Profile governing interpretation */
512
+ profile: CaliperProfile
513
+ /** Application context */
514
+ edApp?: CaliperEntity
515
+ /** Entity generated as result */
516
+ generated?: CaliperEntity
517
+ /** Target segment within object */
518
+ target?: CaliperEntity
519
+ /** Referring context */
520
+ referrer?: CaliperEntity
521
+ /** Organization/group context */
522
+ group?: CaliperEntity
523
+ /** User's membership/role */
524
+ membership?: CaliperEntity
525
+ /** Current user session */
526
+ session?: CaliperEntity
527
+ /** LTI session context */
528
+ federatedSession?: CaliperEntity
529
+ /** Additional custom attributes */
530
+ extensions?: Record<string, unknown>
531
+ }
532
+
533
+ /**
534
+ * Caliper Envelope.
535
+ *
536
+ * Container for transmitting Caliper events to the API.
537
+ */
538
+ interface CaliperEnvelope {
539
+ /** Sensor identifier (IRI format) */
540
+ sensor: string
541
+ /** ISO 8601 datetime when data was sent */
542
+ sendTime: string
543
+ /** Caliper data version */
544
+ dataVersion: 'http://purl.imsglobal.org/ctx/caliper/v1p2'
545
+ /** Array of events or entities */
546
+ data: CaliperEvent[]
547
+ }
548
+
549
+ /**
550
+ * Result of sending events.
551
+ */
552
+ interface SendEventsResult {
553
+ /** Job ID for tracking async processing */
554
+ jobId: string
555
+ }
556
+
557
+ /**
558
+ * Individual event result from job completion.
559
+ */
560
+ interface EventResult {
561
+ /** Allocated internal ID */
562
+ allocatedId: string
563
+ /** External event ID */
564
+ externalId: string
565
+ }
566
+
567
+ /**
568
+ * Job status response.
569
+ */
570
+ interface JobStatus {
571
+ id: string
572
+ state: 'waiting' | 'active' | 'completed' | 'failed'
573
+ returnValue?: {
574
+ status: 'success' | 'error'
575
+ results: EventResult[]
576
+ }
577
+ processedOn?: string | null
578
+ }
579
+
580
+ /**
581
+ * Stored Caliper event (from list/get).
582
+ *
583
+ * This represents an event as returned by the API, which differs from the
584
+ * input CaliperEvent format. The API adds internal fields and transforms
585
+ * the original event ID to `externalId`.
586
+ *
587
+ * @remarks
588
+ * **API Docs Drift**: The official OpenAPI spec (caliper-api.yaml) does not
589
+ * accurately document this response structure. This type was derived from
590
+ * actual API responses. Key differences:
591
+ * - `id` is a number (internal DB ID), not a string
592
+ * - `externalId` contains the original URN UUID (use this for `get()` calls)
593
+ * - Response is wrapped in `{ events: StoredEvent[] }` for list, `{ event: StoredEvent }` for get
594
+ */
595
+ interface StoredEvent {
596
+ /** Internal numeric ID (allocated by the database) */
597
+ id: number
598
+ /** Original event ID (URN UUID format) - use this for get() calls */
599
+ externalId: string
600
+ /** Sensor that sent the event */
601
+ sensor: string
602
+ /** Event type (e.g., 'ActivityEvent', 'Event') */
603
+ type: string
604
+ /** Caliper profile (e.g., 'TimebackProfile') */
605
+ profile?: string
606
+ /** The action or predicate */
607
+ action: string
608
+ /** When the event occurred */
609
+ eventTime: string
610
+ /** When the event was sent */
611
+ sendTime: string
612
+ /** When the record was last updated */
613
+ updated_at: string | null
614
+ /** When the record was created */
615
+ created_at: string
616
+ /** When the record was deleted (soft delete) */
617
+ deleted_at: string | null
618
+ /** The agent who initiated the event */
619
+ actor: CaliperEntity
620
+ /** The object of the event */
621
+ object: CaliperEntity
622
+ /** Generated entity (e.g., result, score) */
623
+ generated?: CaliperEntity | null
624
+ /** Target entity */
625
+ target?: CaliperEntity | null
626
+ /** Referrer entity */
627
+ referrer?: CaliperEntity | null
628
+ /** EdApp entity */
629
+ edApp?: CaliperEntity | null
630
+ /** Group/organization entity */
631
+ group?: CaliperEntity | null
632
+ /** Membership entity */
633
+ membership?: CaliperEntity | null
634
+ /** Session entity */
635
+ session?: CaliperEntity | null
636
+ /** Federated session entity */
637
+ federatedSession?: CaliperEntity | null
638
+ /** Extension data */
639
+ extensions?: Record<string, unknown> | null
640
+ /** Client application ID */
641
+ clientAppId?: string | null
642
+ }
643
+
644
+ /**
645
+ * Result from listing events.
646
+ */
647
+ interface ListEventsResult {
648
+ events: StoredEvent[]
649
+ pagination: PaginationMeta
650
+ }
651
+
652
+ /**
653
+ * API Response Types
654
+ *
655
+ * Types for Caliper API responses.
656
+ *
657
+ * @remarks
658
+ * **IMPORTANT - API Docs Drift**: The official API documentation (caliper/response.yaml
659
+ * and caliper-api.yaml) does NOT accurately reflect actual API responses. The types
660
+ * in this file were derived from testing actual API responses. See individual type
661
+ * comments for specific discrepancies.
662
+ */
663
+
664
+
665
+
666
+ /**
667
+ * Generic API response wrapper.
668
+ */
669
+ interface ApiResponse<T> {
670
+ status: 'success' | 'error'
671
+ message?: string
672
+ data?: T
673
+ }
674
+
675
+ /**
676
+ * Pagination metadata returned by list endpoints.
677
+ */
678
+ interface PaginationMeta {
679
+ /** Total number of items across all pages */
680
+ total: number
681
+ /** Total number of pages */
682
+ totalPages: number
683
+ /** Current page number (1-indexed) */
684
+ currentPage: number
685
+ /** Number of items per page */
686
+ limit: number
687
+ }
688
+
689
+ /**
690
+ * Response from GET /caliper/events (list events).
691
+ *
692
+ * @remarks
693
+ * **API Docs Drift**: Official docs (caliper/response.yaml) incorrectly show
694
+ * `{ status, message, errors? }`. Actual response is `{ events, pagination }`.
695
+ */
696
+ interface ListEventsResponse {
697
+ /** Array of stored events */
698
+ events: StoredEvent[]
699
+ /** Pagination metadata */
700
+ pagination: PaginationMeta
701
+ }
702
+
703
+ /**
704
+ * Response from GET /caliper/events/:externalId (get single event).
705
+ *
706
+ * @remarks
707
+ * **API Docs Drift**: Official docs (caliper/response.yaml) incorrectly show
708
+ * `{ status, message, errors? }`. Actual response is `{ status, event }`.
709
+ */
710
+ interface GetEventResponse {
711
+ /** Status indicator */
712
+ status: 'success' | 'error'
713
+ /** The requested event */
714
+ event: StoredEvent
715
+ }
716
+
717
+ /**
718
+ * Response from POST /caliper/event (send events).
719
+ *
720
+ * @remarks
721
+ * **API Docs Drift**: Official docs (caliper/response.yaml) incorrectly show
722
+ * `{ status, message, errors? }`. Actual response is `{ jobId }`.
723
+ * Use the jobId with `jobs.getStatus()` to track processing.
724
+ */
725
+ interface SendEventsResponse {
726
+ /** Job ID for tracking async processing */
727
+ jobId: string
728
+ }
729
+
730
+ /**
731
+ * Job status response payload (GET /jobs/{jobId}/status).
732
+ *
733
+ * @remarks
734
+ * This endpoint is correctly documented in caliper/response.yaml.
735
+ */
736
+ interface JobStatusResponse {
737
+ job: JobStatus
738
+ }
739
+
740
+ /**
741
+ * Options for waitForCompletion polling.
742
+ */
743
+ interface WaitForCompletionOptions {
744
+ /** Maximum time to wait in milliseconds (default: 30000) */
745
+ timeoutMs?: number
746
+ /** Interval between status checks in milliseconds (default: 1000) */
747
+ pollIntervalMs?: number
748
+ }
749
+
750
+ /**
751
+ * Validation result from the validate endpoint.
752
+ */
753
+ interface ValidationResult {
754
+ /** Whether validation succeeded */
755
+ status: 'success' | 'error'
756
+ /** Human-readable message */
757
+ message?: string
758
+ /** Validation errors (if any) */
759
+ errors?: unknown
760
+ }
761
+
762
+ /**
763
+ * Caliper Constants
764
+ *
765
+ * Configuration constants for the Caliper Analytics client.
766
+ */
767
+
768
+ /**
769
+ * Caliper JSON-LD context version.
770
+ */
771
+ declare const CALIPER_DATA_VERSION = "http://purl.imsglobal.org/ctx/caliper/v1p2";
772
+
773
+ type input<T> = T extends {
774
+ _zod: {
775
+ input: any;
776
+ };
777
+ } ? T["_zod"]["input"] : unknown;
778
+
779
+ /**
780
+ * Caliper Schemas
781
+ *
782
+ * Zod schemas for the IMS Caliper Analytics standard with Timeback Profile.
783
+ */
784
+
785
+
786
+
787
+ // ═══════════════════════════════════════════════════════════════════════════════
788
+ // BUILDER INPUTS
789
+ // ═══════════════════════════════════════════════════════════════════════════════
790
+
791
+ declare const ActivityCompletedInput = z
792
+ .object({
793
+ actor: TimebackUser,
794
+ object: TimebackActivityContext,
795
+ metrics: z.array(TimebackActivityMetric).min(1, 'metrics must contain at least one metric'),
796
+ eventTime: IsoDateTimeString.optional(),
797
+ metricsId: z.string().optional(),
798
+ id: z.string().optional(),
799
+ /** Event-level extensions */
800
+ extensions: z.record(z.string(), z.unknown()).optional(),
801
+ /**
802
+ * Application context (IRI or entity).
803
+ *
804
+ * Maps to `edApp` in the Caliper event. Identifies the educational
805
+ * application where the event occurred.
806
+ */
807
+ edApp: z.union([z.string(), z.record(z.string(), z.unknown())]).optional(),
808
+ /**
809
+ * Session context (IRI or entity).
810
+ *
811
+ * Maps to `session` in the Caliper event. Used for event-to-session
812
+ * correlation (e.g., linking heartbeats with completions via runId).
813
+ */
814
+ session: z.union([z.string(), z.record(z.string(), z.unknown())]).optional(),
815
+ /**
816
+ * Attempt number (1-based).
817
+ *
818
+ * Maps to `generated.attempt` in the Caliper event.
819
+ */
820
+ attempt: z.number().int().min(1).optional(),
821
+ /**
822
+ * Extensions for the generated metrics collection.
823
+ *
824
+ * Maps to `generated.extensions` in the Caliper event.
825
+ * Use `generatedExtensions.pctCompleteApp` (0–100) for app-reported course progress.
826
+ */
827
+ generatedExtensions: z
828
+ .object({
829
+ /**
830
+ * App-reported course progress (per enrollment), as a percentage from 0–100.
831
+ *
832
+ * This is emitted to Caliper as `generated.extensions.pctCompleteApp`.
833
+ *
834
+ * @remarks
835
+ * This value is not clamped here (Caliper client keeps the raw shape).
836
+ */
837
+ pctCompleteApp: z.number().optional(),
838
+ })
839
+ .loose()
840
+ .optional(),
841
+ })
842
+ .strict()
843
+
844
+ // ═══════════════════════════════════════════════════════════════════════════════
845
+ // TYPE EXPORTS (REQUEST INPUTS)
846
+ // ═══════════════════════════════════════════════════════════════════════════════
847
+
848
+ type ActivityCompletedInput = input<typeof ActivityCompletedInput>
849
+
850
+ declare const TimeSpentInput = z
851
+ .object({
852
+ actor: TimebackUser,
853
+ object: TimebackActivityContext,
854
+ metrics: z.array(TimebackTimeMetric).min(1, 'metrics must contain at least one metric'),
855
+ eventTime: IsoDateTimeString.optional(),
856
+ metricsId: z.string().optional(),
857
+ id: z.string().optional(),
858
+ extensions: z.record(z.string(), z.unknown()).optional(),
859
+ edApp: z.union([z.string(), z.record(z.string(), z.unknown())]).optional(),
860
+ session: z.union([z.string(), z.record(z.string(), z.unknown())]).optional(),
861
+ })
862
+ .strict()
863
+ type TimeSpentInput = input<typeof TimeSpentInput>
864
+
865
+ declare const CaliperListEventsParams = z
866
+ .object({
867
+ limit: z.number().int().positive().optional(),
868
+ offset: z.number().int().min(0).optional(),
869
+ sensor: z.string().min(1).optional(),
870
+ startDate: IsoDateTimeString.optional(),
871
+ endDate: IsoDateTimeString.optional(),
872
+ actorId: z.string().min(1).optional(),
873
+ actorEmail: z.email().optional(),
874
+ })
875
+ .strict()
876
+ type CaliperListEventsParams = input<typeof CaliperListEventsParams>
877
+
878
+ export { ActivityCompletedInput, CALIPER_DATA_VERSION, CaliperListEventsParams as ListEventsParams, TimeSpentInput };
879
+ export type { ActivityCompletedEvent, ActivityMetricType, ApiResponse, CaliperActor, CaliperEntity, CaliperEnvelope, CaliperEvent, CaliperProfile, EventResult, GetEventResponse, JobStatus, JobStatusResponse, ListEventsResponse, ListEventsResult, PaginationMeta, SendEventsResponse, SendEventsResult, StoredEvent, TimeSpentEvent, TimeSpentMetric, TimeSpentMetricType, TimebackActivity, TimebackActivityContext, TimebackActivityMetric, TimebackActivityMetricsCollection, TimebackApp, TimebackCourse, TimebackEvent, TimebackEventBase, TimebackSubject, TimebackTimeSpentMetricsCollection, TimebackUser, TimebackUserRole, ValidationResult, WaitForCompletionOptions };