@natlibfi/melinda-rest-api-commons 5.0.0-alpha.1 → 5.0.0-alpha.3

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.
package/dist/amqp.js ADDED
@@ -0,0 +1,235 @@
1
+ import amqplib from "amqplib";
2
+ import createDebugLogger from "debug";
3
+ import { promisify, inspect } from "util";
4
+ import httpStatus from "http-status";
5
+ import { MarcRecord } from "@natlibfi/marc-record";
6
+ import { Error as ApiError } from "@natlibfi/melinda-commons";
7
+ import { createLogger } from "@natlibfi/melinda-backend-commons";
8
+ import { CHUNK_SIZE } from "./constants.js";
9
+ import { logError } from "./utils.js";
10
+ export default async function(AMQP_URL, runHealthCheck = false) {
11
+ const logger = createLogger();
12
+ const debug = createDebugLogger("@natlibfi/melinda-rest-api-commons:amqp");
13
+ const debugHC = debug.extend("HC");
14
+ const debugData = debug.extend("data");
15
+ const setTimeoutPromise = promisify(setTimeout);
16
+ debug(`Creating an AMQP operator to ${AMQP_URL}`);
17
+ const connection = await amqplib.connect(AMQP_URL);
18
+ const channel = await connection.createChannel();
19
+ const healthCheckLoop = runHealthCheck ? healthCheck() : false;
20
+ debug(`Connection: ${connection}`);
21
+ debug(`Channel: ${channel}`);
22
+ debug(`HealthCheckLoop: ${healthCheckLoop ? "Running health check" : "Not running health check"}`);
23
+ return { checkQueue, consumeChunk, consumeOne, ackMessages, nackMessages, sendToQueue, removeQueue, messagesToRecords, closeChannel, closeConnection };
24
+ async function closeChannel() {
25
+ debug(`Closing channel`);
26
+ await channel.close();
27
+ debug(`Channel: ${channel}`);
28
+ }
29
+ async function closeConnection() {
30
+ debug(`Closing connection`);
31
+ await connection.close();
32
+ debug(`Connection: ${connection}`);
33
+ }
34
+ async function healthCheck(wait = false) {
35
+ if (wait) {
36
+ await setTimeoutPromise(wait);
37
+ return healthCheck(false);
38
+ }
39
+ try {
40
+ debugHC(`Health checking amqp by asserting a queue`);
41
+ await channel.assertQueue("HEALTHCHECK", { durable: false });
42
+ debugHC(`Waiting 200ms before running healthCheck next`);
43
+ return healthCheck(200);
44
+ } catch (error) {
45
+ debugHC(`HealthCheck error ${JSON.stringify(error)}`);
46
+ handleAmqpErrors(error);
47
+ }
48
+ }
49
+ async function checkQueue({ queue, style = "basic", toRecord = true, purge = false }) {
50
+ debug(`checkQueue: ${queue}, Style: ${style}, toRecord: ${toRecord}, Purge: ${purge}`);
51
+ try {
52
+ errorUndefinedQueue(queue);
53
+ const channelInfo = await channel.assertQueue(queue, { durable: true });
54
+ if (purge) {
55
+ await purgeQueue(purge);
56
+ logger.verbose(`Queue ${queue} has purged ${channelInfo.messageCount} messages`);
57
+ debug(`Queue ${queue} has purged ${channelInfo.messageCount} messages`);
58
+ return checkQueue({ queue, style });
59
+ }
60
+ if (style === "messages") {
61
+ return channelInfo.messageCount;
62
+ }
63
+ if (style === "one") {
64
+ if (checkMessageCount(channelInfo)) {
65
+ return consumeOne(queue, toRecord);
66
+ }
67
+ return false;
68
+ }
69
+ if (style === "basic") {
70
+ if (checkMessageCount(channelInfo)) {
71
+ return consumeChunk(queue, toRecord);
72
+ }
73
+ return false;
74
+ }
75
+ throw new ApiError(httpStatus.INTERNAL_SERVER_ERROR, `CheckQueue does not recognize style ${style}`);
76
+ } catch (error) {
77
+ handleAmqpErrors(error);
78
+ }
79
+ function checkMessageCount(channelInfo) {
80
+ if (channelInfo.messageCount < 1) {
81
+ debug(`checkQueue: ${channelInfo.messageCount} - ${queue} is empty`);
82
+ return false;
83
+ }
84
+ debug(`Queue ${queue} has ${channelInfo.messageCount} messages`);
85
+ return true;
86
+ }
87
+ function purgeQueue(purge2) {
88
+ debug(`Purging queue: ${queue}, purge: ${purge2}`);
89
+ if (purge2) {
90
+ return channel.purgeQueue(queue);
91
+ }
92
+ }
93
+ }
94
+ async function consumeChunk(queue, toRecord) {
95
+ debug(`Prepared to consumeChunk from queue: ${queue}`);
96
+ try {
97
+ await channel.assertQueue(queue, { durable: true });
98
+ const messages = await getData(queue);
99
+ const headers = getHeaderInfo(messages[0]);
100
+ debug(`consumeChunk (${messages ? messages.length : "0"} from queue ${queue}) ${toRecord ? "to records" : "just messages"}`);
101
+ if (toRecord) {
102
+ const records = await messagesToRecords(messages);
103
+ return { headers, records, messages };
104
+ }
105
+ return { headers, messages };
106
+ } catch (error) {
107
+ handleAmqpErrors(error);
108
+ }
109
+ }
110
+ async function consumeOne(queue, toRecord) {
111
+ debug(`Prepared to consumeOne from queue: ${queue}`);
112
+ try {
113
+ await channel.assertQueue(queue, { durable: true });
114
+ const message = await channel.get(queue);
115
+ debugData(`Message: ${inspect(message, { colors: true, maxArrayLength: 3, depth: 3 })}`);
116
+ debug(`consumeOne from queue: ${queue} ${toRecord ? "to records" : "just the message"}`);
117
+ if (message) {
118
+ if (toRecord) {
119
+ const headers = getHeaderInfo(message);
120
+ const records = messagesToRecords([message]);
121
+ return { headers, records, messages: [message] };
122
+ }
123
+ return message;
124
+ }
125
+ return false;
126
+ } catch (error) {
127
+ handleAmqpErrors(error);
128
+ }
129
+ }
130
+ function ackMessages(messages) {
131
+ messages.forEach((message) => {
132
+ debug(`Ack message ${message.properties.correlationId}`);
133
+ channel.ack(message);
134
+ });
135
+ }
136
+ function nackMessages(messages) {
137
+ messages.forEach((message) => {
138
+ debug(`Nack message ${message.properties.correlationId}`);
139
+ channel.nack(message);
140
+ });
141
+ }
142
+ async function sendToQueue({ queue, correlationId, headers, data }) {
143
+ debug(`sendToQueue`);
144
+ try {
145
+ debug(`Queue ${queue}`);
146
+ debug(`CorrelationId ${correlationId}`);
147
+ debugData(`Data ${JSON.stringify(data)}`);
148
+ debug(`Headers ${JSON.stringify(headers)}`);
149
+ errorUndefinedQueue(queue);
150
+ debug(`Asserting queue: ${queue}`);
151
+ await channel.assertQueue(queue, { durable: true });
152
+ debug(`Actually sendToQueue: ${queue}`);
153
+ await channel.sendToQueue(
154
+ queue,
155
+ Buffer.from(JSON.stringify({ data })),
156
+ {
157
+ correlationId,
158
+ persistent: true,
159
+ headers
160
+ }
161
+ );
162
+ debug(`Send message for ${correlationId} to queue: ${queue}`);
163
+ } catch (error) {
164
+ const errorToThrow = error;
165
+ debug(`SendToQueue errored: ${JSON.stringify(error)}`);
166
+ handleAmqpErrors(errorToThrow);
167
+ }
168
+ }
169
+ async function removeQueue(queue) {
170
+ const tempChannel = await connection.createChannel();
171
+ logger.verbose(`Removing queue ${queue}.`);
172
+ debug(`Removing queue ${queue}.`);
173
+ await tempChannel.deleteQueue(queue);
174
+ if (tempChannel) {
175
+ await tempChannel.close();
176
+ return;
177
+ }
178
+ return;
179
+ }
180
+ function messagesToRecords(messages) {
181
+ debug(`Parsing messages (${messages.length}) to records`);
182
+ return messages.map((message) => {
183
+ const content = JSON.parse(message.content.toString());
184
+ return new MarcRecord(content.data, { subfieldValues: false });
185
+ });
186
+ }
187
+ async function getData(queue) {
188
+ debug(`Getting queue data from ${queue}`);
189
+ try {
190
+ const { messageCount } = await channel.checkQueue(queue);
191
+ debug(`There is ${messageCount} messages in queue ${queue}`);
192
+ const messagesToGet = messageCount >= CHUNK_SIZE ? CHUNK_SIZE : messageCount;
193
+ debug(`Getting ${messagesToGet} messages from queue ${queue}`);
194
+ const messages = await pump(messagesToGet);
195
+ debug(`Returning ${messages.length} unique messages`);
196
+ return messages;
197
+ } catch (error) {
198
+ handleAmqpErrors(error);
199
+ }
200
+ async function pump(count, results = [], identifiers = []) {
201
+ if (count === 0) {
202
+ return results;
203
+ }
204
+ const message = await channel.get(queue);
205
+ const identifier = {
206
+ correlationId: message.properties.correlationId,
207
+ deliveryTag: message.fields.deliveryTag
208
+ };
209
+ if (identifiers.includes(identifier)) {
210
+ return pump(count - 1, results, identifiers);
211
+ }
212
+ return pump(count - 1, results.concat(message), identifiers.concat(identifier));
213
+ }
214
+ }
215
+ function getHeaderInfo(data) {
216
+ return data.properties.headers;
217
+ }
218
+ function errorUndefinedQueue(queue) {
219
+ if (queue === void 0 || queue === "" || queue === null) {
220
+ throw new ApiError(httpStatus.INTERNAL_SERVER_ERROR, `Undefined queue!`);
221
+ }
222
+ }
223
+ function handleAmqpErrors(error) {
224
+ const newError = error;
225
+ debug(`HandleAmqpErrors got an error: ${JSON.stringify(error)}`);
226
+ if (error instanceof ApiError) {
227
+ debug(`We have an ApiError`);
228
+ throw new ApiError(newError.status, newError.payload);
229
+ }
230
+ debug(`We have a non-ApiError`);
231
+ logError(error);
232
+ throw newError;
233
+ }
234
+ }
235
+ //# sourceMappingURL=amqp.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/amqp.js"],
4
+ "sourcesContent": ["import amqplib from 'amqplib';\nimport createDebugLogger from 'debug';\nimport {promisify, inspect} from 'util';\nimport httpStatus from 'http-status';\nimport {MarcRecord} from '@natlibfi/marc-record';\nimport {Error as ApiError} from '@natlibfi/melinda-commons';\nimport {createLogger} from '@natlibfi/melinda-backend-commons';\nimport {CHUNK_SIZE} from './constants.js';\nimport {logError} from './utils.js';\n\nexport default async function (AMQP_URL, runHealthCheck = false) {\n const logger = createLogger();\n const debug = createDebugLogger('@natlibfi/melinda-rest-api-commons:amqp');\n const debugHC = debug.extend('HC');\n const debugData = debug.extend('data');\n const setTimeoutPromise = promisify(setTimeout);\n\n debug(`Creating an AMQP operator to ${AMQP_URL}`);\n const connection = await amqplib.connect(AMQP_URL);\n const channel = await connection.createChannel();\n\n const healthCheckLoop = runHealthCheck ? healthCheck() : false;\n\n debug(`Connection: ${connection}`);\n debug(`Channel: ${channel}`);\n debug(`HealthCheckLoop: ${healthCheckLoop ? 'Running health check' : 'Not running health check'}`);\n\n return {checkQueue, consumeChunk, consumeOne, ackMessages, nackMessages, sendToQueue, removeQueue, messagesToRecords, closeChannel, closeConnection};\n\n async function closeChannel() {\n debug(`Closing channel`);\n await channel.close();\n debug(`Channel: ${channel}`);\n }\n\n async function closeConnection() {\n debug(`Closing connection`);\n await connection.close();\n debug(`Connection: ${connection}`);\n }\n\n async function healthCheck(wait = false) {\n if (wait) {\n await setTimeoutPromise(wait);\n return healthCheck(false);\n }\n\n try {\n debugHC(`Health checking amqp by asserting a queue`);\n await channel.assertQueue('HEALTHCHECK', {durable: false});\n debugHC(`Waiting 200ms before running healthCheck next`);\n return healthCheck(200);\n } catch (error) {\n debugHC(`HealthCheck error ${JSON.stringify(error)}`);\n handleAmqpErrors(error);\n }\n }\n\n // eslint-disable-next-line max-statements\n async function checkQueue({queue, style = 'basic', toRecord = true, purge = false}) {\n debug(`checkQueue: ${queue}, Style: ${style}, toRecord: ${toRecord}, Purge: ${purge}`);\n\n try {\n\n errorUndefinedQueue(queue);\n const channelInfo = await channel.assertQueue(queue, {durable: true});\n\n if (purge) {\n await purgeQueue(purge);\n logger.verbose(`Queue ${queue} has purged ${channelInfo.messageCount} messages`);\n debug(`Queue ${queue} has purged ${channelInfo.messageCount} messages`);\n return checkQueue({queue, style});\n }\n\n if (style === 'messages') {\n return channelInfo.messageCount;\n }\n\n\n // Note: returns one message (+ record, of toRecord: true)\n // note: if toRecord is false returns just plain message / false\n // note: if toRecord is true returns {headers, records, messages} -object / false\n // should this be more consistent?\n if (style === 'one') {\n if (checkMessageCount(channelInfo)) {\n return consumeOne(queue, toRecord);\n }\n return false;\n }\n\n // Note: returns a chunk of (100) messages (+ records, if toRecord: true)\n // returns {headers, records, messages} object or {headers, messages} object depending on toRecord\n if (style === 'basic') {\n if (checkMessageCount(channelInfo)) {\n return consumeChunk(queue, toRecord);\n }\n return false;\n }\n\n // Defaults:\n throw new ApiError(httpStatus.INTERNAL_SERVER_ERROR, `CheckQueue does not recognize style ${style}`);\n } catch (error) {\n handleAmqpErrors(error);\n }\n\n function checkMessageCount(channelInfo) {\n if (channelInfo.messageCount < 1) {\n debug(`checkQueue: ${channelInfo.messageCount} - ${queue} is empty`);\n return false;\n }\n debug(`Queue ${queue} has ${channelInfo.messageCount} messages`);\n return true;\n }\n\n function purgeQueue(purge) {\n debug(`Purging queue: ${queue}, purge: ${purge}`);\n if (purge) {\n return channel.purgeQueue(queue);\n }\n }\n }\n\n async function consumeChunk(queue, toRecord) {\n debug(`Prepared to consumeChunk from queue: ${queue}`);\n try {\n await channel.assertQueue(queue, {durable: true});\n\n // getData: next chunk (100) messages\n const messages = await getData(queue);\n\n // Note: headers are from the first message of the chunk\n const headers = getHeaderInfo(messages[0]);\n debug(`consumeChunk (${messages ? messages.length : '0'} from queue ${queue}) ${toRecord ? 'to records' : 'just messages'}`);\n\n if (toRecord) {\n const records = await messagesToRecords(messages);\n return {headers, records, messages};\n }\n\n return {headers, messages};\n } catch (error) {\n handleAmqpErrors(error);\n }\n }\n\n async function consumeOne(queue, toRecord) {\n debug(`Prepared to consumeOne from queue: ${queue}`);\n try {\n await channel.assertQueue(queue, {durable: true});\n\n // Returns false if 0 items in queue\n const message = await channel.get(queue);\n\n debugData(`Message: ${inspect(message, {colors: true, maxArrayLength: 3, depth: 3})}`);\n // Do not spam the logs\n debug(`consumeOne from queue: ${queue} ${toRecord ? 'to records' : 'just the message'}`);\n\n if (message) {\n if (toRecord) {\n const headers = getHeaderInfo(message);\n const records = messagesToRecords([message]);\n return {headers, records, messages: [message]};\n }\n\n return message;\n }\n\n return false;\n } catch (error) {\n handleAmqpErrors(error);\n }\n }\n\n function ackMessages(messages) {\n messages.forEach(message => {\n debug(`Ack message ${message.properties.correlationId}`);\n channel.ack(message);\n });\n }\n\n function nackMessages(messages) {\n messages.forEach(message => {\n debug(`Nack message ${message.properties.correlationId}`);\n channel.nack(message);\n });\n }\n\n async function sendToQueue({queue, correlationId, headers, data}) {\n debug(`sendToQueue`);\n // eslint-disable-next-line no-useless-catch\n try {\n debug(`Queue ${queue}`);\n debug(`CorrelationId ${correlationId}`);\n debugData(`Data ${JSON.stringify(data)}`);\n debug(`Headers ${JSON.stringify(headers)}`);\n\n errorUndefinedQueue(queue);\n\n debug(`Asserting queue: ${queue}`);\n await channel.assertQueue(queue, {durable: true});\n\n debug(`Actually sendToQueue: ${queue}`);\n await channel.sendToQueue(\n queue,\n Buffer.from(JSON.stringify({data})),\n {\n correlationId,\n persistent: true,\n headers\n }\n );\n debug(`Send message for ${correlationId} to queue: ${queue}`);\n\n\n } catch (error) {\n const errorToThrow = error;\n //if (error instanceof ApiError) {\n // throw error;\n //}\n debug(`SendToQueue errored: ${JSON.stringify(error)}`);\n handleAmqpErrors(errorToThrow);\n }\n }\n\n async function removeQueue(queue) {\n // deleteQueue borks the channel if the queue does not exist\n // -> use throwaway tempChannel to avoid killing actual channel in use\n // this might be doable also with assertQueue before deleteQueue\n const tempChannel = await connection.createChannel();\n logger.verbose(`Removing queue ${queue}.`);\n debug(`Removing queue ${queue}.`);\n await tempChannel.deleteQueue(queue);\n\n if (tempChannel) {\n await tempChannel.close();\n return;\n }\n\n return;\n }\n\n // ----------------\n // Helper functions\n // ----------------\n\n function messagesToRecords(messages) {\n debug(`Parsing messages (${messages.length}) to records`);\n\n return messages.map(message => {\n const content = JSON.parse(message.content.toString());\n // Use subfieldValues: false validationOption here\n return new MarcRecord(content.data, {subfieldValues: false});\n });\n }\n\n async function getData(queue) {\n debug(`Getting queue data from ${queue}`);\n try {\n const {messageCount} = await channel.checkQueue(queue);\n debug(`There is ${messageCount} messages in queue ${queue}`);\n const messagesToGet = messageCount >= CHUNK_SIZE ? CHUNK_SIZE : messageCount;\n debug(`Getting ${messagesToGet} messages from queue ${queue}`);\n\n const messages = await pump(messagesToGet);\n\n debug(`Returning ${messages.length} unique messages`);\n\n return messages;\n } catch (error) {\n handleAmqpErrors(error);\n }\n\n async function pump(count, results = [], identifiers = []) {\n if (count === 0) {\n return results;\n }\n\n const message = await channel.get(queue);\n const identifier = {\n correlationId: message.properties.correlationId,\n deliveryTag: message.fields.deliveryTag\n };\n // Filter not unique messages\n if (identifiers.includes(identifier)) {\n return pump(count - 1, results, identifiers);\n }\n\n return pump(count - 1, results.concat(message), identifiers.concat(identifier));\n }\n }\n\n function getHeaderInfo(data) {\n return data.properties.headers;\n }\n\n function errorUndefinedQueue(queue) {\n if (queue === undefined || queue === '' || queue === null) {\n throw new ApiError(httpStatus.INTERNAL_SERVER_ERROR, `Undefined queue!`);\n }\n }\n\n function handleAmqpErrors(error) {\n const newError = error;\n debug(`HandleAmqpErrors got an error: ${JSON.stringify(error)}`);\n if (error instanceof ApiError) {\n debug(`We have an ApiError`);\n throw new ApiError(newError.status, newError.payload);\n }\n debug(`We have a non-ApiError`);\n logError(error);\n throw newError;\n }\n}\n\n\n"],
5
+ "mappings": "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",
6
+ "names": ["purge"]
7
+ }
@@ -0,0 +1,49 @@
1
+ export const QUEUE_ITEM_STATE = {
2
+ VALIDATOR: {
3
+ PENDING_QUEUING: "PENDING_QUEUING",
4
+ PENDING_VALIDATION: "PENDING_VALIDATION",
5
+ QUEUING_IN_PROGRESS: "QUEUING_IN_PROGRESS",
6
+ UPLOADING: "UPLOADING",
7
+ VALIDATING: "VALIDATING",
8
+ WAITING_FOR_RECORDS: "WAITING_FOR_RECORDS"
9
+ },
10
+ IMPORTER: {
11
+ IMPORTING: "IMPORTING",
12
+ IN_PROCESS: "IN_PROCESS",
13
+ IN_QUEUE: "IN_QUEUE"
14
+ },
15
+ DONE: "DONE",
16
+ ERROR: "ERROR",
17
+ ABORT: "ABORT"
18
+ };
19
+ export const IMPORT_JOB_STATE = {
20
+ EMPTY: "EMPTY",
21
+ QUEUING: "QUEUING",
22
+ IN_QUEUE: "IN_QUEUE",
23
+ IMPORTING: "IMPORTING",
24
+ PROCESSING: "PROCESSING",
25
+ DONE: "DONE",
26
+ ERROR: "ERROR",
27
+ ABORT: "ABORT"
28
+ };
29
+ export const OPERATIONS = {
30
+ CREATE: "CREATE",
31
+ UPDATE: "UPDATE",
32
+ FIX: "FIX"
33
+ };
34
+ export const CHUNK_SIZE = 100;
35
+ export const LOG_ITEM_TYPE = {
36
+ INPUT_RECORD_LOG: "INPUT_RECORD_LOG",
37
+ MERGE_LOG: "MERGE_LOG",
38
+ MATCH_LOG: "MATCH_LOG",
39
+ RESULT_RECORD_LOG: "RESULT_RECORD_LOG",
40
+ SPLITTER_LOG: "SPLITTER_LOG",
41
+ LOAD_PROCESS_LOG: "LOAD_PROCESS_LOG"
42
+ };
43
+ export const CONVERSION_FORMATS = {
44
+ MARCXML: "MARCXML",
45
+ ISO2709: "ISO2709",
46
+ JSON: "JSON",
47
+ ALEPHSEQ: "ALEPHSEQ"
48
+ };
49
+ //# sourceMappingURL=constants.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/constants.js"],
4
+ "sourcesContent": ["// QueueItemState flows: see README.md\n\nexport const QUEUE_ITEM_STATE = {\n VALIDATOR: {\n PENDING_QUEUING: 'PENDING_QUEUING',\n PENDING_VALIDATION: 'PENDING_VALIDATION',\n QUEUING_IN_PROGRESS: 'QUEUING_IN_PROGRESS',\n UPLOADING: 'UPLOADING',\n VALIDATING: 'VALIDATING',\n WAITING_FOR_RECORDS: 'WAITING_FOR_RECORDS'\n },\n IMPORTER: {\n IMPORTING: 'IMPORTING',\n IN_PROCESS: 'IN_PROCESS',\n IN_QUEUE: 'IN_QUEUE'\n },\n DONE: 'DONE',\n ERROR: 'ERROR',\n ABORT: 'ABORT'\n};\n\nexport const IMPORT_JOB_STATE = {\n EMPTY: 'EMPTY',\n QUEUING: 'QUEUING',\n IN_QUEUE: 'IN_QUEUE',\n IMPORTING: 'IMPORTING',\n PROCESSING: 'PROCESSING',\n DONE: 'DONE',\n ERROR: 'ERROR',\n ABORT: 'ABORT'\n};\n\nexport const OPERATIONS = {\n CREATE: 'CREATE',\n UPDATE: 'UPDATE',\n FIX: 'FIX'\n};\n\nexport const CHUNK_SIZE = 100;\n\n// We could configure here whether a logItemType is for a several records of a single record\n// ie. whether is has bulkSequence or bulkSequenceStart & bulkSequenceEnd\nexport const LOG_ITEM_TYPE = {\n INPUT_RECORD_LOG: 'INPUT_RECORD_LOG',\n MERGE_LOG: 'MERGE_LOG',\n MATCH_LOG: 'MATCH_LOG',\n RESULT_RECORD_LOG: 'RESULT_RECORD_LOG',\n SPLITTER_LOG: 'SPLITTER_LOG',\n LOAD_PROCESS_LOG: 'LOAD_PROCESS_LOG'\n};\n\nexport const CONVERSION_FORMATS = {\n MARCXML: 'MARCXML',\n ISO2709: 'ISO2709',\n JSON: 'JSON',\n ALEPHSEQ: 'ALEPHSEQ'\n};\n"],
5
+ "mappings": "AAEO,aAAM,mBAAmB;AAAA,EAC9B,WAAW;AAAA,IACT,iBAAiB;AAAA,IACjB,oBAAoB;AAAA,IACpB,qBAAqB;AAAA,IACrB,WAAW;AAAA,IACX,YAAY;AAAA,IACZ,qBAAqB;AAAA,EACvB;AAAA,EACA,UAAU;AAAA,IACR,WAAW;AAAA,IACX,YAAY;AAAA,IACZ,UAAU;AAAA,EACZ;AAAA,EACA,MAAM;AAAA,EACN,OAAO;AAAA,EACP,OAAO;AACT;AAEO,aAAM,mBAAmB;AAAA,EAC9B,OAAO;AAAA,EACP,SAAS;AAAA,EACT,UAAU;AAAA,EACV,WAAW;AAAA,EACX,YAAY;AAAA,EACZ,MAAM;AAAA,EACN,OAAO;AAAA,EACP,OAAO;AACT;AAEO,aAAM,aAAa;AAAA,EACxB,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,KAAK;AACP;AAEO,aAAM,aAAa;AAInB,aAAM,gBAAgB;AAAA,EAC3B,kBAAkB;AAAA,EAClB,WAAW;AAAA,EACX,WAAW;AAAA,EACX,mBAAmB;AAAA,EACnB,cAAc;AAAA,EACd,kBAAkB;AACpB;AAEO,aAAM,qBAAqB;AAAA,EAChC,SAAS;AAAA,EACT,SAAS;AAAA,EACT,MAAM;AAAA,EACN,UAAU;AACZ;",
6
+ "names": []
7
+ }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../src/helpers/conversion.js"],
3
+ "sources": ["../../src/helpers/conversion.js"],
4
4
  "sourcesContent": ["\n\nimport httpStatus from 'http-status';\nimport {MARCXML, ISO2709, Json, AlephSequential} from '@natlibfi/marc-record-serializers';\nimport {createLogger} from '@natlibfi/melinda-backend-commons';\nimport {Error as ConversionError} from '@natlibfi/melinda-commons';\nimport {CONVERSION_FORMATS} from '../constants.js';\nimport {logError} from '../utils.js';\n\nexport default function () {\n const logger = createLogger();\n\n return {serialize, unserialize};\n\n // This uses format as a number form contants CONVERSION_FORMATS\n function serialize(record, format) {\n logger.verbose(`Serializing record to ${format}`);\n try {\n if (format === CONVERSION_FORMATS.MARCXML) {\n return MARCXML.to(record);\n }\n\n if (format === CONVERSION_FORMATS.ISO2709) {\n return ISO2709.to(record);\n }\n\n if (format === CONVERSION_FORMATS.JSON) {\n return Json.to(record);\n }\n\n if (format === CONVERSION_FORMATS.ALEPHSEQ) {\n return AlephSequential.to(record);\n }\n\n throw new ConversionError(httpStatus.UNSUPPORTED_MEDIA_TYPE);\n } catch (err) {\n logError(err);\n const message = err.message || err.payload?.message || err.payload;\n logger.debug(`${message}`);\n if (err instanceof ConversionError) {\n throw err;\n }\n throw new ConversionError(httpStatus.BAD_REQUEST, `Error while serializing record. ${message}`);\n }\n }\n\n // eslint-disable-next-line max-statements\n function unserialize(data, format, validationOptions = {subfieldValues: false}) {\n logger.verbose(`Unserializing record from ${format}`);\n logger.silly(`Format: ${format}`);\n logger.debug(`Validation options: ${JSON.stringify(validationOptions)}`);\n logger.silly(`Data: ${JSON.stringify(data)}`);\n try {\n if (format === CONVERSION_FORMATS.MARCXML) {\n logger.silly('Unserialize format marcxml');\n return MARCXML.from(data, validationOptions);\n }\n\n if (format === CONVERSION_FORMATS.ISO2709) {\n logger.silly('Unserialize format iso2709');\n return ISO2709.from(data, validationOptions);\n }\n\n if (format === CONVERSION_FORMATS.JSON) {\n logger.silly('Unserialize format json');\n return Json.from(data, validationOptions);\n }\n\n if (format === CONVERSION_FORMATS.ALEPHSEQ) {\n logger.silly('Unserialize format aleph sequential');\n return AlephSequential.from(data, validationOptions);\n }\n\n throw new ConversionError(httpStatus.UNSUPPORTED_MEDIA_TYPE);\n } catch (err) {\n logError(err);\n const message = err.message || err.payload?.message || err.payload;\n logger.debug(`${message}`);\n if (err instanceof ConversionError) {\n throw err;\n }\n throw new ConversionError(httpStatus.BAD_REQUEST, `Error while unserializing record. ${message}`);\n }\n }\n}\n"],
