@dmptool/utils 1.0.27 → 1.0.29

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/dynamo.js CHANGED
@@ -671,7 +671,6 @@ exports.deleteDMP = deleteDMP;
671
671
  // We're not currently using it, but did not want to remove it just in case
672
672
  // we need it in the future
673
673
  //
674
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
675
674
  const scanTable = async (dynamoConnectionParams, params) => {
676
675
  if (!dynamoConnectionParams || !params) {
677
676
  throw new DMPToolDynamoError('Missing Dynamo config or params');
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/index.d.ts CHANGED
@@ -1,10 +1,10 @@
1
1
  export * from './cloudFormation';
2
2
  export * from './dynamo';
3
- export * from './eventBridge';
4
3
  export * from './general';
5
4
  export * from './logger';
6
5
  export * from './maDMP';
7
6
  export * from './maDMPTypes';
8
7
  export * from './rds';
9
8
  export * from './s3';
9
+ export * from './sqs';
10
10
  export * from './ssm';
package/dist/index.js CHANGED
@@ -17,11 +17,11 @@ Object.defineProperty(exports, "__esModule", { value: true });
17
17
  // Entrypoint for the package
18
18
  __exportStar(require("./cloudFormation"), exports);
19
19
  __exportStar(require("./dynamo"), exports);
20
- __exportStar(require("./eventBridge"), exports);
21
20
  __exportStar(require("./general"), exports);
22
21
  __exportStar(require("./logger"), exports);
23
22
  __exportStar(require("./maDMP"), exports);
24
23
  __exportStar(require("./maDMPTypes"), exports);
25
24
  __exportStar(require("./rds"), exports);
26
25
  __exportStar(require("./s3"), exports);
26
+ __exportStar(require("./sqs"), exports);
27
27
  __exportStar(require("./ssm"), exports);
package/dist/maDMP.js CHANGED
@@ -382,34 +382,38 @@ const loadNarrativeTemplateInfo = async (rdsConnectionParams, planId) => {
382
382
  section: [],
383
383
  };
384
384
  results.forEach((row) => {
385
- // Sections may have several rows in the results, so we need to check if we
386
- // already have the section defined.
387
- let curSection = narrative.section.find((s) => {
388
- return s.id === row.sectionId;
389
- });
390
- if (curSection === undefined || curSection === null) {
391
- curSection = {
392
- id: row.sectionId,
393
- title: row.sectionTitle,
394
- description: row.sectionDescription !== null ? row.sectionDescription : undefined,
395
- order: row.sectionOrder !== null ? row.sectionOrder : 0,
396
- question: [],
397
- };
398
- narrative.section.push(curSection);
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
+ // Every row in the results represents a single question/answer pair
404
+ curSection.question.push({
405
+ id: row.questionId,
406
+ text: row.questionText,
407
+ order: row.questionOrder !== null ? row.questionOrder : 0,
408
+ answer: hasAnswer
409
+ ? {
410
+ id: row.answerId,
411
+ json: row.answerJSON
412
+ }
413
+ : undefined
414
+ });
415
+ }
399
416
  }
400
- const hasAnswer = row.answerJSON !== undefined && row.answerJSON !== null;
401
- // Every row in the results represents a single question/answer pair
402
- curSection.question.push({
403
- id: row.questionId,
404
- text: row.questionText,
405
- order: row.questionOrder !== null ? row.questionOrder : 0,
406
- answer: hasAnswer
407
- ? {
408
- id: row.answerId,
409
- json: row.answerJSON
410
- }
411
- : undefined
412
- });
413
417
  });
414
418
  return narrative;
415
419
  };
