@natlibfi/melinda-record-matching 4.3.5 → 5.0.0-alpha.1

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.
Files changed (101) hide show
  1. package/.github/workflows/melinda-node-tests.yml +11 -7
  2. package/eslint.config.js +52 -0
  3. package/example.env +4 -0
  4. package/package.json +22 -90
  5. package/src/candidate-search/choose-queries.js +1 -3
  6. package/src/candidate-search/index.js +63 -89
  7. package/src/candidate-search/{index.spec.js → index.test.js} +19 -18
  8. package/src/candidate-search/query-list/bib.js +10 -4
  9. package/src/candidate-search/query-list/{bib.spec.js → bib.test.js} +8 -7
  10. package/src/candidate-search/query-list/component.js +127 -0
  11. package/src/candidate-search/query-list/index.js +23 -9
  12. package/src/cli.js +177 -0
  13. package/src/index.js +22 -37
  14. package/src/{index.spec.js → index.test.js} +11 -14
  15. package/src/match-detection/features/bib/all-source-ids.js +2 -2
  16. package/src/match-detection/features/bib/authors.js +3 -2
  17. package/src/match-detection/features/bib/index.js +16 -16
  18. package/src/match-detection/features/bib/{index.spec.js → index.test.js} +7 -6
  19. package/src/match-detection/features/bib/isbn.js +2 -2
  20. package/src/match-detection/features/bib/issn.js +1 -1
  21. package/src/match-detection/features/bib/language.js +5 -5
  22. package/src/match-detection/features/bib/media-type.js +1 -1
  23. package/src/match-detection/features/bib/melinda-id.js +1 -1
  24. package/src/match-detection/features/bib/melinda-identifier-factory.js +5 -5
  25. package/src/match-detection/features/bib/other-standard-identifier.js +1 -1
  26. package/src/match-detection/features/bib/publication-time-allow-cons-years-multi.js +6 -6
  27. package/src/match-detection/features/bib/publication-time-allow-cons-years.js +1 -1
  28. package/src/match-detection/features/bib/publication-time.js +1 -1
  29. package/src/match-detection/features/bib/standard-identifier-factory.js +1 -2
  30. package/src/match-detection/features/bib/title-version-original.js +2 -1
  31. package/src/match-detection/features/bib/title.js +6 -5
  32. package/src/match-detection/features/index.js +1 -1
  33. package/src/match-detection/index.js +1 -1
  34. package/src/match-detection/{index.spec.js → index.test.js} +9 -8
  35. package/src/matching-utils.js +8 -9
  36. package/dist/candidate-search/candidate-search-utils.js +0 -29
  37. package/dist/candidate-search/candidate-search-utils.js.map +0 -1
  38. package/dist/candidate-search/choose-queries.js +0 -122
  39. package/dist/candidate-search/choose-queries.js.map +0 -1
  40. package/dist/candidate-search/index.js +0 -260
  41. package/dist/candidate-search/index.js.map +0 -1
  42. package/dist/candidate-search/index.spec.js +0 -133
  43. package/dist/candidate-search/index.spec.js.map +0 -1
  44. package/dist/candidate-search/query-list/bib.js +0 -458
  45. package/dist/candidate-search/query-list/bib.js.map +0 -1
  46. package/dist/candidate-search/query-list/bib.spec.js +0 -46
  47. package/dist/candidate-search/query-list/bib.spec.js.map +0 -1
  48. package/dist/candidate-search/query-list/index.js +0 -47
  49. package/dist/candidate-search/query-list/index.js.map +0 -1
  50. package/dist/index.js +0 -555
  51. package/dist/index.js.map +0 -1
  52. package/dist/index.spec.js +0 -99
  53. package/dist/index.spec.js.map +0 -1
  54. package/dist/match-detection/features/bib/all-source-ids.js +0 -91
  55. package/dist/match-detection/features/bib/all-source-ids.js.map +0 -1
  56. package/dist/match-detection/features/bib/authors.js +0 -86
  57. package/dist/match-detection/features/bib/authors.js.map +0 -1
  58. package/dist/match-detection/features/bib/bibliographic-level.js +0 -15
  59. package/dist/match-detection/features/bib/bibliographic-level.js.map +0 -1
  60. package/dist/match-detection/features/bib/host-component.js +0 -15
  61. package/dist/match-detection/features/bib/host-component.js.map +0 -1
  62. package/dist/match-detection/features/bib/index.js +0 -119
  63. package/dist/match-detection/features/bib/index.js.map +0 -1
  64. package/dist/match-detection/features/bib/index.spec.js +0 -65
  65. package/dist/match-detection/features/bib/index.spec.js.map +0 -1
  66. package/dist/match-detection/features/bib/isbn.js +0 -49
  67. package/dist/match-detection/features/bib/isbn.js.map +0 -1
  68. package/dist/match-detection/features/bib/issn.js +0 -24
  69. package/dist/match-detection/features/bib/issn.js.map +0 -1
  70. package/dist/match-detection/features/bib/language.js +0 -113
  71. package/dist/match-detection/features/bib/language.js.map +0 -1
  72. package/dist/match-detection/features/bib/media-type.js +0 -56
  73. package/dist/match-detection/features/bib/media-type.js.map +0 -1
  74. package/dist/match-detection/features/bib/melinda-id.js +0 -21
  75. package/dist/match-detection/features/bib/melinda-id.js.map +0 -1
  76. package/dist/match-detection/features/bib/melinda-identifier-factory.js +0 -62
  77. package/dist/match-detection/features/bib/melinda-identifier-factory.js.map +0 -1
  78. package/dist/match-detection/features/bib/other-standard-identifier.js +0 -25
  79. package/dist/match-detection/features/bib/other-standard-identifier.js.map +0 -1
  80. package/dist/match-detection/features/bib/publication-time-allow-cons-years-multi.js +0 -229
  81. package/dist/match-detection/features/bib/publication-time-allow-cons-years-multi.js.map +0 -1
  82. package/dist/match-detection/features/bib/publication-time-allow-cons-years.js +0 -44
  83. package/dist/match-detection/features/bib/publication-time-allow-cons-years.js.map +0 -1
  84. package/dist/match-detection/features/bib/publication-time.js +0 -21
  85. package/dist/match-detection/features/bib/publication-time.js.map +0 -1
  86. package/dist/match-detection/features/bib/record-type.js +0 -18
  87. package/dist/match-detection/features/bib/record-type.js.map +0 -1
  88. package/dist/match-detection/features/bib/standard-identifier-factory.js +0 -188
  89. package/dist/match-detection/features/bib/standard-identifier-factory.js.map +0 -1
  90. package/dist/match-detection/features/bib/title-version-original.js +0 -52
  91. package/dist/match-detection/features/bib/title-version-original.js.map +0 -1
  92. package/dist/match-detection/features/bib/title.js +0 -70
  93. package/dist/match-detection/features/bib/title.js.map +0 -1
  94. package/dist/match-detection/features/index.js +0 -11
  95. package/dist/match-detection/features/index.js.map +0 -1
  96. package/dist/match-detection/index.js +0 -174
  97. package/dist/match-detection/index.js.map +0 -1
  98. package/dist/match-detection/index.spec.js +0 -63
  99. package/dist/match-detection/index.spec.js.map +0 -1
  100. package/dist/matching-utils.js +0 -115
  101. package/dist/matching-utils.js.map +0 -1