5
5
  "mappings": "AAEA,OAAO,gBAAgB;AACvB,SAAQ,SAAS,SAAS,MAAM,uBAAsB;AACtD,SAAQ,oBAAmB;AAC3B,SAAQ,SAAS,uBAAsB;AACvC,SAAQ,0BAAyB;AACjC,SAAQ,gBAAe;AAEvB,0BAA2B;AACzB,QAAM,SAAS,aAAa;AAE5B,SAAO,EAAC,WAAW,YAAW;AAG9B,WAAS,UAAU,QAAQ,QAAQ;AACjC,WAAO,QAAQ,yBAAyB,MAAM,EAAE;AAChD,QAAI;AACF,UAAI,WAAW,mBAAmB,SAAS;AACzC,eAAO,QAAQ,GAAG,MAAM;AAAA,MAC1B;AAEA,UAAI,WAAW,mBAAmB,SAAS;AACzC,eAAO,QAAQ,GAAG,MAAM;AAAA,MAC1B;AAEA,UAAI,WAAW,mBAAmB,MAAM;AACtC,eAAO,KAAK,GAAG,MAAM;AAAA,MACvB;AAEA,UAAI,WAAW,mBAAmB,UAAU;AAC1C,eAAO,gBAAgB,GAAG,MAAM;AAAA,MAClC;AAEA,YAAM,IAAI,gBAAgB,WAAW,sBAAsB;AAAA,IAC7D,SAAS,KAAK;AACZ,eAAS,GAAG;AACZ,YAAM,UAAU,IAAI,WAAW,IAAI,SAAS,WAAW,IAAI;AAC3D,aAAO,MAAM,GAAG,OAAO,EAAE;AACzB,UAAI,eAAe,iBAAiB;AAClC,cAAM;AAAA,MACR;AACA,YAAM,IAAI,gBAAgB,WAAW,aAAa,mCAAmC,OAAO,EAAE;AAAA,IAChG;AAAA,EACF;AAGA,WAAS,YAAY,MAAM,QAAQ,oBAAoB,EAAC,gBAAgB,MAAK,GAAG;AAC9E,WAAO,QAAQ,6BAA6B,MAAM,EAAE;AACpD,WAAO,MAAM,WAAW,MAAM,EAAE;AAChC,WAAO,MAAM,uBAAuB,KAAK,UAAU,iBAAiB,CAAC,EAAE;AACvE,WAAO,MAAM,SAAS,KAAK,UAAU,IAAI,CAAC,EAAE;AAC5C,QAAI;AACF,UAAI,WAAW,mBAAmB,SAAS;AACzC,eAAO,MAAM,4BAA4B;AACzC,eAAO,QAAQ,KAAK,MAAM,iBAAiB;AAAA,MAC7C;AAEA,UAAI,WAAW,mBAAmB,SAAS;AACzC,eAAO,MAAM,4BAA4B;AACzC,eAAO,QAAQ,KAAK,MAAM,iBAAiB;AAAA,MAC7C;AAEA,UAAI,WAAW,mBAAmB,MAAM;AACtC,eAAO,MAAM,yBAAyB;AACtC,eAAO,KAAK,KAAK,MAAM,iBAAiB;AAAA,MAC1C;AAEA,UAAI,WAAW,mBAAmB,UAAU;AAC1C,eAAO,MAAM,qCAAqC;AAClD,eAAO,gBAAgB,KAAK,MAAM,iBAAiB;AAAA,MACrD;AAEA,YAAM,IAAI,gBAAgB,WAAW,sBAAsB;AAAA,IAC7D,SAAS,KAAK;AACZ,eAAS,GAAG;AACZ,YAAM,UAAU,IAAI,WAAW,IAAI,SAAS,WAAW,IAAI;AAC3D,aAAO,MAAM,GAAG,OAAO,EAAE;AACzB,UAAI,eAAe,iBAAiB;AAClC,cAAM;AAAA,MACR;AACA,YAAM,IAAI,gBAAgB,WAAW,aAAa,qCAAqC,OAAO,EAAE;AAAA,IAClG;AAAA,EACF;AACF;",
