@dmptool/utils 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,48 @@
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
+ /**
6
+ * Publishes an event to EventBridge.
7
+ *
8
+ * @param source The name of the caller (e.g. the Lambda Function or Application Function)
9
+ * @param detailType The type of event (resources typically watch for specific types of events)
10
+ * @param detail The payload of the event (will be accessible to the invoked resource)
11
+ */
12
+ const putEvent = async (source, detailType, details) => {
13
+ var _a, _b, _c, _d, _e;
14
+ const busName = process.env.EVENTBRIDGE_BUS_NAME;
15
+ if (busName) {
16
+ // Create a new EventBridge client instance
17
+ const client = new client_eventbridge_1.EventBridgeClient({
18
+ region: (_a = process.env.AWS_REGION) !== null && _a !== void 0 ? _a : "us-west-2",
19
+ });
20
+ // Publish the event
21
+ const response = await client.send(new client_eventbridge_1.PutEventsCommand({
22
+ Entries: [
23
+ {
24
+ EventBusName: busName,
25
+ Detail: details ? JSON.stringify(details) : undefined,
26
+ DetailType: detailType,
27
+ Source: source,
28
+ },
29
+ ],
30
+ }));
31
+ if (response) {
32
+ const statusCode = (_c = (_b = response.$metadata) === null || _b === void 0 ? void 0 : _b.httpStatusCode) !== null && _c !== void 0 ? _c : 500;
33
+ // We got a response, so return it.
34
+ return {
35
+ status: statusCode,
36
+ message: statusCode >= 200 && statusCode <= 300 ? "Ok" : "Failure",
37
+ eventId: (_e = (_d = response.Entries) === null || _d === void 0 ? void 0 : _d[0]) === null || _e === void 0 ? void 0 : _e.EventId
38
+ };
39
+ }
40
+ }
41
+ // The busName was not available or the response was undefined
42
+ return {
43
+ status: 500,
44
+ message: `Failure: ${busName ? 'Unable to put event.' : 'Missing EVENTBRIDGE_BUS_NAME variable!'}`,
45
+ eventId: undefined
46
+ };
47
+ };
48
+ exports.putEvent = putEvent;
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Convert an error to a string
3
+ *
4
+ * @param error the error to convert
5
+ * @returns the error message
6
+ */
7
+ export declare const toErrorMessage: (error: unknown) => string;
8
+ /**
9
+ * Convert http to https
10
+ *
11
+ * @param input a URL with the protocol
12
+ * @returns a URL with the protocol converted to https
13
+ */
14
+ export declare const normaliseHttpProtocol: (input: string | null) => string | null;
15
+ /**
16
+ *Function to return the current date.
17
+ *
18
+ * @returns The current date as YYYY-MM-DD.
19
+ */
20
+ export declare const currentDateAsString: () => string;
21
+ /**
22
+ * Function to convert a MySQL DB date/time (in ISO `YYY-MM-DDThh:mm:ddZ` format to RFC3339 format
23
+ *
24
+ * @param dateTime the MySQL DB date/time to convert
25
+ * @returns the converted date/time in RFC3339 format
26
+ */
27
+ export declare const convertMySQLDateTimeToRFC3339: (dateTime: string | Date | null | undefined) => string | null;
28
+ /**
29
+ * Generate a random hex code
30
+ *
31
+ * @param size the size of the hex code to generate
32
+ * @returns a random hex code
33
+ */
34
+ export declare const randomHex: (size: number) => string;
35
+ /**
36
+ * Function to check if a value is null or undefined.
37
+ *
38
+ * @param val
39
+ * @returns True if the value is null or undefined, false otherwise.
40
+ */
41
+ export declare const isNullOrUndefined: (val: unknown) => boolean;
42
+ /**
43
+ * Remove null and undefined values from an object or array.
44
+ *
45
+ * @param obj An object (may contain nested objects and arrays)
46
+ * @returns The object with null and undefined values removed.
47
+ */
48
+ export declare const removeNullAndUndefinedFromObject: (obj: any) => any;
49
+ /**
50
+ * Function to test for equality between two objects, arrays or primitives
51
+ *
52
+ * @param a An object (may contain nested objects and arrays)
53
+ * @param b Another object (may contain nested objects and arrays)
54
+ * @returns True if the objects are equal, false otherwise
55
+ */
56
+ export declare const areEqual: (a: any, b: any) => boolean;
@@ -0,0 +1,142 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.areEqual = exports.removeNullAndUndefinedFromObject = exports.isNullOrUndefined = exports.randomHex = exports.convertMySQLDateTimeToRFC3339 = exports.currentDateAsString = exports.normaliseHttpProtocol = exports.toErrorMessage = void 0;
4
+ /**
5
+ * Convert an error to a string
6
+ *
7
+ * @param error the error to convert
8
+ * @returns the error message
9
+ */
10
+ const toErrorMessage = (error) => {
11
+ if (error instanceof Error)
12
+ return error.message;
13
+ return String(error);
14
+ };
15
+ exports.toErrorMessage = toErrorMessage;
16
+ /**
17
+ * Convert http to https
18
+ *
19
+ * @param input a URL with the protocol
20
+ * @returns a URL with the protocol converted to https
21
+ */
22
+ const normaliseHttpProtocol = (input) => {
23
+ if (!input) {
24
+ return null;
25
+ }
26
+ return input.trim().replace(/^http:\/\//, 'https://');
27
+ };
28
+ exports.normaliseHttpProtocol = normaliseHttpProtocol;
29
+ /**
30
+ *Function to return the current date.
31
+ *
32
+ * @returns The current date as YYYY-MM-DD.
33
+ */
34
+ // Function to return the current date as "YYYY-MM-DD"
35
+ const currentDateAsString = () => {
36
+ const now = new Date();
37
+ // Extract components
38
+ const year = now.getFullYear();
39
+ // Months are 0-indexed so need to add 1 here
40
+ const month = String(now.getMonth() + 1).padStart(2, '0');
41
+ const day = String(now.getDate()).padStart(2, '0');
42
+ // Format as YYYY-MM-DD
43
+ return `${year}-${month}-${day}`;
44
+ };
45
+ exports.currentDateAsString = currentDateAsString;
46
+ /**
47
+ * Function to convert a MySQL DB date/time (in ISO `YYY-MM-DDThh:mm:ddZ` format to RFC3339 format
48
+ *
49
+ * @param dateTime the MySQL DB date/time to convert
50
+ * @returns the converted date/time in RFC3339 format
51
+ */
52
+ const convertMySQLDateTimeToRFC3339 = (dateTime) => {
53
+ var _a;
54
+ if (dateTime) {
55
+ if (typeof dateTime !== 'string')
56
+ return dateTime.toISOString();
57
+ const newDate = (_a = dateTime === null || dateTime === void 0 ? void 0 : dateTime.trim()) === null || _a === void 0 ? void 0 : _a.replace(' ', 'T');
58
+ return newDate.includes('T')
59
+ ? (newDate.endsWith('Z') ? newDate : newDate + 'Z')
60
+ : newDate + 'T00:00:00Z';
61
+ }
62
+ return null;
63
+ };
64
+ exports.convertMySQLDateTimeToRFC3339 = convertMySQLDateTimeToRFC3339;
65
+ /**
66
+ * Generate a random hex code
67
+ *
68
+ * @param size the size of the hex code to generate
69
+ * @returns a random hex code
70
+ */
71
+ const randomHex = (size) => {
72
+ return [...Array(size)].map(() => Math.floor(Math.random() * 16).toString(16)).join('');
73
+ };
74
+ exports.randomHex = randomHex;
75
+ /**
76
+ * Function to check if a value is null or undefined.
77
+ *
78
+ * @param val
79
+ * @returns True if the value is null or undefined, false otherwise.
80
+ */
81
+ const isNullOrUndefined = (val) => {
82
+ return val === null || val === undefined;
83
+ };
84
+ exports.isNullOrUndefined = isNullOrUndefined;
85
+ /**
86
+ * Remove null and undefined values from an object or array.
87
+ *
88
+ * @param obj An object (may contain nested objects and arrays)
89
+ * @returns The object with null and undefined values removed.
90
+ */
91
+ const removeNullAndUndefinedFromObject = (obj) => {
92
+ if (Array.isArray(obj)) {
93
+ return obj.map(exports.removeNullAndUndefinedFromObject).filter(v => !(0, exports.isNullOrUndefined)(v));
94
+ }
95
+ else if (!(0, exports.isNullOrUndefined)(obj) && typeof obj === 'object') {
96
+ return Object.fromEntries(Object.entries(obj)
97
+ .map(([k, v]) => [k, (0, exports.removeNullAndUndefinedFromObject)(v)])
98
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
99
+ .filter(([_, v]) => !(0, exports.isNullOrUndefined)(v)));
100
+ }
101
+ return obj;
102
+ };
103
+ exports.removeNullAndUndefinedFromObject = removeNullAndUndefinedFromObject;
104
+ /**
105
+ * Function to test for equality between two objects, arrays or primitives
106
+ *
107
+ * @param a An object (may contain nested objects and arrays)
108
+ * @param b Another object (may contain nested objects and arrays)
109
+ * @returns True if the objects are equal, false otherwise
110
+ */
111
+ const areEqual = (a, b) => {
112
+ // Check for strict equality (handles primitives and same references)
113
+ if (a === b)
114
+ return true;
115
+ // If either is not an object (or is null), they can't be equal
116
+ if (typeof a !== 'object' || a === null || typeof b !== 'object' || b === null) {
117
+ return false;
118
+ }
119
+ // If one is an array and the other isn't, they aren't equal
120
+ if (Array.isArray(a) !== Array.isArray(b))
121
+ return false;
122
+ // Handle Arrays specifically
123
+ if (Array.isArray(a) && Array.isArray(b)) {
124
+ if (a.length !== b.length)
125
+ return false;
126
+ return a.every((item, index) => (0, exports.areEqual)(item, b[index]));
127
+ }
128
+ // Handle Objects
129
+ const keysA = Object.keys(a);
130
+ const keysB = Object.keys(b);
131
+ // If the number of properties is different, they aren't equal'
132
+ if (keysA.length !== keysB.length)
133
+ return false;
134
+ // Check each property for equality
135
+ for (const key of keysA) {
136
+ if (!keysB.includes(key) || !(0, exports.areEqual)(a[key], b[key])) {
137
+ return false;
138
+ }
139
+ }
140
+ return true;
141
+ };
142
+ exports.areEqual = areEqual;
@@ -0,0 +1,10 @@
1
+ export * from './cloudFormation';
2
+ export * from './dynamo';
3
+ export * from './eventBridge';
4
+ export * from './general';
5
+ export * from './logger';
6
+ export * from './maDMP';
7
+ export * from './maDMPTypes';
8
+ export * from './rds';
9
+ export * from './s3';
10
+ export * from './ssm';
package/dist/index.js ADDED
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ // Entrypoint for the package
18
+ __exportStar(require("./cloudFormation"), exports);
19
+ __exportStar(require("./dynamo"), exports);
20
+ __exportStar(require("./eventBridge"), exports);
21
+ __exportStar(require("./general"), exports);
22
+ __exportStar(require("./logger"), exports);
23
+ __exportStar(require("./maDMP"), exports);
24
+ __exportStar(require("./maDMPTypes"), exports);
25
+ __exportStar(require("./rds"), exports);
26
+ __exportStar(require("./s3"), exports);
27
+ __exportStar(require("./ssm"), exports);
@@ -0,0 +1,17 @@
1
+ import { Logger } from 'pino';
2
+ export declare enum LogLevel {
3
+ trace = "trace",
4
+ debug = "debug",
5
+ info = "info",
6
+ warn = "warn",
7
+ error = "error",
8
+ fatal = "fatal"
9
+ }
10
+ /**
11
+ * Initialize a Pino logger with ECS formatting for the Lambda function.
12
+ *
13
+ * @param lambdaName Name of the function, used as the module name in the logs
14
+ * @param logLevel Log level to use, defaults to 'info'
15
+ * @returns A Pino logger instance
16
+ */
17
+ export declare const initializeLogger: (lambdaName: string, logLevel: LogLevel) => Logger;
package/dist/logger.js ADDED
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.initializeLogger = exports.LogLevel = void 0;
7
+ const pino_1 = __importDefault(require("pino"));
8
+ const pino_lambda_1 = require("pino-lambda");
9
+ const ecs_pino_format_1 = require("@elastic/ecs-pino-format");
10
+ // The available log levels
11
+ var LogLevel;
12
+ (function (LogLevel) {
13
+ LogLevel["trace"] = "trace";
14
+ LogLevel["debug"] = "debug";
15
+ LogLevel["info"] = "info";
16
+ LogLevel["warn"] = "warn";
17
+ LogLevel["error"] = "error";
18
+ LogLevel["fatal"] = "fatal";
19
+ })(LogLevel || (exports.LogLevel = LogLevel = {}));
20
+ /**
21
+ * Initialize a Pino logger with ECS formatting for the Lambda function.
22
+ *
23
+ * @param lambdaName Name of the function, used as the module name in the logs
24
+ * @param logLevel Log level to use, defaults to 'info'
25
+ * @returns A Pino logger instance
26
+ */
27
+ const initializeLogger = (lambdaName, logLevel) => {
28
+ const destination = (0, pino_lambda_1.pinoLambdaDestination)();
29
+ const logger = (0, pino_1.default)(Object.assign({
30
+ // Set the minimum log level
31
+ level: logLevel || 'info' }, ecs_pino_format_1.ecsFormat), destination);
32
+ // Define a standardized module name
33
+ logger.child({ module: lambdaName });
34
+ return logger;
35
+ };
36
+ exports.initializeLogger = initializeLogger;
@@ -0,0 +1,41 @@
1
+ import { DMPToolDMPType, DMPToolExtensionType } from "@dmptool/types";
2
+ /**
3
+ * Validate the specified DMP metadata record against the RDA Common Standard
4
+ * and DMP Tool extensions schema
5
+ *
6
+ * @param dmp The DMP metadata record to validate
7
+ * @returns the DMP metadata record if it is valid
8
+ * @throws DMPValidationError if the record is invalid with the error message(s)
9
+ */
10
+ export declare const validateRDACommonStandard: (dmp: DMPToolDMPType) => DMPToolDMPType;
11
+ /**
12
+ * Validate the specified DMP metadata record against the RDA Common Standard
13
+ * and DMP Tool extensions schema
14
+ *
15
+ * @param dmp The DMP metadata record to validate
16
+ * @returns the DMP metadata record if it is valid
17
+ * @throws DMPValidationError if the record is invalid with the error message(s)
18
+ */
19
+ export declare const validateDMPToolExtensions: (dmp: DMPToolExtensionType) => DMPToolExtensionType;
20
+ /**
21
+ *
22
+ * Generate a JSON representation for a DMP that confirms to the RDA Common Metadata
23
+ * standard and includes DMP Tool specific extensions to that standard.
24
+ *
25
+ * Some things of note about the JSON representation:
26
+ * - There are no primitive booleans, booleans are represented as: 'yes',
27
+ * 'no', 'unknown'
28
+ * - There are no primitive dates, strings formatted as 'YYYY-MM-DD hh:mm:ss:msZ'
29
+ * are used
30
+ * - The `provenance` is used to store the ID of the system that created the DMP
31
+ * - The `privacy` should be used to determine authorization for viewing the
32
+ * DMP narrative
33
+ * - The `featured` indicates whether the DMP is featured on the DMP Tool
34
+ * website's public plans page
35
+ * - The `registered` indicates whether the DMP is published/registered with DataCite/EZID
36
+ * - The `tombstoned` indicates that it was published/registered but is now removed
37
+ *
38
+ * @param planId the ID of the plan to generate the DMP for
39
+ * @returns a JSON representation of the DMP
40
+ */
41
+ export declare function planToDMPCommonStandard(planId: number): Promise<DMPToolDMPType | undefined>;