@natlibfi/marc-record-validators-melinda 12.1.0-alpha.1 → 13.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (425) hide show
  1. package/.github/workflows/melinda-node-tests-and-publish.yml +17 -17
  2. package/README.md +1 -1
  3. package/dist/addMissingField041.js +6 -3
  4. package/dist/addMissingField041.js.map +2 -2
  5. package/dist/addMissingField336.js +7 -4
  6. package/dist/addMissingField336.js.map +2 -2
  7. package/dist/addMissingField337.js +6 -3
  8. package/dist/addMissingField337.js.map +2 -2
  9. package/dist/addMissingField338.js +8 -5
  10. package/dist/addMissingField338.js.map +2 -2
  11. package/dist/cyrillux-usemarcon-replacement.js +5 -2
  12. package/dist/cyrillux-usemarcon-replacement.js.map +2 -2
  13. package/dist/cyrillux.js +24 -18
  14. package/dist/cyrillux.js.map +2 -2
  15. package/dist/dataProvenanceUtils.js +19 -0
  16. package/dist/dataProvenanceUtils.js.map +7 -0
  17. package/dist/disambiguateSeriesStatements.js +2 -1
  18. package/dist/disambiguateSeriesStatements.js.map +2 -2
  19. package/dist/disambiguateSeriesStatements.test.js +1 -7
  20. package/dist/disambiguateSeriesStatements.test.js.map +2 -2
  21. package/dist/drop-terms.js +123 -0
  22. package/dist/drop-terms.js.map +7 -0
  23. package/dist/drop-terms.test.js +56 -0
  24. package/dist/drop-terms.test.js.map +7 -0
  25. package/dist/field-008-18-34-character-groups.test.js +1 -7
  26. package/dist/field-008-18-34-character-groups.test.js.map +2 -2
  27. package/dist/field-505-separators.test.js +1 -7
  28. package/dist/field-505-separators.test.js.map +2 -2
  29. package/dist/field-521-fix.test.js +1 -7
  30. package/dist/field-521-fix.test.js.map +2 -2
  31. package/dist/fix-33X.js +7 -4
  32. package/dist/fix-33X.js.map +2 -2
  33. package/dist/fix-33X.test.js +1 -1
  34. package/dist/fix-33X.test.js.map +1 -1
  35. package/dist/fix-country-codes.js +5 -0
  36. package/dist/fix-country-codes.js.map +2 -2
  37. package/dist/fix-country-codes.test.js +1 -7
  38. package/dist/fix-country-codes.test.js.map +2 -2
  39. package/dist/fix-language-codes.js +5 -1
  40. package/dist/fix-language-codes.js.map +2 -2
  41. package/dist/fix-sami-041.js +109 -0
  42. package/dist/fix-sami-041.js.map +7 -0
  43. package/dist/fix-sami-041.test.js +40 -0
  44. package/dist/fix-sami-041.test.js.map +7 -0
  45. package/dist/fixRelatorTerms.js +2 -0
  46. package/dist/fixRelatorTerms.js.map +2 -2
  47. package/dist/fixRelatorTerms.test.js +1 -7
  48. package/dist/fixRelatorTerms.test.js.map +2 -2
  49. package/dist/index.js +18 -4
  50. package/dist/index.js.map +2 -2
  51. package/dist/indicator-fixes.js +15 -1
  52. package/dist/indicator-fixes.js.map +2 -2
  53. package/dist/indicator-fixes.test.js +1 -7
  54. package/dist/indicator-fixes.test.js.map +2 -2
  55. package/dist/item-language.js +41 -39
  56. package/dist/item-language.js.map +2 -2
  57. package/dist/item-language.test.js +3 -3
  58. package/dist/item-language.test.js.map +2 -2
  59. package/dist/melindaCustomMergeFields.js +31 -0
  60. package/dist/melindaCustomMergeFields.js.map +2 -2
  61. package/dist/merge-fields/controlSubfields.js.map +2 -2
  62. package/dist/merge-fields/counterpartField.js +149 -152
  63. package/dist/merge-fields/counterpartField.js.map +3 -3
  64. package/dist/merge-fields/dataProvenance.js +6 -20
  65. package/dist/merge-fields/dataProvenance.js.map +2 -2
  66. package/dist/merge-fields/index.js +1 -1
  67. package/dist/merge-fields/index.js.map +2 -2
  68. package/dist/merge-fields/mergableIndicator.js +1 -5
  69. package/dist/merge-fields/mergableIndicator.js.map +2 -2
  70. package/dist/merge-fields/mergableTag.js +2 -0
  71. package/dist/merge-fields/mergableTag.js.map +2 -2
  72. package/dist/merge-fields/mergeConfig.js +2 -0
  73. package/dist/merge-fields/mergeConfig.js.map +2 -2
  74. package/dist/merge-fields/mergeConstraints.js +38 -35
  75. package/dist/merge-fields/mergeConstraints.js.map +3 -3
  76. package/dist/merge-fields/mergeField.js +4 -3
  77. package/dist/merge-fields/mergeField.js.map +2 -2
  78. package/dist/merge-fields/mergeOrAddSubfield.js +8 -7
  79. package/dist/merge-fields/mergeOrAddSubfield.js.map +2 -2
  80. package/dist/merge-fields/mergeSubfield.js +5 -1
  81. package/dist/merge-fields/mergeSubfield.js.map +2 -2
  82. package/dist/merge-fields/worldKnowledge.js +52 -0
  83. package/dist/merge-fields/worldKnowledge.js.map +2 -2
  84. package/dist/merge-fields.test.js +4 -9
  85. package/dist/merge-fields.test.js.map +2 -2
  86. package/dist/mergeField500Lisapainokset.test.js +1 -7
  87. package/dist/mergeField500Lisapainokset.test.js.map +2 -2
  88. package/dist/mergeRelatorTermFields.js +9 -6
  89. package/dist/mergeRelatorTermFields.js.map +2 -2
  90. package/dist/mergeRelatorTermFields.test.js +1 -7
  91. package/dist/mergeRelatorTermFields.test.js.map +2 -2
  92. package/dist/multiple-subfield-0.test.js +1 -7
  93. package/dist/multiple-subfield-0.test.js.map +2 -2
  94. package/dist/normalize-dashes.js +9 -6
  95. package/dist/normalize-dashes.js.map +2 -2
  96. package/dist/normalize-dashes.test.js +1 -7
  97. package/dist/normalize-dashes.test.js.map +2 -2
  98. package/dist/normalize-identifiers.js.map +2 -2
  99. package/dist/normalize-identifiers.test.js +1 -7
  100. package/dist/normalize-identifiers.test.js.map +2 -2
  101. package/dist/normalize-qualifying-information.test.js +1 -7
  102. package/dist/normalize-qualifying-information.test.js.map +2 -2
  103. package/dist/normalize-utf8-diacritics.js.map +2 -2
  104. package/dist/normalize-utf8-diacritics.test.js +1 -7
  105. package/dist/normalize-utf8-diacritics.test.js.map +2 -2
  106. package/dist/normalizeFieldForComparison.js +24 -14
  107. package/dist/normalizeFieldForComparison.js.map +2 -2
  108. package/dist/normalizeSubfieldValueForComparison.js.map +1 -1
  109. package/dist/prepublicationUtils.js +1 -1
  110. package/dist/prepublicationUtils.js.map +2 -2
  111. package/dist/punctuation.test.js +1 -7
  112. package/dist/punctuation.test.js.map +2 -2
  113. package/dist/punctuation2.js +15 -12
  114. package/dist/punctuation2.js.map +2 -2
  115. package/dist/punctuation2.test.js +1 -7
  116. package/dist/punctuation2.test.js.map +2 -2
  117. package/dist/reindexSubfield6OccurenceNumbers.js +11 -10
  118. package/dist/reindexSubfield6OccurenceNumbers.js.map +2 -2
  119. package/dist/reindexSubfield6OccurenceNumbers.test.js +1 -7
  120. package/dist/reindexSubfield6OccurenceNumbers.test.js.map +2 -2
  121. package/dist/remove-041-zxx.js +56 -0
  122. package/dist/remove-041-zxx.js.map +7 -0
  123. package/dist/remove-041-zxx.test.js +40 -0
  124. package/dist/remove-041-zxx.test.js.map +7 -0
  125. package/dist/removeDuplicateDataFields.js +4 -26
  126. package/dist/removeDuplicateDataFields.js.map +2 -2
  127. package/dist/removeDuplicateDataFields.test.js +1 -7
  128. package/dist/removeDuplicateDataFields.test.js.map +2 -2
  129. package/dist/removeInferiorDataFields.js +82 -45
  130. package/dist/removeInferiorDataFields.js.map +3 -3
  131. package/dist/removeInferiorDataFields.test.js +5 -9
  132. package/dist/removeInferiorDataFields.test.js.map +2 -2
  133. package/dist/resolveOrphanedSubfield6s.js +4 -5
  134. package/dist/resolveOrphanedSubfield6s.js.map +2 -2
  135. package/dist/resolveOrphanedSubfield6s.test.js +1 -7
  136. package/dist/resolveOrphanedSubfield6s.test.js.map +2 -2
  137. package/dist/sanitize-vocabulary-source-codes.test.js +1 -7
  138. package/dist/sanitize-vocabulary-source-codes.test.js.map +2 -2
  139. package/dist/sortFields.js +16 -1
  140. package/dist/sortFields.js.map +2 -2
  141. package/dist/sortFields.test.js +1 -7
  142. package/dist/sortFields.test.js.map +2 -2
  143. package/dist/sortRelatorTerms.test.js +1 -7
  144. package/dist/sortRelatorTerms.test.js.map +2 -2
  145. package/dist/sortSubfields.js +27 -21
  146. package/dist/sortSubfields.js.map +2 -2
  147. package/dist/sortSubfields.test.js +1 -7
  148. package/dist/sortSubfields.test.js.map +2 -2
  149. package/dist/stripPunctuation.js +7 -3
  150. package/dist/stripPunctuation.js.map +2 -2
  151. package/dist/stripPunctuation.test.js +1 -7
  152. package/dist/stripPunctuation.test.js.map +2 -2
  153. package/dist/subfield6Utils.js +2 -12
  154. package/dist/subfield6Utils.js.map +2 -2
  155. package/dist/subfield8Utils.js +0 -5
  156. package/dist/subfield8Utils.js.map +2 -2
  157. package/dist/subfieldValueNormalizations.test.js +1 -7
  158. package/dist/subfieldValueNormalizations.test.js.map +2 -2
  159. package/dist/sync-007-and-300.test.js +1 -7
  160. package/dist/sync-007-and-300.test.js.map +2 -2
  161. package/dist/sync-language.js +103 -0
  162. package/dist/sync-language.js.map +7 -0
  163. package/dist/sync-language.test.js +40 -0
  164. package/dist/sync-language.test.js.map +7 -0
  165. package/dist/translate-terms.js +124 -87
  166. package/dist/translate-terms.js.map +3 -3
  167. package/dist/translate-terms.test.js +5 -8
  168. package/dist/translate-terms.test.js.map +2 -2
  169. package/dist/typeOfDate-008.js +3 -1
  170. package/dist/typeOfDate-008.js.map +2 -2
  171. package/dist/update-field-540.js.map +2 -2
  172. package/dist/update-field-540.test.js +1 -7
  173. package/dist/update-field-540.test.js.map +2 -2
  174. package/dist/urn.js +13 -12
  175. package/dist/urn.js.map +2 -2
  176. package/dist/urn.test.js +1 -7
  177. package/dist/urn.test.js.map +2 -2
  178. package/dist/utils.js +29 -3
  179. package/dist/utils.js.map +2 -2
  180. package/package.json +20 -27
  181. package/src/addMissingField041.js +8 -4
  182. package/src/addMissingField336.js +10 -5
  183. package/src/addMissingField337.js +9 -5
  184. package/src/addMissingField338.js +11 -6
  185. package/src/cyrillux-usemarcon-replacement.js +9 -5
  186. package/src/cyrillux.js +34 -23
  187. package/src/dataProvenanceUtils.js +21 -0
  188. package/src/disambiguateSeriesStatements.js +4 -1
  189. package/src/disambiguateSeriesStatements.test.js +3 -8
  190. package/src/drop-terms.js +164 -0
  191. package/src/drop-terms.test.js +81 -0
  192. package/src/field-008-18-34-character-groups.test.js +3 -8
  193. package/src/field-505-separators.test.js +3 -8
  194. package/src/field-521-fix.test.js +3 -8
  195. package/src/fix-33X.js +10 -6
  196. package/src/fix-33X.test.js +1 -1
  197. package/src/fix-country-codes.js +7 -3
  198. package/src/fix-country-codes.test.js +3 -8
  199. package/src/fix-language-codes.js +8 -4
  200. package/src/fix-sami-041.js +147 -0
  201. package/src/fix-sami-041.test.js +52 -0
  202. package/src/fixRelatorTerms.js +5 -0
  203. package/src/fixRelatorTerms.test.js +3 -8
  204. package/src/index.js +20 -7
  205. package/src/indicator-fixes.js +22 -7
  206. package/src/indicator-fixes.test.js +3 -8
  207. package/src/item-language.js +49 -42
  208. package/src/item-language.test.js +3 -3
  209. package/src/melindaCustomMergeFields.js +31 -0
  210. package/src/merge-fields/controlSubfields.js +0 -1
  211. package/src/merge-fields/counterpartField.js +191 -290
  212. package/src/merge-fields/dataProvenance.js +8 -25
  213. package/src/merge-fields/index.js +1 -1
  214. package/src/merge-fields/mergableIndicator.js +4 -5
  215. package/src/merge-fields/mergableTag.js +2 -0
  216. package/src/merge-fields/mergeConfig.js +2 -1
  217. package/src/merge-fields/mergeConstraints.js +41 -36
  218. package/src/merge-fields/mergeField.js +4 -7
  219. package/src/merge-fields/mergeOrAddSubfield.js +8 -7
  220. package/src/merge-fields/mergeSubfield.js +11 -2
  221. package/src/merge-fields/worldKnowledge.js +77 -3
  222. package/src/merge-fields.test.js +5 -10
  223. package/src/mergeField500Lisapainokset.test.js +3 -8
  224. package/src/mergeRelatorTermFields.js +12 -11
  225. package/src/mergeRelatorTermFields.test.js +3 -8
  226. package/src/multiple-subfield-0.test.js +3 -8
  227. package/src/normalize-dashes.js +13 -7
  228. package/src/normalize-dashes.test.js +3 -8
  229. package/src/normalize-identifiers.js +12 -19
  230. package/src/normalize-identifiers.test.js +3 -8
  231. package/src/normalize-qualifying-information.test.js +3 -8
  232. package/src/normalize-utf8-diacritics.js +6 -3
  233. package/src/normalize-utf8-diacritics.test.js +3 -8
  234. package/src/normalizeFieldForComparison.js +39 -22
  235. package/src/normalizeSubfieldValueForComparison.js +2 -2
  236. package/src/prepublicationUtils.js +1 -1
  237. package/src/punctuation.test.js +3 -8
  238. package/src/punctuation2.js +44 -40
  239. package/src/punctuation2.test.js +3 -8
  240. package/src/reindexSubfield6OccurenceNumbers.js +13 -11
  241. package/src/reindexSubfield6OccurenceNumbers.test.js +3 -8
  242. package/src/remove-041-zxx.js +85 -0
  243. package/src/remove-041-zxx.test.js +52 -0
  244. package/src/removeDuplicateDataFields.js +30 -28
  245. package/src/removeDuplicateDataFields.test.js +3 -8
  246. package/src/removeInferiorDataFields.js +126 -71
  247. package/src/removeInferiorDataFields.test.js +7 -10
  248. package/src/resolveOrphanedSubfield6s.js +7 -5
  249. package/src/resolveOrphanedSubfield6s.test.js +3 -8
  250. package/src/sanitize-vocabulary-source-codes.test.js +3 -8
  251. package/src/sortFields.js +20 -1
  252. package/src/sortFields.test.js +3 -8
  253. package/src/sortRelatorTerms.test.js +3 -8
  254. package/src/sortSubfields.js +31 -25
  255. package/src/sortSubfields.test.js +3 -8
  256. package/src/stripPunctuation.js +10 -5
  257. package/src/stripPunctuation.test.js +3 -8
  258. package/src/subfield6Utils.js +31 -33
  259. package/src/subfield8Utils.js +10 -7
  260. package/src/subfieldValueNormalizations.test.js +3 -8
  261. package/src/sync-007-and-300.test.js +3 -8
  262. package/src/sync-language.js +148 -0
  263. package/src/sync-language.test.js +52 -0
  264. package/src/translate-terms.js +168 -109
  265. package/src/translate-terms.test.js +12 -16
  266. package/src/typeOfDate-008.js +4 -1
  267. package/src/update-field-540.js +7 -5
  268. package/src/update-field-540.test.js +3 -8
  269. package/src/urn.js +17 -13
  270. package/src/urn.test.js +3 -8
  271. package/src/utils.js +39 -12
  272. package/test-fixtures/cyrillux/f02b/expectedResult.json +23 -0
  273. package/test-fixtures/cyrillux/f02b/metadata.json +11 -0
  274. package/test-fixtures/cyrillux/f02b/record.json +14 -0
  275. package/test-fixtures/cyrillux/f14/expectedResult.json +32 -0
  276. package/test-fixtures/cyrillux/f14/metadata.json +10 -0
  277. package/test-fixtures/cyrillux/f14/record.json +14 -0
  278. package/test-fixtures/drop-terms/01/expectedResult.json +31 -0
  279. package/test-fixtures/drop-terms/01/metadata.json +6 -0
  280. package/test-fixtures/drop-terms/01/record.json +35 -0
  281. package/test-fixtures/drop-terms/02/expectedResult.json +7 -0
  282. package/test-fixtures/drop-terms/02/metadata.json +6 -0
  283. package/test-fixtures/drop-terms/02/record.json +40 -0
  284. package/test-fixtures/drop-terms/03/expectedResult.json +6 -0
  285. package/test-fixtures/drop-terms/03/metadata.json +18 -0
  286. package/test-fixtures/drop-terms/03/record.json +39 -0
  287. package/test-fixtures/drop-terms/04/expectedResult.json +6 -0
  288. package/test-fixtures/drop-terms/04/metadata.json +19 -0
  289. package/test-fixtures/drop-terms/04/record.json +24 -0
  290. package/test-fixtures/fix-language-codes/02/metadata.json +1 -1
  291. package/test-fixtures/fix-relator-terms/f02/metadata.json +1 -1
  292. package/test-fixtures/fix-relator-terms/f04/expectedResult.json +18 -0
  293. package/test-fixtures/fix-relator-terms/f04/metadata.json +5 -0
  294. package/test-fixtures/fix-relator-terms/f04/record.json +20 -0
  295. package/test-fixtures/fix-sami-041/01/expectedResult.json +6 -0
  296. package/test-fixtures/fix-sami-041/01/metadata.json +4 -0
  297. package/test-fixtures/fix-sami-041/01/record.json +14 -0
  298. package/test-fixtures/fix-sami-041/02/expectedResult.json +10 -0
  299. package/test-fixtures/fix-sami-041/02/metadata.json +4 -0
  300. package/test-fixtures/fix-sami-041/02/record.json +8 -0
  301. package/test-fixtures/fix-sami-041/03/expectedResult.json +5 -0
  302. package/test-fixtures/fix-sami-041/03/metadata.json +5 -0
  303. package/test-fixtures/fix-sami-041/03/record.json +8 -0
  304. package/test-fixtures/fix-sami-041/04/expectedResult.json +7 -0
  305. package/test-fixtures/fix-sami-041/04/metadata.json +4 -0
  306. package/test-fixtures/fix-sami-041/04/record.json +10 -0
  307. package/test-fixtures/fix-sami-041/05/expectedResult.json +10 -0
  308. package/test-fixtures/fix-sami-041/05/metadata.json +6 -0
  309. package/test-fixtures/fix-sami-041/05/record.json +8 -0
  310. package/test-fixtures/fix-sami-041/06/expectedResult.json +10 -0
  311. package/test-fixtures/fix-sami-041/06/metadata.json +4 -0
  312. package/test-fixtures/fix-sami-041/06/record.json +9 -0
  313. package/test-fixtures/indicator-fixes/11/expectedResult.json +10 -0
  314. package/test-fixtures/indicator-fixes/11/metadata.json +4 -0
  315. package/test-fixtures/indicator-fixes/11/record.json +10 -0
  316. package/test-fixtures/merge-fields/f042_01/expectedResult.json +12 -0
  317. package/test-fixtures/merge-fields/f042_01/metadata.json +6 -0
  318. package/test-fixtures/merge-fields/f042_01/record.json +13 -0
  319. package/test-fixtures/merge-fields/f05/metadata.json +1 -1
  320. package/test-fixtures/merge-fields/f06/expectedResult.json +42 -0
  321. package/test-fixtures/merge-fields/f06/metadata.json +6 -0
  322. package/test-fixtures/merge-fields/f06/record.json +41 -0
  323. package/test-fixtures/merge-fields/f07/expectedResult.json +18 -0
  324. package/test-fixtures/merge-fields/f07/metadata.json +6 -0
  325. package/test-fixtures/merge-fields/f07/record.json +18 -0
  326. package/test-fixtures/merge-fields/f08/expectedResult.json +12 -0
  327. package/test-fixtures/merge-fields/f08/metadata.json +7 -0
  328. package/test-fixtures/merge-fields/f08/record.json +10 -0
  329. package/test-fixtures/merge-fields/f09/expectedResult.json +14 -0
  330. package/test-fixtures/merge-fields/f09/metadata.json +6 -0
  331. package/test-fixtures/merge-fields/f09/record.json +14 -0
  332. package/test-fixtures/merge-fields/f10/expectedResult.json +25 -0
  333. package/test-fixtures/merge-fields/f10/metadata.json +6 -0
  334. package/test-fixtures/merge-fields/f10/record.json +25 -0
  335. package/test-fixtures/merge-fields/f11/expectedResult.json +40 -0
  336. package/test-fixtures/merge-fields/f11/metadata.json +7 -0
  337. package/test-fixtures/merge-fields/f11/record.json +50 -0
  338. package/test-fixtures/merge-fields/f12/expectedResult.json +17 -0
  339. package/test-fixtures/merge-fields/f12/metadata.json +6 -0
  340. package/test-fixtures/merge-fields/f12/record.json +25 -0
  341. package/test-fixtures/merge-fields/f13/expectedResult.json +18 -0
  342. package/test-fixtures/merge-fields/f13/metadata.json +6 -0
  343. package/test-fixtures/merge-fields/f13/record.json +28 -0
  344. package/test-fixtures/merge-fields/f14/expectedResult.json +25 -0
  345. package/test-fixtures/merge-fields/f14/metadata.json +6 -0
  346. package/test-fixtures/merge-fields/f14/record.json +25 -0
  347. package/test-fixtures/merge-fields/f15/expectedResult.json +8 -0
  348. package/test-fixtures/merge-fields/f15/metadata.json +6 -0
  349. package/test-fixtures/merge-fields/f15/record.json +9 -0
  350. package/test-fixtures/merge-fields/f16/expectedResult.json +12 -0
  351. package/test-fixtures/merge-fields/f16/metadata.json +7 -0
  352. package/test-fixtures/merge-fields/f16/record.json +13 -0
  353. package/test-fixtures/merge-fields/f300_01/expectedResult.json +9 -0
  354. package/test-fixtures/merge-fields/f300_01/metadata.json +6 -0
  355. package/test-fixtures/merge-fields/f300_01/record.json +8 -0
  356. package/test-fixtures/merge-fields/f300_02/expectedResult.json +13 -0
  357. package/test-fixtures/merge-fields/f300_02/metadata.json +6 -0
  358. package/test-fixtures/merge-fields/f300_02/record.json +16 -0
  359. package/test-fixtures/merge-fields/f300_03/expectedResult.json +13 -0
  360. package/test-fixtures/merge-fields/f300_03/metadata.json +6 -0
  361. package/test-fixtures/merge-fields/f300_03/record.json +16 -0
  362. package/test-fixtures/merge-fields/f490_01/expectedResult.json +13 -0
  363. package/test-fixtures/merge-fields/f490_01/metadata.json +6 -0
  364. package/test-fixtures/merge-fields/f490_01/record.json +16 -0
  365. package/test-fixtures/remove-041-zxx/01/expectedResult.json +5 -0
  366. package/test-fixtures/remove-041-zxx/01/metadata.json +5 -0
  367. package/test-fixtures/remove-041-zxx/01/record.json +10 -0
  368. package/test-fixtures/remove-041-zxx/02/expectedResult.json +7 -0
  369. package/test-fixtures/remove-041-zxx/02/metadata.json +5 -0
  370. package/test-fixtures/remove-041-zxx/02/record.json +9 -0
  371. package/test-fixtures/remove-041-zxx/11/expectedResult.json +10 -0
  372. package/test-fixtures/remove-041-zxx/11/metadata.json +5 -0
  373. package/test-fixtures/remove-041-zxx/11/record.json +9 -0
  374. package/test-fixtures/remove-041-zxx/12/expectedResult.json +10 -0
  375. package/test-fixtures/remove-041-zxx/12/metadata.json +5 -0
  376. package/test-fixtures/remove-041-zxx/12/record.json +9 -0
  377. package/test-fixtures/remove-inferior-datafields/f17/expectedResult.json +11 -0
  378. package/test-fixtures/remove-inferior-datafields/f17/metadata.json +5 -0
  379. package/test-fixtures/remove-inferior-datafields/f17/record.json +15 -0
  380. package/test-fixtures/remove-inferior-datafields/f18/expectedResult.json +13 -0
  381. package/test-fixtures/remove-inferior-datafields/f18/metadata.json +5 -0
  382. package/test-fixtures/remove-inferior-datafields/f18/record.json +18 -0
  383. package/test-fixtures/remove-inferior-datafields/f19/expectedResult.json +17 -0
  384. package/test-fixtures/remove-inferior-datafields/f19/metadata.json +5 -0
  385. package/test-fixtures/remove-inferior-datafields/f19/record.json +18 -0
  386. package/test-fixtures/remove-inferior-datafields/f20/expectedResult.json +15 -0
  387. package/test-fixtures/remove-inferior-datafields/f20/metadata.json +5 -0
  388. package/test-fixtures/remove-inferior-datafields/f20/record.json +29 -0
  389. package/test-fixtures/sort-fields/15/input.json +9 -0
  390. package/test-fixtures/sort-fields/15/metadata.json +5 -0
  391. package/test-fixtures/sort-fields/15/result.json +10 -0
  392. package/test-fixtures/sync-language/01/expectedResult.json +5 -0
  393. package/test-fixtures/sync-language/01/metadata.json +5 -0
  394. package/test-fixtures/sync-language/01/record.json +7 -0
  395. package/test-fixtures/sync-language/02/expectedResult.json +6 -0
  396. package/test-fixtures/sync-language/02/metadata.json +5 -0
  397. package/test-fixtures/sync-language/02/record.json +10 -0
  398. package/test-fixtures/sync-language/03/expectedResult.json +6 -0
  399. package/test-fixtures/sync-language/03/metadata.json +5 -0
  400. package/test-fixtures/sync-language/03/record.json +6 -0
  401. package/test-fixtures/sync-language/10/expectedResult.json +10 -0
  402. package/test-fixtures/sync-language/10/metadata.json +5 -0
  403. package/test-fixtures/sync-language/10/record.json +8 -0
  404. package/test-fixtures/sync-language/11/expectedResult.json +10 -0
  405. package/test-fixtures/sync-language/11/metadata.json +5 -0
  406. package/test-fixtures/sync-language/11/record.json +7 -0
  407. package/test-fixtures/sync-language/12/expectedResult.json +9 -0
  408. package/test-fixtures/sync-language/12/metadata.json +6 -0
  409. package/test-fixtures/sync-language/12/record.json +6 -0
  410. package/test-fixtures/sync-language/13/expectedResult.json +10 -0
  411. package/test-fixtures/sync-language/13/metadata.json +5 -0
  412. package/test-fixtures/sync-language/13/record.json +8 -0
  413. package/test-fixtures/sync-language/14/expectedResult.json +9 -0
  414. package/test-fixtures/sync-language/14/metadata.json +5 -0
  415. package/test-fixtures/sync-language/14/record.json +7 -0
  416. package/test-fixtures/sync-language/15/expectedResult.json +9 -0
  417. package/test-fixtures/sync-language/15/metadata.json +5 -0
  418. package/test-fixtures/sync-language/15/record.json +7 -0
  419. package/test-fixtures/translate-terms/05/expectedResult.json +12 -0
  420. package/test-fixtures/translate-terms/05/metadata.json +7 -0
  421. package/test-fixtures/translate-terms/05/record.json +11 -0
  422. package/test-fixtures/translate-terms/06/expectedResult.json +12 -0
  423. package/test-fixtures/translate-terms/06/metadata.json +7 -0
  424. package/test-fixtures/translate-terms/06/record.json +11 -0
  425. package/test-fixtures/translate-terms-data.js +23 -0
