@natlibfi/melinda-rest-api-commons 6.1.0-alpha.0 → 6.2.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. package/.github/workflows/melinda-node-tests-and-publish.yml +4 -2
  2. package/README.md +211 -14
  3. package/dist/amqp.d.ts +41 -0
  4. package/dist/amqp.d.ts.map +1 -0
  5. package/dist/amqp.js +251 -235
  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 -64
  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 +161 -163
  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 -121
  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 +595 -547
  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 +274 -242
  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 +112 -110
  54. package/dist/utils.js.map +1 -7
  55. package/eslint.config.ts +66 -0
  56. package/package.json +17 -11
  57. package/{tests/amqp-error-branches.test.js → test/amqp-error-branches.test.ts} +135 -61
  58. package/{tests/amqp.healthtest.js → test/amqp.healthtest.ts} +19 -11
  59. package/{tests/amqp.tests.localtest.js → test/amqp.tests.localtest.ts} +54 -35
  60. package/{tests/helpers/conversion.test.js → test/helpers/conversion.test.ts} +26 -14
  61. package/{tests/helpers/fix-edge.test.js → test/helpers/fix-edge.test.ts} +16 -12
  62. package/{tests/helpers/fix.test.js → test/helpers/fix.test.ts} +14 -8
  63. package/{tests/helpers/validation.test.js → test/helpers/validation.test.ts} +7 -6
  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} +6 -8
  66. package/{tests/mongo-check-and-set-import-job-state.test.js → test/mongo-check-and-set-import-job-state.test.ts} +6 -9
  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/{tests/mongo-error-branches.test.js → test/mongo-error-branches.test.ts} +166 -65
  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} +6 -8
  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} +6 -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/{tests/mongoLog-protect.test.js → test/mongoLog-protect.test.ts} +18 -17
  85. package/{tests/mongoLog.test.js → test/mongoLog.test.ts} +8 -8
  86. package/{tests/testUtils.js → test/testUtils.ts} +49 -15
  87. package/{tests/utils.test.js → test/utils.test.ts} +5 -5
  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
@@ -3,8 +3,11 @@ import createDebugLogger from 'debug';
3
3
  import {promisify} from 'util';
4
4
  import {READERS} from '@natlibfi/fixura';
5
5
  import generateTests from '@natlibfi/fixugen';
6
+ import type {CallbackArgs} from '@natlibfi/fixugen';
6
7
  import {Error as ApiError} from '@natlibfi/melinda-commons';
7
- import {amqpFactory} from '../src/index.js';
8
+ import type {GetMessage, Message} from 'amqplib';
9
+ import {amqpFactory} from '../src/index.ts';
10
+ import type {AmqpOperator, QueueItemMessagePayload, QueueItemRecordPayload, SendToQueueParams} from '../src/amqp.ts';
8
11
 
9
12
  const setTimeoutPromise = promisify(setTimeout);
10
13
  const debug = createDebugLogger('@natlibfi/melinda-rest-api-commons:amqp:test');