6
6
  "names": []
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../src/helpers/fix-constants.js"],
3
+ "sources": ["../../src/helpers/fix-constants.js"],
4
4
  "sourcesContent": ["// This could be formatted so that 035-prefix and SID contents would be better connected than by just an array index\nexport const BIB_F035_TO_SID = {\n f035Filters: [/^\\(FI-BTJ\\)/u, /^\\(FI-TATI\\)/u],\n fSIDFilters: ['FI-BTJ', 'tati']\n};\n\n// There is somewhere other implementations of this same standardPrefixes to alephInternalPrefixes normalization\nexport const REPLACE_PREFIXES = [\n {\n oldPrefix: 'FI-MELINDA',\n newPrefix: 'FIN01',\n prefixReplaceCodes: ['w']\n },\n {\n oldPrefix: 'FI-ASTERI-S',\n newPrefix: 'FIN10',\n prefixReplaceCodes: ['0']\n },\n {\n oldPrefix: 'FI-ASTERI-N',\n newPrefix: 'FIN11',\n prefixReplaceCodes: ['0']\n },\n {\n oldPrefix: 'FI-ASTERI-A',\n newPrefix: 'FIN12',\n prefixReplaceCodes: ['0']\n },\n {\n oldPrefix: 'FI-ASTERI-W',\n newPrefix: 'FIN13',\n prefixReplaceCodes: ['0']\n }\n];\n\n// If placed in config.js testing needs envs\n// BIB_FORMAT_SETTINGS is outdated, use other settings instead\n\n\nexport const BIB_FORMAT_SETTINGS = {\n replacePrefixes: REPLACE_PREFIXES,\n generateMissingSIDs: BIB_F035_TO_SID\n};\n\nexport const BIB_PREVALIDATION_FIX_SETTINGS = {\n generateMissingSIDs: BIB_F035_TO_SID\n};\n\nexport const BIB_POSTMERGE_FIX_SETTINGS = {\n handleTempUrns: true,\n stripF884s: true\n};\n\nexport const BIB_PREIMPORT_FIX_SETTINGS = {\n replacePrefixes: REPLACE_PREFIXES,\n stripMelindaTempSubfields: true,\n stripF984s: true\n};\n\nexport const AUTNAME_PREIMPORT_FIX_SETTINGS = {\n replacePrefixes: REPLACE_PREFIXES\n};\n\nexport const BIB_HANDLE_TEMP_URNS_SETTINGS = {\n handleTempUrns: true\n};\n\nexport const BIB_STRIP_F884S_SETTINGS = {\n stripF884s: true\n};\n\nexport const BIB_STRIP_F984S_SETTINGS = {\n stripF984s: true\n};\n\nexport const BIB_STRIP_MELINDA_TEMP_SUBFIELDS_SETTINGS = {\n stripMelindaTempSubfields: true\n};\n"],
