@natlibfi/melinda-record-matching 4.3.2-alpha.3 → 4.3.2-alpha.5

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.
@@ -0,0 +1,150 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.CandidateSearchError = void 0;
7
+ exports.default = _default;
8
+ var _debug = _interopRequireDefault(require("debug"));
9
+ var _sruClient = _interopRequireWildcard(require("@natlibfi/sru-client"));
10
+ function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
11
+ function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
12
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
13
+ /**
14
+ *
15
+ * @licstart The following is the entire license notice for the JavaScript code in this file.
16
+ *
17
+ * Melinda record matching modules for Javascript
18
+ *
19
+ * Copyright (C) 2023 University Of Helsinki (The National Library Of Finland)
20
+ *
21
+ * This file is part of melinda-record-matching-js
22
+ *
23
+ * melinda-record-matching-js program is free software: you can redistribute it and/or modify
24
+ * it under the terms of the GNU Lesser General Public License as
25
+ * published by the Free Software Foundation, either version 3 of the
26
+ * License, or (at your option) any later version.
27
+ *
28
+ * melinda-record-matching-js is distributed in the hope that it will be useful,
29
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
30
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31
+ * GNU Lesser General Public License for more details.
32
+ *
33
+ * You should have received a copy of the GNU Affero General Public License
34
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
35
+ *
36
+ * @licend The above is the entire license notice
37
+ * for the JavaScript code in this file.
38
+ *
39
+ */
40
+
41
+ class CandidateSearchError extends Error {}
42
+ exports.CandidateSearchError = CandidateSearchError;
43
+ async function _default({
44
+ url,
45
+ queryList,
46
+ queryListType,
47
+ maxCandidates = 50
48
+ }) {
49
+ const debug = (0, _debug.default)('@natlibfi/melinda-record-matching:candidate-search:choose-queries');
50
+ const debugData = debug.extend('data');
51
+ const debugDev = debug.extend('dev');
52
+ debugData(`Url: ${url}`);
53
+ debugData(`QueryList: ${queryList}`);
54
+ debugData(`queryListType: ${queryListType}`);
55
+ const client = (0, _sruClient.default)({
56
+ url,
57
+ maxRecordsPerRequest: 0,
58
+ version: '2.0',
59
+ retrieveAll: false
60
+ });
61
+ debugDev(`QueryList (type: ${queryListType}) ${JSON.stringify(queryList)}`);
62
+ try {
63
+ const {
64
+ queriesWithTotals
65
+ } = await getQueryTotals({
66
+ queryList,
67
+ queryOffset: 0,
68
+ queriesWithTotals: []
69
+ });
70
+ debugDev(`QueryResult: ${JSON.stringify(queriesWithTotals)}`);
71
+ const filteredQueryResult = filterQueryResult({
72
+ queriesWithTotals,
73
+ maxCandidates
74
+ });
75
+ debugDev(`filteredQueryResult: ${JSON.stringify(filteredQueryResult)}`);
76
+ return filteredQueryResult;
77
+ } catch (err) {
78
+ throw new CandidateSearchError(err);
79
+ }
80
+ async function getQueryTotals({
81
+ queryList,
82
+ queryOffset = 0,
83
+ queriesWithTotals = []
84
+ }) {
85
+ const query = queryList[queryOffset];
86
+ debug(`Running query ${JSON.stringify(query)} (${queryOffset}) for total`);
87
+ if (query) {
88
+ const {
89
+ total
90
+ } = await retrieveTotal();
91
+ const newQueriesWithTotals = [...queriesWithTotals, {
92
+ query,
93
+ total
94
+ }];
95
+ debug(`Query ${queryOffset} ${query} done.`);
96
+ debug(`There are (${queryList.length - (queryOffset + 1)} queries left)`);
97
+ return getQueryTotals({
98
+ queryList,
99
+ queryOffset: queryOffset + 1,
100
+ queriesWithTotals: newQueriesWithTotals
101
+ });
102
+ }
103
+ debug(`All ${queryList.length} queries done, there's no query for ${queryOffset}`);
104
+ return {
105
+ queriesWithTotals
106
+ };
107
+ function retrieveTotal() {
108
+ return new Promise((resolve, reject) => {
109
+ // eslint-disable-next-line functional/no-let
110
+ let totalRecords = 0;
111
+ debug(`Searching total amount of candidates for query: ${query}`);
112
+ client.searchRetrieve(query).on('error', err => {
113
+ // eslint-disable-next-line functional/no-conditional-statements
114
+ if (err instanceof _sruClient.SruSearchError) {
115
+ debug(`SRU SruSearchError for query: ${query}: ${err}`);
116
+ reject(new CandidateSearchError(`SRU SruSearchError for query: ${query}: ${err}`));
117
+ }
118
+ debug(`SRU error for query: ${query}: ${err}`);
119
+ reject(new CandidateSearchError(`SRU error for query: ${query}: ${err}`));
120
+ }).on('total', total => {
121
+ debug(`Got total: ${total}`);
122
+ totalRecords += total;
123
+ }).on('end', () => {
124
+ try {
125
+ resolve({
126
+ total: totalRecords
127
+ });
128
+ } catch (err) {
129
+ debug(`Error caught on END`);
130
+ reject(err);
131
+ }
132
+ }).on('record', () => {
133
+ debugDev(`RECORD: We should no get records here`);
134
+ });
135
+ });
136
+ }
137
+ }
138
+ function filterQueryResult({
139
+ queriesWithTotals,
140
+ maxCandidates
141
+ }) {
142
+ debug(`Filtering queries (${queriesWithTotals.length}), maxCandidates: ${maxCandidates}`);
143
+ debugData(`${JSON.stringify(queriesWithTotals)}`);
144
+ // Drop queries where total result is 0 or greater than given maxCandidates
145
+ const filteredQueryResult = queriesWithTotals.filter(queryWithTotal => queryWithTotal.total !== 0 && queryWithTotal.total < maxCandidates);
146
+ debugData(`${JSON.stringify(filteredQueryResult)}`);
147
+ return filteredQueryResult;
148
+ }
149
+ }
150
+ //# sourceMappingURL=choose-queries.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"choose-queries.js","names":["_debug","_interopRequireDefault","require","_sruClient","_interopRequireWildcard","_getRequireWildcardCache","e","WeakMap","r","t","__esModule","default","has","get","n","__proto__","a","Object","defineProperty","getOwnPropertyDescriptor","u","prototype","hasOwnProperty","call","i","set","obj","CandidateSearchError","Error","exports","_default","url","queryList","queryListType","maxCandidates","debug","createDebugLogger","debugData","extend","debugDev","client","createClient","maxRecordsPerRequest","version","retrieveAll","JSON","stringify","queriesWithTotals","getQueryTotals","queryOffset","filteredQueryResult","filterQueryResult","err","query","total","retrieveTotal","newQueriesWithTotals","length","Promise","resolve","reject","totalRecords","searchRetrieve","on","SruSearchError","filter","queryWithTotal"],"sources":["../../src/candidate-search/choose-queries.js"],"sourcesContent":["/**\n*\n* @licstart The following is the entire license notice for the JavaScript code in this file.\n*\n* Melinda record matching modules for Javascript\n*\n* Copyright (C) 2023 University Of Helsinki (The National Library Of Finland)\n*\n* This file is part of melinda-record-matching-js\n*\n* melinda-record-matching-js program is free software: you can redistribute it and/or modify\n* it under the terms of the GNU Lesser General Public License as\n* published by the Free Software Foundation, either version 3 of the\n* License, or (at your option) any later version.\n*\n* melinda-record-matching-js is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n* GNU Lesser General Public License for more details.\n*\n* You should have received a copy of the GNU Affero General Public License\n* along with this program. If not, see <http://www.gnu.org/licenses/>.\n*\n* @licend The above is the entire license notice\n* for the JavaScript code in this file.\n*\n*/\n\nimport createDebugLogger from 'debug';\nimport createClient, {SruSearchError} from '@natlibfi/sru-client';\n\nexport class CandidateSearchError extends Error {}\n\nexport default async function ({url, queryList, queryListType, maxCandidates = 50}) {\n\n const debug = createDebugLogger('@natlibfi/melinda-record-matching:candidate-search:choose-queries');\n const debugData = debug.extend('data');\n const debugDev = debug.extend('dev');\n\n debugData(`Url: ${url}`);\n debugData(`QueryList: ${queryList}`);\n debugData(`queryListType: ${queryListType}`);\n\n const client = createClient({\n url,\n maxRecordsPerRequest: 0,\n version: '2.0',\n retrieveAll: false\n });\n\n debugDev(`QueryList (type: ${queryListType}) ${JSON.stringify(queryList)}`);\n try {\n const {queriesWithTotals} = await getQueryTotals({queryList, queryOffset: 0, queriesWithTotals: []});\n debugDev(`QueryResult: ${JSON.stringify(queriesWithTotals)}`);\n const filteredQueryResult = filterQueryResult({queriesWithTotals, maxCandidates});\n debugDev(`filteredQueryResult: ${JSON.stringify(filteredQueryResult)}`);\n return filteredQueryResult;\n } catch (err) {\n throw new CandidateSearchError(err);\n }\n\n async function getQueryTotals({queryList, queryOffset = 0, queriesWithTotals = []}) {\n\n const query = queryList[queryOffset];\n debug(`Running query ${JSON.stringify(query)} (${queryOffset}) for total`);\n\n if (query) {\n const {total} = await retrieveTotal();\n\n const newQueriesWithTotals = [...queriesWithTotals, {query, total}];\n debug(`Query ${queryOffset} ${query} done.`);\n debug(`There are (${queryList.length - (queryOffset + 1)} queries left)`);\n return getQueryTotals({queryList, queryOffset: queryOffset + 1, queriesWithTotals: newQueriesWithTotals});\n }\n\n debug(`All ${queryList.length} queries done, there's no query for ${queryOffset}`);\n return {queriesWithTotals};\n\n function retrieveTotal() {\n return new Promise((resolve, reject) => {\n // eslint-disable-next-line functional/no-let\n let totalRecords = 0;\n\n debug(`Searching total amount of candidates for query: ${query}`);\n\n client.searchRetrieve(query)\n .on('error', err => {\n // eslint-disable-next-line functional/no-conditional-statements\n if (err instanceof SruSearchError) {\n debug(`SRU SruSearchError for query: ${query}: ${err}`);\n reject(new CandidateSearchError(`SRU SruSearchError for query: ${query}: ${err}`));\n }\n debug(`SRU error for query: ${query}: ${err}`);\n reject(new CandidateSearchError(`SRU error for query: ${query}: ${err}`));\n })\n .on('total', total => {\n debug(`Got total: ${total}`);\n totalRecords += total;\n })\n .on('end', () => {\n try {\n resolve({total: totalRecords});\n } catch (err) {\n debug(`Error caught on END`);\n reject(err);\n }\n })\n .on('record', () => {\n debugDev(`RECORD: We should no get records here`);\n });\n });\n }\n }\n function filterQueryResult({queriesWithTotals, maxCandidates}) {\n debug(`Filtering queries (${queriesWithTotals.length}), maxCandidates: ${maxCandidates}`);\n debugData(`${JSON.stringify(queriesWithTotals)}`);\n // Drop queries where total result is 0 or greater than given maxCandidates\n const filteredQueryResult = queriesWithTotals.filter((queryWithTotal) => queryWithTotal.total !== 0 && queryWithTotal.total < maxCandidates);\n debugData(`${JSON.stringify(filteredQueryResult)}`);\n return filteredQueryResult;\n }\n\n}\n"],"mappings":"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"}
@@ -16,6 +16,7 @@ var _marcRecord = require("@natlibfi/marc-record");
16
16
  var _marcRecordSerializers = require("@natlibfi/marc-record-serializers");
17
17
  var _queryList = _interopRequireWildcard(require("./query-list"));
18
18
  var _melindaCommons = require("@natlibfi/melinda-commons");
19
+ var _chooseQueries = _interopRequireDefault(require("./choose-queries"));
19
20
  function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
20
21
  function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
21
22
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
@@ -51,7 +52,7 @@ class CandidateSearchError extends Error {}
51
52
 
52
53
  // serverMaxResults : maximum size of total search result available from the server, defaults to Aleph's 20000
53
54
  exports.CandidateSearchError = CandidateSearchError;
