@natlibfi/marc-record-merge 8.0.0 → 8.0.1-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.
@@ -20,7 +20,7 @@ jobs:
20
20
 
21
21
  steps:
22
22
  - name: Checkout the code
23
- uses: actions/checkout@v5
23
+ uses: actions/checkout@v6
24
24
  - name: Use Node.js ${{ matrix.node-version }}
25
25
  uses: actions/setup-node@v6
26
26
  with:
@@ -39,7 +39,7 @@ jobs:
39
39
  container: node:22
40
40
 
41
41
  steps:
42
- - uses: actions/checkout@v5
42
+ - uses: actions/checkout@v6
43
43
  - uses: mikaelvesavuori/license-compliance-action@v1
44
44
  with:
45
45
  exclude_pattern: /^@natlibfi/
@@ -51,7 +51,7 @@ jobs:
51
51
 
52
52
  steps:
53
53
  - name: Checkout the code
54
- uses: actions/checkout@v5
54
+ uses: actions/checkout@v6
55
55
  - name: nodejsscan scan
56
56
  id: njsscan
57
57
  uses: ajinabraham/njsscan-action@master
@@ -64,7 +64,7 @@ jobs:
64
64
  if: contains(github.ref, 'refs/tags/')
65
65
 
66
66
  steps:
67
- - uses: actions/checkout@v5
67
+ - uses: actions/checkout@v6
68
68
  # Setup .npmrc file to publish to npm
69
69
  - uses: actions/setup-node@v6
70
70
  with:
package/README.md CHANGED
@@ -126,6 +126,6 @@ More info can be read here: https://github.com/NatLibFi/marc-record-js
126
126
 
127
127
  ## License and copyright
128
128
 
129
- Copyright (c) 2020-2025 **University Of Helsinki (The National Library Of Finland)**
129
+ Copyright (c) 2020-2026 **University Of Helsinki (The National Library Of Finland)**
130
130
 
131
131
  This project's source code is licensed under the terms of **MIT** or any later version.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/reducers/copy.js"],