5
5
  "mappings": "AACO,aAAM,kBAAkB;AAAA,EAC7B,aAAa,CAAC,gBAAgB,eAAe;AAAA,EAC7C,aAAa,CAAC,UAAU,MAAM;AAChC;AAGO,aAAM,mBAAmB;AAAA,EAC9B;AAAA,IACE,WAAW;AAAA,IACX,WAAW;AAAA,IACX,oBAAoB,CAAC,GAAG;AAAA,EAC1B;AAAA,EACA;AAAA,IACE,WAAW;AAAA,IACX,WAAW;AAAA,IACX,oBAAoB,CAAC,GAAG;AAAA,EAC1B;AAAA,EACA;AAAA,IACE,WAAW;AAAA,IACX,WAAW;AAAA,IACX,oBAAoB,CAAC,GAAG;AAAA,EAC1B;AAAA,EACA;AAAA,IACE,WAAW;AAAA,IACX,WAAW;AAAA,IACX,oBAAoB,CAAC,GAAG;AAAA,EAC1B;AAAA,EACA;AAAA,IACE,WAAW;AAAA,IACX,WAAW;AAAA,IACX,oBAAoB,CAAC,GAAG;AAAA,EAC1B;AACF;AAMO,aAAM,sBAAsB;AAAA,EACjC,iBAAiB;AAAA,EACjB,qBAAqB;AACvB;AAEO,aAAM,iCAAiC;AAAA,EAC5C,qBAAqB;AACvB;AAEO,aAAM,6BAA6B;AAAA,EACxC,gBAAgB;AAAA,EAChB,YAAY;AACd;AAEO,aAAM,6BAA6B;AAAA,EACxC,iBAAiB;AAAA,EACjB,2BAA2B;AAAA,EAC3B,YAAY;AACd;AAEO,aAAM,iCAAiC;AAAA,EAC5C,iBAAiB;AACnB;AAEO,aAAM,gCAAgC;AAAA,EAC3C,gBAAgB;AAClB;AAEO,aAAM,2BAA2B;AAAA,EACtC,YAAY;AACd;AAEO,aAAM,2BAA2B;AAAA,EACtC,YAAY;AACd;AAEO,aAAM,4CAA4C;AAAA,EACvD,2BAA2B;AAC7B;",
