@natlibfi/melinda-rest-api-commons 6.0.1 → 6.2.0-alpha.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 (94) hide show
  1. package/.github/workflows/melinda-node-tests-and-publish.yml +4 -2
  2. package/README.md +82 -0
  3. package/dist/amqp.d.ts +41 -0
  4. package/dist/amqp.d.ts.map +1 -0
  5. package/dist/amqp.js +242 -218
  6. package/dist/amqp.js.map +1 -7
  7. package/dist/constants.d.ts +49 -0
  8. package/dist/constants.d.ts.map +1 -0
  9. package/dist/constants.js +38 -38
  10. package/dist/constants.js.map +1 -7
  11. package/dist/helpers/conversion.d.ts +8 -0
  12. package/dist/helpers/conversion.d.ts.map +1 -0
  13. package/dist/helpers/conversion.js +70 -65
  14. package/dist/helpers/conversion.js.map +1 -7
  15. package/dist/helpers/fix-constants.d.ts +76 -0
  16. package/dist/helpers/fix-constants.d.ts.map +1 -0
  17. package/dist/helpers/fix-constants.js +41 -41
  18. package/dist/helpers/fix-constants.js.map +1 -7
  19. package/dist/helpers/fix-handle-tempurns.d.ts +3 -0
  20. package/dist/helpers/fix-handle-tempurns.d.ts.map +1 -0
  21. package/dist/helpers/fix-handle-tempurns.js +73 -71
  22. package/dist/helpers/fix-handle-tempurns.js.map +1 -7
  23. package/dist/helpers/fix-strip-f884s.d.ts +10 -0
  24. package/dist/helpers/fix-strip-f884s.d.ts.map +1 -0
  25. package/dist/helpers/fix-strip-f884s.js +163 -151
  26. package/dist/helpers/fix-strip-f884s.js.map +1 -7
  27. package/dist/helpers/fix.d.ts +6 -0
  28. package/dist/helpers/fix.d.ts.map +1 -0
  29. package/dist/helpers/fix.js +133 -117
  30. package/dist/helpers/fix.js.map +1 -7
  31. package/dist/helpers/validation.d.ts +9 -0
  32. package/dist/helpers/validation.d.ts.map +1 -0
  33. package/dist/helpers/validation.js +14 -16
  34. package/dist/helpers/validation.js.map +1 -7
  35. package/dist/index.d.ts +13 -0
  36. package/dist/index.d.ts.map +1 -0
  37. package/dist/index.js +1 -1
  38. package/dist/index.js.map +1 -7
  39. package/dist/mongo.d.ts +165 -0
  40. package/dist/mongo.d.ts.map +1 -0
  41. package/dist/mongo.js +603 -464
  42. package/dist/mongo.js.map +1 -7
  43. package/dist/mongoError.d.ts +2 -0
  44. package/dist/mongoError.d.ts.map +1 -0
  45. package/dist/mongoError.js +19 -0
  46. package/dist/mongoError.js.map +1 -0
  47. package/dist/mongoLog.d.ts +50 -0
  48. package/dist/mongoLog.d.ts.map +1 -0
  49. package/dist/mongoLog.js +282 -172
  50. package/dist/mongoLog.js.map +1 -7
  51. package/dist/utils.d.ts +36 -0
  52. package/dist/utils.d.ts.map +1 -0
  53. package/dist/utils.js +118 -87
  54. package/dist/utils.js.map +1 -7
  55. package/eslint.config.ts +66 -0
  56. package/package.json +23 -25
  57. package/test/amqp-error-branches.test.ts +551 -0
  58. package/{tests/amqp.healthtest.js → test/amqp.healthtest.ts} +19 -7
  59. package/{tests/amqp.tests.localtest.js → test/amqp.tests.localtest.ts} +66 -52
  60. package/{tests/helpers/conversion.test.js → test/helpers/conversion.test.ts} +39 -11
  61. package/test/helpers/fix-edge.test.ts +201 -0
  62. package/test/helpers/fix.test.ts +65 -0
  63. package/{tests/helpers/validation.test.js → test/helpers/validation.test.ts} +13 -8
  64. package/{tests/mongo-add-blob-size.test.js → test/mongo-add-blob-size.test.ts} +14 -15
  65. package/{tests/mongo-check-and-check-state.test.js → test/mongo-check-and-check-state.test.ts} +9 -9
  66. package/{tests/mongo-check-and-set-import-job-state.test.js → test/mongo-check-and-set-import-job-state.test.ts} +9 -10
  67. package/{tests/mongo-check-timeout.test.js → test/mongo-check-timeout.test.ts} +6 -9
  68. package/{tests/mongo-create-bulk.test.js → test/mongo-create-bulk.test.ts} +6 -7
  69. package/{tests/mongo-create-prio.test.js → test/mongo-create-prio.test.ts} +6 -6
  70. package/test/mongo-error-branches.test.ts +883 -0
  71. package/{tests/mongo-get-one.test.js → test/mongo-get-one.test.ts} +6 -6
  72. package/{tests/mongo-get-stream.test.js → test/mongo-get-stream.test.ts} +10 -9
  73. package/{tests/mongo-push-ids.test.js → test/mongo-push-ids.test.ts} +6 -6
  74. package/{tests/mongo-push-messages.test.js → test/mongo-push-messages.test.ts} +6 -6
  75. package/{tests/mongo-query-by-id.test.js → test/mongo-query-by-id.test.ts} +6 -9
  76. package/{tests/mongo-query.test.js → test/mongo-query.test.ts} +6 -7
  77. package/{tests/mongo-read-content.test.js → test/mongo-read-content.test.ts} +16 -9
  78. package/{tests/mongo-remove.test.js → test/mongo-remove.test.ts} +6 -8
  79. package/{tests/mongo-set-blob-size.test.js → test/mongo-set-blob-size.test.ts} +6 -6
  80. package/{tests/mongo-set-import-job-state.test.js → test/mongo-set-import-job-state.test.ts} +6 -6
  81. package/{tests/mongo-set-operation.test.js → test/mongo-set-operation.test.ts} +6 -6
  82. package/{tests/mongo-set-operations.test.js → test/mongo-set-operations.test.ts} +6 -6
  83. package/{tests/mongo-set-state.test.js → test/mongo-set-state.test.ts} +6 -6
  84. package/test/mongoLog-protect.test.ts +182 -0
  85. package/test/mongoLog.test.ts +191 -0
  86. package/{tests/testUtils.js → test/testUtils.ts} +49 -15
  87. package/test/utils.test.ts +360 -0
  88. package/tsconfig.json +62 -0
  89. package/tsconfig.test.json +17 -0
  90. package/dist/helpers/fix-utils.js +0 -39
  91. package/dist/helpers/fix-utils.js.map +0 -7
  92. package/eslint.config.js +0 -53
  93. package/tests/helpers/fix.test.js +0 -41
  94. package/tests/mongoLog.test.js +0 -84
