@natlibfi/marc-record-validators-melinda 12.0.0 → 12.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (229) hide show
  1. package/dist/disambiguateSeriesStatements.test.js +1 -7
  2. package/dist/disambiguateSeriesStatements.test.js.map +2 -2
  3. package/dist/drop-terms.js +122 -0
  4. package/dist/drop-terms.js.map +7 -0
  5. package/dist/drop-terms.test.js +56 -0
  6. package/dist/drop-terms.test.js.map +7 -0
  7. package/dist/field-008-18-34-character-groups.test.js +1 -7
  8. package/dist/field-008-18-34-character-groups.test.js.map +2 -2
  9. package/dist/field-505-separators.test.js +1 -7
  10. package/dist/field-505-separators.test.js.map +2 -2
  11. package/dist/field-521-fix.test.js +1 -7
  12. package/dist/field-521-fix.test.js.map +2 -2
  13. package/dist/fix-33X.test.js +1 -1
  14. package/dist/fix-33X.test.js.map +1 -1
  15. package/dist/fix-country-codes.test.js +1 -7
  16. package/dist/fix-country-codes.test.js.map +2 -2
  17. package/dist/fix-sami-041.js +87 -0
  18. package/dist/fix-sami-041.js.map +7 -0
  19. package/dist/fix-sami-041.test.js +40 -0
  20. package/dist/fix-sami-041.test.js.map +7 -0
  21. package/dist/fixRelatorTerms.test.js +1 -7
  22. package/dist/fixRelatorTerms.test.js.map +2 -2
  23. package/dist/index.js +7 -1
  24. package/dist/index.js.map +2 -2
  25. package/dist/indicator-fixes.js +10 -0
  26. package/dist/indicator-fixes.js.map +2 -2
  27. package/dist/indicator-fixes.test.js +1 -7
  28. package/dist/indicator-fixes.test.js.map +2 -2
  29. package/dist/merge-fields.test.js +2 -7
  30. package/dist/merge-fields.test.js.map +2 -2
  31. package/dist/mergeField500Lisapainokset.test.js +1 -7
  32. package/dist/mergeField500Lisapainokset.test.js.map +2 -2
  33. package/dist/mergeRelatorTermFields.test.js +1 -7
  34. package/dist/mergeRelatorTermFields.test.js.map +2 -2
  35. package/dist/multiple-subfield-0.test.js +1 -7
  36. package/dist/multiple-subfield-0.test.js.map +2 -2
  37. package/dist/normalize-dashes.test.js +1 -7
  38. package/dist/normalize-dashes.test.js.map +2 -2
  39. package/dist/normalize-identifiers.test.js +1 -7
  40. package/dist/normalize-identifiers.test.js.map +2 -2
  41. package/dist/normalize-qualifying-information.test.js +1 -7
  42. package/dist/normalize-qualifying-information.test.js.map +2 -2
  43. package/dist/normalize-utf8-diacritics.test.js +1 -7
  44. package/dist/normalize-utf8-diacritics.test.js.map +2 -2
  45. package/dist/punctuation.test.js +1 -7
  46. package/dist/punctuation.test.js.map +2 -2
  47. package/dist/punctuation2.test.js +1 -7
  48. package/dist/punctuation2.test.js.map +2 -2
  49. package/dist/reindexSubfield6OccurenceNumbers.test.js +1 -7
  50. package/dist/reindexSubfield6OccurenceNumbers.test.js.map +2 -2
  51. package/dist/remove-041-zxx.js +56 -0
  52. package/dist/remove-041-zxx.js.map +7 -0
  53. package/dist/remove-041-zxx.test.js +40 -0
  54. package/dist/remove-041-zxx.test.js.map +7 -0
  55. package/dist/removeDuplicateDataFields.test.js +1 -7
  56. package/dist/removeDuplicateDataFields.test.js.map +2 -2
  57. package/dist/removeInferiorDataFields.js +1 -9
  58. package/dist/removeInferiorDataFields.js.map +2 -2
  59. package/dist/removeInferiorDataFields.test.js +1 -7
  60. package/dist/removeInferiorDataFields.test.js.map +2 -2
  61. package/dist/resolveOrphanedSubfield6s.js +1 -3
  62. package/dist/resolveOrphanedSubfield6s.js.map +2 -2
  63. package/dist/resolveOrphanedSubfield6s.test.js +1 -7
  64. package/dist/resolveOrphanedSubfield6s.test.js.map +2 -2
  65. package/dist/sanitize-vocabulary-source-codes.test.js +1 -7
  66. package/dist/sanitize-vocabulary-source-codes.test.js.map +2 -2
  67. package/dist/sortFields.js +16 -1
  68. package/dist/sortFields.js.map +2 -2
  69. package/dist/sortFields.test.js +1 -7
  70. package/dist/sortFields.test.js.map +2 -2
  71. package/dist/sortRelatorTerms.test.js +1 -7
  72. package/dist/sortRelatorTerms.test.js.map +2 -2
  73. package/dist/sortSubfields.js +3 -1
  74. package/dist/sortSubfields.js.map +2 -2
  75. package/dist/sortSubfields.test.js +1 -7
  76. package/dist/sortSubfields.test.js.map +2 -2
  77. package/dist/stripPunctuation.js +7 -4
  78. package/dist/stripPunctuation.js.map +2 -2
  79. package/dist/stripPunctuation.test.js +1 -7
  80. package/dist/stripPunctuation.test.js.map +2 -2
  81. package/dist/subfield6Utils.js +1 -13
  82. package/dist/subfield6Utils.js.map +2 -2
  83. package/dist/subfieldValueNormalizations.test.js +1 -7
  84. package/dist/subfieldValueNormalizations.test.js.map +2 -2
  85. package/dist/sync-007-and-300.test.js +1 -7
  86. package/dist/sync-007-and-300.test.js.map +2 -2
  87. package/dist/sync-language.js +103 -0
  88. package/dist/sync-language.js.map +7 -0
  89. package/dist/sync-language.test.js +40 -0
  90. package/dist/sync-language.test.js.map +7 -0
  91. package/dist/translate-terms.js +121 -85
  92. package/dist/translate-terms.js.map +3 -3
  93. package/dist/translate-terms.test.js +5 -8
  94. package/dist/translate-terms.test.js.map +2 -2
  95. package/dist/update-field-540.test.js +1 -7
  96. package/dist/update-field-540.test.js.map +2 -2
  97. package/dist/urn.test.js +1 -7
  98. package/dist/urn.test.js.map +2 -2
  99. package/package.json +8 -6
  100. package/src/disambiguateSeriesStatements.test.js +3 -8
  101. package/src/drop-terms.js +162 -0
  102. package/src/drop-terms.test.js +81 -0
  103. package/src/field-008-18-34-character-groups.test.js +3 -8
  104. package/src/field-505-separators.test.js +3 -8
  105. package/src/field-521-fix.test.js +3 -8
  106. package/src/fix-33X.test.js +1 -1
  107. package/src/fix-country-codes.test.js +3 -8
  108. package/src/fix-sami-041.js +113 -0
  109. package/src/fix-sami-041.test.js +52 -0
  110. package/src/fixRelatorTerms.test.js +3 -8
  111. package/src/index.js +8 -1
  112. package/src/indicator-fixes.js +12 -0
  113. package/src/indicator-fixes.test.js +3 -8
  114. package/src/merge-fields.test.js +3 -8
  115. package/src/mergeField500Lisapainokset.test.js +3 -8
  116. package/src/mergeRelatorTermFields.test.js +3 -8
  117. package/src/multiple-subfield-0.test.js +3 -8
  118. package/src/normalize-dashes.test.js +3 -8
  119. package/src/normalize-identifiers.test.js +3 -8
  120. package/src/normalize-qualifying-information.test.js +3 -8
  121. package/src/normalize-utf8-diacritics.test.js +3 -8
  122. package/src/punctuation.test.js +3 -8
  123. package/src/punctuation2.test.js +3 -8
  124. package/src/reindexSubfield6OccurenceNumbers.test.js +3 -8
  125. package/src/remove-041-zxx.js +85 -0
  126. package/src/remove-041-zxx.test.js +52 -0
  127. package/src/removeDuplicateDataFields.test.js +3 -8
  128. package/src/removeInferiorDataFields.js +7 -7
  129. package/src/removeInferiorDataFields.test.js +3 -8
  130. package/src/resolveOrphanedSubfield6s.js +3 -3
  131. package/src/resolveOrphanedSubfield6s.test.js +3 -8
  132. package/src/sanitize-vocabulary-source-codes.test.js +3 -8
  133. package/src/sortFields.js +20 -1
  134. package/src/sortFields.test.js +3 -8
  135. package/src/sortRelatorTerms.test.js +3 -8
  136. package/src/sortSubfields.js +3 -1
  137. package/src/sortSubfields.test.js +3 -8
  138. package/src/stripPunctuation.js +9 -6
  139. package/src/stripPunctuation.test.js +3 -8
  140. package/src/subfield6Utils.js +13 -13
  141. package/src/subfieldValueNormalizations.test.js +3 -8
  142. package/src/sync-007-and-300.test.js +3 -8
  143. package/src/sync-language.js +148 -0
  144. package/src/sync-language.test.js +52 -0
  145. package/src/translate-terms.js +158 -103
  146. package/src/translate-terms.test.js +12 -16
  147. package/src/update-field-540.test.js +3 -8
  148. package/src/urn.test.js +3 -8
  149. package/test-fixtures/drop-terms/01/expectedResult.json +31 -0
  150. package/test-fixtures/drop-terms/01/metadata.json +6 -0
  151. package/test-fixtures/drop-terms/01/record.json +35 -0
  152. package/test-fixtures/drop-terms/02/expectedResult.json +7 -0
  153. package/test-fixtures/drop-terms/02/metadata.json +6 -0
  154. package/test-fixtures/drop-terms/02/record.json +40 -0
  155. package/test-fixtures/drop-terms/03/expectedResult.json +6 -0
  156. package/test-fixtures/drop-terms/03/metadata.json +18 -0
  157. package/test-fixtures/drop-terms/03/record.json +39 -0
  158. package/test-fixtures/drop-terms/04/expectedResult.json +6 -0
  159. package/test-fixtures/drop-terms/04/metadata.json +19 -0
  160. package/test-fixtures/drop-terms/04/record.json +24 -0
  161. package/test-fixtures/fix-language-codes/02/metadata.json +1 -1
  162. package/test-fixtures/fix-sami-041/01/expectedResult.json +6 -0
  163. package/test-fixtures/fix-sami-041/01/metadata.json +4 -0
  164. package/test-fixtures/fix-sami-041/01/record.json +13 -0
  165. package/test-fixtures/fix-sami-041/02/expectedResult.json +10 -0
  166. package/test-fixtures/fix-sami-041/02/metadata.json +4 -0
  167. package/test-fixtures/fix-sami-041/02/record.json +8 -0
  168. package/test-fixtures/fix-sami-041/03/expectedResult.json +5 -0
  169. package/test-fixtures/fix-sami-041/03/metadata.json +5 -0
  170. package/test-fixtures/fix-sami-041/03/record.json +8 -0
  171. package/test-fixtures/fix-sami-041/04/expectedResult.json +7 -0
  172. package/test-fixtures/fix-sami-041/04/metadata.json +4 -0
  173. package/test-fixtures/fix-sami-041/04/record.json +10 -0
  174. package/test-fixtures/fix-sami-041/05/expectedResult.json +10 -0
  175. package/test-fixtures/fix-sami-041/05/metadata.json +6 -0
  176. package/test-fixtures/fix-sami-041/05/record.json +8 -0
  177. package/test-fixtures/indicator-fixes/11/expectedResult.json +10 -0
  178. package/test-fixtures/indicator-fixes/11/metadata.json +4 -0
  179. package/test-fixtures/indicator-fixes/11/record.json +10 -0
  180. package/test-fixtures/merge-fields/f05/metadata.json +1 -1
  181. package/test-fixtures/remove-041-zxx/01/expectedResult.json +5 -0
  182. package/test-fixtures/remove-041-zxx/01/metadata.json +5 -0
  183. package/test-fixtures/remove-041-zxx/01/record.json +10 -0
  184. package/test-fixtures/remove-041-zxx/02/expectedResult.json +7 -0
  185. package/test-fixtures/remove-041-zxx/02/metadata.json +5 -0
  186. package/test-fixtures/remove-041-zxx/02/record.json +9 -0
  187. package/test-fixtures/remove-041-zxx/11/expectedResult.json +10 -0
  188. package/test-fixtures/remove-041-zxx/11/metadata.json +5 -0
  189. package/test-fixtures/remove-041-zxx/11/record.json +9 -0
  190. package/test-fixtures/remove-041-zxx/12/expectedResult.json +10 -0
  191. package/test-fixtures/remove-041-zxx/12/metadata.json +5 -0
  192. package/test-fixtures/remove-041-zxx/12/record.json +9 -0
  193. package/test-fixtures/sort-fields/15/input.json +9 -0
  194. package/test-fixtures/sort-fields/15/metadata.json +5 -0
  195. package/test-fixtures/sort-fields/15/result.json +10 -0
  196. package/test-fixtures/sync-language/01/expectedResult.json +5 -0
  197. package/test-fixtures/sync-language/01/metadata.json +5 -0
  198. package/test-fixtures/sync-language/01/record.json +7 -0
  199. package/test-fixtures/sync-language/02/expectedResult.json +6 -0
  200. package/test-fixtures/sync-language/02/metadata.json +5 -0
  201. package/test-fixtures/sync-language/02/record.json +10 -0
  202. package/test-fixtures/sync-language/03/expectedResult.json +6 -0
  203. package/test-fixtures/sync-language/03/metadata.json +5 -0
  204. package/test-fixtures/sync-language/03/record.json +6 -0
  205. package/test-fixtures/sync-language/10/expectedResult.json +10 -0
  206. package/test-fixtures/sync-language/10/metadata.json +5 -0
  207. package/test-fixtures/sync-language/10/record.json +8 -0
  208. package/test-fixtures/sync-language/11/expectedResult.json +10 -0
  209. package/test-fixtures/sync-language/11/metadata.json +5 -0
  210. package/test-fixtures/sync-language/11/record.json +7 -0
  211. package/test-fixtures/sync-language/12/expectedResult.json +9 -0
  212. package/test-fixtures/sync-language/12/metadata.json +6 -0
  213. package/test-fixtures/sync-language/12/record.json +6 -0
  214. package/test-fixtures/sync-language/13/expectedResult.json +10 -0
  215. package/test-fixtures/sync-language/13/metadata.json +5 -0
  216. package/test-fixtures/sync-language/13/record.json +8 -0
  217. package/test-fixtures/sync-language/14/expectedResult.json +9 -0
  218. package/test-fixtures/sync-language/14/metadata.json +5 -0
  219. package/test-fixtures/sync-language/14/record.json +7 -0
  220. package/test-fixtures/sync-language/15/expectedResult.json +9 -0
  221. package/test-fixtures/sync-language/15/metadata.json +5 -0
  222. package/test-fixtures/sync-language/15/record.json +7 -0
  223. package/test-fixtures/translate-terms/05/expectedResult.json +12 -0
  224. package/test-fixtures/translate-terms/05/metadata.json +7 -0
  225. package/test-fixtures/translate-terms/05/record.json +11 -0
  226. package/test-fixtures/translate-terms/06/expectedResult.json +12 -0
  227. package/test-fixtures/translate-terms/06/metadata.json +7 -0
  228. package/test-fixtures/translate-terms/06/record.json +11 -0
  229. package/test-fixtures/translate-terms-data.js +23 -0
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/update-field-540.test.js"],
4
- "sourcesContent": ["import assert from 'node:assert';\nimport {MarcRecord} from '@natlibfi/marc-record';\nimport validatorFactory from './update-field-540.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', 'update-field-540'],\n useMetadataFile: true,\n recurse: false,\n fixura: {\n reader: READERS.JSON\n },\n hooks: {\n before: async () => {\n testValidatorFactory();\n }\n }\n});\n\nconst debug = createDebugLogger('@natlibfi/marc-record-validators-melinda/update-field-540:test');\n\nasync function testValidatorFactory() {\n const validator = await validatorFactory();\n\n assert(validator)\n .to.be.an('object')\n .that.has.any.keys('description', 'validate');\n\n assert(validator.description).to.be.a('string');\n assert(validator.validate).to.be.a('function');\n}\n\nasync function callback({getFixture, enabled = true, fix = false}) {\n if (enabled === false) {\n debug('TEST SKIPPED!');\n return;\n }\n\n const validator = await validatorFactory();\n const record = new MarcRecord(getFixture('record.json'));\n const expectedResult = getFixture('expectedResult.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,kBAAkB;AAAA,EACrE,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;AAED,MAAM,QAAQ,kBAAkB,gEAAgE;AAEhG,eAAe,uBAAuB;AACpC,QAAM,YAAY,MAAM,iBAAiB;AAEzC,SAAO,SAAS,EACb,GAAG,GAAG,GAAG,QAAQ,EACjB,KAAK,IAAI,IAAI,KAAK,eAAe,UAAU;AAE9C,SAAO,UAAU,WAAW,EAAE,GAAG,GAAG,EAAE,QAAQ;AAC9C,SAAO,UAAU,QAAQ,EAAE,GAAG,GAAG,EAAE,UAAU;AAC/C;AAEA,eAAe,SAAS,EAAC,YAAY,UAAU,MAAM,MAAM,MAAK,GAAG;AACjE,MAAI,YAAY,OAAO;AACrB,UAAM,eAAe;AACrB;AAAA,EACF;AAEA,QAAM,YAAY,MAAM,iBAAiB;AACzC,QAAM,SAAS,IAAI,WAAW,WAAW,aAAa,CAAC;AACvD,QAAM,iBAAiB,WAAW,qBAAqB;AAGvD,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 './update-field-540.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', 'update-field-540'],\n useMetadataFile: true,\n recurse: false,\n fixura: {\n reader: READERS.JSON\n },\n hooks: {\n before: async () => {\n testValidatorFactory();\n }\n }\n});\n\n//const debug = createDebugLogger('@natlibfi/marc-record-validators-melinda/update-field-540:test');\n\nasync function testValidatorFactory() {\n const validator = await validatorFactory();\n\n assert(validator)\n .to.be.an('object')\n .that.has.any.keys('description', 'validate');\n\n assert(validator.description).to.be.a('string');\n assert(validator.validate).to.be.a('function');\n}\n\nasync function callback({getFixture, fix = false}) {\n const validator = await validatorFactory();\n const record = new MarcRecord(getFixture('record.json'));\n const expectedResult = getFixture('expectedResult.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,kBAAkB;AAAA,EACrE,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;AAID,eAAe,uBAAuB;AACpC,QAAM,YAAY,MAAM,iBAAiB;AAEzC,SAAO,SAAS,EACb,GAAG,GAAG,GAAG,QAAQ,EACjB,KAAK,IAAI,IAAI,KAAK,eAAe,UAAU;AAE9C,SAAO,UAAU,WAAW,EAAE,GAAG,GAAG,EAAE,QAAQ;AAC9C,SAAO,UAAU,QAAQ,EAAE,GAAG,GAAG,EAAE,UAAU;AAC/C;AAEA,eAAe,SAAS,EAAC,YAAY,MAAM,MAAK,GAAG;AACjD,QAAM,YAAY,MAAM,iBAAiB;AACzC,QAAM,SAAS,IAAI,WAAW,WAAW,aAAa,CAAC;AACvD,QAAM,iBAAiB,WAAW,qBAAqB;AAGvD,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/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/package.json CHANGED
@@ -14,7 +14,7 @@
14
14
  "url": "https://github.com/NatLibFi/marc-record-validators-melinda"
15
15
  },