6
6
  "names": []
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../src/helpers/fix-handle-tempurns.js"],
3
+ "sources": ["../../src/helpers/fix-handle-tempurns.js"],
4
4
  "sourcesContent": ["\n\n//import {MarcRecord} from '@natlibfi/marc-record';\nimport createDebugLogger from 'debug';\n\nconst debug = createDebugLogger('@natlibfi/melinda-rest-api-commons:fixRecord:handleTempUrns');\nconst debugData = debug.extend('data');\n\n// eslint-disable-next-line max-statements\nexport function handleTempUrns(newRecord, options) {\n\n if (options !== true) {\n debug(`NOT running handleTempUrns fixer, no options`);\n return newRecord;\n }\n\n debug(`Running handleTempUrns fixer`);\n debugData(`Options for handleTempUrns: ${JSON.stringify(options)}`);\n\n const {f856sUrnsWithTempSubfields, f856sUrnsWithNoTempSubfields} = getf856sUrns(newRecord);\n\n // None of the URNs has temp subfields, we don't need to do anything\n if (f856sUrnsWithTempSubfields.length < 1) {\n debug(`No Urns with temp subfield`);\n return newRecord;\n }\n\n // Do we have an existing URN with legal deposit subfields, if we have, we can remove the temp URN field(s)\n const existingLegalDepositURN = validateLD(f856sUrnsWithNoTempSubfields);\n debug(`existingLegalDepositURN: ${existingLegalDepositURN}`);\n\n if (existingLegalDepositURN) {\n debug(`We have an existing LD URN, we can delete temp fields (${f856sUrnsWithTempSubfields.length})`);\n newRecord.removeFields(f856sUrnsWithTempSubfields);\n return newRecord;\n }\n\n // We do not have an existing legalDepositURN, we should use the tempURN and remove the temp subfields from it\n if (!existingLegalDepositURN && f856sUrnsWithTempSubfields.length > 0) {\n //debug(`All Urns (${f856sUrn.length}) have a temp subfield`);\n debugData(`Original temp URNs: (${JSON.stringify(f856sUrnsWithTempSubfields)})`);\n const fixedFields = f856sUrnsWithTempSubfields.map(removeTempSubfield).filter(field => field);\n debug(`We removed temp subfields: (${JSON.stringify(fixedFields)})`);\n newRecord.removeFields(f856sUrnsWithTempSubfields);\n newRecord.insertFields(fixedFields);\n return newRecord;\n }\n // Should we check that the non-temp URN has 2nd ind '0' - meaning that the URN handles the actual resource itself?\n}\n\nfunction getf856sUrns(newRecord) {\n const hasURN = f => f.tag === '856' && f.subfields.some(({code, value}) => code === 'u' && (/urn.fi/u).test(value));\n\n const hasTempSubfield = f => f.subfields.some(({code, value}) => code === '9' && (/^MELINDA<TEMP>$/u).test(value));\n const hasNoTempSubfield = f => !f.subfields.some(({code, value}) => code === '9' && (/^MELINDA<TEMP>$/u).test(value));\n\n const f856sUrn = newRecord.fields.filter(hasURN);\n const f856sUrnsWithTempSubfields = f856sUrn.filter(hasTempSubfield);\n const f856sUrnsWithNoTempSubfields = f856sUrn.filter(hasNoTempSubfield);\n\n debugData(`URN f856s: ${JSON.stringify(f856sUrn)}`);\n debugData(`URN f856s with temp subfield: ${JSON.stringify(f856sUrnsWithTempSubfields)}`);\n return {f856sUrn, f856sUrnsWithTempSubfields, f856sUrnsWithNoTempSubfields};\n}\n\n\n// ---- LD-functions below are same as in https://github.com/NatLibFi/marc-record-validators-melinda/blob/feature-updates-to-urn/src/urn.js\n// we propably should develop the urn/legaldeposit -validator to use also here\n\nfunction validateLD(f856sUrn) {\n debug(`Validating the existence of legal deposit subfields`);\n\n const LD_SUBFIELDS_OLD = [\n {code: 'z', value: 'K\u00E4ytett\u00E4viss\u00E4 vapaakappalekirjastoissa'},\n {code: '5', value: 'FI-Vapaa'}\n ];\n\n const LD_SUBFIELDS_NEW = [\n {code: 'z', value: 'K\u00E4ytett\u00E4viss\u00E4 vapaakappalety\u00F6asemilla'},\n {code: '5', value: 'FI-Vapaa'}\n ];\n\n const f856sUrnWithOldLdSubfields = f856sUrn.filter(field => fieldHasLDSubfields(field, LD_SUBFIELDS_OLD));\n const f856sUrnWithNewLdSubfields = f856sUrn.filter(field => fieldHasLDSubfields(field, LD_SUBFIELDS_NEW));\n const f856sUrnWithLdSubfields = [...f856sUrnWithNewLdSubfields, ...f856sUrnWithOldLdSubfields];\n\n if (f856sUrnWithLdSubfields.length > 0) {\n debug(`Record has ${f856sUrnWithLdSubfields.length} URN fields with all necessary legal deposit subfields`);\n debugData(`f856sUrnWithLdSubfields: ${JSON.stringify(f856sUrnWithLdSubfields)}`);\n return true;\n }\n return false;\n}\n\nfunction fieldHasLDSubfields(field, ldSubfields) {\n if (ldSubfields.every(ldsf => field.subfields.some(sf => sf.code === ldsf.code && sf.value === ldsf.value))) {\n return true;\n }\n}\n\nfunction removeTempSubfield(field) {\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 !== '9' && !(/^MELINDA<TEMP>$/u).test(sf.value));\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"],
