@openstax/ts-utils 1.20.1 → 1.20.3
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/misc/helpers.d.ts +4 -0
- package/dist/cjs/misc/helpers.js +13 -1
- package/dist/cjs/services/lrsGateway/addStatementDefaultFields.d.ts +4 -4
- package/dist/cjs/services/lrsGateway/addStatementDefaultFields.js +2 -2
- package/dist/cjs/services/lrsGateway/attempt-utils.d.ts +22 -22
- package/dist/cjs/services/lrsGateway/attempt-utils.js +2 -2
- package/dist/cjs/services/lrsGateway/index.d.ts +2 -1
- package/dist/cjs/tsconfig.without-specs.cjs.tsbuildinfo +1 -1
- package/dist/esm/misc/helpers.d.ts +4 -0
- package/dist/esm/misc/helpers.js +13 -1
- package/dist/esm/services/lrsGateway/addStatementDefaultFields.d.ts +4 -4
- package/dist/esm/services/lrsGateway/addStatementDefaultFields.js +2 -2
- package/dist/esm/services/lrsGateway/attempt-utils.d.ts +22 -22
- package/dist/esm/services/lrsGateway/attempt-utils.js +2 -2
- package/dist/esm/services/lrsGateway/index.d.ts +2 -1
- package/dist/esm/services/lrsGateway/index.js +1 -1
- package/dist/esm/tsconfig.without-specs.esm.tsbuildinfo +1 -1
- package/package.json +1 -1
|
@@ -80,6 +80,8 @@ export declare const mapFind: <I, R>(array: I[], mapper: (item: I) => R, predica
|
|
|
80
80
|
/**
|
|
81
81
|
* returns a function that will only ever call the given function once, returning the first result for every subsequent call
|
|
82
82
|
*
|
|
83
|
+
* does not cache rejected promises, to avoid cache poisoning on failed async requests
|
|
84
|
+
*
|
|
83
85
|
* eg:
|
|
84
86
|
* const heavyFunction = () => 'hello';
|
|
85
87
|
* const butOnlyOnce = once(() => 'hello');
|
|
@@ -90,6 +92,8 @@ export declare const mapFind: <I, R>(array: I[], mapper: (item: I) => R, predica
|
|
|
90
92
|
export declare const once: <F extends (...args: any[]) => any>(fn: F) => F;
|
|
91
93
|
/**
|
|
92
94
|
* memoizes a function with any number of arguments
|
|
95
|
+
*
|
|
96
|
+
* does not cache rejected promises, to avoid cache poisoning on failed async requests
|
|
93
97
|
*/
|
|
94
98
|
export declare const memoize: <F extends (...args: any[]) => any>(fn: F) => F;
|
|
95
99
|
/**
|
package/dist/esm/misc/helpers.js
CHANGED
|
@@ -96,6 +96,8 @@ export const mapFind = (array, mapper, predicate = (r) => !!r) => {
|
|
|
96
96
|
/**
|
|
97
97
|
* returns a function that will only ever call the given function once, returning the first result for every subsequent call
|
|
98
98
|
*
|
|
99
|
+
* does not cache rejected promises, to avoid cache poisoning on failed async requests
|
|
100
|
+
*
|
|
99
101
|
* eg:
|
|
100
102
|
* const heavyFunction = () => 'hello';
|
|
101
103
|
* const butOnlyOnce = once(() => 'hello');
|
|
@@ -121,6 +123,8 @@ export const once = (fn) => {
|
|
|
121
123
|
};
|
|
122
124
|
/**
|
|
123
125
|
* memoizes a function with any number of arguments
|
|
126
|
+
*
|
|
127
|
+
* does not cache rejected promises, to avoid cache poisoning on failed async requests
|
|
124
128
|
*/
|
|
125
129
|
export const memoize = (fn) => {
|
|
126
130
|
const cache = {};
|
|
@@ -143,7 +147,15 @@ export const memoize = (fn) => {
|
|
|
143
147
|
};
|
|
144
148
|
return ((...args) => {
|
|
145
149
|
const thisCache = resolveCache(cache, args);
|
|
146
|
-
|
|
150
|
+
if ('result' in thisCache) {
|
|
151
|
+
return thisCache.result;
|
|
152
|
+
}
|
|
153
|
+
thisCache.result = fn(...args);
|
|
154
|
+
if (typeof thisCache.result === 'object' && thisCache.result instanceof Promise) {
|
|
155
|
+
// Clear the result when possible but do not return a Promise that resolves to the initialValue
|
|
156
|
+
thisCache.result.catch(() => delete thisCache.result);
|
|
157
|
+
}
|
|
158
|
+
return thisCache.result;
|
|
147
159
|
});
|
|
148
160
|
};
|
|
149
161
|
/**
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
export declare const addStatementDefaultFields: (statement: Pick<XapiStatement, 'object' | 'verb' | 'context' | 'result'> & {
|
|
1
|
+
import { User } from '../authProvider';
|
|
2
|
+
import { EagerXapiStatement, UXapiStatement, XapiStatement } from '.';
|
|
3
|
+
export declare const addStatementDefaultFields: (statement: (Pick<XapiStatement, 'object' | 'verb' | 'context' | 'result'> & {
|
|
4
4
|
id?: string;
|
|
5
|
-
}, user: User) => EagerXapiStatement;
|
|
5
|
+
}) | UXapiStatement, user: User) => EagerXapiStatement;
|
|
@@ -2,7 +2,6 @@ import formatISO from 'date-fns/formatISO';
|
|
|
2
2
|
import { v4 as uuid } from 'uuid';
|
|
3
3
|
export const addStatementDefaultFields = (statement, user) => ({
|
|
4
4
|
id: uuid(),
|
|
5
|
-
...statement,
|
|
6
5
|
actor: {
|
|
7
6
|
account: {
|
|
8
7
|
homePage: 'https://openstax.org',
|
|
@@ -10,5 +9,6 @@ export const addStatementDefaultFields = (statement, user) => ({
|
|
|
10
9
|
},
|
|
11
10
|
objectType: 'Agent',
|
|
12
11
|
},
|
|
13
|
-
timestamp: formatISO(new Date())
|
|
12
|
+
timestamp: formatISO(new Date()),
|
|
13
|
+
...statement,
|
|
14
14
|
});
|
|
@@ -1,23 +1,23 @@
|
|
|
1
|
-
import { LrsGateway,
|
|
1
|
+
import { LrsGateway, UXapiStatement } from '.';
|
|
2
2
|
export declare type ActivityState = {
|
|
3
3
|
attempts: number;
|
|
4
4
|
completedAttempts: number;
|
|
5
|
-
currentAttempt?:
|
|
6
|
-
currentAttemptCompleted?:
|
|
7
|
-
currentAttemptStatements:
|
|
8
|
-
mostRecentAttemptWithCompleted?:
|
|
9
|
-
mostRecentAttemptWithCompletedCompleted?:
|
|
5
|
+
currentAttempt?: UXapiStatement;
|
|
6
|
+
currentAttemptCompleted?: UXapiStatement;
|
|
7
|
+
currentAttemptStatements: UXapiStatement[];
|
|
8
|
+
mostRecentAttemptWithCompleted?: UXapiStatement;
|
|
9
|
+
mostRecentAttemptWithCompletedCompleted?: UXapiStatement;
|
|
10
10
|
};
|
|
11
|
-
export declare const matchAttempt: (statement:
|
|
12
|
-
export declare const matchAttemptCompleted: (attempt:
|
|
13
|
-
export declare const resolveAttempts: (statements:
|
|
11
|
+
export declare const matchAttempt: (statement: UXapiStatement) => boolean;
|
|
12
|
+
export declare const matchAttemptCompleted: (attempt: UXapiStatement) => (statement: UXapiStatement) => boolean;
|
|
13
|
+
export declare const resolveAttempts: (statements: UXapiStatement[], options?: {
|
|
14
14
|
activityIRI?: string | undefined;
|
|
15
15
|
parentActivityAttempt?: string | undefined;
|
|
16
|
-
} | undefined) =>
|
|
17
|
-
export declare const resolveCompletedForAttempt: (statements:
|
|
18
|
-
export declare const oldestStatement: (statements:
|
|
19
|
-
export declare const mostRecentStatement: (statements:
|
|
20
|
-
export declare const resolveAttemptInfo: (statements:
|
|
16
|
+
} | undefined) => UXapiStatement[];
|
|
17
|
+
export declare const resolveCompletedForAttempt: (statements: UXapiStatement[], attempt: UXapiStatement, activityIRI?: string | undefined) => UXapiStatement | undefined;
|
|
18
|
+
export declare const oldestStatement: (statements: UXapiStatement[]) => UXapiStatement | undefined;
|
|
19
|
+
export declare const mostRecentStatement: (statements: UXapiStatement[]) => UXapiStatement | undefined;
|
|
20
|
+
export declare const resolveAttemptInfo: (statements: UXapiStatement[], options?: {
|
|
21
21
|
activityIRI?: string | undefined;
|
|
22
22
|
currentAttempt?: string | undefined;
|
|
23
23
|
parentActivityAttempt?: string | undefined;
|
|
@@ -28,20 +28,20 @@ export declare const loadStatementsForActivityAndFirstChildren: (gateway: LrsGat
|
|
|
28
28
|
attempt?: string | undefined;
|
|
29
29
|
ensureSync?: boolean | undefined;
|
|
30
30
|
user?: string | undefined;
|
|
31
|
-
} | undefined) => Promise<XapiStatement[]>;
|
|
31
|
+
} | undefined) => Promise<import(".").XapiStatement[]>;
|
|
32
32
|
export declare const loadActivityAttemptInfo: (gateway: LrsGateway, activityIRI: string, options?: {
|
|
33
33
|
currentAttempt?: string | undefined;
|
|
34
34
|
parentActivityAttempt?: string | undefined;
|
|
35
35
|
ensureSync?: boolean | undefined;
|
|
36
36
|
} | undefined) => Promise<ActivityState>;
|
|
37
|
-
export declare const createStatement: (verb:
|
|
37
|
+
export declare const createStatement: (verb: UXapiStatement['verb'], activity: {
|
|
38
38
|
iri: string;
|
|
39
39
|
type: string;
|
|
40
40
|
name: string;
|
|
41
41
|
extensions?: {
|
|
42
42
|
[key: string]: string;
|
|
43
43
|
} | undefined;
|
|
44
|
-
}, attempt: string, parentActivityIRI?: string | undefined) => Pick<
|
|
44
|
+
}, attempt: string, parentActivityIRI?: string | undefined) => Pick<UXapiStatement, 'object' | 'verb' | 'context'>;
|
|
45
45
|
export declare const createAttemptStatement: (activity: {
|
|
46
46
|
iri: string;
|
|
47
47
|
type: string;
|
|
@@ -52,7 +52,7 @@ export declare const createAttemptStatement: (activity: {
|
|
|
52
52
|
}, parentActivity?: {
|
|
53
53
|
iri?: string | undefined;
|
|
54
54
|
attempt?: string | undefined;
|
|
55
|
-
} | undefined) => Pick<
|
|
55
|
+
} | undefined) => Pick<UXapiStatement, 'object' | 'verb' | 'context'>;
|
|
56
56
|
export declare const putAttemptStatement: (gateway: LrsGateway, activity: {
|
|
57
57
|
iri: string;
|
|
58
58
|
type: string;
|
|
@@ -64,7 +64,7 @@ export declare const putAttemptStatement: (gateway: LrsGateway, activity: {
|
|
|
64
64
|
iri?: string | undefined;
|
|
65
65
|
attempt?: string | undefined;
|
|
66
66
|
} | undefined) => Promise<import(".").EagerXapiStatement>;
|
|
67
|
-
export declare const createAttemptActivityStatement: (attemptStatement:
|
|
68
|
-
export declare const putAttemptActivityStatement: (gateway: LrsGateway, attemptStatement:
|
|
69
|
-
export declare const createCompletedStatement: (attemptStatement:
|
|
70
|
-
export declare const putCompletedStatement: (gateway: LrsGateway, attemptStatement:
|
|
67
|
+
export declare const createAttemptActivityStatement: (attemptStatement: UXapiStatement, verb: UXapiStatement['verb'], result?: UXapiStatement['result']) => Pick<UXapiStatement, 'object' | 'verb' | 'context' | 'result'>;
|
|
68
|
+
export declare const putAttemptActivityStatement: (gateway: LrsGateway, attemptStatement: UXapiStatement, verb: UXapiStatement['verb'], result?: UXapiStatement['result']) => Promise<import(".").EagerXapiStatement>;
|
|
69
|
+
export declare const createCompletedStatement: (attemptStatement: UXapiStatement, result?: UXapiStatement['result']) => Pick<UXapiStatement, 'object' | 'verb' | 'context' | 'result'>;
|
|
70
|
+
export declare const putCompletedStatement: (gateway: LrsGateway, attemptStatement: UXapiStatement, result: UXapiStatement['result']) => Promise<import(".").EagerXapiStatement>;
|
|
@@ -32,8 +32,8 @@ export const resolveAttempts = (statements, options) => statements.filter(statem
|
|
|
32
32
|
});
|
|
33
33
|
export const resolveCompletedForAttempt = (statements, attempt, activityIRI) => statements.find(statement => matchAttemptCompleted(attempt)(statement)
|
|
34
34
|
&& (!activityIRI || statement.object.id === activityIRI));
|
|
35
|
-
export const oldestStatement = (statements) => statements.reduce((result, statement) => result && isBefore(parseISO(result.stored
|
|
36
|
-
export const mostRecentStatement = (statements) => statements.reduce((result, statement) => result && isAfter(parseISO(result.stored
|
|
35
|
+
export const oldestStatement = (statements) => statements.reduce((result, statement) => result && isBefore(parseISO('stored' in result && result.stored ? result.stored : result.timestamp), parseISO(statement.timestamp)) ? result : statement, statements[0]);
|
|
36
|
+
export const mostRecentStatement = (statements) => statements.reduce((result, statement) => result && isAfter(parseISO('stored' in result && result.stored ? result.stored : result.timestamp), parseISO(statement.timestamp)) ? result : statement, statements[0]);
|
|
37
37
|
export const resolveAttemptInfo = (statements, options) => {
|
|
38
38
|
// TODO optimize. i'm 100% that this could all be done in one iteration but i'm not messing around with that for now.
|
|
39
39
|
const attempts = resolveAttempts(statements, options);
|
|
@@ -74,6 +74,7 @@ export interface XapiStatement {
|
|
|
74
74
|
}
|
|
75
75
|
export declare type SavedXapiStatement = WithRequired<XapiStatement, 'stored'>;
|
|
76
76
|
export declare type EagerXapiStatement = Omit<XapiStatement, 'stored'>;
|
|
77
|
+
export declare type UXapiStatement = XapiStatement | EagerXapiStatement | SavedXapiStatement;
|
|
77
78
|
export declare type LrsGateway = ReturnType<ReturnType<ReturnType<typeof lrsGateway>>>;
|
|
78
79
|
export declare type LrsProvider = ReturnType<ReturnType<typeof lrsGateway>>;
|
|
79
80
|
export declare const lrsGateway: <C extends string = "lrs">(initializer: Initializer<C>) => (configProvider: { [key in C]: {
|
|
@@ -82,7 +83,7 @@ export declare const lrsGateway: <C extends string = "lrs">(initializer: Initial
|
|
|
82
83
|
}; }) => (authProvider: AuthProvider) => {
|
|
83
84
|
putXapiStatements: (statements: Array<(Pick<XapiStatement, 'object' | 'verb' | 'context' | 'result'> & {
|
|
84
85
|
id?: string;
|
|
85
|
-
}) |
|
|
86
|
+
}) | UXapiStatement>) => Promise<EagerXapiStatement[]>;
|
|
86
87
|
getXapiStatements: (params: {
|
|
87
88
|
verb?: string | undefined;
|
|
88
89
|
activity?: string | undefined;
|
|
@@ -6,7 +6,7 @@ import { UnauthorizedError } from '../../errors';
|
|
|
6
6
|
import { fetchStatusRetry } from '../../fetch/fetchStatusRetry';
|
|
7
7
|
import { ifDefined } from '../../guards';
|
|
8
8
|
import { METHOD } from '../../routing';
|
|
9
|
-
import { addStatementDefaultFields } from
|
|
9
|
+
import { addStatementDefaultFields } from './addStatementDefaultFields';
|
|
10
10
|
export const lrsGateway = (initializer) => (configProvider) => {
|
|
11
11
|
const config = configProvider[ifDefined(initializer.configSpace, 'lrs')];
|
|
12
12
|
const lrsHost = once(() => resolveConfigValue(config.lrsHost));
|