16
16
  "license": "MIT",
17
- "version": "12.0.0",
17
+ "version": "12.0.1",
18
18
  "main": "./dist/index.js",
19
19
  "publishConfig": {
20
20
  "access": "public"
@@ -29,22 +29,24 @@
29
29
  "lint:dev": "eslint --fix ./src",
30
30
  "test": "npm run lint && npm run test:base",
31
31
  "test:base": "node --test --test-force-exit --experimental-test-coverage --test-reporter=spec './src/*.test.js' './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' './src/**/*.test.js'",
32
34
  "dev:test": "cross-env DEBUG=@natlibfi/* NODE_ENV=test node --watch --test --experimental-test-coverage --test-reporter=spec './src/*.test.js' './src/**/*.test.js'",
33
35
  "dev:debug": "cross-env LOG_LEVEL=debug DEBUG=@natlibfi/* NODE_ENV=test"
34
36
  },
35
37
  "dependencies": {
36
38
  "@natlibfi/iso9-1995": "^1.0.0",
37
39
  "@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": "^10.0.1",
41
+ "@natlibfi/marc-record-serializers": "^11.0.1",
40
42
  "@natlibfi/marc-record-validate": "^9.0.0",
41
- "@natlibfi/melinda-commons": "^14.0.0",
43
+ "@natlibfi/melinda-commons": "^14.0.1",
42
44
  "@natlibfi/sfs-4900": "^2.0.0",
43
45
  "@natlibfi/sru-client": "^7.0.0",
44
46
  "cld3-asm": "^4.0.0",
45
47
  "clone": "^2.1.2",
46
48
  "debug": "^4.4.3",
47
- "isbn3": "^2.0.0",
49
+ "isbn3": "^2.0.1",
48
50
  "langs": "^2.0.0",
49
51
  "undici": "^7.16.0",
50
52
  "xml2js": "^0.6.2",
@@ -57,7 +59,7 @@
57
59
  "@natlibfi/fixugen": "^3.0.0",
58
60
  "@natlibfi/fixura": "^4.0.0",
59
61
  "cross-env": "^10.1.0",
60
- "esbuild": "^0.25.12",
62
+ "esbuild": "^0.27.1",
61
63
  "eslint": "^9.39.1",
62
64
  "fetch-mock": "^12.6.0"
63
65
  },