@@ -1,10 +1,11 @@
1
1
 
2
+ import assert from 'node:assert';
3
+ import {describe} from 'node:test';
4
+ import createDebugLogger from 'debug';
2
5
  import generateTests from '@natlibfi/fixugen';
3
6
  import {READERS} from '@natlibfi/fixura';
4
- import {expect} from 'chai';
5
7
  import {MarcRecord} from '@natlibfi/marc-record';
6
- import * as features from '.';
7
- import createDebugLogger from 'debug';
8
+ import * as features from './index.js';
8
9
 
9
10
 
10
11
  const debug = createDebugLogger('@natlibfi/melinda-record-matching:match-detection:features/bib:test');
@@ -13,7 +14,7 @@ const debugData = debug.extend('data');
13
14
 
14
15
  describe('match-detection/features/bib/', () => {
15
16
  generateTests({
16
- path: [__dirname, '..', '..', '..', '..', 'test-fixtures', 'match-detection', 'features', 'bib'],
17
+ path: [import.meta.dirname, '..', '..', '..', '..', 'test-fixtures', 'match-detection', 'features', 'bib'],
17
18
  useMetadataFile: true,
18
19
  fixura: {
19
20
  reader: READERS.JSON
@@ -33,7 +34,7 @@ describe('match-detection/features/bib/', () => {
33
34
  debugData(`Record: ${record}`);
34
35
  const {extract} = features[feature](options);
35
36
 
36
- expect(extract({record})).to.eql(expectedFeatures);
37
+ assert.deepStrictEqual(extract({record}), expectedFeatures);
37
38
  return;
38
39
  }
39
40
 
@@ -41,7 +42,7 @@ describe('match-detection/features/bib/', () => {
41
42
  const {featuresA, featuresB, expectedPoints} = expectations;
42
43
  const {compare} = features[feature](options);
43
44
 
44
- expect(compare(featuresA, featuresB)).to.equal(expectedPoints);
45
+ assert.equal(compare(featuresA, featuresB), expectedPoints);
45
46
  return;
46
47
  }
47
48
 
@@ -1,7 +1,7 @@
1
1
 
2
- import createInterface from './standard-identifier-factory';
3
- import {parse as isbnParse} from 'isbn3';
4
2
  import createDebugLogger from 'debug';
3
+ import {parse as isbnParse} from 'isbn3';
4
+ import createInterface from './standard-identifier-factory.js';
5
5
 
6
6
  const debug = createDebugLogger(`@natlibfi/melinda-record-matching:match-detection:features:standard-identifiers:ISBN`);
7
7
  const debugData = debug.extend('data');
@@ -1,5 +1,5 @@
1
1
 
2
- import createInterface from './standard-identifier-factory';
2
+ import createInterface from './standard-identifier-factory.js';
3
3
 
4
4
  export default () => {
5
5
  const {extract, compare} = createInterface({pattern: /^022$/u, subfieldCodes: ['a', 'z', 'y']});
@@ -1,6 +1,6 @@
1
1
 
2
2
  import createDebugLogger from 'debug';
3
- import {getMatchCounts} from '../../../matching-utils';
3
+ import {getMatchCounts} from '../../../matching-utils.js';
4
4
 
5
5
  const debug = createDebugLogger('@natlibfi/melinda-record-matching:match-detection:features:language');
6
6
  const debugData = debug.extend('data');
@@ -12,10 +12,10 @@ export default () => ({
12
12
 
13
13
  const value008 = get008Value();
14
14
  const values041 = get041Values();
15
- debugData(`${label} 008: ${JSON.stringify(value008)}, 041: ${JSON.stringify(values041)}`);
15
+ debugData(`${label}: 008: ${JSON.stringify(value008)}, 041: ${JSON.stringify(values041)}`);
16
16
 
17
17
  if (!value008 && values041.length < 1) {
18
- debugData(`{$label} No actual values found`);
18
+ debugData(`${label}: No actual values found`);
19
19
  return [];
20
20
  }
21
21
 
@@ -26,14 +26,14 @@ export default () => ({
26
26
 
27
27
  function get008Value() {
28
28
  const value = record.get(/^008$/u)?.[0]?.value || undefined;
29
- debugData(`${label} 008 value: ${value}`);
29
+ debugData(`${label}: 008 value: ${value}`);
30
30
 
31
31
  if (!value) {
32
32
  return undefined;
33
33
  }
34
34
 
35
35
  const code = value.slice(35, 38);
36
- debugData(`${label} 008 code: ${code}`);
36
+ debugData(`${label}: 008 code: ${code}`);
37
37
  return isLangCodeForALanguage(code) ? code : undefined;
38
38
  }
39
39
 
@@ -13,7 +13,7 @@ export default () => ({
13
13
  debugData(`Record (${label}): ${JSON.stringify(record)}`);
14
14
  debugData(`RecordExternal: ${JSON.stringify(recordExternal)}`);
15
15
  const values337 = get337Values();
16
- debug(`${label} 337 $b values: ${JSON.stringify(values337)}`);
16
+ debug(`${label}: 337 $b values: ${JSON.stringify(values337)}`);
17
17
 
18
18
  return values337;
19
19
 
@@ -1,5 +1,5 @@
1
1
 
2
- import createInterface from './melinda-identifier-factory';
2
+ import createInterface from './melinda-identifier-factory.js';
3
3
 
4
4
  export default () => {
5
5
  const {extract, compare} = createInterface();
@@ -1,6 +1,6 @@
1
1
 
2
2
  import createDebugLogger from 'debug';
3
- import {getMelindaIdsF035} from '../../../matching-utils';
3
+ import {getMelindaIdsF035} from '../../../matching-utils.js';
4
4
 
5
5
  // 003+001 FI-MELINDA <melinda-id>
6
6
  // 035 $a (FI-MELINDA)<melinda-id>
@@ -38,25 +38,25 @@ export default () => {
38
38
  function compare(a, b) {
39
39
 
40
40
  if (a.isMelindaRecord && b.isMelindaRecord &&
41
- a.f001 === b.f001) {
41
+ a.f001 === b.f001) {
42
42
  debugData(`Melinda record's A f001 ${a.f001} matches Melinda record's B f001 ${a.f001}`);
43
43
  return 1;
44
44
  }
45
45
 
46
46
  if (a.isMelindaRecord && typeof b.f035MelindaIds !== 'undefined' &&
47
- b.f035MelindaIds.some(id => id === a.f001)) {
47
+ b.f035MelindaIds.some(id => id === a.f001)) {
48
48
  debugData(`Melinda record's A f001 ${a.f001} matches record B f035 ${JSON.stringify(b.f035MelindaIds)}`);
49
49
  return 1;
50
50
  }
51
51
 
52
52
  if (b.isMelindaRecord && typeof a.f035MelindaIds !== 'undefined' &&
53
- a.f035MelindaIds.some(id => id === b.f001)) {
53
+ a.f035MelindaIds.some(id => id === b.f001)) {
54
54
  debugData(`Melinda record's B f001 ${b.f001} matches record A f035 ${JSON.stringify(a.f035MelindaIds)}`);
55
55
  return 1;
56
56
  }
57
57
 
58
58
  if (typeof a.f035MelindaIds !== 'undefined' && typeof b.f035MelindaIds !== 'undefined' &&
59
- a.f035MelindaIds.some(idA => b.f035MelindaIds.some(idB => idB === idA))) {
59
+ a.f035MelindaIds.some(idA => b.f035MelindaIds.some(idB => idB === idA))) {
60
60
  debugData(`Record A f035 ${JSON.stringify(a.f035MelindaIds)} matches record B f035 ${JSON.stringify(b.f035MelindaIds)}`);
61
61
  return 1;
62
62
  }
@@ -1,5 +1,5 @@
1
1
 
2
- import createInterface from './standard-identifier-factory';
2
+ import createInterface from './standard-identifier-factory.js';
3
3
 
4
4
  // DEVELOP: we should compare indicators and sf2 for f024
5
5
 
@@ -1,6 +1,6 @@
1
1
 
2
- import {testStringOrNumber} from '../../../matching-utils';
3
2
  import createDebugLogger from 'debug';
3
+ import {testStringOrNumber} from '../../../matching-utils.js';
4
4
 
5
5
  // We should also get copyright time and copyright/publication times from 26x
6
6
  // We should also get publishing time type from f008
@@ -13,13 +13,13 @@ export default () => ({
13
13
  const label = recordExternal && recordExternal.label ? recordExternal.label : 'record';
14
14
 
15
15
  const f008Values = extractF008Values(record);
16
- debug(`${label} f008: ${JSON.stringify(f008Values)}`);
16
+ debug(`${label}: f008: ${JSON.stringify(f008Values)}`);
17
17
 
18
18
  const f26xValues = extractF26xValues(record);
19
- debug(`${label} f26x: ${JSON.stringify(f26xValues)}`);
19
+ debug(`${label}: f26x: ${JSON.stringify(f26xValues)}`);
20
20
 
21
21
  const f500Values = extractF500Years(record);
22
- debug(`${label} f500: ${JSON.stringify(f500Values)}`);
22
+ debug(`${label}: f500: ${JSON.stringify(f500Values)}`);
23
23
 
24
24
  // We should get copyrightYear from f008Date2 to copyrightYears when f008YearType = 'r'
25
25
  // Is the original year (f008Date2) in f008YearType === 'r' comparable to copyrightYear?
@@ -123,7 +123,7 @@ export default () => ({
123
123
  .flat()
124
124
  .filter(({code}) => code === 'a')
125
125
  .map(({value}) => value);
126
- //.filter(value => value.test(reprintRegex));
126
+ //.filter(value => value.test(reprintRegex));
127
127
 
128
128
  debug(`f500 reprint field contents: ${JSON.stringify(reprintFieldContents)}`);
129
129
 
@@ -172,7 +172,7 @@ export default () => ({
172
172
  // Handle consequent years as a match
173
173
  // see publication-time for a version that does not handle consequent years as a match
174
174
  if (!(isNaN(firstANumber) || isNaN(firstBNumber)) &&
175
- (firstANumber + 1 === firstBNumber || firstANumber - 1 === firstBNumber)) {
175
+ (firstANumber + 1 === firstBNumber || firstANumber - 1 === firstBNumber)) {
176
176
  return 0.1;
177
177
  }
178
178
 
@@ -1,6 +1,6 @@
1
1
 
2
- import {testStringOrNumber} from '../../../matching-utils';
3
2
  import createDebugLogger from 'debug';
3
+ import {testStringOrNumber} from '../../../matching-utils.js';
4
4
 
5
5
  // We should also get copyright time and copyright/publication times from 26x
6
6
 
@@ -1,6 +1,6 @@
1
1
 
2
2
 
3
- import {testStringOrNumber} from '../../../matching-utils';
3
+ import {testStringOrNumber} from '../../../matching-utils.js';
4
4
 
5
5
  // We should also get copyright time and copyright/publication times from 26x
6
6
  // see publication-time-allow-cons-years for a version allowing consequent years to match
@@ -1,8 +1,7 @@
1
1
  /* eslint-disable max-statements */
2
2
 
3
-
4
3
  import createDebugLogger from 'debug';
5
- import {extractSubfieldsFromField, uniqueSubfields} from '../../../matching-utils';
4
+ import {extractSubfieldsFromField, uniqueSubfields} from '../../../matching-utils.js';
6
5
 
7
6
  // Note about validity of standardIdentifiers:
8
7
  // We have three types of invalid standardIdentifiers:
@@ -1,6 +1,7 @@
1
1
 
2
2
  import createDebugLogger from 'debug';
3
- import {LevenshteinDistance as leven} from 'natural';
3
+ import naturalPkg from 'natural';
4
+ const {LevenshteinDistance: leven} = naturalPkg;
4
5
 
5
6
  export default ({treshold = 10} = {}) => ({
6
7
  name: 'titleVersionOriginal',
@@ -1,6 +1,7 @@
1
- import {LevenshteinDistance as leven} from 'natural';
2
- import {testStringOrNumber} from '../../../matching-utils';
3
1
  import createDebugLogger from 'debug';
2
+ import naturalPkg from 'natural';
3
+ const {LevenshteinDistance: leven} = naturalPkg;
4
+ import {testStringOrNumber} from '../../../matching-utils.js';
4
5
 
5
6
  const debug = createDebugLogger('@natlibfi/melinda-record-matching:match-detection:features:title');
6
7
  const debugData = debug.extend('data');
@@ -11,7 +12,7 @@ export default ({treshold = 10} = {}) => ({
11
12
  extract: ({record, recordExternal}) => {
12
13
  const label = recordExternal && recordExternal.label ? recordExternal.label : 'record';
13
14
  const title = getTitle();
14
- debug(`${label} title: ${title}`);
15
+ debug(`${label}: title: ${title}`);
15
16
 
16
17
  if (testStringOrNumber(title)) {
17
18
  const titleAsNormalizedString = String(title)
@@ -22,7 +23,7 @@ export default ({treshold = 10} = {}) => ({
22
23
  // - we could precompose the finnish letters back to avoid this
23
24
  .replace(/[^\p{Letter}\p{Number}]/gu, '')
24
25
  .toLowerCase();
25
- debug(`${label} titleString: ${titleAsNormalizedString}`);
26
+ debug(`${label}: titleString: ${titleAsNormalizedString}`);
26
27
  return [titleAsNormalizedString];
27
28
  }
28
29
 
@@ -30,7 +31,7 @@ export default ({treshold = 10} = {}) => ({
30
31
 
31
32
  function getTitle() {
32
33
  const [field] = record.get(/^245$/u);
33
- debugData(`${label} titleField: ${JSON.stringify(field)}`);
34
+ debugData(`${label}: titleField: ${JSON.stringify(field)}`);
34
35
 
35
36
  if (field) {
36
37
  return field.subfields
@@ -1,3 +1,3 @@
1
1
 
2
- import * as bib from './bib';
2
+ import * as bib from './bib/index.js';
3
3
  export {bib};
@@ -1,6 +1,6 @@
1
1
 
2
2
  import createDebugLogger from 'debug';
3
- import * as features from './features';
3
+ import * as features from './features/index.js';
4
4
 
5
5
  export {features};
6
6
 
@@ -1,19 +1,20 @@
1
-
1
+ import assert from 'node:assert';
2
+ import {describe} from 'node:test';
3
+ import createDebugLogger from 'debug';
4
+ import {inspect} from 'util';
2
5
  import generateTests from '@natlibfi/fixugen';
3
6
  import {READERS} from '@natlibfi/fixura';
4
- import {expect} from 'chai';
5
7
  import {MarcRecord} from '@natlibfi/marc-record';
6
- import * as features from './features';
7
- import createDetectionInterface from '.';
8
- import {inspect} from 'util';
9
- import createDebugLogger from 'debug';
8
+
9
+ import createDetectionInterface from './index.js';
10
+ import * as features from './features/index.js';
10
11
 
11
12
  const debug = createDebugLogger('@natlibfi/melinda-record-matching:match-detection:test');
12
13
  const debugData = debug.extend('data');
13
14
 
14
15
  describe('match-detection', () => {
15
16
  generateTests({
16
- path: [__dirname, '..', '..', 'test-fixtures', 'match-detection', 'index'],
17
+ path: [import.meta.dirname, '..', '..', 'test-fixtures', 'match-detection', 'index'],
17
18
  useMetadataFile: true,
18
19
  recurse: false,
19
20
  fixura: {
@@ -39,7 +40,7 @@ describe('match-detection', () => {
39
40
  const results = detect({recordA, recordB});
40
41
  debugData(`${JSON.stringify(results)}`);
41
42
 
42
- expect(results).to.eql(expectedResults);
43
+ assert.deepStrictEqual(results, expectedResults);
43
44
 
44
45
  function formatOptions() {
45
46
  const contextFeatures = features[options.strategy.type];
@@ -15,7 +15,7 @@ export function getMelindaIdsF035(record) {
15
15
  return [];
16
16
  }
17
17
 
18
- const allF035MelindaIds = [].concat(...f035s.map(toMelindaIds));
18
+ const allF035MelindaIds = [].concat(...f035s.map(field => toMelindaIds(field)));
19
19
  const f035MelindaIds = [...new Set(allF035MelindaIds)];
20
20
 
21
21
  debugData(`Fields (${f035s.length}): ${JSON.stringify(f035s)}`);
@@ -23,16 +23,15 @@ export function getMelindaIdsF035(record) {
23
23
  debugData(`Unique ids (${f035MelindaIds.length}): ${JSON.stringify(f035MelindaIds)}`);
24
24
 
25
25
  return f035MelindaIds;
26
+ }
26
27
 
27
- function toMelindaIds({subfields}) {
28
- const melindaIdRegExp = /^(?<prefix>\(FI-MELINDA\)|FCC)(?<id>\d{9})$/u;
29
-
30
- return subfields
31
- .filter(sub => ['a', 'z'].includes(sub.code))
32
- .filter(sub => testStringOrNumber(sub.value) && melindaIdRegExp.test(String(sub.value)))
33
- .map(({value}) => testStringOrNumber(value) ? String(value).replace(melindaIdRegExp, '$<id>') : '');
28
+ export function toMelindaIds({subfields}, subfieldsToParse = ['a', 'z']) {
29
+ const melindaIdRegExp = /^(?<prefix>\(FI-MELINDA\)|FCC)(?<id>\d{9})$/u;
34
30
 
35
- }
31
+ return subfields
32
+ .filter(sub => subfieldsToParse.includes(sub.code))
33
+ .filter(sub => testStringOrNumber(sub.value) && melindaIdRegExp.test(String(sub.value)))
34
+ .map(({value}) => testStringOrNumber(value) ? String(value).replace(melindaIdRegExp, '$<id>') : '');
36
35
  }
37
36
 
38
37
  export function validateSidFieldSubfieldCounts(field) {
@@ -1,29 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.toQueries = toQueries;
7
- var _debug = _interopRequireDefault(require("debug"));
8
- function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
9
- function toQueries(identifiers, queryString) {
10
- const debug = (0, _debug.default)('@natlibfi/melinda-record-matching:toQueries');
11
- const debugData = debug.extend('data');
12
-
13
- // We quote the identifier, if it contains a slash! (Slash in non-quoted SRU-search breaks search.)
14
- const quotedIdentifiers = identifiers.map(identifier => identifier.match(/\//u) ? `"${identifier}"` : `${identifier}`);
15
-
16
- // Aleph supports only two queries with or -operator (This is not actually true)
17
- const pairs = toPairs(quotedIdentifiers);
18
- const queries = pairs.map(([a, b]) => b ? `${queryString}=${a} or ${queryString}=${b}` : `${queryString}=${a}`);
19
- debugData(`Pairs (${pairs.length}): ${JSON.stringify(pairs)}`);
20
- debugData(`Queries (${queries.length}): ${JSON.stringify(queries)}`);
21
- return queries;
22
- }
23
- function toPairs(array) {
24
- if (array.length === 0) {
25
- return [];
26
- }
27
- return [array.slice(0, 2)].concat(toPairs(array.slice(2), 2));
28
- }
29
- //# sourceMappingURL=candidate-search-utils.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"candidate-search-utils.js","names":["_debug","_interopRequireDefault","require","e","__esModule","default","toQueries","identifiers","queryString","debug","createDebugLogger","debugData","extend","quotedIdentifiers","map","identifier","match","pairs","toPairs","queries","a","b","length","JSON","stringify","array","slice","concat"],"sources":["../../src/candidate-search/candidate-search-utils.js"],"sourcesContent":["import createDebugLogger from 'debug';\n\nexport function toQueries(identifiers, queryString) {\n\n const debug = createDebugLogger('@natlibfi/melinda-record-matching:toQueries');\n const debugData = debug.extend('data');\n\n // We quote the identifier, if it contains a slash! (Slash in non-quoted SRU-search breaks search.)\n const quotedIdentifiers = identifiers.map(identifier => identifier.match(/\\//u) ? `\"${identifier}\"` : `${identifier}`);\n\n // Aleph supports only two queries with or -operator (This is not actually true)\n const pairs = toPairs(quotedIdentifiers);\n const queries = pairs.map(([a, b]) => b ? `${queryString}=${a} or ${queryString}=${b}` : `${queryString}=${a}`);\n\n debugData(`Pairs (${pairs.length}): ${JSON.stringify(pairs)}`);\n debugData(`Queries (${queries.length}): ${JSON.stringify(queries)}`);\n\n return queries;\n}\n\nfunction toPairs(array) {\n if (array.length === 0) {\n return [];\n }\n return [array.slice(0, 2)].concat(toPairs(array.slice(2), 2));\n}\n"],"mappings":";;;;;;AAAA,IAAAA,MAAA,GAAAC,sBAAA,CAAAC,OAAA;AAAsC,SAAAD,uBAAAE,CAAA,WAAAA,CAAA,IAAAA,CAAA,CAAAC,UAAA,GAAAD,CAAA,KAAAE,OAAA,EAAAF,CAAA;AAE/B,SAASG,SAASA,CAACC,WAAW,EAAEC,WAAW,EAAE;EAElD,MAAMC,KAAK,GAAG,IAAAC,cAAiB,EAAC,6CAA6C,CAAC;EAC9E,MAAMC,SAAS,GAAGF,KAAK,CAACG,MAAM,CAAC,MAAM,CAAC;;EAEtC;EACA,MAAMC,iBAAiB,GAAGN,WAAW,CAACO,GAAG,CAACC,UAAU,IAAIA,UAAU,CAACC,KAAK,CAAC,KAAK,CAAC,GAAG,IAAID,UAAU,GAAG,GAAG,GAAGA,UAAU,EAAE,CAAC;;EAEtH;EACA,MAAME,KAAK,GAAGC,OAAO,CAACL,iBAAiB,CAAC;EACxC,MAAMM,OAAO,GAAGF,KAAK,CAACH,GAAG,CAAC,CAAC,CAACM,CAAC,EAAEC,CAAC,CAAC,KAAKA,CAAC,GAAG,GAAGb,WAAW,IAAIY,CAAC,OAAOZ,WAAW,IAAIa,CAAC,EAAE,GAAG,GAAGb,WAAW,IAAIY,CAAC,EAAE,CAAC;EAE/GT,SAAS,CAAC,UAAUM,KAAK,CAACK,MAAM,MAAMC,IAAI,CAACC,SAAS,CAACP,KAAK,CAAC,EAAE,CAAC;EAC9DN,SAAS,CAAC,YAAYQ,OAAO,CAACG,MAAM,MAAMC,IAAI,CAACC,SAAS,CAACL,OAAO,CAAC,EAAE,CAAC;EAEpE,OAAOA,OAAO;AAChB;AAEA,SAASD,OAAOA,CAACO,KAAK,EAAE;EACtB,IAAIA,KAAK,CAACH,MAAM,KAAK,CAAC,EAAE;IACtB,OAAO,EAAE;EACX;EACA,OAAO,CAACG,KAAK,CAACC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAACC,MAAM,CAACT,OAAO,CAACO,KAAK,CAACC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AAC/D","ignoreList":[]}
@@ -1,122 +0,0 @@
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 && {}.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(e) { return e && e.__esModule ? e : { default: e }; }
13
- class CandidateSearchError extends Error {}
14
- exports.CandidateSearchError = CandidateSearchError;
15
- async function _default({
16
- url,
17
- queryList,
18
- queryListType,
19
- maxCandidates = 50
20
- }) {
21
- const debug = (0, _debug.default)('@natlibfi/melinda-record-matching:candidate-search:choose-queries');
22
- const debugData = debug.extend('data');
23
- const debugDev = debug.extend('dev');
24
- debugData(`Url: ${url}`);
25
- debugData(`QueryList: ${queryList}`);
26
- debugData(`queryListType: ${queryListType}`);
27
- const client = (0, _sruClient.default)({
28
- url,
29
- maxRecordsPerRequest: 0,
30
- version: '2.0',
31
- retrieveAll: false
32
- });
33
- debugDev(`QueryList (type: ${queryListType}) ${JSON.stringify(queryList)}`);
34
- try {
35
- const {
36
- queriesWithTotals
37
- } = await getQueryTotals({
38
- queryList,
39
- queryOffset: 0,
40
- queriesWithTotals: []
41
- });
42
- debugDev(`QueryResult: ${JSON.stringify(queriesWithTotals)}`);
43
- const filteredQueryResult = filterQueryResult({
44
- queriesWithTotals,
45
- maxCandidates
46
- });
47
- debugDev(`filteredQueryResult: ${JSON.stringify(filteredQueryResult)}`);
48
- return filteredQueryResult;
49
- } catch (err) {
50
- throw new CandidateSearchError(err);
51
- }
52
- async function getQueryTotals({
53
- queryList,
54
- queryOffset = 0,
55
- queriesWithTotals = []
56
- }) {
57
- const query = queryList[queryOffset];
58
- debug(`Running query ${JSON.stringify(query)} (${queryOffset}) for total`);
59
- if (query) {
60
- const {
61
- total
62
- } = await retrieveTotal();
63
- const newQueriesWithTotals = [...queriesWithTotals, {
64
- query,
65
- total
66
- }];
67
- debug(`Query ${queryOffset} ${query} done.`);
68
- debug(`There are (${queryList.length - (queryOffset + 1)} queries left)`);
69
- return getQueryTotals({
70
- queryList,
71
- queryOffset: queryOffset + 1,
72
- queriesWithTotals: newQueriesWithTotals
73
- });
74
- }
75
- debug(`All ${queryList.length} queries done, there's no query for ${queryOffset}`);
76
- return {
77
- queriesWithTotals
78
- };
79
- function retrieveTotal() {
80
- return new Promise((resolve, reject) => {
81
- // eslint-disable-next-line functional/no-let
82
- let totalRecords = 0;
83
- debug(`Searching total amount of candidates for query: ${query}`);
84
- client.searchRetrieve(query).on('error', err => {
85
- // eslint-disable-next-line functional/no-conditional-statements
86
- if (err instanceof _sruClient.SruSearchError) {
87
- debug(`SRU SruSearchError for query: ${query}: ${err}`);
88
- reject(new CandidateSearchError(`SRU SruSearchError for query: ${query}: ${err}`));
89
- }
90
- debug(`SRU error for query: ${query}: ${err}`);
91
- reject(new CandidateSearchError(`SRU error for query: ${query}: ${err}`));
92
- }).on('total', total => {
93
- debug(`Got total: ${total}`);
94
- totalRecords += total;
95
- }).on('end', () => {
96
- try {
97
- resolve({
98
- total: totalRecords
99
- });
100
- } catch (err) {
101
- debug(`Error caught on END`);
102
- reject(err);
103
- }
104
- }).on('record', () => {
105
- debugDev(`RECORD: We should no get records here`);
106
- });
107
- });
108
- }
109
- }
110
- function filterQueryResult({
111
- queriesWithTotals,
112
- maxCandidates
113
- }) {
114
- debug(`Filtering queries (${queriesWithTotals.length}), maxCandidates: ${maxCandidates}`);
115
- debugData(`${JSON.stringify(queriesWithTotals)}`);
116
- // Drop queries where total result is 0 or greater than given maxCandidates
117
- const filteredQueryResult = queriesWithTotals.filter(queryWithTotal => queryWithTotal.total !== 0 && queryWithTotal.total < maxCandidates);
118
- debugData(`${JSON.stringify(filteredQueryResult)}`);
119
- return filteredQueryResult;
120
- }
121
- }
122
- //# sourceMappingURL=choose-queries.js.map
@@ -1 +0,0 @@
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","hasOwnProperty","call","i","set","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":["import 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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","ignoreList":[]}