4
- "sourcesContent": ["import {MarcRecord} from '@natlibfi/marc-record';\nimport createDebugLogger from 'debug';\n\nexport default ({\n tagPattern,\n compareTagsOnly = false,\n compareWithoutTag = false,\n compareWithoutIndicators = false,\n compareWithoutIndicator1 = false,\n compareWithoutIndicator2 = false,\n subfieldsMustBeIdentical = true,\n excludeSubfields = [],\n dropSubfields = [],\n copyUnless = [],\n baseValidators = {subfieldValues: false},\n sourceValidators = {subfieldValues: false},\n swapTag = [],\n swapSubfieldCode = [],\n doNotCopyIfFieldPresent = false\n}) => (base, source) => {\n\n const debug = createDebugLogger('@natlibfi/marc-record-merge:copy');\n const debugData = debug.extend('data');\n const debugOptions = createDebugLogger('@natlibfi/marc-record-merge:compare-options');\n const debugCompare = createDebugLogger('@natlibfi/marc-record-merge:compare');\n\n debugData(`base: ${JSON.stringify(base)}`);\n debugData(`source: ${JSON.stringify(source)}`);\n\n const {baseRecord, sourceRecord} = getRecordsFromParameters(base, source, baseValidators, sourceValidators);\n\n function getRecordsFromParameters(base, source, baseValidators, sourceValidators) {\n // records if we got an object ({base, source}) as a parameter\n if (source === undefined && base.base !== undefined && base.source !== undefined) {\n const baseRecord = new MarcRecord(base.base, baseValidators);\n const sourceRecord = new MarcRecord(base.source, sourceValidators);\n return {baseRecord, sourceRecord};\n }\n // records if we got an non-object (base, source) as a parameter\n const baseRecord = new MarcRecord(base, baseValidators);\n const sourceRecord = new MarcRecord(source, sourceValidators);\n return {baseRecord, sourceRecord};\n }\n\n const ignoreInd1 = compareWithoutIndicators || compareWithoutIndicator1;\n const ignoreInd2 = compareWithoutIndicators || compareWithoutIndicator2;\n\n debugOptions(`Tag Pattern: ${tagPattern}`);\n debugOptions(`Compare tags only: ${compareTagsOnly}`);\n debugOptions(`Omit indicator 1 from comparison: ${ignoreInd1}`);\n debugOptions(`Omit indicator 2 from comparison: ${ignoreInd2}`);\n debugOptions(`Copy if identical: ${subfieldsMustBeIdentical}`);\n debugOptions(`Exclude subfields: [${excludeSubfields}]`);\n debugOptions(`Drop subfields [${dropSubfields}]`);\n debugOptions(`Copy unless contains subfields: ${JSON.stringify(copyUnless)}`);\n\n const baseFields = baseRecord.get(tagPattern);\n const sourceFields = sourceRecord.get(tagPattern);\n const doNotCopy = doNotCopyIfFieldPresent ? baseRecord.get(doNotCopyIfFieldPresent).length > 0 : false;\n\n if (doNotCopy) {\n return baseRecord.toObject();\n }\n debug(`FFS: ${compareWithoutIndicator1}, ${compareWithoutIndicators}, ${ignoreInd1}`);\n debug(`Base fields: `, baseFields);\n debug(`Source fields: `, sourceFields);\n\n // Logic steps\n const baseCompareFields = baseFields.map(baseField => createCompareField(baseField));\n const compareResultFields = compareFields(sourceFields, baseCompareFields);\n const droppedUnwantedSubfield = checkDropSubfields(compareResultFields);\n const droppedUnwantedFields = checkCopyUnlessFields(droppedUnwantedSubfield);\n const swappedSubfields = checkSwapSubfieldCodes(droppedUnwantedFields);\n const swappedTags = checkSwapTag(swappedSubfields);\n const uniqueFields = [...new Set(swappedTags.map(field => JSON.stringify(field)))].map(field => JSON.parse(field));\n debug('Fields to be copied');\n debug(JSON.stringify(uniqueFields));\n\n // Add fields to base;\n uniqueFields.forEach(field => baseRecord.insertField(field));\n debugData(`baseRecord before return: ${JSON.stringify(baseRecord)}`);\n //return baseRecord;\n return baseRecord.toObject();\n\n function compareFields(sourceFields, baseCompareFields, uniqFields = []) {\n const [sourceField, ...rest] = sourceFields;\n if (sourceField === undefined) {\n return uniqFields;\n }\n\n if (baseCompareFields.length === 0) {\n return compareFields(rest, baseCompareFields, [...uniqFields, sourceField]);\n }\n\n // Source and base are also compared for identicalness\n // Non-identical fields are copied from source to base as duplicates\n const sourceCompareField = createCompareField(sourceField);\n const unique = checkCompareFields(baseCompareFields, sourceCompareField);\n\n debugCompare(`${JSON.stringify(sourceField)} ${unique ? 'is UNIQUE' : 'not UNIQUE'}`);\n\n if (unique) {\n return compareFields(rest, baseCompareFields, [...uniqFields, sourceField]);\n }\n\n return compareFields(rest, baseCompareFields, uniqFields);\n\n function checkCompareFields(baseCompareFields, sourceCompareField) {\n let unique = true;\n\n baseCompareFields.forEach(baseCompareField => {\n debugCompare(`Comparing ${JSON.stringify(sourceCompareField)} to ${JSON.stringify(baseCompareField)}}`);\n\n if (sourceCompareField.value !== baseCompareField.value) {\n debugCompare(`Value is different ${sourceCompareField.value} !== ${baseCompareField.value}`);\n return;\n }\n\n if (sourceCompareField.ind1 !== baseCompareField.ind1) {\n debugCompare(`Ind1 is different ${sourceCompareField.ind1} !== ${baseCompareField.ind1}`);\n return;\n }\n\n if (sourceCompareField.ind2 !== baseCompareField.ind2) {\n debugCompare(`Ind2 is different ${sourceCompareField.ind2} !== ${baseCompareField.ind2}`);\n return;\n }\n\n if ('subfields' in sourceCompareField) {\n const allFound = checkSubfields(sourceCompareField.subfields, baseCompareField.subfields);\n debugCompare(`Subfields are different ${!allFound}`);\n if (!allFound) {\n return;\n }\n\n unique = false;\n return;\n }\n\n unique = false;\n return;\n });\n\n return unique;\n }\n\n function checkSubfields(sourceSubfields, baseSubfields) {\n const foundSubs = sourceSubfields.filter(sSub => baseSubfields.some(bSub => sSub.code === bSub.code && sSub.value === bSub.value));\n\n if (subfieldsMustBeIdentical) {\n return foundSubs.length === sourceSubfields.length && foundSubs.length === baseSubfields.length;\n }\n\n return foundSubs.length === sourceSubfields.length;\n }\n }\n\n // compare objects have only fields that matter in comparison\n function createCompareField(field) {\n if (compareTagsOnly) {\n return {tag: field.tag};\n }\n\n if ('value' in field) {\n return {tag: field.tag, value: field.value};\n }\n\n const [filteredField] = checkDropSubfields([field]);\n const [foundRule] = swapTag.filter(rule => new RegExp(rule.from, 'u').test(field.tag));\n const replacementTag = foundRule ? foundRule.to : undefined;\n\n const params = [\n {name: 'tag', value: compareWithoutTag ? replacementTag : field.tag},\n {name: 'ind1', value: ignoreInd1 ? undefined : field.ind1},\n {name: 'ind2', value: ignoreInd2 ? undefined : field.ind2},\n {name: 'subfields', value: createCompareSubfields(filteredField.subfields)}\n ].map(param => [param.name, param.value]);\n\n return Object.fromEntries(params);\n\n function createCompareSubfields(subfields) {\n const nonExcludedSubfields = subfields.filter(sub => !excludeSubfields.some(code => code === sub.code));\n const normalizedSubfields = nonExcludedSubfields.map(sub => ({code: sub.code, value: normalizeSubfieldValue(sub.value)}));\n\n return normalizedSubfields;\n\n function normalizeSubfieldValue(value) {\n return value.toLowerCase().replace(/\\s+/ug, '');\n }\n }\n }\n\n function checkSwapTag(fields) {\n if (swapTag.length > 0) {\n return fields.map(field => ({...field, tag: swapTagsFunc(field.tag)}));\n }\n\n return fields;\n\n function swapTagsFunc(tag) {\n const [foundRule] = swapTag.filter(rule => new RegExp(rule.from, 'u').test(tag));\n\n if (foundRule === undefined) {\n return tag;\n }\n\n return foundRule.to;\n }\n }\n\n function checkSwapSubfieldCodes(fields) {\n if (swapSubfieldCode.length > 0) {\n return fields.map(field => ({...field, subfields: swapSubfieldCodesFunc(field.subfields)}));\n }\n\n return fields;\n\n function swapSubfieldCodesFunc(subfields) {\n return subfields.map(sub => {\n const [foundRule] = swapSubfieldCode.filter(rule => rule.from === sub.code);\n\n if (foundRule === undefined) {\n return sub;\n }\n\n return {code: foundRule.to, value: sub.value};\n });\n }\n }\n\n function checkDropSubfields(fields) {\n if (dropSubfields.length > 0) {\n return fields.map(field => ({...field, subfields: dropSubfieldsFunc(field.subfields)}))\n .filter(field => field.subfields.length > 0);\n }\n\n return fields;\n\n function dropSubfieldsFunc(subfields) {\n return subfields.filter(sub => { // eslint-disable-line\n return !dropSubfields.some(({code, value = false, condition = false}) => {\n if (code !== sub.code) {\n return false;\n }\n\n if (!condition && value) {\n return value === sub.value;\n }\n\n if (condition === 'unless' && value) {\n return !new RegExp(value, 'u').test(sub.value);\n }\n\n return true;\n });\n });\n }\n }\n\n function checkCopyUnlessFields(fields) {\n if (copyUnless.length > 0) {\n return fields.filter(({subfields}) => copyUnless.some(filter => !subfields.some(sub => sub.code === filter.code && new RegExp(filter.value, 'u').test(sub.value))));\n }\n\n return fields;\n }\n};\n"],
4
+ "sourcesContent": ["import {MarcRecord} from '@natlibfi/marc-record';\nimport createDebugLogger from 'debug';\n\nexport default ({\n tagPattern,\n compareTagsOnly = false,\n compareWithoutTag = false,\n compareWithoutIndicators = false,\n compareWithoutIndicator1 = false,\n compareWithoutIndicator2 = false,\n subfieldsMustBeIdentical = true,\n excludeSubfields = [],\n dropSubfields = [],\n copyUnless = [],\n baseValidators = {subfieldValues: false},\n sourceValidators = {subfieldValues: false},\n swapTag = [],\n swapSubfieldCode = [],\n doNotCopyIfFieldPresent = false\n}) => (base, source) => {\n\n const debug = createDebugLogger('@natlibfi/marc-record-merge:copy');\n const debugData = debug.extend('data');\n const debugOptions = createDebugLogger('@natlibfi/marc-record-merge:compare-options');\n const debugCompare = createDebugLogger('@natlibfi/marc-record-merge:compare');\n\n debugData(`base: ${JSON.stringify(base)}`);\n debugData(`source: ${JSON.stringify(source)}`);\n\n const {baseRecord, sourceRecord} = getRecordsFromParameters(base, source, baseValidators, sourceValidators);\n\n function getRecordsFromParameters(base, source, baseValidators, sourceValidators) {\n // records if we got an object ({base, source}) as a parameter\n if (source === undefined && base.base !== undefined && base.source !== undefined) {\n const baseRecord = new MarcRecord(base.base, baseValidators);\n const sourceRecord = new MarcRecord(base.source, sourceValidators);\n return {baseRecord, sourceRecord};\n }\n // records if we got an non-object (base, source) as a parameter\n const baseRecord = new MarcRecord(base, baseValidators);\n const sourceRecord = new MarcRecord(source, sourceValidators);\n return {baseRecord, sourceRecord};\n }\n\n const ignoreInd1 = compareWithoutIndicators || compareWithoutIndicator1;\n const ignoreInd2 = compareWithoutIndicators || compareWithoutIndicator2;\n\n debugOptions(`Tag Pattern: ${tagPattern}`);\n debugOptions(`Compare tags only: ${compareTagsOnly}`);\n debugOptions(`Omit indicator 1 from comparison: ${ignoreInd1}`);\n debugOptions(`Omit indicator 2 from comparison: ${ignoreInd2}`);\n debugOptions(`Copy if identical: ${subfieldsMustBeIdentical}`);\n debugOptions(`Exclude subfields: [${excludeSubfields}]`);\n debugOptions(`Drop subfields [${dropSubfields}]`);\n debugOptions(`Copy unless contains subfields: ${JSON.stringify(copyUnless)}`);\n\n const baseFields = baseRecord.get(tagPattern);\n const sourceFields = sourceRecord.get(tagPattern);\n const doNotCopy = doNotCopyIfFieldPresent ? baseRecord.get(doNotCopyIfFieldPresent).length > 0 : false;\n\n if (doNotCopy) {\n return baseRecord.toObject();\n }\n debug(`FFS: ${compareWithoutIndicator1}, ${compareWithoutIndicators}, ${ignoreInd1}`);\n debug(`Base fields: `, baseFields);\n debug(`Source fields: `, sourceFields);\n\n // Logic steps\n const baseCompareFields = baseFields.map(baseField => createCompareField(baseField));\n const compareResultFields = compareFields(sourceFields, baseCompareFields);\n const droppedUnwantedSubfield = checkDropSubfields(compareResultFields);\n const droppedUnwantedFields = checkCopyUnlessFields(droppedUnwantedSubfield);\n const swappedSubfields = checkSwapSubfieldCodes(droppedUnwantedFields);\n const swappedTags = checkSwapTag(swappedSubfields);\n const uniqueFields = [...new Set(swappedTags.map(field => JSON.stringify(field)))].map(field => JSON.parse(field));\n debug('Fields to be copied');\n debug(JSON.stringify(uniqueFields));\n\n // Add fields to base;\n uniqueFields.forEach(field => baseRecord.insertField(field));\n debugData(`baseRecord before return: ${JSON.stringify(baseRecord)}`);\n //return baseRecord;\n return baseRecord.toObject();\n\n function compareFields(sourceFields, baseCompareFields, uniqFields = []) {\n const [sourceField, ...rest] = sourceFields;\n if (sourceField === undefined) {\n return uniqFields;\n }\n\n if (baseCompareFields.length === 0) {\n return compareFields(rest, baseCompareFields, [...uniqFields, sourceField]);\n }\n\n // Source and base are also compared for identicalness\n // Non-identical fields are copied from source to base as duplicates\n const sourceCompareField = createCompareField(sourceField);\n const unique = checkCompareFields(baseCompareFields, sourceCompareField);\n\n debugCompare(`${JSON.stringify(sourceField)} ${unique ? 'is UNIQUE' : 'not UNIQUE'}`);\n\n if (unique) {\n return compareFields(rest, baseCompareFields, [...uniqFields, sourceField]);\n }\n\n return compareFields(rest, baseCompareFields, uniqFields);\n\n function checkCompareFields(baseCompareFields, sourceCompareField) {\n let unique = true;\n\n baseCompareFields.forEach(baseCompareField => {\n debugCompare(`Comparing ${JSON.stringify(sourceCompareField)} to ${JSON.stringify(baseCompareField)}}`);\n\n if (sourceCompareField.value !== baseCompareField.value) {\n debugCompare(`Value is different ${sourceCompareField.value} !== ${baseCompareField.value}`);\n return;\n }\n\n if (sourceCompareField.ind1 !== baseCompareField.ind1) {\n debugCompare(`Ind1 is different ${sourceCompareField.ind1} !== ${baseCompareField.ind1}`);\n return;\n }\n\n if (sourceCompareField.ind2 !== baseCompareField.ind2) {\n debugCompare(`Ind2 is different ${sourceCompareField.ind2} !== ${baseCompareField.ind2}`);\n return;\n }\n\n if ('subfields' in sourceCompareField) {\n const allFound = checkSubfields(sourceCompareField.subfields, baseCompareField.subfields);\n debugCompare(`Subfields are different ${!allFound}`);\n if (!allFound) {\n return;\n }\n\n unique = false;\n return;\n }\n\n unique = false;\n return;\n });\n\n return unique;\n }\n\n function checkSubfields(sourceSubfields, baseSubfields) {\n const foundSubs = sourceSubfields.filter(sSub => baseSubfields.some(bSub => sSub.code === bSub.code && sSub.value === bSub.value));\n\n if (subfieldsMustBeIdentical) {\n return foundSubs.length === sourceSubfields.length && foundSubs.length === baseSubfields.length;\n }\n\n return foundSubs.length === sourceSubfields.length;\n }\n }\n\n // compare objects have only fields that matter in comparison\n function createCompareField(field) {\n if (compareTagsOnly) {\n return {tag: field.tag};\n }\n\n if ('value' in field) {\n return {tag: field.tag, value: field.value};\n }\n\n const [filteredField] = checkDropSubfields([field]);\n const [foundRule] = swapTag.filter(rule => new RegExp(rule.from, 'u').test(field.tag));\n const replacementTag = foundRule ? foundRule.to : undefined;\n\n const params = [\n {name: 'tag', value: compareWithoutTag ? replacementTag : field.tag},\n {name: 'ind1', value: ignoreInd1 ? undefined : field.ind1},\n {name: 'ind2', value: ignoreInd2 ? undefined : field.ind2},\n {name: 'subfields', value: createCompareSubfields(filteredField.subfields)}\n ].map(param => [param.name, param.value]);\n\n return Object.fromEntries(params);\n\n function createCompareSubfields(subfields) {\n const nonExcludedSubfields = subfields.filter(sub => !excludeSubfields.some(code => code === sub.code));\n const normalizedSubfields = nonExcludedSubfields.map(sub => ({code: sub.code, value: normalizeSubfieldValue(sub.value)}));\n\n return normalizedSubfields;\n\n function normalizeSubfieldValue(value) {\n return value.toLowerCase().replace(/\\s+/ug, '');\n }\n }\n }\n\n function checkSwapTag(fields) {\n if (swapTag.length > 0) {\n return fields.map(field => ({...field, tag: swapTagsFunc(field.tag)}));\n }\n\n return fields;\n\n function swapTagsFunc(tag) {\n const [foundRule] = swapTag.filter(rule => new RegExp(rule.from, 'u').test(tag));\n\n if (foundRule === undefined) {\n return tag;\n }\n\n return foundRule.to;\n }\n }\n\n function checkSwapSubfieldCodes(fields) {\n if (swapSubfieldCode.length > 0) {\n return fields.map(field => ({...field, subfields: swapSubfieldCodesFunc(field.subfields)}));\n }\n\n return fields;\n\n function swapSubfieldCodesFunc(subfields) {\n return subfields.map(sub => {\n const [foundRule] = swapSubfieldCode.filter(rule => rule.from === sub.code);\n\n if (foundRule === undefined) {\n return sub;\n }\n\n return {code: foundRule.to, value: sub.value};\n });\n }\n }\n\n function checkDropSubfields(fields) {\n if (dropSubfields.length > 0) {\n return fields.map(field => ({...field, subfields: dropSubfieldsFunc(field.subfields)}))\n .filter(field => field.subfields.length > 0);\n }\n\n return fields;\n\n function dropSubfieldsFunc(subfields) {\n return subfields.filter(sub => {\n return !dropSubfields.some(({code, value = false, condition = false}) => {\n if (code !== sub.code) {\n return false;\n }\n\n if (!condition && value) {\n return value === sub.value;\n }\n\n if (condition === 'unless' && value) {\n return !new RegExp(value, 'u').test(sub.value);\n }\n\n return true;\n });\n });\n }\n }\n\n function checkCopyUnlessFields(fields) {\n if (copyUnless.length > 0) {\n return fields.filter(({subfields}) => copyUnless.some(filter => !subfields.some(sub => sub.code === filter.code && new RegExp(filter.value, 'u').test(sub.value))));\n }\n\n return fields;\n }\n};\n"],
5
5
  "mappings": "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",
