@openstax/ts-utils 1.44.0 → 1.44.2
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/dist/cjs/services/accountsGateway/index.d.ts +4 -0
- package/dist/cjs/services/accountsGateway/index.js +1 -1
- package/dist/cjs/services/lrsGateway/addStatementDefaultFields.js +2 -7
- package/dist/cjs/services/lrsGateway/attempt-utils.d.ts +8 -4
- package/dist/cjs/services/lrsGateway/attempt-utils.js +39 -9
- package/dist/cjs/services/lrsGateway/file-system.js +2 -7
- package/dist/cjs/services/lrsGateway/index.d.ts +2 -7
- package/dist/cjs/services/lrsGateway/index.js +4 -25
- package/dist/cjs/services/lrsGateway/xapiUtils.js +2 -3
- package/dist/cjs/tsconfig.without-specs.cjs.tsbuildinfo +1 -1
- package/dist/esm/services/accountsGateway/index.d.ts +4 -0
- package/dist/esm/services/accountsGateway/index.js +1 -1
- package/dist/esm/services/lrsGateway/addStatementDefaultFields.js +2 -7
- package/dist/esm/services/lrsGateway/attempt-utils.d.ts +8 -4
- package/dist/esm/services/lrsGateway/attempt-utils.js +35 -8
- package/dist/esm/services/lrsGateway/file-system.js +2 -7
- package/dist/esm/services/lrsGateway/index.d.ts +2 -7
- package/dist/esm/services/lrsGateway/index.js +2 -23
- package/dist/esm/services/lrsGateway/xapiUtils.js +3 -4
- package/dist/esm/tsconfig.without-specs.esm.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/script/bin/.init-params-script.bash.swp +0 -0
|
@@ -66,6 +66,8 @@ export type SearchUsersResponse = {
|
|
|
66
66
|
export type UpdateUserPayload = Partial<ApiUser>;
|
|
67
67
|
export type MappedUserInfo<T> = {
|
|
68
68
|
data: T;
|
|
69
|
+
firstName: string;
|
|
70
|
+
lastName: string;
|
|
69
71
|
fullName: string;
|
|
70
72
|
platformUserId?: string;
|
|
71
73
|
uuid: string;
|
|
@@ -81,6 +83,8 @@ export declare const accountsGateway: <C extends string = "accounts">(initialize
|
|
|
81
83
|
[uuid: string]: T;
|
|
82
84
|
}, platformId?: string) => Promise<{
|
|
83
85
|
data: T;
|
|
86
|
+
firstName: string;
|
|
87
|
+
lastName: string;
|
|
84
88
|
fullName: string;
|
|
85
89
|
platformUserId: string | undefined;
|
|
86
90
|
uuid: string;
|
|
@@ -92,7 +92,7 @@ export const accountsGateway = (initializer) => (configProvider) => {
|
|
|
92
92
|
accountsUuid: user.uuid,
|
|
93
93
|
});
|
|
94
94
|
}
|
|
95
|
-
return { data, fullName: user.full_name, platformUserId, uuid: user.uuid };
|
|
95
|
+
return { data, firstName: user.first_name, lastName: user.last_name, fullName: user.full_name, platformUserId, uuid: user.uuid };
|
|
96
96
|
});
|
|
97
97
|
return results.filter(isDefined);
|
|
98
98
|
};
|
|
@@ -1,14 +1,9 @@
|
|
|
1
1
|
import formatISO from 'date-fns/formatISO';
|
|
2
2
|
import { v4 as uuid } from 'uuid';
|
|
3
|
+
import { formatAgent } from './attempt-utils';
|
|
3
4
|
export const addStatementDefaultFields = (statement, user) => ({
|
|
4
5
|
id: uuid(),
|
|
5
|
-
actor:
|
|
6
|
-
account: {
|
|
7
|
-
homePage: 'https://openstax.org',
|
|
8
|
-
name: user.uuid,
|
|
9
|
-
},
|
|
10
|
-
objectType: 'Agent',
|
|
11
|
-
},
|
|
6
|
+
actor: formatAgent(user.uuid),
|
|
12
7
|
timestamp: formatISO(new Date()),
|
|
13
8
|
...statement,
|
|
14
9
|
});
|
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
import { LrsGateway, UXapiStatement } from '.';
|
|
1
|
+
import { LrsGateway, UXapiStatement, XapiAgent } from '.';
|
|
2
|
+
export declare const formatAgent: (agent: string | XapiAgent) => XapiAgent;
|
|
2
3
|
export declare const EXT_PENDING_SCORING = "https://openstax.org/xapi/extensions/pending-scoring";
|
|
3
4
|
export type AttemptEntry = {
|
|
4
5
|
attempt: UXapiStatement;
|
|
5
6
|
completed?: UXapiStatement;
|
|
6
7
|
scored?: UXapiStatement;
|
|
8
|
+
needsScoring: boolean;
|
|
7
9
|
};
|
|
8
10
|
export type ActivityState = {
|
|
9
11
|
attempts: number;
|
|
@@ -53,7 +55,7 @@ export declare const createStatement: (verb: UXapiStatement["verb"], activity: {
|
|
|
53
55
|
extensions?: {
|
|
54
56
|
[key: string]: string;
|
|
55
57
|
};
|
|
56
|
-
}, attempt: string, parentActivityIRI?: string) => Pick<UXapiStatement, "object" | "verb" | "context">;
|
|
58
|
+
}, attempt: string, parentActivityIRI?: string, instructor?: string) => Pick<UXapiStatement, "object" | "verb" | "context">;
|
|
57
59
|
export declare const createAttemptStatement: (activity: {
|
|
58
60
|
iri: string;
|
|
59
61
|
type: string;
|
|
@@ -82,5 +84,7 @@ export declare const createCompletedStatement: (attemptStatement: UXapiStatement
|
|
|
82
84
|
export declare const putCompletedStatement: (gateway: LrsGateway, attemptStatement: UXapiStatement, result: UXapiStatement["result"], user?: string) => Promise<import(".").EagerXapiStatement>;
|
|
83
85
|
export declare const createCompletedPendingScoringStatement: (attemptStatement: UXapiStatement) => Pick<UXapiStatement, "object" | "verb" | "context" | "result">;
|
|
84
86
|
export declare const putCompletedPendingScoringStatement: (gateway: LrsGateway, attemptStatement: UXapiStatement, user?: string) => Promise<import(".").EagerXapiStatement>;
|
|
85
|
-
export declare const createScoredStatement: (attemptStatement: UXapiStatement, result: UXapiStatement["result"]) => Pick<UXapiStatement, "object" | "verb" | "context" | "result">;
|
|
86
|
-
export declare const putScoredStatement: (gateway: LrsGateway, attemptStatement: UXapiStatement, result: UXapiStatement["result"], user?: string) => Promise<import(".").EagerXapiStatement>;
|
|
87
|
+
export declare const createScoredStatement: (attemptStatement: UXapiStatement, result: UXapiStatement["result"], instructor?: string) => Pick<UXapiStatement, "object" | "verb" | "context" | "result">;
|
|
88
|
+
export declare const putScoredStatement: (gateway: LrsGateway, attemptStatement: UXapiStatement, result: UXapiStatement["result"], user?: string, instructor?: string) => Promise<import(".").EagerXapiStatement>;
|
|
89
|
+
export declare const createScoredPendingScoringStatement: (attemptStatement: UXapiStatement, result: UXapiStatement["result"]) => Pick<UXapiStatement, "object" | "verb" | "context" | "result">;
|
|
90
|
+
export declare const putScoredPendingScoringStatement: (gateway: LrsGateway, attemptStatement: UXapiStatement, result: UXapiStatement["result"], user?: string) => Promise<import(".").EagerXapiStatement>;
|
|
@@ -11,6 +11,18 @@ import intervalToDuration from 'date-fns/intervalToDuration';
|
|
|
11
11
|
import isAfter from 'date-fns/isAfter';
|
|
12
12
|
import isBefore from 'date-fns/isBefore';
|
|
13
13
|
import parseISO from 'date-fns/parseISO';
|
|
14
|
+
export const formatAgent = (agent) => {
|
|
15
|
+
if (typeof agent === 'string') {
|
|
16
|
+
return {
|
|
17
|
+
objectType: 'Agent',
|
|
18
|
+
account: {
|
|
19
|
+
homePage: 'https://openstax.org',
|
|
20
|
+
name: agent,
|
|
21
|
+
},
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
return agent;
|
|
25
|
+
};
|
|
14
26
|
var Verb;
|
|
15
27
|
(function (Verb) {
|
|
16
28
|
Verb["Attempted"] = "http://adlnet.gov/expapi/verbs/attempted";
|
|
@@ -53,9 +65,12 @@ export const resolveScoredForAttempt = (statements, attempt, activityIRI) => {
|
|
|
53
65
|
return mostRecentStatement(scoringStatements);
|
|
54
66
|
};
|
|
55
67
|
const resolveAttemptEntries = (statements, attempts, activityIRI) => attempts.reduce((acc, attempt) => {
|
|
68
|
+
var _a, _b, _c, _d;
|
|
56
69
|
const completed = resolveCompletedForAttempt(statements, attempt, activityIRI);
|
|
57
70
|
const scored = resolveScoredForAttempt(statements, attempt, activityIRI);
|
|
58
|
-
|
|
71
|
+
const needsScoring = (((_b = (_a = completed === null || completed === void 0 ? void 0 : completed.result) === null || _a === void 0 ? void 0 : _a.extensions) === null || _b === void 0 ? void 0 : _b[EXT_PENDING_SCORING]) === 'true' && scored === undefined) ||
|
|
72
|
+
((_d = (_c = scored === null || scored === void 0 ? void 0 : scored.result) === null || _c === void 0 ? void 0 : _c.extensions) === null || _d === void 0 ? void 0 : _d[EXT_PENDING_SCORING]) === 'true';
|
|
73
|
+
acc.push({ attempt, completed, scored, needsScoring });
|
|
59
74
|
return acc;
|
|
60
75
|
}, []);
|
|
61
76
|
export const getStatementTimeString = (statement) => 'stored' in statement && statement.stored ? statement.stored : statement.timestamp;
|
|
@@ -150,7 +165,7 @@ export const loadActivityAttemptInfo = async (gateway, activityIRI, options) =>
|
|
|
150
165
|
const loadOptions = parentActivityAttempt ? { ...partialOptions, registration: parentActivityAttempt } : partialOptions;
|
|
151
166
|
return resolveAttemptInfo(await gateway.getAllXapiStatements({ ...loadOptions, activity: activityIRI }), { ...options, activityIRI });
|
|
152
167
|
};
|
|
153
|
-
export const createStatement = (verb, activity, attempt, parentActivityIRI) => {
|
|
168
|
+
export const createStatement = (verb, activity, attempt, parentActivityIRI, instructor) => {
|
|
154
169
|
return {
|
|
155
170
|
context: {
|
|
156
171
|
...(parentActivityIRI ? {
|
|
@@ -164,6 +179,7 @@ export const createStatement = (verb, activity, attempt, parentActivityIRI) => {
|
|
|
164
179
|
},
|
|
165
180
|
} : {}),
|
|
166
181
|
registration: attempt,
|
|
182
|
+
...(instructor ? { instructor: formatAgent(instructor) } : {}),
|
|
167
183
|
},
|
|
168
184
|
object: {
|
|
169
185
|
definition: {
|
|
@@ -207,7 +223,7 @@ export const createAttemptStatement = (activity, parentActivity) => {
|
|
|
207
223
|
} : {}),
|
|
208
224
|
...(parentActivity.attempt ? {
|
|
209
225
|
registration: parentActivity.attempt,
|
|
210
|
-
} : {})
|
|
226
|
+
} : {}),
|
|
211
227
|
},
|
|
212
228
|
} : {}),
|
|
213
229
|
object: {
|
|
@@ -273,7 +289,7 @@ export const createCompletedStatement = (attemptStatement, result) => {
|
|
|
273
289
|
statement: {
|
|
274
290
|
objectType: 'StatementRef',
|
|
275
291
|
id: attemptStatement.id,
|
|
276
|
-
}
|
|
292
|
+
},
|
|
277
293
|
},
|
|
278
294
|
object: attemptStatement.object,
|
|
279
295
|
verb: {
|
|
@@ -301,7 +317,7 @@ export const putCompletedPendingScoringStatement = async (gateway, attemptStatem
|
|
|
301
317
|
], user))[0];
|
|
302
318
|
};
|
|
303
319
|
// scored statement for when the open written response has been graded.
|
|
304
|
-
export const createScoredStatement = (attemptStatement, result) => {
|
|
320
|
+
export const createScoredStatement = (attemptStatement, result, instructor) => {
|
|
305
321
|
var _a, _b;
|
|
306
322
|
return {
|
|
307
323
|
context: {
|
|
@@ -314,7 +330,8 @@ export const createScoredStatement = (attemptStatement, result) => {
|
|
|
314
330
|
statement: {
|
|
315
331
|
objectType: 'StatementRef',
|
|
316
332
|
id: attemptStatement.id,
|
|
317
|
-
}
|
|
333
|
+
},
|
|
334
|
+
...(instructor ? { instructor: formatAgent(instructor) } : {}),
|
|
318
335
|
},
|
|
319
336
|
object: attemptStatement.object,
|
|
320
337
|
verb: {
|
|
@@ -327,6 +344,16 @@ export const createScoredStatement = (attemptStatement, result) => {
|
|
|
327
344
|
}
|
|
328
345
|
};
|
|
329
346
|
};
|
|
330
|
-
export const putScoredStatement = async (gateway, attemptStatement, result, user) => {
|
|
331
|
-
return (await gateway.putXapiStatements([createScoredStatement(attemptStatement, result)], user))[0];
|
|
347
|
+
export const putScoredStatement = async (gateway, attemptStatement, result, user, instructor) => {
|
|
348
|
+
return (await gateway.putXapiStatements([createScoredStatement(attemptStatement, result, instructor)], user))[0];
|
|
349
|
+
};
|
|
350
|
+
// scored statement for retry assessments - records a score but marks the attempt as still pending scoring
|
|
351
|
+
export const createScoredPendingScoringStatement = (attemptStatement, result) => createScoredStatement(attemptStatement, {
|
|
352
|
+
...result,
|
|
353
|
+
extensions: { [EXT_PENDING_SCORING]: 'true' },
|
|
354
|
+
});
|
|
355
|
+
export const putScoredPendingScoringStatement = async (gateway, attemptStatement, result, user) => {
|
|
356
|
+
return (await gateway.putXapiStatements([
|
|
357
|
+
createScoredPendingScoringStatement(attemptStatement, result),
|
|
358
|
+
], user))[0];
|
|
332
359
|
};
|
|
@@ -7,6 +7,7 @@ import { resolveConfigValue } from '../../config';
|
|
|
7
7
|
import { UnauthorizedError } from '../../errors';
|
|
8
8
|
import { ifDefined } from '../../guards';
|
|
9
9
|
import { hashValue } from '../../misc/hashValue';
|
|
10
|
+
import { formatAgent } from './attempt-utils';
|
|
10
11
|
const pageSize = 5;
|
|
11
12
|
export const fileSystemLrsGateway = (initializer) => (configProvider) => ({ authProvider }) => {
|
|
12
13
|
const name = resolveConfigValue(configProvider[initializer.configSpace || 'fileSystem'].name);
|
|
@@ -69,13 +70,7 @@ export const fileSystemLrsGateway = (initializer) => (configProvider) => ({ auth
|
|
|
69
70
|
const statementsWithDefaults = statements.map(statement => ({
|
|
70
71
|
...statement,
|
|
71
72
|
id: uuid(),
|
|
72
|
-
actor:
|
|
73
|
-
account: {
|
|
74
|
-
homePage: 'https://openstax.org',
|
|
75
|
-
name: author.uuid,
|
|
76
|
-
},
|
|
77
|
-
objectType: 'Agent',
|
|
78
|
-
},
|
|
73
|
+
actor: formatAgent(author.uuid),
|
|
79
74
|
timestamp: formatISO(new Date()),
|
|
80
75
|
}));
|
|
81
76
|
await load;
|
|
@@ -23,13 +23,7 @@ export interface StateDocument {
|
|
|
23
23
|
[key: string]: any;
|
|
24
24
|
}
|
|
25
25
|
export interface XapiStatement {
|
|
26
|
-
actor:
|
|
27
|
-
account: {
|
|
28
|
-
homePage: 'https://openstax.org';
|
|
29
|
-
name: string;
|
|
30
|
-
};
|
|
31
|
-
objectType: 'Agent';
|
|
32
|
-
};
|
|
26
|
+
actor: XapiAgent;
|
|
33
27
|
id: string;
|
|
34
28
|
context?: {
|
|
35
29
|
contextActivities?: {
|
|
@@ -46,6 +40,7 @@ export interface XapiStatement {
|
|
|
46
40
|
};
|
|
47
41
|
registration?: string;
|
|
48
42
|
platform?: string;
|
|
43
|
+
instructor?: XapiAgent;
|
|
49
44
|
};
|
|
50
45
|
object: {
|
|
51
46
|
definition?: {
|
|
@@ -7,6 +7,7 @@ import { ifDefined } from '../../guards';
|
|
|
7
7
|
import { retryWithDelay } from '../../misc/helpers';
|
|
8
8
|
import { METHOD } from '../../routing';
|
|
9
9
|
import { addStatementDefaultFields } from './addStatementDefaultFields';
|
|
10
|
+
import { formatAgent } from './attempt-utils';
|
|
10
11
|
import { RequestBatcher } from './batching';
|
|
11
12
|
export const lrsGateway = (initializer) => (configProvider) => {
|
|
12
13
|
const config = configProvider[ifDefined(initializer.configSpace, 'lrs')];
|
|
@@ -33,22 +34,6 @@ export const lrsGateway = (initializer) => (configProvider) => {
|
|
|
33
34
|
const makeFetch = async (options) => {
|
|
34
35
|
return enableBatching ? batcher.queueRequest(options) : batcher.singleRequest(options);
|
|
35
36
|
};
|
|
36
|
-
/**
|
|
37
|
-
* Formats an agent parameter into a full XapiAgent object.
|
|
38
|
-
* Accepts either a UUID string or a full XapiAgent object.
|
|
39
|
-
*/
|
|
40
|
-
const formatAgent = (agent) => {
|
|
41
|
-
if (typeof agent === 'string') {
|
|
42
|
-
return {
|
|
43
|
-
objectType: 'Agent',
|
|
44
|
-
account: {
|
|
45
|
-
homePage: 'https://openstax.org',
|
|
46
|
-
name: agent,
|
|
47
|
-
},
|
|
48
|
-
};
|
|
49
|
-
}
|
|
50
|
-
return agent;
|
|
51
|
-
};
|
|
52
37
|
// Note: This method actually uses POST
|
|
53
38
|
const putXapiStatements = async (statements, user) => {
|
|
54
39
|
const userObj = user
|
|
@@ -110,13 +95,7 @@ ${await response.text()}`);
|
|
|
110
95
|
queryParams.until = options.until;
|
|
111
96
|
// Add agent unless anyUser is true
|
|
112
97
|
if (anyUser !== true) {
|
|
113
|
-
queryParams.agent = JSON.stringify(
|
|
114
|
-
account: {
|
|
115
|
-
homePage: 'https://openstax.org',
|
|
116
|
-
name: user || assertDefined(await authProvider.getUser(), new UnauthorizedError()).uuid,
|
|
117
|
-
},
|
|
118
|
-
objectType: 'Agent',
|
|
119
|
-
});
|
|
98
|
+
queryParams.agent = JSON.stringify(formatAgent(user || assertDefined(await authProvider.getUser(), new UnauthorizedError()).uuid));
|
|
120
99
|
}
|
|
121
100
|
return makeFetch({
|
|
122
101
|
path: '/data/xAPI/statements',
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import partition from 'lodash/fp/partition';
|
|
2
2
|
import { roundToPrecision } from '../..';
|
|
3
|
-
import {
|
|
3
|
+
import { getStatementTimeString, resolveAttemptInfo } from './attempt-utils';
|
|
4
4
|
export const getRegistrationAttemptInfo = async (lrs, registration, options) => {
|
|
5
5
|
const { currentPreference, ...xapiOptions } = options !== null && options !== void 0 ? options : {};
|
|
6
6
|
const allStatements = await lrs.getAllXapiStatements({ ...xapiOptions, registration });
|
|
@@ -24,7 +24,7 @@ export const getRegistrationAttemptInfo = async (lrs, registration, options) =>
|
|
|
24
24
|
// ltijs: https://cvmcosta.me/ltijs/#/grading
|
|
25
25
|
// Note: "min" is currently completely ignored
|
|
26
26
|
export const getScoreGrade = (entry, options) => {
|
|
27
|
-
var _a, _b
|
|
27
|
+
var _a, _b;
|
|
28
28
|
const { raw, scaled, max } = ((_b = (_a = entry.scored) === null || _a === void 0 ? void 0 : _a.result) === null || _b === void 0 ? void 0 : _b.score) || {};
|
|
29
29
|
const { maxScore, userId } = options;
|
|
30
30
|
const scoreMaximum = maxScore !== null && maxScore !== void 0 ? maxScore : 100;
|
|
@@ -37,8 +37,7 @@ export const getScoreGrade = (entry, options) => {
|
|
|
37
37
|
startedAt: entry.attempt ? getStatementTimeString(entry.attempt) : undefined,
|
|
38
38
|
submittedAt: entry.completed ? getStatementTimeString(entry.completed) : undefined,
|
|
39
39
|
};
|
|
40
|
-
const pendingManual = entry.
|
|
41
|
-
&& ((_e = (_d = (_c = entry.completed) === null || _c === void 0 ? void 0 : _c.result) === null || _d === void 0 ? void 0 : _d.extensions) === null || _e === void 0 ? void 0 : _e[EXT_PENDING_SCORING]) === 'true';
|
|
40
|
+
const pendingManual = entry.needsScoring;
|
|
42
41
|
return {
|
|
43
42
|
userId,
|
|
44
43
|
activityProgress: entry.completed ? 'Completed' : 'Started',
|