@openstax/ts-utils 1.21.11 → 1.23.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/dist/cjs/assertions/index.d.ts +85 -0
- package/dist/cjs/assertions/index.js +157 -0
- package/dist/cjs/aws/ssmService.d.ts +5 -0
- package/dist/cjs/aws/ssmService.js +9 -0
- package/dist/cjs/config/awsParameterConfig.d.ts +10 -0
- package/dist/cjs/config/awsParameterConfig.js +26 -0
- package/dist/cjs/config/envConfig.d.ts +24 -0
- package/dist/cjs/config/envConfig.js +57 -0
- package/dist/cjs/config/index.d.ts +48 -0
- package/dist/cjs/config/index.js +35 -0
- package/dist/cjs/config/lambdaParameterConfig.d.ts +12 -0
- package/dist/cjs/config/lambdaParameterConfig.js +45 -0
- package/dist/cjs/config/replaceConfig.d.ts +14 -0
- package/dist/cjs/config/replaceConfig.js +22 -0
- package/dist/cjs/config/resolveConfigValue.d.ts +5 -0
- package/dist/cjs/config/resolveConfigValue.js +12 -0
- package/dist/cjs/errors/index.d.ts +77 -0
- package/dist/cjs/errors/index.js +109 -0
- package/dist/cjs/fetch/fetchStatusRetry.d.ts +7 -0
- package/dist/cjs/fetch/fetchStatusRetry.js +16 -0
- package/dist/cjs/fetch/index.d.ts +64 -0
- package/dist/cjs/fetch/index.js +55 -0
- package/dist/cjs/guards/index.d.ts +30 -0
- package/dist/cjs/guards/index.js +35 -0
- package/dist/cjs/index.d.ts +4 -0
- package/dist/cjs/index.js +20 -0
- package/dist/cjs/middleware/apiErrorHandler.d.ts +24 -0
- package/dist/cjs/middleware/apiErrorHandler.js +41 -0
- package/dist/cjs/middleware/apiSlowResponseMiddleware.d.ts +23 -0
- package/dist/cjs/middleware/apiSlowResponseMiddleware.js +54 -0
- package/dist/cjs/middleware/index.d.ts +47 -0
- package/dist/cjs/middleware/index.js +48 -0
- package/dist/cjs/middleware/lambdaCorsResponseMiddleware.d.ts +20 -0
- package/dist/cjs/middleware/lambdaCorsResponseMiddleware.js +42 -0
- package/dist/cjs/middleware/throwNotFoundMiddleware.d.ts +4 -0
- package/dist/cjs/middleware/throwNotFoundMiddleware.js +14 -0
- package/dist/cjs/misc/hashValue.d.ts +10 -0
- package/dist/cjs/misc/hashValue.js +17 -0
- package/dist/cjs/misc/helpers.d.ts +124 -0
- package/dist/cjs/misc/helpers.js +214 -0
- package/dist/cjs/misc/merge.d.ts +21 -0
- package/dist/cjs/misc/merge.js +45 -0
- package/dist/cjs/misc/partitionSequence.d.ts +35 -0
- package/dist/cjs/misc/partitionSequence.js +55 -0
- package/dist/cjs/pagination/index.d.ts +91 -0
- package/dist/cjs/pagination/index.js +83 -0
- package/dist/cjs/routing/helpers.d.ts +57 -0
- package/dist/cjs/routing/helpers.js +90 -0
- package/dist/cjs/routing/index.d.ts +272 -0
- package/dist/cjs/routing/index.js +270 -0
- package/dist/cjs/routing/validators/zod.d.ts +4 -0
- package/dist/cjs/routing/validators/zod.js +12 -0
- package/dist/cjs/services/accountsGateway/index.d.ts +85 -0
- package/dist/cjs/services/accountsGateway/index.js +118 -0
- package/dist/cjs/services/apiGateway/index.d.ts +63 -0
- package/dist/cjs/services/apiGateway/index.js +108 -0
- package/dist/cjs/services/authProvider/browser.d.ts +74 -0
- package/dist/cjs/services/authProvider/browser.js +154 -0
- package/dist/cjs/services/authProvider/decryption.d.ts +19 -0
- package/dist/cjs/services/authProvider/decryption.js +61 -0
- package/dist/cjs/services/authProvider/index.d.ts +61 -0
- package/dist/cjs/services/authProvider/index.js +26 -0
- package/dist/cjs/services/authProvider/subrequest.d.ts +16 -0
- package/dist/cjs/services/authProvider/subrequest.js +50 -0
- package/dist/cjs/services/authProvider/utils/decryptAndVerify.d.ts +29 -0
- package/dist/cjs/services/authProvider/utils/decryptAndVerify.js +91 -0
- package/dist/cjs/services/authProvider/utils/embeddedAuthProvider.d.ts +26 -0
- package/dist/cjs/services/authProvider/utils/embeddedAuthProvider.js +47 -0
- package/dist/cjs/services/authProvider/utils/userRoleValidator.d.ts +13 -0
- package/dist/cjs/services/authProvider/utils/userRoleValidator.js +37 -0
- package/dist/cjs/services/documentStore/dynamoEncoding.d.ts +10 -0
- package/dist/cjs/services/documentStore/dynamoEncoding.js +52 -0
- package/dist/cjs/services/documentStore/index.d.ts +14 -0
- package/dist/cjs/services/documentStore/index.js +2 -0
- package/dist/cjs/services/documentStore/unversioned/dynamodb.d.ts +16 -0
- package/dist/cjs/services/documentStore/unversioned/dynamodb.js +122 -0
- package/dist/cjs/services/documentStore/unversioned/file-system.d.ts +18 -0
- package/dist/cjs/services/documentStore/unversioned/file-system.js +121 -0
- package/dist/cjs/services/documentStore/unversioned/index.d.ts +2 -0
- package/dist/cjs/services/documentStore/unversioned/index.js +2 -0
- package/dist/cjs/services/documentStore/versioned/dynamodb.d.ts +22 -0
- package/dist/cjs/services/documentStore/versioned/dynamodb.js +135 -0
- package/dist/cjs/services/documentStore/versioned/file-system.d.ts +24 -0
- package/dist/cjs/services/documentStore/versioned/file-system.js +62 -0
- package/dist/cjs/services/documentStore/versioned/index.d.ts +17 -0
- package/dist/cjs/services/documentStore/versioned/index.js +2 -0
- package/dist/cjs/services/exercisesGateway/index.d.ts +71 -0
- package/dist/cjs/services/exercisesGateway/index.js +97 -0
- package/dist/cjs/services/fileServer/index.d.ts +17 -0
- package/dist/cjs/services/fileServer/index.js +19 -0
- package/dist/cjs/services/fileServer/localFileServer.d.ts +13 -0
- package/dist/cjs/services/fileServer/localFileServer.js +23 -0
- package/dist/cjs/services/fileServer/s3FileServer.d.ts +16 -0
- package/dist/cjs/services/fileServer/s3FileServer.js +25 -0
- package/dist/cjs/services/launchParams/index.d.ts +2 -0
- package/dist/cjs/services/launchParams/index.js +7 -0
- package/dist/cjs/services/launchParams/signer.d.ts +27 -0
- package/dist/cjs/services/launchParams/signer.js +58 -0
- package/dist/cjs/services/launchParams/verifier.d.ts +22 -0
- package/dist/cjs/services/launchParams/verifier.js +94 -0
- package/dist/cjs/services/logger/console.d.ts +4 -0
- package/dist/cjs/services/logger/console.js +12 -0
- package/dist/cjs/services/logger/index.d.ts +39 -0
- package/dist/cjs/services/logger/index.js +31 -0
- package/dist/cjs/services/lrsGateway/addStatementDefaultFields.d.ts +5 -0
- package/dist/cjs/services/lrsGateway/addStatementDefaultFields.js +21 -0
- package/dist/cjs/services/lrsGateway/attempt-utils.d.ts +70 -0
- package/dist/cjs/services/lrsGateway/attempt-utils.js +258 -0
- package/dist/cjs/services/lrsGateway/file-system.d.ts +17 -0
- package/dist/cjs/services/lrsGateway/file-system.js +140 -0
- package/dist/cjs/services/lrsGateway/index.d.ts +125 -0
- package/dist/cjs/services/lrsGateway/index.js +138 -0
- package/dist/cjs/services/lrsGateway/xapiUtils.d.ts +61 -0
- package/dist/cjs/services/lrsGateway/xapiUtils.js +94 -0
- package/dist/cjs/services/postgresConnection/index.d.ts +35 -0
- package/dist/cjs/services/postgresConnection/index.js +63 -0
- package/dist/cjs/services/searchProvider/index.d.ts +31 -0
- package/dist/cjs/services/searchProvider/index.js +2 -0
- package/dist/cjs/services/searchProvider/memorySearchTheBadWay.d.ts +14 -0
- package/dist/cjs/services/searchProvider/memorySearchTheBadWay.js +89 -0
- package/dist/cjs/tsconfig.without-specs.cjs.tsbuildinfo +1 -0
- package/dist/cjs/types.d.ts +31 -0
- package/dist/cjs/types.js +2 -0
- package/dist/esm/assertions/index.d.ts +85 -0
- package/dist/esm/assertions/index.js +146 -0
- package/dist/esm/aws/ssmService.d.ts +5 -0
- package/dist/esm/aws/ssmService.js +6 -0
- package/dist/esm/config/awsParameterConfig.d.ts +10 -0
- package/dist/esm/config/awsParameterConfig.js +22 -0
- package/dist/esm/config/envConfig.d.ts +24 -0
- package/dist/esm/config/envConfig.js +53 -0
- package/dist/esm/config/index.d.ts +48 -0
- package/dist/esm/config/index.js +17 -0
- package/dist/esm/config/lambdaParameterConfig.d.ts +12 -0
- package/dist/esm/config/lambdaParameterConfig.js +38 -0
- package/dist/esm/config/replaceConfig.d.ts +14 -0
- package/dist/esm/config/replaceConfig.js +18 -0
- package/dist/esm/config/resolveConfigValue.d.ts +5 -0
- package/dist/esm/config/resolveConfigValue.js +8 -0
- package/dist/esm/errors/index.d.ts +77 -0
- package/dist/esm/errors/index.js +99 -0
- package/dist/esm/fetch/fetchStatusRetry.d.ts +7 -0
- package/dist/esm/fetch/fetchStatusRetry.js +12 -0
- package/dist/esm/fetch/index.d.ts +64 -0
- package/dist/esm/fetch/index.js +46 -0
- package/dist/esm/guards/index.d.ts +30 -0
- package/dist/esm/guards/index.js +28 -0
- package/dist/esm/index.d.ts +4 -0
- package/dist/esm/index.js +4 -0
- package/dist/esm/middleware/apiErrorHandler.d.ts +24 -0
- package/dist/esm/middleware/apiErrorHandler.js +37 -0
- package/dist/esm/middleware/apiSlowResponseMiddleware.d.ts +23 -0
- package/dist/esm/middleware/apiSlowResponseMiddleware.js +50 -0
- package/dist/esm/middleware/index.d.ts +47 -0
- package/dist/esm/middleware/index.js +44 -0
- package/dist/esm/middleware/lambdaCorsResponseMiddleware.d.ts +20 -0
- package/dist/esm/middleware/lambdaCorsResponseMiddleware.js +38 -0
- package/dist/esm/middleware/throwNotFoundMiddleware.d.ts +4 -0
- package/dist/esm/middleware/throwNotFoundMiddleware.js +10 -0
- package/dist/esm/misc/hashValue.d.ts +10 -0
- package/dist/esm/misc/hashValue.js +13 -0
- package/dist/esm/misc/helpers.d.ts +124 -0
- package/dist/esm/misc/helpers.js +199 -0
- package/dist/esm/misc/merge.d.ts +21 -0
- package/dist/esm/misc/merge.js +40 -0
- package/dist/esm/misc/partitionSequence.d.ts +35 -0
- package/dist/esm/misc/partitionSequence.js +48 -0
- package/dist/esm/pagination/index.d.ts +91 -0
- package/dist/esm/pagination/index.js +77 -0
- package/dist/esm/routing/helpers.d.ts +57 -0
- package/dist/esm/routing/helpers.js +83 -0
- package/dist/esm/routing/index.d.ts +272 -0
- package/dist/esm/routing/index.js +232 -0
- package/dist/esm/routing/validators/zod.d.ts +4 -0
- package/dist/esm/routing/validators/zod.js +8 -0
- package/dist/esm/services/accountsGateway/index.d.ts +85 -0
- package/dist/esm/services/accountsGateway/index.js +111 -0
- package/dist/esm/services/apiGateway/index.d.ts +63 -0
- package/dist/esm/services/apiGateway/index.js +77 -0
- package/dist/esm/services/authProvider/browser.d.ts +74 -0
- package/dist/esm/services/authProvider/browser.js +150 -0
- package/dist/esm/services/authProvider/decryption.d.ts +19 -0
- package/dist/esm/services/authProvider/decryption.js +57 -0
- package/dist/esm/services/authProvider/index.d.ts +61 -0
- package/dist/esm/services/authProvider/index.js +18 -0
- package/dist/esm/services/authProvider/subrequest.d.ts +16 -0
- package/dist/esm/services/authProvider/subrequest.js +43 -0
- package/dist/esm/services/authProvider/utils/decryptAndVerify.d.ts +29 -0
- package/dist/esm/services/authProvider/utils/decryptAndVerify.js +85 -0
- package/dist/esm/services/authProvider/utils/embeddedAuthProvider.d.ts +26 -0
- package/dist/esm/services/authProvider/utils/embeddedAuthProvider.js +40 -0
- package/dist/esm/services/authProvider/utils/userRoleValidator.d.ts +13 -0
- package/dist/esm/services/authProvider/utils/userRoleValidator.js +33 -0
- package/dist/esm/services/documentStore/dynamoEncoding.d.ts +10 -0
- package/dist/esm/services/documentStore/dynamoEncoding.js +45 -0
- package/dist/esm/services/documentStore/index.d.ts +14 -0
- package/dist/esm/services/documentStore/index.js +1 -0
- package/dist/esm/services/documentStore/unversioned/dynamodb.d.ts +16 -0
- package/dist/esm/services/documentStore/unversioned/dynamodb.js +118 -0
- package/dist/esm/services/documentStore/unversioned/file-system.d.ts +18 -0
- package/dist/esm/services/documentStore/unversioned/file-system.js +91 -0
- package/dist/esm/services/documentStore/unversioned/index.d.ts +2 -0
- package/dist/esm/services/documentStore/unversioned/index.js +1 -0
- package/dist/esm/services/documentStore/versioned/dynamodb.d.ts +22 -0
- package/dist/esm/services/documentStore/versioned/dynamodb.js +131 -0
- package/dist/esm/services/documentStore/versioned/file-system.d.ts +24 -0
- package/dist/esm/services/documentStore/versioned/file-system.js +58 -0
- package/dist/esm/services/documentStore/versioned/index.d.ts +17 -0
- package/dist/esm/services/documentStore/versioned/index.js +1 -0
- package/dist/esm/services/exercisesGateway/index.d.ts +71 -0
- package/dist/esm/services/exercisesGateway/index.js +70 -0
- package/dist/esm/services/fileServer/index.d.ts +17 -0
- package/dist/esm/services/fileServer/index.js +13 -0
- package/dist/esm/services/fileServer/localFileServer.d.ts +13 -0
- package/dist/esm/services/fileServer/localFileServer.js +16 -0
- package/dist/esm/services/fileServer/s3FileServer.d.ts +16 -0
- package/dist/esm/services/fileServer/s3FileServer.js +21 -0
- package/dist/esm/services/launchParams/index.d.ts +2 -0
- package/dist/esm/services/launchParams/index.js +2 -0
- package/dist/esm/services/launchParams/signer.d.ts +27 -0
- package/dist/esm/services/launchParams/signer.js +51 -0
- package/dist/esm/services/launchParams/verifier.d.ts +22 -0
- package/dist/esm/services/launchParams/verifier.js +67 -0
- package/dist/esm/services/logger/console.d.ts +4 -0
- package/dist/esm/services/logger/console.js +8 -0
- package/dist/esm/services/logger/index.d.ts +39 -0
- package/dist/esm/services/logger/index.js +27 -0
- package/dist/esm/services/lrsGateway/addStatementDefaultFields.d.ts +5 -0
- package/dist/esm/services/lrsGateway/addStatementDefaultFields.js +14 -0
- package/dist/esm/services/lrsGateway/attempt-utils.d.ts +70 -0
- package/dist/esm/services/lrsGateway/attempt-utils.js +236 -0
- package/dist/esm/services/lrsGateway/file-system.d.ts +17 -0
- package/dist/esm/services/lrsGateway/file-system.js +110 -0
- package/dist/esm/services/lrsGateway/index.d.ts +125 -0
- package/dist/esm/services/lrsGateway/index.js +111 -0
- package/dist/esm/services/lrsGateway/xapiUtils.d.ts +61 -0
- package/dist/esm/services/lrsGateway/xapiUtils.js +84 -0
- package/dist/esm/services/postgresConnection/index.d.ts +35 -0
- package/dist/esm/services/postgresConnection/index.js +56 -0
- package/dist/esm/services/searchProvider/index.d.ts +31 -0
- package/dist/esm/services/searchProvider/index.js +1 -0
- package/dist/esm/services/searchProvider/memorySearchTheBadWay.d.ts +14 -0
- package/dist/esm/services/searchProvider/memorySearchTheBadWay.js +85 -0
- package/dist/esm/tsconfig.without-specs.esm.tsbuildinfo +1 -0
- package/dist/esm/types.d.ts +31 -0
- package/dist/esm/types.js +1 -0
- package/package.json +16 -16
- package/script/bin/deploy.bash +8 -0
- package/script/bin/get-env-param.bash +3 -3
- package/script/bin/init-params-script.bash +10 -1
- package/script/bin/upload-params.bash +3 -3
- package/dist/tsconfig.tsbuildinfo +0 -1
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
exports.lrsGateway = void 0;
|
|
27
|
+
const queryString = __importStar(require("query-string"));
|
|
28
|
+
const __1 = require("../..");
|
|
29
|
+
const assertions_1 = require("../../assertions");
|
|
30
|
+
const config_1 = require("../../config");
|
|
31
|
+
const errors_1 = require("../../errors");
|
|
32
|
+
const fetchStatusRetry_1 = require("../../fetch/fetchStatusRetry");
|
|
33
|
+
const guards_1 = require("../../guards");
|
|
34
|
+
const helpers_1 = require("../../misc/helpers");
|
|
35
|
+
const routing_1 = require("../../routing");
|
|
36
|
+
const addStatementDefaultFields_1 = require("./addStatementDefaultFields");
|
|
37
|
+
const lrsGateway = (initializer) => (configProvider) => {
|
|
38
|
+
const config = configProvider[(0, guards_1.ifDefined)(initializer.configSpace, 'lrs')];
|
|
39
|
+
const lrsHost = (0, __1.once)(() => (0, config_1.resolveConfigValue)(config.lrsHost));
|
|
40
|
+
const lrsAuthorization = (0, __1.once)(() => (0, config_1.resolveConfigValue)(config.lrsAuthorization));
|
|
41
|
+
return ({ authProvider, logger }) => {
|
|
42
|
+
const fetcher = (0, fetchStatusRetry_1.fetchStatusRetry)(initializer.fetch, {
|
|
43
|
+
logger,
|
|
44
|
+
retries: 2,
|
|
45
|
+
wait: 1000,
|
|
46
|
+
status: [502]
|
|
47
|
+
});
|
|
48
|
+
// Note: This method actually uses POST
|
|
49
|
+
const putXapiStatements = async (statements) => {
|
|
50
|
+
const user = (0, assertions_1.assertDefined)(await authProvider.getUser(), new errors_1.UnauthorizedError);
|
|
51
|
+
const statementsWithDefaults = statements.map(statement => (0, addStatementDefaultFields_1.addStatementDefaultFields)(statement, user));
|
|
52
|
+
const response = await fetcher((await lrsHost()).replace(/\/+$/, '') + '/data/xAPI/statements', {
|
|
53
|
+
body: JSON.stringify(statementsWithDefaults),
|
|
54
|
+
headers: {
|
|
55
|
+
Authorization: await lrsAuthorization(),
|
|
56
|
+
'Content-Type': 'application/json',
|
|
57
|
+
'X-Experience-API-Version': '1.0.0',
|
|
58
|
+
},
|
|
59
|
+
method: routing_1.METHOD.POST,
|
|
60
|
+
});
|
|
61
|
+
if (![200, 201].includes(response.status)) {
|
|
62
|
+
throw new Error(`Unexpected LRS POST statements response code ${response.status} with body:
|
|
63
|
+
|
|
64
|
+
${await response.text()}`);
|
|
65
|
+
}
|
|
66
|
+
await response.json();
|
|
67
|
+
return statementsWithDefaults;
|
|
68
|
+
};
|
|
69
|
+
// Note: This code does not currently handle a single statement response,
|
|
70
|
+
// which can return 404 if the statement is not found
|
|
71
|
+
const formatGetXapiStatementsResponse = async (response) => {
|
|
72
|
+
if (response.status !== 200) {
|
|
73
|
+
throw new Error(`Unexpected LRS GET statements response code ${response.status} with body:
|
|
74
|
+
|
|
75
|
+
${await response.text()}`);
|
|
76
|
+
}
|
|
77
|
+
return response.json();
|
|
78
|
+
};
|
|
79
|
+
const getMoreXapiStatements = async (more) => fetcher((await lrsHost()).replace(/\/+$/, '') + more, {
|
|
80
|
+
headers: {
|
|
81
|
+
Authorization: await lrsAuthorization(),
|
|
82
|
+
'X-Experience-API-Version': '1.0.0',
|
|
83
|
+
},
|
|
84
|
+
}).then(formatGetXapiStatementsResponse);
|
|
85
|
+
const fetchXapiStatements = async ({ user, anyUser, ...options }) => fetcher((await lrsHost()).replace(/\/+$/, '') + '/data/xAPI/statements?' + queryString.stringify({
|
|
86
|
+
...options,
|
|
87
|
+
...(anyUser === true ? {} : {
|
|
88
|
+
agent: JSON.stringify({
|
|
89
|
+
account: {
|
|
90
|
+
homePage: 'https://openstax.org',
|
|
91
|
+
name: user || (0, assertions_1.assertDefined)(await authProvider.getUser(), new errors_1.UnauthorizedError()).uuid,
|
|
92
|
+
},
|
|
93
|
+
objectType: 'Agent',
|
|
94
|
+
}),
|
|
95
|
+
})
|
|
96
|
+
}), {
|
|
97
|
+
headers: {
|
|
98
|
+
Authorization: await lrsAuthorization(),
|
|
99
|
+
'X-Experience-API-Version': '1.0.0',
|
|
100
|
+
},
|
|
101
|
+
});
|
|
102
|
+
const getXapiStatements = async (params) => {
|
|
103
|
+
const { ensureSync, ...fetchParams } = params;
|
|
104
|
+
if (ensureSync) {
|
|
105
|
+
const date = new Date();
|
|
106
|
+
return (0, helpers_1.retryWithDelay)(async (abort) => {
|
|
107
|
+
// this function retries for the consistency, if the fetch errors just abort
|
|
108
|
+
const response = await fetchXapiStatements(fetchParams).catch(abort);
|
|
109
|
+
const consistentThrough = response.headers.get('X-Experience-API-Consistent-Through');
|
|
110
|
+
if (!consistentThrough || new Date(consistentThrough) < date) {
|
|
111
|
+
throw new Error(`xAPI consistent through ${consistentThrough}; not in sync with current date ${date.toISOString()}.`);
|
|
112
|
+
}
|
|
113
|
+
return formatGetXapiStatementsResponse(response);
|
|
114
|
+
}, { retries: 4, logger });
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
return fetchXapiStatements(fetchParams).then(formatGetXapiStatementsResponse);
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
const getAllXapiStatements = async ({ fetchUntil, ...params }) => {
|
|
121
|
+
const loadRemaining = async (result) => {
|
|
122
|
+
if (!result.more || (fetchUntil && fetchUntil(result.statements))) {
|
|
123
|
+
return result.statements;
|
|
124
|
+
}
|
|
125
|
+
const { more, statements } = await getMoreXapiStatements(result.more);
|
|
126
|
+
return loadRemaining({ more, statements: [...result.statements, ...statements] });
|
|
127
|
+
};
|
|
128
|
+
return loadRemaining(await getXapiStatements(params));
|
|
129
|
+
};
|
|
130
|
+
return {
|
|
131
|
+
putXapiStatements,
|
|
132
|
+
getXapiStatements,
|
|
133
|
+
getMoreXapiStatements,
|
|
134
|
+
getAllXapiStatements,
|
|
135
|
+
};
|
|
136
|
+
};
|
|
137
|
+
};
|
|
138
|
+
exports.lrsGateway = lrsGateway;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { AccountsGateway, MappedUserInfo } from '../accountsGateway';
|
|
2
|
+
import { AuthProvider } from '../authProvider';
|
|
3
|
+
import { Logger } from '../logger';
|
|
4
|
+
import { ActivityState } from './attempt-utils';
|
|
5
|
+
import { LrsGateway } from '.';
|
|
6
|
+
export interface Grade {
|
|
7
|
+
scoreGiven: number;
|
|
8
|
+
scoreMaximum: number;
|
|
9
|
+
comment?: string;
|
|
10
|
+
activityProgress: 'Initialized' | 'Started' | 'inProgress' | 'Submitted' | 'Completed';
|
|
11
|
+
gradingProgress: 'FullyGraded' | 'Pending' | 'PendingManual' | 'Failed' | 'NotReady';
|
|
12
|
+
userId?: string;
|
|
13
|
+
}
|
|
14
|
+
export declare const getRegistrationAttemptInfo: (lrs: LrsGateway, registration: string, options?: {
|
|
15
|
+
activity?: string | undefined;
|
|
16
|
+
anyUser?: boolean | undefined;
|
|
17
|
+
currentPreference?: "latest" | "oldest" | undefined;
|
|
18
|
+
ensureSync?: boolean | undefined;
|
|
19
|
+
user?: string | undefined;
|
|
20
|
+
} | undefined) => Promise<{
|
|
21
|
+
[key: string]: ActivityState;
|
|
22
|
+
}>;
|
|
23
|
+
export declare const getScoreGrade: (score: {
|
|
24
|
+
scaled?: number;
|
|
25
|
+
raw?: number;
|
|
26
|
+
min?: number;
|
|
27
|
+
max?: number;
|
|
28
|
+
}, completed: boolean, userId?: string | undefined, maxScore?: number | undefined) => Grade;
|
|
29
|
+
export declare type Progress = {
|
|
30
|
+
scaled: number;
|
|
31
|
+
max?: number;
|
|
32
|
+
raw?: number;
|
|
33
|
+
};
|
|
34
|
+
export declare type GradeAndProgress = {
|
|
35
|
+
grade: Grade;
|
|
36
|
+
progress: Progress;
|
|
37
|
+
name?: string;
|
|
38
|
+
};
|
|
39
|
+
export declare const getCurrentGrade: (services: {
|
|
40
|
+
lrs: LrsGateway;
|
|
41
|
+
ltiAuthProvider: AuthProvider;
|
|
42
|
+
}, registration: string, options?: {
|
|
43
|
+
currentPreference?: "latest" | "oldest" | undefined;
|
|
44
|
+
incompleteAttemptCallback?: ((info: ActivityState) => Promise<GradeAndProgress>) | undefined;
|
|
45
|
+
name?: string | undefined;
|
|
46
|
+
scoreMaximum?: number | undefined;
|
|
47
|
+
userId?: string | undefined;
|
|
48
|
+
} | undefined) => Promise<GradeAndProgress | null>;
|
|
49
|
+
export declare type UserActivityInfo = MappedUserInfo<ActivityState>;
|
|
50
|
+
export declare const getAssignmentGrades: (services: {
|
|
51
|
+
accountsGateway: AccountsGateway;
|
|
52
|
+
lrs: LrsGateway;
|
|
53
|
+
logger: Logger;
|
|
54
|
+
}, assignmentIRI: string, registration: string, options?: {
|
|
55
|
+
anyUser?: boolean | undefined;
|
|
56
|
+
currentPreference?: "latest" | "oldest" | undefined;
|
|
57
|
+
incompleteAttemptsCallback?: ((mappedInfo: UserActivityInfo[]) => Promise<GradeAndProgress[]>) | undefined;
|
|
58
|
+
platformId?: string | undefined;
|
|
59
|
+
scoreMaximum?: number | undefined;
|
|
60
|
+
user?: string | undefined;
|
|
61
|
+
} | undefined) => Promise<GradeAndProgress[]>;
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.getAssignmentGrades = exports.getCurrentGrade = exports.getScoreGrade = exports.getRegistrationAttemptInfo = void 0;
|
|
7
|
+
const partition_1 = __importDefault(require("lodash/fp/partition"));
|
|
8
|
+
const __1 = require("../..");
|
|
9
|
+
const attempt_utils_1 = require("./attempt-utils");
|
|
10
|
+
const getRegistrationAttemptInfo = async (lrs, registration, options) => {
|
|
11
|
+
const { currentPreference, ...xapiOptions } = options !== null && options !== void 0 ? options : {};
|
|
12
|
+
const allStatements = await lrs.getAllXapiStatements({ ...xapiOptions, registration });
|
|
13
|
+
// Partition statements for each user
|
|
14
|
+
const statementsPerUser = {};
|
|
15
|
+
allStatements.forEach((statement) => {
|
|
16
|
+
var _a;
|
|
17
|
+
// If we ever support accounts from different statement.actor.account.homePage, this method may need changes
|
|
18
|
+
// (unless we can guarantee the statement.actor.account.name are unique)
|
|
19
|
+
statementsPerUser[_a = statement.actor.account.name] || (statementsPerUser[_a] = []);
|
|
20
|
+
statementsPerUser[statement.actor.account.name].push(statement);
|
|
21
|
+
});
|
|
22
|
+
const result = {};
|
|
23
|
+
for (const [userUuid, userStatements] of Object.entries(statementsPerUser)) {
|
|
24
|
+
result[userUuid] = (0, attempt_utils_1.resolveAttemptInfo)(userStatements, { currentPreference });
|
|
25
|
+
}
|
|
26
|
+
return result;
|
|
27
|
+
};
|
|
28
|
+
exports.getRegistrationAttemptInfo = getRegistrationAttemptInfo;
|
|
29
|
+
// generates a payload that can be sent to the LMS, documentation here:
|
|
30
|
+
// lti: http://www.imsglobal.org/spec/lti-ags/v2p0#score-publish-service
|
|
31
|
+
// ltijs: https://cvmcosta.me/ltijs/#/grading
|
|
32
|
+
const getScoreGrade = (score, completed, userId, maxScore) => {
|
|
33
|
+
const { raw, scaled, max } = score;
|
|
34
|
+
const scoreMaximum = maxScore !== null && maxScore !== void 0 ? maxScore : 100;
|
|
35
|
+
const scoreGiven = raw && max
|
|
36
|
+
? scoreMaximum / max * raw
|
|
37
|
+
: scaled
|
|
38
|
+
? scaled * scoreMaximum
|
|
39
|
+
: 0;
|
|
40
|
+
return {
|
|
41
|
+
userId,
|
|
42
|
+
activityProgress: completed ? 'Completed' : 'Started',
|
|
43
|
+
// canvas assumes that anything that isn't 'FullyGraded' requires manual grading and displays a "needs grading" icon.
|
|
44
|
+
// if you warp your mind you can consider the portion of the assignment which is completed to be fully graded.
|
|
45
|
+
gradingProgress: 'FullyGraded',
|
|
46
|
+
scoreMaximum,
|
|
47
|
+
scoreGiven: (0, __1.roundToPrecision)(scoreGiven, -2),
|
|
48
|
+
};
|
|
49
|
+
};
|
|
50
|
+
exports.getScoreGrade = getScoreGrade;
|
|
51
|
+
// These methods assign 0's to incomplete activities
|
|
52
|
+
const getCompletedActivityStateGradeAndProgress = ({ name, scoreMaximum, state, userId }) => {
|
|
53
|
+
var _a, _b;
|
|
54
|
+
return ({
|
|
55
|
+
grade: (0, exports.getScoreGrade)(((_b = (_a = state.currentAttemptCompleted) === null || _a === void 0 ? void 0 : _a.result) === null || _b === void 0 ? void 0 : _b.score) || {}, !!state.currentAttemptCompleted, userId, scoreMaximum),
|
|
56
|
+
progress: {
|
|
57
|
+
scaled: state.currentAttemptCompleted ? 1 : 0,
|
|
58
|
+
},
|
|
59
|
+
name,
|
|
60
|
+
});
|
|
61
|
+
};
|
|
62
|
+
const getCompletedUserInfosGradeAndProgress = (infos, scoreMaximum) => infos.map(({ data, fullName, platformUserId }) => getCompletedActivityStateGradeAndProgress({
|
|
63
|
+
name: fullName, scoreMaximum, userId: platformUserId, state: data
|
|
64
|
+
}));
|
|
65
|
+
const getCurrentGrade = async (services, registration, options) => {
|
|
66
|
+
var _a;
|
|
67
|
+
const user = await services.ltiAuthProvider.getUser();
|
|
68
|
+
if (!user) {
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
const userId = (_a = options === null || options === void 0 ? void 0 : options.userId) !== null && _a !== void 0 ? _a : user.uuid;
|
|
72
|
+
const { currentPreference, incompleteAttemptCallback, name, scoreMaximum } = options !== null && options !== void 0 ? options : {};
|
|
73
|
+
const infoPerUser = await (0, exports.getRegistrationAttemptInfo)(services.lrs, registration, { currentPreference });
|
|
74
|
+
const userInfo = infoPerUser[user.uuid];
|
|
75
|
+
if (!userInfo) {
|
|
76
|
+
return getCompletedActivityStateGradeAndProgress({ name, scoreMaximum, state: (0, attempt_utils_1.resolveAttemptInfo)([]), userId });
|
|
77
|
+
}
|
|
78
|
+
if (userInfo.currentAttemptCompleted || !incompleteAttemptCallback) {
|
|
79
|
+
return getCompletedActivityStateGradeAndProgress({ name, scoreMaximum, state: userInfo, userId });
|
|
80
|
+
}
|
|
81
|
+
return incompleteAttemptCallback(userInfo);
|
|
82
|
+
};
|
|
83
|
+
exports.getCurrentGrade = getCurrentGrade;
|
|
84
|
+
const getAssignmentGrades = async (services, assignmentIRI, registration, options) => {
|
|
85
|
+
const { anyUser, currentPreference, incompleteAttemptsCallback, platformId, scoreMaximum, user } = options !== null && options !== void 0 ? options : {};
|
|
86
|
+
const infoPerUserUuid = await (0, exports.getRegistrationAttemptInfo)(services.lrs, registration, { activity: assignmentIRI, anyUser, currentPreference, user });
|
|
87
|
+
const mappedInfo = await services.accountsGateway.mapUserUuids(infoPerUserUuid, services.logger, platformId);
|
|
88
|
+
if (!incompleteAttemptsCallback) {
|
|
89
|
+
return getCompletedUserInfosGradeAndProgress(mappedInfo, scoreMaximum);
|
|
90
|
+
}
|
|
91
|
+
const [incompleteInfo, completedInfo] = (0, partition_1.default)((info) => info.data.currentAttemptCompleted === undefined)(mappedInfo);
|
|
92
|
+
return getCompletedUserInfosGradeAndProgress(completedInfo, scoreMaximum).concat(await incompleteAttemptsCallback(incompleteInfo));
|
|
93
|
+
};
|
|
94
|
+
exports.getAssignmentGrades = getAssignmentGrades;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import postgres, { Sql } from 'postgres';
|
|
2
|
+
import { ConfigProviderForConfig } from '../../config';
|
|
3
|
+
import type { Logger } from '../logger';
|
|
4
|
+
declare type Config = {
|
|
5
|
+
host: string;
|
|
6
|
+
readHost: string;
|
|
7
|
+
port: string;
|
|
8
|
+
database: string;
|
|
9
|
+
username: string;
|
|
10
|
+
password: string;
|
|
11
|
+
};
|
|
12
|
+
interface Initializer<C> {
|
|
13
|
+
configSpace?: C;
|
|
14
|
+
}
|
|
15
|
+
export declare const postgresConnection: <C extends string = "local">(initializer: Initializer<C>) => (configProvider: { [key in C]: {
|
|
16
|
+
host: import("../../config").ConfigValueProvider<string>;
|
|
17
|
+
readHost: import("../../config").ConfigValueProvider<string>;
|
|
18
|
+
port: import("../../config").ConfigValueProvider<string>;
|
|
19
|
+
database: import("../../config").ConfigValueProvider<string>;
|
|
20
|
+
username: import("../../config").ConfigValueProvider<string>;
|
|
21
|
+
password: import("../../config").ConfigValueProvider<string>;
|
|
22
|
+
}; }) => (services: {
|
|
23
|
+
logger: Logger;
|
|
24
|
+
}) => {
|
|
25
|
+
db: () => Promise<postgres.Sql<{}>>;
|
|
26
|
+
dbRead: () => Promise<postgres.Sql<{}>>;
|
|
27
|
+
migrate: (migrations: Migration[]) => Promise<void>;
|
|
28
|
+
down: () => Promise<void[]>;
|
|
29
|
+
};
|
|
30
|
+
export declare type PostgresConnection = ReturnType<ReturnType<ReturnType<typeof postgresConnection>>>;
|
|
31
|
+
export interface Migration {
|
|
32
|
+
name: string;
|
|
33
|
+
up: (db: Sql) => Promise<void>;
|
|
34
|
+
}
|
|
35
|
+
export {};
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.postgresConnection = void 0;
|
|
7
|
+
const postgres_1 = __importDefault(require("postgres"));
|
|
8
|
+
const assertions_1 = require("../../assertions");
|
|
9
|
+
const config_1 = require("../../config");
|
|
10
|
+
const guards_1 = require("../../guards");
|
|
11
|
+
const helpers_1 = require("../../misc/helpers");
|
|
12
|
+
const postgresConnection = (initializer) => (configProvider) => {
|
|
13
|
+
const config = configProvider[(0, guards_1.ifDefined)(initializer.configSpace, 'local')];
|
|
14
|
+
const host = (0, helpers_1.once)(() => (0, config_1.resolveConfigValue)(config.host));
|
|
15
|
+
const readHost = (0, helpers_1.once)(() => (0, config_1.resolveConfigValue)(config.readHost));
|
|
16
|
+
const connectionOptions = (0, helpers_1.once)(async () => ({
|
|
17
|
+
port: (0, assertions_1.assertNotNaN)(parseInt(await (0, config_1.resolveConfigValue)(config.port), 10), new Error('port must be a number')),
|
|
18
|
+
database: await (0, config_1.resolveConfigValue)(config.database),
|
|
19
|
+
username: await (0, config_1.resolveConfigValue)(config.username),
|
|
20
|
+
password: await (0, config_1.resolveConfigValue)(config.password),
|
|
21
|
+
transform: postgres_1.default.camel,
|
|
22
|
+
}));
|
|
23
|
+
const connections = [];
|
|
24
|
+
const sql = (0, helpers_1.once)(async () => {
|
|
25
|
+
const options = await connectionOptions();
|
|
26
|
+
const connection = (0, postgres_1.default)({ ...options, host: await host() });
|
|
27
|
+
connections.push(connection);
|
|
28
|
+
return connection;
|
|
29
|
+
});
|
|
30
|
+
const sqlRead = (0, helpers_1.once)(async () => {
|
|
31
|
+
const options = await connectionOptions();
|
|
32
|
+
const connection = (0, postgres_1.default)({ ...options, host: await readHost() });
|
|
33
|
+
connections.push(connection);
|
|
34
|
+
return connection;
|
|
35
|
+
});
|
|
36
|
+
return (services) => ({
|
|
37
|
+
db: sql,
|
|
38
|
+
dbRead: sqlRead,
|
|
39
|
+
migrate: async (migrations) => {
|
|
40
|
+
await migrate(services, await sql(), migrations);
|
|
41
|
+
},
|
|
42
|
+
down: () => Promise.all(connections.map(c => c.end()))
|
|
43
|
+
});
|
|
44
|
+
};
|
|
45
|
+
exports.postgresConnection = postgresConnection;
|
|
46
|
+
async function migrate(services, db, migrations) {
|
|
47
|
+
await db `
|
|
48
|
+
CREATE TABLE IF NOT EXISTS migrations (
|
|
49
|
+
id SERIAL PRIMARY KEY,
|
|
50
|
+
name TEXT NOT NULL,
|
|
51
|
+
ran_at TIMESTAMP NOT NULL DEFAULT NOW()
|
|
52
|
+
)
|
|
53
|
+
`;
|
|
54
|
+
const ranMigrations = await db `SELECT name FROM migrations`;
|
|
55
|
+
for (const migration of migrations) {
|
|
56
|
+
if (ranMigrations.some(({ name }) => name === migration.name)) {
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
services.logger.log(`Running migration ${migration.name}`);
|
|
60
|
+
await migration.up(db);
|
|
61
|
+
await db `INSERT INTO migrations (name) VALUES (${migration.name})`;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export declare type Filter = {
|
|
2
|
+
key: string;
|
|
3
|
+
value: string | string[] | boolean;
|
|
4
|
+
};
|
|
5
|
+
declare type Field = {
|
|
6
|
+
key: string;
|
|
7
|
+
type?: 'text';
|
|
8
|
+
weight: number;
|
|
9
|
+
} | {
|
|
10
|
+
key: string;
|
|
11
|
+
type: 'keyword';
|
|
12
|
+
} | {
|
|
13
|
+
key: string;
|
|
14
|
+
type: 'boolean';
|
|
15
|
+
};
|
|
16
|
+
export interface IndexOptions<T> {
|
|
17
|
+
body: T;
|
|
18
|
+
id: string;
|
|
19
|
+
}
|
|
20
|
+
export interface SearchOptions {
|
|
21
|
+
page?: number;
|
|
22
|
+
query: string | undefined;
|
|
23
|
+
fields: Field[];
|
|
24
|
+
/**
|
|
25
|
+
* @deprecated use `must` instead
|
|
26
|
+
*/
|
|
27
|
+
filter?: Filter[];
|
|
28
|
+
must?: Filter[];
|
|
29
|
+
must_not?: Filter[];
|
|
30
|
+
}
|
|
31
|
+
export {};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { IndexOptions, SearchOptions } from '.';
|
|
2
|
+
export declare const memorySearchTheBadWay: <T>({ loadAllDocumentsTheBadWay }: {
|
|
3
|
+
loadAllDocumentsTheBadWay: () => Promise<T[]>;
|
|
4
|
+
}) => {
|
|
5
|
+
ensureIndexCreated: () => Promise<undefined>;
|
|
6
|
+
index: (_options: IndexOptions<T>) => Promise<undefined>;
|
|
7
|
+
search: (options: SearchOptions) => Promise<{
|
|
8
|
+
items: T[];
|
|
9
|
+
pageSize: number;
|
|
10
|
+
currentPage: number;
|
|
11
|
+
totalItems: number;
|
|
12
|
+
totalPages: number;
|
|
13
|
+
}>;
|
|
14
|
+
};
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.memorySearchTheBadWay = void 0;
|
|
4
|
+
const __1 = require("../..");
|
|
5
|
+
const errors_1 = require("../../errors");
|
|
6
|
+
const guards_1 = require("../../guards");
|
|
7
|
+
const MIN_MATCH = 0.5;
|
|
8
|
+
const MAX_RESULTS = 10;
|
|
9
|
+
var MatchType;
|
|
10
|
+
(function (MatchType) {
|
|
11
|
+
MatchType[MatchType["Must"] = 0] = "Must";
|
|
12
|
+
MatchType[MatchType["MustNot"] = 1] = "MustNot";
|
|
13
|
+
})(MatchType || (MatchType = {}));
|
|
14
|
+
const resolveField = (document, field) => field.key.toString().split('.').reduce((result, key) => result[key], document);
|
|
15
|
+
const memorySearchTheBadWay = ({ loadAllDocumentsTheBadWay }) => {
|
|
16
|
+
return {
|
|
17
|
+
ensureIndexCreated: async () => undefined,
|
|
18
|
+
index: async (_options) => undefined,
|
|
19
|
+
search: async (options) => {
|
|
20
|
+
const getFieldType = (field) => { var _a; return (_a = options.fields.find(f => f.key == field.key)) === null || _a === void 0 ? void 0 : _a.type; };
|
|
21
|
+
const results = (await loadAllDocumentsTheBadWay())
|
|
22
|
+
.map(document => {
|
|
23
|
+
let weight = 0;
|
|
24
|
+
const matchFilters = (filters, mustMatch) => {
|
|
25
|
+
for (const field of filters) {
|
|
26
|
+
const docValues = (0, __1.coerceArray)(resolveField(document, field));
|
|
27
|
+
const coerceValue = getFieldType(field) === 'boolean'
|
|
28
|
+
? (input) => {
|
|
29
|
+
if ([true, 'true', '1', 1].includes(input)) {
|
|
30
|
+
return true;
|
|
31
|
+
}
|
|
32
|
+
if ([false, 'false', '0', 0, ''].includes(input)) {
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
throw new errors_1.InvalidRequestError('input is not a valid boolean filter');
|
|
36
|
+
}
|
|
37
|
+
: (x) => x;
|
|
38
|
+
const hasMatch = (0, __1.coerceArray)(field.value).map(coerceValue).some(v => docValues.includes(v));
|
|
39
|
+
if ((mustMatch === MatchType.Must && !hasMatch) || (mustMatch === MatchType.MustNot && hasMatch)) {
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return true;
|
|
44
|
+
};
|
|
45
|
+
if (options.query !== undefined) {
|
|
46
|
+
for (const field of options.fields) {
|
|
47
|
+
if (field.type !== undefined && field.type !== 'text') {
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
const value = resolveField(document, field);
|
|
51
|
+
if (value === undefined || value === null) {
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
if (typeof value === 'string') {
|
|
55
|
+
if (value.toUpperCase().indexOf(options.query.toUpperCase()) !== -1) {
|
|
56
|
+
weight += (1 * field.weight);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
throw new Error(`invalid value type when searching in field ${field.key.toString()}`);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
const { must_not } = options;
|
|
65
|
+
const must = 'filter' in options ? options.filter : options.must;
|
|
66
|
+
if ((must === null || must === void 0 ? void 0 : must.length) && !matchFilters(must, MatchType.Must)) {
|
|
67
|
+
return undefined;
|
|
68
|
+
}
|
|
69
|
+
if ((must_not === null || must_not === void 0 ? void 0 : must_not.length) && !matchFilters(must_not, MatchType.MustNot)) {
|
|
70
|
+
return undefined;
|
|
71
|
+
}
|
|
72
|
+
return { document, weight };
|
|
73
|
+
})
|
|
74
|
+
.filter(guards_1.isDefined)
|
|
75
|
+
.filter(r => !options.query || r.weight >= MIN_MATCH);
|
|
76
|
+
results.sort((a, b) => b.weight - a.weight);
|
|
77
|
+
const page = options.page || 1;
|
|
78
|
+
const offset = (page - 1) * MAX_RESULTS;
|
|
79
|
+
return {
|
|
80
|
+
items: results.slice(offset, offset + MAX_RESULTS).map(r => r.document),
|
|
81
|
+
pageSize: MAX_RESULTS,
|
|
82
|
+
currentPage: page,
|
|
83
|
+
totalItems: results.length,
|
|
84
|
+
totalPages: Math.ceil(results.length / MAX_RESULTS)
|
|
85
|
+
};
|
|
86
|
+
},
|
|
87
|
+
};
|
|
88
|
+
};
|
|
89
|
+
exports.memorySearchTheBadWay = memorySearchTheBadWay;
|