6
6
  "names": ["base", "source", "baseValidators", "sourceValidators", "baseRecord", "sourceRecord", "sourceFields", "baseCompareFields", "sourceCompareField", "unique"]
7
7
  }
@@ -12,7 +12,6 @@ export default ({
12
12
  equalityFunction = strictEquality,
13
13
  baseValidators = { subfieldValues: false },
14
14
  sourceValidators = { subfieldValues: false }
15
- // eslint-disable-next-line max-statements
16
15
  }) => (base, source) => {
17
16
  const debug = createDebugLogger("@natlibfi/marc-record-merge:select");
18
17
  const { baseRecord, sourceRecord } = getRecordsFromParameters(base, source, baseValidators, sourceValidators);
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/reducers/select.js"],
4
- "sourcesContent": ["import {normalizeSync} from 'normalize-diacritics';\nimport createDebugLogger from 'debug';\nimport {MarcRecord} from '@natlibfi/marc-record';\n\nexport function strictEquality(subfieldA, subfieldB) {\n return subfieldA.code === subfieldB.code &&\n subfieldA.value === subfieldB.value;\n}\n\nexport function subsetEquality(subfieldA, subfieldB) {\n return subfieldA.code === subfieldB.code &&\n (subfieldA.value.indexOf(subfieldB.value) !== -1 || subfieldB.value.indexOf(subfieldA.value) !== -1);\n}\n// EqualityFunction can be either strictEquality or subsetEquality\n\nexport default ({\n tagPattern,\n equalityFunction = strictEquality,\n baseValidators = {subfieldValues: false},\n sourceValidators = {subfieldValues: false}\n// eslint-disable-next-line max-statements\n}) => (base, source) => {\n const debug = createDebugLogger('@natlibfi/marc-record-merge:select');\n\n const {baseRecord, sourceRecord} = getRecordsFromParameters(base, source, baseValidators, sourceValidators);\n\n function getRecordsFromParameters(base, source, baseValidators, sourceValidators) {\n // records if we got an object ({base, source}) as a parameter\n if (source === undefined && base.base !== undefined && base.source !== undefined) {\n const baseRecord = new MarcRecord(base.base, baseValidators);\n const sourceRecord = new MarcRecord(base.source, sourceValidators);\n return {baseRecord, sourceRecord};\n }\n // records if we got an non-object (base, source) as a parameter\n const baseRecord = new MarcRecord(base, baseValidators);\n const sourceRecord = new MarcRecord(source, sourceValidators);\n return {baseRecord, sourceRecord};\n }\n\n const baseFields = baseRecord.get(tagPattern);\n const sourceFields = sourceRecord.get(tagPattern);\n const fieldTag = sourceFields.map(field => field.tag);\n debug(`Comparing field ${fieldTag}`);\n\n checkFieldType(baseFields);\n checkFieldType(sourceFields);\n\n if (baseFields.length > 1 || sourceFields.length > 1) {\n debug(`Multiple fields in base or source`);\n debug(`No changes to base`);\n return baseRecord.toObject();\n }\n const [baseField] = baseFields;\n const [sourceField] = sourceFields;\n\n if (baseField.tag === sourceField.tag === false) {\n debug(`Base tag ${baseField.tag} is not equal to source tag ${sourceField.tag}`);\n debug(`No changes to base`);\n return baseRecord.toObject();\n }\n const baseSubs = baseField.subfields;\n const sourceSubs = sourceField.subfields;\n\n const baseSubsNormalized = baseSubs\n .map(({code, value}) => ({code, value: normalizeSubfieldValue(value)}));\n\n const sourceSubsNormalized = sourceSubs\n .map(({code, value}) => ({code, value: normalizeSubfieldValue(value)}));\n\n // Returns the base subfields for which a matching source subfield is found\n const equalSubfieldsBase = baseSubsNormalized\n .filter(baseSubfield => sourceSubsNormalized\n .some(sourceSubfield => equalityFunction(baseSubfield, sourceSubfield)));\n debug(`equalSubfieldsBase: ${JSON.stringify(equalSubfieldsBase, undefined, 2)}`);\n\n // Returns the source subfields for which a matching base subfield is found\n const equalSubfieldsSource = sourceSubsNormalized\n .filter(sourceSubfield => baseSubsNormalized\n .some(baseSubfield => equalityFunction(sourceSubfield, baseSubfield)));\n debug(`equalSubfieldsSource: ${JSON.stringify(equalSubfieldsSource, undefined, 2)}`);\n\n if (baseSubs.length === sourceSubs.length && equalSubfieldsBase.length < baseSubs.length) {\n debug(`Base and source subfields are not equal`);\n debug(`No changes to base`);\n return baseRecord.toObject();\n }\n\n if (baseSubs.length === sourceSubs.length && equalSubfieldsBase.length === equalSubfieldsSource.length) {\n debug(`Checking subfield equality`);\n const totalSubfieldLengthBase = baseSubsNormalized\n .map(({value}) => value.length)\n .reduce((acc, value) => acc + value);\n const totalSubfieldLengthSource = sourceSubsNormalized\n .map(({value}) => value.length)\n .reduce((acc, value) => acc + value);\n\n if (totalSubfieldLengthSource > totalSubfieldLengthBase) {\n return replaceBasefieldWithSourcefield(baseRecord.toObject());\n }\n }\n\n if (sourceSubs.length > baseSubs.length && equalSubfieldsBase.length === baseSubs.length) {\n return replaceBasefieldWithSourcefield(baseRecord.toObject());\n }\n\n debug(`No changes to base`);\n return baseRecord.toObject();\n\n function replaceBasefieldWithSourcefield(base) {\n const index = base.fields.findIndex(field => field === baseField);\n base.fields.splice(index, 1, sourceField);\n debug(`Source field is longer, replacing base with source`);\n return base;\n }\n\n function checkFieldType(fields) {\n const checkedFields = fields.map(field => {\n if ('value' in field) {\n throw new Error('Invalid control field, expected data field');\n }\n return field;\n });\n return checkedFields;\n }\n\n function normalizeSubfieldValue(value) {\n // Regexp options: g: global search, u: unicode\n const punctuation = /[.,\\-/#!?$%^&*;:{}=_`~()[\\]]/gu;\n return normalizeSync(value).toLowerCase().replace(punctuation, '', 'u').replace(/\\s+/gu, ' ').trim();\n }\n};\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import {normalizeSync} from 'normalize-diacritics';\nimport createDebugLogger from 'debug';\nimport {MarcRecord} from '@natlibfi/marc-record';\n\nexport function strictEquality(subfieldA, subfieldB) {\n return subfieldA.code === subfieldB.code &&\n subfieldA.value === subfieldB.value;\n}\n\nexport function subsetEquality(subfieldA, subfieldB) {\n return subfieldA.code === subfieldB.code &&\n (subfieldA.value.indexOf(subfieldB.value) !== -1 || subfieldB.value.indexOf(subfieldA.value) !== -1);\n}\n// EqualityFunction can be either strictEquality or subsetEquality\n\nexport default ({\n tagPattern,\n equalityFunction = strictEquality,\n baseValidators = {subfieldValues: false},\n sourceValidators = {subfieldValues: false}\n}) => (base, source) => {\n const debug = createDebugLogger('@natlibfi/marc-record-merge:select');\n\n const {baseRecord, sourceRecord} = getRecordsFromParameters(base, source, baseValidators, sourceValidators);\n\n function getRecordsFromParameters(base, source, baseValidators, sourceValidators) {\n // records if we got an object ({base, source}) as a parameter\n if (source === undefined && base.base !== undefined && base.source !== undefined) {\n const baseRecord = new MarcRecord(base.base, baseValidators);\n const sourceRecord = new MarcRecord(base.source, sourceValidators);\n return {baseRecord, sourceRecord};\n }\n // records if we got an non-object (base, source) as a parameter\n const baseRecord = new MarcRecord(base, baseValidators);\n const sourceRecord = new MarcRecord(source, sourceValidators);\n return {baseRecord, sourceRecord};\n }\n\n const baseFields = baseRecord.get(tagPattern);\n const sourceFields = sourceRecord.get(tagPattern);\n const fieldTag = sourceFields.map(field => field.tag);\n debug(`Comparing field ${fieldTag}`);\n\n checkFieldType(baseFields);\n checkFieldType(sourceFields);\n\n if (baseFields.length > 1 || sourceFields.length > 1) {\n debug(`Multiple fields in base or source`);\n debug(`No changes to base`);\n return baseRecord.toObject();\n }\n const [baseField] = baseFields;\n const [sourceField] = sourceFields;\n\n if (baseField.tag === sourceField.tag === false) {\n debug(`Base tag ${baseField.tag} is not equal to source tag ${sourceField.tag}`);\n debug(`No changes to base`);\n return baseRecord.toObject();\n }\n const baseSubs = baseField.subfields;\n const sourceSubs = sourceField.subfields;\n\n const baseSubsNormalized = baseSubs\n .map(({code, value}) => ({code, value: normalizeSubfieldValue(value)}));\n\n const sourceSubsNormalized = sourceSubs\n .map(({code, value}) => ({code, value: normalizeSubfieldValue(value)}));\n\n // Returns the base subfields for which a matching source subfield is found\n const equalSubfieldsBase = baseSubsNormalized\n .filter(baseSubfield => sourceSubsNormalized\n .some(sourceSubfield => equalityFunction(baseSubfield, sourceSubfield)));\n debug(`equalSubfieldsBase: ${JSON.stringify(equalSubfieldsBase, undefined, 2)}`);\n\n // Returns the source subfields for which a matching base subfield is found\n const equalSubfieldsSource = sourceSubsNormalized\n .filter(sourceSubfield => baseSubsNormalized\n .some(baseSubfield => equalityFunction(sourceSubfield, baseSubfield)));\n debug(`equalSubfieldsSource: ${JSON.stringify(equalSubfieldsSource, undefined, 2)}`);\n\n if (baseSubs.length === sourceSubs.length && equalSubfieldsBase.length < baseSubs.length) {\n debug(`Base and source subfields are not equal`);\n debug(`No changes to base`);\n return baseRecord.toObject();\n }\n\n if (baseSubs.length === sourceSubs.length && equalSubfieldsBase.length === equalSubfieldsSource.length) {\n debug(`Checking subfield equality`);\n const totalSubfieldLengthBase = baseSubsNormalized\n .map(({value}) => value.length)\n .reduce((acc, value) => acc + value);\n const totalSubfieldLengthSource = sourceSubsNormalized\n .map(({value}) => value.length)\n .reduce((acc, value) => acc + value);\n\n if (totalSubfieldLengthSource > totalSubfieldLengthBase) {\n return replaceBasefieldWithSourcefield(baseRecord.toObject());\n }\n }\n\n if (sourceSubs.length > baseSubs.length && equalSubfieldsBase.length === baseSubs.length) {\n return replaceBasefieldWithSourcefield(baseRecord.toObject());\n }\n\n debug(`No changes to base`);\n return baseRecord.toObject();\n\n function replaceBasefieldWithSourcefield(base) {\n const index = base.fields.findIndex(field => field === baseField);\n base.fields.splice(index, 1, sourceField);\n debug(`Source field is longer, replacing base with source`);\n return base;\n }\n\n function checkFieldType(fields) {\n const checkedFields = fields.map(field => {\n if ('value' in field) {\n throw new Error('Invalid control field, expected data field');\n }\n return field;\n });\n return checkedFields;\n }\n\n function normalizeSubfieldValue(value) {\n // Regexp options: g: global search, u: unicode\n const punctuation = /[.,\\-/#!?$%^&*;:{}=_`~()[\\]]/gu;\n return normalizeSync(value).toLowerCase().replace(punctuation, '', 'u').replace(/\\s+/gu, ' ').trim();\n }\n};\n"],
5
+ "mappings": "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",
6
6
  "names": ["base", "source", "baseValidators", "sourceValidators", "baseRecord", "sourceRecord"]
7
7
  }