@@ -3,7 +3,7 @@ import {MarcRecord} from '@natlibfi/marc-record';
3
3
  import validatorFactory from './disambiguateSeriesStatements.js';
4
4
  import {READERS} from '@natlibfi/fixura';
5
5
  import generateTests from '@natlibfi/fixugen';
6
- import createDebugLogger from 'debug';
6
+ //import createDebugLogger from 'debug';
7
7
 
8
8
  generateTests({
9
9
  callback,
@@ -19,7 +19,7 @@ generateTests({
19
19
  }
20
20
  }
21
21
  });
22
- const debug = createDebugLogger('@natlibfi/marc-record-validators-melinda/disambiguateSeriesStatements:test');
22
+ //const debug = createDebugLogger('@natlibfi/marc-record-validators-melinda/disambiguateSeriesStatements:test');
23
23
 
24
24
  async function testValidatorFactory() {
25
25
  const validator = await validatorFactory();
@@ -29,12 +29,7 @@ async function testValidatorFactory() {
29
29
  assert.equal(typeof validator.validate, 'function');
30
30
  }
31
31
 
32
- async function callback({getFixture, enabled = true, fix = false}) {
33
- if (enabled === false) {
34
- debug('TEST SKIPPED!');
35
- return;
36
- }
37
-
32
+ async function callback({getFixture, fix = false}) {
38
33
  const validator = await validatorFactory();
39
34
  const record = new MarcRecord(getFixture('record.json'));
40
35
  const expectedResult = getFixture('expectedResult.json');
@@ -0,0 +1,162 @@
1
+ // Author(s): Nicholas Volk
2
+
3
+ import clone from 'clone';
4
+ import createDebugLogger from 'debug';
5
+ import {fieldToString, nvdebug} from './utils.js';
6
+ import {getLexiconAndLanguage, getTermData, isLabel, isValidSubfield0} from './translate-terms.js';
7
+
8
+ const debug = createDebugLogger('@natlibfi/marc-record-validators-melinda:drop-terms');
9
+
10
+
11
+ const defaultConfig = {
12
+ 'constraints': [
13
+ {'tag': '648', 'lex': 'yso/fin'},
14
+ {'tag': '648', 'lex': 'yso/swe'},
15
+ {'tag': '650', 'lex': 'yso/fin'},
16
+ {'tag': '650', 'lex': 'yso/swe'},
17
+ {'tag': '651', 'lex': 'yso/fin'},
18
+ {'tag': '651', 'lex': 'yso/swe'},
19
+ {'tag': '655', 'lex': 'slm/fin'},
20
+ {'tag': '655', 'lex': 'slm/swe'}
21
+ ],
22
+ 'keep invalid url': false, // If not true, removes illegal subfield $0. The whole field removal is later decided by 'keep 0-less'
23
+ 'keep invalid label': false, // label ($a) is neither pref Label nor altLabel => remove whole field
24
+ 'remove altLabel': false,
25
+ 'remove 0-less': true
26
+ };
27
+
28
+ export default function (config = defaultConfig) {
29
+
30
+ return {
31
+ description: 'Drop yso and slm terms that do not match their identifiers. Use for incoming records only! Not for records already in Melinda!',
32
+ validate, fix
33
+ };
34
+
35
+ async function fix(record, validateMode = false) {
36
+ const clonedFields = record.fields.map(f => clone(f));
37
+
38
+ const results = await processFields(clonedFields);
39
+
40
+ const removables = results.map((f, i) => !f ? record.fields[i] : undefined).filter(f => f);
41
+ const modMessages = results.map((f, i) => getMod(f, i)).filter(f => f);
42
+ const removalMessages = removables.map(f => `Remove '${fieldToString(f)}'`);
43
+ const allMessages = [...modMessages, ...removalMessages];
44
+
45
+ if (validateMode) {
46
+ if (allMessages.length === 0) {
47
+ return {'message': [], 'valid': true};
48
+ }
49
+ return {'message': allMessages, 'valid': false};
50
+ }
51
+
52
+ removables.forEach(f => record.removeField(f));
53
+
54
+ return {message: [], fix: allMessages, valid: true};
55
+
56
+ function getMod(field, index) {
57
+ if (!field) {
58
+ return undefined;
59
+ }
60
+ const before = fieldToString(record.fields[index]);
61
+ const after = fieldToString(results[index]);
62
+ if (before !== after) {
63
+ if (!validateMode) {
64
+ record.fields[index] = field;
65
+ }
66
+ return `Modify '${before}' => '${after}'`;
67
+ }
68
+ return undefined;
69
+ }
70
+ }
71
+
72
+ function isPotentialField(f) {
73
+ if (!config || !config.constraints) {
74
+ return false;
75
+ }
76
+ return config.constraints.some(c => c.tag === f.tag && f.subfields?.some(sf => sf.code === '2' && sf.value === c.lex));
77
+ }
78
+
79
+ async function validate(record) {
80
+ return fix(record, true);
81
+ }
82
+
83
+
84
+ async function processFields(fields, results = []) {
85
+ const [currField, ...remainingFields] = fields;
86
+ if (!currField) {
87
+ return results;
88
+ }
89
+
90
+ if (!isPotentialField(currField)) { // Not interested in this field
91
+ return processFields(remainingFields, [...results, currField]);
92
+ }
93
+
94
+ removeSyntacticallyIllegalSubfield0s(currField); // iff config wants them to be removed...
95
+
96
+ const removable = await isRemovableField(currField);
97
+
98
+ return processFields(remainingFields, [...results, removable ? undefined : currField]);
99
+ }
100
+
101
+ function removeSyntacticallyIllegalSubfield0s(field) {
102
+ if (config['keep invalid url']) {
103
+ return;
104
+ }
105
+
106
+ const lexData = getLexiconAndLanguage(field);
107
+ if (!lexData.lang) { // This is an error of sorts. Should we proceed and remove $0s?
108
+ return;
109
+ }
110
+
111
+ field.subfields = field.subfields.filter(sf => sf.code !== '0' || isValidSubfield0(sf, lexData.lex));
112
+ }
113
+
114
+ async function isRemovableField(field) {
115
+ // nvdebug(`FOO===== ${fieldToString(field)}`);
116
+
117
+
118
+ // $0-less field:
119
+ if (!field.subfields.some(sf => sf.code === '0')) {
120
+ return config['remove 0-less'];
121
+ }
122
+
123
+ const subfield0 = field.subfields.find(sf => sf.code === '0');
124
+ const data = await getTermData(subfield0.value);
125
+ // NB! No data might be a BUG! This might delete all incoming terms if Finto is down... (we should distinguish between a miss and a failure)
126
+ // However, if we use this validator only for incoming records, it's fine enough.
127
+
128
+ if (data) {
129
+ const subfieldA = field.subfields.find(sf => sf.code === 'a');
130
+ if (subfieldA) {
131
+ const lexData = getLexiconAndLanguage(field);
132
+
133
+ // $a is the pref label. All is fine!
134
+ if (isLabel(data.prefLabel, subfieldA.value, lexData.lang)) {
135
+ debug(`altLabel found: ${subfieldA.value}`);
136
+ return false;
137
+ }
138
+ if (isLabel(data.altLabel, subfieldA.value, lexData.lang)) {
139
+ debug(`altLabel found: ${subfieldA.value}`);
140
+ // Oddly enough this could remove altLabel but keep totally invalid labels...
141
+ return config['remove altLabel'];
142
+ }
143
+ debug(`a-2-0 mismatch: ${fieldToString(field)}`);
144
+ }
145
+ }
146
+
147
+
148
+ if (config['keep invalid label']) {
149
+ // We keep the label $a. However, we can get rid of $0 if we want to (semantic reasons)
150
+ if (!config['keep invalid url']) {
151
+ nvdebug(`=============== 0-removal`);
152
+ field.subfields = field.subfields.filter(sf => sf.code !== '0');
153
+ }
154
+ return false;
155
+ }
156
+ return true;
157
+
158
+ }
159
+
160
+
161
+ }
162
+
@@ -0,0 +1,81 @@
1
+ import assert from 'node:assert/strict';
2
+ //import createDebugLogger from 'debug';
3
+ import fetchMock from 'fetch-mock';
4
+
5
+ import validatorFactory from './drop-terms.js';
6
+
7
+ import {MarcRecord} from '@natlibfi/marc-record';
8
+ import {READERS} from '@natlibfi/fixura';
9
+ import generateTests from '@natlibfi/fixugen';
10
+
11
+
12
+ import {fakeData} from '../test-fixtures/translate-terms-data.js';
13
+
14
+
15
+ const uris = [
16
+ 'http://www.yso.fi/onto/yso/p444',
17
+ 'http://www.yso.fi/onto/yso/p500',
18
+ 'http://www.yso.fi/onto/yso/p13299',
19
+ 'http://www.yso.fi/onto/yso/p111739',
20
+ 'http://www.yso.fi/onto/yso/p6197061979',
21
+ 'http://www.yso.fi/onto/yso/p6196061969',
22
+ 'http://urn.fi/URN:NBN:fi:au:slm:s161'
23
+ ];
24
+
25
+ const useMock = 1;
26
+
27
+
28
+ generateTests({
29
+ callback,
30
+ path: [import.meta.dirname, '..', 'test-fixtures', 'drop-terms'],
31
+ useMetadataFile: true,
32
+ recurse: false,
33
+ fixura: {
34
+ reader: READERS.JSON
35
+ },
36
+ hooks: {
37
+ before: async () => {
38
+
39
+ if (useMock) {
40
+ fetchMock.mockGlobal()
41
+ .get(`https://api.finto.fi/rest/v1/data?uri=${uris[0]}&format=application%2Fjson`, {status: 200, headers: {}, body: fakeData})
42
+ .get(`https://api.finto.fi/rest/v1/data?uri=${uris[1]}&format=application%2Fjson`, {status: 200, headers: {}, body: fakeData})
43
+ .get(`https://api.finto.fi/rest/v1/data?uri=${uris[2]}&format=application%2Fjson`, {status: 200, headers: {}, body: fakeData})
44
+ .get(`https://api.finto.fi/rest/v1/data?uri=${uris[3]}&format=application%2Fjson`, {status: 200, headers: {}, body: fakeData})
45
+ .get(`https://api.finto.fi/rest/v1/data?uri=${uris[4]}&format=application%2Fjson`, {status: 200, headers: {}, body: fakeData})
46
+ .get(`https://api.finto.fi/rest/v1/data?uri=${uris[5]}&format=application%2Fjson`, {status: 200, headers: {}, body: fakeData})
47
+ .get(`https://api.finto.fi/rest/v1/data?uri=${uris[6]}&format=application%2Fjson`, {status: 200, headers: {}, body: fakeData});
48
+ }
49
+
50
+ testValidatorFactory();
51
+ }
52
+ }
53
+ });
54
+
55
+ //const debug = createDebugLogger('@natlibfi/marc-record-validators-melinda/drop-terms:test');
56
+
57
+ async function testValidatorFactory() {
58
+ const validator = await validatorFactory();
59
+
60
+ assert.equal(typeof validator, 'object');
61
+ assert.equal(typeof validator.description, 'string');
62
+ assert.equal(typeof validator.validate, 'function');
63
+ }
64
+
65
+ async function callback({getFixture, fix = false, config = undefined}) {
66
+ const validator = await validatorFactory(config);
67
+ const record = new MarcRecord(getFixture('record.json'));
68
+ const expectedResult = getFixture('expectedResult.json');
69
+ // console.log(expectedResult); // eslint-disable-line
70
+
71
+ if (!fix) {
72
+ const result = await validator.validate(record);
73
+ assert.deepEqual(result, expectedResult);
74
+ const originalRecord = new MarcRecord(getFixture('record.json'));
75
+ assert.deepEqual(record, originalRecord); // Validation should not change the record
76
+ return;
77
+ }
78
+ const expectedResult2 = new MarcRecord(expectedResult);
79
+ await validator.fix(record);
80
+ assert.deepEqual(record, expectedResult2);
81
+ }
@@ -3,7 +3,7 @@ import {MarcRecord} from '@natlibfi/marc-record';
3
3
  import validatorFactory from './field-008-18-34-character-groups.js';
4
4
  import {READERS} from '@natlibfi/fixura';
5
5
  import generateTests from '@natlibfi/fixugen';
6
- import createDebugLogger from 'debug';
6
+ //import createDebugLogger from 'debug';
7
7
 
8
8
  generateTests({
9
9
  callback,
@@ -19,7 +19,7 @@ generateTests({
19
19
  }
20
20
  }
21
21
  });
22
- const debug = createDebugLogger('@natlibfi/marc-record-validators-melinda/field-008-18-34-character-groups:test');
22
+ //const debug = createDebugLogger('@natlibfi/marc-record-validators-melinda/field-008-18-34-character-groups:test');
23
23
 
24
24
  async function testValidatorFactory() {
25
25
  const validator = await validatorFactory();
@@ -30,12 +30,7 @@ async function testValidatorFactory() {
30
30
  assert.equal(typeof validator.validate, 'function');
31
31
  }
32
32
 
33
- async function callback({getFixture, enabled = true, fix = false}) {
34
- if (enabled === false) {
35
- debug('TEST SKIPPED!');
36
- return;
37
- }
38
-
33
+ async function callback({getFixture, fix = false}) {
39
34
  const validator = await validatorFactory();
40
35
  const record = new MarcRecord(getFixture('record.json'));
41
36
  const expectedResult = getFixture('expectedResult.json');
@@ -3,7 +3,7 @@ import {MarcRecord} from '@natlibfi/marc-record';
3
3
  import validatorFactory from './field-505-separators.js';
4
4
  import {READERS} from '@natlibfi/fixura';
5
5
  import generateTests from '@natlibfi/fixugen';
6
- import createDebugLogger from 'debug';
6
+ //import createDebugLogger from 'debug';
7
7
 
8
8
  generateTests({
9
9
  callback,
@@ -19,7 +19,7 @@ generateTests({
19
19
  }
20
20
  }
21
21
  });
22
- const debug = createDebugLogger('@natlibfi/marc-record-validators-melinda/field-505-separators:test');
22
+ //const debug = createDebugLogger('@natlibfi/marc-record-validators-melinda/field-505-separators:test');
23
23
 
24
24
  async function testValidatorFactory() {
25
25
  const validator = await validatorFactory();
@@ -29,12 +29,7 @@ async function testValidatorFactory() {
29
29
  assert.equal(typeof validator.validate, 'function');
30
30
  }
31
31
 
32
- async function callback({getFixture, enabled = true, fix = false}) {
33
- if (enabled === false) {
34
- debug('TEST SKIPPED!');
35
- return;
36
- }
37
-
32
+ async function callback({getFixture, fix = false}) {
38
33
  const validator = await validatorFactory();
39
34
 
40
35
  const recordFixture = getFixture('record.json');
@@ -3,7 +3,7 @@ import {MarcRecord} from '@natlibfi/marc-record';
3
3
  import validatorFactory from './field-521-fix.js';
4
4
  import {READERS} from '@natlibfi/fixura';
5
5
  import generateTests from '@natlibfi/fixugen';
6
- import createDebugLogger from 'debug';
6
+ //import createDebugLogger from 'debug';
7
7
 
8
8
  generateTests({
9
9
  callback,
@@ -19,7 +19,7 @@ generateTests({
19
19
  }
20
20
  }
21
21
  });
22
- const debug = createDebugLogger('@natlibfi/marc-record-validators-melinda/fix521:test');
22
+ //const debug = createDebugLogger('@natlibfi/marc-record-validators-melinda/fix521:test');
23
23
 
24
24
  async function testValidatorFactory() {
25
25
  const validator = await validatorFactory();
@@ -29,12 +29,7 @@ async function testValidatorFactory() {
29
29
  assert.equal(typeof validator.validate, 'function');
30
30
  }
31
31
 
32
- async function callback({getFixture, enabled = true, fix = false}) {
33
- if (enabled === false) {
34
- debug('TEST SKIPPED!');
35
- return;
36
- }
37
-
32
+ async function callback({getFixture, fix = false}) {
38
33
  const validator = await validatorFactory();
39
34
  const record = new MarcRecord(getFixture('record.json'));
40
35
  const expectedResult = getFixture('expectedResult.json');
@@ -22,7 +22,7 @@ generateTests({
22
22
  async function testValidatorFactory() {
23
23
  const validator = await validatorFactory();
24
24
 
25
- assert.equal(typeof validator, 'objecr');
25
+ assert.equal(typeof validator, 'object');
26
26
  assert.equal(typeof validator.description, 'string');
27
27
  assert.equal(typeof validator.validate, 'function');
28
28
  assert.equal(typeof validator.fix, 'function');
@@ -3,7 +3,7 @@ import {MarcRecord} from '@natlibfi/marc-record';
3
3
  import validatorFactory from './fix-country-codes.js';
4
4
  import {READERS} from '@natlibfi/fixura';
5
5
  import generateTests from '@natlibfi/fixugen';
6
- import createDebugLogger from 'debug';
6
+ //import createDebugLogger from 'debug';
7
7
 
8
8
  generateTests({
9
9
  callback,
@@ -19,7 +19,7 @@ generateTests({
19
19
  }
20
20
  }
21
21
  });
22
- const debug = createDebugLogger('@natlibfi/marc-record-validators-melinda/fix-country-codes:test');
22
+ //const debug = createDebugLogger('@natlibfi/marc-record-validators-melinda/fix-country-codes:test');
23
23
 
24
24
  async function testValidatorFactory() {
25
25
  const validator = await validatorFactory();
@@ -29,12 +29,7 @@ async function testValidatorFactory() {
29
29
  assert.equal(typeof validator.validate, 'function');
30
30
  }
31
31
 
32
- async function callback({getFixture, enabled = true, fix = false}) {
33
- if (enabled === false) {
34
- debug('TEST SKIPPED!');
35
- return;
36
- }
37
-
32
+ async function callback({getFixture, fix = false}) {
38
33
  const validator = await validatorFactory();
39
34
  const record = new MarcRecord(getFixture('record.json'));
40
35
  const expectedResult = getFixture('expectedResult.json');
@@ -0,0 +1,113 @@
1
+ // Author(s): Nicholas Volk
2
+
3
+ //import createDebugLogger from 'debug';
4
+ import clone from 'clone';
5
+
6
+ import {fieldToString} from './utils.js';
7
+
8
+ // const debug = createDebugLogger('@natlibfi/marc-record-validators-melinda:fix-sami-041');
9
+
10
+
11
+
12
+ export default function () {
13
+ /* 'sma': eteläsaame, 'sme': pohjoissaame, 'smj': luulajansaame, 'smn': inarinsaame, 'sms': koltansaame */
14
+ const samiLanguages = ['sma', 'sme', 'smj', 'smn', 'sms'];
15
+ const relevantSubfieldCodes = ['a', 'd']; // Subfield codes that should also have 'smi' if a sami langauge is used. Confirmed by A.R. via Slack 2025-12-05
16
+
17
+ return {
18
+ description: 'Add corresponing \'smi\' subfield before a specific sami language subfields, if needed',
19
+ validate, fix
20
+ };
21
+
22
+ function fix(record, validateMode = false) {
23
+ const relevantFields = record.fields.filter(f => isRelevantField(f, validateMode)).map(f => validateMode ? clone(f) : f); // NV! relevant fields are cloned in validation mode!
24
+ // Nothing to do:
25
+ if (relevantFields.length === 0) {
26
+ if (validateMode) {
27
+ return {message: [], valid: true};
28
+ }
29
+ return {message: [], fix: [], valid: true};
30
+ }
31
+
32
+ const relevantFieldsAsStrings = relevantFields.map(f => fieldToString(f)); // get original values
33
+
34
+ relevantFields.forEach(f => processField(f));
35
+ const modFieldsAsStrings = relevantFields.map(f => fieldToString(f));
36
+ const report = [...updateAndReport008(), ...createReport(relevantFieldsAsStrings, modFieldsAsStrings)];
37
+
38
+ if (validateMode) {
39
+ return {'message': report, 'valid': false};
40
+ }
41
+
42
+ return {message: [], fix: report, valid: true};
43
+
44
+ function updateAndReport008() {
45
+ const [f008] = record.get('008').map(f => validateMode ? clone(f) : f);
46
+
47
+ if (!f008) {
48
+ return [];
49
+ }
50
+ const currLang = f008.value.substr(35, 3);
51
+ if (!samiLanguages.includes(currLang)) { // NB! If original 008/35-37 was not a sami language, we don't change anything!
52
+ return [];
53
+ }
54
+ const origValue = f008.value;
55
+ const firstRelevantSubfield = relevantFields[0].subfields.find(sf => sf.code === 'a' || sf.code === 'd'); // NB! don't use relevantSubfieldCodes here!
56
+ if (firstRelevantSubfield.value === 'smi') { // First relevant subfield is
57
+ f008.value = `${f008.value.substr(0, 35)}smi${f008.value.substr(38)}`;
58
+ }
59
+ return createReport([origValue], [f008.value]);
60
+ }
61
+ }
62
+
63
+ function createReport(origArray, modArray) {
64
+ return origArray.map((entry, index) => createEntry(entry, index));
65
+
66
+ function createEntry(item, index) {
67
+ return `'${item}' => '${modArray[index]}'`;
68
+ }
69
+ }
70
+
71
+ function validate(record) {
72
+ return fix(record, true);
73
+ }
74
+
75
+ function processField(f) {
76
+ f.subfields = prosessSubfields(f.subfields);
77
+ return f;
78
+ }
79
+
80
+ function prosessSubfields(incomingSubfields, outgoingSubfields = []) {
81
+ const [currSubfield, ...otherSubfields] = incomingSubfields;
82
+ if (!currSubfield) {
83
+ return outgoingSubfields;
84
+ }
85
+ if (!isRelevantSamiSubfield(currSubfield, [...outgoingSubfields, ...otherSubfields])) {
86
+ return prosessSubfields(otherSubfields, [...outgoingSubfields, currSubfield]);
87
+ }
88
+
89
+ const smiSubfield = {
90
+ code: currSubfield.code,
91
+ value: 'smi'
92
+ };
93
+ return prosessSubfields(otherSubfields, [...outgoingSubfields, smiSubfield, currSubfield]);
94
+ }
95
+
96
+ function isRelevantField(f) {
97
+ if (f.tag !== '041' || !f.subfields || f.subfields.some(sf => sf.code === '2')) {
98
+ return false;
99
+ }
100
+ return f.subfields.some(sf => isRelevantSamiSubfield(sf, f.subfields)); // it's ok to pass sf in f.subfields also
101
+ }
102
+
103
+ function isRelevantSamiSubfield(sf, otherSubfields) {
104
+ if (!relevantSubfieldCodes.includes(sf.code) || !samiLanguages.includes(sf.value)) {
105
+ return false;
106
+ }
107
+ if (otherSubfields.some(sf2 => sf2.code === sf.code && sf2.value === 'smi')) {
108
+ return false;
109
+ }
110
+ return true;
111
+ }
112
+ }
113
+