5
5
  "mappings": "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",
6
6
  "names": []
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../src/helpers/fix-strip-f884s.js"],
3
+ "sources": ["../../src/helpers/fix-strip-f884s.js"],
4
4
  "sourcesContent": ["import createDebugLogger from 'debug';\n//import {sortFieldsBySubfieldValue, removeSubfield} from './fix-utils';\nimport {inspect} from 'util';\nimport {MarcRecord} from '@natlibfi/marc-record';\n\nexport function stripF884s(newRecord, options) {\n const debug = createDebugLogger('@natlibfi/melinda-rest-api-commons:fixRecord:stripF884s');\n const debugData = debug.extend('data');\n\n if (options !== true) {\n debug(`NOT running stripF884s fixer, no options`);\n return newRecord;\n }\n\n debug(`Running stripF884s fixer`);\n debugData(`Options for stripF884s: ${JSON.stringify(options)}`);\n\n // Handle only f884 with $5 MELINDA - let's no remove random f884s\n const isMelindaf884 = f => f.tag === '884' && f.subfields.some(({code, value}) => code === '5' && value === 'MELINDA');\n\n const f884Melindas = newRecord.fields.filter(isMelindaf884);\n debugData(`Melinda's f884s (${f884Melindas.length}) \\n ${JSON.stringify(f884Melindas)}`);\n //debugData(`Melinda's f884s (${f884Melindas.length}) \\n ${inspect(f884Melindas, {depth: 3})}`);\n\n if (f884Melindas.length < 2) {\n debug(`Not enough Melinda's f884s to filter (${f884Melindas.length})`);\n return newRecord;\n }\n\n // Pick data (firstDate, lastDate, hash with latest date) for all conversion : source combinations\n const results = f884Melindas.reduce((allResults, f884, index) => {\n debugData(`All results: ${JSON.stringify(allResults)}`);\n //debugData(`Handling field (${index}): ${inspect(f884, {depth: 3})}`);\n debugData(`Handling field *(${index})*: ${JSON.stringify(f884)}`);\n\n const conversion = findConversion(f884);\n const source = findSource(f884);\n const convSource = `${conversion}:${source}`;\n const {firstDate, lastDate} = findDates(f884);\n const hash = findHash(f884);\n\n // Find currently existing data for conversion : source combination\n const currResult = allResults[convSource];\n debugData(JSON.stringify(currResult));\n\n // If we do not have any current data, add data from field\n if (!currResult) {\n debug(`Add a new convSource ${convSource} to results`);\n const newResult = {\n conversion,\n source,\n firstDate,\n lastDate,\n hash\n };\n debugData(`- New result: ${JSON.stringify(newResult)}`);\n return {\n ...allResults,\n [convSource]: newResult\n };\n }\n // If we have current data, update it from the data from field, if needed\n debug(`Update result for ${convSource}`);\n debugData(`- Current result: ${JSON.stringify(currResult)}`);\n\n const updatedResult = {\n ...currResult,\n firstDate: currResult.firstDate > firstDate && firstDate !== '00000000' ? firstDate : currResult.firstDate,\n lastDate: currResult.lastDate < lastDate ? lastDate : currResult.lastDate,\n hash: currResult.lastDate < lastDate && lastDate !== '00000000' && hash !== '0000000000000000000000000000000000000000000000000000000000000000' ? hash : currResult.hash\n };\n debugData(`- Updated result: ${JSON.stringify(updatedResult)}`);\n return {\n ...allResults,\n [convSource]: updatedResult\n };\n }, {});\n\n debugData(`RESULTS: ${JSON.stringify(results)}`);\n const editedf884s = editFields(f884Melindas, results);\n\n debug(`Edited fields (${editedf884s.length})`);\n //debugData(inspect(editedf884s, {depth: 3}));\n debugData(`${JSON.stringify(editedf884s)}`);\n\n // We update each field based on the results we got from fields\n // Note: we do not add $g:s or $k:s if the field doesn't have them\n function editFields(fields, results) {\n debug(`EDITING FIELDS (${fields.length})`);\n const editedFields = fields.map((field) => {\n const convSource = `${findConversion(field)}:${findSource(field)}`;\n debug(`Looking for: ${convSource}`);\n\n if (convSource && results[convSource]) {\n debugData(`Found: ${JSON.stringify(results[convSource])}`);\n const firstDate = results[convSource].firstDate && results[convSource].firstDate !== '00000000' ? results[convSource].firstDate : '';\n const lastDate = results[convSource].lastDate && results[convSource].lastDate !== '00000000' ? results[convSource].lastDate : '';\n\n const source = results[convSource].source && results[convSource].source !== 'NO_SOURCE' ? results[convSource].source : '';\n const hash = results[convSource].hash && results[convSource].hash !== '0000000000000000000000000000000000000000000000000000000000000000' ? results[convSource].hash : '';\n\n const sfGAll = firstDate === lastDate ? `${firstDate}` : `${firstDate} - ${lastDate}`;\n debugData(`EditedDates: ${sfGAll}`);\n const sfKAll = `${source}:${hash}`;\n\n const sfG = sfGAll.replace(/^ - /u, '').replace(/ - $/u, '');\n const sfK = sfKAll.replace(/^:/u, '').replace(/:$/u, '');\n\n return {\n ...field,\n subfields: field.subfields.map(subfield => {\n\n // we don't get $g or $k if the original field doesn't have them\n if (subfield.code === 'g') {\n return {\n code: subfield.code,\n value: sfG\n };\n }\n\n if (subfield.code === 'k') {\n return {\n code: subfield.code,\n value: sfK\n };\n }\n\n return subfield;\n })\n\n };\n }\n debug(`Not found: ${convSource}`);\n return field;\n });\n return editedFields;\n }\n\n // we'll need to uniq these too\n\n const uniq884s = uniqFields(editedf884s);\n debug(`UniqFields (${uniq884s.length})`);\n debugData(inspect(uniq884s, {depth: 3}));\n\n\n function uniqFields(fields) {\n return fields.reduce((uniq, field) => {\n if (!uniq.some(f => MarcRecord.isEqual(f, field))) {\n uniq.push(field);\n }\n\n return uniq;\n }, []);\n }\n // Replace original Melinda-f884s with remaining Melinda-f884s\n // NOTE: this sorts MELINDA-f884s after possible other f884s\n newRecord.removeFields(f884Melindas);\n newRecord.insertFields(uniq884s);\n\n return newRecord;\n\n\n // Find conversion:source pairs\n // Find first date\n // Find last date and last hash\n\n\n function findConversion(f884) {\n const [sfA] = f884.subfields.filter((subfield) => subfield.code === 'a').map(subfield => subfield.value);\n const conversion = sfA;\n debugData(`Conversion: \"${conversion}\"`);\n return conversion;\n }\n\n function findSource(f884) {\n const [sfK] = f884.subfields.filter((subfield) => subfield.code === 'k').map(subfield => subfield.value);\n const source = sfK.replace(/:.*$/u, '');\n if (source && source.length !== 64) {\n debugData(`Source: \"${source}\"`);\n return source;\n }\n const emptySource = 'NO_SOURCE';\n debugData(`Source: \"${emptySource}\"`);\n return emptySource;\n }\n\n function findHash(f884) {\n const [sfK] = f884.subfields.filter((subfield) => subfield.code === 'k').map(subfield => subfield.value);\n const hash = sfK.replace(/^.*:/u, '');\n if (hash && hash.length === 64) {\n debugData(`Hash: \"${hash}\"`);\n return hash;\n }\n const emptyHash = '0000000000000000000000000000000000000000000000000000000000000000';\n debugData(`Hash: \"${emptyHash}\"`);\n return emptyHash;\n }\n\n function findDates(f884) {\n const [sfG] = f884.subfields.filter((subfield) => subfield.code === 'g').map(subfield => subfield.value);\n if (sfG && (/ - /u).test(sfG)) {\n const firstDate = sfG.replace(/ - .*$/u, '').padStart(8, '0');\n const lastDate = sfG.replace(/^.* - /u, '').padStart(8, '0');\n debugData(`FirstDate: \"${firstDate}\", LastDate: \"${lastDate}\"`);\n return {firstDate, lastDate};\n }\n const firstDate = sfG ? sfG.padStart(8, '0') : '00000000';\n const lastDate = sfG ? sfG.padStart(8, '0') : '00000000';\n\n debugData(`FirstDate: \"${firstDate}\", LastDate: \"${lastDate}\"`);\n return {firstDate, lastDate};\n }\n\n}\n"],
