@natlibfi/marc-record-merge 6.0.0-beta.8 → 7.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.
- package/.github/CODEOWNERS +2 -9
- package/.github/dependabot.yml +2 -3
- package/.github/workflows/melinda-node-tests.yml +2 -2
- package/README.md +16 -0
- package/dist/index.js +49 -4
- package/dist/index.js.map +1 -1
- package/dist/index.spec.js +59 -0
- package/dist/index.spec.js.map +1 -0
- package/dist/reducers/copy.js +59 -148
- package/dist/reducers/copy.js.map +1 -1
- package/dist/reducers/copy.spec.js +9 -12
- package/dist/reducers/copy.spec.js.map +1 -1
- package/dist/reducers/copy2.spec.js +66 -0
- package/dist/reducers/copy2.spec.js.map +1 -0
- package/dist/reducers/index.js +0 -6
- package/dist/reducers/index.js.map +1 -1
- package/dist/reducers/select.js +43 -40
- package/dist/reducers/select.js.map +1 -1
- package/dist/reducers/select.spec.js +4 -15
- package/dist/reducers/select.spec.js.map +1 -1
- package/dist/reducers/select2.spec.js +58 -0
- package/dist/reducers/select2.spec.js.map +1 -0
- package/package.json +18 -18
- package/src/index.js +51 -1
- package/src/index.spec.js +45 -0
- package/src/reducers/copy.js +42 -103
- package/src/reducers/copy.spec.js +4 -6
- package/src/reducers/copy2.spec.js +55 -0
- package/src/reducers/select.js +31 -10
- package/src/reducers/select2.spec.js +49 -0
- package/test-fixtures/index/01/base.json +24 -0
- package/test-fixtures/index/01/merged.json +24 -0
- package/test-fixtures/index/01/metadata.json +8 -0
- package/test-fixtures/index/01/source.json +40 -0
- package/test-fixtures/index/02/base.json +24 -0
- package/test-fixtures/index/02/merged.json +24 -0
- package/test-fixtures/index/02/metadata.json +7 -0
- package/test-fixtures/index/02/source.json +40 -0
- package/test-fixtures/reducers/copy/04 - compareWithoutIndicators/03/metadata.json +6 -0
- package/test-fixtures/reducers/copy/04 - compareWithoutIndicators/04/base.json +20 -0
- package/test-fixtures/reducers/copy/04 - compareWithoutIndicators/04/merged.json +31 -0
- package/test-fixtures/reducers/copy/04 - compareWithoutIndicators/04/metadata.json +5 -0
- package/test-fixtures/reducers/copy/04 - compareWithoutIndicators/04/source.json +20 -0
- package/test-fixtures/reducers/copy/11 - compareWithoutTag/01/base.json +28 -0
- package/test-fixtures/reducers/copy/11 - compareWithoutTag/01/merged.json +28 -0
- package/test-fixtures/reducers/copy/11 - compareWithoutTag/01/metadata.json +6 -0
- package/test-fixtures/reducers/copy/11 - compareWithoutTag/01/source.json +20 -0
- package/test-fixtures/reducers/copy/11 - compareWithoutTag/02/base.json +28 -0
- package/test-fixtures/reducers/copy/11 - compareWithoutTag/02/merged.json +39 -0
- package/test-fixtures/reducers/copy/11 - compareWithoutTag/02/metadata.json +6 -0
- package/test-fixtures/reducers/copy/11 - compareWithoutTag/02/source.json +31 -0
- package/test-fixtures/reducers/copy/11 - compareWithoutTag/03/base.json +28 -0
- package/test-fixtures/reducers/copy/11 - compareWithoutTag/03/merged.json +28 -0
- package/test-fixtures/reducers/copy/11 - compareWithoutTag/03/metadata.json +7 -0
- package/test-fixtures/reducers/copy/11 - compareWithoutTag/03/source.json +20 -0
- package/test-fixtures/reducers/copy/11 - compareWithoutTag/04/base.json +17 -0
- package/test-fixtures/reducers/copy/11 - compareWithoutTag/04/merged.json +28 -0
- package/test-fixtures/reducers/copy/11 - compareWithoutTag/04/metadata.json +7 -0
- package/test-fixtures/reducers/copy/11 - compareWithoutTag/04/source.json +31 -0
- package/test-fixtures/reducers/copy/11 - compareWithoutTag/05/base.json +28 -0
- package/test-fixtures/reducers/copy/11 - compareWithoutTag/05/merged.json +28 -0
- package/test-fixtures/reducers/copy/11 - compareWithoutTag/05/metadata.json +7 -0
- package/test-fixtures/reducers/copy/11 - compareWithoutTag/05/source.json +28 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"select.spec.js","names":["MarcRecord","setValidationOptions","subfieldValues","generateTests","callback","path","__dirname","useMetadataFile","recurse","fixura","reader","READERS","JSON","failWhenNotFound","getFixture","disabled","tagPatternRegExp","expectedError","useSubsetEquality","console","log","base","source","tagPattern","RegExp","expectedRecord","equalityFunction","subsetEquality","undefined","expect","createReducer","to","throw","Error","mergedRecord","eql"],"sources":["../../src/reducers/select.spec.js"],"sourcesContent":["import {expect} from 'chai';\nimport {MarcRecord} from '@natlibfi/marc-record';\nimport createReducer, {subsetEquality} from './select';\nimport {READERS} from '@natlibfi/fixura';\nimport generateTests from '@natlibfi/fixugen';\n\nMarcRecord.setValidationOptions({subfieldValues: false});\n\ngenerateTests({\n callback,\n path: [__dirname, '..', '..', 'test-fixtures', 'reducers', 'select'],\n useMetadataFile: true,\n recurse: false,\n fixura: {\n reader: READERS.JSON,\n failWhenNotFound: false\n }\n});\n\nfunction callback({\n getFixture,\n disabled = false,\n tagPatternRegExp = false,\n expectedError = false,\n useSubsetEquality = false\n}) {\n if (disabled) {\n console.log('TEST DISABLED!'); // eslint-disable-line no-console\n return;\n }\n // const base = new MarcRecord(getFixture('base.json'), {subfieldValues: false});\n // const source = new MarcRecord(getFixture('source.json'), {subfieldValues: false});\n\n const base = getFixture('base.json');\n const source = getFixture('source.json');\n\n const tagPattern = new RegExp(tagPatternRegExp, 'u');\n const expectedRecord = getFixture('merged.json');\n const equalityFunction = useSubsetEquality ? subsetEquality : undefined;\n\n // Bypass expected error in testing\n if (expectedError) {\n expect(() => createReducer.to.throw(Error, 'control field'));\n return;\n }\n\n const mergedRecord = createReducer({tagPattern, equalityFunction})(base, source);\n expect(mergedRecord).to.eql(expectedRecord);\n}\n"],"mappings":";;AAAA
|
|
1
|
+
{"version":3,"file":"select.spec.js","names":["_chai","require","_marcRecord","_select","_interopRequireWildcard","_fixura","_fixugen","_interopRequireDefault","obj","__esModule","default","_getRequireWildcardCache","nodeInterop","WeakMap","cacheBabelInterop","cacheNodeInterop","cache","has","get","newObj","hasPropertyDescriptor","Object","defineProperty","getOwnPropertyDescriptor","key","prototype","hasOwnProperty","call","desc","set","MarcRecord","setValidationOptions","subfieldValues","generateTests","callback","path","__dirname","useMetadataFile","recurse","fixura","reader","READERS","JSON","failWhenNotFound","getFixture","disabled","tagPatternRegExp","expectedError","useSubsetEquality","console","log","base","source","tagPattern","RegExp","expectedRecord","equalityFunction","subsetEquality","undefined","expect","createReducer","to","throw","Error","mergedRecord","eql"],"sources":["../../src/reducers/select.spec.js"],"sourcesContent":["import {expect} from 'chai';\nimport {MarcRecord} from '@natlibfi/marc-record';\nimport createReducer, {subsetEquality} from './select';\nimport {READERS} from '@natlibfi/fixura';\nimport generateTests from '@natlibfi/fixugen';\n\nMarcRecord.setValidationOptions({subfieldValues: false});\n\ngenerateTests({\n callback,\n path: [__dirname, '..', '..', 'test-fixtures', 'reducers', 'select'],\n useMetadataFile: true,\n recurse: false,\n fixura: {\n reader: READERS.JSON,\n failWhenNotFound: false\n }\n});\n\nfunction callback({\n getFixture,\n disabled = false,\n tagPatternRegExp = false,\n expectedError = false,\n useSubsetEquality = false\n}) {\n if (disabled) {\n console.log('TEST DISABLED!'); // eslint-disable-line no-console\n return;\n }\n // const base = new MarcRecord(getFixture('base.json'), {subfieldValues: false});\n // const source = new MarcRecord(getFixture('source.json'), {subfieldValues: false});\n\n const base = getFixture('base.json');\n const source = getFixture('source.json');\n\n const tagPattern = new RegExp(tagPatternRegExp, 'u');\n const expectedRecord = getFixture('merged.json');\n const equalityFunction = useSubsetEquality ? subsetEquality : undefined;\n\n // Bypass expected error in testing\n if (expectedError) {\n expect(() => createReducer.to.throw(Error, 'control field'));\n return;\n }\n\n const mergedRecord = createReducer({tagPattern, equalityFunction})(base, source);\n expect(mergedRecord).to.eql(expectedRecord);\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _chai = require("chai");
|
|
4
|
+
var _marcRecord = require("@natlibfi/marc-record");
|
|
5
|
+
var _select = _interopRequireWildcard(require("./select"));
|
|
6
|
+
var _fixura = require("@natlibfi/fixura");
|
|
7
|
+
var _fixugen = _interopRequireDefault(require("@natlibfi/fixugen"));
|
|
8
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
9
|
+
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
|
|
10
|
+
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
|
11
|
+
_marcRecord.MarcRecord.setValidationOptions({
|
|
12
|
+
subfieldValues: false
|
|
13
|
+
});
|
|
14
|
+
(0, _fixugen.default)({
|
|
15
|
+
callback,
|
|
16
|
+
path: [__dirname, '..', '..', 'test-fixtures', 'reducers', 'select'],
|
|
17
|
+
useMetadataFile: true,
|
|
18
|
+
recurse: false,
|
|
19
|
+
fixura: {
|
|
20
|
+
reader: _fixura.READERS.JSON,
|
|
21
|
+
failWhenNotFound: false
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
function callback({
|
|
25
|
+
getFixture,
|
|
26
|
+
disabled = false,
|
|
27
|
+
tagPatternRegExp = false,
|
|
28
|
+
expectedError = false,
|
|
29
|
+
useSubsetEquality = false
|
|
30
|
+
}) {
|
|
31
|
+
if (disabled) {
|
|
32
|
+
console.log('TEST DISABLED!'); // eslint-disable-line no-console
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
// const base = new MarcRecord(getFixture('base.json'), {subfieldValues: false});
|
|
36
|
+
// const source = new MarcRecord(getFixture('source.json'), {subfieldValues: false});
|
|
37
|
+
|
|
38
|
+
const base = getFixture('base.json');
|
|
39
|
+
const source = getFixture('source.json');
|
|
40
|
+
const tagPattern = new RegExp(tagPatternRegExp, 'u');
|
|
41
|
+
const expectedRecord = getFixture('merged.json');
|
|
42
|
+
const equalityFunction = useSubsetEquality ? _select.subsetEquality : undefined;
|
|
43
|
+
|
|
44
|
+
// Bypass expected error in testing
|
|
45
|
+
if (expectedError) {
|
|
46
|
+
(0, _chai.expect)(() => _select.default.to.throw(Error, 'control field'));
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
const mergedRecord = (0, _select.default)({
|
|
50
|
+
tagPattern,
|
|
51
|
+
equalityFunction
|
|
52
|
+
})({
|
|
53
|
+
base,
|
|
54
|
+
source
|
|
55
|
+
});
|
|
56
|
+
(0, _chai.expect)(mergedRecord).to.eql(expectedRecord);
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=select2.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"select2.spec.js","names":["_chai","require","_marcRecord","_select","_interopRequireWildcard","_fixura","_fixugen","_interopRequireDefault","obj","__esModule","default","_getRequireWildcardCache","nodeInterop","WeakMap","cacheBabelInterop","cacheNodeInterop","cache","has","get","newObj","hasPropertyDescriptor","Object","defineProperty","getOwnPropertyDescriptor","key","prototype","hasOwnProperty","call","desc","set","MarcRecord","setValidationOptions","subfieldValues","generateTests","callback","path","__dirname","useMetadataFile","recurse","fixura","reader","READERS","JSON","failWhenNotFound","getFixture","disabled","tagPatternRegExp","expectedError","useSubsetEquality","console","log","base","source","tagPattern","RegExp","expectedRecord","equalityFunction","subsetEquality","undefined","expect","createReducer","to","throw","Error","mergedRecord","eql"],"sources":["../../src/reducers/select2.spec.js"],"sourcesContent":["import {expect} from 'chai';\nimport {MarcRecord} from '@natlibfi/marc-record';\nimport createReducer, {subsetEquality} from './select';\nimport {READERS} from '@natlibfi/fixura';\nimport generateTests from '@natlibfi/fixugen';\n\nMarcRecord.setValidationOptions({subfieldValues: false});\n\ngenerateTests({\n callback,\n path: [__dirname, '..', '..', 'test-fixtures', 'reducers', 'select'],\n useMetadataFile: true,\n recurse: false,\n fixura: {\n reader: READERS.JSON,\n failWhenNotFound: false\n }\n});\n\nfunction callback({\n getFixture,\n disabled = false,\n tagPatternRegExp = false,\n expectedError = false,\n useSubsetEquality = false\n}) {\n if (disabled) {\n console.log('TEST DISABLED!'); // eslint-disable-line no-console\n return;\n }\n // const base = new MarcRecord(getFixture('base.json'), {subfieldValues: false});\n // const source = new MarcRecord(getFixture('source.json'), {subfieldValues: false});\n\n const base = getFixture('base.json');\n const source = getFixture('source.json');\n\n const tagPattern = new RegExp(tagPatternRegExp, 'u');\n const expectedRecord = getFixture('merged.json');\n const equalityFunction = useSubsetEquality ? subsetEquality : undefined;\n\n // Bypass expected error in testing\n if (expectedError) {\n expect(() => createReducer.to.throw(Error, 'control field'));\n return;\n }\n\n const mergedRecord = createReducer({tagPattern, equalityFunction})({base, source});\n expect(mergedRecord).to.eql(expectedRecord);\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -14,10 +14,10 @@
|
|
|
14
14
|
"url": "git@github.com:natlibfi/marc-record-merge-js.git"
|
|
15
15
|
},
|
|
16
16
|
"license": "MIT",
|
|
17
|
-
"version": "
|
|
17
|
+
"version": "7.0.0-alpha.1",
|
|
18
18
|
"main": "./dist/index.js",
|
|
19
19
|
"engines": {
|
|
20
|
-
"node": ">=
|
|
20
|
+
"node": ">=18"
|
|
21
21
|
},
|
|
22
22
|
"type": "commonjs",
|
|
23
23
|
"scripts": {
|
|
@@ -25,8 +25,8 @@
|
|
|
25
25
|
"prepublishOnly": "npm run build:transpile",
|
|
26
26
|
"lint": "eslint ./src",
|
|
27
27
|
"lint:dev": "eslint ./src --fix",
|
|
28
|
-
"test:base": "cross-env NODE_ENV=test mocha --require @babel/register --reporter-option maxDiffSize=15000
|
|
29
|
-
"test": "npm run lint && npm run test:base",
|
|
28
|
+
"test:base": "cross-env NODE_ENV=test mocha --require @babel/register --reporter-option maxDiffSize=15000",
|
|
29
|
+
"test": "npm run lint && npm run test:base -- --recursive src",
|
|
30
30
|
"test:dev": "npm run lint:dev && npm run coverage",
|
|
31
31
|
"coverage": "npm run coverage:unit && npm run coverage:report",
|
|
32
32
|
"coverage:unit": "nyc --silent npm run test:base",
|
|
@@ -37,26 +37,26 @@
|
|
|
37
37
|
"dev:test:debug": "cross-env DEBUG=@natlibfi/* NODE_ENV=test nodemon -w src -w test-fixtures --exec 'clear && npm run test:dev'"
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
|
-
"@natlibfi/
|
|
41
|
-
"@natlibfi/fixura": "^2.2.1",
|
|
42
|
-
"@natlibfi/marc-record": "^7.1.0-alpha.2",
|
|
40
|
+
"@natlibfi/marc-record": "^7.2.2",
|
|
43
41
|
"debug": "^4.3.4",
|
|
44
|
-
"normalize-diacritics": "2.
|
|
42
|
+
"normalize-diacritics": "^2.13.2"
|
|
45
43
|
},
|
|
46
44
|
"devDependencies": {
|
|
47
|
-
"@babel/cli": "^7.
|
|
48
|
-
"@babel/core": "^7.
|
|
49
|
-
"@babel/eslint-parser": "^7.
|
|
50
|
-
"@babel/preset-env": "^7.
|
|
51
|
-
"@babel/register": "^7.
|
|
52
|
-
"@natlibfi/eslint-config-melinda-backend": "^
|
|
45
|
+
"@babel/cli": "^7.21.0",
|
|
46
|
+
"@babel/core": "^7.21.4",
|
|
47
|
+
"@babel/eslint-parser": "^7.21.3",
|
|
48
|
+
"@babel/preset-env": "^7.21.4",
|
|
49
|
+
"@babel/register": "^7.21.0",
|
|
50
|
+
"@natlibfi/eslint-config-melinda-backend": "^3.0.0",
|
|
53
51
|
"babel-plugin-istanbul": "^6.1.1",
|
|
54
52
|
"babel-plugin-rewire": "^1.2.0",
|
|
55
|
-
"chai": "^4.3.
|
|
53
|
+
"chai": "^4.3.7",
|
|
56
54
|
"cross-env": "^7.0.3",
|
|
57
|
-
"eslint": "^8.
|
|
58
|
-
"mocha": "^10.
|
|
59
|
-
"
|
|
55
|
+
"eslint": "^8.38.0",
|
|
56
|
+
"mocha": "^10.2.0",
|
|
57
|
+
"@natlibfi/fixugen": "2.0.0",
|
|
58
|
+
"@natlibfi/fixura": "^3.0.0",
|
|
59
|
+
"nodemon": "^2.0.22",
|
|
60
60
|
"nyc": "^15.1.0"
|
|
61
61
|
},
|
|
62
62
|
"eslintConfig": {
|
package/src/index.js
CHANGED
|
@@ -1,4 +1,54 @@
|
|
|
1
1
|
import Reducers from './reducers';
|
|
2
|
+
import createDebugLogger from 'debug';
|
|
3
|
+
|
|
4
|
+
const debug = createDebugLogger('@natlibfi/melinda-marc-record-merge:index');
|
|
5
|
+
const debugData = debug.extend('data');
|
|
2
6
|
|
|
3
7
|
export {Reducers};
|
|
4
|
-
export default ({base, source, reducers}) => reducers.reduce((base, reducer) => reducer(base, source), base);
|
|
8
|
+
// export default ({base, source, reducers}) => reducers.reduce((base, reducer) => reducer(base, source), base);
|
|
9
|
+
|
|
10
|
+
// NV: Modified the reducer loop so, that not only base, but also is carried back.
|
|
11
|
+
// However, we try to be backward-compatible: normally after the reducers, only base is returned.
|
|
12
|
+
|
|
13
|
+
export default ({base, source, reducers}) => {
|
|
14
|
+
|
|
15
|
+
const combo = {base, source};
|
|
16
|
+
const resultCombo = reducers.reduce((combo, reducer) => {
|
|
17
|
+
const returnCombo = singleRound(reducer, combo.base, combo.source);
|
|
18
|
+
//debugData(`returnCombo after current reducer: ${JSON.stringify(returnCombo)}`);
|
|
19
|
+
return returnCombo;
|
|
20
|
+
}, combo);
|
|
21
|
+
|
|
22
|
+
debugData(`ResultCombo after reducers: ${JSON.stringify(resultCombo)}`);
|
|
23
|
+
|
|
24
|
+
// Hack to make my melinda-marc-record-merge-reducers single tests that expect both
|
|
25
|
+
// base and source to return them both:
|
|
26
|
+
if (reducers.length === 1 && resultCombo.base && resultCombo.source) {
|
|
27
|
+
debug('Single reducer, returning resultCombo');
|
|
28
|
+
debugData(JSON.stringify(resultCombo));
|
|
29
|
+
|
|
30
|
+
return resultCombo;
|
|
31
|
+
}
|
|
32
|
+
// All other tests return just base... Backward (compability) it is!
|
|
33
|
+
debug('Multiple reducers, returning just base');
|
|
34
|
+
debugData(JSON.stringify(resultCombo.base));
|
|
35
|
+
return resultCombo.base;
|
|
36
|
+
|
|
37
|
+
function singleRound(reducer, base, source) {
|
|
38
|
+
//debug(`SINGLE ROUND INPUT (base, source)`);
|
|
39
|
+
//debugData(base);
|
|
40
|
+
//debugData(base);
|
|
41
|
+
const reducerResult = reducer(base, source);
|
|
42
|
+
//debug(`reducerResult:`);
|
|
43
|
+
//debugData(reducerResult);
|
|
44
|
+
if (reducerResult.base !== undefined && reducerResult.source !== undefined) {
|
|
45
|
+
debug('NEW STYLE REDUCER RESULT v2');
|
|
46
|
+
const combo = reducerResult;
|
|
47
|
+
//debugData(combo);
|
|
48
|
+
return combo;
|
|
49
|
+
}
|
|
50
|
+
debug('OLD SCHOOL REDUCER RESULT v2');
|
|
51
|
+
//debugData({base: reducerResult, source});
|
|
52
|
+
return {base: reducerResult, source};
|
|
53
|
+
}
|
|
54
|
+
};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import merger, {Reducers} from './index';
|
|
2
|
+
import {inspect} from 'util';
|
|
3
|
+
import createDebugLogger from 'debug';
|
|
4
|
+
import {expect} from 'chai';
|
|
5
|
+
import {MarcRecord} from '@natlibfi/marc-record';
|
|
6
|
+
import {READERS} from '@natlibfi/fixura';
|
|
7
|
+
import generateTests from '@natlibfi/fixugen';
|
|
8
|
+
|
|
9
|
+
generateTests({
|
|
10
|
+
callback,
|
|
11
|
+
path: [__dirname, '..', 'test-fixtures', 'index'],
|
|
12
|
+
recurse: false,
|
|
13
|
+
useMetadataFile: true,
|
|
14
|
+
fixura: {
|
|
15
|
+
failWhenNotFound: false,
|
|
16
|
+
reader: READERS.JSON
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
function callback({getFixture, reducerConfigs = []}) {
|
|
21
|
+
const base = new MarcRecord(getFixture('base.json'), {subfieldValues: false});
|
|
22
|
+
const source = new MarcRecord(getFixture('source.json'), {subfieldValues: false});
|
|
23
|
+
const expectedRecord = getFixture('merged.json');
|
|
24
|
+
|
|
25
|
+
const debug = createDebugLogger('@natlibfi/melinda-marc-record-merge-reducers:index:test');
|
|
26
|
+
const debugData = debug.extend('data');
|
|
27
|
+
|
|
28
|
+
const testReducerConfigs = reducerConfigs;
|
|
29
|
+
const reducers = [...testReducerConfigs.map(conf => Reducers.copy(conf))];
|
|
30
|
+
|
|
31
|
+
debugData(`Reducers: ${inspect(reducers, {colors: true, maxArrayLength: 10, depth: 8})})}`);
|
|
32
|
+
|
|
33
|
+
const result = merger({base, source, reducers});
|
|
34
|
+
|
|
35
|
+
debug(`Merge result is: ${result.constructor.name}`);
|
|
36
|
+
debugData(`${JSON.stringify(result)}`);
|
|
37
|
+
|
|
38
|
+
// Use either result.base or a plain result as resultRecord
|
|
39
|
+
// It can also be a MarcRecord or a plain object
|
|
40
|
+
const resultRecord = result.base || result;
|
|
41
|
+
const resultRecordToRecord = new MarcRecord(resultRecord, {subfieldValues: false});
|
|
42
|
+
expect(resultRecordToRecord.toObject()).to.eql(expectedRecord);
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
}
|
package/src/reducers/copy.js
CHANGED
|
@@ -7,7 +7,10 @@ import createDebugLogger from 'debug';
|
|
|
7
7
|
export default ({
|
|
8
8
|
tagPattern,
|
|
9
9
|
compareTagsOnly = false,
|
|
10
|
+
compareWithoutTag = false,
|
|
10
11
|
compareWithoutIndicators = false,
|
|
12
|
+
compareWithoutIndicator1 = false,
|
|
13
|
+
compareWithoutIndicator2 = false,
|
|
11
14
|
subfieldsMustBeIdentical = true,
|
|
12
15
|
excludeSubfields = [],
|
|
13
16
|
dropSubfields = [],
|
|
@@ -18,15 +21,37 @@ export default ({
|
|
|
18
21
|
swapSubfieldCode = [],
|
|
19
22
|
doNotCopyIfFieldPresent = false
|
|
20
23
|
}) => (base, source) => {
|
|
21
|
-
const baseRecord = new MarcRecord(base, baseValidators);
|
|
22
|
-
const sourceRecord = new MarcRecord(source, sourceValidators);
|
|
23
24
|
|
|
24
|
-
const debug = createDebugLogger('@natlibfi/marc-record-merge');
|
|
25
|
+
const debug = createDebugLogger('@natlibfi/marc-record-merge:copy');
|
|
26
|
+
const debugData = debug.extend('data');
|
|
25
27
|
const debugOptions = createDebugLogger('@natlibfi/marc-record-merge:compare-options');
|
|
26
28
|
const debugCompare = createDebugLogger('@natlibfi/marc-record-merge:compare');
|
|
29
|
+
|
|
30
|
+
debugData(`base: ${JSON.stringify(base)}`);
|
|
31
|
+
debugData(`source: ${JSON.stringify(source)}`);
|
|
32
|
+
|
|
33
|
+
const {baseRecord, sourceRecord} = getRecordsFromParameters(base, source, baseValidators, sourceValidators);
|
|
34
|
+
|
|
35
|
+
function getRecordsFromParameters(base, source, baseValidators, sourceValidators) {
|
|
36
|
+
// records if we got an object ({base, source}) as a parameter
|
|
37
|
+
if (source === undefined && base.base !== undefined && base.source !== undefined) {
|
|
38
|
+
const baseRecord = new MarcRecord(base.base, baseValidators);
|
|
39
|
+
const sourceRecord = new MarcRecord(base.source, sourceValidators);
|
|
40
|
+
return {baseRecord, sourceRecord};
|
|
41
|
+
}
|
|
42
|
+
// records if we got an non-object (base, source) as a parameter
|
|
43
|
+
const baseRecord = new MarcRecord(base, baseValidators);
|
|
44
|
+
const sourceRecord = new MarcRecord(source, sourceValidators);
|
|
45
|
+
return {baseRecord, sourceRecord};
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const ignoreInd1 = compareWithoutIndicators || compareWithoutIndicator1;
|
|
49
|
+
const ignoreInd2 = compareWithoutIndicators || compareWithoutIndicator2;
|
|
50
|
+
|
|
27
51
|
debugOptions(`Tag Pattern: ${tagPattern}`);
|
|
28
52
|
debugOptions(`Compare tags only: ${compareTagsOnly}`);
|
|
29
|
-
debugOptions(`
|
|
53
|
+
debugOptions(`Omit indicator 1 from comparison: ${ignoreInd1}`);
|
|
54
|
+
debugOptions(`Omit indicator 2 from comparison: ${ignoreInd2}`);
|
|
30
55
|
debugOptions(`Copy if identical: ${subfieldsMustBeIdentical}`);
|
|
31
56
|
debugOptions(`Exclude subfields: [${excludeSubfields}]`);
|
|
32
57
|
debugOptions(`Drop subfields [${dropSubfields}]`);
|
|
@@ -39,23 +64,26 @@ export default ({
|
|
|
39
64
|
if (doNotCopy) {
|
|
40
65
|
return baseRecord.toObject();
|
|
41
66
|
}
|
|
42
|
-
|
|
67
|
+
debug(`FFS: ${compareWithoutIndicator1}, ${compareWithoutIndicators}, ${ignoreInd1}`);
|
|
43
68
|
debug(`Base fields: `, baseFields);
|
|
44
69
|
debug(`Source fields: `, sourceFields);
|
|
45
70
|
|
|
71
|
+
// Logic steps
|
|
46
72
|
const baseCompareFields = baseFields.map(baseField => createCompareField(baseField));
|
|
47
73
|
const compareResultFields = compareFields(sourceFields, baseCompareFields);
|
|
48
74
|
const droppedUnwantedSubfield = checkDropSubfields(compareResultFields);
|
|
49
75
|
const droppedUnwantedFields = checkCopyUnlessFields(droppedUnwantedSubfield);
|
|
50
76
|
const swappedSubfields = checkSwapSubfieldCodes(droppedUnwantedFields);
|
|
51
77
|
const swappedTags = checkSwapTag(swappedSubfields);
|
|
78
|
+
const uniqueFields = [...new Set(swappedTags.map(field => JSON.stringify(field)))].map(field => JSON.parse(field));
|
|
52
79
|
debug('Fields to be copied');
|
|
53
|
-
debug(JSON.stringify(
|
|
80
|
+
debug(JSON.stringify(uniqueFields));
|
|
54
81
|
|
|
55
82
|
// Add fields to base;
|
|
56
|
-
|
|
83
|
+
uniqueFields.forEach(field => baseRecord.insertField(field));
|
|
84
|
+
debugData(`baseRecord before return: ${JSON.stringify(baseRecord)}`);
|
|
85
|
+
//return baseRecord;
|
|
57
86
|
return baseRecord.toObject();
|
|
58
|
-
//return copyFields(baseFields, sourceFields);
|
|
59
87
|
|
|
60
88
|
function compareFields(sourceFields, baseCompareFields, uniqFields = []) {
|
|
61
89
|
const [sourceField, ...rest] = sourceFields;
|
|
@@ -130,6 +158,7 @@ export default ({
|
|
|
130
158
|
}
|
|
131
159
|
}
|
|
132
160
|
|
|
161
|
+
// compare objects have only fields that matter in comparison
|
|
133
162
|
function createCompareField(field) {
|
|
134
163
|
if (compareTagsOnly) {
|
|
135
164
|
return {tag: field.tag};
|
|
@@ -140,11 +169,13 @@ export default ({
|
|
|
140
169
|
}
|
|
141
170
|
|
|
142
171
|
const [filteredField] = checkDropSubfields([field]);
|
|
172
|
+
const [foundRule] = swapTag.filter(rule => new RegExp(rule.from, 'u').test(field.tag));
|
|
173
|
+
const replacementTag = foundRule ? foundRule.to : undefined;
|
|
143
174
|
|
|
144
175
|
const params = [
|
|
145
|
-
{name: 'tag', value: field.tag},
|
|
146
|
-
{name: 'ind1', value:
|
|
147
|
-
{name: 'ind2', value:
|
|
176
|
+
{name: 'tag', value: compareWithoutTag ? replacementTag : field.tag},
|
|
177
|
+
{name: 'ind1', value: ignoreInd1 ? undefined : field.ind1},
|
|
178
|
+
{name: 'ind2', value: ignoreInd2 ? undefined : field.ind2},
|
|
148
179
|
{name: 'subfields', value: createCompareSubfields(filteredField.subfields)}
|
|
149
180
|
].map(param => [param.name, param.value]);
|
|
150
181
|
|
|
@@ -237,95 +268,3 @@ export default ({
|
|
|
237
268
|
return fields;
|
|
238
269
|
}
|
|
239
270
|
};
|
|
240
|
-
|
|
241
|
-
// function copyFields() { //eslint-disable-line no-unused-vars
|
|
242
|
-
// const sourceTags = sourceFields.map(field => field.tag);
|
|
243
|
-
// sourceTags.forEach(tag => debug(`Comparing field ${tag}`));
|
|
244
|
-
|
|
245
|
-
// /*
|
|
246
|
-
// if (combine.length > 0) {
|
|
247
|
-
// debug(`*** NOW Copy options: ${tagPattern}, ${compareTagsOnly}, ${compareWithoutIndicators}, ${subfieldsMustBeIdentical}, [${combine}], [${excludeSubfields}], [${dropSubfields}]`);
|
|
248
|
-
// combine.forEach(row => debug(` ### combine ${row} <- `));
|
|
249
|
-
// return [];
|
|
250
|
-
// }
|
|
251
|
-
// */
|
|
252
|
-
|
|
253
|
-
// // If compareTagsOnly = true, only this part is run
|
|
254
|
-
// // The field is copied from source only if it is missing completely from base
|
|
255
|
-
// if (compareTagsOnly && baseFields.length === 0) {
|
|
256
|
-
// sourceTags.forEach(tag => debug(`Missing field ${tag} copied from source to base`));
|
|
257
|
-
// sourceFields.forEach(f => base.insertField(f));
|
|
258
|
-
// return true;
|
|
259
|
-
// }
|
|
260
|
-
|
|
261
|
-
// // If compareTagsOnly = false (default)
|
|
262
|
-
// // Source and base are also compared for identicalness
|
|
263
|
-
// // Non-identical fields are copied from source to base as duplicates
|
|
264
|
-
// if (!compareTagsOnly) {
|
|
265
|
-
// const filterMissing = function (sourceField) {
|
|
266
|
-
// if ('value' in sourceField) {
|
|
267
|
-
// debug(`Checking control field ${sourceField.tag} for identicalness`);
|
|
268
|
-
// return baseFields.some(isIdenticalControlField) === false;
|
|
269
|
-
// }
|
|
270
|
-
// if ('subfields' in sourceField) {
|
|
271
|
-
// debug(`Checking data field ${sourceField.tag} for identicalness`);
|
|
272
|
-
// return baseFields.some(isIdenticalDataField) === false;
|
|
273
|
-
// }
|
|
274
|
-
|
|
275
|
-
// function normalizeControlField(field) {
|
|
276
|
-
// return field.value.toLowerCase().replace(/\s+/u, '');
|
|
277
|
-
// }
|
|
278
|
-
|
|
279
|
-
// function isIdenticalControlField(baseField) {
|
|
280
|
-
// const normalizedBaseField = normalizeControlField(baseField);
|
|
281
|
-
// const normalizedSourceField = normalizeControlField(sourceField);
|
|
282
|
-
// return normalizedSourceField === normalizedBaseField;
|
|
283
|
-
// }
|
|
284
|
-
|
|
285
|
-
// function isIdenticalDataField(baseField) {
|
|
286
|
-
// // If excluded subfields have been defined for this field, they must be ignored first
|
|
287
|
-
// // (i.e. source and base fields are considered identical if all non-excluded subfields are identical)
|
|
288
|
-
// if (excludeSubfields.length > 0 &&
|
|
289
|
-
// sourceField.tag === baseField.tag &&
|
|
290
|
-
// sourceField.ind1 === baseField.ind1 &&
|
|
291
|
-
// sourceField.ind2 === baseField.ind2) {
|
|
292
|
-
// excludeSubfields.forEach(sub => debug(`Subfield ${sub} excluded from identicalness comparison`));
|
|
293
|
-
// // Compare only those subfields that are not excluded
|
|
294
|
-
// const baseSubsToCompare = baseField.subfields.filter(subfield => excludeSubfields.indexOf(subfield.code) === -1);
|
|
295
|
-
// return baseSubsToCompare.every(isIdenticalSubfield);
|
|
296
|
-
// }
|
|
297
|
-
// // If there are no excluded subfields (default case)
|
|
298
|
-
// if (sourceField.tag === baseField.tag &&
|
|
299
|
-
// sourceField.ind1 === baseField.ind1 &&
|
|
300
|
-
// sourceField.ind2 === baseField.ind2 &&
|
|
301
|
-
// sourceField.subfields.length === baseField.subfields.length) {
|
|
302
|
-
// return baseField.subfields.every(isIdenticalSubfield);
|
|
303
|
-
// }
|
|
304
|
-
// function normalizeSubfield(subfield) {
|
|
305
|
-
// return subfield.value.toLowerCase().replace(/\s+/u, '');
|
|
306
|
-
// }
|
|
307
|
-
// function isIdenticalSubfield(baseSub) {
|
|
308
|
-
// const normBaseSub = normalizeSubfield(baseSub);
|
|
309
|
-
// return sourceField.subfields.some(sourceSub => {
|
|
310
|
-
// const normSourceSub = normalizeSubfield(sourceSub);
|
|
311
|
-
// return normSourceSub === normBaseSub;
|
|
312
|
-
// });
|
|
313
|
-
// }
|
|
314
|
-
// }
|
|
315
|
-
// };
|
|
316
|
-
// // Search for fields missing from base
|
|
317
|
-
// const missingFields = sourceFields.filter(filterMissing);
|
|
318
|
-
// missingFields.forEach(f => base.insertField(f));
|
|
319
|
-
// if (missingFields.length > 0) {
|
|
320
|
-
// const missingTags = missingFields.map(field => field.tag);
|
|
321
|
-
// missingTags.forEach(tag => debug(`Field ${tag} copied from source to base`));
|
|
322
|
-
// return base;
|
|
323
|
-
// }
|
|
324
|
-
// if (missingFields.length === 0) {
|
|
325
|
-
// debug(`No missing fields found`);
|
|
326
|
-
// return base;
|
|
327
|
-
// }
|
|
328
|
-
// }
|
|
329
|
-
// debug(`No missing fields found`);
|
|
330
|
-
// return base;
|
|
331
|
-
// }
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import {expect} from 'chai';
|
|
2
2
|
import {READERS} from '@natlibfi/fixura';
|
|
3
|
-
//import {MarcRecord} from '@natlibfi/marc-record';
|
|
4
3
|
import createReducer from './copy';
|
|
5
4
|
import generateTests from '@natlibfi/fixugen';
|
|
6
5
|
|
|
@@ -22,7 +21,10 @@ function callback({
|
|
|
22
21
|
getFixture,
|
|
23
22
|
tagPatternRegExp,
|
|
24
23
|
compareTagsOnly = false,
|
|
24
|
+
compareWithoutTag = false,
|
|
25
25
|
compareWithoutIndicators = false,
|
|
26
|
+
compareWithoutIndicator1 = false,
|
|
27
|
+
compareWithoutIndicator2 = false,
|
|
26
28
|
subfieldsMustBeIdentical = false,
|
|
27
29
|
copyUnless = undefined,
|
|
28
30
|
excludeSubfields = undefined,
|
|
@@ -31,17 +33,13 @@ function callback({
|
|
|
31
33
|
swapTag = [],
|
|
32
34
|
doNotCopyIfFieldPresent = false
|
|
33
35
|
}) {
|
|
34
|
-
|
|
35
36
|
const base = getFixture('base.json');
|
|
36
37
|
const source = getFixture('source.json');
|
|
37
|
-
|
|
38
|
-
// const base = new MarcRecord(getFixture('base.json'), {subfieldValues: false});
|
|
39
|
-
// const source = new MarcRecord(getFixture('source.json'), {subfieldValues: false});
|
|
40
38
|
const tagPattern = new RegExp(tagPatternRegExp, 'u');
|
|
41
39
|
const expectedRecord = getFixture('merged.json');
|
|
42
40
|
|
|
43
41
|
const merged = createReducer({
|
|
44
|
-
tagPattern, compareTagsOnly, compareWithoutIndicators,
|
|
42
|
+
tagPattern, compareTagsOnly, compareWithoutTag, compareWithoutIndicators, compareWithoutIndicator1, compareWithoutIndicator2,
|
|
45
43
|
copyUnless, subfieldsMustBeIdentical, excludeSubfields,
|
|
46
44
|
dropSubfields, swapSubfieldCode, swapTag,
|
|
47
45
|
doNotCopyIfFieldPresent
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import {expect} from 'chai';
|
|
2
|
+
import {READERS} from '@natlibfi/fixura';
|
|
3
|
+
import createReducer from './copy';
|
|
4
|
+
import generateTests from '@natlibfi/fixugen';
|
|
5
|
+
|
|
6
|
+
//import createDebugLogger from 'debug'; // <---
|
|
7
|
+
//const debug = createDebugLogger('@natlibfi/marc-record-merge/copy.spec.js'); // <---
|
|
8
|
+
|
|
9
|
+
generateTests({
|
|
10
|
+
callback,
|
|
11
|
+
path: [__dirname, '..', '..', 'test-fixtures', 'reducers', 'copy'],
|
|
12
|
+
useMetadataFile: true,
|
|
13
|
+
recurse: true,
|
|
14
|
+
fixura: {
|
|
15
|
+
reader: READERS.JSON,
|
|
16
|
+
failWhenNotFound: false
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
function callback({
|
|
22
|
+
getFixture,
|
|
23
|
+
tagPatternRegExp,
|
|
24
|
+
compareTagsOnly = false,
|
|
25
|
+
compareWithoutTag = false,
|
|
26
|
+
compareWithoutIndicators = false,
|
|
27
|
+
compareWithoutIndicator1 = false,
|
|
28
|
+
compareWithoutIndicator2 = false,
|
|
29
|
+
subfieldsMustBeIdentical = false,
|
|
30
|
+
copyUnless = undefined,
|
|
31
|
+
excludeSubfields = undefined,
|
|
32
|
+
dropSubfields = undefined,
|
|
33
|
+
swapSubfieldCode = [],
|
|
34
|
+
swapTag = [],
|
|
35
|
+
doNotCopyIfFieldPresent = false
|
|
36
|
+
}) {
|
|
37
|
+
const base = getFixture('base.json');
|
|
38
|
+
const source = getFixture('source.json');
|
|
39
|
+
const tagPattern = new RegExp(tagPatternRegExp, 'u');
|
|
40
|
+
const expectedRecord = getFixture('merged.json');
|
|
41
|
+
|
|
42
|
+
const merged = createReducer({
|
|
43
|
+
tagPattern, compareTagsOnly, compareWithoutTag, compareWithoutIndicators, compareWithoutIndicator1, compareWithoutIndicator2,
|
|
44
|
+
copyUnless, subfieldsMustBeIdentical, excludeSubfields,
|
|
45
|
+
dropSubfields, swapSubfieldCode, swapTag,
|
|
46
|
+
doNotCopyIfFieldPresent
|
|
47
|
+
})({base, source});
|
|
48
|
+
//debug(`*** mergedRecord: `, mergedRecord); //<--
|
|
49
|
+
//debug(`*** mergedRecord,Strfy: `, JSON.stringify(mergedRecord)); //<--
|
|
50
|
+
//debug(`*** expectedRecord: `, expectedRecord); //<--
|
|
51
|
+
//debug(`*** expectedRecord,Strfy: `, JSON.stringify(expectedRecord)); //<--
|
|
52
|
+
expect(merged.constructor.name).not.to.eql('MarcRecord');
|
|
53
|
+
expect(merged.constructor.name).to.eql('Object');
|
|
54
|
+
expect(merged).to.eql(expectedRecord);
|
|
55
|
+
}
|
package/src/reducers/select.js
CHANGED
|
@@ -12,10 +12,31 @@ export function subsetEquality(subfieldA, subfieldB) {
|
|
|
12
12
|
(subfieldA.value.indexOf(subfieldB.value) !== -1 || subfieldB.value.indexOf(subfieldA.value) !== -1);
|
|
13
13
|
}
|
|
14
14
|
// EqualityFunction can be either strictEquality or subsetEquality
|
|
15
|
-
|
|
15
|
+
|
|
16
|
+
export default ({
|
|
17
|
+
tagPattern,
|
|
18
|
+
equalityFunction = strictEquality,
|
|
19
|
+
baseValidators = {subfieldValues: false},
|
|
20
|
+
sourceValidators = {subfieldValues: false}
|
|
21
|
+
// eslint-disable-next-line max-statements
|
|
22
|
+
}) => (base, source) => {
|
|
16
23
|
const debug = createDebugLogger('@natlibfi/marc-record-merge:select');
|
|
17
|
-
|
|
18
|
-
const sourceRecord =
|
|
24
|
+
|
|
25
|
+
const {baseRecord, sourceRecord} = getRecordsFromParameters(base, source, baseValidators, sourceValidators);
|
|
26
|
+
|
|
27
|
+
function getRecordsFromParameters(base, source, baseValidators, sourceValidators) {
|
|
28
|
+
// records if we got an object ({base, source}) as a parameter
|
|
29
|
+
if (source === undefined && base.base !== undefined && base.source !== undefined) {
|
|
30
|
+
const baseRecord = new MarcRecord(base.base, baseValidators);
|
|
31
|
+
const sourceRecord = new MarcRecord(base.source, sourceValidators);
|
|
32
|
+
return {baseRecord, sourceRecord};
|
|
33
|
+
}
|
|
34
|
+
// records if we got an non-object (base, source) as a parameter
|
|
35
|
+
const baseRecord = new MarcRecord(base, baseValidators);
|
|
36
|
+
const sourceRecord = new MarcRecord(source, sourceValidators);
|
|
37
|
+
return {baseRecord, sourceRecord};
|
|
38
|
+
}
|
|
39
|
+
|
|
19
40
|
const baseFields = baseRecord.get(tagPattern);
|
|
20
41
|
const sourceFields = sourceRecord.get(tagPattern);
|
|
21
42
|
const fieldTag = sourceFields.map(field => field.tag);
|
|
@@ -27,7 +48,7 @@ export default ({tagPattern, equalityFunction = strictEquality}) => (base, sourc
|
|
|
27
48
|
if (baseFields.length > 1 || sourceFields.length > 1) {
|
|
28
49
|
debug(`Multiple fields in base or source`);
|
|
29
50
|
debug(`No changes to base`);
|
|
30
|
-
return
|
|
51
|
+
return baseRecord.toObject();
|
|
31
52
|
}
|
|
32
53
|
const [baseField] = baseFields;
|
|
33
54
|
const [sourceField] = sourceFields;
|
|
@@ -35,7 +56,7 @@ export default ({tagPattern, equalityFunction = strictEquality}) => (base, sourc
|
|
|
35
56
|
if (baseField.tag === sourceField.tag === false) {
|
|
36
57
|
debug(`Base tag ${baseField.tag} is not equal to source tag ${sourceField.tag}`);
|
|
37
58
|
debug(`No changes to base`);
|
|
38
|
-
return
|
|
59
|
+
return baseRecord.toObject();
|
|
39
60
|
}
|
|
40
61
|
const baseSubs = baseField.subfields;
|
|
41
62
|
const sourceSubs = sourceField.subfields;
|
|
@@ -61,7 +82,7 @@ export default ({tagPattern, equalityFunction = strictEquality}) => (base, sourc
|
|
|
61
82
|
if (baseSubs.length === sourceSubs.length && equalSubfieldsBase.length < baseSubs.length) {
|
|
62
83
|
debug(`Base and source subfields are not equal`);
|
|
63
84
|
debug(`No changes to base`);
|
|
64
|
-
return
|
|
85
|
+
return baseRecord.toObject();
|
|
65
86
|
}
|
|
66
87
|
|
|
67
88
|
if (baseSubs.length === sourceSubs.length && equalSubfieldsBase.length === equalSubfieldsSource.length) {
|
|
@@ -74,16 +95,16 @@ export default ({tagPattern, equalityFunction = strictEquality}) => (base, sourc
|
|
|
74
95
|
.reduce((acc, value) => acc + value);
|
|
75
96
|
|
|
76
97
|
if (totalSubfieldLengthSource > totalSubfieldLengthBase) {
|
|
77
|
-
return replaceBasefieldWithSourcefield(
|
|
98
|
+
return replaceBasefieldWithSourcefield(baseRecord.toObject());
|
|
78
99
|
}
|
|
79
100
|
}
|
|
80
101
|
|
|
81
102
|
if (sourceSubs.length > baseSubs.length && equalSubfieldsBase.length === baseSubs.length) {
|
|
82
|
-
return replaceBasefieldWithSourcefield(
|
|
103
|
+
return replaceBasefieldWithSourcefield(baseRecord.toObject());
|
|
83
104
|
}
|
|
84
105
|
|
|
85
106
|
debug(`No changes to base`);
|
|
86
|
-
return
|
|
107
|
+
return baseRecord.toObject();
|
|
87
108
|
|
|
88
109
|
function replaceBasefieldWithSourcefield(base) {
|
|
89
110
|
const index = base.fields.findIndex(field => field === baseField);
|
|
@@ -94,7 +115,7 @@ export default ({tagPattern, equalityFunction = strictEquality}) => (base, sourc
|
|
|
94
115
|
|
|
95
116
|
function checkFieldType(fields) {
|
|
96
117
|
const checkedFields = fields.map(field => {
|
|
97
|
-
if ('value' in field) { // eslint-disable-line functional/no-conditional-
|
|
118
|
+
if ('value' in field) { // eslint-disable-line functional/no-conditional-statements
|
|
98
119
|
throw new Error('Invalid control field, expected data field');
|
|
99
120
|
}
|
|
100
121
|
return field;
|