package/dist/urn.js CHANGED
@@ -1,9 +1,10 @@
1
- import { isElectronicMaterial } from "./utils.js";
1
+ import { isElectronicMaterial, nvdebug } from "./utils.js";
2
2
  import createDebugLogger from "debug";
3
3
  const URN_GENERATOR_URL = "https://generator.urn.fi/cgi-bin/urn_generator.cgi?type=nbn";
4
4
  export default function(isLegalDeposit = false, useMelindaTemp = true) {
5
5
  const debug = createDebugLogger("@natlibfi/marc-record-validators-melinda:urn");
6
6
  const debugData = debug.extend("data");
7
+ const debugDev = debug.extend("dev");
7
8
  function hasLegalDepositURN(field) {
8
9
  if (field.tag !== "856" || ["1", "2", "3", "4"].includes(field.ind2)) {
9
10
  return false;
@@ -20,9 +21,9 @@ export default function(isLegalDeposit = false, useMelindaTemp = true) {
20
21
  };
21
22
  async function fix(record) {
22
23
  const f856sUrn = record.fields.filter(hasLegalDepositURN);
23
- debugData(`f856sUrn: ${JSON.stringify(f856sUrn)}`);
24
+ nvdebug(`f856sUrn: ${JSON.stringify(f856sUrn)}`, debugDev);
24
25
  const ldSubfields = isLegalDeposit ? createLDSubfields() : [];
25
- debugData(`IsLegalDeposit: ${isLegalDeposit}, LegalDepositSubfields: ${JSON.stringify(ldSubfields)}`);
26
+ nvdebug(`IsLegalDeposit: ${isLegalDeposit}, LegalDepositSubfields: ${JSON.stringify(ldSubfields)}`, debugDev);
26
27
  if (f856sUrn.length === 0) {
27
28
  const { code, value, generated } = await createURNSubfield(record);
28
29
  if (generated && useMelindaTemp) {
@@ -64,7 +65,7 @@ export default function(isLegalDeposit = false, useMelindaTemp = true) {
64
65
  }
65
66
  return acc;
66
67
  }, void 0);
67
- debugData(`isbns: ${isbn}`);
68
+ nvdebug(`isbns: ${isbn}`, debugDev);
68
69
  const { generated, value } = await createURN(isbn);
69
70
  return { code: "u", value, generated };
70
71
  async function createURN(isbn2 = false) {
@@ -101,31 +102,31 @@ export default function(isLegalDeposit = false, useMelindaTemp = true) {
101
102
  }
102
103
  }
103
104
  function validateLD(f856sUrn) {
104
- debug(`Validating the existence of legal deposit subfields`);
105
+ nvdebug(`Validating the existence of legal deposit subfields`, debugDev);
105
106
  const ldSubfields = createLDSubfields();
106
107
  const f856sUrnWithLdSubfields = f856sUrn.filter((field) => fieldHasLDSubfields(field, ldSubfields));
107
108
  if (f856sUrnWithLdSubfields.length > 0) {
108
- debug(`Record has ${f856sUrnWithLdSubfields.length} URN fields with all necessary legal deposit subfields`);
109
- debugData(`f856sUrnWithLdSubfields: ${JSON.stringify(f856sUrnWithLdSubfields)}`);
109
+ nvdebug(`Record has ${f856sUrnWithLdSubfields.length} URN fields with all necessary legal deposit subfields`, debugDev);
110
+ nvdebug(`f856sUrnWithLdSubfields: ${JSON.stringify(f856sUrnWithLdSubfields)}`, debugData);
110
111
  return true;
111
112
  }
112
113
  return false;
113
114
  }
114
115
  function validate(record) {
115
116
  if (!isElectronicMaterial(record)) {
116
- debug(`Record is not electronic - no need to validate legal deposit URNs`);
117
+ nvdebug(`Record is not electronic - no need to validate legal deposit URNs`, debugDev);
117
118
  return { valid: true };
118
119
  }
119
120
  const f856sUrn = record.fields.filter(hasLegalDepositURN);
120
121
  if (f856sUrn.length > 0) {
121
- debug(`Record has ${f856sUrn.length} URN fields`);
122
- debugData(`f856sUrn: ${JSON.stringify(f856sUrn)}`);
122
+ nvdebug(`Record has ${f856sUrn.length} URN fields`, debugDev);
123
+ nvdebug(`f856sUrn: ${JSON.stringify(f856sUrn)}`, debugData);
123
124
  if (!isLegalDeposit || validateLD(f856sUrn)) {
124
- debug(`Record is valid`);
125
+ nvdebug(`Record is valid`, debugDev);
125
126
  return { valid: true };
126
127
  }
127
128
  }
128
- debug(`No (valid) URN fields - Record is not valid`);
129
+ nvdebug(`No (valid) URN fields - Record is not valid`, debugDev);
129
130
  return { valid: false };
130
131
  }
131
132
  }
package/dist/urn.js.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/urn.js"],
4
- "sourcesContent": ["//import fetch from 'node-fetch';\nimport {isElectronicMaterial} from './utils.js';\nimport createDebugLogger from 'debug';\n\nconst URN_GENERATOR_URL = 'https://generator.urn.fi/cgi-bin/urn_generator.cgi?type=nbn';\n\nexport default function (isLegalDeposit = false, useMelindaTemp = true) {\n const debug = createDebugLogger('@natlibfi/marc-record-validators-melinda:urn');\n const debugData = debug.extend('data');\n\n //console.log(`IS LEGAL DEPOSIT? ${isLegalDeposit ? 'YES' : 'NO'}`); // eslint-disable-line no-console\n\n // We should check that the f856 with URN has second indicator '0' (Resource), ' ' (No information provided) or '8' (No display constant generated)\n // - if second indicator is '1' (Version of resource) or '2' (Related resource) the URN in f856 is not correct for the resource described in the record\n\n // This checks only the existence of URNs from the Finnish urn.fi -resolver\n\n function hasLegalDepositURN(field) {\n if (field.tag !== '856' || ['1', '2', '3', '4'].includes(field.ind2)) {\n return false;\n }\n\n // First attempt to fix MET-573. However, does useMelindaTemp come into play as well?\n if (isLegalDeposit && !field.subfields.some(sf => sf.code === '5' && sf.value === 'FI-Vapaa')) {\n return false;\n }\n\n return field.subfields.some(sf => sf.code === 'u' && (/^https?:\\/\\/urn\\.fi/u).test(sf.value));\n }\n\n\n return {\n description: 'Adds URN for record, to 856-field (if not existing). If isLegalDeposit is active, adds legal deposit subfields to the f856s with URN.',\n validate,\n fix\n };\n\n async function fix(record) {\n const f856sUrn = record.fields.filter(hasLegalDepositURN);\n debugData(`f856sUrn: ${JSON.stringify(f856sUrn)}`);\n\n const ldSubfields = isLegalDeposit ? createLDSubfields() : [];\n debugData(`IsLegalDeposit: ${isLegalDeposit}, LegalDepositSubfields: ${JSON.stringify(ldSubfields)}`);\n\n // We add the URN even if we're not getting the legalDeposit - where does this URN resolve?\n // We probably should not do these additions\n\n if (f856sUrn.length === 0) {\n const {code, value, generated} = await createURNSubfield(record);\n\n if (generated && useMelindaTemp) {\n const tempSubField = {code: '9', value: 'MELINDA<TEMP>'};\n\n record.insertField({\n tag: '856',\n ind1: '4',\n ind2: '0',\n subfields: [{code, value}, ...ldSubfields, tempSubField]\n });\n\n return true;\n }\n\n record.insertField({\n tag: '856',\n ind1: '4',\n ind2: '0',\n subfields: [{code, value}, ...ldSubfields]\n });\n\n return true;\n }\n\n if (isLegalDeposit) {\n\n // We add here legal deposit information to all URN-f856s - we probably should not do this\n // We should add extra f856 URN / URNs for legal deposits that already have a open (non-legal-deposit) URN\n // How do we decide which URN to use as a template if there are several URNs\n // We should check for existence of a legal deposit URN anyways\n\n f856sUrn.forEach(f => {\n // Change phrase from old to new if field with old phrase is found\n if (f.subfields.some(sf => hasOld856LdPhrase(sf))) {\n f.subfields\n .find(sf => hasOld856LdPhrase(sf))\n .value = 'K\u00E4ytett\u00E4viss\u00E4 vapaakappalety\u00F6asemilla';\n }\n\n // Create subfields if necessary\n ldSubfields.forEach(ldsf => {\n if (!f.subfields.some(sf => sf.code === ldsf.code && sf.value === ldsf.value && !hasOld856LdPhrase(sf))) {\n f.subfields.push(ldsf);\n }\n });\n });\n }\n\n return true;\n\n // We should check existence of URN in f024 i1: '7' $2 urn/URN for this too\n\n async function createURNSubfield(rec) {\n // isbn is picked from the last 020 $a in the record\n // what should we do in case of several 020 $a:s\n const isbn = rec.fields.reduce((acc, f) => {\n if (f.tag === '020') {\n const a = f.subfields.find(sf => sf.code === 'a');\n return a ? a.value : undefined;\n }\n\n return acc;\n }, undefined);\n\n debugData(`isbns: ${isbn}`);\n\n const {generated, value} = await createURN(isbn);\n return {code: 'u', value, generated};\n\n async function createURN(isbn = false) {\n if (isbn) {\n return {generated: false, value: `https://urn.fi/URN:ISBN:${isbn}`};\n }\n\n const response = await fetch(URN_GENERATOR_URL);\n const body = await response.text();\n\n // If we generated URN we could also add it to the 024\n // generated 024 should also have $9 MELINDA<TEMP>\n return {generated: true, value: `https://urn.fi/${body}`};\n }\n }\n\n function hasOld856LdPhrase({code, value}) {\n if (code === 'z' && value === 'K\u00E4ytett\u00E4viss\u00E4 vapaakappalekirjastoissa') {\n return true;\n }\n\n return false;\n }\n\n }\n\n // Later when the new subfields that have f506/f540 -type contents, we should add also them here\n function createLDSubfields() {\n return [\n {\n code: 'z',\n value: 'K\u00E4ytett\u00E4viss\u00E4 vapaakappalety\u00F6asemilla'\n },\n {\n code: '5',\n value: 'FI-Vapaa'\n }\n ];\n }\n\n function fieldHasLDSubfields(field, ldSubfields) {\n if (ldSubfields.every(ldsf => field.subfields.some(sf => sf.code === ldsf.code && sf.value === ldsf.value))) {\n return true;\n }\n }\n\n function validateLD(f856sUrn) {\n debug(`Validating the existence of legal deposit subfields`);\n const ldSubfields = createLDSubfields();\n const f856sUrnWithLdSubfields = f856sUrn.filter(field => fieldHasLDSubfields(field, ldSubfields));\n if (f856sUrnWithLdSubfields.length > 0) {\n debug(`Record has ${f856sUrnWithLdSubfields.length} URN fields with all necessary legal deposit subfields`);\n debugData(`f856sUrnWithLdSubfields: ${JSON.stringify(f856sUrnWithLdSubfields)}`);\n return true;\n }\n return false;\n }\n\n function validate(record) {\n // if not electronic skip this validator\n if (!isElectronicMaterial(record)) {\n debug(`Record is not electronic - no need to validate legal deposit URNs`);\n return {valid: true};\n }\n\n const f856sUrn = record.fields.filter(hasLegalDepositURN);\n\n if (f856sUrn.length > 0) {\n debug(`Record has ${f856sUrn.length} URN fields`);\n debugData(`f856sUrn: ${JSON.stringify(f856sUrn)}`);\n\n if (!isLegalDeposit || validateLD(f856sUrn)) {\n debug(`Record is valid`);\n return {valid: true};\n }\n }\n debug(`No (valid) URN fields - Record is not valid`);\n return {valid: false};\n }\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["//import fetch from 'node-fetch';\nimport {isElectronicMaterial, nvdebug} from './utils.js';\nimport createDebugLogger from 'debug';\n\nconst URN_GENERATOR_URL = 'https://generator.urn.fi/cgi-bin/urn_generator.cgi?type=nbn';\n\n// eslint-disable-next-line max-lines-per-function\nexport default function (isLegalDeposit = false, useMelindaTemp = true) {\n const debug = createDebugLogger('@natlibfi/marc-record-validators-melinda:urn');\n const debugData = debug.extend('data');\n const debugDev = debug.extend('dev');\n\n\n //nvdebug(`IS LEGAL DEPOSIT? ${isLegalDeposit ? 'YES' : 'NO'}`, debugDev); // eslint-disable-line no-console\n\n // We should check that the f856 with URN has second indicator '0' (Resource), ' ' (No information provided) or '8' (No display constant generated)\n // - if second indicator is '1' (Version of resource) or '2' (Related resource) the URN in f856 is not correct for the resource described in the record\n\n // This checks only the existence of URNs from the Finnish urn.fi -resolver\n\n function hasLegalDepositURN(field) {\n if (field.tag !== '856' || ['1', '2', '3', '4'].includes(field.ind2)) {\n return false;\n }\n\n // First attempt to fix MET-573. However, does useMelindaTemp come into play as well?\n if (isLegalDeposit && !field.subfields.some(sf => sf.code === '5' && sf.value === 'FI-Vapaa')) {\n return false;\n }\n\n return field.subfields.some(sf => sf.code === 'u' && (/^https?:\\/\\/urn\\.fi/u).test(sf.value));\n }\n\n\n return {\n description: 'Adds URN for record, to 856-field (if not existing). If isLegalDeposit is active, adds legal deposit subfields to the f856s with URN.',\n validate,\n fix\n };\n\n // eslint-disable-next-line max-lines-per-function\n async function fix(record) {\n const f856sUrn = record.fields.filter(hasLegalDepositURN);\n nvdebug(`f856sUrn: ${JSON.stringify(f856sUrn)}`, debugDev);\n\n const ldSubfields = isLegalDeposit ? createLDSubfields() : [];\n nvdebug(`IsLegalDeposit: ${isLegalDeposit}, LegalDepositSubfields: ${JSON.stringify(ldSubfields)}`, debugDev);\n\n // We add the URN even if we're not getting the legalDeposit - where does this URN resolve?\n // We probably should not do these additions\n\n if (f856sUrn.length === 0) {\n const {code, value, generated} = await createURNSubfield(record);\n\n if (generated && useMelindaTemp) {\n const tempSubField = {code: '9', value: 'MELINDA<TEMP>'};\n\n record.insertField({\n tag: '856',\n ind1: '4',\n ind2: '0',\n subfields: [{code, value}, ...ldSubfields, tempSubField]\n });\n\n return true;\n }\n\n record.insertField({\n tag: '856',\n ind1: '4',\n ind2: '0',\n subfields: [{code, value}, ...ldSubfields]\n });\n\n return true;\n }\n\n if (isLegalDeposit) {\n\n // We add here legal deposit information to all URN-f856s - we probably should not do this\n // We should add extra f856 URN / URNs for legal deposits that already have a open (non-legal-deposit) URN\n // How do we decide which URN to use as a template if there are several URNs\n // We should check for existence of a legal deposit URN anyways\n\n f856sUrn.forEach(f => {\n // Change phrase from old to new if field with old phrase is found\n if (f.subfields.some(sf => hasOld856LdPhrase(sf))) {\n f.subfields\n .find(sf => hasOld856LdPhrase(sf))\n .value = 'K\u00E4ytett\u00E4viss\u00E4 vapaakappalety\u00F6asemilla';\n }\n\n // Create subfields if necessary\n ldSubfields.forEach(ldsf => {\n if (!f.subfields.some(sf => sf.code === ldsf.code && sf.value === ldsf.value && !hasOld856LdPhrase(sf))) {\n f.subfields.push(ldsf);\n }\n });\n });\n }\n\n return true;\n\n // We should check existence of URN in f024 i1: '7' $2 urn/URN for this too\n\n async function createURNSubfield(rec) {\n // isbn is picked from the last 020 $a in the record\n // what should we do in case of several 020 $a:s\n const isbn = rec.fields.reduce((acc, f) => {\n if (f.tag === '020') {\n const a = f.subfields.find(sf => sf.code === 'a');\n return a ? a.value : undefined;\n }\n\n return acc;\n }, undefined);\n\n nvdebug(`isbns: ${isbn}`, debugDev);\n\n const {generated, value} = await createURN(isbn);\n return {code: 'u', value, generated};\n\n async function createURN(isbn = false) {\n if (isbn) {\n return {generated: false, value: `https://urn.fi/URN:ISBN:${isbn}`};\n }\n\n const response = await fetch(URN_GENERATOR_URL);\n const body = await response.text();\n\n // If we generated URN we could also add it to the 024\n // generated 024 should also have $9 MELINDA<TEMP>\n return {generated: true, value: `https://urn.fi/${body}`};\n }\n }\n\n function hasOld856LdPhrase({code, value}) {\n if (code === 'z' && value === 'K\u00E4ytett\u00E4viss\u00E4 vapaakappalekirjastoissa') {\n return true;\n }\n\n return false;\n }\n\n }\n\n // Later when the new subfields that have f506/f540 -type contents, we should add also them here\n function createLDSubfields() {\n return [\n {\n code: 'z',\n value: 'K\u00E4ytett\u00E4viss\u00E4 vapaakappalety\u00F6asemilla'\n },\n {\n code: '5',\n value: 'FI-Vapaa'\n }\n ];\n }\n\n function fieldHasLDSubfields(field, ldSubfields) {\n if (ldSubfields.every(ldsf => field.subfields.some(sf => sf.code === ldsf.code && sf.value === ldsf.value))) {\n return true;\n }\n }\n\n function validateLD(f856sUrn) {\n nvdebug(`Validating the existence of legal deposit subfields`, debugDev);\n const ldSubfields = createLDSubfields();\n const f856sUrnWithLdSubfields = f856sUrn.filter(field => fieldHasLDSubfields(field, ldSubfields));\n if (f856sUrnWithLdSubfields.length > 0) {\n nvdebug(`Record has ${f856sUrnWithLdSubfields.length} URN fields with all necessary legal deposit subfields`, debugDev);\n nvdebug(`f856sUrnWithLdSubfields: ${JSON.stringify(f856sUrnWithLdSubfields)}`, debugData);\n return true;\n }\n return false;\n }\n\n function validate(record) {\n // if not electronic skip this validator\n if (!isElectronicMaterial(record)) {\n nvdebug(`Record is not electronic - no need to validate legal deposit URNs`, debugDev);\n return {valid: true};\n }\n\n const f856sUrn = record.fields.filter(hasLegalDepositURN);\n\n if (f856sUrn.length > 0) {\n nvdebug(`Record has ${f856sUrn.length} URN fields`, debugDev);\n nvdebug(`f856sUrn: ${JSON.stringify(f856sUrn)}`, debugData);\n\n if (!isLegalDeposit || validateLD(f856sUrn)) {\n nvdebug(`Record is valid`, debugDev);\n return {valid: true};\n }\n }\n nvdebug(`No (valid) URN fields - Record is not valid`, debugDev);\n return {valid: false};\n }\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["isbn"]
7
7
  }
package/dist/urn.test.js CHANGED
@@ -3,7 +3,6 @@ import { MarcRecord } from "@natlibfi/marc-record";
3
3
  import validatorFactory from "./urn.js";
4
4
  import { READERS } from "@natlibfi/fixura";
5
5
  import generateTests from "@natlibfi/fixugen";
6
- import createDebugLogger from "debug";
7
6
  generateTests({
8
7
  callback,
9
8
  path: [import.meta.dirname, "..", "test-fixtures", "urn"],
@@ -18,18 +17,13 @@ generateTests({
18
17
  }
19
18
  }
20
19
  });
21
- const debug = createDebugLogger("@natlibfi/marc-record-validators-melinda/urn:test");
22
20
  async function testValidatorFactory() {
23
21
  const validator = await validatorFactory();
24
22
  assert.equal(typeof validator, "object");
25
23
  assert.equal(typeof validator.description, "string");
26
24
  assert.equal(typeof validator.validate, "function");
27
25
  }
28
- async function callback({ getFixture, enabled = true, fix = true, isLegalDeposit = false }) {
29
- if (enabled === false) {
30
- debug("TEST SKIPPED!");
31
- return;
32
- }
26
+ async function callback({ getFixture, fix = true, isLegalDeposit = false }) {
33
27
  const validator = await validatorFactory(isLegalDeposit);
34
28
  const record = new MarcRecord(getFixture("input.json"));
35
29
  const expectedResult = getFixture("result.json");
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/urn.test.js"],
4
- "sourcesContent": ["import assert from 'node:assert';\nimport {MarcRecord} from '@natlibfi/marc-record';\nimport validatorFactory from './urn.js';\nimport {READERS} from '@natlibfi/fixura';\nimport generateTests from '@natlibfi/fixugen';\nimport createDebugLogger from 'debug';\n\ngenerateTests({\n callback,\n path: [import.meta.dirname, '..', 'test-fixtures', 'urn'],\n useMetadataFile: true,\n recurse: false,\n fixura: {\n reader: READERS.JSON\n },\n hooks: {\n before: async () => {\n testValidatorFactory();\n }\n }\n});\nconst debug = createDebugLogger('@natlibfi/marc-record-validators-melinda/urn:test');\n\nasync function testValidatorFactory() {\n const validator = await validatorFactory();\n\n assert.equal(typeof validator, 'object');\n assert.equal(typeof validator.description, 'string');\n assert.equal(typeof validator.validate, 'function');\n}\n\nasync function callback({getFixture, enabled = true, fix = true, isLegalDeposit = false}) {\n if (enabled === false) {\n debug('TEST SKIPPED!');\n return;\n }\n\n const validator = await validatorFactory(isLegalDeposit);\n const record = new MarcRecord(getFixture('input.json'));\n const expectedResult = getFixture('result.json');\n // console.log(expectedResult); // eslint-disable-line\n\n if (!fix) {\n const result = await validator.validate(record);\n assert.deepEqual(result, expectedResult);\n return;\n }\n\n await validator.fix(record);\n assert.deepEqual(record, expectedResult);\n}\n"],
5
- "mappings": "AAAA,OAAO,YAAY;AACnB,SAAQ,kBAAiB;AACzB,OAAO,sBAAsB;AAC7B,SAAQ,eAAc;AACtB,OAAO,mBAAmB;AAC1B,OAAO,uBAAuB;AAE9B,cAAc;AAAA,EACZ;AAAA,EACA,MAAM,CAAC,YAAY,SAAS,MAAM,iBAAiB,KAAK;AAAA,EACxD,iBAAiB;AAAA,EACjB,SAAS;AAAA,EACT,QAAQ;AAAA,IACN,QAAQ,QAAQ;AAAA,EAClB;AAAA,EACA,OAAO;AAAA,IACL,QAAQ,YAAY;AAClB,2BAAqB;AAAA,IACvB;AAAA,EACF;AACF,CAAC;AACD,MAAM,QAAQ,kBAAkB,mDAAmD;AAEnF,eAAe,uBAAuB;AACpC,QAAM,YAAY,MAAM,iBAAiB;AAEzC,SAAO,MAAM,OAAO,WAAW,QAAQ;AACvC,SAAO,MAAM,OAAO,UAAU,aAAa,QAAQ;AACnD,SAAO,MAAM,OAAO,UAAU,UAAU,UAAU;AACpD;AAEA,eAAe,SAAS,EAAC,YAAY,UAAU,MAAM,MAAM,MAAM,iBAAiB,MAAK,GAAG;AACxF,MAAI,YAAY,OAAO;AACrB,UAAM,eAAe;AACrB;AAAA,EACF;AAEA,QAAM,YAAY,MAAM,iBAAiB,cAAc;AACvD,QAAM,SAAS,IAAI,WAAW,WAAW,YAAY,CAAC;AACtD,QAAM,iBAAiB,WAAW,aAAa;AAG/C,MAAI,CAAC,KAAK;AACR,UAAM,SAAS,MAAM,UAAU,SAAS,MAAM;AAC9C,WAAO,UAAU,QAAQ,cAAc;AACvC;AAAA,EACF;AAEA,QAAM,UAAU,IAAI,MAAM;AAC1B,SAAO,UAAU,QAAQ,cAAc;AACzC;",
4
+ "sourcesContent": ["import assert from 'node:assert';\nimport {MarcRecord} from '@natlibfi/marc-record';\nimport validatorFactory from './urn.js';\nimport {READERS} from '@natlibfi/fixura';\nimport generateTests from '@natlibfi/fixugen';\n//import createDebugLogger from 'debug';\n\ngenerateTests({\n callback,\n path: [import.meta.dirname, '..', 'test-fixtures', 'urn'],\n useMetadataFile: true,\n recurse: false,\n fixura: {\n reader: READERS.JSON\n },\n hooks: {\n before: async () => {\n testValidatorFactory();\n }\n }\n});\n//const debug = createDebugLogger('@natlibfi/marc-record-validators-melinda/urn:test');\n\nasync function testValidatorFactory() {\n const validator = await validatorFactory();\n\n assert.equal(typeof validator, 'object');\n assert.equal(typeof validator.description, 'string');\n assert.equal(typeof validator.validate, 'function');\n}\n\nasync function callback({getFixture, fix = true, isLegalDeposit = false}) {\n const validator = await validatorFactory(isLegalDeposit);\n const record = new MarcRecord(getFixture('input.json'));\n const expectedResult = getFixture('result.json');\n // console.log(expectedResult); // eslint-disable-line\n\n if (!fix) {\n const result = await validator.validate(record);\n assert.deepEqual(result, expectedResult);\n return;\n }\n\n await validator.fix(record);\n assert.deepEqual(record, expectedResult);\n}\n"],
5
+ "mappings": "AAAA,OAAO,YAAY;AACnB,SAAQ,kBAAiB;AACzB,OAAO,sBAAsB;AAC7B,SAAQ,eAAc;AACtB,OAAO,mBAAmB;AAG1B,cAAc;AAAA,EACZ;AAAA,EACA,MAAM,CAAC,YAAY,SAAS,MAAM,iBAAiB,KAAK;AAAA,EACxD,iBAAiB;AAAA,EACjB,SAAS;AAAA,EACT,QAAQ;AAAA,IACN,QAAQ,QAAQ;AAAA,EAClB;AAAA,EACA,OAAO;AAAA,IACL,QAAQ,YAAY;AAClB,2BAAqB;AAAA,IACvB;AAAA,EACF;AACF,CAAC;AAGD,eAAe,uBAAuB;AACpC,QAAM,YAAY,MAAM,iBAAiB;AAEzC,SAAO,MAAM,OAAO,WAAW,QAAQ;AACvC,SAAO,MAAM,OAAO,UAAU,aAAa,QAAQ;AACnD,SAAO,MAAM,OAAO,UAAU,UAAU,UAAU;AACpD;AAEA,eAAe,SAAS,EAAC,YAAY,MAAM,MAAM,iBAAiB,MAAK,GAAG;AACxE,QAAM,YAAY,MAAM,iBAAiB,cAAc;AACvD,QAAM,SAAS,IAAI,WAAW,WAAW,YAAY,CAAC;AACtD,QAAM,iBAAiB,WAAW,aAAa;AAG/C,MAAI,CAAC,KAAK;AACR,UAAM,SAAS,MAAM,UAAU,SAAS,MAAM;AAC9C,WAAO,UAAU,QAAQ,cAAc;AACvC;AAAA,EACF;AAEA,QAAM,UAAU,IAAI,MAAM;AAC1B,SAAO,UAAU,QAAQ,cAAc;AACzC;",
6
6
  "names": []
7
7
  }
package/dist/utils.js CHANGED
@@ -1,7 +1,8 @@
1
1
  import createDebugLogger from "debug";
2
+ import { melindaFieldSpecs } from "./melindaCustomMergeFields.js";
3
+ import { isDataProvenanceSubfieldCode } from "./dataProvenanceUtils.js";
2
4
  const debug = createDebugLogger("@natlibfi/melinda-marc-record-merge-reducers:utils");
3
5
  const debugDev = debug.extend("dev");
4
- import { melindaFieldSpecs } from "./melindaCustomMergeFields.js";
5
6
  export function isElectronicMaterial(record) {
6
7
  const f337s = record.get("337");
7
8
  return f337s.length > 0 && f337s.some((f) => fieldHasSubfield(f, "b", "c") && fieldHasSubfield(f, "2", "rdamedia"));
@@ -77,12 +78,29 @@ export function fieldsToString(fields) {
77
78
  export function nvdebugFieldArray(fields, prefix = " ", func = void 0) {
78
79
  fields.forEach((field) => nvdebug(`${prefix}${fieldToString(field)}`, func));
79
80
  }
80
- export function isControlSubfieldCode(subfieldCode) {
81
- if (["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "w"].includes(subfieldCode)) {
81
+ function isControlSubfieldCode(subfieldCode, tag = void 0) {
82
+ if (["0", "1", "2", "5", "6", "8", "w"].includes(subfieldCode)) {
82
83
  return true;
83
84
  }
85
+ if (tag && subfieldCode === "7") {
86
+ if (tag.match(/^7[678]/u) || ["800", "810", "811", "830"].includes(tag)) {
87
+ return true;
88
+ }
89
+ }
84
90
  return false;
85
91
  }
92
+ export function isContentSubfieldCode(subfieldCode, tag = void 0) {
93
+ if (isControlSubfieldCode(subfieldCode, tag)) {
94
+ return false;
95
+ }
96
+ if (tag && isDataProvenanceSubfieldCode(subfieldCode, tag)) {
97
+ return false;
98
+ }
99
+ if (["2", "3", "4", "7", "9"].includes(subfieldCode)) {
100
+ return false;
101
+ }
102
+ return true;
103
+ }
86
104
  export function getCatalogingLanguage(record, defaultCatalogingLanguage = void 0) {
87
105
  const [field040] = record.get(/^040$/u);
88
106
  if (!field040) {
@@ -177,4 +195,12 @@ export function subfieldArraysContainSameData(arr1, arr2) {
177
195
  }
178
196
  return arr2.every((sf2) => arr1.some((sf) => subfieldsAreIdentical(sf, sf2)));
179
197
  }
198
+ export function tagIsRepeatable(tag) {
199
+ const fieldSpecs = melindaFieldSpecs.fields.filter((field) => field.tag === tag);
200
+ if (fieldSpecs.length !== 1) {
201
+ debugDev(` WARNING! Getting field ${tag} data failed! Default to repeatable field.`);
202
+ return true;
203
+ }
204
+ return fieldSpecs[0].repeatable;
205
+ }
180
206
  //# sourceMappingURL=utils.js.map
package/dist/utils.js.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/utils.js"],
4
- "sourcesContent": ["import createDebugLogger from 'debug';\n\n//import fs from 'fs';\n//import path from 'path';\n\nconst debug = createDebugLogger('@natlibfi/melinda-marc-record-merge-reducers:utils');\n//const debugData = debug.extend('data');\nconst debugDev = debug.extend('dev');\n\nimport {melindaFieldSpecs} from './melindaCustomMergeFields.js';\n\n//JSON.parse(fs.readFileSync(path.join(__dirname, '..', 'src', 'melindaCustomMergeFields.json'), 'utf8'));\n\nexport function isElectronicMaterial(record) {\n const f337s = record.get('337');\n\n return f337s.length > 0 && f337s.some(f => fieldHasSubfield(f, 'b', 'c') && fieldHasSubfield(f, '2', 'rdamedia'));\n}\n\nexport function nvdebug(message, func = undefined) {\n if (func) {\n func(message);\n }\n //console.info(message); // eslint-disable-line no-console\n}\n\nexport function fieldHasSubfield(field, subfieldCode, subfieldValue = null) {\n if (!field.subfields) {\n return false;\n }\n if (subfieldValue === null) {\n return field.subfields.some(sf => sf.code === subfieldCode);\n }\n return field.subfields.some(sf => sf.code === subfieldCode && subfieldValue === sf.value);\n}\n\nexport function subfieldToString(sf) {\n if (!sf.value) {\n return `\u2021${sf.code}`;\n }\n return `\u2021${sf.code} ${sf.value}`;\n}\n\nfunction normalizeIndicatorValue(val) {\n if (val === ' ') {\n return '#';\n }\n return val;\n}\n\nexport function recordToString(record) {\n const ldr = `LDR ${record.leader}`;\n const fields = record.fields.map(f => fieldToString(f));\n return `${ldr}\\n${fields.join('\\n')}`;\n}\n\nexport function removeSubfield(record, tag, subfieldCode) {\n record.fields = record.fields.map(field => {\n if (field.tag !== tag || !field.subfields) { // Don't procss irrelevant fields\n return field;\n }\n field.subfields = field.subfields.filter(sf => sf.code !== subfieldCode);\n if (field.subfields.length === 0) {\n return false;\n }\n return field;\n }).filter(field => field);\n}\n\nexport function recordRemoveValuelessSubfields(record) {\n record.fields = record.fields.map(field => {\n if (!field.subfields) { // Keep control fields\n return field;\n }\n // Remove empty subfields from datafields:\n field.subfields = field.subfields.filter(sf => sf.value);\n\n if (field.subfields && field.subfields.length === 0) {\n return false; // Return false instead of a field if field has no subfields left. These will soon be filtered out.\n }\n\n return field; //if field has subfields return it\n }).filter(field => field); // Filter those falses out\n}\n\nexport function fieldToString(f) {\n if ('subfields' in f) {\n return `${f.tag} ${normalizeIndicatorValue(f.ind1)}${normalizeIndicatorValue(f.ind2)}${formatSubfields(f)}`;\n }\n return `${f.tag} ${f.value}`;\n\n function formatSubfields(field) {\n return field.subfields.map(sf => ` ${subfieldToString(sf)}`).join('');\n }\n}\n\nexport function fieldsToString(fields) {\n return fields.map(f => fieldToString(f)).join('\\t__SEPARATOR__\\t');\n}\n\nexport function nvdebugFieldArray(fields, prefix = ' ', func = undefined) {\n fields.forEach(field => nvdebug(`${prefix}${fieldToString(field)}`, func));\n}\n\nexport function isControlSubfieldCode(subfieldCode) {\n // NB! Only $w, $0, $1, $5, $6 and $8 are really control subfields. In Finland $9 is oft a control subfield\n // $3 material (part of the whole thing)\n // $4 means 'relationship' (similar to relator terms at least in X00 and similar)\n // $7 is usually provinance subfield. However, it can be stored in other subfields as well. See merge-fields/dataProvenance.js for details\n // However, change this only if needed. Maybe all provinance subfields should return true?\n // This may become relevant when AI starts to create stuff...\n if (['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'w'].includes(subfieldCode)) {\n return true;\n }\n return false;\n}\n\nexport function getCatalogingLanguage(record, defaultCatalogingLanguage = undefined) {\n const [field040] = record.get(/^040$/u);\n if (!field040) {\n return defaultCatalogingLanguage;\n }\n const [b] = field040.subfields.filter(sf => sf.code === 'b');\n if (!b) {\n return defaultCatalogingLanguage;\n }\n return b.value;\n}\n\n\nexport function uniqArray(arr) {\n return arr.filter((val, i) => arr.indexOf(val) === i);\n}\n\nexport function fieldsAreIdentical(field1, field2) {\n if (field1.tag !== field2.tag) { // NB! We are skipping normalizations here on purpose! They should be done beforehand...\n return false;\n }\n return fieldToString(field1) === fieldToString(field2);\n\n // The order of subfields is relevant! Bloody JS idiotisms make people use conditions such as:\n // return field1.subfields.every(sf => field2.subfields.some(sf2 => sf.code === sf2.code && sf.value === sf2.value));\n}\n\nexport function fieldHasNSubfields(field, subfieldCode/*, subfieldValue = null*/) {\n const relevantSubfields = field.subfields.filter(sf => sf.code === subfieldCode);\n //if (subfieldValue === null) {\n return relevantSubfields.length;\n //}\n //const subset = relevantSubfields.filter(value => value === subfieldValue);\n //return subset.length;\n}\n\nexport function removeCopyright(value) {\n return value.replace(/^(?:c|p|\u00A9|\u2117|Cop\\. ?) ?((?:1[0-9][0-9][0-9]|20[012][0-9])\\.?)$/ui, '$1');\n}\n\nfunction isNonStandardNonrepeatableSubfield(tag, subfieldCode) {\n // Put these into config or so...\n if (tag === '264') {\n return ['a', 'b', 'c'].includes(subfieldCode);\n }\n\n if (['336', '337', '338'].includes(tag)) {\n return ['a', 'b', '2'].includes(subfieldCode);\n }\n\n return false;\n}\n\n\nexport function subfieldIsRepeatable(tag, subfieldCode) {\n\n if (isNonStandardNonrepeatableSubfield(tag, subfieldCode)) {\n return false;\n }\n\n // These we know or \"know\":\n // NB! $5 is (according to MARC21 format) non-repeatable, and not usable in all fields, but Melinda has a local exception to this, see MET-300\n if ('0159'.indexOf(subfieldCode) > -1) {\n // Uh, can $0 appear on any field?\n return true;\n }\n\n const fieldSpecs = melindaFieldSpecs.fields.filter(field => field.tag === tag);\n if (fieldSpecs.length !== 1) {\n nvdebug(` WARNING! Getting field ${tag} data failed! ${fieldSpecs.length} hits. Default value true is used for'${subfieldCode}' .`, debugDev);\n return true;\n }\n\n const subfieldSpecs = fieldSpecs[0].subfields.filter(subfield => subfield.code === subfieldCode);\n // Currently we don't support multiple $6 fields due to re-indexing limitations...\n // Well, $6 is non-repeatable, isn't it?!?\n // (This might actually already be fixed... Marginal issue, but check eventually.)\n if (subfieldSpecs.length !== 1 || subfieldCode === '6') {\n return false; // repeatable if not specified, I guess. Maybe add log or warn?\n }\n return subfieldSpecs[0].repeatable;\n}\n\nfunction marc21GetTagsLegalIndicators(tag) {\n const fieldSpecs = melindaFieldSpecs.fields.filter(field => field.tag === tag);\n if (fieldSpecs.length === 0) {\n return undefined;\n }\n return fieldSpecs[0].indicators;\n}\n\nexport function marc21GetTagsLegalInd1Value(tag) {\n const indicator = marc21GetTagsLegalIndicators(tag);\n if (indicator === undefined) {\n return undefined;\n }\n return indicator.ind1;\n}\n\nexport function marc21GetTagsLegalInd2Value(tag) {\n const indicator = marc21GetTagsLegalIndicators(tag);\n if (indicator === undefined) {\n return undefined;\n }\n return indicator.ind2;\n}\n\nexport function nvdebugSubfieldArray(subfields, prefix = ' ', func = undefined) {\n subfields.forEach(subfield => nvdebug(`${prefix}${subfieldToString(subfield)}`, func));\n}\n\nexport function subfieldsAreIdentical(subfieldA, subfieldB) {\n return subfieldA.code === subfieldB.code && subfieldA.value === subfieldB.value;\n}\n\nexport function fieldHasMultipleSubfields(field, subfieldCode/*, subfieldValue = null*/) {\n return fieldHasNSubfields(field, subfieldCode) > 1;\n}\n\nexport function hasCopyright(value) {\n const modValue = removeCopyright(value);\n return value !== modValue;\n}\n\n\n\nexport function subfieldArraysContainSameData(arr1, arr2) {\n if ( !arr1.every(sf => arr2.some(sf2 => subfieldsAreIdentical(sf, sf2))) ) {\n return false;\n }\n\n return arr2.every(sf2 => arr1.some(sf => subfieldsAreIdentical(sf, sf2)));\n}"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import createDebugLogger from 'debug';\nimport {melindaFieldSpecs} from './melindaCustomMergeFields.js';\nimport {isDataProvenanceSubfieldCode} from './dataProvenanceUtils.js';\n\nconst debug = createDebugLogger('@natlibfi/melinda-marc-record-merge-reducers:utils');\n//const debugData = debug.extend('data');\nconst debugDev = debug.extend('dev');\n\n\n\n//JSON.parse(fs.readFileSync(path.join(__dirname, '..', 'src', 'melindaCustomMergeFields.json'), 'utf8'));\n\nexport function isElectronicMaterial(record) {\n const f337s = record.get('337');\n\n return f337s.length > 0 && f337s.some(f => fieldHasSubfield(f, 'b', 'c') && fieldHasSubfield(f, '2', 'rdamedia'));\n}\n\nexport function nvdebug(message, func = undefined) {\n if (func) {\n func(message);\n }\n //console.info(message); // eslint-disable-line no-console\n}\n\nexport function fieldHasSubfield(field, subfieldCode, subfieldValue = null) {\n if (!field.subfields) {\n return false;\n }\n if (subfieldValue === null) {\n return field.subfields.some(sf => sf.code === subfieldCode);\n }\n return field.subfields.some(sf => sf.code === subfieldCode && subfieldValue === sf.value);\n}\n\nexport function subfieldToString(sf) {\n if (!sf.value) {\n return `\u2021${sf.code}`;\n }\n return `\u2021${sf.code} ${sf.value}`;\n}\n\nfunction normalizeIndicatorValue(val) {\n if (val === ' ') {\n return '#';\n }\n return val;\n}\n\nexport function recordToString(record) {\n const ldr = `LDR ${record.leader}`;\n const fields = record.fields.map(f => fieldToString(f));\n return `${ldr}\\n${fields.join('\\n')}`;\n}\n\nexport function removeSubfield(record, tag, subfieldCode) {\n record.fields = record.fields.map(field => {\n if (field.tag !== tag || !field.subfields) { // Don't procss irrelevant fields\n return field;\n }\n field.subfields = field.subfields.filter(sf => sf.code !== subfieldCode);\n if (field.subfields.length === 0) {\n return false;\n }\n return field;\n }).filter(field => field);\n}\n\nexport function recordRemoveValuelessSubfields(record) {\n record.fields = record.fields.map(field => {\n if (!field.subfields) { // Keep control fields\n return field;\n }\n // Remove empty subfields from datafields:\n field.subfields = field.subfields.filter(sf => sf.value);\n\n if (field.subfields && field.subfields.length === 0) {\n return false; // Return false instead of a field if field has no subfields left. These will soon be filtered out.\n }\n\n return field; //if field has subfields return it\n }).filter(field => field); // Filter those falses out\n}\n\nexport function fieldToString(f) {\n if ('subfields' in f) {\n return `${f.tag} ${normalizeIndicatorValue(f.ind1)}${normalizeIndicatorValue(f.ind2)}${formatSubfields(f)}`;\n }\n return `${f.tag} ${f.value}`;\n\n function formatSubfields(field) {\n return field.subfields.map(sf => ` ${subfieldToString(sf)}`).join('');\n }\n}\n\nexport function fieldsToString(fields) {\n return fields.map(f => fieldToString(f)).join('\\t__SEPARATOR__\\t');\n}\n\nexport function nvdebugFieldArray(fields, prefix = ' ', func = undefined) {\n fields.forEach(field => nvdebug(`${prefix}${fieldToString(field)}`, func));\n}\n\nfunction isControlSubfieldCode(subfieldCode, tag = undefined) {\n // NB! Only $w, $0, $1, $5, $6 and $8 are really control subfields. In Finland $9 is oft a control subfield\n if (['0', '1', '2', '5', '6', '8', 'w'].includes(subfieldCode)) {\n return true;\n }\n // Subfield '7' is control subfield for some tags:\n if (tag && subfieldCode === '7') {\n if ( tag.match(/^7[678]/u) || ['800', '810', '811', '830'].includes(tag) ) {\n return true;\n }\n }\n return false;\n}\n\nexport function isContentSubfieldCode(subfieldCode, tag = undefined) {\n if (isControlSubfieldCode(subfieldCode, tag)) { // 'w', '0', '1', '5', '6' and '8'. (Also '7' for ....)\n return false;\n }\n if (tag && isDataProvenanceSubfieldCode(subfieldCode, tag)) { // Note that default '7' is handled below\n return false;\n }\n // $7 contains typically data provenance, sometimes it's a control field, and for f533, f856 ja f857 it's something else, but it's never content!\n if (['2', '3', '4', '7', '9'].includes(subfieldCode)) {\n return false;\n }\n\n\n return true;\n}\n\n\n\nexport function getCatalogingLanguage(record, defaultCatalogingLanguage = undefined) {\n const [field040] = record.get(/^040$/u);\n if (!field040) {\n return defaultCatalogingLanguage;\n }\n const [b] = field040.subfields.filter(sf => sf.code === 'b');\n if (!b) {\n return defaultCatalogingLanguage;\n }\n return b.value;\n}\n\n\nexport function uniqArray(arr) {\n return arr.filter((val, i) => arr.indexOf(val) === i);\n}\n\nexport function fieldsAreIdentical(field1, field2) {\n if (field1.tag !== field2.tag) { // NB! We are skipping normalizations here on purpose! They should be done beforehand...\n return false;\n }\n return fieldToString(field1) === fieldToString(field2);\n\n // The order of subfields is relevant! Bloody JS idiotisms make people use conditions such as:\n // return field1.subfields.every(sf => field2.subfields.some(sf2 => sf.code === sf2.code && sf.value === sf2.value));\n}\n\nexport function fieldHasNSubfields(field, subfieldCode/*, subfieldValue = null*/) {\n const relevantSubfields = field.subfields.filter(sf => sf.code === subfieldCode);\n //if (subfieldValue === null) {\n return relevantSubfields.length;\n //}\n //const subset = relevantSubfields.filter(value => value === subfieldValue);\n //return subset.length;\n}\n\nexport function removeCopyright(value) {\n return value.replace(/^(?:c|p|\u00A9|\u2117|Cop\\. ?) ?((?:1[0-9][0-9][0-9]|20[012][0-9])\\.?)$/ui, '$1');\n}\n\nfunction isNonStandardNonrepeatableSubfield(tag, subfieldCode) {\n // Put these into config or so...\n if (tag === '264') {\n return ['a', 'b', 'c'].includes(subfieldCode);\n }\n\n if (['336', '337', '338'].includes(tag)) {\n return ['a', 'b', '2'].includes(subfieldCode);\n }\n\n return false;\n}\n\n\nexport function subfieldIsRepeatable(tag, subfieldCode) {\n\n if (isNonStandardNonrepeatableSubfield(tag, subfieldCode)) {\n return false;\n }\n\n // These we know or \"know\":\n // NB! $5 is (according to MARC21 format) non-repeatable, and not usable in all fields, but Melinda has a local exception to this, see MET-300\n if ('0159'.indexOf(subfieldCode) > -1) {\n // Uh, can $0 appear on any field?\n return true;\n }\n\n const fieldSpecs = melindaFieldSpecs.fields.filter(field => field.tag === tag);\n if (fieldSpecs.length !== 1) {\n nvdebug(` WARNING! Getting field ${tag} data failed! ${fieldSpecs.length} hits. Default value true is used for'${subfieldCode}' .`, debugDev);\n return true;\n }\n\n const subfieldSpecs = fieldSpecs[0].subfields.filter(subfield => subfield.code === subfieldCode);\n // Currently we don't support multiple $6 fields due to re-indexing limitations...\n // Well, $6 is non-repeatable, isn't it?!?\n // (This might actually already be fixed... Marginal issue, but check eventually.)\n if (subfieldSpecs.length !== 1 || subfieldCode === '6') {\n return false; // repeatable if not specified, I guess. Maybe add log or warn?\n }\n return subfieldSpecs[0].repeatable;\n}\n\nfunction marc21GetTagsLegalIndicators(tag) {\n const fieldSpecs = melindaFieldSpecs.fields.filter(field => field.tag === tag);\n if (fieldSpecs.length === 0) {\n return undefined;\n }\n return fieldSpecs[0].indicators;\n}\n\nexport function marc21GetTagsLegalInd1Value(tag) {\n const indicator = marc21GetTagsLegalIndicators(tag);\n if (indicator === undefined) {\n return undefined;\n }\n return indicator.ind1;\n}\n\nexport function marc21GetTagsLegalInd2Value(tag) {\n const indicator = marc21GetTagsLegalIndicators(tag);\n if (indicator === undefined) {\n return undefined;\n }\n return indicator.ind2;\n}\n\nexport function nvdebugSubfieldArray(subfields, prefix = ' ', func = undefined) {\n subfields.forEach(subfield => nvdebug(`${prefix}${subfieldToString(subfield)}`, func));\n}\n\nexport function subfieldsAreIdentical(subfieldA, subfieldB) {\n return subfieldA.code === subfieldB.code && subfieldA.value === subfieldB.value;\n}\n\nexport function fieldHasMultipleSubfields(field, subfieldCode/*, subfieldValue = null*/) {\n return fieldHasNSubfields(field, subfieldCode) > 1;\n}\n\nexport function hasCopyright(value) {\n const modValue = removeCopyright(value);\n return value !== modValue;\n}\n\n\n\nexport function subfieldArraysContainSameData(arr1, arr2) {\n if ( !arr1.every(sf => arr2.some(sf2 => subfieldsAreIdentical(sf, sf2))) ) {\n return false;\n }\n\n return arr2.every(sf2 => arr1.some(sf => subfieldsAreIdentical(sf, sf2)));\n}\n\nexport function tagIsRepeatable(tag) {\n const fieldSpecs = melindaFieldSpecs.fields.filter(field => field.tag === tag);\n if (fieldSpecs.length !== 1) {\n debugDev(` WARNING! Getting field ${tag} data failed! Default to repeatable field.`);\n return true;\n }\n return fieldSpecs[0].repeatable;\n}\n"],
5
+ "mappings": "AAAA,OAAO,uBAAuB;AAC9B,SAAQ,yBAAwB;AAChC,SAAQ,oCAAmC;AAE3C,MAAM,QAAQ,kBAAkB,oDAAoD;AAEpF,MAAM,WAAW,MAAM,OAAO,KAAK;AAM5B,gBAAS,qBAAqB,QAAQ;AAC3C,QAAM,QAAQ,OAAO,IAAI,KAAK;AAE9B,SAAO,MAAM,SAAS,KAAK,MAAM,KAAK,OAAK,iBAAiB,GAAG,KAAK,GAAG,KAAK,iBAAiB,GAAG,KAAK,UAAU,CAAC;AAClH;AAEO,gBAAS,QAAQ,SAAS,OAAO,QAAW;AACjD,MAAI,MAAM;AACR,SAAK,OAAO;AAAA,EACd;AAEF;AAEO,gBAAS,iBAAiB,OAAO,cAAc,gBAAgB,MAAM;AAC1E,MAAI,CAAC,MAAM,WAAW;AACpB,WAAO;AAAA,EACT;AACA,MAAI,kBAAkB,MAAM;AAC1B,WAAO,MAAM,UAAU,KAAK,QAAM,GAAG,SAAS,YAAY;AAAA,EAC5D;AACA,SAAO,MAAM,UAAU,KAAK,QAAM,GAAG,SAAS,gBAAgB,kBAAkB,GAAG,KAAK;AAC1F;AAEO,gBAAS,iBAAiB,IAAI;AACnC,MAAI,CAAC,GAAG,OAAO;AACb,WAAO,SAAI,GAAG,IAAI;AAAA,EACpB;AACA,SAAO,SAAI,GAAG,IAAI,IAAI,GAAG,KAAK;AAChC;AAEA,SAAS,wBAAwB,KAAK;AACpC,MAAI,QAAQ,KAAK;AACf,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAEO,gBAAS,eAAe,QAAQ;AACrC,QAAM,MAAM,SAAS,OAAO,MAAM;AAClC,QAAM,SAAS,OAAO,OAAO,IAAI,OAAK,cAAc,CAAC,CAAC;AACtD,SAAO,GAAG,GAAG;AAAA,EAAK,OAAO,KAAK,IAAI,CAAC;AACrC;AAEO,gBAAS,eAAe,QAAQ,KAAK,cAAc;AACxD,SAAO,SAAS,OAAO,OAAO,IAAI,WAAS;AACzC,QAAI,MAAM,QAAQ,OAAO,CAAC,MAAM,WAAW;AACzC,aAAO;AAAA,IACT;AACA,UAAM,YAAY,MAAM,UAAU,OAAO,QAAM,GAAG,SAAS,YAAY;AACvE,QAAI,MAAM,UAAU,WAAW,GAAG;AAChC,aAAO;AAAA,IACT;AACA,WAAO;AAAA,EACT,CAAC,EAAE,OAAO,WAAS,KAAK;AAC1B;AAEO,gBAAS,+BAA+B,QAAQ;AACrD,SAAO,SAAS,OAAO,OAAO,IAAI,WAAS;AACzC,QAAI,CAAC,MAAM,WAAW;AACpB,aAAO;AAAA,IACT;AAEA,UAAM,YAAY,MAAM,UAAU,OAAO,QAAM,GAAG,KAAK;AAEvD,QAAI,MAAM,aAAa,MAAM,UAAU,WAAW,GAAG;AACnD,aAAO;AAAA,IACT;AAEA,WAAO;AAAA,EACT,CAAC,EAAE,OAAO,WAAS,KAAK;AAC1B;AAEO,gBAAS,cAAc,GAAG;AAC/B,MAAI,eAAe,GAAG;AACpB,WAAO,GAAG,EAAE,GAAG,IAAI,wBAAwB,EAAE,IAAI,CAAC,GAAG,wBAAwB,EAAE,IAAI,CAAC,GAAG,gBAAgB,CAAC,CAAC;AAAA,EAC3G;AACA,SAAO,GAAG,EAAE,GAAG,OAAO,EAAE,KAAK;AAE7B,WAAS,gBAAgB,OAAO;AAC9B,WAAO,MAAM,UAAU,IAAI,QAAM,IAAI,iBAAiB,EAAE,CAAC,EAAE,EAAE,KAAK,EAAE;AAAA,EACtE;AACF;AAEO,gBAAS,eAAe,QAAQ;AACrC,SAAO,OAAO,IAAI,OAAK,cAAc,CAAC,CAAC,EAAE,KAAK,iBAAmB;AACnE;AAEO,gBAAS,kBAAkB,QAAQ,SAAS,MAAM,OAAO,QAAW;AACzE,SAAO,QAAQ,WAAS,QAAQ,GAAG,MAAM,GAAG,cAAc,KAAK,CAAC,IAAI,IAAI,CAAC;AAC3E;AAEA,SAAS,sBAAsB,cAAc,MAAM,QAAW;AAE5D,MAAI,CAAC,KAAK,KAAK,KAAK,KAAK,KAAK,KAAK,GAAG,EAAE,SAAS,YAAY,GAAG;AAC9D,WAAO;AAAA,EACT;AAEA,MAAI,OAAO,iBAAiB,KAAK;AAC/B,QAAK,IAAI,MAAM,UAAU,KAAK,CAAC,OAAO,OAAO,OAAO,KAAK,EAAE,SAAS,GAAG,GAAI;AACzE,aAAO;AAAA,IACT;AAAA,EACF;AACA,SAAO;AACT;AAEO,gBAAS,sBAAsB,cAAc,MAAM,QAAW;AACnE,MAAI,sBAAsB,cAAc,GAAG,GAAG;AAC5C,WAAO;AAAA,EACT;AACA,MAAI,OAAO,6BAA6B,cAAc,GAAG,GAAG;AAC1D,WAAO;AAAA,EACT;AAEA,MAAI,CAAC,KAAK,KAAK,KAAK,KAAK,GAAG,EAAE,SAAS,YAAY,GAAG;AACpD,WAAO;AAAA,EACT;AAGA,SAAO;AACT;AAIO,gBAAS,sBAAsB,QAAQ,4BAA4B,QAAW;AACnF,QAAM,CAAC,QAAQ,IAAI,OAAO,IAAI,QAAQ;AACtC,MAAI,CAAC,UAAU;AACb,WAAO;AAAA,EACT;AACA,QAAM,CAAC,CAAC,IAAI,SAAS,UAAU,OAAO,QAAM,GAAG,SAAS,GAAG;AAC3D,MAAI,CAAC,GAAG;AACN,WAAO;AAAA,EACT;AACA,SAAO,EAAE;AACX;AAGO,gBAAS,UAAU,KAAK;AAC7B,SAAO,IAAI,OAAO,CAAC,KAAK,MAAM,IAAI,QAAQ,GAAG,MAAM,CAAC;AACtD;AAEO,gBAAS,mBAAmB,QAAQ,QAAQ;AACjD,MAAI,OAAO,QAAQ,OAAO,KAAK;AAC7B,WAAO;AAAA,EACT;AACA,SAAO,cAAc,MAAM,MAAM,cAAc,MAAM;AAIvD;AAEO,gBAAS,mBAAmB,OAAO,cAAwC;AAChF,QAAM,oBAAoB,MAAM,UAAU,OAAO,QAAM,GAAG,SAAS,YAAY;AAE/E,SAAO,kBAAkB;AAI3B;AAEO,gBAAS,gBAAgB,OAAO;AACrC,SAAO,MAAM,QAAQ,mEAAmE,IAAI;AAC9F;AAEA,SAAS,mCAAmC,KAAK,cAAc;AAE7D,MAAI,QAAQ,OAAO;AACjB,WAAO,CAAC,KAAK,KAAK,GAAG,EAAE,SAAS,YAAY;AAAA,EAC9C;AAEA,MAAI,CAAC,OAAO,OAAO,KAAK,EAAE,SAAS,GAAG,GAAG;AACvC,WAAO,CAAC,KAAK,KAAK,GAAG,EAAE,SAAS,YAAY;AAAA,EAC9C;AAEA,SAAO;AACT;AAGO,gBAAS,qBAAqB,KAAK,cAAc;AAEtD,MAAI,mCAAmC,KAAK,YAAY,GAAG;AACzD,WAAO;AAAA,EACT;AAIA,MAAI,OAAO,QAAQ,YAAY,IAAI,IAAI;AAErC,WAAO;AAAA,EACT;AAEA,QAAM,aAAa,kBAAkB,OAAO,OAAO,WAAS,MAAM,QAAQ,GAAG;AAC7E,MAAI,WAAW,WAAW,GAAG;AAC3B,YAAQ,2BAA2B,GAAG,iBAAiB,WAAW,MAAM,yCAAyC,YAAY,OAAO,QAAQ;AAC5I,WAAO;AAAA,EACT;AAEA,QAAM,gBAAgB,WAAW,CAAC,EAAE,UAAU,OAAO,cAAY,SAAS,SAAS,YAAY;AAI/F,MAAI,cAAc,WAAW,KAAK,iBAAiB,KAAK;AACtD,WAAO;AAAA,EACT;AACA,SAAO,cAAc,CAAC,EAAE;AAC1B;AAEA,SAAS,6BAA6B,KAAK;AACzC,QAAM,aAAa,kBAAkB,OAAO,OAAO,WAAS,MAAM,QAAQ,GAAG;AAC7E,MAAI,WAAW,WAAW,GAAG;AAC3B,WAAO;AAAA,EACT;AACA,SAAO,WAAW,CAAC,EAAE;AACvB;AAEO,gBAAS,4BAA4B,KAAK;AAC/C,QAAM,YAAY,6BAA6B,GAAG;AAClD,MAAI,cAAc,QAAW;AAC3B,WAAO;AAAA,EACT;AACA,SAAO,UAAU;AACnB;AAEO,gBAAS,4BAA4B,KAAK;AAC/C,QAAM,YAAY,6BAA6B,GAAG;AAClD,MAAI,cAAc,QAAW;AAC3B,WAAO;AAAA,EACT;AACA,SAAO,UAAU;AACnB;AAEO,gBAAS,qBAAqB,WAAW,SAAS,MAAM,OAAO,QAAW;AAC/E,YAAU,QAAQ,cAAY,QAAQ,GAAG,MAAM,GAAG,iBAAiB,QAAQ,CAAC,IAAI,IAAI,CAAC;AACvF;AAEO,gBAAS,sBAAsB,WAAW,WAAW;AAC1D,SAAO,UAAU,SAAS,UAAU,QAAQ,UAAU,UAAU,UAAU;AAC5E;AAEO,gBAAS,0BAA0B,OAAO,cAAwC;AACvF,SAAO,mBAAmB,OAAO,YAAY,IAAI;AACnD;AAEO,gBAAS,aAAa,OAAO;AAClC,QAAM,WAAW,gBAAgB,KAAK;AACtC,SAAO,UAAU;AACnB;AAIO,gBAAS,8BAA8B,MAAM,MAAM;AACxD,MAAK,CAAC,KAAK,MAAM,QAAM,KAAK,KAAK,SAAO,sBAAsB,IAAI,GAAG,CAAC,CAAC,GAAI;AACzE,WAAO;AAAA,EACT;AAEA,SAAO,KAAK,MAAM,SAAO,KAAK,KAAK,QAAM,sBAAsB,IAAI,GAAG,CAAC,CAAC;AAC1E;AAEO,gBAAS,gBAAgB,KAAK;AACnC,QAAM,aAAa,kBAAkB,OAAO,OAAO,WAAS,MAAM,QAAQ,GAAG;AAC7E,MAAI,WAAW,WAAW,GAAG;AAC3B,aAAS,2BAA2B,GAAG,4CAA4C;AACnF,WAAO;AAAA,EACT;AACA,SAAO,WAAW,CAAC,EAAE;AACvB;",
6
6
  "names": []
7
7
  }
package/package.json CHANGED
@@ -14,13 +14,13 @@
14
14
  "url": "https://github.com/NatLibFi/marc-record-validators-melinda"
15
15
  },
16
16
  "license": "MIT",
17
- "version": "12.1.0-alpha.1",
17
+ "version": "13.0.0",
18
18
  "main": "./dist/index.js",
19
19
  "publishConfig": {
20
20
  "access": "public"
21
21
  },
22
22
  "engines": {
23
- "node": ">=22"
23
+ "node": ">=24"
24
24
  },
25
25
  "scripts": {
26
26
  "prepare": "npm run build",
@@ -28,41 +28,34 @@
28
28
  "lint": "eslint ./src",
29
29
  "lint:dev": "eslint --fix ./src",
30
30
  "test": "npm run lint && npm run test:base",
31
- "test:base": "node --test --test-force-exit --experimental-test-coverage --test-reporter=spec './src/*.test.js' './src/**/*.test.js'",
32
- "dev:test": "cross-env DEBUG=@natlibfi/* NODE_ENV=test node --watch --test --experimental-test-coverage --test-reporter=spec './src/*.test.js' './src/**/*.test.js'",
31
+ "test:base": "node --test --test-force-exit --experimental-test-coverage --test-reporter=spec './src/**/*.test.js'",
32
+ "test:only": "npm run lint && npm run test:base:only",
33
+ "test:base:only": "node --test --test-only --test-force-exit --experimental-test-coverage --test-reporter=spec './src/**/*.test.js'",
34
+ "dev:test": "cross-env DEBUG=@natlibfi/* NODE_ENV=test node --watch --test --experimental-test-coverage --test-reporter=spec './src/**/*.test.js'",
33
35
  "dev:debug": "cross-env LOG_LEVEL=debug DEBUG=@natlibfi/* NODE_ENV=test"
34
36
  },
35
37
  "dependencies": {
36
- "@natlibfi/iso9-1995": "^1.0.0",
37
- "@natlibfi/issn-verify": "^2.0.0",
38
- "@natlibfi/marc-record": "^10.0.0",
39
- "@natlibfi/marc-record-serializers": "^11.0.0",
40
- "@natlibfi/marc-record-validate": "^9.0.0",
41
- "@natlibfi/melinda-commons": "^14.0.0",
38
+ "@natlibfi/iso9-1995": "^1.1.4",
39
+ "@natlibfi/issn-verify": "^2.0.3",
40
+ "@natlibfi/marc-record": "^10.0.2",
41
+ "@natlibfi/marc-record-serializers": "^11.0.3",
42
+ "@natlibfi/marc-record-validate": "^9.0.1",
43
+ "@natlibfi/melinda-commons": "^14.0.2",
42
44
  "@natlibfi/sfs-4900": "^2.0.0",
43
- "@natlibfi/sru-client": "^7.0.0",
44
- "cld3-asm": "^4.0.0",
45
+ "@natlibfi/sru-client": "^7.0.2",
45
46
  "clone": "^2.1.2",
46
47
  "debug": "^4.4.3",
47
- "isbn3": "^2.0.0",
48
- "langs": "^2.0.0",
49
- "undici": "^7.16.0",
48
+ "franc": "^6.2.0",
49
+ "isbn3": "^2.0.9",
50
50
  "xml2js": "^0.6.2",
51
51
  "xregexp": "^5.1.2"
52
52
  },
53
- "peerDependencies": {
54
- "@natlibfi/marc-record-validate": "^9.0.0"
55
- },
56
53
  "devDependencies": {
57
- "@natlibfi/fixugen": "^3.0.0",
58
- "@natlibfi/fixura": "^4.0.0",
54
+ "@natlibfi/fixugen": "^3.0.1",
55
+ "@natlibfi/fixura": "^4.0.1",
59
56
  "cross-env": "^10.1.0",
60
- "esbuild": "^0.27.0",
61
- "eslint": "^9.39.1",
57
+ "esbuild": "^0.28.0",
58
+ "eslint": "^10.7.0",
62
59
  "fetch-mock": "^12.6.0"
63
- },
64
- "overrides": {
65
- "nanoid": "^3.3.8"
66
- },
67
- "nvolkComment": "cld3-asm 4.0.0 uses emscripten-wasm-loader ^3.0.3 which uses problematic, non-secure nanoid version 2.X.X."
60
+ }
68
61
  }
@@ -1,6 +1,10 @@
1
- //import createDebugLogger from 'debug';
1
+ import createDebugLogger from 'debug';
2
2
  import {fieldToString, nvdebug} from './utils.js';
3
3
 
4
+ const debug = createDebugLogger('@natlibfi/marc-record-validators-melinda:addMissingField041');
5
+ //const debugData = debug.extend('data');
6
+ const debugDev = debug.extend('dev');
7
+
4
8
  const description = 'Add missing 041 field based on 008/35-37';
5
9
 
6
10
  // const multimediaRegexp = /multimedia/ui;
@@ -12,7 +16,7 @@ export default function () {
12
16
  };
13
17
 
14
18
  function isRealLanguageCode(languageCode = '|||') {
15
- nvdebug(`Language code 008/35-37: ${languageCode}`);
19
+ nvdebug(`Language code 008/35-37: ${languageCode}`, debugDev);
16
20
  if (!languageCode.match(/^[a-z]{3}$/u) || ['mul', 'und', 'zxx'].includes(languageCode)) {
17
21
  return false;
18
22
  }
@@ -43,7 +47,7 @@ export default function () {
43
47
  }
44
48
 
45
49
  function fix(record) {
46
- nvdebug(`FIX ${description}...`);
50
+ nvdebug(`FIX ${description}...`, debugDev);
47
51
  const data = generateContent(record);
48
52
  const res = {message: [], fix: [], valid: true};
49
53
  if (data) {
@@ -54,7 +58,7 @@ export default function () {
54
58
  }
55
59
 
56
60
  function validate(record) {
57
- nvdebug(`VALIDATE ${description}...`);
61
+ nvdebug(`VALIDATE ${description}...`, debugDev);
58
62
  const data = generateContent(record);
59
63
  if (!data) {
60
64
  return {message: [], valid: true};
@@ -1,11 +1,16 @@
1
- //import createDebugLogger from 'debug';
1
+ import createDebugLogger from 'debug';
2
2
  import {fieldToString, getCatalogingLanguage, nvdebug} from './utils.js';
3
3
  import {getFormOfItem, map336CodeToTerm} from './field33XUtils.js';
4
4
 
5
+ const debug = createDebugLogger('@natlibfi/marc-record-validators-melinda:addMissingField336');
6
+ //const debugData = debug.extend('data');
7
+ const debugDev = debug.extend('dev');
8
+
5
9
  const description = 'Add missing 336 field(s)';
6
10
 
7
11
  // const multimediaRegexp = /multimedia/ui;
8
12
 
13
+ // eslint-disable-next-line max-lines-per-function
9
14
  export default function () {
10
15
 
11
16
  return {
@@ -13,9 +18,9 @@ export default function () {
13
18
  };
14
19
 
15
20
  function fix(record) {
16
- nvdebug(`FIX ${description}...`);
21
+ nvdebug(`FIX ${description}...`, debugDev);
17
22
  const newFields = getMissing336s(record);
18
- nvdebug(` GOT ${newFields.length}...`);
23
+ nvdebug(` GOT ${newFields.length}...`, debugDev);
19
24
  // FFS: we actually need newFields array here! Videogame, for example, might be
20
25
  // 336 ## ‡a kaksiulotteinen liikkuva kuva ‡b tdi ‡2 rdacontent
21
26
  // 336 ## ‡a tietokoneohjelma ‡b cop ‡2 rdacontent
@@ -28,7 +33,7 @@ export default function () {
28
33
  }
29
34
 
30
35
  function validate(record) {
31
- nvdebug(`VALIDATE ${description}...`);
36
+ nvdebug(`VALIDATE ${description}...`, debugDev);
32
37
  const newFields = getMissing336s(record);
33
38
  if (newFields.length === 0) {
34
39
  return {message: [], valid: true};
@@ -251,7 +256,7 @@ export default function () {
251
256
  }
252
257
 
253
258
  const bees = guessMissing336Bs(record); // bees = b-subfields
254
- nvdebug(` WE HAVE ${bees.length} BEES: ${bees.join(', ')}`);
259
+ nvdebug(` WE HAVE ${bees.length} BEES: ${bees.join(', ')}`, debugDev);
255
260
 
256
261
 
257
262
  return bees.map(b => codeToField(b, getCatalogingLanguage(record, 'fin')));
@@ -1,7 +1,11 @@
1
- //import createDebugLogger from 'debug';
1
+ import createDebugLogger from 'debug';
2
2
  import {fieldToString, getCatalogingLanguage, nvdebug} from './utils.js';
3
3
  import {getFormOfItem, map337CodeToTerm} from './field33XUtils.js';
4
4
 
5
+ const debug = createDebugLogger('@natlibfi/marc-record-validators-melinda:addMissingField337');
6
+ //const debugData = debug.extend('data');
7
+ const debugDev = debug.extend('dev');
8
+
5
9
  const description = 'Add missing 337 field(s)';
6
10
 
7
11
  // Based on https://github.com/NatLibFi/USEMARCON-Cyrillux/blob/master/008-23-337a.tbl . Extended!
@@ -27,7 +31,7 @@ export default function () {
27
31
  };
28
32
 
29
33
  function fix(record) {
30
- nvdebug(`FIX ${description}...`);
34
+ nvdebug(`FIX ${description}...`, debugDev);
31
35
  const newField = getMissing337(record);
32
36
  const res = {message: [], fix: [], valid: true};
33
37
  if (newField) {
@@ -39,7 +43,7 @@ export default function () {
39
43
  }
40
44
 
41
45
  function validate(record) {
42
- nvdebug(`VALIDATE ${description}....`);
46
+ nvdebug(`VALIDATE ${description}....`, debugDev);
43
47
  const newField = getMissing337(record);
44
48
  if (!newField) {
45
49
  return {message: [], valid: true};
@@ -101,7 +105,7 @@ export default function () {
101
105
  function getMissing337(record) {
102
106
  const [f337] = record.get('337');
103
107
  if (f337) {
104
- // nvdebug(fieldToString(f337));
108
+ // nvdebug(fieldToString(f337), debugDev);
105
109
  return undefined;
106
110
  }
107
111
 
@@ -122,7 +126,7 @@ export default function () {
122
126
  }
123
127
 
124
128
  function mapFormOfItemToField337B(formOfItem) {
125
- nvdebug(`mapping ${formOfItem} to 337$b`);
129
+ nvdebug(`mapping ${formOfItem} to 337$b`, debugDev);
126
130
 
127
131
  const [result] = mappings337B.filter(row => row.formOfItem === formOfItem);
128
132
  if (result) {
@@ -1,10 +1,15 @@
1
- //import createDebugLogger from 'debug';
1
+ import createDebugLogger from 'debug';
2
2
  import {fieldHasSubfield, fieldToString, getCatalogingLanguage, nvdebug} from './utils.js';
3
3
  import {getFormOfItem, map338CodeToTerm} from './field33XUtils.js';
4
4
 
5
+ const debug = createDebugLogger('@natlibfi/marc-record-validators-melinda:addMissingField338');
6
+ //const debugData = debug.extend('data');
7
+ const debugDev = debug.extend('dev');
8
+
5
9
  // Based mostly on USEMARCON-RDA. However, many things have been rethought, modernized etc.
6
10
  const description = 'Add missing 338 field(s)';
7
11
 
12
+ // eslint-disable-next-line max-lines-per-function
8
13
  export default function () {
9
14
 
10
15
  return {
@@ -12,7 +17,7 @@ export default function () {
12
17
  };
13
18
 
14
19
  function fix(record) {
15
- nvdebug(`FIX ${description}...`);
20
+ nvdebug(`FIX ${description}...`, debugDev);
16
21
  const newField = getMissing338(record);
17
22
  const res = {message: [], fix: [], valid: true};
18
23
 
@@ -25,7 +30,7 @@ export default function () {
25
30
  }
26
31
 
27
32
  function validate(record) {
28
- nvdebug(`VALIDATE ${description}...`);
33
+ nvdebug(`VALIDATE ${description}...`, debugDev);
29
34
  const newField = getMissing338(record);
30
35
  if (!newField) {
31
36
  return {message: [], valid: true};
@@ -57,7 +62,7 @@ export default function () {
57
62
  if (!extent) {
58
63
  return undefined;
59
64
  }
60
- nvdebug(`AUDIO EXTENT: '${extent}`);
65
+ nvdebug(`AUDIO EXTENT: '${extent}`, debugDev);
61
66
  if (extent.match(/^(?:audio discs?|[^ ]*ljudskiva|[^ ]*ljudskivor|LP-levy|LP-levyä|LP-skiva|LP-skivor|[^ ]*äänilevy)$/iu)) {
62
67
  return 'sd';
63
68
  }
@@ -173,7 +178,7 @@ export default function () {
173
178
  }
174
179
 
175
180
  function extentToCarrierType(record) {
176
- nvdebug(`EXTENT2CARRIERTYPE`);
181
+ nvdebug(`EXTENT2CARRIERTYPE`, debugDev);
177
182
  return extentToAudioCarrierType(record) ||
178
183
  extentToComputerCarrierType(record) ||
179
184
  extentToMicroformCarrierType(record) ||
@@ -288,7 +293,7 @@ export default function () {
288
293
  }
289
294
 
290
295
  function audioToField338(record) {
291
- nvdebug('AUDIO-TO-338');
296
+ nvdebug('AUDIO-TO-338', debugDev);
292
297
  const typeOfRecord = record.getTypeOfRecord(record);
293
298
  if (typeOfRecord !== 'i' && typeOfRecord !== 'j') {
294
299
  return undefined;