@@ -0,0 +1,360 @@
1
+
2
+ import assert from 'node:assert';
3
+ import {test} from 'node:test';
4
+ import httpStatus from 'http-status';
5
+ import {Error as ApiError} from '@natlibfi/melinda-commons';
6
+ import {
7
+ logError,
8
+ createImportJobState,
9
+ createRecordResponseItem,
10
+ addRecordResponseItem,
11
+ addRecordResponseItems
12
+ } from '../src/utils.ts';
13
+
14
+ test('createImportJobState should return state object for valid operation and state', () => {
15
+ const result = createImportJobState('CREATE', 'EMPTY');
16
+ assert.deepStrictEqual(result, {CREATE: 'EMPTY'});
17
+ });
18
+
19
+ test('createImportJobState should return query object when queryImportJobState is true', () => {
20
+ const result = createImportJobState('CREATE', 'EMPTY', true);
21
+ assert.deepStrictEqual(result, {'importJobState.CREATE': 'EMPTY'});
22
+ });
23
+
24
+ test('createImportJobState should throw for invalid state', () => {
25
+ assert.throws(() => {
26
+ createImportJobState('CREATE', 'INVALID_STATE');
27
+ }, new Error('Invalid IMPORT_JOB_STATE'));
28
+ });
29
+
30
+ test('createImportJobState should throw for invalid operation', () => {
31
+ assert.throws(() => {
32
+ createImportJobState('INVALID_OPERATION', 'EMPTY');
33
+ }, new Error('Invalid operation'));
34
+ });
35
+
36
+ test('createRecordResponseItem should use message from responsePayload.message', () => {
37
+ const result = createRecordResponseItem({
38
+ responsePayload: {message: 'payload message'},
39
+ responseStatus: 'UPDATED'
40
+ });
41
+ assert.equal(result.message, 'payload message');
42
+ });
43
+
44
+ test('createRecordResponseItem should use string responsePayload as message', () => {
45
+ const result = createRecordResponseItem({
46
+ responsePayload: 'string payload',
47
+ responseStatus: 'UPDATED'
48
+ });
49
+ assert.equal(result.message, 'string payload');
50
+ });
51
+
52
+ test('createRecordResponseItem should use empty message when payload has no message', () => {
53
+ const result = createRecordResponseItem({
54
+ responsePayload: {ids: ['123']},
55
+ responseStatus: 'UPDATED'
56
+ });
57
+ assert.equal(result.message, '');
58
+ });
59
+
60
+ test('createRecordResponseItem should default databaseId when id is omitted', () => {
61
+ const result = createRecordResponseItem({
62
+ responsePayload: {message: 'ok'},
63
+ responseStatus: 'UPDATED'
64
+ });
65
+ assert.equal(result.databaseId, '000000000');
66
+ });
67
+
68
+ test('createRecordResponseItem should set databaseId from id when provided', () => {
69
+ const result = createRecordResponseItem({
70
+ responsePayload: {message: 'ok'},
71
+ responseStatus: 'UPDATED',
72
+ id: '12345'
73
+ });
74
+ assert.equal(result.databaseId, '12345');
75
+ });
76
+
77
+ test('createRecordResponseItem should map UPDATED, CREATED and INVALID statuses', () => {
78
+ for (const responseStatus of ['UPDATED', 'CREATED', 'INVALID']) {
79
+ const result = createRecordResponseItem({
80
+ responsePayload: {message: 'msg'},
81
+ responseStatus
82
+ });
83
+ assert.equal(result.recordStatus, responseStatus);
84
+ assert.equal(result.detailedRecordStatus, responseStatus);
85
+ assert.equal(result.message, 'msg');
86
+ }
87
+ });
88
+
89
+ test('createRecordResponseItem should map SKIPPED status', () => {
90
+ const result = createRecordResponseItem({
91
+ responsePayload: {message: 'skipped'},
92
+ responseStatus: 'SKIPPED'
93
+ });
94
+ assert.equal(result.recordStatus, 'SKIPPED');
95
+ assert.equal(result.detailedRecordStatus, 'SKIPPED');
96
+ });
97
+
98
+ test('createRecordResponseItem should map SKIPPED_UPDATE to recordStatus SKIPPED', () => {
99
+ const result = createRecordResponseItem({
100
+ responsePayload: {message: 'skipped update'},
101
+ responseStatus: 'SKIPPED_UPDATE'
102
+ });
103
+ assert.equal(result.recordStatus, 'SKIPPED');
104
+ assert.equal(result.detailedRecordStatus, 'SKIPPED_UPDATE');
105
+ });
106
+
107
+ test('createRecordResponseItem should map CONFLICT duplicate message to DUPLICATE', () => {
108
+ const result = createRecordResponseItem({
109
+ responsePayload: {
110
+ message: 'Duplicates in database: 123',
111
+ ids: ['123', '456']
112
+ },
113
+ responseStatus: httpStatus.CONFLICT,
114
+ id: '123'
115
+ });
116
+ assert.equal(result.recordStatus, 'DUPLICATE');
117
+ assert.equal(result.detailedRecordStatus, 'DUPLICATE');
118
+ assert.deepStrictEqual(result.ids, ['123', '456']);
119
+ });
120
+
121
+ test('createRecordResponseItem should map CONFLICT MatchValidation message to ERROR', () => {
122
+ const result = createRecordResponseItem({
123
+ responsePayload: {
124
+ message: 'MatchValidation for all: something',
125
+ ids: ['123']
126
+ },
127
+ responseStatus: 'CONFLICT',
128
+ id: '123'
129
+ });
130
+ assert.equal(result.recordStatus, 'ERROR');
131
+ assert.equal(result.detailedRecordStatus, 'CONFLICT');
132
+ });
133
+
134
+ test('createRecordResponseItem should attach ids to CONFLICT when id does not match', () => {
135
+ const result = createRecordResponseItem({
136
+ responsePayload: {
137
+ message: 'conflict',
138
+ ids: ['789']
139
+ },
140
+ responseStatus: httpStatus.CONFLICT,
141
+ id: '123'
142
+ });
143
+ assert.equal(result.recordStatus, 'ERROR');
144
+ assert.equal(result.detailedRecordStatus, 'CONFLICT');
145
+ assert.deepStrictEqual(result.ids, ['789']);
146
+ });
147
+
148
+ test('createRecordResponseItem should omit ids from CONFLICT when ids matches id', () => {
149
+ const result = createRecordResponseItem({
150
+ responsePayload: {
151
+ message: 'conflict',
152
+ ids: ['123']
153
+ },
154
+ responseStatus: httpStatus.CONFLICT,
155
+ id: '123'
156
+ });
157
+ assert.equal(result.recordStatus, 'ERROR');
158
+ assert.equal(result.detailedRecordStatus, 'CONFLICT');
159
+ assert.equal(Object.hasOwn(result, 'ids'), false);
160
+ });
161
+
162
+ // a missing (undefined/null) responsePayload is rejected with a clear
163
+ // message; objects and strings remain the valid payload forms
164
+ test('createRecordResponseItem should throw with a missing responsePayload', () => {
165
+ assert.throws(
166
+ () => createRecordResponseItem({responsePayload: undefined, responseStatus: 'UPDATED'}),
167
+ /responsePayload must be an object or a string!/
168
+ );
169
+ assert.throws(
170
+ () => createRecordResponseItem({responsePayload: null, responseStatus: 'UPDATED'}),
171
+ /responsePayload must be an object or a string!/
172
+ );
173
+ });
174
+
175
+ // a string payload is a documented valid form and must not be rejected by the guard
176
+ test('createRecordResponseItem accepts a string responsePayload', () => {
177
+ const item = createRecordResponseItem({responsePayload: 'Something went wrong', responseStatus: 422, id: '000000001'});
178
+ assert.equal(item.message, 'Something went wrong');
179
+ });
180
+
181
+ // for CONFLICT with an empty ids array, no `ids` field is
182
+ // attached to the response item (previously the empty array was attached
183
+ // because `ids[0] !== id` was true for an empty array).
184
+ test('createRecordResponseItem should omit ids on CONFLICT when ids is empty', () => {
185
+ const result = createRecordResponseItem({
186
+ responsePayload: {
187
+ message: 'conflict',
188
+ ids: []
189
+ },
190
+ responseStatus: httpStatus.CONFLICT,
191
+ id: '123'
192
+ });
193
+ assert.equal(result.recordStatus, 'ERROR');
194
+ assert.equal(result.detailedRecordStatus, 'CONFLICT');
195
+ assert.equal(Object.hasOwn(result, 'ids'), false);
196
+ });
197
+
198
+ test('createRecordResponseItem should map UNPROCESSABLE_ENTITY to INVALID', () => {
199
+ const result = createRecordResponseItem({
200
+ responsePayload: {
201
+ message: 'unprocessable',
202
+ ids: ['456']
203
+ },
204
+ responseStatus: httpStatus.UNPROCESSABLE_ENTITY,
205
+ id: '123'
206
+ });
207
+ assert.equal(result.recordStatus, 'INVALID');
208
+ assert.equal(result.detailedRecordStatus, 'UNPROCESSABLE_ENTITY');
209
+ assert.deepStrictEqual(result.ids, ['456']);
210
+ });
211
+
212
+ test('createRecordResponseItem should map UNPROCESSABLE_ENTITY without ids when matching', () => {
213
+ const result = createRecordResponseItem({
214
+ responsePayload: {
215
+ message: 'unprocessable',
216
+ ids: ['123']
217
+ },
218
+ responseStatus: 'UNPROCESSABLE_ENTITY',
219
+ id: '123'
220
+ });
221
+ assert.equal(result.recordStatus, 'INVALID');
222
+ assert.equal(result.detailedRecordStatus, 'UNPROCESSABLE_ENTITY');
223
+ assert.equal(Object.hasOwn(result, 'ids'), false);
224
+ });
225
+
226
+ test('createRecordResponseItem should map NOT_FOUND to ERROR', () => {
227
+ const result = createRecordResponseItem({
228
+ responsePayload: {message: 'not found'},
229
+ responseStatus: httpStatus.NOT_FOUND
230
+ });
231
+ assert.equal(result.recordStatus, 'ERROR');
232
+ assert.equal(result.detailedRecordStatus, 'NOT_FOUND');
233
+ assert.equal(result.message, 'not found');
234
+ });
235
+
236
+ test('createRecordResponseItem should map FORBIDDEN to ERROR', () => {
237
+ const result = createRecordResponseItem({
238
+ responsePayload: {message: 'forbidden'},
239
+ responseStatus: httpStatus.FORBIDDEN
240
+ });
241
+ assert.equal(result.recordStatus, 'ERROR');
242
+ assert.equal(result.detailedRecordStatus, 'FORBIDDEN');
243
+ assert.equal(result.message, 'forbidden');
244
+ });
245
+
246
+ test('createRecordResponseItem should map unknown status to ERROR with appended message', () => {
247
+ const result = createRecordResponseItem({
248
+ responsePayload: {message: 'some message'},
249
+ responseStatus: 'SOMETHING_ELSE'
250
+ });
251
+ assert.equal(result.recordStatus, 'ERROR');
252
+ assert.equal(result.detailedRecordStatus, 'SOMETHING_ELSE');
253
+ assert.equal(result.message, 'some message - Unknown recordStatus: SOMETHING_ELSE');
254
+ });
255
+
256
+ test('createRecordResponseItem should map UNKNOWN status to ERROR with ids', () => {
257
+ const result = createRecordResponseItem({
258
+ responsePayload: {
259
+ message: 'unknown',
260
+ ids: ['42']
261
+ },
262
+ responseStatus: 'UNKNOWN'
263
+ });
264
+ assert.equal(result.recordStatus, 'ERROR');
265
+ assert.equal(result.detailedRecordStatus, 'UNKNOWN');
266
+ assert.deepStrictEqual(result.ids, ['42']);
267
+ });
268
+
269
+ test('addRecordResponseItem should push the recordResponseItem via mongoOperator', async () => {
270
+ let captured: unknown;
271
+ const mongoOperator = {
272
+ pushMessages: async (args: unknown) => {
273
+ captured = args;
274
+ }
275
+ };
276
+ const recordResponseItem = {databaseId: '000000000'};
277
+ const result = await addRecordResponseItem({
278
+ recordResponseItem,
279
+ correlationId: 'corr-1',
280
+ mongoOperator
281
+ });
282
+ assert.equal(result, true);
283
+ assert.deepStrictEqual(captured, {
284
+ correlationId: 'corr-1',
285
+ messages: [recordResponseItem],
286
+ messageField: 'records'
287
+ });
288
+ });
289
+
290
+ test('addRecordResponseItem should throw for non-object input', async () => {
291
+ const mongoOperator = {
292
+ pushMessages: async () => {}
293
+ };
294
+ for (const badInput of [undefined, null, 'not-an-object', 42, [{databaseId: '1'}]]) {
295
+ await assert.rejects(
296
+ addRecordResponseItem({
297
+ recordResponseItem: badInput,
298
+ correlationId: 'corr-42',
299
+ mongoOperator
300
+ }),
301
+ new Error('RecordResponseItem is not an object!')
302
+ );
303
+ }
304
+ });
305
+
306
+ test('addRecordResponseItems should push all items in one call', async () => {
307
+ let captured: unknown;
308
+ let callCount = 0;
309
+ const mongoOperator = {
310
+ pushMessages: async (args: unknown) => {
311
+ callCount += 1;
312
+ captured = args;
313
+ }
314
+ };
315
+ const items = [
316
+ {databaseId: '1'},
317
+ {databaseId: '2'}
318
+ ];
319
+ const result = await addRecordResponseItems({
320
+ recordResponseItems: items,
321
+ correlationId: 'corr-2',
322
+ mongoOperator
323
+ });
324
+ assert.equal(result, true);
325
+ assert.equal(callCount, 1);
326
+ assert.deepStrictEqual(captured, {
327
+ correlationId: 'corr-2',
328
+ messages: items,
329
+ messageField: 'records'
330
+ });
331
+ });
332
+
333
+ test('addRecordResponseItems should throw for non-array input', async () => {
334
+ const mongoOperator = {
335
+ pushMessages: async () => {}
336
+ };
337
+ await assert.rejects(
338
+ addRecordResponseItems({
339
+ recordResponseItems: 'not-an-array',
340
+ correlationId: 'corr-3',
341
+ mongoOperator
342
+ }),
343
+ new Error('RecordResponseItems is not an array!')
344
+ );
345
+ });
346
+
347
+ test('logError should not throw for ApiError, SIGINT and regular errors', () => {
348
+ assert.doesNotThrow(() => {
349
+ logError(new ApiError(404, 'Not found'));
350
+ });
351
+ assert.doesNotThrow(() => {
352
+ logError('SIGINT');
353
+ });
354
+ assert.doesNotThrow(() => {
355
+ logError(new Error('some error'));
356
+ });
357
+ assert.doesNotThrow(() => {
358
+ logError('plain string without stack');
359
+ });
360
+ });
package/tsconfig.json ADDED
@@ -0,0 +1,62 @@
1
+ {
2
+ "include": [
3
+ "src"
4
+ ],
5
+ "exclude": [
6
+ "node_modules",
7
+ "dist"
8
+ ],
9
+ "compilerOptions": {
10
+ // File Layout
11
+ "rootDir": "./src",
12
+ "outDir": "./dist",
13
+ // Environment Settings
14
+ "module": "nodenext",
15
+ "moduleResolution": "nodenext",
16
+ "target": "esnext",
17
+ "typeRoots": [
18
+ "./node_modules/@types"
19
+ ],
20
+ "types": [
21
+ "node"
22
+ ],
23
+ "lib": [
24
+ "esnext"
25
+ ],
26
+ // Other Outputs
27
+ "sourceMap": true,
28
+ "declaration": true,
29
+ "declarationMap": true,
30
+ // Stricter Typechecking Options
31
+ "noUncheckedIndexedAccess": true,
32
+ // Style Options
33
+ "noImplicitReturns": true,
34
+ "noImplicitOverride": true,
35
+ "noUnusedLocals": true,
36
+ "noUnusedParameters": true,
37
+ "noFallthroughCasesInSwitch": true,
38
+ "noPropertyAccessFromIndexSignature": true,
39
+ // Recommended Options
40
+ "strict": true,
41
+ "isolatedModules": true,
42
+ "noUncheckedSideEffectImports": true,
43
+ "moduleDetection": "force",
44
+ "skipLibCheck": true,
45
+ "allowImportingTsExtensions": true,
46
+ "noEmit": false,
47
+ // Customized options
48
+ "allowJs": true,
49
+ "checkJs": true,
50
+ "esModuleInterop": true,
51
+ "allowUnreachableCode": false,
52
+ "strictFunctionTypes": true,
53
+ "strictNullChecks": true,
54
+ "removeComments": true,
55
+ // Only allow syntax accepted by Node >= 23.6
56
+ "erasableSyntaxOnly": true,
57
+ // Proposed options from Node docs: https://nodejs.org/api/typescript.html#type-stripping
58
+ "rewriteRelativeImportExtensions": true,
59
+ "verbatimModuleSyntax": true,
60
+ "forceConsistentCasingInFileNames": true
61
+ }
62
+ }
@@ -0,0 +1,17 @@
1
+ {
2
+ "extends": "./tsconfig.json",
3
+ "include": [
4
+ "src",
5
+ "test"
6
+ ],
7
+ "exclude": [
8
+ "node_modules",
9
+ "dist"
10
+ ],
11
+ "compilerOptions": {
12
+ // Typechecking only — never emits. The build config (tsconfig.json)
13
+ // keeps rootDir ./src so `npm run build` still emits only src/ -> dist/.
14
+ "noEmit": true,
15
+ "rootDir": "."
16
+ }
17
+ }
@@ -1,39 +0,0 @@
1
- export function removeSubfield(field, code) {
2
- if (!isNaN(field.tag) && parseInt(field.tag, 10) >= 10) {
3
- const filteredSubfields = field.subfields.filter((sf) => sf.code !== code);
4
- if (filteredSubfields.length < 1) {
5
- return false;
6
- }
7
- return {
8
- tag: field.tag,
9
- ind1: field.ind1,
10
- ind2: field.ind2,
11
- subfields: filteredSubfields
12
- };
13
- }
14
- return field;
15
- }
16
- export function sortFieldsBySubfieldValue(fields, subfieldCode) {
17
- return [...fields].sort((a, b) => {
18
- const a1value = getFirstSubfieldValue(a, subfieldCode);
19
- const b1value = getFirstSubfieldValue(b, subfieldCode);
20
- if (a1value && !b1value) {
21
- return -1;
22
- }
23
- if (!a1value && b1value) {
24
- return 1;
25
- }
26
- if (a1value > b1value) {
27
- return 1;
28
- }
29
- if (b1value > a1value) {
30
- return -1;
31
- }
32
- return 0;
33
- });
34
- function getFirstSubfieldValue(field, subfieldCode2) {
35
- const subs = field.subfields ? field.subfields.filter((subf) => subf.code === subfieldCode2) : [];
36
- return subs.length > 0 ? subs[0].value : "";
37
- }
38
- }
39
- //# sourceMappingURL=fix-utils.js.map
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../src/helpers/fix-utils.js"],
4
- "sourcesContent": ["export function removeSubfield(field, code) {\n\n // Handle non-numeric fields, and fields with a numeric tag of 010 and greater\n // Aleph's FMT as a controlfield might be a problem\n if (!isNaN(field.tag) && parseInt(field.tag, 10) >= 10) {\n\n const filteredSubfields = field.subfields.filter(sf => sf.code !== code);\n\n // Remove whole field if there are no subfields left\n if (filteredSubfields.length < 1) {\n return false;\n }\n\n return {\n tag: field.tag,\n ind1: field.ind1,\n ind2: field.ind2,\n subfields: filteredSubfields\n };\n }\n // return controlFields as is\n return field;\n}\n\n\n// sort fields by value of each fields first subfield with subfielCode\nexport function sortFieldsBySubfieldValue(fields, subfieldCode) {\n return [...fields].sort((a, b) => {\n const a1value = getFirstSubfieldValue(a, subfieldCode);\n const b1value = getFirstSubfieldValue(b, subfieldCode);\n if (a1value && !b1value) {\n return -1;\n }\n if (!a1value && b1value) {\n return 1;\n }\n if (a1value > b1value) {\n return 1;\n }\n if (b1value > a1value) {\n return -1;\n }\n return 0;\n });\n // get value for the for instance of subfield with subfieldCode\n function getFirstSubfieldValue(field, subfieldCode) {\n const subs = field.subfields ? field.subfields.filter(subf => subf.code === subfieldCode) : [];\n return subs.length > 0 ? subs[0].value : '';\n }\n}\n"],
5
- "mappings": "AAAO,gBAAS,eAAe,OAAO,MAAM;AAI1C,MAAI,CAAC,MAAM,MAAM,GAAG,KAAK,SAAS,MAAM,KAAK,EAAE,KAAK,IAAI;AAEtD,UAAM,oBAAoB,MAAM,UAAU,OAAO,QAAM,GAAG,SAAS,IAAI;AAGvE,QAAI,kBAAkB,SAAS,GAAG;AAChC,aAAO;AAAA,IACT;AAEA,WAAO;AAAA,MACL,KAAK,MAAM;AAAA,MACX,MAAM,MAAM;AAAA,MACZ,MAAM,MAAM;AAAA,MACZ,WAAW;AAAA,IACb;AAAA,EACF;AAEA,SAAO;AACT;AAIO,gBAAS,0BAA0B,QAAQ,cAAc;AAC9D,SAAO,CAAC,GAAG,MAAM,EAAE,KAAK,CAAC,GAAG,MAAM;AAChC,UAAM,UAAU,sBAAsB,GAAG,YAAY;AACrD,UAAM,UAAU,sBAAsB,GAAG,YAAY;AACrD,QAAI,WAAW,CAAC,SAAS;AACvB,aAAO;AAAA,IACT;AACA,QAAI,CAAC,WAAW,SAAS;AACvB,aAAO;AAAA,IACT;AACA,QAAI,UAAU,SAAS;AACrB,aAAO;AAAA,IACT;AACA,QAAI,UAAU,SAAS;AACrB,aAAO;AAAA,IACT;AACA,WAAO;AAAA,EACT,CAAC;AAED,WAAS,sBAAsB,OAAOA,eAAc;AAClD,UAAM,OAAO,MAAM,YAAY,MAAM,UAAU,OAAO,UAAQ,KAAK,SAASA,aAAY,IAAI,CAAC;AAC7F,WAAO,KAAK,SAAS,IAAI,KAAK,CAAC,EAAE,QAAQ;AAAA,EAC3C;AACF;",
6
- "names": ["subfieldCode"]
7
- }
package/eslint.config.js DELETED
@@ -1,53 +0,0 @@
1
- // Eslint configuration object for src
2
- const configSrc = {
3
- files: [
4
- "src/*",
5
- "tests/*"
6
- ],
7
- linterOptions: {
8
- reportUnusedDisableDirectives: true,
9
- },
10
- rules: {
11
- "no-console": "warn",
12
- "eqeqeq": ["error", "always"],
13
- "no-const-assign": "error",
14
- "max-depth": ["warn", 4],
15
- "max-lines": ["warn", 500],
16
- "max-lines-per-function": ["warn", {"max": 100}],
17
- "no-else-return": ["error", {allowElseIf: false}],
18
- "no-plusplus": [
19
- "error",
20
- {
21
- "allowForLoopAfterthoughts": true
22
- }
23
- ],
24
- "array-callback-return": [
25
- "error",
26
- {
27
- "checkForEach": false
28
- }
29
- ],
30
- "no-unused-vars": [
31
- "error",
32
- {
33
- "argsIgnorePattern": "next"
34
- }
35
- ],
36
- "no-warning-comments": "off"
37
- }
38
- };
39
-
40
- // Eslint configuration object for globally ignoring .js files
41
- // - ignore all files that start with a dot
42
- // - ignore all files inside directories named 'dist'
43
- const configIgnores = {
44
- ignores: [
45
- "**/.*",
46
- "**/dist/"
47
- ]
48
- };
49
-
50
- export default [
51
- configSrc,
52
- configIgnores
53
- ];
@@ -1,41 +0,0 @@
1
- import assert from 'node:assert';
2
- import createDebugLogger from 'debug';
3
- import {MarcRecord} from '@natlibfi/marc-record';
4
- import {READERS} from '@natlibfi/fixura';
5
- import generateTests from '@natlibfi/fixugen';
6
- import {fixRecord} from '../../src/helpers/fix.js';
7
- import * as fixSettings from '../../src/helpers/fix-constants.js';
8
- // import inspect from 'util';
9
-
10
- const debug = createDebugLogger('@natlibfi/melinda-rest-api-commons:fix:test');
11
- const debugData = debug.extend('data');
12
-
13
- generateTests({
14
- callback,
15
- path: [import.meta.dirname, '..', '..', 'test-fixtures', 'fix'],
16
- recurse: true,
17
- useMetadataFile: true,
18
- fixura: {
19
- failWhenNotFound: false,
20
- reader: READERS.JSON
21
- }
22
- });
23
-
24
- function callback({getFixture, settings = undefined}) {
25
- if (settings !== undefined && fixSettings[settings] === undefined) {
26
- throw new Error(`There are no settings ${settings} defined!`);
27
- }
28
- const runSettings = fixSettings[settings] || settings;
29
-
30
- const record = new MarcRecord(getFixture('record.json'), {subfieldValues: false});
31
- const expectedRecord = getFixture('expectedRecord.json');
32
-
33
- debug(`Running fixer with settings ${settings}.`);
34
- debugData(JSON.stringify(runSettings, null, 2));
35
-
36
- const resultRecord = fixRecord(record, runSettings);
37
- debugData(`Result: ${JSON.stringify(resultRecord)}`);
38
- debugData(`Expected: ${JSON.stringify(expectedRecord)}`);
39
- assert.deepStrictEqual(resultRecord, expectedRecord);
40
-
41
- }
@@ -1,84 +0,0 @@
1
- import assert from 'node:assert';
2
- import {READERS} from '@natlibfi/fixura';
3
- import generateTests from '@natlibfi/fixugen';
4
- import mongoFixturesFactory from '@natlibfi/fixura-mongo';
5
- import createMongoLogOperator from '../src/mongoLog.js';
6
-
7
- let mongoFixtures; // eslint-disable-line functional/no-let
8
-
9
- generateTests({
10
- callback,
11
- path: [import.meta.dirname, '..', 'test-fixtures', 'mongoLog'],
12
- recurse: false,
13
- useMetadataFile: true,
14
- fixura: {
15
- failWhenNotFound: true,
16
- reader: READERS.JSON
17
- },
18
- hooks: {
19
- before: async () => {
20
- await initMongofixtures();
21
- },
22
- beforeEach: () => mongoFixtures.clear(),
23
- afterEach: () => mongoFixtures.clear(),
24
- after: async () => {
25
- await mongoFixtures.close();
26
- }
27
- }
28
- });
29
-
30
- async function initMongofixtures() {
31
- mongoFixtures = await mongoFixturesFactory({
32
- rootPath: [import.meta.dirname, '..', 'test-fixtures', 'mongoLog'],
33
- gridFS: {bucketName: 'blobs'},
34
- useObjectId: true,
35
- format: {
36
- creationTime: v => new Date(v),
37
- modificationTime: v => new Date(v)
38
- }
39
- });
40
- }
41
-
42
- async function callback({
43
- getFixture,
44
- functionName,
45
- params,
46
- preFillDb = false
47
- }) {
48
- const mongoUri = await mongoFixtures.getUri();
49
- const mongoLogOperator = await createMongoLogOperator(mongoUri, '');
50
- const expectedResult = await getFixture('expectedResult.json');
51
- // console.log(typeof mongoUri); // eslint-disable-line
52
-
53
- if (preFillDb) {
54
- await mongoFixtures.populate(getFixture('dbContents.json'));
55
- }
56
-
57
- if (functionName === 'addLogItem') {
58
- await mongoLogOperator.addLogItem(params);
59
- const dump = await mongoFixtures.dump();
60
- return assert.deepStrictEqual(dump.logs[0]['0'], expectedResult);
61
- }
62
-
63
- if (functionName === 'getListOfCatalogers') {
64
- const result = await mongoLogOperator.getListOfCatalogers();
65
- // console.log(result); // eslint-disable-line
66
-
67
- return assert.deepEqual(result, expectedResult);
68
- }
69
-
70
- if (functionName === 'getExpandedListOfLogs') {
71
- const result = await mongoLogOperator.getExpandedListOfLogs(params);
72
- // console.log(result); // eslint-disable-line
73
-
74
- return assert.deepEqual(result, expectedResult);
75
- }
76
-
77
- if (functionName === 'getListOfLogs') {
78
- const result = await mongoLogOperator.getListOfLogs(params);
79
- // console.log(result); // eslint-disable-line
80
- return assert.deepEqual(result, expectedResult);
81
- }
82
- throw new Error(`Unknown functionName: ${functionName}`);
83
- }
84
-