5
5
  "mappings": "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",
6
6
  "names": ["results", "firstDate", "lastDate"]
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../src/helpers/fix-utils.js"],
3
+ "sources": ["../../src/helpers/fix-utils.js"],
4
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
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
6
  "names": ["subfieldCode"]
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../src/helpers/fix.js"],
3
+ "sources": ["../../src/helpers/fix.js"],
4
4
  "sourcesContent": ["import createDebugLogger from 'debug';\nimport {MarcRecord} from '@natlibfi/marc-record';\nimport {createLogger} from '@natlibfi/melinda-backend-commons';\n\nimport {FieldExclusion, SubfieldExclusion} from '@natlibfi/marc-record-validators-melinda';\n\nimport {handleTempUrns} from './fix-handle-tempurns.js';\nimport {stripF884s} from './fix-strip-f884s.js';\n\nexport * from './fix-constants.js';\n\nconst logger = createLogger();\nconst debug = createDebugLogger('@natlibfi/melinda-rest-api-commons:fixRecord');\nconst debugData = debug.extend('data');\n\nexport function fixRecord(record, settings = {}) {\n\n logger.verbose(`We will apply formatting to the record according to settings: ${JSON.stringify(settings)}`);\n const newRecord = MarcRecord.clone(record, {subfieldValues: false});\n debugData(`settings: ${JSON.stringify(settings)}`);\n\n // We should handle these in some prettier way ...\n\n // Fix 1, generate SIDs\n const generateMissingSIDsOptions = settings.generateMissingSIDs || undefined;\n const newRecord1 = generateMissingSIDs(newRecord, generateMissingSIDsOptions);\n\n // Fix 2, replace identifier prefixes\n const replacePrefixesOptions = settings.replacePrefixes || [];\n const newRecord2 = replaceAllPrefixes(newRecord1, replacePrefixesOptions);\n\n // Fix 3, handle temporary URNs from legal deposit record import\n const newRecord3 = handleTempUrns(newRecord2, settings.handleTempUrns);\n\n // Fix 4, strip extra field 884s\n const newRecord4 = stripF884s(newRecord3, settings.stripF884s);\n\n // Fix 5, strip extra field 984s\n const newRecord5 = stripF984s(newRecord4, settings.stripF984s || false);\n\n // Fix 6, strip $9 MELINDA<TEMP> subfields\n const newRecord6 = stripMelindaTempSubfields(newRecord5, settings.stripMelindaTempSubfields || false);\n\n debugData(newRecord6);\n\n return newRecord6.toObject();\n\n}\n\n\nfunction replaceAllPrefixes(record, replacePrefixesOptions) {\n if (replacePrefixesOptions.length < 1) {\n debug(`NOT running replacePrefixes, no options`);\n return record;\n }\n\n debug(`Running replacePrefixes fixer`);\n debugData(`replacePrefixesOptions: ${JSON.stringify(replacePrefixesOptions)}`);\n\n replacePrefixesOptions.forEach(options => {\n replacePrefix(record, options);\n });\n return record;\n}\n\n\n// Replace prefix in all specified subfields\nfunction replacePrefix(record, options) {\n const {oldPrefix, newPrefix, prefixReplaceCodes} = options;\n debug(`Replacing ${oldPrefix} with ${newPrefix} in subfields ${prefixReplaceCodes}`);\n const pattern = `(${oldPrefix})`;\n const replacement = `(${newPrefix})`;\n record.getDatafields()\n .forEach(field => {\n field.subfields\n .filter(({code}) => prefixReplaceCodes.includes(code))\n .forEach(subfield => {\n subfield.value = subfield.value.replace(pattern, replacement);\n });\n });\n return record;\n}\n\n\nfunction generateMissingSIDs(record, options) {\n\n const f035Filters = options && options.f035Filters ? options.f035Filters : [];\n const fSIDFilters = options && options.fSIDFilters ? options.fSIDFilters : [];\n\n if (f035Filters.length !== fSIDFilters.length || f035Filters.length < 1 || fSIDFilters.length < 1) {\n debug(`NOT running generateMissingsSIDs, no options`);\n return record;\n }\n\n debug(`Running generateMissingSIDs fixer`);\n debugData(`generateMissingSIDs options: ${JSON.stringify(options)}`);\n\n const f035s = f035ToSidInfo(record.get(/^035$/u));\n const fSIDs = sidsToSidInfo(record.get(/^SID$/u));\n\n const sidsToBeAdded = genNewSids(fSIDs.length === 0\n ? f035s\n // test that SIDs are not there yet\n : f035s.filter(f035SidInfo => !fSIDs.some(fSIDInfo => f035SidInfo.SID === fSIDInfo.SID && f035SidInfo.value === fSIDInfo.value)));\n\n debugData(`Adding (${sidsToBeAdded.length}) SIDs: ${JSON.stringify(sidsToBeAdded)}`);\n\n // Add new SIDs\n sidsToBeAdded.forEach(sidField => record.insertField(sidField));\n return record;\n\n function genNewSids(sidsToBeAdded) {\n return sidsToBeAdded.map(sidInfo => ({tag: 'SID', ind1: ' ', ind2: ' ', subfields: [{code: 'c', value: sidInfo.value}, {code: 'b', value: sidInfo.SID}]}));\n }\n\n function sidsToSidInfo(SIDs) {\n return SIDs.flatMap(({subfields}) => {\n const [SID] = subfields.filter(sub => sub.code === 'b' && fSIDFilters.includes(sub.value)).map(sub => sub.value);\n const [value] = subfields.filter(sub => sub.code === 'c' && sub.value !== undefined).map(sub => sub.value);\n\n if (SID && value) {\n return {\n SID,\n value\n };\n }\n\n return undefined;\n }).filter(value => value !== undefined);\n }\n\n function f035ToSidInfo(f035s) {\n return f035s.flatMap(({subfields}) => {\n const [wantedSub] = subfields.filter(sub => sub.code === 'a' && f035Filters.some(regexp => regexp.test(sub.value)));\n\n if (wantedSub) {\n return {\n SID: fSIDFilters[f035Filters.findIndex(regexp => regexp.test(wantedSub.value))],\n value: wantedSub.value.slice(wantedSub.value.indexOf(')') + 1)\n };\n }\n\n return undefined;\n }).filter(value => value !== undefined);\n }\n}\n\n\nfunction stripF984s(record, stripF984sSettings) {\n const F984A_PATTERN = /^(?:ALWAYS|NEVER)-PREFER-IN-MERGE$/u;\n const config = [\n {\n tag: /^984$/u,\n subfields: [\n {\n code: /a/u,\n value: F984A_PATTERN\n }\n ]\n }\n ];\n\n debug(`Running removeF984AFields`);\n debugData(`removeF984AFieldsSettings: ${JSON.stringify(stripF984sSettings)}`);\n\n if (!stripF984sSettings || !F984A_PATTERN || record.get('984').length < 1) {\n debug(`No settings or pattern for removeF984AFields or f984 in record`);\n return record;\n }\n\n debug(`Removing f984 fields with subfield $a consisting values ${F984A_PATTERN.toString()}`);\n // eslint-disable-next-line new-cap\n const validator = FieldExclusion(config);\n validator.fix(record);\n return record;\n\n}\n\nfunction stripMelindaTempSubfields(record, stripMelindaTempSubfieldsSettings) {\n if (!stripMelindaTempSubfieldsSettings) {\n debug(`No settings for stripMelindaTempSubfields`);\n return record;\n }\n // NOTE: we remove $9 MELINDA<TEMP> subfields only from f856\n const tagPattern = /856/u;\n const subfieldCodePattern = /9/u;\n const subfieldValuePattern = /^MELINDA<TEMP>$/u;\n const config = [\n {\n tag: tagPattern,\n subfields: [\n {\n code: subfieldCodePattern,\n value: subfieldValuePattern\n }\n ]\n }\n ];\n\n debug(`Running stripMelindaTempSubfields`);\n\n // eslint-disable-next-line new-cap\n const validator = SubfieldExclusion(config);\n validator.fix(record);\n return record;\n}\n"],