54
- var _default = ({
55
+ var _default = async ({
55
56
  record,
56
57
  searchSpec,
57
58
  url,
@@ -76,6 +77,16 @@ var _default = ({
76
77
  const queryListResult = (0, _queryList.default)(record, searchSpec);
77
78
  const queryList = queryListResult[0]?.queryList ? queryListResult[0].queryList : queryListResult;
78
79
  const queryListType = queryListResult[0]?.queryListType ? queryListResult[0].queryListType : undefined;
80
+
81
+ // if generateQueryList errored we should throw 422
82
+ if (queryList.length === 0) {
83
+ debug(`Empty list`);
84
+ throw new CandidateSearchError(`Generated query list contains no queries`);
85
+ }
86
+ if (queryListType && queryListType !== 'alternates') {
87
+ debug(`Unknown queryListType`);
88
+ throw new CandidateSearchError(`Generated query list has invalid type`);
89
+ }
79
90
  const client = (0, _sruClient.default)({
80
91
  url,
81
92
  maxRecordsPerRequest: adjustedMaxRecordsPerRequest,
@@ -83,30 +94,29 @@ var _default = ({
83
94
  retrieveAll: false
84
95
  });
85
96
  debug(`Searching matches for ${inputRecordId}`);
86
- const chosenQueryList = choseQueries(queryList, queryListType);
87
-
88
- // eslint-disable-next-line require-await
89
- function choseQueries(queryList, queryListType) {
97
+ const chosenQueryList = await filterQueryList({
98
+ queryList,
99
+ queryListType
100
+ });
101
+ debug(`Chosen queries: ${JSON.stringify(chosenQueryList)}`);
102
+ async function filterQueryList({
103
+ queryList,
104
+ queryListType,
105
+ maxCandidates
106
+ }) {
90
107
  debug(`Generated queryList (type: ${queryListType}) ${JSON.stringify(queryList)}`);
91
-
92
- // if generateQueryList errored we should throw 422
93
- if (queryList.length === 0) {
94
- throw new CandidateSearchError(`Generated query list contains no queries`);
95
- }
96
- if (queryListType && queryListType !== 'alternates') {
97
- throw new CandidateSearchError(`Generated query list has invalid type`);
98
- }
99
108
  if (queryListType === 'alternates' && queryList.length > 1) {
100
- //const [query] = queryList;
101
- //const totalResult = await retrieveTotal(query);
102
- // const totalsForQueries = queryList.map(query => retrieveTotal(query));
103
- //debug(`${JSON.stringify(totalResult)}`);
104
- return queryList;
105
- //return [];
109
+ const queryListResult = await (0, _chooseQueries.default)({
110
+ url,
111
+ queryList,
112
+ queryListType,
113
+ maxCandidates
114
+ });
115
+ debug(`queryListResult: ${JSON.stringify(queryListResult)}`);
116
+ return queryListResult.map(elem => elem.query);
106
117
  }
107
118
  return queryList;
108
119
  }
109
-
110
120
  // state.totalRecords : amount of candidate records available to the current query (undefined, if there was no queries left)
111
121
  // state.query : current query (undefined if there was no queries left)
112
122
  // state.searchCounter : sequence for current search for current query (undefined, if there we no queries left)
@@ -115,8 +125,12 @@ var _default = ({
115
125
  // state.queryCounter : sequence for current query
116
126
  // state.maxedQueries : queries that resulted in more than serverMaxResults hits
117
127
 
128
+ return {
129
+ search
130
+ };
131
+
118
132
  // eslint-disable-next-line max-statements
119
- return async ({
133
+ async function search({
120
134
  queryOffset = 0,
121
135
  resultSetOffset = 1,
122
136
  totalRecords = 0,
@@ -124,13 +138,7 @@ var _default = ({
124
138
  queryCandidateCounter = 0,
125
139
  queryCounter = 0,
126
140
  maxedQueries = []
127
- }) => {
128
- /*
129
- if (queryListType === 'alternates') {
130
- debug('Alternates - stop here');
131
- return {records: [], failures: [], queriesLeft: 0, queryCounter, maxedQueries};
132
- }
133
- */
141
+ }) {
134
142
  const query = chosenQueryList[queryOffset];
135
143
  debug(`Running query ${JSON.stringify(query)} (${queryOffset})`);
136
144
  if (query) {
@@ -259,31 +267,7 @@ var _default = ({
259
267
  });
260
268
  });
261
269
  }
262
- };
263
-
264
- /*
265
- async function retrieveTotal(query) {
266
- debug(`Searching for candidateTotals with query: ${query}`);
267
- totalClient.searchRetrieve(query)
268
- .on('error', err => {
269
- // eslint-disable-next-line functional/no-conditional-statements
270
- if (err instanceof SruSearchError) {
271
- debug(`SRU SruSearchError for query: ${query}: ${err}`);
272
- throw new CandidateSearchError(`SRU SruSearchError for getting total for query: ${query}: ${err}`);
273
- }
274
- debug(`SRU error for query: ${query}: ${err}`);
275
- throw new CandidateSearchError(`SRU error for getting total for query: ${query}: ${err}`);
276
- })
277
- .on('total', total => {
278
- debug(`Got total: ${total}`);
279
- return {query, total};
280
- })
281
- .on('end', end => {
282
- debug(`End ${JSON.stringify(end)}`);
283
- });
284
270
  }
285
- */
286
-
287
271
  function checkMaxedQuery(query, total, serverMaxResult) {
288
272
  if (total >= serverMaxResult) {
289
273
  debug(`WARNING: Query ${query} resulted in ${total} hits which meets the serverMaxResult (${serverMaxResult}) `);
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["_debug","_interopRequireDefault","require","_sruClient","_interopRequireWildcard","_marcRecord","_marcRecordSerializers","_queryList","_melindaCommons","_getRequireWildcardCache","e","WeakMap","r","t","__esModule","default","has","get","n","__proto__","a","Object","defineProperty","getOwnPropertyDescriptor","u","prototype","hasOwnProperty","call","i","set","obj","CandidateSearchError","Error","exports","_default","record","searchSpec","url","maxCandidates","maxRecordsPerRequest","serverMaxResult","MarcRecord","setValidationOptions","subfieldValues","debug","createDebugLogger","debugData","extend","JSON","stringify","adjustedMaxRecordsPerRequest","inputRecordId","getRecordId","queryListResult","generateQueryList","queryList","queryListType","undefined","client","createClient","version","retrieveAll","chosenQueryList","choseQueries","length","queryOffset","resultSetOffset","totalRecords","searchCounter","queryCandidateCounter","queryCounter","maxedQueries","query","records","failures","nextOffset","total","retrieveRecords","newTotalRecords","newQueryCounter","newSearchCounter","newQueryCandidateCounter","maxedQuery","checkMaxedQuery","newMaxedQueries","concat","queriesLeft","Promise","resolve","reject","promises","searchRetrieve","startRecord","on","err","SruSearchError","recordPromises","allSettled","filtered","filter","status","map","value","reason","payload","recordXML","push","handleRecord","recordMarc","MARCXML","from","recordId","id","idFromXML","getRecordIdFromXML","message","MatchingError","data","field"],"sources":["../../src/candidate-search/index.js"],"sourcesContent":["/**\n*\n* @licstart The following is the entire license notice for the JavaScript code in this file.\n*\n* Melinda record matching modules for Javascript\n*\n* Copyright (C) 2020-2023 University Of Helsinki (The National Library Of Finland)\n*\n* This file is part of melinda-record-matching-js\n*\n* melinda-record-matching-js program is free software: you can redistribute it and/or modify\n* it under the terms of the GNU Lesser General Public License as\n* published by the Free Software Foundation, either version 3 of the\n* License, or (at your option) any later version.\n*\n* melinda-record-matching-js is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n* GNU Lesser General Public License for more details.\n*\n* You should have received a copy of the GNU Affero General Public License\n* along with this program. If not, see <http://www.gnu.org/licenses/>.\n*\n* @licend The above is the entire license notice\n* for the JavaScript code in this file.\n*\n*/\n\nimport createDebugLogger from 'debug';\nimport createClient, {SruSearchError} from '@natlibfi/sru-client';\nimport {MarcRecord} from '@natlibfi/marc-record';\nimport {MARCXML} from '@natlibfi/marc-record-serializers';\nimport generateQueryList from './query-list';\nimport {Error as MatchingError} from '@natlibfi/melinda-commons';\n\nexport {searchTypes} from './query-list';\n\nexport class CandidateSearchError extends Error {}\n\n// serverMaxResults : maximum size of total search result available from the server, defaults to Aleph's 20000\n\nexport default ({record, searchSpec, url, maxCandidates, maxRecordsPerRequest = 50, serverMaxResult = 20000}) => {\n MarcRecord.setValidationOptions({subfieldValues: false});\n\n const debug = createDebugLogger('@natlibfi/melinda-record-matching:candidate-search');\n const debugData = debug.extend('data');\n\n debugData(`SearchSpec: ${JSON.stringify(searchSpec)}`);\n debugData(`Url: ${url}`);\n debugData(`MaxRecordsPerRequest ${maxRecordsPerRequest}`);\n debugData(`ServerMaxResult: ${serverMaxResult}`);\n debugData(`MaxCandidates: ${maxCandidates}`);\n\n // Do not retrieve more candidates than defined in maxCandidates\n const adjustedMaxRecordsPerRequest = maxRecordsPerRequest >= maxCandidates ? maxCandidates : maxRecordsPerRequest;\n\n const inputRecordId = getRecordId(record);\n const queryListResult = generateQueryList(record, searchSpec);\n const queryList = queryListResult[0]?.queryList ? queryListResult[0].queryList : queryListResult;\n const queryListType = queryListResult[0]?.queryListType ? queryListResult[0].queryListType : undefined;\n\n const client = createClient({\n url,\n maxRecordsPerRequest: adjustedMaxRecordsPerRequest,\n version: '2.0',\n retrieveAll: false\n });\n\n debug(`Searching matches for ${inputRecordId}`);\n const chosenQueryList = choseQueries(queryList, queryListType);\n\n // eslint-disable-next-line require-await\n function choseQueries(queryList, queryListType) {\n debug(`Generated queryList (type: ${queryListType}) ${JSON.stringify(queryList)}`);\n\n // if generateQueryList errored we should throw 422\n if (queryList.length === 0) {\n throw new CandidateSearchError(`Generated query list contains no queries`);\n }\n\n if (queryListType && queryListType !== 'alternates') {\n throw new CandidateSearchError(`Generated query list has invalid type`);\n }\n\n if (queryListType === 'alternates' && queryList.length > 1) {\n //const [query] = queryList;\n //const totalResult = await retrieveTotal(query);\n // const totalsForQueries = queryList.map(query => retrieveTotal(query));\n //debug(`${JSON.stringify(totalResult)}`);\n return queryList;\n //return [];\n }\n return queryList;\n }\n\n\n // state.totalRecords : amount of candidate records available to the current query (undefined, if there was no queries left)\n // state.query : current query (undefined if there was no queries left)\n // state.searchCounter : sequence for current search for current query (undefined, if there we no queries left)\n // state.queryCandidateCounter: amount of candidates (records+failures) retrieved from SRU for matching for current query, including the current record+failure set (undefined if there were no queries left)\n // state.queriesLeft : amount of queries left\n // state.queryCounter : sequence for current query\n // state.maxedQueries : queries that resulted in more than serverMaxResults hits\n\n\n // eslint-disable-next-line max-statements\n return async ({queryOffset = 0, resultSetOffset = 1, totalRecords = 0, searchCounter = 0, queryCandidateCounter = 0, queryCounter = 0, maxedQueries = []}) => {\n\n /*\n if (queryListType === 'alternates') {\n debug('Alternates - stop here');\n return {records: [], failures: [], queriesLeft: 0, queryCounter, maxedQueries};\n }\n */\n const query = chosenQueryList[queryOffset];\n debug(`Running query ${JSON.stringify(query)} (${queryOffset})`);\n\n if (query) {\n const {records, failures, nextOffset, total} = await retrieveRecords();\n\n // If resultSetOffset === 1 this is the first search for the current query\n debugData(`ResultSetOffset: ${resultSetOffset}`);\n const newTotalRecords = resultSetOffset === 1 ? total : totalRecords;\n const newQueryCounter = resultSetOffset === 1 ? queryCounter + 1 : queryCounter;\n const newSearchCounter = resultSetOffset === 1 ? 1 : searchCounter + 1;\n const newQueryCandidateCounter = resultSetOffset === 1 ? records.length + failures.length : queryCandidateCounter + records.length + failures.length;\n\n const maxedQuery = resultSetOffset === 1 ? checkMaxedQuery(query, total, serverMaxResult) : undefined;\n const newMaxedQueries = maxedQuery ? maxedQueries.concat(maxedQuery) : maxedQueries;\n\n if (typeof nextOffset === 'number') {\n debug(`Next search will be for query ${queryOffset} ${query}, starting from record ${nextOffset}`);\n return {records, failures, queryOffset, resultSetOffset: nextOffset, queriesLeft: queryList.length - (queryOffset + 1), totalRecords: newTotalRecords, query, searchCounter: newSearchCounter, queryCandidateCounter: newQueryCandidateCounter, queryCounter: newQueryCounter, maxedQueries: newMaxedQueries};\n }\n debug(`Query ${queryOffset} ${query} done.`);\n debug(`There are (${queryList.length - (queryOffset + 1)} queries left)`);\n return {records, failures, queryOffset: queryOffset + 1, queriesLeft: queryList.length - (queryOffset + 1), totalRecords: newTotalRecords, query, searchCounter: newSearchCounter, queryCandidateCounter: newQueryCandidateCounter, queryCounter: newQueryCounter, maxedQueries: newMaxedQueries};\n }\n\n debug(`All ${queryList.length} queries done, there's no query for ${queryOffset}`);\n return {records: [], failures: [], queriesLeft: 0, queryCounter, maxedQueries};\n\n function retrieveRecords() {\n return new Promise((resolve, reject) => {\n const promises = [];\n // eslint-disable-next-line functional/no-let\n let totalRecords = 0;\n\n debug(`Searching for candidates with query: ${query} (Offset ${resultSetOffset})`);\n\n client.searchRetrieve(query, {startRecord: resultSetOffset})\n .on('error', err => {\n // eslint-disable-next-line functional/no-conditional-statements\n if (err instanceof SruSearchError) {\n debug(`SRU SruSearchError for query: ${query}: ${err}`);\n reject(new CandidateSearchError(`SRU SruSearchError for query: ${query}: ${err}`));\n }\n debug(`SRU error for query: ${query}: ${err}`);\n reject(new CandidateSearchError(`SRU error for query: ${query}: ${err}`));\n })\n .on('total', total => {\n debug(`Got total: ${total}`);\n totalRecords += total;\n })\n .on('end', async nextOffset => {\n try {\n const recordPromises = await Promise.allSettled(promises);\n debugData(`All recordPromises: ${JSON.stringify(recordPromises)}`);\n const filtered = recordPromises.filter(r => r.status === 'fulfilled').map(r => r.value);\n const failures = recordPromises.filter(r => r.status === 'rejected').map(r => ({status: r.reason.status, payload: r.reason.payload}));\n\n debug(`Found ${recordPromises.length} records`);\n debug(`Found ${filtered.length} convertable candidates`);\n debug(`Found ${failures.length} NON-convertable candidates`);\n debugData(`Converted: ${JSON.stringify(filtered)}.`);\n debugData(`Not converted: ${JSON.stringify(failures)}.`);\n\n\n resolve({nextOffset, records: filtered, failures, total: totalRecords});\n } catch (err) {\n debug(`Error caught on END`);\n reject(err);\n }\n })\n .on('record', recordXML => {\n promises.push(handleRecord()); // eslint-disable-line functional/immutable-data\n\n async function handleRecord() {\n try {\n const recordMarc = await MARCXML.from(recordXML, {subfieldValues: false});\n const recordId = getRecordId(recordMarc);\n\n return {record: recordMarc, id: recordId};\n } catch (err) {\n // What should this do?\n const idFromXML = getRecordIdFromXML(recordXML);\n debugData(`Failed converting record: ${err.message}, id: ${idFromXML}, data: ${recordXML}`);\n //return {message: `Failed converting record: ${err.message}`, id: idFromXML, data: recordXML};\n throw new MatchingError(422, {message: `Failed converting record: ${err.message}`, id: idFromXML || '000000000', data: recordXML});\n }\n }\n });\n });\n }\n };\n\n /*\n async function retrieveTotal(query) {\n debug(`Searching for candidateTotals with query: ${query}`);\n totalClient.searchRetrieve(query)\n .on('error', err => {\n // eslint-disable-next-line functional/no-conditional-statements\n if (err instanceof SruSearchError) {\n debug(`SRU SruSearchError for query: ${query}: ${err}`);\n throw new CandidateSearchError(`SRU SruSearchError for getting total for query: ${query}: ${err}`);\n }\n debug(`SRU error for query: ${query}: ${err}`);\n throw new CandidateSearchError(`SRU error for getting total for query: ${query}: ${err}`);\n })\n .on('total', total => {\n debug(`Got total: ${total}`);\n return {query, total};\n })\n .on('end', end => {\n debug(`End ${JSON.stringify(end)}`);\n });\n }\n*/\n\n\n function checkMaxedQuery(query, total, serverMaxResult) {\n if (total >= serverMaxResult) {\n debug(`WARNING: Query ${query} resulted in ${total} hits which meets the serverMaxResult (${serverMaxResult}) `);\n return query;\n }\n }\n\n function getRecordId(record) {\n const [field] = record.get(/^001$/u);\n return field ? field.value : '';\n }\n\n function getRecordIdFromXML(recordXML) {\n //<controlfield tag=\\\"001\\\">015376846</controlfield\n debug(`Cannot yet find possible database record id from recordXML (length ${recordXML.length})`);\n return undefined;\n }\n\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["_debug","_interopRequireDefault","require","_sruClient","_interopRequireWildcard","_marcRecord","_marcRecordSerializers","_queryList","_melindaCommons","_chooseQueries","_getRequireWildcardCache","e","WeakMap","r","t","__esModule","default","has","get","n","__proto__","a","Object","defineProperty","getOwnPropertyDescriptor","u","prototype","hasOwnProperty","call","i","set","obj","CandidateSearchError","Error","exports","_default","record","searchSpec","url","maxCandidates","maxRecordsPerRequest","serverMaxResult","MarcRecord","setValidationOptions","subfieldValues","debug","createDebugLogger","debugData","extend","JSON","stringify","adjustedMaxRecordsPerRequest","inputRecordId","getRecordId","queryListResult","generateQueryList","queryList","queryListType","undefined","length","client","createClient","version","retrieveAll","chosenQueryList","filterQueryList","chooseQueries","map","elem","query","search","queryOffset","resultSetOffset","totalRecords","searchCounter","queryCandidateCounter","queryCounter","maxedQueries","records","failures","nextOffset","total","retrieveRecords","newTotalRecords","newQueryCounter","newSearchCounter","newQueryCandidateCounter","maxedQuery","checkMaxedQuery","newMaxedQueries","concat","queriesLeft","Promise","resolve","reject","promises","searchRetrieve","startRecord","on","err","SruSearchError","recordPromises","allSettled","filtered","filter","status","value","reason","payload","recordXML","push","handleRecord","recordMarc","MARCXML","from","recordId","id","idFromXML","getRecordIdFromXML","message","MatchingError","data","field"],"sources":["../../src/candidate-search/index.js"],"sourcesContent":["/**\n*\n* @licstart The following is the entire license notice for the JavaScript code in this file.\n*\n* Melinda record matching modules for Javascript\n*\n* Copyright (C) 2020-2023 University Of Helsinki (The National Library Of Finland)\n*\n* This file is part of melinda-record-matching-js\n*\n* melinda-record-matching-js program is free software: you can redistribute it and/or modify\n* it under the terms of the GNU Lesser General Public License as\n* published by the Free Software Foundation, either version 3 of the\n* License, or (at your option) any later version.\n*\n* melinda-record-matching-js is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n* GNU Lesser General Public License for more details.\n*\n* You should have received a copy of the GNU Affero General Public License\n* along with this program. If not, see <http://www.gnu.org/licenses/>.\n*\n* @licend The above is the entire license notice\n* for the JavaScript code in this file.\n*\n*/\n\nimport createDebugLogger from 'debug';\nimport createClient, {SruSearchError} from '@natlibfi/sru-client';\nimport {MarcRecord} from '@natlibfi/marc-record';\nimport {MARCXML} from '@natlibfi/marc-record-serializers';\nimport generateQueryList from './query-list';\nimport {Error as MatchingError} from '@natlibfi/melinda-commons';\nimport chooseQueries from './choose-queries';\n\nexport {searchTypes} from './query-list';\n\nexport class CandidateSearchError extends Error {}\n\n// serverMaxResults : maximum size of total search result available from the server, defaults to Aleph's 20000\n\nexport default async ({record, searchSpec, url, maxCandidates, maxRecordsPerRequest = 50, serverMaxResult = 20000}) => {\n MarcRecord.setValidationOptions({subfieldValues: false});\n\n const debug = createDebugLogger('@natlibfi/melinda-record-matching:candidate-search');\n const debugData = debug.extend('data');\n\n debugData(`SearchSpec: ${JSON.stringify(searchSpec)}`);\n debugData(`Url: ${url}`);\n debugData(`MaxRecordsPerRequest ${maxRecordsPerRequest}`);\n debugData(`ServerMaxResult: ${serverMaxResult}`);\n debugData(`MaxCandidates: ${maxCandidates}`);\n\n // Do not retrieve more candidates than defined in maxCandidates\n const adjustedMaxRecordsPerRequest = maxRecordsPerRequest >= maxCandidates ? maxCandidates : maxRecordsPerRequest;\n\n const inputRecordId = getRecordId(record);\n const queryListResult = generateQueryList(record, searchSpec);\n const queryList = queryListResult[0]?.queryList ? queryListResult[0].queryList : queryListResult;\n const queryListType = queryListResult[0]?.queryListType ? queryListResult[0].queryListType : undefined;\n\n // if generateQueryList errored we should throw 422\n if (queryList.length === 0) {\n debug(`Empty list`);\n throw new CandidateSearchError(`Generated query list contains no queries`);\n }\n if (queryListType && queryListType !== 'alternates') {\n debug(`Unknown queryListType`);\n throw new CandidateSearchError(`Generated query list has invalid type`);\n }\n\n const client = createClient({\n url,\n maxRecordsPerRequest: adjustedMaxRecordsPerRequest,\n version: '2.0',\n retrieveAll: false\n });\n\n debug(`Searching matches for ${inputRecordId}`);\n const chosenQueryList = await filterQueryList({queryList, queryListType});\n debug(`Chosen queries: ${JSON.stringify(chosenQueryList)}`);\n\n async function filterQueryList({queryList, queryListType, maxCandidates}) {\n debug(`Generated queryList (type: ${queryListType}) ${JSON.stringify(queryList)}`);\n\n if (queryListType === 'alternates' && queryList.length > 1) {\n const queryListResult = await chooseQueries({url, queryList, queryListType, maxCandidates});\n debug(`queryListResult: ${JSON.stringify(queryListResult)}`);\n return queryListResult.map(elem => elem.query);\n }\n return queryList;\n }\n // state.totalRecords : amount of candidate records available to the current query (undefined, if there was no queries left)\n // state.query : current query (undefined if there was no queries left)\n // state.searchCounter : sequence for current search for current query (undefined, if there we no queries left)\n // state.queryCandidateCounter: amount of candidates (records+failures) retrieved from SRU for matching for current query, including the current record+failure set (undefined if there were no queries left)\n // state.queriesLeft : amount of queries left\n // state.queryCounter : sequence for current query\n // state.maxedQueries : queries that resulted in more than serverMaxResults hits\n\n return {search};\n\n // eslint-disable-next-line max-statements\n async function search({queryOffset = 0, resultSetOffset = 1, totalRecords = 0, searchCounter = 0, queryCandidateCounter = 0, queryCounter = 0, maxedQueries = []}) {\n\n const query = chosenQueryList[queryOffset];\n debug(`Running query ${JSON.stringify(query)} (${queryOffset})`);\n\n if (query) {\n const {records, failures, nextOffset, total} = await retrieveRecords();\n\n // If resultSetOffset === 1 this is the first search for the current query\n debugData(`ResultSetOffset: ${resultSetOffset}`);\n const newTotalRecords = resultSetOffset === 1 ? total : totalRecords;\n const newQueryCounter = resultSetOffset === 1 ? queryCounter + 1 : queryCounter;\n const newSearchCounter = resultSetOffset === 1 ? 1 : searchCounter + 1;\n const newQueryCandidateCounter = resultSetOffset === 1 ? records.length + failures.length : queryCandidateCounter + records.length + failures.length;\n\n const maxedQuery = resultSetOffset === 1 ? checkMaxedQuery(query, total, serverMaxResult) : undefined;\n const newMaxedQueries = maxedQuery ? maxedQueries.concat(maxedQuery) : maxedQueries;\n\n if (typeof nextOffset === 'number') {\n debug(`Next search will be for query ${queryOffset} ${query}, starting from record ${nextOffset}`);\n return {records, failures, queryOffset, resultSetOffset: nextOffset, queriesLeft: queryList.length - (queryOffset + 1), totalRecords: newTotalRecords, query, searchCounter: newSearchCounter, queryCandidateCounter: newQueryCandidateCounter, queryCounter: newQueryCounter, maxedQueries: newMaxedQueries};\n }\n debug(`Query ${queryOffset} ${query} done.`);\n debug(`There are (${queryList.length - (queryOffset + 1)} queries left)`);\n return {records, failures, queryOffset: queryOffset + 1, queriesLeft: queryList.length - (queryOffset + 1), totalRecords: newTotalRecords, query, searchCounter: newSearchCounter, queryCandidateCounter: newQueryCandidateCounter, queryCounter: newQueryCounter, maxedQueries: newMaxedQueries};\n }\n\n debug(`All ${queryList.length} queries done, there's no query for ${queryOffset}`);\n return {records: [], failures: [], queriesLeft: 0, queryCounter, maxedQueries};\n\n function retrieveRecords() {\n return new Promise((resolve, reject) => {\n const promises = [];\n // eslint-disable-next-line functional/no-let\n let totalRecords = 0;\n\n debug(`Searching for candidates with query: ${query} (Offset ${resultSetOffset})`);\n\n client.searchRetrieve(query, {startRecord: resultSetOffset})\n .on('error', err => {\n // eslint-disable-next-line functional/no-conditional-statements\n if (err instanceof SruSearchError) {\n debug(`SRU SruSearchError for query: ${query}: ${err}`);\n reject(new CandidateSearchError(`SRU SruSearchError for query: ${query}: ${err}`));\n }\n debug(`SRU error for query: ${query}: ${err}`);\n reject(new CandidateSearchError(`SRU error for query: ${query}: ${err}`));\n })\n .on('total', total => {\n debug(`Got total: ${total}`);\n totalRecords += total;\n })\n .on('end', async nextOffset => {\n try {\n const recordPromises = await Promise.allSettled(promises);\n debugData(`All recordPromises: ${JSON.stringify(recordPromises)}`);\n const filtered = recordPromises.filter(r => r.status === 'fulfilled').map(r => r.value);\n const failures = recordPromises.filter(r => r.status === 'rejected').map(r => ({status: r.reason.status, payload: r.reason.payload}));\n\n debug(`Found ${recordPromises.length} records`);\n debug(`Found ${filtered.length} convertable candidates`);\n debug(`Found ${failures.length} NON-convertable candidates`);\n debugData(`Converted: ${JSON.stringify(filtered)}.`);\n debugData(`Not converted: ${JSON.stringify(failures)}.`);\n\n\n resolve({nextOffset, records: filtered, failures, total: totalRecords});\n } catch (err) {\n debug(`Error caught on END`);\n reject(err);\n }\n })\n .on('record', recordXML => {\n promises.push(handleRecord()); // eslint-disable-line functional/immutable-data\n\n async function handleRecord() {\n try {\n const recordMarc = await MARCXML.from(recordXML, {subfieldValues: false});\n const recordId = getRecordId(recordMarc);\n\n return {record: recordMarc, id: recordId};\n } catch (err) {\n // What should this do?\n const idFromXML = getRecordIdFromXML(recordXML);\n debugData(`Failed converting record: ${err.message}, id: ${idFromXML}, data: ${recordXML}`);\n //return {message: `Failed converting record: ${err.message}`, id: idFromXML, data: recordXML};\n throw new MatchingError(422, {message: `Failed converting record: ${err.message}`, id: idFromXML || '000000000', data: recordXML});\n }\n }\n });\n });\n }\n }\n\n function checkMaxedQuery(query, total, serverMaxResult) {\n if (total >= serverMaxResult) {\n debug(`WARNING: Query ${query} resulted in ${total} hits which meets the serverMaxResult (${serverMaxResult}) `);\n return query;\n }\n }\n\n function getRecordId(record) {\n const [field] = record.get(/^001$/u);\n return field ? field.value : '';\n }\n\n function getRecordIdFromXML(recordXML) {\n //<controlfield tag=\\\"001\\\">015376846</controlfield\n debug(`Cannot yet find possible database record id from recordXML (length ${recordXML.length})`);\n return undefined;\n }\n};\n"],"mappings":"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"}
@@ -48,6 +48,8 @@ describe('candidate-search', () => {
48
48
  reader: _fixura.READERS.JSON
49
49
  }
50
50
  });
51
+
52
+ // eslint-disable-next-line max-statements
51
53
  async function callback({
52
54
  getFixture,
53
55
  factoryOptions,
@@ -61,23 +63,38 @@ describe('candidate-search', () => {
61
63
  return;
62
64
  }
63
65
  if (expectedFactoryError) {
66
+ debug(`We're expecting an error`);
64
67
  if (expectedFactoryError.isCandidateSearchError) {
65
- (0, _chai.expect)(() => (0, _.default)({
68
+ try {
69
+ const result = (0, _.default)({
70
+ ...formatFactoryOptions(),
71
+ url
72
+ });
73
+ debug(result);
74
+ } catch (err) {
75
+ (0, _chai.expect)(err).to.equal(new _.CandidateSearchError(expectedFactoryError));
76
+ }
77
+ return;
78
+ }
79
+ try {
80
+ const result = (0, _.default)({
66
81
  ...formatFactoryOptions(),
67
82
  url
68
- })).to.throw(_.CandidateSearchError, new RegExp(expectedFactoryError, 'u'));
69
- return;
83
+ });
84
+ debug(result);
85
+ } catch (err) {
86
+ (0, _chai.expect)(err).to.equal(new Error(expectedFactoryError));
70
87
  }
71
- (0, _chai.expect)(() => (0, _.default)({
72
- ...formatFactoryOptions(),
73
- url
74
- })).to.throw(new RegExp(expectedFactoryError, 'u'));
75
88
  return;
76
89
  }
77
- const search = (0, _.default)({
90
+ const {
91
+ search
92
+ } = await (0, _.default)({
78
93
  ...formatFactoryOptions(),
79
94
  url
80
95
  });
96
+ // eslint-disable-next-line no-console
97
+ console.log(search);
81
98
  await iterate({
82
99
  searchOptions,
83
100
  expectedSearchError
@@ -1 +1 @@
1
- {"version":3,"file":"index.spec.js","names":["_chai","require","_fixura","_fixugenHttpClient","_interopRequireDefault","_marcRecord","_melindaCommons","_","_interopRequireWildcard","_debug","_getRequireWildcardCache","e","WeakMap","r","t","__esModule","default","has","get","n","__proto__","a","Object","defineProperty","getOwnPropertyDescriptor","u","prototype","hasOwnProperty","call","i","set","obj","debug","createDebugLogger","describe","generateTests","callback","path","__dirname","recurse","fixura","reader","READERS","JSON","getFixture","factoryOptions","searchOptions","expectedFactoryError","expectedSearchError","enabled","url","isCandidateSearchError","expect","createSearchInterface","formatFactoryOptions","to","throw","CandidateSearchError","RegExp","search","iterate","stringify","maxRecordsPerRequest","maxServerResults","undefined","record","MarcRecord","subfieldValues","expectedErrorStatus","count","expectedResults","Error","err","be","an","errorMessage","MatchingError","payload","message","errorStatus","status","match","results","formatResults","eql","records","map","id","toObject"],"sources":["../../src/candidate-search/index.spec.js"],"sourcesContent":["/**\n*\n* @licstart The following is the entire license notice for the JavaScript code in this file.\n*\n* Melinda record matching modules for Javascript\n*\n* Copyright (C) 2020-2022 University Of Helsinki (The National Library Of Finland)\n*\n* This file is part of melinda-record-matching-js\n*\n* melinda-record-matching-js program is free software: you can redistribute it and/or modify\n* it under the terms of the GNU Lesser General Public License as\n* published by the Free Software Foundation, either version 3 of the\n* License, or (at your option) any later version.\n*\n* melinda-record-matching-js is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n* GNU Lesser General Public License for more details.\n*\n* You should have received a copy of the GNU Affero General Public License\n* along with this program. If not, see <http://www.gnu.org/licenses/>.\n*\n* @licend The above is the entire license notice\n* for the JavaScript code in this file.\n*\n*/\n\nimport {expect} from 'chai';\nimport {READERS} from '@natlibfi/fixura';\nimport generateTests from '@natlibfi/fixugen-http-client';\nimport {MarcRecord} from '@natlibfi/marc-record';\nimport {Error as MatchingError} from '@natlibfi/melinda-commons';\nimport createSearchInterface, {CandidateSearchError} from '.';\nimport createDebugLogger from 'debug';\n\nconst debug = createDebugLogger('@natlibfi/melinda-record-matching:candidate-search:test');\n\ndescribe('candidate-search', () => {\n generateTests({\n callback,\n path: [__dirname, '..', '..', 'test-fixtures', 'candidate-search', 'index'],\n recurse: false,\n fixura: {\n reader: READERS.JSON\n }\n });\n\n async function callback({getFixture, factoryOptions, searchOptions, expectedFactoryError = false, expectedSearchError = false, enabled = true}) {\n const url = 'http://foo.bar';\n\n if (!enabled) {\n return;\n }\n\n if (expectedFactoryError) {\n if (expectedFactoryError.isCandidateSearchError) {\n expect(() => createSearchInterface({...formatFactoryOptions(), url})).to.throw(CandidateSearchError, new RegExp(expectedFactoryError, 'u'));\n return;\n }\n\n expect(() => createSearchInterface({...formatFactoryOptions(), url})).to.throw(new RegExp(expectedFactoryError, 'u'));\n return;\n }\n\n const search = createSearchInterface({...formatFactoryOptions(), url});\n await iterate({searchOptions, expectedSearchError});\n\n function formatFactoryOptions() {\n debug(`Using factoryOptions: ${JSON.stringify(factoryOptions)}`);\n return {\n ...factoryOptions,\n maxRecordsPerRequest: factoryOptions.maxRecordsPerRequest || 1,\n maxServerResults: factoryOptions.maxServerResults || undefined,\n record: new MarcRecord(factoryOptions.record, {subfieldValues: false})\n };\n }\n\n async function iterate({searchOptions, expectedSearchError, expectedErrorStatus, count = 1}) {\n const expectedResults = getFixture(`expectedResults${count}.json`);\n\n if (expectedSearchError) { // eslint-disable-line functional/no-conditional-statements\n try {\n await search(searchOptions);\n throw new Error('Expected an error');\n } catch (err) {\n debug(`Got an error: ${err}`);\n expect(err).to.be.an('error');\n const errorMessage = err instanceof MatchingError ? err.payload.message : err.message;\n const errorStatus = err instanceof MatchingError ? err.status : undefined;\n debug(`errorMessage: ${errorMessage}, errorStatus: ${errorStatus}`);\n expect(errorMessage).to.match(new RegExp(expectedSearchError, 'u'));\n\n if (expectedErrorStatus) {\n expect(errorStatus).to.be(expectedErrorStatus);\n return;\n }\n return;\n }\n }\n\n // eslint-disable-next-line functional/no-conditional-statements\n if (!expectedSearchError) {\n const results = await search(searchOptions);\n expect(formatResults(results)).to.eql(expectedResults);\n }\n\n function formatResults(results) {\n debug(results);\n return {\n ...results,\n records: results.records.map(({record, id}) => ({id, record: record.toObject()}))\n };\n }\n\n }\n }\n});\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.spec.js","names":["_chai","require","_fixura","_fixugenHttpClient","_interopRequireDefault","_marcRecord","_melindaCommons","_","_interopRequireWildcard","_debug","_getRequireWildcardCache","e","WeakMap","r","t","__esModule","default","has","get","n","__proto__","a","Object","defineProperty","getOwnPropertyDescriptor","u","prototype","hasOwnProperty","call","i","set","obj","debug","createDebugLogger","describe","generateTests","callback","path","__dirname","recurse","fixura","reader","READERS","JSON","getFixture","factoryOptions","searchOptions","expectedFactoryError","expectedSearchError","enabled","url","isCandidateSearchError","result","createSearchInterface","formatFactoryOptions","err","expect","to","equal","CandidateSearchError","Error","search","console","log","iterate","stringify","maxRecordsPerRequest","maxServerResults","undefined","record","MarcRecord","subfieldValues","expectedErrorStatus","count","expectedResults","be","an","errorMessage","MatchingError","payload","message","errorStatus","status","match","RegExp","results","formatResults","eql","records","map","id","toObject"],"sources":["../../src/candidate-search/index.spec.js"],"sourcesContent":["/**\n*\n* @licstart The following is the entire license notice for the JavaScript code in this file.\n*\n* Melinda record matching modules for Javascript\n*\n* Copyright (C) 2020-2022 University Of Helsinki (The National Library Of Finland)\n*\n* This file is part of melinda-record-matching-js\n*\n* melinda-record-matching-js program is free software: you can redistribute it and/or modify\n* it under the terms of the GNU Lesser General Public License as\n* published by the Free Software Foundation, either version 3 of the\n* License, or (at your option) any later version.\n*\n* melinda-record-matching-js is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n* GNU Lesser General Public License for more details.\n*\n* You should have received a copy of the GNU Affero General Public License\n* along with this program. If not, see <http://www.gnu.org/licenses/>.\n*\n* @licend The above is the entire license notice\n* for the JavaScript code in this file.\n*\n*/\n\nimport {expect} from 'chai';\nimport {READERS} from '@natlibfi/fixura';\nimport generateTests from '@natlibfi/fixugen-http-client';\nimport {MarcRecord} from '@natlibfi/marc-record';\nimport {Error as MatchingError} from '@natlibfi/melinda-commons';\nimport createSearchInterface, {CandidateSearchError} from '.';\nimport createDebugLogger from 'debug';\n\nconst debug = createDebugLogger('@natlibfi/melinda-record-matching:candidate-search:test');\n\ndescribe('candidate-search', () => {\n generateTests({\n callback,\n path: [__dirname, '..', '..', 'test-fixtures', 'candidate-search', 'index'],\n recurse: false,\n fixura: {\n reader: READERS.JSON\n }\n });\n\n // eslint-disable-next-line max-statements\n async function callback({getFixture, factoryOptions, searchOptions, expectedFactoryError = false, expectedSearchError = false, enabled = true}) {\n const url = 'http://foo.bar';\n\n if (!enabled) {\n return;\n }\n\n if (expectedFactoryError) {\n debug(`We're expecting an error`);\n if (expectedFactoryError.isCandidateSearchError) {\n try {\n const result = createSearchInterface({...formatFactoryOptions(), url});\n debug(result);\n } catch (err) {\n expect(err).to.equal(new CandidateSearchError(expectedFactoryError));\n }\n return;\n }\n\n try {\n const result = createSearchInterface({...formatFactoryOptions(), url});\n debug(result);\n } catch (err) {\n expect(err).to.equal(new Error(expectedFactoryError));\n }\n return;\n }\n\n const {search} = await createSearchInterface({...formatFactoryOptions(), url});\n // eslint-disable-next-line no-console\n console.log(search);\n await iterate({searchOptions, expectedSearchError});\n\n function formatFactoryOptions() {\n debug(`Using factoryOptions: ${JSON.stringify(factoryOptions)}`);\n return {\n ...factoryOptions,\n maxRecordsPerRequest: factoryOptions.maxRecordsPerRequest || 1,\n maxServerResults: factoryOptions.maxServerResults || undefined,\n record: new MarcRecord(factoryOptions.record, {subfieldValues: false})\n };\n }\n\n async function iterate({searchOptions, expectedSearchError, expectedErrorStatus, count = 1}) {\n const expectedResults = getFixture(`expectedResults${count}.json`);\n\n if (expectedSearchError) { // eslint-disable-line functional/no-conditional-statements\n try {\n await search(searchOptions);\n throw new Error('Expected an error');\n } catch (err) {\n debug(`Got an error: ${err}`);\n expect(err).to.be.an('error');\n const errorMessage = err instanceof MatchingError ? err.payload.message : err.message;\n const errorStatus = err instanceof MatchingError ? err.status : undefined;\n debug(`errorMessage: ${errorMessage}, errorStatus: ${errorStatus}`);\n expect(errorMessage).to.match(new RegExp(expectedSearchError, 'u'));\n\n if (expectedErrorStatus) {\n expect(errorStatus).to.be(expectedErrorStatus);\n return;\n }\n return;\n }\n }\n\n // eslint-disable-next-line functional/no-conditional-statements\n if (!expectedSearchError) {\n const results = await search(searchOptions);\n expect(formatResults(results)).to.eql(expectedResults);\n }\n\n function formatResults(results) {\n debug(results);\n return {\n ...results,\n records: results.records.map(({record, id}) => ({id, record: record.toObject()}))\n };\n }\n\n }\n }\n});\n"],"mappings":"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"}
package/dist/index.js CHANGED
@@ -63,14 +63,17 @@ var _default = ({
63
63
  debugData(`ReturnNonMatches: ${JSON.stringify(returnNonMatches)}`);
64
64
  debugData(`ReturnFailures: ${JSON.stringify(returnFailures)}`);
65
65
  const detect = (0, _matchDetection.default)(detectionOptions, returnStrategy);
66
- return ({
66
+ return prepareSearch;
67
+ async function prepareSearch({
67
68
  record,
68
69
  recordExternal = {
69
70
  recordSource: 'incomingRecord',
70
71
  label: 'ic'
71
72
  }
72
- }) => {
73
- const search = (0, _candidateSearch.default)({
73
+ }) {
74
+ const {
75
+ search
76
+ } = await (0, _candidateSearch.default)({
74
77
  ...searchOptions,
75
78
  record,
76
79
  maxCandidates,
@@ -573,7 +576,7 @@ var _default = ({
573
576
  return true;
574
577
  }
575
578
  }
576
- };
579
+ }
577
580
  };
578
581
  exports.default = _default;
579
582
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["_debug","_interopRequireDefault","require","_candidateSearch","_interopRequireWildcard","candidateSearch","exports","_matchDetection","matchDetection","_getRequireWildcardCache","e","WeakMap","r","t","__esModule","default","has","get","n","__proto__","a","Object","defineProperty","getOwnPropertyDescriptor","u","prototype","hasOwnProperty","call","i","set","obj","_default","detection","detectionOptions","search","searchOptions","maxMatches","maxCandidates","returnStrategy","returnQuery","returnNonMatches","returnFailures","debug","createDebugLogger","debugData","extend","JSON","stringify","detect","createDetectionInterface","record","recordExternal","recordSource","label","createSearchInterface","iterate","initialState","matches","candidateCount","nonMatches","duplicateCount","nonMatchCount","conversionFailures","matchErrors","records","failures","state","length","recordSetSize","failureSetSize","newCandidateCount","newConversionFailures","concat","handleRecordSet","queriesLeft","searchCounter","query","returnResult","stopReason","matchResult","iterateRecords","newDuplicateCount","newNonMatchCount","newMatches","newNonMatches","newMatchErrors","handleMatchResult","maxMatchesFound","maxCandidatesRetrieved","addQuery","map","match","matchQuery","conversionFailureCount","matchErrorCount","checkCounts","matchStatus","getMatchState","matchesResult","result","matchCount","chosenNonMatchCount","totalHandled","conversionFailuresCount","resultSetOffset","totalRecords","queryCandidateCounter","maxedQueries","searchesLeft","nonRetrieved","maxedQueriesStopReason","undefined","conversionFailuresStopReason","matchErrorsStopReason","newStopReason","status","recordMatches","recordNonMatches","recordCount","recordDuplicateCount","recordNonMatchCount","recordMatchErrors","candidate","newRecordCount","candidateNotInMatches","candidateRecord","id","candidateId","recordBExternal","detectionResult","recordA","recordB","recordAExternal","handleDetectionResult","error","matchError","payload","message","newRecordMatchErrors","slice","strategy","treshold","probability","strategyResult","newMatch","handleRecordMatch","newRecordNonMatchCount","isMatch","newRecordMatches","newRecordNonMatches","newCandidateId","find"],"sources":["../src/index.js"],"sourcesContent":["/**\n*\n* @licstart The following is the entire license notice for the JavaScript code in this file.\n*\n* Melinda record matching modules for Javascript\n*\n* Copyright (C) 2020-2022 University Of Helsinki (The National Library Of Finland)\n*\n* This file is part of melinda-record-matching-js\n*\n* melinda-record-matching-js program is free software: you can redistribute it and/or modify\n* it under the terms of the GNU Lesser General Public License as\n* published by the Free Software Foundation, either version 3 of the\n* License, or (at your option) any later version.\n*\n* melinda-record-matching-js is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n* GNU Lesser General Public License for more details.\n*\n* You should have received a copy of the GNU Affero General Public License\n* along with this program. If not, see <http://www.gnu.org/licenses/>.\n*\n* @licend The above is the entire license notice\n* for the JavaScript code in this file.\n*\n*/\n\nimport createDebugLogger from 'debug';\nimport createSearchInterface, * as candidateSearch from './candidate-search';\nimport createDetectionInterface, * as matchDetection from './match-detection';\n//import inspect from 'util';\n\nexport {candidateSearch, matchDetection};\n\nexport default ({detection: detectionOptions, search: searchOptions, maxMatches = 1, maxCandidates = 25, returnStrategy = false, returnQuery = false, returnNonMatches = false, returnFailures = false}) => {\n const debug = createDebugLogger('@natlibfi/melinda-record-matching:index');\n const debugData = debug.extend('data');\n\n debugData(`DetectionOptions: ${JSON.stringify(detectionOptions)}`);\n debugData(`SearchOptions: ${JSON.stringify(searchOptions)}`);\n debugData(`MaxMatches: ${JSON.stringify(maxMatches)}`);\n debugData(`MaxCandidates: ${JSON.stringify(maxCandidates)}`);\n debugData(`ReturnStrategy: ${JSON.stringify(returnStrategy)}`);\n debugData(`ReturnQuery: ${JSON.stringify(returnQuery)}`);\n debugData(`ReturnNonMatches: ${JSON.stringify(returnNonMatches)}`);\n debugData(`ReturnFailures: ${JSON.stringify(returnFailures)}`);\n\n\n const detect = createDetectionInterface(detectionOptions, returnStrategy);\n\n return ({record, recordExternal = {recordSource: 'incomingRecord', label: 'ic'}}) => {\n\n const search = createSearchInterface({...searchOptions, record, maxCandidates, recordExternal});\n return iterate({});\n\n // candidateCount : amount of candidate records retrived from SRU for matching, NOT including current record set\n // matches : candidates that have been detected as matches by current matcher job\n // nonMatches : candidates that have been detected as non-matches by current matcher job (only if returnNonMatches is 'true')\n // duplicateCount : amount of candidate records that were retrieved from the SRU but not handled further because they were already found in the matches/nonMatches\n\n // state.totalRecords : amount of candidate records available to the current query (undefined, if there was no queries left)\n // state.query : current query (undefined if there was no queries left)\n // state.searchCounter : sequence for current search for current query (undefined, if there we no queries left)\n // state.queryCandidateCounter: amount of candidate records retrieved from SRU for matching for current query, including the current record set (undefined if there were no queries left)\n // state.queriesLeft : amount of queries left\n // state.queryCounter : sequence for current query\n // state.maxedQueries : queries that resulted in more than serverMaxResults hits\n\n async function iterate({initialState = {}, matches = [], candidateCount = 0, nonMatches = [], duplicateCount = 0, nonMatchCount = 0, conversionFailures = [], matchErrors = []}) {\n debugData(`Starting next matcher iteration.`);\n const {records, failures, ...state} = await search(initialState);\n\n debugData(`Current state: ${JSON.stringify(state)}, matches: ${matches.length}, candidateCount: ${candidateCount}, nonMatches: ${nonMatches.length}, nonMatchCount: ${nonMatchCount}, conversionFailures: ${conversionFailures}, matchErrors: ${matchErrors.length}`);\n const recordSetSize = records.length;\n const failureSetSize = failures.length;\n const newCandidateCount = candidateCount + recordSetSize + failureSetSize;\n\n const newConversionFailures = conversionFailures.concat(failures);\n debugData(`Failures: ${failures.length}, ConversionFailures: ${conversionFailures.length}, NewConversionFailures: ${newConversionFailures.length}`);\n\n if (recordSetSize > 0) {\n return handleRecordSet();\n }\n\n if (state.queriesLeft > 0) {\n debug(`Empty record set ${state.searchCounter} for ${state.query}, but there are ${state.queriesLeft} queries left`);\n return iterate({initialState: state, matches, candidateCount: newCandidateCount, nonMatches, nonMatchCount, duplicateCount, conversionFailures: newConversionFailures, matchErrors});\n }\n\n debug(`No (more) candidate records to check, no more queries left, matches: ${matches.length}`);\n return returnResult({matches, state, stopReason: '', nonMatches, nonMatchCount, candidateCount: newCandidateCount, duplicateCount, conversionFailures: newConversionFailures, matchErrors});\n\n function handleRecordSet() {\n debug(`Checking record set of ${recordSetSize} candidate records for possible matches, found by ${state.searchCounter} search for ${state.query}`);\n\n const matchResult = iterateRecords({records, recordSetSize, maxMatches, matches, nonMatches, nonMatchCount});\n\n const newDuplicateCount = duplicateCount + matchResult.duplicateCount;\n const newNonMatchCount = nonMatchCount + matchResult.nonMatchCount;\n const {newMatches, newNonMatches, newMatchErrors} = handleMatchResult(matchResult, matches, nonMatches, matchErrors);\n\n if (maxMatchesFound({matches: newMatches, maxMatches})) {\n return returnResult({matches: newMatches, state, stopReason: 'maxMatches', nonMatches: newNonMatches, duplicateCount: newDuplicateCount, candidateCount: newCandidateCount, nonMatchCount: newNonMatchCount, conversionFailures: newConversionFailures, matchErrors: newMatchErrors});\n }\n\n if (maxCandidatesRetrieved(newCandidateCount, maxCandidates)) {\n return returnResult({matches: newMatches, state, stopReason: 'maxCandidates', nonMatches: newNonMatches, duplicateCount: newDuplicateCount, candidateCount: newCandidateCount, nonMatchCount: newNonMatchCount, conversionFailures: newConversionFailures, matchErrors: newMatchErrors});\n }\n\n return iterate({initialState: state, matches: newMatches, candidateCount: newCandidateCount, nonMatches: newNonMatches, duplicateCount: newDuplicateCount, nonMatchCount: newNonMatchCount, conversionFailures: newConversionFailures, matchErrors: newMatchErrors});\n }\n\n function handleMatchResult(matchResult, matches, nonMatches, matchErrors) {\n debugData(`- Amount of new matches from record set: ${matchResult.matches.length}`);\n // eslint-disable-next-line functional/no-conditional-statements\n if (returnNonMatches) {\n debugData(`- Amount of new nonMatches from record set: ${matchResult.nonMatches.length}`);\n }\n\n const newMatches = matches.concat(returnQuery ? addQuery(matchResult.matches) : matchResult.matches);\n const newNonMatches = returnNonMatches ? nonMatches.concat(returnQuery ? addQuery(matchResult.nonMatches) : matchResult.nonMatches) : [];\n const newMatchErrors = matchErrors.concat(matchResult.matchErrors);\n\n debugData(`- Total amount of matches: ${newMatches.length}`);\n // eslint-disable-next-line functional/no-conditional-statements\n if (returnNonMatches) {\n debugData(`- Total amount of nonMatches: ${newNonMatches.length}`);\n }\n\n debugData(`MatchResult: ${JSON.stringify(matchResult)}`);\n debugData(`Old matchErrors: ${JSON.stringify(matchErrors)}, matchErrors from matchResult: ${JSON.stringify(matchResult.matchErrors)}, New matchErrors: ${JSON.stringify(newMatchErrors)}`);\n\n debugData(`- Total amount of matchErrors: ${newMatchErrors.length}`);\n\n return {newMatches, newNonMatches, newMatchErrors};\n }\n\n function addQuery(matches) {\n debugData(`Adding query ${state.query} to matches`);\n return matches.map((match) => ({...match, matchQuery: state.query}));\n }\n\n function maxCandidatesRetrieved(candidateCount, maxCandidates) {\n debugData(`Total amount of candidate records retrieved: ${newCandidateCount} (max: ${maxCandidates})`);\n if (maxCandidates && candidateCount >= maxCandidates) {\n debug(`Stopped matching because maximum number of candidate records ${candidateCount} / ${maxCandidates} have been retrieved`);\n return true;\n }\n }\n }\n\n // matches : array of matching candidate records\n // nonMatches : array of nonMatching candidate records (if returnNonMatches option is true, otherwise empty array)\n // - candidate.id\n // - candidate.record\n // - probability\n // - strategy (if returnStrategy option is true)\n // - treshold (if returnStrategy option is true)\n // - matchQuery (if returnQuery option is true)\n // failures: array of conversionFailures from candidate-search and matchErrors from matchDetection in error format {status, payload: {message, id}} if returnFailures is true\n\n // we could have here also returnRecords/returnMatchRecords/returnNonMatchRecord options that could be turned false for not to return actual record data\n\n // matchStatus.status: boolean, true if matcher retrieved and handled all found candidate records, false if it did not\n // matchStatus.stopReason: string ('maxMatches','maxCandidates','maxedQueries','conversionFailures', empty string/undefined), reason for stopping retrieving or handling the candidate records\n // - only one stopReason is returned (if there would be several possible stopReasons, stopReason is picked in the above order)\n // - currently stopReason can be non-empty also in cases where status is true, if matcher hit the stop reason when handling the last available candidate record\n\n function returnResult({matches, state, stopReason, nonMatches, duplicateCount, candidateCount, nonMatchCount, conversionFailures, matchErrors}) {\n const conversionFailureCount = conversionFailures.length;\n const matchErrorCount = matchErrors.length;\n checkCounts({matches, nonMatches, candidateCount, duplicateCount, nonMatchCount, conversionFailureCount, matchErrorCount});\n const matchStatus = getMatchState(state, stopReason, conversionFailureCount, matchErrorCount);\n // add nonMatches to result only if returnNonMatches is 'true', otherwise nonMatches have not been gathered\n const matchesResult = returnNonMatches ? {matches, matchStatus, nonMatches, candidateCount} : {matches, matchStatus, candidateCount};\n const failures = [...conversionFailures, ...matchErrors];\n const result = returnFailures ? {...matchesResult, conversionFailures: failures} : matchesResult;\n debugData(`ReturnFailures ${returnFailures}`);\n debugData(`${JSON.stringify(result)}`);\n return result;\n\n // note that in cases where the matching has been stopped because of maxMatches checkCounts won't (in most cases) match\n\n function checkCounts({matches, nonMatches, candidateCount, duplicateCount, nonMatchCount, conversionFailureCount, matchErrorCount}) {\n const matchCount = matches.length;\n debugData(`Return nonMatches: ${returnNonMatches}`);\n const chosenNonMatchCount = returnNonMatches ? nonMatches.length : nonMatchCount;\n const totalHandled = matchCount + chosenNonMatchCount + duplicateCount;\n debug(`candidateCount: ${candidateCount}, matches: ${matchCount}, nonMatches: ${chosenNonMatchCount}, duplicateCount: ${duplicateCount}, conversionFailureCount: ${conversionFailureCount}, matchErrorCount: ${matchErrorCount}`);\n debug(`We got result for ${totalHandled} / ${candidateCount} retrieved candidates`);\n if (totalHandled !== candidateCount) {\n debug(`WARNING: Missing results for ${candidateCount - totalHandled} candidates`);\n return;\n }\n return;\n }\n\n // eslint-disable-next-line max-statements\n function getMatchState(state, stopReason, conversionFailuresCount, matchErrorCount) {\n debugData(`${JSON.stringify(state)}`);\n debug(`We had ${conversionFailuresCount} retrieved candidates that could not be converted.`);\n debug(`We had ${matchErrorCount} retrieved candidates that errored in matchDetection.`);\n debug(`Queries left ${state.queriesLeft}, Searches for current query left: ${state.resultSetOffset && state.resultSetOffset <= state.totalRecords}, non-retrieved records: ${state.totalRecords - state.queryCandidateCounter}, maxedQueries (${state.maxedQueries.length}): ${state.maxedQueries}`);\n\n debugData(`StopReason: <${stopReason}>`);\n\n const searchesLeft = state.resultSetOffset && state.resultSetOffset <= state.totalRecords;\n const nonRetrieved = searchesLeft ? state.totalRecords - state.queryCandidateCounter : 0;\n debugData(`nonRetrieved: ${nonRetrieved}`);\n\n // matchStatus.stopReason: string ('maxMatches','maxCandidates','maxedQueries','conversionFailures', empty string/undefined), reason for stopping retrieving or handling the candidate records\n // 'maxMatches' and 'maxCandidates' are in stopReason, 'maxedQueries', 'conversionFailures' and 'matchErrors' are created here\n\n if (state.queriesLeft > 0 || nonRetrieved > 0 || state.maxedQueries.length > 0 || conversionFailureCount > 0 || matchErrorCount > 0) {\n const maxedQueriesStopReason = state.maxedQueries.length > 0 ? 'maxedQueries' : undefined;\n const conversionFailuresStopReason = conversionFailureCount > 0 ? 'conversionFailures' : undefined;\n const matchErrorsStopReason = matchErrorCount > 0 ? 'matchErrors' : undefined;\n const newStopReason = stopReason === '' || stopReason === undefined ? maxedQueriesStopReason || conversionFailuresStopReason || matchErrorsStopReason : stopReason;\n debugData(`MaxedQueriesStopReason: <${maxedQueriesStopReason}>`);\n debugData(`ConversionFailureStopReason <${conversionFailuresStopReason}>`);\n debugData(`MatchErrorsStopReason <${matchErrorsStopReason}>`);\n debugData(`NewStopReason: <${newStopReason}>`);\n debug(`Match status: false`);\n return {status: false, stopReason: newStopReason};\n }\n\n debug(`Match status: true`);\n return {status: true, stopReason};\n }\n }\n\n // NOTES:\n // - we could optimize by creating the featureSet for the incoming record once and using it for all database/candidateRecords\n // - if creating the featureSet for the incoming record fails we have an unprocessable entity\n // - if creating the featureSet for a candidate record fails we could skip that candidate - but list the case as a detectionFailure, same as conversionFailures\n\n function iterateRecords({records, recordSetSize, maxMatches, matches = [], nonMatches = [], recordMatches = [], recordNonMatches = [], recordCount = 0, recordDuplicateCount = 0, recordNonMatchCount = 0, recordMatchErrors = []}) {\n\n // recordSetSize : total amount of records in the current record set\n // recordCount : amount of records from the current record set that have been handled\n // maxMatches : setting for maximum amount found by current matcher job before the matcher job is stopped\n // recordDuplicateCount : amount of records from the current record set that are already included in matches/nonMatches results\n // recordNonMatchCount: amount of records from the current record set that are nonMatches (only is returnNonMatches setting is false)\n\n // records : non-handled records in the current record set\n // matches : found matches in the current matcher job\n // recordMatches : found matches in the current record set\n // recordNonMatches : found nonMatches in the current record set (only if returnNonMatches setting is true)\n // recordMatchErrors: errored matchDetection in the current record set\n\n const [candidate] = records;\n const newRecordCount = candidate ? recordCount + 1 : recordCount;\n\n // The matcher uses same matchDetection strategy for candidates from all candidate-searches -> matchDetection result for the same candidate is always same\n // Exceptions would happen if the candidate would have been updated in the database between candidate searches\n // Note that if returnNonMatches is false, matcher won't remember candidates that didn't match, so they will be matched again everytime they are retrieved by\n // different candidate search queries. Same candidate search query won't have duplicate records.\n\n /* We could optimize and detect all retrieved candidates at once\n const candidateRecords = records.map(record => record.record);\n const recordsIsArray = Array.isArray(candidateRecords);\n debug(`records is an array: ${recordsIsArray}`);\n const result = detect(record, candidateRecords);\n debugData(`${JSON.stringify(result)}`);\n */\n\n if (candidate) {\n\n // eslint-disable-next-line functional/no-conditional-statements\n if (candidateNotInMatches(matches.concat(nonMatches), candidate)) {\n const {record: candidateRecord, id: candidateId} = candidate;\n const recordBExternal = {id: candidate.id, recordSource: 'databaseRecord', label: `db-${candidate.id}`};\n try {\n debug(`Running matchDetection for record ${candidateId} (${newRecordCount}/${recordSetSize})`);\n // we should handle errors from detection somehow - ie. cases where either record or candidateRecord errors\n const detectionResult = detect({recordA: record, recordB: candidateRecord, recordAExternal: recordExternal, recordBExternal});\n\n return handleDetectionResult(detectionResult, candidateId, candidateRecord);\n } catch (error) {\n debug(`MatchDetection errored: database record ${candidateId}: ${error}`);\n\n const matchError = {status: 422, payload: {message: `Matching errored for database record ${candidateId}. ${error.message}.`, id: candidateId}};\n const newRecordMatchErrors = recordMatchErrors.concat(matchError);\n return iterateRecords({records: records.slice(1), recordSetSize, maxMatches, matches, recordMatches, recordCount: newRecordCount, recordNonMatches, recordDuplicateCount, recordNonMatchCount, recordMatchErrors: newRecordMatchErrors});\n }\n }\n\n return iterateRecords({records: records.slice(1), recordSetSize, maxMatches, matches, recordMatches, recordCount: newRecordCount, recordNonMatches, recordDuplicateCount: recordDuplicateCount + 1, recordNonMatchCount, recordMatchErrors});\n }\n\n debug(`No more candidates, record set (${recordCount}/${recordSetSize}) done, ${recordMatches.length} matches found, ${recordDuplicateCount} candidates already handled, ${returnNonMatches ? `${recordNonMatches.length}` : `${recordNonMatchCount}`} nonMatches found.`);\n return {matches: recordMatches, nonMatches: returnNonMatches ? recordNonMatches : [], duplicateCount: recordDuplicateCount, nonMatchCount: recordNonMatchCount, matchErrors: recordMatchErrors};\n\n function handleDetectionResult(detectionResult, candidateId, candidateRecord) {\n debugData(`MatchDetection results for ${candidateId} (${newRecordCount}/${recordSetSize}): ${JSON.stringify(detectionResult)}`);\n\n if (detectionResult.match || returnNonMatches) {\n debug(`${detectionResult.match ? `Record ${candidateId} (${newRecordCount}/${recordSetSize}) is a match!` : `Record ${candidateId} (${newRecordCount}/${recordSetSize}) is NOT a match!`}`);\n debugData(`Strategy: ${JSON.stringify(detectionResult.strategy)}, Treshold: ${JSON.stringify(detectionResult.treshold)}`);\n\n const matchResult = {\n probability: detectionResult.probability,\n candidate: {\n id: candidateId,\n record: candidateRecord\n }\n };\n const strategyResult = {\n strategy: detectionResult.strategy,\n treshold: detectionResult.treshold\n };\n const newMatch = returnStrategy ? {...matchResult, ...strategyResult} : {...matchResult};\n\n debugData(`${JSON.stringify(newMatch)}`);\n\n return handleRecordMatch(detectionResult.match, newMatch);\n }\n\n const newRecordNonMatchCount = recordNonMatchCount + 1;\n debugData(`- Total nonMatches after this detection: ${newRecordNonMatchCount}`);\n\n return iterateRecords({records: records.slice(1), recordSetSize, maxMatches, matches, recordMatches, recordCount: newRecordCount, recordNonMatches, recordDuplicateCount, recordNonMatchCount: newRecordNonMatchCount, recordMatchErrors});\n }\n\n function handleRecordMatch(isMatch, newMatch) {\n const newRecordMatches = isMatch ? recordMatches.concat(newMatch) : recordMatches;\n const newRecordNonMatches = isMatch ? recordNonMatches : recordNonMatches.concat(newMatch);\n const newRecordNonMatchCount = isMatch ? recordNonMatchCount : recordNonMatchCount + 1;\n\n debugData(`- Total matches after this detection: ${matches.concat(newRecordMatches).length} (max: ${maxMatches})`);\n\n // eslint-disable-next-line functional/no-conditional-statements\n if (returnNonMatches) {\n debugData(`- Total nonMatches after this detection: ${nonMatches.concat(newRecordNonMatches).length}`);\n }\n debugData(`- Total nonMatchCount after this detection: ${recordNonMatchCount}`);\n\n if (maxMatchesFound({matches: matches.concat(newRecordMatches), maxMatches})) {\n debug(`MaxMatches (${maxMatches}) reached, handled candidates in record set: ${newRecordCount} non-handled candidates in record set ${recordSetSize - newRecordCount}`);\n return {matches: newRecordMatches, nonMatches: returnNonMatches ? newRecordNonMatches : [], duplicateCount: recordDuplicateCount, nonMatchCount: newRecordNonMatchCount, matchErrors: recordMatchErrors};\n }\n\n return iterateRecords({records: records.slice(1), recordSetSize, maxMatches, matches, recordMatches: newRecordMatches, recordCount: newRecordCount, recordNonMatches: returnNonMatches ? newRecordNonMatches : [], duplicateCount: recordDuplicateCount, recordNonMatchCount: newRecordNonMatchCount, matchErrors: recordMatchErrors});\n }\n\n function candidateNotInMatches(matches, candidate) {\n debug(`Checking that record ${candidate.id} is not already included in ${matches.length} matches/nonMatches`);\n const newCandidateId = candidate.id;\n debugData(`newCandidateId: ${newCandidateId}`);\n const result = matches.find(({candidate}) => candidate.id === newCandidateId);\n debugData(`Result: ${result}`);\n if (result) {\n debug(`${candidate.id} was already handled.`);\n return false;\n }\n debug(`${candidate.id} not found in matches/nonMatches`);\n return true;\n }\n }\n\n function maxMatchesFound({matches, maxMatches}) {\n if (maxMatches && matches.length >= maxMatches) {\n debug(`Stopping recordSet iteration: maxMatches (${maxMatches}) for matcher job found.`);\n return true;\n }\n }\n };\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["_debug","_interopRequireDefault","require","_candidateSearch","_interopRequireWildcard","candidateSearch","exports","_matchDetection","matchDetection","_getRequireWildcardCache","e","WeakMap","r","t","__esModule","default","has","get","n","__proto__","a","Object","defineProperty","getOwnPropertyDescriptor","u","prototype","hasOwnProperty","call","i","set","obj","_default","detection","detectionOptions","search","searchOptions","maxMatches","maxCandidates","returnStrategy","returnQuery","returnNonMatches","returnFailures","debug","createDebugLogger","debugData","extend","JSON","stringify","detect","createDetectionInterface","prepareSearch","record","recordExternal","recordSource","label","createSearchInterface","iterate","initialState","matches","candidateCount","nonMatches","duplicateCount","nonMatchCount","conversionFailures","matchErrors","records","failures","state","length","recordSetSize","failureSetSize","newCandidateCount","newConversionFailures","concat","handleRecordSet","queriesLeft","searchCounter","query","returnResult","stopReason","matchResult","iterateRecords","newDuplicateCount","newNonMatchCount","newMatches","newNonMatches","newMatchErrors","handleMatchResult","maxMatchesFound","maxCandidatesRetrieved","addQuery","map","match","matchQuery","conversionFailureCount","matchErrorCount","checkCounts","matchStatus","getMatchState","matchesResult","result","matchCount","chosenNonMatchCount","totalHandled","conversionFailuresCount","resultSetOffset","totalRecords","queryCandidateCounter","maxedQueries","searchesLeft","nonRetrieved","maxedQueriesStopReason","undefined","conversionFailuresStopReason","matchErrorsStopReason","newStopReason","status","recordMatches","recordNonMatches","recordCount","recordDuplicateCount","recordNonMatchCount","recordMatchErrors","candidate","newRecordCount","candidateNotInMatches","candidateRecord","id","candidateId","recordBExternal","detectionResult","recordA","recordB","recordAExternal","handleDetectionResult","error","matchError","payload","message","newRecordMatchErrors","slice","strategy","treshold","probability","strategyResult","newMatch","handleRecordMatch","newRecordNonMatchCount","isMatch","newRecordMatches","newRecordNonMatches","newCandidateId","find"],"sources":["../src/index.js"],"sourcesContent":["/**\n*\n* @licstart The following is the entire license notice for the JavaScript code in this file.\n*\n* Melinda record matching modules for Javascript\n*\n* Copyright (C) 2020-2022 University Of Helsinki (The National Library Of Finland)\n*\n* This file is part of melinda-record-matching-js\n*\n* melinda-record-matching-js program is free software: you can redistribute it and/or modify\n* it under the terms of the GNU Lesser General Public License as\n* published by the Free Software Foundation, either version 3 of the\n* License, or (at your option) any later version.\n*\n* melinda-record-matching-js is distributed in the hope that it will be useful,\n* but WITHOUT ANY WARRANTY; without even the implied warranty of\n* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n* GNU Lesser General Public License for more details.\n*\n* You should have received a copy of the GNU Affero General Public License\n* along with this program. If not, see <http://www.gnu.org/licenses/>.\n*\n* @licend The above is the entire license notice\n* for the JavaScript code in this file.\n*\n*/\n\nimport createDebugLogger from 'debug';\nimport createSearchInterface, * as candidateSearch from './candidate-search';\nimport createDetectionInterface, * as matchDetection from './match-detection';\n//import inspect from 'util';\n\nexport {candidateSearch, matchDetection};\n\nexport default ({detection: detectionOptions, search: searchOptions, maxMatches = 1, maxCandidates = 25, returnStrategy = false, returnQuery = false, returnNonMatches = false, returnFailures = false}) => {\n const debug = createDebugLogger('@natlibfi/melinda-record-matching:index');\n const debugData = debug.extend('data');\n\n debugData(`DetectionOptions: ${JSON.stringify(detectionOptions)}`);\n debugData(`SearchOptions: ${JSON.stringify(searchOptions)}`);\n debugData(`MaxMatches: ${JSON.stringify(maxMatches)}`);\n debugData(`MaxCandidates: ${JSON.stringify(maxCandidates)}`);\n debugData(`ReturnStrategy: ${JSON.stringify(returnStrategy)}`);\n debugData(`ReturnQuery: ${JSON.stringify(returnQuery)}`);\n debugData(`ReturnNonMatches: ${JSON.stringify(returnNonMatches)}`);\n debugData(`ReturnFailures: ${JSON.stringify(returnFailures)}`);\n\n\n const detect = createDetectionInterface(detectionOptions, returnStrategy);\n\n return prepareSearch;\n\n async function prepareSearch({record, recordExternal = {recordSource: 'incomingRecord', label: 'ic'}}) {\n\n const {search} = await createSearchInterface({...searchOptions, record, maxCandidates, recordExternal});\n return iterate({});\n\n // candidateCount : amount of candidate records retrived from SRU for matching, NOT including current record set\n // matches : candidates that have been detected as matches by current matcher job\n // nonMatches : candidates that have been detected as non-matches by current matcher job (only if returnNonMatches is 'true')\n // duplicateCount : amount of candidate records that were retrieved from the SRU but not handled further because they were already found in the matches/nonMatches\n\n // state.totalRecords : amount of candidate records available to the current query (undefined, if there was no queries left)\n // state.query : current query (undefined if there was no queries left)\n // state.searchCounter : sequence for current search for current query (undefined, if there we no queries left)\n // state.queryCandidateCounter: amount of candidate records retrieved from SRU for matching for current query, including the current record set (undefined if there were no queries left)\n // state.queriesLeft : amount of queries left\n // state.queryCounter : sequence for current query\n // state.maxedQueries : queries that resulted in more than serverMaxResults hits\n\n async function iterate({initialState = {}, matches = [], candidateCount = 0, nonMatches = [], duplicateCount = 0, nonMatchCount = 0, conversionFailures = [], matchErrors = []}) {\n debugData(`Starting next matcher iteration.`);\n const {records, failures, ...state} = await search(initialState);\n\n debugData(`Current state: ${JSON.stringify(state)}, matches: ${matches.length}, candidateCount: ${candidateCount}, nonMatches: ${nonMatches.length}, nonMatchCount: ${nonMatchCount}, conversionFailures: ${conversionFailures}, matchErrors: ${matchErrors.length}`);\n const recordSetSize = records.length;\n const failureSetSize = failures.length;\n const newCandidateCount = candidateCount + recordSetSize + failureSetSize;\n\n const newConversionFailures = conversionFailures.concat(failures);\n debugData(`Failures: ${failures.length}, ConversionFailures: ${conversionFailures.length}, NewConversionFailures: ${newConversionFailures.length}`);\n\n if (recordSetSize > 0) {\n return handleRecordSet();\n }\n\n if (state.queriesLeft > 0) {\n debug(`Empty record set ${state.searchCounter} for ${state.query}, but there are ${state.queriesLeft} queries left`);\n return iterate({initialState: state, matches, candidateCount: newCandidateCount, nonMatches, nonMatchCount, duplicateCount, conversionFailures: newConversionFailures, matchErrors});\n }\n\n debug(`No (more) candidate records to check, no more queries left, matches: ${matches.length}`);\n return returnResult({matches, state, stopReason: '', nonMatches, nonMatchCount, candidateCount: newCandidateCount, duplicateCount, conversionFailures: newConversionFailures, matchErrors});\n\n function handleRecordSet() {\n debug(`Checking record set of ${recordSetSize} candidate records for possible matches, found by ${state.searchCounter} search for ${state.query}`);\n\n const matchResult = iterateRecords({records, recordSetSize, maxMatches, matches, nonMatches, nonMatchCount});\n\n const newDuplicateCount = duplicateCount + matchResult.duplicateCount;\n const newNonMatchCount = nonMatchCount + matchResult.nonMatchCount;\n const {newMatches, newNonMatches, newMatchErrors} = handleMatchResult(matchResult, matches, nonMatches, matchErrors);\n\n if (maxMatchesFound({matches: newMatches, maxMatches})) {\n return returnResult({matches: newMatches, state, stopReason: 'maxMatches', nonMatches: newNonMatches, duplicateCount: newDuplicateCount, candidateCount: newCandidateCount, nonMatchCount: newNonMatchCount, conversionFailures: newConversionFailures, matchErrors: newMatchErrors});\n }\n\n if (maxCandidatesRetrieved(newCandidateCount, maxCandidates)) {\n return returnResult({matches: newMatches, state, stopReason: 'maxCandidates', nonMatches: newNonMatches, duplicateCount: newDuplicateCount, candidateCount: newCandidateCount, nonMatchCount: newNonMatchCount, conversionFailures: newConversionFailures, matchErrors: newMatchErrors});\n }\n\n return iterate({initialState: state, matches: newMatches, candidateCount: newCandidateCount, nonMatches: newNonMatches, duplicateCount: newDuplicateCount, nonMatchCount: newNonMatchCount, conversionFailures: newConversionFailures, matchErrors: newMatchErrors});\n }\n\n function handleMatchResult(matchResult, matches, nonMatches, matchErrors) {\n debugData(`- Amount of new matches from record set: ${matchResult.matches.length}`);\n // eslint-disable-next-line functional/no-conditional-statements\n if (returnNonMatches) {\n debugData(`- Amount of new nonMatches from record set: ${matchResult.nonMatches.length}`);\n }\n\n const newMatches = matches.concat(returnQuery ? addQuery(matchResult.matches) : matchResult.matches);\n const newNonMatches = returnNonMatches ? nonMatches.concat(returnQuery ? addQuery(matchResult.nonMatches) : matchResult.nonMatches) : [];\n const newMatchErrors = matchErrors.concat(matchResult.matchErrors);\n\n debugData(`- Total amount of matches: ${newMatches.length}`);\n // eslint-disable-next-line functional/no-conditional-statements\n if (returnNonMatches) {\n debugData(`- Total amount of nonMatches: ${newNonMatches.length}`);\n }\n\n debugData(`MatchResult: ${JSON.stringify(matchResult)}`);\n debugData(`Old matchErrors: ${JSON.stringify(matchErrors)}, matchErrors from matchResult: ${JSON.stringify(matchResult.matchErrors)}, New matchErrors: ${JSON.stringify(newMatchErrors)}`);\n\n debugData(`- Total amount of matchErrors: ${newMatchErrors.length}`);\n\n return {newMatches, newNonMatches, newMatchErrors};\n }\n\n function addQuery(matches) {\n debugData(`Adding query ${state.query} to matches`);\n return matches.map((match) => ({...match, matchQuery: state.query}));\n }\n\n function maxCandidatesRetrieved(candidateCount, maxCandidates) {\n debugData(`Total amount of candidate records retrieved: ${newCandidateCount} (max: ${maxCandidates})`);\n if (maxCandidates && candidateCount >= maxCandidates) {\n debug(`Stopped matching because maximum number of candidate records ${candidateCount} / ${maxCandidates} have been retrieved`);\n return true;\n }\n }\n }\n\n // matches : array of matching candidate records\n // nonMatches : array of nonMatching candidate records (if returnNonMatches option is true, otherwise empty array)\n // - candidate.id\n // - candidate.record\n // - probability\n // - strategy (if returnStrategy option is true)\n // - treshold (if returnStrategy option is true)\n // - matchQuery (if returnQuery option is true)\n // failures: array of conversionFailures from candidate-search and matchErrors from matchDetection in error format {status, payload: {message, id}} if returnFailures is true\n\n // we could have here also returnRecords/returnMatchRecords/returnNonMatchRecord options that could be turned false for not to return actual record data\n\n // matchStatus.status: boolean, true if matcher retrieved and handled all found candidate records, false if it did not\n // matchStatus.stopReason: string ('maxMatches','maxCandidates','maxedQueries','conversionFailures', empty string/undefined), reason for stopping retrieving or handling the candidate records\n // - only one stopReason is returned (if there would be several possible stopReasons, stopReason is picked in the above order)\n // - currently stopReason can be non-empty also in cases where status is true, if matcher hit the stop reason when handling the last available candidate record\n\n function returnResult({matches, state, stopReason, nonMatches, duplicateCount, candidateCount, nonMatchCount, conversionFailures, matchErrors}) {\n const conversionFailureCount = conversionFailures.length;\n const matchErrorCount = matchErrors.length;\n checkCounts({matches, nonMatches, candidateCount, duplicateCount, nonMatchCount, conversionFailureCount, matchErrorCount});\n const matchStatus = getMatchState(state, stopReason, conversionFailureCount, matchErrorCount);\n // add nonMatches to result only if returnNonMatches is 'true', otherwise nonMatches have not been gathered\n const matchesResult = returnNonMatches ? {matches, matchStatus, nonMatches, candidateCount} : {matches, matchStatus, candidateCount};\n const failures = [...conversionFailures, ...matchErrors];\n const result = returnFailures ? {...matchesResult, conversionFailures: failures} : matchesResult;\n debugData(`ReturnFailures ${returnFailures}`);\n debugData(`${JSON.stringify(result)}`);\n return result;\n\n // note that in cases where the matching has been stopped because of maxMatches checkCounts won't (in most cases) match\n\n function checkCounts({matches, nonMatches, candidateCount, duplicateCount, nonMatchCount, conversionFailureCount, matchErrorCount}) {\n const matchCount = matches.length;\n debugData(`Return nonMatches: ${returnNonMatches}`);\n const chosenNonMatchCount = returnNonMatches ? nonMatches.length : nonMatchCount;\n const totalHandled = matchCount + chosenNonMatchCount + duplicateCount;\n debug(`candidateCount: ${candidateCount}, matches: ${matchCount}, nonMatches: ${chosenNonMatchCount}, duplicateCount: ${duplicateCount}, conversionFailureCount: ${conversionFailureCount}, matchErrorCount: ${matchErrorCount}`);\n debug(`We got result for ${totalHandled} / ${candidateCount} retrieved candidates`);\n if (totalHandled !== candidateCount) {\n debug(`WARNING: Missing results for ${candidateCount - totalHandled} candidates`);\n return;\n }\n return;\n }\n\n // eslint-disable-next-line max-statements\n function getMatchState(state, stopReason, conversionFailuresCount, matchErrorCount) {\n debugData(`${JSON.stringify(state)}`);\n debug(`We had ${conversionFailuresCount} retrieved candidates that could not be converted.`);\n debug(`We had ${matchErrorCount} retrieved candidates that errored in matchDetection.`);\n debug(`Queries left ${state.queriesLeft}, Searches for current query left: ${state.resultSetOffset && state.resultSetOffset <= state.totalRecords}, non-retrieved records: ${state.totalRecords - state.queryCandidateCounter}, maxedQueries (${state.maxedQueries.length}): ${state.maxedQueries}`);\n\n debugData(`StopReason: <${stopReason}>`);\n\n const searchesLeft = state.resultSetOffset && state.resultSetOffset <= state.totalRecords;\n const nonRetrieved = searchesLeft ? state.totalRecords - state.queryCandidateCounter : 0;\n debugData(`nonRetrieved: ${nonRetrieved}`);\n\n // matchStatus.stopReason: string ('maxMatches','maxCandidates','maxedQueries','conversionFailures', empty string/undefined), reason for stopping retrieving or handling the candidate records\n // 'maxMatches' and 'maxCandidates' are in stopReason, 'maxedQueries', 'conversionFailures' and 'matchErrors' are created here\n\n if (state.queriesLeft > 0 || nonRetrieved > 0 || state.maxedQueries.length > 0 || conversionFailureCount > 0 || matchErrorCount > 0) {\n const maxedQueriesStopReason = state.maxedQueries.length > 0 ? 'maxedQueries' : undefined;\n const conversionFailuresStopReason = conversionFailureCount > 0 ? 'conversionFailures' : undefined;\n const matchErrorsStopReason = matchErrorCount > 0 ? 'matchErrors' : undefined;\n const newStopReason = stopReason === '' || stopReason === undefined ? maxedQueriesStopReason || conversionFailuresStopReason || matchErrorsStopReason : stopReason;\n debugData(`MaxedQueriesStopReason: <${maxedQueriesStopReason}>`);\n debugData(`ConversionFailureStopReason <${conversionFailuresStopReason}>`);\n debugData(`MatchErrorsStopReason <${matchErrorsStopReason}>`);\n debugData(`NewStopReason: <${newStopReason}>`);\n debug(`Match status: false`);\n return {status: false, stopReason: newStopReason};\n }\n\n debug(`Match status: true`);\n return {status: true, stopReason};\n }\n }\n\n // NOTES:\n // - we could optimize by creating the featureSet for the incoming record once and using it for all database/candidateRecords\n // - if creating the featureSet for the incoming record fails we have an unprocessable entity\n // - if creating the featureSet for a candidate record fails we could skip that candidate - but list the case as a detectionFailure, same as conversionFailures\n\n function iterateRecords({records, recordSetSize, maxMatches, matches = [], nonMatches = [], recordMatches = [], recordNonMatches = [], recordCount = 0, recordDuplicateCount = 0, recordNonMatchCount = 0, recordMatchErrors = []}) {\n\n // recordSetSize : total amount of records in the current record set\n // recordCount : amount of records from the current record set that have been handled\n // maxMatches : setting for maximum amount found by current matcher job before the matcher job is stopped\n // recordDuplicateCount : amount of records from the current record set that are already included in matches/nonMatches results\n // recordNonMatchCount: amount of records from the current record set that are nonMatches (only is returnNonMatches setting is false)\n\n // records : non-handled records in the current record set\n // matches : found matches in the current matcher job\n // recordMatches : found matches in the current record set\n // recordNonMatches : found nonMatches in the current record set (only if returnNonMatches setting is true)\n // recordMatchErrors: errored matchDetection in the current record set\n\n const [candidate] = records;\n const newRecordCount = candidate ? recordCount + 1 : recordCount;\n\n // The matcher uses same matchDetection strategy for candidates from all candidate-searches -> matchDetection result for the same candidate is always same\n // Exceptions would happen if the candidate would have been updated in the database between candidate searches\n // Note that if returnNonMatches is false, matcher won't remember candidates that didn't match, so they will be matched again everytime they are retrieved by\n // different candidate search queries. Same candidate search query won't have duplicate records.\n\n /* We could optimize and detect all retrieved candidates at once\n const candidateRecords = records.map(record => record.record);\n const recordsIsArray = Array.isArray(candidateRecords);\n debug(`records is an array: ${recordsIsArray}`);\n const result = detect(record, candidateRecords);\n debugData(`${JSON.stringify(result)}`);\n */\n\n if (candidate) {\n\n // eslint-disable-next-line functional/no-conditional-statements\n if (candidateNotInMatches(matches.concat(nonMatches), candidate)) {\n const {record: candidateRecord, id: candidateId} = candidate;\n const recordBExternal = {id: candidate.id, recordSource: 'databaseRecord', label: `db-${candidate.id}`};\n try {\n debug(`Running matchDetection for record ${candidateId} (${newRecordCount}/${recordSetSize})`);\n // we should handle errors from detection somehow - ie. cases where either record or candidateRecord errors\n const detectionResult = detect({recordA: record, recordB: candidateRecord, recordAExternal: recordExternal, recordBExternal});\n\n return handleDetectionResult(detectionResult, candidateId, candidateRecord);\n } catch (error) {\n debug(`MatchDetection errored: database record ${candidateId}: ${error}`);\n\n const matchError = {status: 422, payload: {message: `Matching errored for database record ${candidateId}. ${error.message}.`, id: candidateId}};\n const newRecordMatchErrors = recordMatchErrors.concat(matchError);\n return iterateRecords({records: records.slice(1), recordSetSize, maxMatches, matches, recordMatches, recordCount: newRecordCount, recordNonMatches, recordDuplicateCount, recordNonMatchCount, recordMatchErrors: newRecordMatchErrors});\n }\n }\n\n return iterateRecords({records: records.slice(1), recordSetSize, maxMatches, matches, recordMatches, recordCount: newRecordCount, recordNonMatches, recordDuplicateCount: recordDuplicateCount + 1, recordNonMatchCount, recordMatchErrors});\n }\n\n debug(`No more candidates, record set (${recordCount}/${recordSetSize}) done, ${recordMatches.length} matches found, ${recordDuplicateCount} candidates already handled, ${returnNonMatches ? `${recordNonMatches.length}` : `${recordNonMatchCount}`} nonMatches found.`);\n return {matches: recordMatches, nonMatches: returnNonMatches ? recordNonMatches : [], duplicateCount: recordDuplicateCount, nonMatchCount: recordNonMatchCount, matchErrors: recordMatchErrors};\n\n function handleDetectionResult(detectionResult, candidateId, candidateRecord) {\n debugData(`MatchDetection results for ${candidateId} (${newRecordCount}/${recordSetSize}): ${JSON.stringify(detectionResult)}`);\n\n if (detectionResult.match || returnNonMatches) {\n debug(`${detectionResult.match ? `Record ${candidateId} (${newRecordCount}/${recordSetSize}) is a match!` : `Record ${candidateId} (${newRecordCount}/${recordSetSize}) is NOT a match!`}`);\n debugData(`Strategy: ${JSON.stringify(detectionResult.strategy)}, Treshold: ${JSON.stringify(detectionResult.treshold)}`);\n\n const matchResult = {\n probability: detectionResult.probability,\n candidate: {\n id: candidateId,\n record: candidateRecord\n }\n };\n const strategyResult = {\n strategy: detectionResult.strategy,\n treshold: detectionResult.treshold\n };\n const newMatch = returnStrategy ? {...matchResult, ...strategyResult} : {...matchResult};\n\n debugData(`${JSON.stringify(newMatch)}`);\n\n return handleRecordMatch(detectionResult.match, newMatch);\n }\n\n const newRecordNonMatchCount = recordNonMatchCount + 1;\n debugData(`- Total nonMatches after this detection: ${newRecordNonMatchCount}`);\n\n return iterateRecords({records: records.slice(1), recordSetSize, maxMatches, matches, recordMatches, recordCount: newRecordCount, recordNonMatches, recordDuplicateCount, recordNonMatchCount: newRecordNonMatchCount, recordMatchErrors});\n }\n\n function handleRecordMatch(isMatch, newMatch) {\n const newRecordMatches = isMatch ? recordMatches.concat(newMatch) : recordMatches;\n const newRecordNonMatches = isMatch ? recordNonMatches : recordNonMatches.concat(newMatch);\n const newRecordNonMatchCount = isMatch ? recordNonMatchCount : recordNonMatchCount + 1;\n\n debugData(`- Total matches after this detection: ${matches.concat(newRecordMatches).length} (max: ${maxMatches})`);\n\n // eslint-disable-next-line functional/no-conditional-statements\n if (returnNonMatches) {\n debugData(`- Total nonMatches after this detection: ${nonMatches.concat(newRecordNonMatches).length}`);\n }\n debugData(`- Total nonMatchCount after this detection: ${recordNonMatchCount}`);\n\n if (maxMatchesFound({matches: matches.concat(newRecordMatches), maxMatches})) {\n debug(`MaxMatches (${maxMatches}) reached, handled candidates in record set: ${newRecordCount} non-handled candidates in record set ${recordSetSize - newRecordCount}`);\n return {matches: newRecordMatches, nonMatches: returnNonMatches ? newRecordNonMatches : [], duplicateCount: recordDuplicateCount, nonMatchCount: newRecordNonMatchCount, matchErrors: recordMatchErrors};\n }\n\n return iterateRecords({records: records.slice(1), recordSetSize, maxMatches, matches, recordMatches: newRecordMatches, recordCount: newRecordCount, recordNonMatches: returnNonMatches ? newRecordNonMatches : [], duplicateCount: recordDuplicateCount, recordNonMatchCount: newRecordNonMatchCount, matchErrors: recordMatchErrors});\n }\n\n function candidateNotInMatches(matches, candidate) {\n debug(`Checking that record ${candidate.id} is not already included in ${matches.length} matches/nonMatches`);\n const newCandidateId = candidate.id;\n debugData(`newCandidateId: ${newCandidateId}`);\n const result = matches.find(({candidate}) => candidate.id === newCandidateId);\n debugData(`Result: ${result}`);\n if (result) {\n debug(`${candidate.id} was already handled.`);\n return false;\n }\n debug(`${candidate.id} not found in matches/nonMatches`);\n return true;\n }\n }\n\n function maxMatchesFound({matches, maxMatches}) {\n if (maxMatches && matches.length >= maxMatches) {\n debug(`Stopping recordSet iteration: maxMatches (${maxMatches}) for matcher job found.`);\n return true;\n }\n }\n }\n};\n"],"mappings":"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"}
package/package.json CHANGED
@@ -14,7 +14,7 @@
14
14
  "url": "git@github.com:natlibfi/melinda-record-matching-js.git"
15
15
  },
16
16
  "license": "LGPL-3.0+",
17
- "version": "4.3.2-alpha.3",
17
+ "version": "4.3.2-alpha.5",
18
18
  "main": "./dist/index.js",
19
19
  "engines": {
20
20
  "node": ">=18"
@@ -38,35 +38,35 @@
38
38
  "watch:test": "cross-env DEBUG=1 NODE_ENV=test nodemon -w src -w test-fixtures --exec 'npm run test:dev'"
39
39
  },
40
40
  "dependencies": {
41
- "@natlibfi/marc-record": "^8.0.2",
41
+ "@natlibfi/marc-record": "^8.1.0",
42
42
  "@natlibfi/marc-record-serializers": "^10.1.2",
43
- "@natlibfi/melinda-commons": "^13.0.9",
44
- "@natlibfi/sru-client": "^6.0.7",
43
+ "@natlibfi/melinda-commons": "^13.0.12",
44
+ "@natlibfi/sru-client": "^6.0.8",
45
45
  "debug": "^4.3.4",
46
- "isbn3": "^1.1.43",
47
- "moment": "^2.29.4",
46
+ "isbn3": "^1.1.44",
47
+ "moment": "^2.30.1",
48
48
  "natural": "^6.10.4",
49
49
  "uuid": "^9.0.1",
50
50
  "winston": "^3.11.0"
51
51
  },
52
52
  "devDependencies": {
53
- "@babel/cli": "^7.23.4",
54
- "@babel/core": "^7.23.6",
55
- "@babel/node": "^7.22.19",
56
- "@babel/preset-env": "^7.23.6",
57
- "@babel/register": "^7.22.15",
58
- "@natlibfi/eslint-config-melinda-backend": "^3.0.3",
59
- "@natlibfi/fixugen": "^2.0.3",
60
- "@natlibfi/fixugen-http-client": "^3.0.2",
61
- "@natlibfi/fixura": "^3.0.3",
53
+ "@babel/cli": "^7.23.9",
54
+ "@babel/core": "^7.23.9",
55
+ "@babel/node": "^7.23.9",
56
+ "@babel/preset-env": "^7.23.9",
57
+ "@babel/register": "^7.23.7",
58
+ "@natlibfi/eslint-config-melinda-backend": "^3.0.4",
59
+ "@natlibfi/fixugen": "^2.0.4",
60
+ "@natlibfi/fixugen-http-client": "^3.0.4",
61
+ "@natlibfi/fixura": "^3.0.4",
62
62
  "babel-plugin-istanbul": "^6.1.1",
63
63
  "babel-plugin-rewire": "^1.2.0",
64
- "chai": "^4.3.10",
64
+ "chai": "^4.4.1",
65
65
  "chai-as-promised": "^7.1.1",
66
66
  "cross-env": "^7.0.3",
67
- "eslint": "^8.55.0",
67
+ "eslint": "^8.56.0",
68
68
  "mocha": "^10.2.0",
69
- "nodemon": "^3.0.2",
69
+ "nodemon": "^3.0.3",
70
70
  "nyc": "^15.1.0"
71
71
  },
72
72
  "eslintConfig": {
@@ -0,0 +1,123 @@
1
+ /**
2
+ *
3
+ * @licstart The following is the entire license notice for the JavaScript code in this file.
4
+ *
5
+ * Melinda record matching modules for Javascript
6
+ *
7
+ * Copyright (C) 2023 University Of Helsinki (The National Library Of Finland)
8
+ *
9
+ * This file is part of melinda-record-matching-js
10
+ *
11
+ * melinda-record-matching-js program is free software: you can redistribute it and/or modify
12
+ * it under the terms of the GNU Lesser General Public License as
13
+ * published by the Free Software Foundation, either version 3 of the
14
+ * License, or (at your option) any later version.
15
+ *
16
+ * melinda-record-matching-js is distributed in the hope that it will be useful,
17
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
18
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19
+ * GNU Lesser General Public License for more details.
20
+ *
21
+ * You should have received a copy of the GNU Affero General Public License
22
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
23
+ *
24
+ * @licend The above is the entire license notice
25
+ * for the JavaScript code in this file.
26
+ *
27
+ */
28
+
29
+ import createDebugLogger from 'debug';
30
+ import createClient, {SruSearchError} from '@natlibfi/sru-client';
31
+
32
+ export class CandidateSearchError extends Error {}
33
+
34
+ export default async function ({url, queryList, queryListType, maxCandidates = 50}) {
35
+
36
+ const debug = createDebugLogger('@natlibfi/melinda-record-matching:candidate-search:choose-queries');
37
+ const debugData = debug.extend('data');
38
+ const debugDev = debug.extend('dev');
39
+
40
+ debugData(`Url: ${url}`);
41
+ debugData(`QueryList: ${queryList}`);
42
+ debugData(`queryListType: ${queryListType}`);
43
+
44
+ const client = createClient({
45
+ url,
46
+ maxRecordsPerRequest: 0,
47
+ version: '2.0',
48
+ retrieveAll: false
49
+ });
50
+
51
+ debugDev(`QueryList (type: ${queryListType}) ${JSON.stringify(queryList)}`);
52
+ try {
53
+ const {queriesWithTotals} = await getQueryTotals({queryList, queryOffset: 0, queriesWithTotals: []});
54
+ debugDev(`QueryResult: ${JSON.stringify(queriesWithTotals)}`);
55
+ const filteredQueryResult = filterQueryResult({queriesWithTotals, maxCandidates});
56
+ debugDev(`filteredQueryResult: ${JSON.stringify(filteredQueryResult)}`);
57
+ return filteredQueryResult;
58
+ } catch (err) {
59
+ throw new CandidateSearchError(err);
60
+ }
61
+
62
+ async function getQueryTotals({queryList, queryOffset = 0, queriesWithTotals = []}) {
63
+
64
+ const query = queryList[queryOffset];
65
+ debug(`Running query ${JSON.stringify(query)} (${queryOffset}) for total`);
66
+
67
+ if (query) {
68
+ const {total} = await retrieveTotal();
69
+
70
+ const newQueriesWithTotals = [...queriesWithTotals, {query, total}];
71
+ debug(`Query ${queryOffset} ${query} done.`);
72
+ debug(`There are (${queryList.length - (queryOffset + 1)} queries left)`);
73
+ return getQueryTotals({queryList, queryOffset: queryOffset + 1, queriesWithTotals: newQueriesWithTotals});
74
+ }
75
+
76
+ debug(`All ${queryList.length} queries done, there's no query for ${queryOffset}`);
77
+ return {queriesWithTotals};
78
+
79
+ function retrieveTotal() {
80
+ return new Promise((resolve, reject) => {
81
+ // eslint-disable-next-line functional/no-let
82
+ let totalRecords = 0;
83
+
84
+ debug(`Searching total amount of candidates for query: ${query}`);
85
+
86
+ client.searchRetrieve(query)
87
+ .on('error', err => {
88
+ // eslint-disable-next-line functional/no-conditional-statements
89
+ if (err instanceof SruSearchError) {
90
+ debug(`SRU SruSearchError for query: ${query}: ${err}`);
91
+ reject(new CandidateSearchError(`SRU SruSearchError for query: ${query}: ${err}`));
92
+ }
93
+ debug(`SRU error for query: ${query}: ${err}`);
94
+ reject(new CandidateSearchError(`SRU error for query: ${query}: ${err}`));
95
+ })
96
+ .on('total', total => {
97
+ debug(`Got total: ${total}`);
98
+ totalRecords += total;
99
+ })
100
+ .on('end', () => {
101
+ try {
102
+ resolve({total: totalRecords});
103
+ } catch (err) {
104
+ debug(`Error caught on END`);
105
+ reject(err);
106
+ }
107
+ })
108
+ .on('record', () => {
109
+ debugDev(`RECORD: We should no get records here`);
110
+ });
111
+ });
112
+ }
113
+ }
114
+ function filterQueryResult({queriesWithTotals, maxCandidates}) {
115
+ debug(`Filtering queries (${queriesWithTotals.length}), maxCandidates: ${maxCandidates}`);
116
+ debugData(`${JSON.stringify(queriesWithTotals)}`);
117
+ // Drop queries where total result is 0 or greater than given maxCandidates
118
+ const filteredQueryResult = queriesWithTotals.filter((queryWithTotal) => queryWithTotal.total !== 0 && queryWithTotal.total < maxCandidates);
119
+ debugData(`${JSON.stringify(filteredQueryResult)}`);
120
+ return filteredQueryResult;
121
+ }
122
+
123
+ }
@@ -32,6 +32,7 @@ import {MarcRecord} from '@natlibfi/marc-record';
32
32
  import {MARCXML} from '@natlibfi/marc-record-serializers';
33
33
  import generateQueryList from './query-list';
34
34
  import {Error as MatchingError} from '@natlibfi/melinda-commons';
35
+ import chooseQueries from './choose-queries';
35
36
 
36
37
  export {searchTypes} from './query-list';
37
38
 
@@ -39,7 +40,7 @@ export class CandidateSearchError extends Error {}
39
40
 
40
41
  // serverMaxResults : maximum size of total search result available from the server, defaults to Aleph's 20000
41
42
 
42
- export default ({record, searchSpec, url, maxCandidates, maxRecordsPerRequest = 50, serverMaxResult = 20000}) => {
43
+ export default async ({record, searchSpec, url, maxCandidates, maxRecordsPerRequest = 50, serverMaxResult = 20000}) => {
43
44
  MarcRecord.setValidationOptions({subfieldValues: false});
44
45
 
45
46
  const debug = createDebugLogger('@natlibfi/melinda-record-matching:candidate-search');
@@ -59,6 +60,16 @@ export default ({record, searchSpec, url, maxCandidates, maxRecordsPerRequest =
59
60
  const queryList = queryListResult[0]?.queryList ? queryListResult[0].queryList : queryListResult;
60
61
  const queryListType = queryListResult[0]?.queryListType ? queryListResult[0].queryListType : undefined;
61
62
 
63
+ // if generateQueryList errored we should throw 422
64
+ if (queryList.length === 0) {
65
+ debug(`Empty list`);
66
+ throw new CandidateSearchError(`Generated query list contains no queries`);
67
+ }
68
+ if (queryListType && queryListType !== 'alternates') {
69
+ debug(`Unknown queryListType`);
70
+ throw new CandidateSearchError(`Generated query list has invalid type`);
71
+ }
72
+
62
73
  const client = createClient({
63
74
  url,
64
75
  maxRecordsPerRequest: adjustedMaxRecordsPerRequest,
@@ -67,33 +78,19 @@ export default ({record, searchSpec, url, maxCandidates, maxRecordsPerRequest =
67
78
  });
68
79
 
69
80
  debug(`Searching matches for ${inputRecordId}`);
70
- const chosenQueryList = choseQueries(queryList, queryListType);
81
+ const chosenQueryList = await filterQueryList({queryList, queryListType});
82
+ debug(`Chosen queries: ${JSON.stringify(chosenQueryList)}`);
71
83
 
72
- // eslint-disable-next-line require-await
73
- function choseQueries(queryList, queryListType) {
84
+ async function filterQueryList({queryList, queryListType, maxCandidates}) {
74
85
  debug(`Generated queryList (type: ${queryListType}) ${JSON.stringify(queryList)}`);
75
86
 
76
- // if generateQueryList errored we should throw 422
77
- if (queryList.length === 0) {
78
- throw new CandidateSearchError(`Generated query list contains no queries`);
79
- }
80
-
81
- if (queryListType && queryListType !== 'alternates') {
82
- throw new CandidateSearchError(`Generated query list has invalid type`);
83
- }
84
-
85
87
  if (queryListType === 'alternates' && queryList.length > 1) {
86
- //const [query] = queryList;
87
- //const totalResult = await retrieveTotal(query);
88
- // const totalsForQueries = queryList.map(query => retrieveTotal(query));
89
- //debug(`${JSON.stringify(totalResult)}`);
90
- return queryList;
91
- //return [];
88
+ const queryListResult = await chooseQueries({url, queryList, queryListType, maxCandidates});
89
+ debug(`queryListResult: ${JSON.stringify(queryListResult)}`);
90
+ return queryListResult.map(elem => elem.query);
92
91
  }
93
92
  return queryList;
94
93
  }
95
-
96
-
97
94
  // state.totalRecords : amount of candidate records available to the current query (undefined, if there was no queries left)
98
95
  // state.query : current query (undefined if there was no queries left)
99
96
  // state.searchCounter : sequence for current search for current query (undefined, if there we no queries left)
@@ -102,16 +99,11 @@ export default ({record, searchSpec, url, maxCandidates, maxRecordsPerRequest =
102
99
  // state.queryCounter : sequence for current query
103
100
  // state.maxedQueries : queries that resulted in more than serverMaxResults hits
104
101
 
102
+ return {search};
105
103
 
106
104
  // eslint-disable-next-line max-statements
107
- return async ({queryOffset = 0, resultSetOffset = 1, totalRecords = 0, searchCounter = 0, queryCandidateCounter = 0, queryCounter = 0, maxedQueries = []}) => {
105
+ async function search({queryOffset = 0, resultSetOffset = 1, totalRecords = 0, searchCounter = 0, queryCandidateCounter = 0, queryCounter = 0, maxedQueries = []}) {
108
106
 
109
- /*
110
- if (queryListType === 'alternates') {
111
- debug('Alternates - stop here');
112
- return {records: [], failures: [], queriesLeft: 0, queryCounter, maxedQueries};
113
- }
114
- */
115
107
  const query = chosenQueryList[queryOffset];
116
108
  debug(`Running query ${JSON.stringify(query)} (${queryOffset})`);
117
109
 
@@ -202,31 +194,7 @@ export default ({record, searchSpec, url, maxCandidates, maxRecordsPerRequest =
202
194
  });
203
195
  });
204
196
  }
205
- };
206
-
207
- /*
208
- async function retrieveTotal(query) {
209
- debug(`Searching for candidateTotals with query: ${query}`);
210
- totalClient.searchRetrieve(query)
211
- .on('error', err => {
212
- // eslint-disable-next-line functional/no-conditional-statements
213
- if (err instanceof SruSearchError) {
214
- debug(`SRU SruSearchError for query: ${query}: ${err}`);
215
- throw new CandidateSearchError(`SRU SruSearchError for getting total for query: ${query}: ${err}`);
216
- }
217
- debug(`SRU error for query: ${query}: ${err}`);
218
- throw new CandidateSearchError(`SRU error for getting total for query: ${query}: ${err}`);
219
- })
220
- .on('total', total => {
221
- debug(`Got total: ${total}`);
222
- return {query, total};
223
- })
224
- .on('end', end => {
225
- debug(`End ${JSON.stringify(end)}`);
226
- });
227
197
  }
228
- */
229
-
230
198
 
231
199
  function checkMaxedQuery(query, total, serverMaxResult) {
232
200
  if (total >= serverMaxResult) {
@@ -245,5 +213,4 @@ export default ({record, searchSpec, url, maxCandidates, maxRecordsPerRequest =
245
213
  debug(`Cannot yet find possible database record id from recordXML (length ${recordXML.length})`);
246
214
  return undefined;
247
215
  }
248
-
249
216
  };
@@ -46,6 +46,7 @@ describe('candidate-search', () => {
46
46
  }
47
47
  });
48
48
 
49
+ // eslint-disable-next-line max-statements
49
50
  async function callback({getFixture, factoryOptions, searchOptions, expectedFactoryError = false, expectedSearchError = false, enabled = true}) {
50
51
  const url = 'http://foo.bar';
51
52
 
@@ -54,16 +55,29 @@ describe('candidate-search', () => {
54
55
  }
55
56
 
56
57
  if (expectedFactoryError) {
58
+ debug(`We're expecting an error`);
57
59
  if (expectedFactoryError.isCandidateSearchError) {
58
- expect(() => createSearchInterface({...formatFactoryOptions(), url})).to.throw(CandidateSearchError, new RegExp(expectedFactoryError, 'u'));
60
+ try {
61
+ const result = createSearchInterface({...formatFactoryOptions(), url});
62
+ debug(result);
63
+ } catch (err) {
64
+ expect(err).to.equal(new CandidateSearchError(expectedFactoryError));
65
+ }
59
66
  return;
60
67
  }
61
68
 
62
- expect(() => createSearchInterface({...formatFactoryOptions(), url})).to.throw(new RegExp(expectedFactoryError, 'u'));
69
+ try {
70
+ const result = createSearchInterface({...formatFactoryOptions(), url});
71
+ debug(result);
72
+ } catch (err) {
73
+ expect(err).to.equal(new Error(expectedFactoryError));
74
+ }
63
75
  return;
64
76
  }
65
77
 
66
- const search = createSearchInterface({...formatFactoryOptions(), url});
78
+ const {search} = await createSearchInterface({...formatFactoryOptions(), url});
79
+ // eslint-disable-next-line no-console
80
+ console.log(search);
67
81
  await iterate({searchOptions, expectedSearchError});
68
82
 
69
83
  function formatFactoryOptions() {
package/src/index.js CHANGED
@@ -49,9 +49,11 @@ export default ({detection: detectionOptions, search: searchOptions, maxMatches
49
49
 
50
50
  const detect = createDetectionInterface(detectionOptions, returnStrategy);
51
51
 
52
- return ({record, recordExternal = {recordSource: 'incomingRecord', label: 'ic'}}) => {
52
+ return prepareSearch;
53
53
 
54
- const search = createSearchInterface({...searchOptions, record, maxCandidates, recordExternal});
54
+ async function prepareSearch({record, recordExternal = {recordSource: 'incomingRecord', label: 'ic'}}) {
55
+
56
+ const {search} = await createSearchInterface({...searchOptions, record, maxCandidates, recordExternal});
55
57
  return iterate({});
56
58
 
57
59
  // candidateCount : amount of candidate records retrived from SRU for matching, NOT including current record set
@@ -365,5 +367,5 @@ export default ({detection: detectionOptions, search: searchOptions, maxMatches
365
367
  return true;
366
368
  }
367
369
  }
368
- };
370
+ }
369
371
  };