@@ -525,7 +529,7 @@ const buildContributors = (applicationName, env, planId, projectId, members, def
525
529
  * @returns the DMP metadata with extensions from the DMP Tool
526
530
  */
527
531
  const buildDMPToolExtensions = async (rdsConnectionParams, applicationName, domainName, plan, project, funding) => {
528
- var _a, _b, _c, _d, _e, _f;
532
+ var _a, _b, _c, _d;
529
533
  const extensions = {
530
534
  rda_schema_version: types_1.RDA_COMMON_STANDARD_VERSION,
531
535
  // Ignoring the `!` assertion here because we know we check the env variable
@@ -533,8 +537,8 @@ const buildDMPToolExtensions = async (rdsConnectionParams, applicationName, doma
533
537
  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
534
538
  provenance: applicationName,
535
539
  featured: plan.featured ? 'yes' : 'no',
536
- privacy: (_b = (_a = plan.visibility) === null || _a === void 0 ? void 0 : _a.toLowerCase()) !== null && _b !== void 0 ? _b : 'private',
537
- status: (_d = (_c = plan.status) === null || _c === void 0 ? void 0 : _c.toLowerCase()) !== null && _d !== void 0 ? _d : 'draft',
540
+ privacy: plan.visibility === 'PUBLIC' ? 'public' : 'private',
541
+ status: (_b = (_a = plan.status) === null || _a === void 0 ? void 0 : _a.toLowerCase()) !== null && _b !== void 0 ? _b : 'draft',
538
542
  };
539
543
  // Generate the DMP Narrative
540
544
  const narrative = await loadNarrativeTemplateInfo(rdsConnectionParams, plan.id);
@@ -570,7 +574,7 @@ const buildDMPToolExtensions = async (rdsConnectionParams, applicationName, doma
570
574
  funder_id: funderId,
571
575
  project_identifier: {
572
576
  identifier: funding.funderProjectNumber,
573
- type: ((_e = funding.funderProjectNumber) === null || _e === void 0 ? void 0 : _e.startsWith('http'))
577
+ type: ((_c = funding.funderProjectNumber) === null || _c === void 0 ? void 0 : _c.startsWith('http'))
574
578
  ? maDMPTypes_1.StandardIdentifierType.URL
575
579
  : maDMPTypes_1.StandardIdentifierType.OTHER
576
580
  }
@@ -585,7 +589,7 @@ const buildDMPToolExtensions = async (rdsConnectionParams, applicationName, doma
585
589
  funder_id: funderId,
586
590
  opportunity_identifier: {
587
591
  identifier: funding.funderOpportunityNumber,
588
- type: ((_f = funding.funderOpportunityNumber) === null || _f === void 0 ? void 0 : _f.startsWith('http'))
592
+ type: ((_d = funding.funderOpportunityNumber) === null || _d === void 0 ? void 0 : _d.startsWith('http'))
589
593
  ? maDMPTypes_1.StandardIdentifierType.URL
590
594
  : maDMPTypes_1.StandardIdentifierType.OTHER
591
595
  }
@@ -608,8 +612,9 @@ const buildDMPToolExtensions = async (rdsConnectionParams, applicationName, doma
608
612
  extensions.funding_opportunity = [funderOpportunity];
609
613
  }
610
614
  if (!(0, general_1.isNullOrUndefined)(narrative)) {
615
+ const id = plan.dmpId.replace('https://doi.org/', '');
611
616
  extensions.narrative = {
612
- download_url: `https://${domainName}/dmps/${plan.dmpId}/narrative`,
617
+ download_url: `https://${domainName}/dmps/${id}/narrative`,
613
618
  template: narrative
614
619
  };
615
620
  }
@@ -663,8 +668,8 @@ const buildProject = (applicationName, planId, project, funding) => {
663
668
  return {
664
669
  title: project.title,
665
670
  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,
671
+ start: (0, general_1.isValidDate)((_d = project.startDate) !== null && _d !== void 0 ? _d : '') ? project.startDate : undefined,
672
+ end: (0, general_1.isValidDate)((_e = project.endDate) !== null && _e !== void 0 ? _e : '') ? project.endDate : undefined,
668
673
  project_id: [{
669
674
  identifier: internalIdBase(applicationName, project.id, planId),
670
675
  type: 'other'
package/dist/sqs.d.ts ADDED
@@ -0,0 +1,19 @@
1
+ import { Logger } from 'pino';
2
+ export interface SendMessageResponse {
3
+ status: number;
4
+ message: string;
5
+ messageId?: string;
6
+ }
7
+ /**
8
+ * Send an SQS message to the specified queue.
9
+ *
10
+ * @param logger The logger to use for logging.
11
+ * @param queueURL The endpoint of the SQS queue to send the message to.
12
+ * @param source The name of the caller (e.g. the Lambda Function or Application Function)
13
+ * @param detailType The type of message
14
+ * @param detail The payload of the message (will be accessible to the invoked resource)
15
+ * @param region The region to publish the message in. Defaults to 'us-west-2'.
16
+ * @returns A SendMessageResponse object containing the status code and message info.
17
+ * @throws Error if there was an error sending the message
18
+ */
19
+ export declare const sendMessage: (logger: Logger, queueURL: string, source: string, detailType: string, details: Record<string, unknown>, region?: string) => Promise<SendMessageResponse>;
package/dist/sqs.js ADDED
@@ -0,0 +1,66 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.sendMessage = void 0;
4
+ const client_sqs_1 = require("@aws-sdk/client-sqs");
5
+ const general_1 = require("./general");
6
+ /**
7
+ * Send an SQS message to the specified queue.
8
+ *
9
+ * @param logger The logger to use for logging.
10
+ * @param queueURL The endpoint of the SQS queue to send the message to.
11
+ * @param source The name of the caller (e.g. the Lambda Function or Application Function)
12
+ * @param detailType The type of message
13
+ * @param detail The payload of the message (will be accessible to the invoked resource)
14
+ * @param region The region to publish the message in. Defaults to 'us-west-2'.
15
+ * @returns A SendMessageResponse object containing the status code and message info.
16
+ * @throws Error if there was an error sending the message
17
+ */
18
+ const sendMessage = async (logger, queueURL, source, detailType, details, region = 'us-west-2') => {
19
+ var _a, _b;
20
+ let errMsg = '';
21
+ if (logger && queueURL) {
22
+ // Create a new SQS client instance
23
+ const client = new client_sqs_1.SQSClient({ region });
24
+ logger.debug({ queueURL, source, detailType, details }, 'Sending message');
25
+ try {
26
+ // Send the message
27
+ const response = await client.send(new client_sqs_1.SendMessageCommand({
28
+ QueueUrl: queueURL,
29
+ MessageBody: JSON.stringify(Object.assign(Object.assign({}, details), { source })),
30
+ MessageAttributes: {
31
+ "DetailType": {
32
+ "DataType": "String",
33
+ "StringValue": detailType
34
+ }
35
+ }
36
+ }));
37
+ if (response) {
38
+ const statusCode = (_b = (_a = response.$metadata) === null || _a === void 0 ? void 0 : _a.httpStatusCode) !== null && _b !== void 0 ? _b : 500;
39
+ // We got a response, so return it.
40
+ return {
41
+ status: statusCode,
42
+ message: statusCode >= 200 && statusCode <= 300 ? "Ok" : "Failure",
43
+ messageId: response.MessageId
44
+ };
45
+ }
46
+ else {
47
+ logger.error({ queueURL, source, detailType, details }, 'No response from SQS');
48
+ errMsg = 'No response from SQS';
49
+ }
50
+ }
51
+ catch (error) {
52
+ logger.fatal({ queueURL, source, detailType, details, error }, 'Error sending message');
53
+ errMsg = `Error sending message: ${(0, general_1.toErrorMessage)(error)}`;
54
+ }
55
+ }
56
+ else {
57
+ errMsg = 'Missing logger or queueURL args!';
58
+ }
59
+ // The SQS was not available or the response was undefined
60
+ return {
61
+ status: 500,
62
+ message: errMsg,
63
+ messageId: undefined
64
+ };
65
+ };
66
+ exports.sendMessage = sendMessage;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dmptool/utils",
3
- "version": "1.0.27",
3
+ "version": "1.0.29",
4
4
  "description": "Helper/Utility functions for use in the DMP Tool services. Particularly AWS tooling and maDMP serialization",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -43,7 +43,7 @@
43
43
  "peerDependencies": {
44
44
  "@aws-sdk/client-cloudformation": "^3.966.0",
45
45
  "@aws-sdk/client-dynamodb": "^3.966.0",
46
- "@aws-sdk/client-eventbridge": "^3.968.0",
46
+ "@aws-sdk/client-sqs": "^3.968.0",
47
47
  "@aws-sdk/client-s3": "^3.966.0",
48
48
  "@aws-sdk/client-sns": "^3.967.0",
49
49
  "@aws-sdk/client-ssm": "^3.966.0",
@@ -1,19 +0,0 @@
1
- import { Logger } from 'pino';
2
- export interface PutEventResponse {
3
- status: number;
4
- message: string;
5
- eventId?: string;
6
- }
7
- /**
8
- * Publishes an event to EventBridge.
9
- *
10
- * @param logger The logger to use for logging.
11
- * @param busName The name of the EventBridge bus to publish the event to.
12
- * @param source The name of the caller (e.g. the Lambda Function or Application Function)
13
- * @param detailType The type of event (resources typically watch for specific types of events)
14
- * @param detail The payload of the event (will be accessible to the invoked resource)
15
- * @param region The region to publish the event in. Defaults to 'us-west-2'.
16
- * @returns A PutEventResponse object containing the status code and message of the response from EventBridge.
17
- * @throws Error if there was an error publishing the event.
18
- */
19
- export declare const putEvent: (logger: Logger, busName: string, source: string, detailType: string, details: Record<string, unknown>, region?: string) => Promise<PutEventResponse>;
@@ -1,66 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.putEvent = void 0;
4
- const client_eventbridge_1 = require("@aws-sdk/client-eventbridge");
5
- const general_1 = require("./general");
6
- /**
7
- * Publishes an event to EventBridge.
8
- *
9
- * @param logger The logger to use for logging.
10
- * @param busName The name of the EventBridge bus to publish the event to.
11
- * @param source The name of the caller (e.g. the Lambda Function or Application Function)
12
- * @param detailType The type of event (resources typically watch for specific types of events)
13
- * @param detail The payload of the event (will be accessible to the invoked resource)
14
- * @param region The region to publish the event in. Defaults to 'us-west-2'.
15
- * @returns A PutEventResponse object containing the status code and message of the response from EventBridge.
16
- * @throws Error if there was an error publishing the event.
17
- */
18
- const putEvent = async (logger, busName, source, detailType, details, region = 'us-west-2') => {
19
- var _a, _b, _c, _d;
20
- let errMsg = '';
21
- if (logger && busName) {
22
- // Create a new EventBridge client instance
23
- const client = new client_eventbridge_1.EventBridgeClient({ region });
24
- logger.debug({ busName, source, detailType, details }, 'Publishing event');
25
- try {
26
- // Publish the event
27
- const response = await client.send(new client_eventbridge_1.PutEventsCommand({
28
- Entries: [
29
- {
30
- EventBusName: busName,
31
- Detail: details ? JSON.stringify(details) : undefined,
32
- DetailType: detailType,
33
- Source: source,
34
- },
35
- ],
36
- }));
37
- if (response) {
38
- const statusCode = (_b = (_a = response.$metadata) === null || _a === void 0 ? void 0 : _a.httpStatusCode) !== null && _b !== void 0 ? _b : 500;
39
- // We got a response, so return it.
40
- return {
41
- status: statusCode,
42
- message: statusCode >= 200 && statusCode <= 300 ? "Ok" : "Failure",
43
- eventId: (_d = (_c = response.Entries) === null || _c === void 0 ? void 0 : _c[0]) === null || _d === void 0 ? void 0 : _d.EventId
44
- };
45
- }
46
- else {
47
- logger.error({ busName, source, detailType, details }, 'No response from EventBridge');
48
- errMsg = 'No response from EventBridge';
49
- }
50
- }
51
- catch (error) {
52
- logger.fatal({ busName, source, detailType, details, error }, 'Error publishing event');
53
- errMsg = `Error publishing event: ${(0, general_1.toErrorMessage)(error)}`;
54
- }
55
- }
56
- else {
57
- errMsg = 'Missing logger or busName args!';
58
- }
59
- // The busName was not available or the response was undefined
60
- return {
61
- status: 500,
62
- message: errMsg,
63
- eventId: undefined
64
- };
65
- };
66
- exports.putEvent = putEvent;