package/package.json CHANGED
@@ -13,7 +13,7 @@
13
13
  "url": "https://github.com/NatLibFi/marc-record-merge-js"
14
14
  },
15
15
  "license": "MIT",
16
- "version": "8.0.0",
16
+ "version": "8.0.1-alpha.1",
17
17
  "type": "module",
18
18
  "main": "./dist/index.js",
19
19
  "engines": {
@@ -31,15 +31,15 @@
31
31
  "test:dev": "npm run lint:dev && npm run test:base"
32
32
  },
33
33
  "dependencies": {
34
- "@natlibfi/marc-record": "^10.0.0",
35
- "debug": "^4.4.1",
34
+ "@natlibfi/marc-record": "^10.0.1",
35
+ "debug": "^4.4.3",
36
36
  "normalize-diacritics": "^2.14.0"
37
37
  },
38
38
  "devDependencies": {
39
39
  "@natlibfi/fixugen": "^3.0.0",
40
40
  "@natlibfi/fixura": "^4.0.0",
41
41
  "cross-env": "^10.1.0",
42
- "esbuild": "^0.25.12",
43
- "eslint": "^9.39.1"
42
+ "esbuild": "^0.27.2",
43
+ "eslint": "^9.39.2"
44
44
  }
45
45
  }
@@ -237,7 +237,7 @@ export default ({
237
237
  return fields;
238
238
 
239
239
  function dropSubfieldsFunc(subfields) {
240
- return subfields.filter(sub => { // eslint-disable-line
240
+ return subfields.filter(sub => {
241
241
  return !dropSubfields.some(({code, value = false, condition = false}) => {
242
242
  if (code !== sub.code) {
243
243
  return false;
@@ -18,7 +18,6 @@ export default ({
18
18
  equalityFunction = strictEquality,
19
19
  baseValidators = {subfieldValues: false},
20
20
  sourceValidators = {subfieldValues: false}
21
- // eslint-disable-next-line max-statements
22
21
  }) => (base, source) => {
23
22
  const debug = createDebugLogger('@natlibfi/marc-record-merge:select');
24
23