@dmptool/utils 1.0.28 → 1.0.30
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/README.md +22 -15
- package/dist/general.d.ts +7 -0
- package/dist/general.js +13 -1
- package/dist/maDMP.js +45 -35
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -15,7 +15,7 @@ See below for usage examples of each utility.
|
|
|
15
15
|
- [AWS CloudFormation Stack Output Access](#cloudformation-support)
|
|
16
16
|
- [AWS DynamoDB Table Access](#dynamodb-support)
|
|
17
17
|
- [General Helper Functions](#general-helper-functions)
|
|
18
|
-
- [
|
|
18
|
+
- [SQS Message Publication](#sqs-support)
|
|
19
19
|
- [Logger Support (Pino with ECS formatting)](#logger-support-pino-with-ecs-formatting)
|
|
20
20
|
- [maDMP Support (serialization and deserialization)](#madmp-support-serialization-and-deserialization)
|
|
21
21
|
- [AWS RDS MySQL Database Access](#rds-mysql-support)
|
|
@@ -209,40 +209,40 @@ if (exists) {
|
|
|
209
209
|
}
|
|
210
210
|
}
|
|
211
211
|
```
|
|
212
|
-
##
|
|
212
|
+
## SQS Support
|
|
213
213
|
|
|
214
|
-
This code can be used to
|
|
214
|
+
This code can be used to send messages to an SQS Queue.
|
|
215
215
|
|
|
216
216
|
### Example usage
|
|
217
217
|
```typescript
|
|
218
|
-
import { initializeLogger,
|
|
218
|
+
import { initializeLogger, sendMessage, SendMessageResponse } from '@dmptool/utils';
|
|
219
219
|
|
|
220
220
|
const region = 'us-west-2';
|
|
221
221
|
|
|
222
222
|
// Initialize a logger
|
|
223
223
|
const logger: Logger = initializeLogger('exampleSSM', LogLevelEnum.DEBUG);
|
|
224
224
|
|
|
225
|
-
const
|
|
225
|
+
const queueURL = 'https://sqs.us-west-2.amazonaws.com/12345/my-example-function';
|
|
226
226
|
|
|
227
227
|
// See the documentation for the AWS Lambda you are trying to invoke to determine what the
|
|
228
228
|
// `detail-type` and `detail` payload should look like.
|
|
229
|
-
const source = 'my-application';
|
|
230
|
-
const detailType = 'my-
|
|
229
|
+
const source = 'my-application';
|
|
230
|
+
const detailType = 'my-message';
|
|
231
231
|
const detail = { property1: 'value1', property2: 'value2' }
|
|
232
232
|
|
|
233
|
-
const
|
|
233
|
+
const sent: SendMessageResponse = await sendMessage(
|
|
234
234
|
logger,
|
|
235
|
-
|
|
235
|
+
queueURL,
|
|
236
236
|
source,
|
|
237
237
|
detailType,
|
|
238
238
|
detail,
|
|
239
|
-
region
|
|
239
|
+
region,
|
|
240
240
|
);
|
|
241
241
|
|
|
242
|
-
if (
|
|
243
|
-
console.log('Message
|
|
242
|
+
if (sent && sent.status >= 200 && sent.status < 300) {
|
|
243
|
+
console.log('Message successfully sent', sent.status);
|
|
244
244
|
} else {
|
|
245
|
-
console.log('Error
|
|
245
|
+
console.log('Error sending message', sent.status, sent.messageId);
|
|
246
246
|
}
|
|
247
247
|
```
|
|
248
248
|
|
|
@@ -304,6 +304,7 @@ Environment variable requirements:
|
|
|
304
304
|
### Example usage
|
|
305
305
|
```typescript
|
|
306
306
|
import { Logger } from 'pino';
|
|
307
|
+
import { Context, SQSEvent, SQSHandler, SQSBatchResponse } from 'aws-lambda';
|
|
307
308
|
import { initializeLogger, LogLevel } from '@dmptool/utils';
|
|
308
309
|
|
|
309
310
|
process.env.AWS_REGION = 'us-west-2';
|
|
@@ -316,14 +317,20 @@ const logger: Logger = initializeLogger('GenerateMaDMPRecordLambda', LogLevel[LO
|
|
|
316
317
|
// Setup the LambdaRequestTracker for the logger
|
|
317
318
|
const withRequest = lambdaRequestTracker();
|
|
318
319
|
|
|
319
|
-
export const handler:
|
|
320
|
+
export const handler: SQSHandler = async (event: SQSEvent, context: Context): Promise<SQSBatchResponse> => {
|
|
320
321
|
// Log the incoming event and context
|
|
321
322
|
logger.debug({ event, context }, 'Received event');
|
|
322
323
|
|
|
323
324
|
// Initialize the logger by setting up automatic request tracing.
|
|
324
325
|
withRequest(event, context);
|
|
325
326
|
|
|
326
|
-
|
|
327
|
+
// Loop through the records in the event
|
|
328
|
+
for (const record of event.Records) {
|
|
329
|
+
logger.info({
|
|
330
|
+
log_level: LOG_LEVEL,
|
|
331
|
+
record_body: record.body
|
|
332
|
+
}, 'Processing record');
|
|
333
|
+
}
|
|
327
334
|
}
|
|
328
335
|
```
|
|
329
336
|
|
package/dist/general.d.ts
CHANGED
|
@@ -20,6 +20,13 @@ export declare const toErrorMessage: (error: unknown) => string;
|
|
|
20
20
|
* @returns a URL with the protocol converted to https
|
|
21
21
|
*/
|
|
22
22
|
export declare const normaliseHttpProtocol: (input: string | null) => string | null;
|
|
23
|
+
/**
|
|
24
|
+
* Function to determine if the string is a valid date / time
|
|
25
|
+
*
|
|
26
|
+
* @param dateString the date string to validate
|
|
27
|
+
* @returns true if the date string is valid, false otherwise
|
|
28
|
+
*/
|
|
29
|
+
export declare const isValidDate: (dateString: string) => boolean;
|
|
23
30
|
/**
|
|
24
31
|
*Function to return the current date.
|
|
25
32
|
*
|
package/dist/general.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.areEqual = exports.removeNullAndUndefinedFromObject = exports.isNullOrUndefined = exports.randomHex = exports.convertMySQLDateTimeToRFC3339 = exports.currentDateAsString = exports.normaliseHttpProtocol = exports.toErrorMessage = exports.EnvironmentEnum = void 0;
|
|
3
|
+
exports.areEqual = exports.removeNullAndUndefinedFromObject = exports.isNullOrUndefined = exports.randomHex = exports.convertMySQLDateTimeToRFC3339 = exports.currentDateAsString = exports.isValidDate = exports.normaliseHttpProtocol = exports.toErrorMessage = exports.EnvironmentEnum = void 0;
|
|
4
4
|
/**
|
|
5
5
|
* Possible environments for the application.
|
|
6
6
|
*/
|
|
@@ -35,6 +35,18 @@ const normaliseHttpProtocol = (input) => {
|
|
|
35
35
|
return input.trim().replace(/^http:\/\//, 'https://');
|
|
36
36
|
};
|
|
37
37
|
exports.normaliseHttpProtocol = normaliseHttpProtocol;
|
|
38
|
+
/**
|
|
39
|
+
* Function to determine if the string is a valid date / time
|
|
40
|
+
*
|
|
41
|
+
* @param dateString the date string to validate
|
|
42
|
+
* @returns true if the date string is valid, false otherwise
|
|
43
|
+
*/
|
|
44
|
+
const isValidDate = (dateString) => {
|
|
45
|
+
const date = Date.parse(dateString);
|
|
46
|
+
// A valid date will return a number, an invalid one will return NaN
|
|
47
|
+
return !Number.isNaN(date);
|
|
48
|
+
};
|
|
49
|
+
exports.isValidDate = isValidDate;
|
|
38
50
|
/**
|
|
39
51
|
*Function to return the current date.
|
|
40
52
|
*
|
package/dist/maDMP.js
CHANGED
|
@@ -382,34 +382,43 @@ const loadNarrativeTemplateInfo = async (rdsConnectionParams, planId) => {
|
|
|
382
382
|
section: [],
|
|
383
383
|
};
|
|
384
384
|
results.forEach((row) => {
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
curSection
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
? {
|
|
408
|
-
id: row.answerId,
|
|
409
|
-
json: row.answerJSON
|
|
385
|
+
if (row.sectionId !== null && row.sectionId !== undefined) {
|
|
386
|
+
// Sections may have several rows in the results, so we need to check if we
|
|
387
|
+
// already have the section defined.
|
|
388
|
+
let curSection = narrative.section.find((s) => {
|
|
389
|
+
return s.id === row.sectionId;
|
|
390
|
+
});
|
|
391
|
+
if (curSection === undefined || curSection === null) {
|
|
392
|
+
curSection = {
|
|
393
|
+
id: row.sectionId,
|
|
394
|
+
title: row.sectionTitle,
|
|
395
|
+
description: row.sectionDescription !== null ? row.sectionDescription : undefined,
|
|
396
|
+
order: row.sectionOrder !== null ? row.sectionOrder : 0,
|
|
397
|
+
question: [],
|
|
398
|
+
};
|
|
399
|
+
narrative.section.push(curSection);
|
|
400
|
+
}
|
|
401
|
+
if (row.questionId !== null && row.questionId !== undefined) {
|
|
402
|
+
const hasAnswer = row.answerJSON !== undefined && row.answerJSON !== null;
|
|
403
|
+
if (hasAnswer) {
|
|
404
|
+
// parse the nested answer value which is stored as a JSON string
|
|
405
|
+
const answerVal = hasAnswer ? JSON.parse(row.answerJSON.answer) : undefined;
|
|
406
|
+
row.answerJSON.answer = answerVal;
|
|
410
407
|
}
|
|
411
|
-
|
|
412
|
-
|
|
408
|
+
// Every row in the results represents a single question/answer pair
|
|
409
|
+
curSection.question.push({
|
|
410
|
+
id: row.questionId,
|
|
411
|
+
text: row.questionText,
|
|
412
|
+
order: row.questionOrder !== null ? row.questionOrder : 0,
|
|
413
|
+
answer: hasAnswer
|
|
414
|
+
? {
|
|
415
|
+
id: row.answerId,
|
|
416
|
+
json: row.answerJSON
|
|
417
|
+
}
|
|
418
|
+
: undefined
|
|
419
|
+
});
|
|
420
|
+
}
|
|
421
|
+
}
|
|
413
422
|
});
|
|
414
423
|
return narrative;
|
|
415
424
|
};
|
|
@@ -525,7 +534,7 @@ const buildContributors = (applicationName, env, planId, projectId, members, def
|
|
|
525
534
|
* @returns the DMP metadata with extensions from the DMP Tool
|
|
526
535
|
*/
|
|
527
536
|
const buildDMPToolExtensions = async (rdsConnectionParams, applicationName, domainName, plan, project, funding) => {
|
|
528
|
-
var _a, _b, _c, _d
|
|
537
|
+
var _a, _b, _c, _d;
|
|
529
538
|
const extensions = {
|
|
530
539
|
rda_schema_version: types_1.RDA_COMMON_STANDARD_VERSION,
|
|
531
540
|
// Ignoring the `!` assertion here because we know we check the env variable
|
|
@@ -533,8 +542,8 @@ const buildDMPToolExtensions = async (rdsConnectionParams, applicationName, doma
|
|
|
533
542
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
534
543
|
provenance: applicationName,
|
|
535
544
|
featured: plan.featured ? 'yes' : 'no',
|
|
536
|
-
privacy:
|
|
537
|
-
status: (
|
|
545
|
+
privacy: plan.visibility === 'PUBLIC' ? 'public' : 'private',
|
|
546
|
+
status: (_b = (_a = plan.status) === null || _a === void 0 ? void 0 : _a.toLowerCase()) !== null && _b !== void 0 ? _b : 'draft',
|
|
538
547
|
};
|
|
539
548
|
// Generate the DMP Narrative
|
|
540
549
|
const narrative = await loadNarrativeTemplateInfo(rdsConnectionParams, plan.id);
|
|
@@ -570,7 +579,7 @@ const buildDMPToolExtensions = async (rdsConnectionParams, applicationName, doma
|
|
|
570
579
|
funder_id: funderId,
|
|
571
580
|
project_identifier: {
|
|
572
581
|
identifier: funding.funderProjectNumber,
|
|
573
|
-
type: ((
|
|
582
|
+
type: ((_c = funding.funderProjectNumber) === null || _c === void 0 ? void 0 : _c.startsWith('http'))
|
|
574
583
|
? maDMPTypes_1.StandardIdentifierType.URL
|
|
575
584
|
: maDMPTypes_1.StandardIdentifierType.OTHER
|
|
576
585
|
}
|
|
@@ -585,7 +594,7 @@ const buildDMPToolExtensions = async (rdsConnectionParams, applicationName, doma
|
|
|
585
594
|
funder_id: funderId,
|
|
586
595
|
opportunity_identifier: {
|
|
587
596
|
identifier: funding.funderOpportunityNumber,
|
|
588
|
-
type: ((
|
|
597
|
+
type: ((_d = funding.funderOpportunityNumber) === null || _d === void 0 ? void 0 : _d.startsWith('http'))
|
|
589
598
|
? maDMPTypes_1.StandardIdentifierType.URL
|
|
590
599
|
: maDMPTypes_1.StandardIdentifierType.OTHER
|
|
591
600
|
}
|
|
@@ -608,8 +617,9 @@ const buildDMPToolExtensions = async (rdsConnectionParams, applicationName, doma
|
|
|
608
617
|
extensions.funding_opportunity = [funderOpportunity];
|
|
609
618
|
}
|
|
610
619
|
if (!(0, general_1.isNullOrUndefined)(narrative)) {
|
|
620
|
+
const id = plan.dmpId.replace('https://doi.org/', '');
|
|
611
621
|
extensions.narrative = {
|
|
612
|
-
download_url: `https://${domainName}/dmps/${
|
|
622
|
+
download_url: `https://${domainName}/dmps/${id}/narrative`,
|
|
613
623
|
template: narrative
|
|
614
624
|
};
|
|
615
625
|
}
|
|
@@ -663,8 +673,8 @@ const buildProject = (applicationName, planId, project, funding) => {
|
|
|
663
673
|
return {
|
|
664
674
|
title: project.title,
|
|
665
675
|
description: (_c = project.abstractText) !== null && _c !== void 0 ? _c : undefined,
|
|
666
|
-
start: (_d = project.startDate) !== null && _d !== void 0 ? _d : undefined,
|
|
667
|
-
end: (_e = project.endDate) !== null && _e !== void 0 ? _e : undefined,
|
|
676
|
+
start: (0, general_1.isValidDate)((_d = project.startDate) !== null && _d !== void 0 ? _d : '') ? project.startDate : undefined,
|
|
677
|
+
end: (0, general_1.isValidDate)((_e = project.endDate) !== null && _e !== void 0 ? _e : '') ? project.endDate : undefined,
|
|
668
678
|
project_id: [{
|
|
669
679
|
identifier: internalIdBase(applicationName, project.id, planId),
|
|
670
680
|
type: 'other'
|
package/package.json
CHANGED