5
5
  "mappings": "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",
6
6
  "names": ["sidsToBeAdded", "f035s"]
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../src/helpers/validation.js"],
3
+ "sources": ["../../src/helpers/validation.js"],
4
4
  "sourcesContent": ["import validateFactory from '@natlibfi/marc-record-validate';\nimport {\n FieldStructure as fieldStructure\n} from '@natlibfi/marc-record-validators-melinda';\nimport {createLogger} from '@natlibfi/melinda-backend-commons';\n\nexport default async () => {\n const logger = createLogger();\n\n logger.verbose('Running inbuilt record validations');\n const validate = validateFactory([await fieldStructure([{tag: /^003$/u, valuePattern: /^FI-MELINDA$/u}])]);\n\n return async unvalidRecord => {\n const {record, valid, report} = await validate(unvalidRecord, {fix: false, validateFixes: false}, {subfieldValues: false});\n\n return {\n record,\n failed: valid === false,\n messages: report\n };\n };\n};\n"],
5
5
  "mappings": "AAAA,OAAO,qBAAqB;AAC5B;AAAA,EACE,kBAAkB;AAAA,OACb;AACP,SAAQ,oBAAmB;AAE3B,eAAe,YAAY;AACzB,QAAM,SAAS,aAAa;AAE5B,SAAO,QAAQ,oCAAoC;AACnD,QAAM,WAAW,gBAAgB,CAAC,MAAM,eAAe,CAAC,EAAC,KAAK,UAAU,cAAc,gBAAe,CAAC,CAAC,CAAC,CAAC;AAEzG,SAAO,OAAM,kBAAiB;AAC5B,UAAM,EAAC,QAAQ,OAAO,OAAM,IAAI,MAAM,SAAS,eAAe,EAAC,KAAK,OAAO,eAAe,MAAK,GAAG,EAAC,gBAAgB,MAAK,CAAC;AAEzH,WAAO;AAAA,MACL;AAAA,MACA,QAAQ,UAAU;AAAA,MAClB,UAAU;AAAA,IACZ;AAAA,EACF;AACF;",
6
6
  "names": []
package/dist/index.js ADDED
@@ -0,0 +1,10 @@
1
+ import mongoFactory from "./mongo.js";
2
+ import mongoLogFactory from "./mongoLog.js";
3
+ import amqpFactory from "./amqp.js";
4
+ import conversions from "./helpers/conversion.js";
5
+ import validations from "./helpers/validation.js";
6
+ import * as fixes from "./helpers/fix.js";
7
+ import { logError, createImportJobState, createRecordResponseItem, addRecordResponseItem, addRecordResponseItems } from "./utils.js";
8
+ export { mongoFactory, mongoLogFactory, amqpFactory, conversions, validations, fixes, logError, createImportJobState, createRecordResponseItem, addRecordResponseItem, addRecordResponseItems };
9
+ export * from "./constants.js";
10
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/index.js"],
4
+ "sourcesContent": ["\n\nimport mongoFactory from './mongo.js';\nimport mongoLogFactory from './mongoLog.js';\nimport amqpFactory from './amqp.js';\nimport conversions from './helpers/conversion.js';\nimport validations from './helpers/validation.js';\nimport * as fixes from './helpers/fix.js';\nimport {logError, createImportJobState, createRecordResponseItem, addRecordResponseItem, addRecordResponseItems} from './utils.js';\n\nexport {mongoFactory, mongoLogFactory, amqpFactory, conversions, validations, fixes, logError, createImportJobState, createRecordResponseItem, addRecordResponseItem, addRecordResponseItems};\nexport * from './constants.js';\n"],
5
+ "mappings": "AAEA,OAAO,kBAAkB;AACzB,OAAO,qBAAqB;AAC5B,OAAO,iBAAiB;AACxB,OAAO,iBAAiB;AACxB,OAAO,iBAAiB;AACxB,YAAY,WAAW;AACvB,SAAQ,UAAU,sBAAsB,0BAA0B,uBAAuB,8BAA6B;AAEtH,SAAQ,cAAc,iBAAiB,aAAa,aAAa,aAAa,OAAO,UAAU,sBAAsB,0BAA0B,uBAAuB;AACtK,cAAc;",
6
+ "names": []
7
+ }