@openstax/ts-utils 1.1.21 → 1.1.22
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/index.js +3 -2
- package/dist/services/authProvider/browser.js +2 -2
- package/dist/services/authProvider/decryption.js +8 -7
- package/dist/services/authProvider/subrequest.js +6 -5
- package/dist/services/exercisesGateway/index.js +7 -6
- package/dist/services/lrsGateway/index.js +9 -8
- package/dist/services/versionedDocumentStore/dynamodb.js +5 -5
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/tsconfig.withoutspecs.tsbuildinfo +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -85,8 +85,9 @@ exports.hashValue = hashValue;
|
|
|
85
85
|
* butOnlyOnce() // returns `hello`;
|
|
86
86
|
*/
|
|
87
87
|
const once = (fn) => {
|
|
88
|
-
|
|
89
|
-
|
|
88
|
+
const initialValue = {};
|
|
89
|
+
let result = initialValue;
|
|
90
|
+
return ((...args) => result === initialValue ? (result = fn(...args)) : result);
|
|
90
91
|
};
|
|
91
92
|
exports.once = once;
|
|
92
93
|
/*
|
|
@@ -7,7 +7,7 @@ const guards_1 = require("../../guards");
|
|
|
7
7
|
const embeddedAuthProvider_1 = require("./utils/embeddedAuthProvider");
|
|
8
8
|
const browserAuthProvider = ({ window, configSpace }) => (configProvider) => {
|
|
9
9
|
const config = configProvider[(0, guards_1.ifDefined)(configSpace, 'auth')];
|
|
10
|
-
const accountsUrl = (0, config_1.resolveConfigValue)(config.accountsUrl);
|
|
10
|
+
const accountsUrl = (0, __1.once)(() => (0, config_1.resolveConfigValue)(config.accountsUrl));
|
|
11
11
|
const queryString = window.location.search;
|
|
12
12
|
const queryKey = 'auth';
|
|
13
13
|
const authQuery = new URLSearchParams(queryString).get(queryKey);
|
|
@@ -71,7 +71,7 @@ const browserAuthProvider = ({ window, configSpace }) => (configProvider) => {
|
|
|
71
71
|
* requests user identity from accounts api using given token or cookie
|
|
72
72
|
*/
|
|
73
73
|
const getFetchUser = async () => {
|
|
74
|
-
const response = await window.fetch((await accountsUrl).replace(/\/+$/, '') + '/accounts/api/user', getAuthorizedFetchConfigFromData(userData));
|
|
74
|
+
const response = await window.fetch((await accountsUrl()).replace(/\/+$/, '') + '/accounts/api/user', getAuthorizedFetchConfigFromData(userData));
|
|
75
75
|
if (response.status === 200) {
|
|
76
76
|
return { ...userData, user: await response.json() };
|
|
77
77
|
}
|
|
@@ -2,21 +2,22 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.decryptionAuthProvider = void 0;
|
|
4
4
|
const jose_1 = require("jose");
|
|
5
|
+
const __1 = require("../..");
|
|
5
6
|
const config_1 = require("../../config");
|
|
6
7
|
const guards_1 = require("../../guards");
|
|
7
8
|
const _1 = require(".");
|
|
8
9
|
const decryptionAuthProvider = (initializer) => (configProvider) => {
|
|
9
10
|
const config = configProvider[(0, guards_1.ifDefined)(initializer.configSpace, 'decryption')];
|
|
10
|
-
const cookieName = (0, config_1.resolveConfigValue)(config.cookieName);
|
|
11
|
-
const encryptionPrivateKey = (0, config_1.resolveConfigValue)(config.encryptionPrivateKey);
|
|
12
|
-
const signaturePublicKey = (0, config_1.resolveConfigValue)(config.signaturePublicKey);
|
|
11
|
+
const cookieName = (0, __1.once)(() => (0, config_1.resolveConfigValue)(config.cookieName));
|
|
12
|
+
const encryptionPrivateKey = (0, __1.once)(() => (0, config_1.resolveConfigValue)(config.encryptionPrivateKey));
|
|
13
|
+
const signaturePublicKey = (0, __1.once)(() => (0, config_1.resolveConfigValue)(config.signaturePublicKey));
|
|
13
14
|
const decryptAndVerify = async (jwt) => {
|
|
14
15
|
try {
|
|
15
16
|
// Decrypt SSO cookie
|
|
16
|
-
const { plaintext } = await (0, jose_1.compactDecrypt)(jwt, Buffer.from(await encryptionPrivateKey), // Note: Buffer.from() is node-js only
|
|
17
|
+
const { plaintext } = await (0, jose_1.compactDecrypt)(jwt, Buffer.from(await encryptionPrivateKey()), // Note: Buffer.from() is node-js only
|
|
17
18
|
{ contentEncryptionAlgorithms: ['A256GCM'], keyManagementAlgorithms: ['dir'] });
|
|
18
19
|
// Verify SSO cookie signature
|
|
19
|
-
const { payload } = await (0, jose_1.compactVerify)(plaintext, await (0, jose_1.importSPKI)(await signaturePublicKey, 'RS256'), { algorithms: ['RS256'] });
|
|
20
|
+
const { payload } = await (0, jose_1.compactVerify)(plaintext, await (0, jose_1.importSPKI)(await signaturePublicKey(), 'RS256'), { algorithms: ['RS256'] });
|
|
20
21
|
return payload;
|
|
21
22
|
}
|
|
22
23
|
catch {
|
|
@@ -26,14 +27,14 @@ const decryptionAuthProvider = (initializer) => (configProvider) => {
|
|
|
26
27
|
return ({ request, profile }) => {
|
|
27
28
|
let user;
|
|
28
29
|
const getAuthorizedFetchConfig = profile.track('getAuthorizedFetchConfig', () => async () => {
|
|
29
|
-
const [token, headers] = (0, _1.getAuthTokenOrCookie)(request, await cookieName);
|
|
30
|
+
const [token, headers] = (0, _1.getAuthTokenOrCookie)(request, await cookieName());
|
|
30
31
|
if (!token) {
|
|
31
32
|
return {};
|
|
32
33
|
}
|
|
33
34
|
return { headers };
|
|
34
35
|
});
|
|
35
36
|
const loadUser = profile.track('loadUser', () => async () => {
|
|
36
|
-
const [token] = (0, _1.getAuthTokenOrCookie)(request, await cookieName);
|
|
37
|
+
const [token] = (0, _1.getAuthTokenOrCookie)(request, await cookieName());
|
|
37
38
|
if (!token) {
|
|
38
39
|
return undefined;
|
|
39
40
|
}
|
|
@@ -1,28 +1,29 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.subrequestAuthProvider = void 0;
|
|
4
|
+
const __1 = require("../..");
|
|
4
5
|
const config_1 = require("../../config");
|
|
5
6
|
const guards_1 = require("../../guards");
|
|
6
7
|
const _1 = require(".");
|
|
7
8
|
const subrequestAuthProvider = (initializer) => (configProvider) => {
|
|
8
9
|
const config = configProvider[(0, guards_1.ifDefined)(initializer.configSpace, 'subrequest')];
|
|
9
|
-
const cookieName = (0, config_1.resolveConfigValue)(config.cookieName);
|
|
10
|
-
const accountsUrl = (0, config_1.resolveConfigValue)(config.accountsUrl);
|
|
10
|
+
const cookieName = (0, __1.once)(() => (0, config_1.resolveConfigValue)(config.cookieName));
|
|
11
|
+
const accountsUrl = (0, __1.once)(() => (0, config_1.resolveConfigValue)(config.accountsUrl));
|
|
11
12
|
return ({ request, profile }) => {
|
|
12
13
|
let user;
|
|
13
14
|
const getAuthorizedFetchConfig = profile.track('getAuthorizedFetchConfig', () => async () => {
|
|
14
|
-
const [token, headers] = (0, _1.getAuthTokenOrCookie)(request, await cookieName);
|
|
15
|
+
const [token, headers] = (0, _1.getAuthTokenOrCookie)(request, await cookieName());
|
|
15
16
|
if (!token) {
|
|
16
17
|
return {};
|
|
17
18
|
}
|
|
18
19
|
return { headers };
|
|
19
20
|
});
|
|
20
21
|
const loadUser = profile.track('loadUser', p => async () => {
|
|
21
|
-
const [token, headers] = (0, _1.getAuthTokenOrCookie)(request, await cookieName);
|
|
22
|
+
const [token, headers] = (0, _1.getAuthTokenOrCookie)(request, await cookieName());
|
|
22
23
|
if (!token) {
|
|
23
24
|
return undefined;
|
|
24
25
|
}
|
|
25
|
-
return p.trackFetch(initializer.fetch)(await accountsUrl, { headers })
|
|
26
|
+
return p.trackFetch(initializer.fetch)(await accountsUrl(), { headers })
|
|
26
27
|
.then(response => response.json());
|
|
27
28
|
});
|
|
28
29
|
return {
|
|
@@ -25,17 +25,18 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
25
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
26
|
exports.exercisesGateway = void 0;
|
|
27
27
|
const queryString = __importStar(require("query-string"));
|
|
28
|
+
const __1 = require("../..");
|
|
28
29
|
const assertions_1 = require("../../assertions");
|
|
29
30
|
const config_1 = require("../../config");
|
|
30
31
|
const guards_1 = require("../../guards");
|
|
31
32
|
const routing_1 = require("../../routing");
|
|
32
33
|
const exercisesGateway = (initializer) => (configProvider) => {
|
|
33
34
|
const config = configProvider[(0, guards_1.ifDefined)(initializer.configSpace, 'exercises')];
|
|
34
|
-
const exercisesHost = (0, config_1.resolveConfigValue)(config.exercisesHost);
|
|
35
|
-
const exercisesAuthToken = (0, config_1.resolveConfigValue)(config.exercisesAuthToken);
|
|
36
|
-
const defaultCorrectness = (0, config_1.resolveConfigValue)(config.defaultCorrectness || '');
|
|
35
|
+
const exercisesHost = (0, __1.once)(() => (0, config_1.resolveConfigValue)(config.exercisesHost));
|
|
36
|
+
const exercisesAuthToken = (0, __1.once)(() => (0, config_1.resolveConfigValue)(config.exercisesAuthToken));
|
|
37
|
+
const defaultCorrectness = (0, __1.once)(() => (0, config_1.resolveConfigValue)(config.defaultCorrectness || ''));
|
|
37
38
|
const doDefaultCorrectness = async (exercise) => {
|
|
38
|
-
if (await defaultCorrectness !== 'true') {
|
|
39
|
+
if (await defaultCorrectness() !== 'true') {
|
|
39
40
|
return exercise;
|
|
40
41
|
}
|
|
41
42
|
for (const question of exercise.questions) {
|
|
@@ -58,12 +59,12 @@ const exercisesGateway = (initializer) => (configProvider) => {
|
|
|
58
59
|
return exercise;
|
|
59
60
|
};
|
|
60
61
|
const request = async (method, path, query = undefined) => {
|
|
61
|
-
const host = (await exercisesHost).replace(/\/+$/, '');
|
|
62
|
+
const host = (await exercisesHost()).replace(/\/+$/, '');
|
|
62
63
|
const baseUrl = `${host}/api/${path}`;
|
|
63
64
|
const url = query ? `${baseUrl}?${queryString.stringify(query)}` : baseUrl;
|
|
64
65
|
return initializer.fetch(url, {
|
|
65
66
|
headers: {
|
|
66
|
-
Authorization: `Bearer ${await exercisesAuthToken}`,
|
|
67
|
+
Authorization: `Bearer ${await exercisesAuthToken()}`,
|
|
67
68
|
},
|
|
68
69
|
method,
|
|
69
70
|
});
|
|
@@ -29,6 +29,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
29
29
|
exports.lrsGateway = void 0;
|
|
30
30
|
const formatISO_1 = __importDefault(require("date-fns/formatISO"));
|
|
31
31
|
const queryString = __importStar(require("query-string"));
|
|
32
|
+
const __1 = require("../..");
|
|
32
33
|
const assertions_1 = require("../../assertions");
|
|
33
34
|
const config_1 = require("../../config");
|
|
34
35
|
const errors_1 = require("../../errors");
|
|
@@ -36,8 +37,8 @@ const guards_1 = require("../../guards");
|
|
|
36
37
|
const routing_1 = require("../../routing");
|
|
37
38
|
const lrsGateway = (initializer) => (configProvider) => {
|
|
38
39
|
const config = configProvider[(0, guards_1.ifDefined)(initializer.configSpace, 'lrs')];
|
|
39
|
-
const lrsHost = (0, config_1.resolveConfigValue)(config.lrsHost);
|
|
40
|
-
const lrsAuthorization = (0, config_1.resolveConfigValue)(config.lrsAuthorization);
|
|
40
|
+
const lrsHost = (0, __1.once)(() => (0, config_1.resolveConfigValue)(config.lrsHost));
|
|
41
|
+
const lrsAuthorization = (0, __1.once)(() => (0, config_1.resolveConfigValue)(config.lrsAuthorization));
|
|
41
42
|
return (authProvider) => {
|
|
42
43
|
const putXapiStatements = async (statements) => {
|
|
43
44
|
const user = (0, assertions_1.assertDefined)(await authProvider.getUser(), new errors_1.UnauthorizedError);
|
|
@@ -52,10 +53,10 @@ const lrsGateway = (initializer) => (configProvider) => {
|
|
|
52
53
|
},
|
|
53
54
|
timestamp: (0, formatISO_1.default)(new Date())
|
|
54
55
|
}));
|
|
55
|
-
return initializer.fetch((await lrsHost).replace(/\/+$/, '') + '/data/xAPI/statements', {
|
|
56
|
+
return initializer.fetch((await lrsHost()).replace(/\/+$/, '') + '/data/xAPI/statements', {
|
|
56
57
|
body: JSON.stringify(statementsWithDefaults),
|
|
57
58
|
headers: {
|
|
58
|
-
Authorization: await lrsAuthorization,
|
|
59
|
+
Authorization: await lrsAuthorization(),
|
|
59
60
|
'Content-Type': 'application/json',
|
|
60
61
|
'X-Experience-API-Version': '1.0.0',
|
|
61
62
|
},
|
|
@@ -65,9 +66,9 @@ const lrsGateway = (initializer) => (configProvider) => {
|
|
|
65
66
|
.then(ids => ids.map((id, index) => ({ id, ...statementsWithDefaults[index] })));
|
|
66
67
|
};
|
|
67
68
|
const getMoreXapiStatements = async (more) => {
|
|
68
|
-
return initializer.fetch((await lrsHost).replace(/\/+$/, '') + more, {
|
|
69
|
+
return initializer.fetch((await lrsHost()).replace(/\/+$/, '') + more, {
|
|
69
70
|
headers: {
|
|
70
|
-
Authorization: await lrsAuthorization,
|
|
71
|
+
Authorization: await lrsAuthorization(),
|
|
71
72
|
'X-Experience-API-Version': '1.0.0',
|
|
72
73
|
},
|
|
73
74
|
})
|
|
@@ -75,7 +76,7 @@ const lrsGateway = (initializer) => (configProvider) => {
|
|
|
75
76
|
.then(json => json);
|
|
76
77
|
};
|
|
77
78
|
const getXapiStatements = async ({ user, anyUser, ...options }) => {
|
|
78
|
-
return initializer.fetch((await lrsHost).replace(/\/+$/, '') + '/data/xAPI/statements?' + queryString.stringify({
|
|
79
|
+
return initializer.fetch((await lrsHost()).replace(/\/+$/, '') + '/data/xAPI/statements?' + queryString.stringify({
|
|
79
80
|
...options,
|
|
80
81
|
...(anyUser === true ? {} : {
|
|
81
82
|
agent: JSON.stringify({
|
|
@@ -88,7 +89,7 @@ const lrsGateway = (initializer) => (configProvider) => {
|
|
|
88
89
|
})
|
|
89
90
|
}), {
|
|
90
91
|
headers: {
|
|
91
|
-
Authorization: await lrsAuthorization,
|
|
92
|
+
Authorization: await lrsAuthorization(),
|
|
92
93
|
'X-Experience-API-Version': '1.0.0',
|
|
93
94
|
},
|
|
94
95
|
})
|
|
@@ -53,12 +53,12 @@ const decodeDynamoDocument = (document) => Object.fromEntries(Object.entries(doc
|
|
|
53
53
|
// i'm not really excited about getAuthor being required, but ts is getting confused about the type when unspecified
|
|
54
54
|
const dynamoVersionedDocumentStore = (initializer) => () => (configProvider) => ({ profile }, hashKey, getAuthor) => {
|
|
55
55
|
const options = (0, guards_1.ifDefined)(initializer, {});
|
|
56
|
-
const tableName = (0, config_1.resolveConfigValue)(configProvider[(0, guards_1.ifDefined)(options.configSpace, 'dynamodb')].tableName);
|
|
56
|
+
const tableName = (0, __1.once)(() => (0, config_1.resolveConfigValue)(configProvider[(0, guards_1.ifDefined)(options.configSpace, 'dynamodb')].tableName));
|
|
57
57
|
return {
|
|
58
58
|
loadAllDocumentsTheBadWay: profile.track('versionedDocumentStore.loadAllDocumentsTheBadWay', () => async () => {
|
|
59
59
|
const loadAllResults = async (ExclusiveStartKey) => {
|
|
60
60
|
var _a;
|
|
61
|
-
const cmd = new client_dynamodb_1.ScanCommand({ TableName: await tableName, ExclusiveStartKey });
|
|
61
|
+
const cmd = new client_dynamodb_1.ScanCommand({ TableName: await tableName(), ExclusiveStartKey });
|
|
62
62
|
const result = await dynamodb().send(cmd);
|
|
63
63
|
const resultItems = ((_a = result.Items) === null || _a === void 0 ? void 0 : _a.map(decodeDynamoDocument)) || [];
|
|
64
64
|
if (result.LastEvaluatedKey) {
|
|
@@ -77,7 +77,7 @@ const dynamoVersionedDocumentStore = (initializer) => () => (configProvider) =>
|
|
|
77
77
|
}),
|
|
78
78
|
getVersions: profile.track('versionedDocumentStore.getVersions', () => async (id, startVersion) => {
|
|
79
79
|
const cmd = new client_dynamodb_1.QueryCommand({
|
|
80
|
-
TableName: await tableName,
|
|
80
|
+
TableName: await tableName(),
|
|
81
81
|
KeyConditionExpression: '#hk = :hkv',
|
|
82
82
|
ExpressionAttributeValues: {
|
|
83
83
|
':hkv': encodeDynamoAttribute(id)
|
|
@@ -119,7 +119,7 @@ const dynamoVersionedDocumentStore = (initializer) => () => (configProvider) =>
|
|
|
119
119
|
expressionAttributeValues[':tsv'] = encodeDynamoAttribute(timestamp);
|
|
120
120
|
}
|
|
121
121
|
const cmd = new client_dynamodb_1.QueryCommand({
|
|
122
|
-
TableName: await tableName,
|
|
122
|
+
TableName: await tableName(),
|
|
123
123
|
KeyConditionExpression: keyConditionExpression,
|
|
124
124
|
ExpressionAttributeNames: expressionAttributeNames,
|
|
125
125
|
ExpressionAttributeValues: expressionAttributeValues,
|
|
@@ -140,7 +140,7 @@ const dynamoVersionedDocumentStore = (initializer) => () => (configProvider) =>
|
|
|
140
140
|
author
|
|
141
141
|
};
|
|
142
142
|
const cmd = new client_dynamodb_1.PutItemCommand({
|
|
143
|
-
TableName: await tableName,
|
|
143
|
+
TableName: await tableName(),
|
|
144
144
|
Item: encodeDynamoDocument(document),
|
|
145
145
|
});
|
|
146
146
|
return dynamodb().send(cmd)
|