@@ -18,8 +21,7 @@ const testData = {
18
21
 
19
22
  debug(`Testing amqp against a local AMQP instance - we'll need some kind of mockup for this`);
20
23
  const amqpUrl = 'amqp://127.0.0.1:5672/';
21
- // eslint-disable-next-line functional/no-let
22
- let amqpOperator;
24
+ let amqpOperator: AmqpOperator;
23
25
 
24
26
  generateTests({
25
27
  callback,
@@ -48,8 +50,15 @@ generateTests({
48
50
  }
49
51
  });
50
52
 
51
- // eslint-disable-next-line max-statements
52
- async function callback({
53
+ /**
54
+ * One fixture case. See the fixture metadata files in test-fixtures/amqp
55
+ * for the possible keys (getFixture, expectToFail, expectedErrorStatus,
56
+ * ackMessages, nackMessages, checkNextMessage, checkQueueStyle, queue,
57
+ * sentToQueue, expectedMessageCount, removeQueue, expectedErrorMessage,
58
+ * expectApiError, expectFalseCheckResult).
59
+ */
60
+ async function callback(callbackParams: CallbackArgs) {
61
+ const {
53
62
  getFixture,
54
63
  expectToFail = false,
55
64
  expectedErrorStatus = '',
@@ -57,14 +66,16 @@ async function callback({
57
66
  nackMessages = false,
58
67
  checkNextMessage = false,
59
68
  checkQueueStyle = false,
60
- queue = testData.queue,
69
+ queue: queueFromFixture = testData.queue,
61
70
  sentToQueue,
62
71
  expectedMessageCount,
63
72
  removeQueue = false,
64
73
  expectedErrorMessage = undefined,
65
74
  expectApiError = false,
66
75
  expectFalseCheckResult = false
67
- }) {
76
+ } = callbackParams;
77
+ // the fixture contract passes the queue name as a string
78
+ const queue = queueFromFixture as string;
68
79
  try {
69
80
  await sendMessagesToQueue();
70
81
 
@@ -79,7 +90,7 @@ async function callback({
79
90
  assert.equal(messageCount, expectedMessageCount);
80
91
 
81
92
  if (checkNextMessage) {
82
- const {headers, records} = await queueCheckNextMessage();
93
+ const {headers, records} = (await queueCheckNextMessage()) as QueueItemRecordPayload;
83
94
  const nextMessage = {headers, records};
84
95
  const expectedNextMessage = getFixture('expectedMessage.json');
85
96
  assert.deepStrictEqual(
@@ -97,15 +108,19 @@ async function callback({
97
108
  testErrors(error);
98
109
  }
99
110
 
100
- function testErrors(error) {
111
+ /**
112
+ * @param error
113
+ */
114
+ function testErrors(error: unknown) {
101
115
  const isApiError = error instanceof ApiError;
102
116
  if (expectApiError) {
103
117
  assert.equal(isApiError, true);
104
118
  debug(`We expected and got an ApiError`);
105
- assert.equal(error.status, expectedErrorStatus);
119
+ const apiError = error as ApiError;
120
+ assert.equal(apiError.status, expectedErrorStatus);
106
121
 
107
122
  if (expectedErrorMessage) {
108
- assert.equal(error.payload, expectedErrorMessage);
123
+ assert.equal(apiError.payload, expectedErrorMessage);
109
124
  return;
110
125
  }
111
126
 
@@ -113,26 +128,26 @@ async function callback({
113
128
  }
114
129
  assert.equal(isApiError, false);
115
130
  debug(`We expected and got an non-ApiError`);
116
- debug(`Error is a ${error.constructor.name}`);
131
+ const maybeError = error as Error;
132
+ debug(`Error is a ${maybeError.constructor.name}`);
117
133
  }
118
134
 
119
135
  function queueRemoval() {
120
136
  if (removeQueue) {
121
- return amqpOperator.removeQueue(removeQueue);
137
+ return amqpOperator.removeQueue(removeQueue as string);
122
138
  }
123
139
 
124
140
  return;
125
141
  }
126
142
 
127
- function queueCheckNextMessage() {
143
+ function queueCheckNextMessage(): Promise<QueueItemRecordPayload> | false {
128
144
  if (checkNextMessage) {
129
- return amqpOperator.consumeOne(testData.queue, true);
145
+ return amqpOperator.consumeOne(testData.queue, true) as Promise<QueueItemRecordPayload>;
130
146
  }
131
147
 
132
148
  return false;
133
149
  }
134
150
 
135
- // eslint-disable-next-line max-statements
136
151
  async function checkQueue() {
137
152
  debug(`checkQueueStyle: ${checkQueueStyle}`);
138
153
 
@@ -144,18 +159,19 @@ async function callback({
144
159
  return;
145
160
  }
146
161
 
147
- assert.equal(Object.hasOwn(result, 'headers'), true);
148
- assert.equal(Object.hasOwn(result, 'records'), true);
149
- assert.equal(Object.hasOwn(result, 'messages'), true);
150
- assert.equal(result.records.length, 1);
151
- assert.equal(result.messages.length, 1);
162
+ const recordResult = result as QueueItemRecordPayload;
163
+ assert.equal(Object.hasOwn(recordResult, 'headers'), true);
164
+ assert.equal(Object.hasOwn(recordResult, 'records'), true);
165
+ assert.equal(Object.hasOwn(recordResult, 'messages'), true);
166
+ assert.equal(recordResult.records.length, 1);
167
+ assert.equal(recordResult.messages.length, 1);
152
168
 
153
169
  return;
154
170
  }
155
171
 
156
172
  if (checkQueueStyle === 'oneNotRecord') {
157
173
  const result = await amqpOperator.checkQueue({queue, style: 'one', toRecord: false, purge: false});
158
- const {fields} = result;
174
+ const {fields} = result as GetMessage;
159
175
 
160
176
  if (expectFalseCheckResult) {
161
177
  assert.strictEqual(result, false);
@@ -178,14 +194,15 @@ async function callback({
178
194
  return;
179
195
  }
180
196
 
181
- assert.equal(Object.hasOwn(result, 'headers'), true);
182
- assert.equal(Object.hasOwn(result, 'records'), true);
183
- assert.equal(Object.hasOwn(result, 'messages'), true);
184
- assert.equal(result.records.length, 3);
185
- assert.equal(result.messages.length, 3);
197
+ const recordResult = result as QueueItemRecordPayload;
198
+ assert.equal(Object.hasOwn(recordResult, 'headers'), true);
199
+ assert.equal(Object.hasOwn(recordResult, 'records'), true);
200
+ assert.equal(Object.hasOwn(recordResult, 'messages'), true);
201
+ assert.equal(recordResult.records.length, 3);
202
+ assert.equal(recordResult.messages.length, 3);
186
203
  const expectedResult = getFixture('expectedResult.json');
187
204
  assert.deepStrictEqual(
188
- JSON.parse(JSON.stringify(result.records)),
205
+ JSON.parse(JSON.stringify(recordResult.records)),
189
206
  expectedResult,
190
207
  );
191
208
 
@@ -200,11 +217,13 @@ async function callback({
200
217
  return;
201
218
  }
202
219
 
203
- assert.equal(Object.hasOwn(result, 'headers'), true);
204
- assert.equal(Object.hasOwn(result, 'messages'), true);
205
- assert.equal(result.messages.length, 3);
220
+ const messageResult = result as QueueItemMessagePayload;
221
+ assert.equal(Object.hasOwn(messageResult, 'headers'), true);
222
+ assert.equal(Object.hasOwn(messageResult, 'messages'), true);
223
+ assert.equal(messageResult.messages.length, 3);
206
224
 
207
- const [{fields}] = result.messages;
225
+ const [firstMessage] = messageResult.messages as [Message, ...Message[]];
226
+ const {fields} = firstMessage;
208
227
 
209
228
  assert.equal(typeof fields.deliveryTag, 'number');
210
229
  assert.equal(typeof fields.messageCount, 'number');
@@ -228,14 +247,14 @@ async function callback({
228
247
  async function ackOrNackMessages() {
229
248
  if (ackMessages) {
230
249
  const message = await amqpOperator.consumeOne(testData.queue, false);
231
- await amqpOperator.ackMessages([message]);
250
+ await amqpOperator.ackMessages([message as GetMessage]);
232
251
 
233
252
  return setTimeoutPromise(10);
234
253
  }
235
254
 
236
255
  if (nackMessages) {
237
256
  const message = await amqpOperator.consumeOne(testData.queue, false);
238
- await amqpOperator.nackMessages([message]);
257
+ await amqpOperator.nackMessages([message as GetMessage]);
239
258
 
240
259
  return setTimeoutPromise(10);
241
260
  }
@@ -245,7 +264,7 @@ async function callback({
245
264
 
246
265
  async function sendMessagesToQueue() {
247
266
  if (sentToQueue) {
248
- const messages = getFixture('input.json');
267
+ const messages = getFixture('input.json') as SendToQueueParams[];
249
268
  // {queue, correlationId, headers, data}
250
269
 
251
270
  const promises = messages.map(message => amqpOperator.sendToQueue(message));
@@ -1,12 +1,11 @@
1
-
2
-
3
1
  import assert from 'node:assert';
4
2
  import {describe, it} from 'node:test';
5
3
  import fixtureFactory from '@natlibfi/fixura';
6
4
  import {MarcRecord} from '@natlibfi/marc-record';
5
+ import type {MarcRecordObject} from '@natlibfi/marc-record';
7
6
  import {Error as ConversionError} from '@natlibfi/melinda-commons';
8
- import createConversionService from '../../src/helpers/conversion.js';
9
- import {CONVERSION_FORMATS} from '../../src/constants.js';
7
+ import createConversionService from '../../src/helpers/conversion.ts';
8
+ import {CONVERSION_FORMATS} from '../../src/constants.ts';
10
9
 
11
10
  describe('services/conversion', () => {
12
11
  const {getFixture} = fixtureFactory({
@@ -20,11 +19,11 @@ describe('services/conversion', () => {
20
19
  });
21
20
  const conversionService = createConversionService();
22
21
 
23
- const marcRecord = new MarcRecord(JSON.parse(getFixture({components: ['json1']})), {subfieldValues: false});
24
- const marcXml = getFixture({components: ['marcxml1']});
25
- const iso2709 = getFixture({components: ['iso2709_1']});
26
- const json = getFixture({components: ['json1']});
27
- const alephSeq = getFixture({components: ['aleph_sequential']});
22
+ const marcRecord = new MarcRecord(JSON.parse(getFixture({components: ['json1']}) as string) as MarcRecordObject, {subfieldValues: false});
23
+ const marcXml = getFixture({components: ['marcxml1']}) as string;
24
+ const iso2709 = getFixture({components: ['iso2709_1']}) as string;
25
+ const json = getFixture({components: ['json1']}) as string;
26
+ const alephSeq = getFixture({components: ['aleph_sequential']}) as string;
28
27
 
29
28
 
30
29
  describe('factory', () => {
@@ -38,11 +37,16 @@ describe('services/conversion', () => {
38
37
 
39
38
  describe('#serialize', () => {
40
39
  it('Should throw because of unsupported format', () => {
40
+ let threw = false;
41
41
  try {
42
- conversionService.serialize();
42
+ // the undefined inputs are the point of this test: serialize must
43
+ // throw a ConversionError for an unsupported format, not a TypeError
44
+ conversionService.serialize(undefined as never, undefined as never);
43
45
  } catch (error) {
46
+ threw = true;
44
47
  assert(error instanceof ConversionError);
45
48
  }
49
+ assert.equal(threw, true);
46
50
  });
47
51
 
48
52
  it('Should serialize to MARCXML', () => {
@@ -68,15 +72,15 @@ describe('services/conversion', () => {
68
72
  it('Should rewrap a plain (non-ConversionError) serializer error into a ConversionError with 400', () => {
69
73
  // a plain {} makes MARCXML.to throw a TypeError, which serialize must
70
74
  // rewrap into a ConversionError 400 (not propagate the raw TypeError)
71
- // eslint-disable-next-line functional/no-let
72
75
  let threw = false;
73
76
  try {
74
- conversionService.serialize({}, CONVERSION_FORMATS.MARCXML);
77
+ conversionService.serialize({} as never, CONVERSION_FORMATS.MARCXML);
75
78
  } catch (error) {
76
79
  threw = true;
77
80
  assert(error instanceof ConversionError);
78
81
  assert.equal(error.status, 400);
79
- assert.ok(error.payload.includes('Error while serializing record.'));
82
+ // the payload is a string here: 'Error while serializing record. ...'
83
+ assert.ok((error.payload as string).includes('Error while serializing record.'));
80
84
  }
81
85
  assert.equal(threw, true);
82
86
  });
@@ -85,11 +89,16 @@ describe('services/conversion', () => {
85
89
 
86
90
  describe('#unserialize', () => {
87
91
  it('Should throw because of unsupported format', () => {
92
+ let threw = false;
88
93
  try {
89
- conversionService.unserialize();
94
+ // the undefined inputs are the point of this test: unserialize must
95
+ // throw a ConversionError for an unsupported format, not a TypeError
96
+ conversionService.unserialize(undefined as never, undefined as never);
90
97
  } catch (error) {
98
+ threw = true;
91
99
  assert(error instanceof ConversionError);
92
100
  }
101
+ assert.equal(threw, true);
93
102
  });
94
103
 
95
104
  it('Should unserialize from MARCXML', async () => {
@@ -114,11 +123,14 @@ describe('services/conversion', () => {
114
123
 
115
124
 
116
125
  it('Should throw because the record could not be unserialized', () => {
126
+ let threw = false;
117
127
  try {
118
128
  conversionService.unserialize('', CONVERSION_FORMATS.JSON);
119
129
  } catch (error) {
130
+ threw = true;
120
131
  assert(error instanceof ConversionError);
121
132
  }
133
+ assert.equal(threw, true);
122
134
  });
123
135
  });
124
136
  });
@@ -3,8 +3,9 @@
3
3
  import assert from 'node:assert';
4
4
  import {test} from 'node:test';
5
5
  import {MarcRecord} from '@natlibfi/marc-record';
6
- import {fixRecord} from '../../src/helpers/fix.js';
7
- import {BIB_STRIP_F884S_SETTINGS, BIB_F035_TO_SID} from '../../src/helpers/fix-constants.js';
6
+ import type {MarcField} from '@natlibfi/marc-record';
7
+ import {fixRecord} from '../../src/helpers/fix.ts';
8
+ import {BIB_STRIP_F884S_SETTINGS, BIB_F035_TO_SID} from '../../src/helpers/fix-constants.ts';
8
9
 
9
10
  // a Melinda f884 (tag 884, $5 MELINDA, $a + $g present) that
10
11
  // has NO $k subfield. findSource/findHash used to call `sfK.replace(...)` on
@@ -52,7 +53,8 @@ test('fixRecord handles Melinda f884 without $k subfield without crashing', () =
52
53
  const result = fixRecord(record, BIB_STRIP_F884S_SETTINGS);
53
54
 
54
55
  // Both Melinda f884s survive (they are not identical, so uniq keeps both)
55
- const f884s = result.fields.filter((f) => f.tag === '884');
56
+ // these are data fields: mirrors the JSDoc baseline MarcField[] cast
57
+ const f884s = (result.fields as MarcField[]).filter((f) => f.tag === '884');
56
58
  assert.equal(f884s.length, 2);
57
59
 
58
60
  // The field WITHOUT $k still has its $a, $g and $5 MELINDA
@@ -62,8 +64,8 @@ test('fixRecord handles Melinda f884 without $k subfield without crashing', () =
62
64
  noK.subfields.map((s) => s.code).sort(),
63
65
  ['5', 'a', 'g']
64
66
  );
65
- const gNoK = noK.subfields.find((s) => s.code === 'g').value;
66
- const aNoK = noK.subfields.find((s) => s.code === 'a').value;
67
+ const gNoK = noK.subfields.find((s) => s.code === 'g')?.value;
68
+ const aNoK = noK.subfields.find((s) => s.code === 'a')?.value;
67
69
  assert.equal(aNoK, 'ONIX3 to MARC transformation');
68
70
  assert.equal(gNoK, '20220101');
69
71
 
@@ -74,8 +76,8 @@ test('fixRecord handles Melinda f884 without $k subfield without crashing', () =
74
76
  withK.subfields.map((s) => s.code).sort(),
75
77
  ['5', 'a', 'g', 'k']
76
78
  );
77
- assert.equal(withK.subfields.find((s) => s.code === 'g').value, '20000718');
78
- assert.equal(withK.subfields.find((s) => s.code === 'k').value,
79
+ assert.equal(withK.subfields.find((s) => s.code === 'g')?.value, '20000718');
80
+ assert.equal(withK.subfields.find((s) => s.code === 'k')?.value,
79
81
  'SRC_4:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa');
80
82
  });
81
83
 
@@ -146,11 +148,12 @@ test('fixRecord ignores an existing SID field whose $b is not in fSIDFilters and
146
148
  }, {subfieldValues: false});
147
149
 
148
150
  const result = fixRecord(record, {generateMissingSIDs: BIB_F035_TO_SID});
149
- const sids = result.fields.filter((f) => f.tag === 'SID');
151
+ // these are data fields: mirrors the JSDoc baseline MarcField[] cast
152
+ const sids = (result.fields as MarcField[]).filter((f) => f.tag === 'SID');
150
153
  assert.equal(sids.length, 2);
151
154
  const generated = sids.find((f) => f.subfields.some((s) => s.code === 'b' && s.value === 'FI-BTJ'));
152
155
  assert.ok(generated, 'a new SID with $b FI-BTJ should have been generated');
153
- assert.equal(generated.subfields.find((s) => s.code === 'c').value, '12345');
156
+ assert.equal(generated.subfields.find((s) => s.code === 'c')?.value, '12345');
154
157
  });
155
158
 
156
159
  test('fixRecord ignores an existing SID field with a matching $b but missing $c and generates the SID from the f035', () => {
@@ -173,12 +176,13 @@ test('fixRecord ignores an existing SID field with a matching $b but missing $c
173
176
  }, {subfieldValues: false});
174
177
 
175
178
  const result = fixRecord(record, {generateMissingSIDs: BIB_F035_TO_SID});
176
- const sids = result.fields.filter((f) => f.tag === 'SID');
179
+ // these are data fields: mirrors the JSDoc baseline MarcField[] cast
180
+ const sids = (result.fields as MarcField[]).filter((f) => f.tag === 'SID');
177
181
  assert.equal(sids.length, 2);
178
182
  const generated = sids.find((f) => f.subfields.some((s) => s.code === 'c'));
179
183
  assert.ok(generated, 'a generated SID with $c should exist');
180
- assert.equal(generated.subfields.find((s) => s.code === 'b').value, 'FI-BTJ');
181
- assert.equal(generated.subfields.find((s) => s.code === 'c').value, '12345');
184
+ assert.equal(generated.subfields.find((s) => s.code === 'b')?.value, 'FI-BTJ');
185
+ assert.equal(generated.subfields.find((s) => s.code === 'c')?.value, '12345');
182
186
  });
183
187
 
184
188
  test('fixRecord adds no SID when the f035 $a matches no f035Filter', () => {
@@ -1,15 +1,20 @@
1
1
  import assert from 'node:assert';
2
2
  import createDebugLogger from 'debug';
3
3
  import {MarcRecord} from '@natlibfi/marc-record';
4
+ import type {MarcRecordObject} from '@natlibfi/marc-record';
4
5
  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';
6
+ import generateTests, {type CallbackArgs} from '@natlibfi/fixugen';
7
+ import {fixRecord} from '../../src/helpers/fix.ts';
8
+ import * as fixSettings from '../../src/helpers/fix-constants.ts';
9
+ import type {FixSettings} from '../../src/helpers/fix-constants.ts';
8
10
  // import inspect from 'util';
9
11
 
10
12
  const debug = createDebugLogger('@natlibfi/melinda-rest-api-commons:fix:test');
11
13
  const debugData = debug.extend('data');
12
14
 
15
+ // the settings names usable via metadata.json
16
+ type SettingsKey = 'BIB_FORMAT_SETTINGS' | 'BIB_PREVALIDATION_FIX_SETTINGS' | 'BIB_POSTMERGE_FIX_SETTINGS' | 'BIB_PREIMPORT_FIX_SETTINGS' | 'AUTNAME_PREIMPORT_FIX_SETTINGS' | 'BIB_HANDLE_TEMP_URNS_SETTINGS' | 'BIB_STRIP_F884S_SETTINGS' | 'BIB_STRIP_F984S_SETTINGS' | 'BIB_STRIP_MELINDA_TEMP_SUBFIELDS_SETTINGS';
17
+
13
18
  generateTests({
14
19
  callback,
15
20
  path: [import.meta.dirname, '..', '..', 'test-fixtures', 'fix'],
@@ -21,15 +26,16 @@ generateTests({
21
26
  }
22
27
  });
23
28
 
24
- function callback({getFixture, settings = undefined}) {
29
+ function callback(callbackParams: CallbackArgs) {
30
+ const {getFixture, settings = undefined} = callbackParams;
25
31
  if (
26
32
  settings !== undefined
27
33
  && typeof settings !== 'object'
28
- && fixSettings[settings] === undefined
34
+ && (fixSettings[settings as SettingsKey]) === undefined
29
35
  ) {
30
36
  throw new Error(`There are no settings ${settings} defined!`);
31
37
  }
32
- let runSettings = fixSettings[settings] || settings;
38
+ let runSettings: FixSettings | undefined = (fixSettings[settings as SettingsKey]) || (settings as FixSettings);
33
39
  // metadata.json is plain JSON, so f035Filters may contain string
34
40
  // patterns which fix.js cannot use as-is; convert them to RegExp
35
41
  if (runSettings && runSettings.generateMissingSIDs) {
@@ -38,14 +44,14 @@ function callback({getFixture, settings = undefined}) {
38
44
  generateMissingSIDs: {
39
45
  ...runSettings.generateMissingSIDs,
40
46
  f035Filters: (runSettings.generateMissingSIDs.f035Filters || []).map(
41
- filter => (typeof filter === 'string' ? new RegExp(filter) : filter)
47
+ (filter): RegExp => (typeof filter === 'string' ? new RegExp(filter) : filter)
42
48
  ),
43
49
  fSIDFilters: runSettings.generateMissingSIDs.fSIDFilters
44
50
  }
45
51
  };
46
52
  }
47
53
 
48
- const record = new MarcRecord(getFixture('record.json'), {subfieldValues: false});
54
+ const record = new MarcRecord(getFixture('record.json') as MarcRecordObject, {subfieldValues: false});
49
55
  const expectedRecord = getFixture('expectedRecord.json');
50
56
 
51
57
  debug(`Running fixer with settings ${settings}.`);
@@ -2,7 +2,9 @@ import assert from 'node:assert';
2
2
  import {describe, it} from 'node:test';
3
3
  import fixtureFactory, {READERS} from '@natlibfi/fixura';
4
4
  import {MarcRecord} from '@natlibfi/marc-record';
5
- import createValidator from '../../src/helpers/validation.js';
5
+ import type {MarcRecordObject} from '@natlibfi/marc-record';
6
+
7
+ import createValidator from '../../src/helpers/validation.ts';
6
8
 
7
9
  describe('services/validate', () => {
8
10
  const FIXTURES_PATH = [
@@ -22,14 +24,14 @@ describe('services/validate', () => {
22
24
  'in',
23
25
  'f003-fi-melinda.json'
24
26
  ]
25
- }));
27
+ }) as MarcRecordObject);
26
28
  const result = await validator(record.toObject());
27
29
  const {record: expectedRecord, ...rest} = getFixture({
28
30
  components: [
29
31
  'out',
30
32
  'f003-fi-melinda.json'
31
33
  ]
32
- });
34
+ }) as Record<string, any>;
33
35
  const {_validationOptions, ...expectedRecordData} = expectedRecord;
34
36
  const {record: actualRecord, ...actualRest} = result;
35
37
  assert.deepStrictEqual(actualRest, rest);
@@ -46,14 +48,14 @@ describe('services/validate', () => {
46
48
  'in',
47
49
  'f003-not-fi-melinda.json'
48
50
  ]
49
- }));
51
+ }) as MarcRecordObject);
50
52
  const result = await validator(record.toObject());
51
53
  const {record: expectedRecord, ...rest} = getFixture({
52
54
  components: [
53
55
  'out',
54
56
  'f003-not-fi-melinda.json'
55
57
  ]
56
- });
58
+ }) as Record<string, any>;
57
59
  const {_validationOptions, ...expectedRecordData} = expectedRecord;
58
60
  const {record: actualRecord, ...actualRest} = result;
59
61
  assert.deepStrictEqual(actualRest, rest);
@@ -62,4 +64,3 @@ describe('services/validate', () => {
62
64
  });
63
65
  });
64
66
  });
65
-
@@ -4,10 +4,10 @@ import mongoFixturesFactory from '@natlibfi/fixura-mongo';
4
4
  import generateTests from '@natlibfi/fixugen';
5
5
  import createDebugLogger from 'debug';
6
6
  //import {handleError, compareToFirstDbEntry, compareToDbEntry, formatQueueItem, streamToString} from './testUtils.js';
7
- import {getMongoOperator, handleError, compareToFirstDbEntry} from './testUtils.js';
7
+ import {getMongoOperator, handleError, compareToFirstDbEntry} from './testUtils.ts';
8
8
 
9
9
 
10
- let mongoFixtures; // eslint-disable-line functional/no-let
10
+ let mongoFixtures: any;
11
11
  const debug = createDebugLogger('@natlibfi/melinda-rest-api-commons/mongo:add-blob-size:test');
12
12
 
13
13
  generateTests({
@@ -41,32 +41,31 @@ generateTests({
41
41
 
42
42
  async function initMongofixtures() {
43
43
  mongoFixtures = await mongoFixturesFactory({
44
- recurse: false,
45
44
  rootPath: [import.meta.dirname, '..', 'test-fixtures', 'mongo', 'add-blob-size'],
46
45
  gridFS: {bucketName: 'foobar'},
47
46
  useObjectId: true
48
47
  });
49
48
  }
50
49
 
51
- // eslint-disable-next-line max-statements, complexity
52
- async function callback({
53
- getFixture,
54
- functionName,
55
- params,
56
- expectModificationTime = false,
57
- preFillDb = false,
58
- expectedToThrow = false,
59
- expectedErrorMessage = '',
60
- expectedErrorStatus = ''
50
+ async function callback(callbackParams: Record<string, any>) {
51
+ const {
52
+ getFixture,
53
+ functionName,
54
+ params,
55
+ expectModificationTime = false,
56
+ preFillDb = false,
57
+ expectedToThrow = false,
58
+ expectedErrorMessage = '',
59
+ expectedErrorStatus = ''
61
60
 
62
- }) {
61
+ } = callbackParams;
63
62
 
64
63
  const mongoOperator = await getMongoOperator(mongoFixtures);
65
64
  const expectedResult = await getFixture('expectedResult.json');
66
65
 
67
66
  await doPreFillDb(preFillDb);
68
67
 
69
- async function doPreFillDb(preFillDb) {
68
+ async function doPreFillDb(preFillDb: boolean) {
70
69
  if (preFillDb) {
71
70
  await mongoFixtures.populate(getFixture('dbContents.json'));
72
71
  return;
@@ -4,10 +4,10 @@ import mongoFixturesFactory from '@natlibfi/fixura-mongo';
4
4
  import generateTests from '@natlibfi/fixugen';
5
5
  import createDebugLogger from 'debug';
6
6
  //import {handleError, compareToFirstDbEntry, compareToDbEntry, formatQueueItem, streamToString} from './testUtils.js';
7
- import {getMongoOperator, handleError, compareToFirstDbEntry} from './testUtils.js';
7
+ import {getMongoOperator, handleError, compareToFirstDbEntry} from './testUtils.ts';
8
8
 
9
9
 
10
- let mongoFixtures; // eslint-disable-line functional/no-let
10
+ let mongoFixtures: any;
11
11
  const debug = createDebugLogger('@natlibfi/melinda-rest-api-commons/mongo:test');
12
12
 
13
13
  generateTests({
@@ -41,14 +41,14 @@ generateTests({
41
41
 
42
42
  async function initMongofixtures() {
43
43
  mongoFixtures = await mongoFixturesFactory({
44
- recurse: false,
45
44
  rootPath: [import.meta.dirname, '..', 'test-fixtures', 'mongo', 'check-and-set-state'],
46
45
  gridFS: {bucketName: 'foobar'},
47
46
  useObjectId: true
48
47
  });
49
48
  }
50
49
 
51
- async function callback({
50
+ async function callback(callbackParams: Record<string, any>) {
51
+ const {
52
52
  getFixture,
53
53
  functionName,
54
54
  params,
@@ -59,14 +59,14 @@ async function callback({
59
59
  expectedErrorStatus = '',
60
60
  expectedOpResult = undefined,
61
61
  updateStateBeforeTest = undefined
62
- }) {
62
+ } = callbackParams;
63
63
 
64
64
  const mongoOperator = await getMongoOperator(mongoFixtures);
65
65
  const expectedResult = await getFixture('expectedResult.json');
66
66
 
67
67
  await doPreFillDb(preFillDb);
68
68
 
69
- async function doPreFillDb(preFillDb) {
69
+ async function doPreFillDb(preFillDb: boolean) {
70
70
  if (preFillDb) {
71
71
  await mongoFixtures.populate(getFixture('dbContents.json'));
72
72
  return;
@@ -81,7 +81,6 @@ async function callback({
81
81
  //{correlationId, state, errorMessage = undefined, errorStatus = undefined})
82
82
  // timeout
83
83
 
84
- // eslint-disable-next-line functional/no-conditional-statements
85
84
  if (updateStateBeforeTest && params.correlationId) {
86
85
  debug(`setState to reset modificationTime`);
87
86
  await mongoOperator.setState({correlationId: params.correlationId, state: updateStateBeforeTest});
@@ -91,7 +90,6 @@ async function callback({
91
90
 
92
91
  // checkAndSetState now returns a discriminated result
93
92
  // {status: 'updated' | 'timeout' | 'unchanged', queueItem} - compare status
94
- // eslint-disable-next-line functional/no-conditional-statements
95
93
  if (expectedOpResult !== undefined) {
96
94
  assert.deepStrictEqual(opResult.status, expectedOpResult);
97
95
  }