@lti-tool/core 0.9.0 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -0
- package/dist/ltiTool.d.ts +70 -3
- package/dist/ltiTool.d.ts.map +1 -1
- package/dist/ltiTool.js +116 -3
- package/dist/schemas/client.schema.d.ts +1 -1
- package/dist/schemas/client.schema.d.ts.map +1 -1
- package/dist/schemas/client.schema.js +1 -1
- package/dist/schemas/common.schema.d.ts +1 -1
- package/dist/schemas/common.schema.d.ts.map +1 -1
- package/dist/schemas/common.schema.js +1 -1
- package/dist/schemas/deployment.schema.d.ts +1 -1
- package/dist/schemas/deployment.schema.d.ts.map +1 -1
- package/dist/schemas/deployment.schema.js +1 -1
- package/dist/schemas/lti13/ags/lineItem.schema.d.ts +80 -0
- package/dist/schemas/lti13/ags/lineItem.schema.d.ts.map +1 -0
- package/dist/schemas/lti13/ags/lineItem.schema.js +49 -0
- package/dist/schemas/lti13/ags/result.schema.d.ts +65 -0
- package/dist/schemas/lti13/ags/result.schema.d.ts.map +1 -0
- package/dist/schemas/lti13/ags/result.schema.js +35 -0
- package/dist/schemas/lti13/ags/scoreSubmission.schema.d.ts +25 -4
- package/dist/schemas/lti13/ags/scoreSubmission.schema.d.ts.map +1 -1
- package/dist/schemas/lti13/ags/scoreSubmission.schema.js +2 -1
- package/dist/schemas/lti13/claims/baseJwtClaims.schema.d.ts +1 -1
- package/dist/schemas/lti13/claims/baseJwtClaims.schema.d.ts.map +1 -1
- package/dist/schemas/lti13/claims/baseJwtClaims.schema.js +1 -1
- package/dist/schemas/lti13/claims/contextClaims.schema.d.ts +1 -1
- package/dist/schemas/lti13/claims/contextClaims.schema.d.ts.map +1 -1
- package/dist/schemas/lti13/claims/contextClaims.schema.js +1 -1
- package/dist/schemas/lti13/claims/coreLtiClaims.schema.d.ts +1 -1
- package/dist/schemas/lti13/claims/coreLtiClaims.schema.d.ts.map +1 -1
- package/dist/schemas/lti13/claims/coreLtiClaims.schema.js +1 -1
- package/dist/schemas/lti13/claims/platformClaims.schema.d.ts +1 -1
- package/dist/schemas/lti13/claims/platformClaims.schema.d.ts.map +1 -1
- package/dist/schemas/lti13/claims/platformClaims.schema.js +1 -1
- package/dist/schemas/lti13/claims/privacyClaims.schema.d.ts +1 -1
- package/dist/schemas/lti13/claims/privacyClaims.schema.d.ts.map +1 -1
- package/dist/schemas/lti13/claims/privacyClaims.schema.js +1 -1
- package/dist/schemas/lti13/claims/serviceClaims.schema.d.ts +1 -1
- package/dist/schemas/lti13/claims/serviceClaims.schema.d.ts.map +1 -1
- package/dist/schemas/lti13/claims/serviceClaims.schema.js +1 -1
- package/dist/schemas/lti13/lti13JwtPayload.schema.d.ts +1 -1
- package/dist/schemas/lti13/lti13JwtPayload.schema.d.ts.map +1 -1
- package/dist/schemas/lti13/lti13JwtPayload.schema.js +1 -1
- package/dist/schemas/lti13/lti13Launch.schema.d.ts +1 -1
- package/dist/schemas/lti13/lti13Launch.schema.d.ts.map +1 -1
- package/dist/schemas/lti13/lti13Launch.schema.js +1 -1
- package/dist/schemas/lti13/lti13Login.schema.d.ts +1 -1
- package/dist/schemas/lti13/lti13Login.schema.d.ts.map +1 -1
- package/dist/schemas/lti13/lti13Login.schema.js +1 -1
- package/dist/services/ags.service.d.ts +86 -0
- package/dist/services/ags.service.d.ts.map +1 -1
- package/dist/services/ags.service.js +184 -8
- package/dist/services/token.service.d.ts.map +1 -1
- package/dist/services/token.service.js +2 -1
- package/package.json +1 -1
- package/src/ltiTool.ts +144 -5
- package/src/schemas/client.schema.ts +1 -1
- package/src/schemas/common.schema.ts +1 -1
- package/src/schemas/deployment.schema.ts +1 -1
- package/src/schemas/lti13/ags/lineItem.schema.ts +85 -0
- package/src/schemas/lti13/ags/result.schema.ts +55 -0
- package/src/schemas/lti13/ags/scoreSubmission.schema.ts +3 -1
- package/src/schemas/lti13/claims/baseJwtClaims.schema.ts +1 -1
- package/src/schemas/lti13/claims/contextClaims.schema.ts +1 -1
- package/src/schemas/lti13/claims/coreLtiClaims.schema.ts +1 -1
- package/src/schemas/lti13/claims/platformClaims.schema.ts +1 -1
- package/src/schemas/lti13/claims/privacyClaims.schema.ts +1 -1
- package/src/schemas/lti13/claims/serviceClaims.schema.ts +1 -1
- package/src/schemas/lti13/lti13JwtPayload.schema.ts +1 -1
- package/src/schemas/lti13/lti13Launch.schema.ts +1 -1
- package/src/schemas/lti13/lti13Login.schema.ts +1 -1
- package/src/services/ags.service.ts +253 -16
- package/src/services/token.service.ts +4 -1
package/src/ltiTool.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { createRemoteJWKSet, decodeJwt, exportJWK, jwtVerify, SignJWT } from 'jose';
|
|
2
2
|
import type { Logger } from 'pino';
|
|
3
3
|
|
|
4
4
|
import type { JWKS } from './interfaces/jwks.js';
|
|
@@ -14,7 +14,16 @@ import {
|
|
|
14
14
|
SessionIdSchema,
|
|
15
15
|
VerifyLaunchParamsSchema,
|
|
16
16
|
} from './schemas/index.js';
|
|
17
|
-
import
|
|
17
|
+
import {
|
|
18
|
+
type CreateLineItem,
|
|
19
|
+
type LineItem,
|
|
20
|
+
type LineItems,
|
|
21
|
+
LineItemSchema,
|
|
22
|
+
LineItemsSchema,
|
|
23
|
+
type UpdateLineItem,
|
|
24
|
+
} from './schemas/lti13/ags/lineItem.schema.js';
|
|
25
|
+
import { type Results, ResultsSchema } from './schemas/lti13/ags/result.schema.js';
|
|
26
|
+
import { type ScoreSubmission } from './schemas/lti13/ags/scoreSubmission.schema.js';
|
|
18
27
|
import { AGSService } from './services/ags.service.js';
|
|
19
28
|
import { createSession } from './services/session.service.js';
|
|
20
29
|
import { TokenService } from './services/token.service.js';
|
|
@@ -259,17 +268,147 @@ export class LTITool {
|
|
|
259
268
|
*
|
|
260
269
|
* @param session - Active LTI session containing AGS service endpoints
|
|
261
270
|
* @param score - Score submission data including grade value and user ID
|
|
262
|
-
* @returns Result of the score submission
|
|
263
271
|
* @throws {Error} When AGS is not available or submission fails
|
|
264
272
|
*/
|
|
265
|
-
async submitScore(session: LTISession, score: ScoreSubmission): Promise<
|
|
273
|
+
async submitScore(session: LTISession, score: ScoreSubmission): Promise<void> {
|
|
266
274
|
if (!session) {
|
|
267
275
|
throw new Error('session is required');
|
|
268
276
|
}
|
|
269
277
|
if (!score) {
|
|
270
278
|
throw new Error('score is required');
|
|
271
279
|
}
|
|
272
|
-
|
|
280
|
+
|
|
281
|
+
await this.agsService.submitScore(session, score);
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
* Retrieves all scores for a specific line item from the platform using Assignment and Grade Services (AGS).
|
|
286
|
+
*
|
|
287
|
+
* @param session - Active LTI session containing AGS service endpoints
|
|
288
|
+
* @returns Array of score submissions for the line item
|
|
289
|
+
* @throws {Error} When AGS is not available or request fails
|
|
290
|
+
*
|
|
291
|
+
* @example
|
|
292
|
+
* ```typescript
|
|
293
|
+
* const scores = await ltiTool.getScores(session);
|
|
294
|
+
* console.log('All scores:', scores.map(s => `${s.userId}: ${s.scoreGiven}`));
|
|
295
|
+
* ```
|
|
296
|
+
*/
|
|
297
|
+
async getScores(session: LTISession): Promise<Results> {
|
|
298
|
+
if (!session) {
|
|
299
|
+
throw new Error('session is required');
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
const response = await this.agsService.getScores(session);
|
|
303
|
+
const data = await response.json();
|
|
304
|
+
return ResultsSchema.parse(data);
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
/**
|
|
308
|
+
* Retrieves line items (gradebook columns) from the platform using Assignment and Grade Services (AGS).
|
|
309
|
+
*
|
|
310
|
+
* @param session - Active LTI session containing AGS service endpoints
|
|
311
|
+
* @returns Array of line items from the platform
|
|
312
|
+
* @throws {Error} When AGS is not available or request fails
|
|
313
|
+
*/
|
|
314
|
+
async listLineItems(session: LTISession): Promise<LineItems> {
|
|
315
|
+
if (!session) {
|
|
316
|
+
throw new Error('session is required');
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
const response = await this.agsService.listLineItems(session);
|
|
320
|
+
const data = await response.json();
|
|
321
|
+
return LineItemsSchema.parse(data);
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
/**
|
|
325
|
+
* Retrieves a specific line item (gradebook column) from the platform using Assignment and Grade Services (AGS).
|
|
326
|
+
*
|
|
327
|
+
* @param session - Active LTI session containing AGS service endpoints
|
|
328
|
+
* @returns Line item data from the platform
|
|
329
|
+
* @throws {Error} When AGS is not available or request fails
|
|
330
|
+
*/
|
|
331
|
+
async getLineItem(session: LTISession): Promise<LineItem> {
|
|
332
|
+
if (!session) {
|
|
333
|
+
throw new Error('session is required');
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
const response = await this.agsService.getLineItem(session);
|
|
337
|
+
const data = await response.json();
|
|
338
|
+
return LineItemSchema.parse(data);
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
/**
|
|
342
|
+
* Creates a new line item (gradebook column) on the platform using Assignment and Grade Services (AGS).
|
|
343
|
+
*
|
|
344
|
+
* @param session - Active LTI session containing AGS service endpoints
|
|
345
|
+
* @param createLineItem - Line item data including label, scoreMaximum, and optional metadata
|
|
346
|
+
* @returns Created line item with platform-generated ID and validated data
|
|
347
|
+
* @throws {Error} When AGS is not available, input validation fails, or creation fails
|
|
348
|
+
*
|
|
349
|
+
* @example
|
|
350
|
+
* ```typescript
|
|
351
|
+
* const newLineItem = await ltiTool.createLineItem(session, {
|
|
352
|
+
* label: 'Quiz 1',
|
|
353
|
+
* scoreMaximum: 100,
|
|
354
|
+
* tag: 'quiz',
|
|
355
|
+
* resourceId: 'quiz-001'
|
|
356
|
+
* });
|
|
357
|
+
* console.log('Created line item:', newLineItem.id);
|
|
358
|
+
* ```
|
|
359
|
+
*/
|
|
360
|
+
async createLineItem(
|
|
361
|
+
session: LTISession,
|
|
362
|
+
createLineItem: CreateLineItem,
|
|
363
|
+
): Promise<LineItem> {
|
|
364
|
+
if (!session) {
|
|
365
|
+
throw new Error('session is required');
|
|
366
|
+
}
|
|
367
|
+
if (!createLineItem) {
|
|
368
|
+
throw new Error('createLineItem is required');
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
const response = await this.agsService.createLineItem(session, createLineItem);
|
|
372
|
+
const data = await response.json();
|
|
373
|
+
return LineItemSchema.parse(data);
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
/**
|
|
377
|
+
* Updates an existing line item (gradebook column) on the platform using Assignment and Grade Services (AGS).
|
|
378
|
+
*
|
|
379
|
+
* @param session - Active LTI session containing AGS service endpoints
|
|
380
|
+
* @param updateLineItem - Updated line item data including all required fields
|
|
381
|
+
* @returns Updated line item with validated data from the platform
|
|
382
|
+
* @throws {Error} When AGS is not available, input validation fails, or update fails
|
|
383
|
+
*/
|
|
384
|
+
async updateLineItem(
|
|
385
|
+
session: LTISession,
|
|
386
|
+
updateLineItem: UpdateLineItem,
|
|
387
|
+
): Promise<LineItem> {
|
|
388
|
+
if (!session) {
|
|
389
|
+
throw new Error('session is required');
|
|
390
|
+
}
|
|
391
|
+
if (!updateLineItem) {
|
|
392
|
+
throw new Error('lineItem is required');
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
const response = await this.agsService.updateLineItem(session, updateLineItem);
|
|
396
|
+
const data = await response.json();
|
|
397
|
+
return LineItemSchema.parse(data);
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
/**
|
|
401
|
+
* Deletes a line item (gradebook column) from the platform using Assignment and Grade Services (AGS).
|
|
402
|
+
*
|
|
403
|
+
* @param session - Active LTI session containing AGS service endpoints
|
|
404
|
+
* @throws {Error} When AGS is not available or deletion fails
|
|
405
|
+
*/
|
|
406
|
+
async deleteLineItem(session: LTISession): Promise<void> {
|
|
407
|
+
if (!session) {
|
|
408
|
+
throw new Error('session is required');
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
await this.agsService.deleteLineItem(session);
|
|
273
412
|
}
|
|
274
413
|
|
|
275
414
|
// Client management
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import * as z from 'zod';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Schema for LTI Assignment and Grade Services (AGS) Line Item.
|
|
5
|
+
* Represents a gradebook column/assignment according to LTI AGS v2.0 specification.
|
|
6
|
+
*
|
|
7
|
+
* @see https://www.imsglobal.org/spec/lti-ags/v2p0/#line-item-service
|
|
8
|
+
*/
|
|
9
|
+
export const LineItemSchema = z.object({
|
|
10
|
+
/** Unique identifier for the line item */
|
|
11
|
+
id: z.url(),
|
|
12
|
+
|
|
13
|
+
/** Maximum score possible for this line item */
|
|
14
|
+
scoreMaximum: z.number().min(0),
|
|
15
|
+
|
|
16
|
+
/** Human-readable label for the line item */
|
|
17
|
+
label: z.string(),
|
|
18
|
+
|
|
19
|
+
/** Optional resource identifier that this line item is associated with */
|
|
20
|
+
resourceId: z.string().optional(),
|
|
21
|
+
|
|
22
|
+
/** Optional resource link identifier */
|
|
23
|
+
resourceLinkId: z.string().optional(),
|
|
24
|
+
|
|
25
|
+
/** Optional tag to identify the line item */
|
|
26
|
+
tag: z.string().optional(),
|
|
27
|
+
|
|
28
|
+
/** Optional start date/time for the assignment */
|
|
29
|
+
startDateTime: z.iso.datetime().optional(),
|
|
30
|
+
|
|
31
|
+
/** Optional end date/time for the assignment */
|
|
32
|
+
endDateTime: z.iso.datetime().optional(),
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Schema for creating a new LTI Assignment and Grade Services (AGS) Line Item.
|
|
37
|
+
* Omits the 'id' field since it's generated by the platform upon creation.
|
|
38
|
+
*
|
|
39
|
+
* @see https://www.imsglobal.org/spec/lti-ags/v2p0/#line-item-service
|
|
40
|
+
*/
|
|
41
|
+
export const CreateLineItemSchema = LineItemSchema.omit({
|
|
42
|
+
id: true,
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Schema for updating an existing LTI Assignment and Grade Services (AGS) Line Item.
|
|
47
|
+
* Omits 'id' and 'resourceLinkId' fields as they are immutable per LTI AGS specification.
|
|
48
|
+
* Tools MUST NOT change these values during updates.
|
|
49
|
+
*
|
|
50
|
+
* @see https://www.imsglobal.org/spec/lti-ags/v2p0/#line-item-service
|
|
51
|
+
*/
|
|
52
|
+
export const UpdateLineItemSchema = LineItemSchema.omit({
|
|
53
|
+
id: true,
|
|
54
|
+
resourceLinkId: true,
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Schema for an array of line items returned from the line items service.
|
|
59
|
+
*/
|
|
60
|
+
export const LineItemsSchema = z.array(LineItemSchema);
|
|
61
|
+
|
|
62
|
+
// types
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Type representing a validated line item for LTI AGS.
|
|
66
|
+
* Represents a gradebook column or assignment.
|
|
67
|
+
*/
|
|
68
|
+
export type LineItem = z.infer<typeof LineItemSchema>;
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Type representing an array of line items.
|
|
72
|
+
*/
|
|
73
|
+
export type LineItems = z.infer<typeof LineItemsSchema>;
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Type representing data required to create a new line item for LTI AGS.
|
|
77
|
+
* Contains all LineItem fields except the platform-generated 'id'.
|
|
78
|
+
*/
|
|
79
|
+
export type CreateLineItem = z.infer<typeof CreateLineItemSchema>;
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Type representing data for updating an existing line item for LTI AGS.
|
|
83
|
+
* Contains all LineItem fields except immutable 'id' and 'resourceLinkId'.
|
|
84
|
+
*/
|
|
85
|
+
export type UpdateLineItem = z.infer<typeof UpdateLineItemSchema>;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import * as z from 'zod';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Schema for LTI Assignment and Grade Services (AGS) Result.
|
|
5
|
+
* Results contain richer metadata than scores, including user info and timestamps.
|
|
6
|
+
*
|
|
7
|
+
* @see https://www.imsglobal.org/spec/lti-ags/v2p0/#result-service
|
|
8
|
+
*/
|
|
9
|
+
export const ResultSchema = z.object({
|
|
10
|
+
/** Unique identifier for the result */
|
|
11
|
+
id: z.string(),
|
|
12
|
+
|
|
13
|
+
/** Score of the result, represented as a URL */
|
|
14
|
+
scoreOf: z.url(),
|
|
15
|
+
|
|
16
|
+
/** URL identifying the Line Item to which this result belongs. */
|
|
17
|
+
userId: z.string(),
|
|
18
|
+
|
|
19
|
+
/** The score given to the user */
|
|
20
|
+
resultScore: z.number().optional(),
|
|
21
|
+
|
|
22
|
+
/** Maximum possible score */
|
|
23
|
+
resultMaximum: z.number().optional(),
|
|
24
|
+
|
|
25
|
+
/** Comment associated with the result */
|
|
26
|
+
comment: z.string().optional(),
|
|
27
|
+
|
|
28
|
+
/** Timestamp when the result was recorded */
|
|
29
|
+
timestamp: z.iso.datetime({ offset: true }).optional(),
|
|
30
|
+
|
|
31
|
+
/** Activity progress status */
|
|
32
|
+
activityProgress: z
|
|
33
|
+
.enum(['Initialized', 'Started', 'InProgress', 'Submitted', 'Completed'])
|
|
34
|
+
.optional(),
|
|
35
|
+
|
|
36
|
+
/** Grading progress status */
|
|
37
|
+
gradingProgress: z
|
|
38
|
+
.enum(['FullyGraded', 'Pending', 'PendingManual', 'Failed', 'NotReady'])
|
|
39
|
+
.optional(),
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Schema for an array of results returned from the results service.
|
|
44
|
+
*/
|
|
45
|
+
export const ResultsSchema = z.array(ResultSchema);
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Type representing a validated result for LTI AGS.
|
|
49
|
+
*/
|
|
50
|
+
export type Result = z.infer<typeof ResultSchema>;
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Type representing an array of results.
|
|
54
|
+
*/
|
|
55
|
+
export type Results = z.infer<typeof ResultsSchema>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as z from 'zod';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Schema for submitting grades via LTI Assignment and Grade Services (AGS).
|
|
@@ -47,6 +47,8 @@ export const ScoreSubmissionSchema = z.object({
|
|
|
47
47
|
.default('FullyGraded'),
|
|
48
48
|
});
|
|
49
49
|
|
|
50
|
+
export const ScoreSubmissionsSchema = z.array(ScoreSubmissionSchema);
|
|
51
|
+
|
|
50
52
|
/**
|
|
51
53
|
* Type representing a validated score submission for LTI AGS.
|
|
52
54
|
* Contains grade data and metadata to be sent to the platform.
|