diff --git a/.eslintrc.cjs b/.eslintrc.cjs index 8c1ec094..19305ccb 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -13,4 +13,5 @@ module.exports = { root: true, extends: '@adobe/helix', + plugins: ['import'], }; diff --git a/README.md b/README.md index 55efa7e0..aa162c22 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,6 @@ # spacecat-shared Shared modules for Spacecat Services + +## Modules +- `spacecat-shared-dynamodb` - DynamoDB client for basic access +- `spacecat-shared-utils` - Utility functions diff --git a/docs/API.md b/docs/API.md new file mode 100644 index 00000000..6392f828 --- /dev/null +++ b/docs/API.md @@ -0,0 +1,213 @@ +## Functions + +
+
createClient(log, dbClient, docClient)Object
+

Creates a client object for interacting with DynamoDB.

+
+
isBoolean(value)boolean
+

Determines if the given value is a boolean or a string representation of a boolean.

+
+
isInteger(value)boolean
+

Checks if the given value is an integer.

+
+
isNumber(value)boolean
+

Determines if the given value is a number.

+
+
isObject(obj)boolean
+

Checks if the given parameter is an object and not an array or null.

+
+
isString(str)boolean
+

Determines if the given parameter is a string.

+
+
hasText(str)boolean
+

Checks if the given string is not empty.

+
+
isValidDate(obj)boolean
+

Checks whether the given object is a valid JavaScript Date.

+
+
isIsoDate(str)boolean
+

Validates whether the given string is a JavaScript ISO date string in +Zulu (UTC) timezone. Used for persisting system dates, which must be +independent of any user timezone.

+
+
isIsoTimeOffsetsDate(str)boolean
+

Validates whether the given string is a JavaScript ISO date string +following UTC time offsets format.

+
+
isValidUrl(urlString)boolean
+

Validates whether the given string is a valid URL with http or https protocol.

+
+
toBoolean(value)boolean
+

Converts a given value to a boolean. Throws an error if the value is not a boolean.

+
+
arrayEquals(a, b)boolean
+

Compares two arrays for equality.

+
+
+ + + +## createClient(log, dbClient, docClient) ⇒ Object +Creates a client object for interacting with DynamoDB. + +**Kind**: global function +**Returns**: Object - A client object with methods to interact with DynamoDB. + +| Param | Type | Description | +| --- | --- | --- | +| log | Object | The logging object, defaults to console. | +| dbClient | DynamoDB | The AWS SDK DynamoDB client instance. | +| docClient | DynamoDBDocumentClient | The AWS SDK DynamoDB Document client instance. | + + + +## isBoolean(value) ⇒ boolean +Determines if the given value is a boolean or a string representation of a boolean. + +**Kind**: global function +**Returns**: boolean - True if the value is a boolean or a string representation of a boolean. + +| Param | Type | Description | +| --- | --- | --- | +| value | \* | The value to check. | + + + +## isInteger(value) ⇒ boolean +Checks if the given value is an integer. + +**Kind**: global function +**Returns**: boolean - True if the value is an integer, false otherwise. + +| Param | Type | Description | +| --- | --- | --- | +| value | \* | The value to check. | + + + +## isNumber(value) ⇒ boolean +Determines if the given value is a number. + +**Kind**: global function +**Returns**: boolean - True if the value is a finite number, false otherwise. + +| Param | Type | Description | +| --- | --- | --- | +| value | \* | The value to check. | + + + +## isObject(obj) ⇒ boolean +Checks if the given parameter is an object and not an array or null. + +**Kind**: global function +**Returns**: boolean - True if the parameter is an object, false otherwise. + +| Param | Type | Description | +| --- | --- | --- | +| obj | \* | The object to check. | + + + +## isString(str) ⇒ boolean +Determines if the given parameter is a string. + +**Kind**: global function +**Returns**: boolean - True if the parameter is a string, false otherwise. + +| Param | Type | Description | +| --- | --- | --- | +| str | \* | The string to check. | + + + +## hasText(str) ⇒ boolean +Checks if the given string is not empty. + +**Kind**: global function +**Returns**: boolean - True if the string is not empty, false otherwise. + +| Param | Type | Description | +| --- | --- | --- | +| str | \* | The string to check. | + + + +## isValidDate(obj) ⇒ boolean +Checks whether the given object is a valid JavaScript Date. + +**Kind**: global function +**Returns**: boolean - True if the given object is a valid Date object, false otherwise. + +| Param | Type | Description | +| --- | --- | --- | +| obj | \* | The object to check. | + + + +## isIsoDate(str) ⇒ boolean +Validates whether the given string is a JavaScript ISO date string in +Zulu (UTC) timezone. Used for persisting system dates, which must be +independent of any user timezone. + +**Kind**: global function +**Returns**: boolean - True if the given string validates successfully. + +| Param | Type | Description | +| --- | --- | --- | +| str | string | The string to validate. | + + + +## isIsoTimeOffsetsDate(str) ⇒ boolean +Validates whether the given string is a JavaScript ISO date string +following UTC time offsets format. + +**Kind**: global function +**Returns**: boolean - True if the given string validates successfully. + +| Param | Type | Description | +| --- | --- | --- | +| str | string | The string to validate. | + + + +## isValidUrl(urlString) ⇒ boolean +Validates whether the given string is a valid URL with http or https protocol. + +**Kind**: global function +**Returns**: boolean - True if the given string validates successfully. + +| Param | Type | Description | +| --- | --- | --- | +| urlString | string | The string to validate. | + + + +## toBoolean(value) ⇒ boolean +Converts a given value to a boolean. Throws an error if the value is not a boolean. + +**Kind**: global function +**Returns**: boolean - The converted boolean value. +**Throws**: + +- Error If the value is not a boolean or a boolean-like string. + + +| Param | Type | Description | +| --- | --- | --- | +| value | \* | The value to convert. | + + + +## arrayEquals(a, b) ⇒ boolean +Compares two arrays for equality. + +**Kind**: global function +**Returns**: boolean - True if the arrays are equal, false otherwise. + +| Param | Type | Description | +| --- | --- | --- | +| a | Array | The first array to compare. | +| b | Array | The second array to compare. | + diff --git a/package-lock.json b/package-lock.json index 37bb48d5..e6344d0b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -92,10 +92,653 @@ "aws4": "1.12.0" } }, + "node_modules/@adobe/spacecat-shared-dynamo": { + "resolved": "packages/spacecat-shared-dynamo", + "link": true + }, "node_modules/@adobe/spacecat-shared-example": { "resolved": "packages/spacecat-shared-example", "link": true }, + "node_modules/@adobe/spacecat-shared-utils": { + "resolved": "packages/spacecat-shared-utils", + "link": true + }, + "node_modules/@aws-crypto/crc32": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/crc32/-/crc32-3.0.0.tgz", + "integrity": "sha512-IzSgsrxUcsrejQbPVilIKy16kAT52EwB6zSaI+M3xxIhKh5+aldEyvI+z6erM7TCLB2BJsFrtHjp6/4/sr+3dA==", + "dependencies": { + "@aws-crypto/util": "^3.0.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^1.11.1" + } + }, + "node_modules/@aws-crypto/crc32/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + }, + "node_modules/@aws-crypto/ie11-detection": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/ie11-detection/-/ie11-detection-3.0.0.tgz", + "integrity": "sha512-341lBBkiY1DfDNKai/wXM3aujNBkXR7tq1URPQDL9wi3AUbI80NR74uF1TXHMm7po1AcnFk8iu2S2IeU/+/A+Q==", + "dependencies": { + "tslib": "^1.11.1" + } + }, + "node_modules/@aws-crypto/ie11-detection/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + }, + "node_modules/@aws-crypto/sha256-browser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-browser/-/sha256-browser-3.0.0.tgz", + "integrity": "sha512-8VLmW2B+gjFbU5uMeqtQM6Nj0/F1bro80xQXCW6CQBWgosFWXTx77aeOF5CAIAmbOK64SdMBJdNr6J41yP5mvQ==", + "dependencies": { + "@aws-crypto/ie11-detection": "^3.0.0", + "@aws-crypto/sha256-js": "^3.0.0", + "@aws-crypto/supports-web-crypto": "^3.0.0", + "@aws-crypto/util": "^3.0.0", + "@aws-sdk/types": "^3.222.0", + "@aws-sdk/util-locate-window": "^3.0.0", + "@aws-sdk/util-utf8-browser": "^3.0.0", + "tslib": "^1.11.1" + } + }, + "node_modules/@aws-crypto/sha256-browser/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + }, + "node_modules/@aws-crypto/sha256-js": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-js/-/sha256-js-3.0.0.tgz", + "integrity": "sha512-PnNN7os0+yd1XvXAy23CFOmTbMaDxgxXtTKHybrJ39Y8kGzBATgBFibWJKH6BhytLI/Zyszs87xCOBNyBig6vQ==", + "dependencies": { + "@aws-crypto/util": "^3.0.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^1.11.1" + } + }, + "node_modules/@aws-crypto/sha256-js/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + }, + "node_modules/@aws-crypto/supports-web-crypto": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/supports-web-crypto/-/supports-web-crypto-3.0.0.tgz", + "integrity": "sha512-06hBdMwUAb2WFTuGG73LSC0wfPu93xWwo5vL2et9eymgmu3Id5vFAHBbajVWiGhPO37qcsdCap/FqXvJGJWPIg==", + "dependencies": { + "tslib": "^1.11.1" + } + }, + "node_modules/@aws-crypto/supports-web-crypto/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + }, + "node_modules/@aws-crypto/util": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/util/-/util-3.0.0.tgz", + "integrity": "sha512-2OJlpeJpCR48CC8r+uKVChzs9Iungj9wkZrl8Z041DWEWvyIHILYKCPNzJghKsivj+S3mLo6BVc7mBNzdxA46w==", + "dependencies": { + "@aws-sdk/types": "^3.222.0", + "@aws-sdk/util-utf8-browser": "^3.0.0", + "tslib": "^1.11.1" + } + }, + "node_modules/@aws-crypto/util/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + }, + "node_modules/@aws-sdk/client-dynamodb": { + "version": "3.454.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-dynamodb/-/client-dynamodb-3.454.0.tgz", + "integrity": "sha512-GztsAk/OwhksDYclc0JoqhoXGqowzfyqJ6405L6m1x3ydS0B0csul/1xnCmmyVEIr9aLJZK7dk0DgdfKsyj3KA==", + "dependencies": { + "@aws-crypto/sha256-browser": "3.0.0", + "@aws-crypto/sha256-js": "3.0.0", + "@aws-sdk/client-sts": "3.454.0", + "@aws-sdk/core": "3.451.0", + "@aws-sdk/credential-provider-node": "3.451.0", + "@aws-sdk/middleware-endpoint-discovery": "3.451.0", + "@aws-sdk/middleware-host-header": "3.451.0", + "@aws-sdk/middleware-logger": "3.451.0", + "@aws-sdk/middleware-recursion-detection": "3.451.0", + "@aws-sdk/middleware-signing": "3.451.0", + "@aws-sdk/middleware-user-agent": "3.451.0", + "@aws-sdk/region-config-resolver": "3.451.0", + "@aws-sdk/types": "3.451.0", + "@aws-sdk/util-endpoints": "3.451.0", + "@aws-sdk/util-user-agent-browser": "3.451.0", + "@aws-sdk/util-user-agent-node": "3.451.0", + "@smithy/config-resolver": "^2.0.18", + "@smithy/fetch-http-handler": "^2.2.6", + "@smithy/hash-node": "^2.0.15", + "@smithy/invalid-dependency": "^2.0.13", + "@smithy/middleware-content-length": "^2.0.15", + "@smithy/middleware-endpoint": "^2.2.0", + "@smithy/middleware-retry": "^2.0.20", + "@smithy/middleware-serde": "^2.0.13", + "@smithy/middleware-stack": "^2.0.7", + "@smithy/node-config-provider": "^2.1.5", + "@smithy/node-http-handler": "^2.1.9", + "@smithy/protocol-http": "^3.0.9", + "@smithy/smithy-client": "^2.1.15", + "@smithy/types": "^2.5.0", + "@smithy/url-parser": "^2.0.13", + "@smithy/util-base64": "^2.0.1", + "@smithy/util-body-length-browser": "^2.0.0", + "@smithy/util-body-length-node": "^2.1.0", + "@smithy/util-defaults-mode-browser": "^2.0.19", + "@smithy/util-defaults-mode-node": "^2.0.25", + "@smithy/util-endpoints": "^1.0.4", + "@smithy/util-retry": "^2.0.6", + "@smithy/util-utf8": "^2.0.2", + "@smithy/util-waiter": "^2.0.13", + "tslib": "^2.5.0", + "uuid": "^8.3.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/client-sso": { + "version": "3.451.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.451.0.tgz", + "integrity": "sha512-KkYSke3Pdv3MfVH/5fT528+MKjMyPKlcLcd4zQb0x6/7Bl7EHrPh1JZYjzPLHelb+UY5X0qN8+cb8iSu1eiwIQ==", + "dependencies": { + "@aws-crypto/sha256-browser": "3.0.0", + "@aws-crypto/sha256-js": "3.0.0", + "@aws-sdk/core": "3.451.0", + "@aws-sdk/middleware-host-header": "3.451.0", + "@aws-sdk/middleware-logger": "3.451.0", + "@aws-sdk/middleware-recursion-detection": "3.451.0", + "@aws-sdk/middleware-user-agent": "3.451.0", + "@aws-sdk/region-config-resolver": "3.451.0", + "@aws-sdk/types": "3.451.0", + "@aws-sdk/util-endpoints": "3.451.0", + "@aws-sdk/util-user-agent-browser": "3.451.0", + "@aws-sdk/util-user-agent-node": "3.451.0", + "@smithy/config-resolver": "^2.0.18", + "@smithy/fetch-http-handler": "^2.2.6", + "@smithy/hash-node": "^2.0.15", + "@smithy/invalid-dependency": "^2.0.13", + "@smithy/middleware-content-length": "^2.0.15", + "@smithy/middleware-endpoint": "^2.2.0", + "@smithy/middleware-retry": "^2.0.20", + "@smithy/middleware-serde": "^2.0.13", + "@smithy/middleware-stack": "^2.0.7", + "@smithy/node-config-provider": "^2.1.5", + "@smithy/node-http-handler": "^2.1.9", + "@smithy/protocol-http": "^3.0.9", + "@smithy/smithy-client": "^2.1.15", + "@smithy/types": "^2.5.0", + "@smithy/url-parser": "^2.0.13", + "@smithy/util-base64": "^2.0.1", + "@smithy/util-body-length-browser": "^2.0.0", + "@smithy/util-body-length-node": "^2.1.0", + "@smithy/util-defaults-mode-browser": "^2.0.19", + "@smithy/util-defaults-mode-node": "^2.0.25", + "@smithy/util-endpoints": "^1.0.4", + "@smithy/util-retry": "^2.0.6", + "@smithy/util-utf8": "^2.0.2", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/client-sts": { + "version": "3.454.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.454.0.tgz", + "integrity": "sha512-0fDvr8WeB6IYO8BUCzcivWmahgGl/zDbaYfakzGnt4mrl5ztYaXE875WI6b7+oFcKMRvN+KLvwu5TtyFuNY+GQ==", + "dependencies": { + "@aws-crypto/sha256-browser": "3.0.0", + "@aws-crypto/sha256-js": "3.0.0", + "@aws-sdk/core": "3.451.0", + "@aws-sdk/credential-provider-node": "3.451.0", + "@aws-sdk/middleware-host-header": "3.451.0", + "@aws-sdk/middleware-logger": "3.451.0", + "@aws-sdk/middleware-recursion-detection": "3.451.0", + "@aws-sdk/middleware-sdk-sts": "3.451.0", + "@aws-sdk/middleware-signing": "3.451.0", + "@aws-sdk/middleware-user-agent": "3.451.0", + "@aws-sdk/region-config-resolver": "3.451.0", + "@aws-sdk/types": "3.451.0", + "@aws-sdk/util-endpoints": "3.451.0", + "@aws-sdk/util-user-agent-browser": "3.451.0", + "@aws-sdk/util-user-agent-node": "3.451.0", + "@smithy/config-resolver": "^2.0.18", + "@smithy/fetch-http-handler": "^2.2.6", + "@smithy/hash-node": "^2.0.15", + "@smithy/invalid-dependency": "^2.0.13", + "@smithy/middleware-content-length": "^2.0.15", + "@smithy/middleware-endpoint": "^2.2.0", + "@smithy/middleware-retry": "^2.0.20", + "@smithy/middleware-serde": "^2.0.13", + "@smithy/middleware-stack": "^2.0.7", + "@smithy/node-config-provider": "^2.1.5", + "@smithy/node-http-handler": "^2.1.9", + "@smithy/protocol-http": "^3.0.9", + "@smithy/smithy-client": "^2.1.15", + "@smithy/types": "^2.5.0", + "@smithy/url-parser": "^2.0.13", + "@smithy/util-base64": "^2.0.1", + "@smithy/util-body-length-browser": "^2.0.0", + "@smithy/util-body-length-node": "^2.1.0", + "@smithy/util-defaults-mode-browser": "^2.0.19", + "@smithy/util-defaults-mode-node": "^2.0.25", + "@smithy/util-endpoints": "^1.0.4", + "@smithy/util-retry": "^2.0.6", + "@smithy/util-utf8": "^2.0.2", + "fast-xml-parser": "4.2.5", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/core": { + "version": "3.451.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.451.0.tgz", + "integrity": "sha512-SamWW2zHEf1ZKe3j1w0Piauryl8BQIlej0TBS18A4ACzhjhWXhCs13bO1S88LvPR5mBFXok3XOT6zPOnKDFktw==", + "dependencies": { + "@smithy/smithy-client": "^2.1.15", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-env": { + "version": "3.451.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.451.0.tgz", + "integrity": "sha512-9dAav7DcRgaF7xCJEQR5ER9ErXxnu/tdnVJ+UPmb1NPeIZdESv1A3lxFDEq1Fs8c4/lzAj9BpshGyJVIZwZDKg==", + "dependencies": { + "@aws-sdk/types": "3.451.0", + "@smithy/property-provider": "^2.0.0", + "@smithy/types": "^2.5.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-ini": { + "version": "3.451.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.451.0.tgz", + "integrity": "sha512-TySt64Ci5/ZbqFw1F9Z0FIGvYx5JSC9e6gqDnizIYd8eMnn8wFRUscRrD7pIHKfrhvVKN5h0GdYovmMO/FMCBw==", + "dependencies": { + "@aws-sdk/credential-provider-env": "3.451.0", + "@aws-sdk/credential-provider-process": "3.451.0", + "@aws-sdk/credential-provider-sso": "3.451.0", + "@aws-sdk/credential-provider-web-identity": "3.451.0", + "@aws-sdk/types": "3.451.0", + "@smithy/credential-provider-imds": "^2.0.0", + "@smithy/property-provider": "^2.0.0", + "@smithy/shared-ini-file-loader": "^2.0.6", + "@smithy/types": "^2.5.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-node": { + "version": "3.451.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.451.0.tgz", + "integrity": "sha512-AEwM1WPyxUdKrKyUsKyFqqRFGU70e4qlDyrtBxJnSU9NRLZI8tfEZ67bN7fHSxBUBODgDXpMSlSvJiBLh5/3pw==", + "dependencies": { + "@aws-sdk/credential-provider-env": "3.451.0", + "@aws-sdk/credential-provider-ini": "3.451.0", + "@aws-sdk/credential-provider-process": "3.451.0", + "@aws-sdk/credential-provider-sso": "3.451.0", + "@aws-sdk/credential-provider-web-identity": "3.451.0", + "@aws-sdk/types": "3.451.0", + "@smithy/credential-provider-imds": "^2.0.0", + "@smithy/property-provider": "^2.0.0", + "@smithy/shared-ini-file-loader": "^2.0.6", + "@smithy/types": "^2.5.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-process": { + "version": "3.451.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.451.0.tgz", + "integrity": "sha512-HQywSdKeD5PErcLLnZfSyCJO+6T+ZyzF+Lm/QgscSC+CbSUSIPi//s15qhBRVely/3KBV6AywxwNH+5eYgt4lQ==", + "dependencies": { + "@aws-sdk/types": "3.451.0", + "@smithy/property-provider": "^2.0.0", + "@smithy/shared-ini-file-loader": "^2.0.6", + "@smithy/types": "^2.5.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-sso": { + "version": "3.451.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.451.0.tgz", + "integrity": "sha512-Usm/N51+unOt8ID4HnQzxIjUJDrkAQ1vyTOC0gSEEJ7h64NSSPGD5yhN7il5WcErtRd3EEtT1a8/GTC5TdBctg==", + "dependencies": { + "@aws-sdk/client-sso": "3.451.0", + "@aws-sdk/token-providers": "3.451.0", + "@aws-sdk/types": "3.451.0", + "@smithy/property-provider": "^2.0.0", + "@smithy/shared-ini-file-loader": "^2.0.6", + "@smithy/types": "^2.5.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-web-identity": { + "version": "3.451.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.451.0.tgz", + "integrity": "sha512-Xtg3Qw65EfDjWNG7o2xD6sEmumPfsy3WDGjk2phEzVg8s7hcZGxf5wYwe6UY7RJvlEKrU0rFA+AMn6Hfj5oOzg==", + "dependencies": { + "@aws-sdk/types": "3.451.0", + "@smithy/property-provider": "^2.0.0", + "@smithy/types": "^2.5.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/endpoint-cache": { + "version": "3.310.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/endpoint-cache/-/endpoint-cache-3.310.0.tgz", + "integrity": "sha512-y3wipforet41EDTI0vnzxILqwAGll1KfI5qcdX9pXF/WF1f+3frcOtPiWtQEZQpy4czRogKm3BHo70QBYAZxlQ==", + "dependencies": { + "mnemonist": "0.38.3", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/lib-dynamodb": { + "version": "3.454.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/lib-dynamodb/-/lib-dynamodb-3.454.0.tgz", + "integrity": "sha512-qeu0ZhTBXrAGzP9fpZDN88u7tLWtoBdGebC0WvE9oMaQnGICu1mgLwb6u+u8TAS19cvPySHln9VmSVs52m8L1g==", + "dependencies": { + "@aws-sdk/util-dynamodb": "3.454.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "@aws-sdk/client-dynamodb": "^3.0.0" + } + }, + "node_modules/@aws-sdk/middleware-endpoint-discovery": { + "version": "3.451.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-endpoint-discovery/-/middleware-endpoint-discovery-3.451.0.tgz", + "integrity": "sha512-OvRb9M12JZaxjpdwPqTndAexjp/s4Ub/GumxED2uy7KDzo95f2A4CA3yRB03ExBERWtKtCShpJG87oTERkDiaQ==", + "dependencies": { + "@aws-sdk/endpoint-cache": "3.310.0", + "@aws-sdk/types": "3.451.0", + "@smithy/node-config-provider": "^2.1.5", + "@smithy/protocol-http": "^3.0.9", + "@smithy/types": "^2.5.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/middleware-host-header": { + "version": "3.451.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.451.0.tgz", + "integrity": "sha512-j8a5jAfhWmsK99i2k8oR8zzQgXrsJtgrLxc3js6U+525mcZytoiDndkWTmD5fjJ1byU1U2E5TaPq+QJeDip05Q==", + "dependencies": { + "@aws-sdk/types": "3.451.0", + "@smithy/protocol-http": "^3.0.9", + "@smithy/types": "^2.5.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/middleware-logger": { + "version": "3.451.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.451.0.tgz", + "integrity": "sha512-0kHrYEyVeB2QBfP6TfbI240aRtatLZtcErJbhpiNUb+CQPgEL3crIjgVE8yYiJumZ7f0jyjo8HLPkwD1/2APaw==", + "dependencies": { + "@aws-sdk/types": "3.451.0", + "@smithy/types": "^2.5.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/middleware-recursion-detection": { + "version": "3.451.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.451.0.tgz", + "integrity": "sha512-J6jL6gJ7orjHGM70KDRcCP7so/J2SnkN4vZ9YRLTeeZY6zvBuHDjX8GCIgSqPn/nXFXckZO8XSnA7u6+3TAT0w==", + "dependencies": { + "@aws-sdk/types": "3.451.0", + "@smithy/protocol-http": "^3.0.9", + "@smithy/types": "^2.5.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/middleware-sdk-sts": { + "version": "3.451.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-sts/-/middleware-sdk-sts-3.451.0.tgz", + "integrity": "sha512-UJ6UfVUEgp0KIztxpAeelPXI5MLj9wUtUCqYeIMP7C1ZhoEMNm3G39VLkGN43dNhBf1LqjsV9jkKMZbVfYXuwg==", + "dependencies": { + "@aws-sdk/middleware-signing": "3.451.0", + "@aws-sdk/types": "3.451.0", + "@smithy/types": "^2.5.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/middleware-signing": { + "version": "3.451.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-signing/-/middleware-signing-3.451.0.tgz", + "integrity": "sha512-s5ZlcIoLNg1Huj4Qp06iKniE8nJt/Pj1B/fjhWc6cCPCM7XJYUCejCnRh6C5ZJoBEYodjuwZBejPc1Wh3j+znA==", + "dependencies": { + "@aws-sdk/types": "3.451.0", + "@smithy/property-provider": "^2.0.0", + "@smithy/protocol-http": "^3.0.9", + "@smithy/signature-v4": "^2.0.0", + "@smithy/types": "^2.5.0", + "@smithy/util-middleware": "^2.0.6", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/middleware-user-agent": { + "version": "3.451.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.451.0.tgz", + "integrity": "sha512-8NM/0JiKLNvT9wtAQVl1DFW0cEO7OvZyLSUBLNLTHqyvOZxKaZ8YFk7d8PL6l76LeUKRxq4NMxfZQlUIRe0eSA==", + "dependencies": { + "@aws-sdk/types": "3.451.0", + "@aws-sdk/util-endpoints": "3.451.0", + "@smithy/protocol-http": "^3.0.9", + "@smithy/types": "^2.5.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/region-config-resolver": { + "version": "3.451.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.451.0.tgz", + "integrity": "sha512-3iMf4OwzrFb4tAAmoROXaiORUk2FvSejnHIw/XHvf/jjR4EqGGF95NZP/n/MeFZMizJWVssrwS412GmoEyoqhg==", + "dependencies": { + "@smithy/node-config-provider": "^2.1.5", + "@smithy/types": "^2.5.0", + "@smithy/util-config-provider": "^2.0.0", + "@smithy/util-middleware": "^2.0.6", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/token-providers": { + "version": "3.451.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.451.0.tgz", + "integrity": "sha512-ij1L5iUbn6CwxVOT1PG4NFjsrsKN9c4N1YEM0lkl6DwmaNOscjLKGSNyj9M118vSWsOs1ZDbTwtj++h0O/BWrQ==", + "dependencies": { + "@aws-crypto/sha256-browser": "3.0.0", + "@aws-crypto/sha256-js": "3.0.0", + "@aws-sdk/middleware-host-header": "3.451.0", + "@aws-sdk/middleware-logger": "3.451.0", + "@aws-sdk/middleware-recursion-detection": "3.451.0", + "@aws-sdk/middleware-user-agent": "3.451.0", + "@aws-sdk/region-config-resolver": "3.451.0", + "@aws-sdk/types": "3.451.0", + "@aws-sdk/util-endpoints": "3.451.0", + "@aws-sdk/util-user-agent-browser": "3.451.0", + "@aws-sdk/util-user-agent-node": "3.451.0", + "@smithy/config-resolver": "^2.0.18", + "@smithy/fetch-http-handler": "^2.2.6", + "@smithy/hash-node": "^2.0.15", + "@smithy/invalid-dependency": "^2.0.13", + "@smithy/middleware-content-length": "^2.0.15", + "@smithy/middleware-endpoint": "^2.2.0", + "@smithy/middleware-retry": "^2.0.20", + "@smithy/middleware-serde": "^2.0.13", + "@smithy/middleware-stack": "^2.0.7", + "@smithy/node-config-provider": "^2.1.5", + "@smithy/node-http-handler": "^2.1.9", + "@smithy/property-provider": "^2.0.0", + "@smithy/protocol-http": "^3.0.9", + "@smithy/shared-ini-file-loader": "^2.0.6", + "@smithy/smithy-client": "^2.1.15", + "@smithy/types": "^2.5.0", + "@smithy/url-parser": "^2.0.13", + "@smithy/util-base64": "^2.0.1", + "@smithy/util-body-length-browser": "^2.0.0", + "@smithy/util-body-length-node": "^2.1.0", + "@smithy/util-defaults-mode-browser": "^2.0.19", + "@smithy/util-defaults-mode-node": "^2.0.25", + "@smithy/util-endpoints": "^1.0.4", + "@smithy/util-retry": "^2.0.6", + "@smithy/util-utf8": "^2.0.2", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/types": { + "version": "3.451.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.451.0.tgz", + "integrity": "sha512-rhK+qeYwCIs+laJfWCcrYEjay2FR/9VABZJ2NRM89jV/fKqGVQR52E5DQqrI+oEIL5JHMhhnr4N4fyECMS35lw==", + "dependencies": { + "@smithy/types": "^2.5.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/util-dynamodb": { + "version": "3.454.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-dynamodb/-/util-dynamodb-3.454.0.tgz", + "integrity": "sha512-gcxzlUzFHHLnnDB8Pc3BqRc2WmbVDf3A8Xre1H5zPNtF8bZihYj0xk3KMK9Sfnk/tkDTL2PfQ2qNf7R7RLTNpw==", + "dependencies": { + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "@aws-sdk/client-dynamodb": "^3.0.0" + } + }, + "node_modules/@aws-sdk/util-endpoints": { + "version": "3.451.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.451.0.tgz", + "integrity": "sha512-giqLGBTnRIcKkDqwU7+GQhKbtJ5Ku35cjGQIfMyOga6pwTBUbaK0xW1Sdd8sBQ1GhApscnChzI9o/R9x0368vw==", + "dependencies": { + "@aws-sdk/types": "3.451.0", + "@smithy/util-endpoints": "^1.0.4", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/util-locate-window": { + "version": "3.310.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.310.0.tgz", + "integrity": "sha512-qo2t/vBTnoXpjKxlsC2e1gBrRm80M3bId27r0BRB2VniSSe7bL1mmzM+/HFtujm0iAxtPM+aLEflLJlJeDPg0w==", + "dependencies": { + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/util-user-agent-browser": { + "version": "3.451.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.451.0.tgz", + "integrity": "sha512-Ws5mG3J0TQifH7OTcMrCTexo7HeSAc3cBgjfhS/ofzPUzVCtsyg0G7I6T7wl7vJJETix2Kst2cpOsxygPgPD9w==", + "dependencies": { + "@aws-sdk/types": "3.451.0", + "@smithy/types": "^2.5.0", + "bowser": "^2.11.0", + "tslib": "^2.5.0" + } + }, + "node_modules/@aws-sdk/util-user-agent-node": { + "version": "3.451.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.451.0.tgz", + "integrity": "sha512-TBzm6P+ql4mkGFAjPlO1CI+w3yUT+NulaiALjl/jNX/nnUp6HsJsVxJf4nVFQTG5KRV0iqMypcs7I3KIhH+LmA==", + "dependencies": { + "@aws-sdk/types": "3.451.0", + "@smithy/node-config-provider": "^2.1.5", + "@smithy/types": "^2.5.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "aws-crt": ">=1.0.0" + }, + "peerDependenciesMeta": { + "aws-crt": { + "optional": true + } + } + }, + "node_modules/@aws-sdk/util-utf8-browser": { + "version": "3.259.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-utf8-browser/-/util-utf8-browser-3.259.0.tgz", + "integrity": "sha512-UvFa/vR+e19XookZF8RzFZBrw2EUkQWxiBW0yYQAhvk3C+QVGl0H3ouca8LDBlBfQKXwmW3huo/59H8rwb1wJw==", + "dependencies": { + "tslib": "^2.3.1" + } + }, "node_modules/@babel/code-frame": { "version": "7.23.4", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.4.tgz", @@ -842,6 +1485,520 @@ "semantic-release": ">=18.0.0-beta.1" } }, + "node_modules/@smithy/abort-controller": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-2.0.14.tgz", + "integrity": "sha512-zXtteuYLWbSXnzI3O6xq3FYvigYZFW8mdytGibfarLL2lxHto9L3ILtGVnVGmFZa7SDh62l39EnU5hesLN87Fw==", + "dependencies": { + "@smithy/types": "^2.6.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/config-resolver": { + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-2.0.19.tgz", + "integrity": "sha512-JsghnQ5zjWmjEVY8TFOulLdEOCj09SjRLugrHlkPZTIBBm7PQitCFVLThbsKPZQOP7N3ME1DU1nKUc1UaVnBog==", + "dependencies": { + "@smithy/node-config-provider": "^2.1.6", + "@smithy/types": "^2.6.0", + "@smithy/util-config-provider": "^2.0.0", + "@smithy/util-middleware": "^2.0.7", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/credential-provider-imds": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-2.1.2.tgz", + "integrity": "sha512-Y62jBWdoLPSYjr9fFvJf+KwTa1EunjVr6NryTEWCnwIY93OJxwV4t0qxjwdPl/XMsUkq79ppNJSEQN6Ohnhxjw==", + "dependencies": { + "@smithy/node-config-provider": "^2.1.6", + "@smithy/property-provider": "^2.0.15", + "@smithy/types": "^2.6.0", + "@smithy/url-parser": "^2.0.14", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/eventstream-codec": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-2.0.14.tgz", + "integrity": "sha512-g/OU/MeWGfHDygoXgMWfG/Xb0QqDnAGcM9t2FRrVAhleXYRddGOEnfanR5cmHgB9ue52MJsyorqFjckzXsylaA==", + "dependencies": { + "@aws-crypto/crc32": "3.0.0", + "@smithy/types": "^2.6.0", + "@smithy/util-hex-encoding": "^2.0.0", + "tslib": "^2.5.0" + } + }, + "node_modules/@smithy/fetch-http-handler": { + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-2.2.7.tgz", + "integrity": "sha512-iSDBjxuH9TgrtMYAr7j5evjvkvgwLY3y+9D547uep+JNkZ1ZT+BaeU20j6I/bO/i26ilCWFImrlXTPsfQtZdIQ==", + "dependencies": { + "@smithy/protocol-http": "^3.0.10", + "@smithy/querystring-builder": "^2.0.14", + "@smithy/types": "^2.6.0", + "@smithy/util-base64": "^2.0.1", + "tslib": "^2.5.0" + } + }, + "node_modules/@smithy/hash-node": { + "version": "2.0.16", + "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-2.0.16.tgz", + "integrity": "sha512-Wbi9A0PacMYUOwjAulQP90Wl3mQ6NDwnyrZQzFjDz+UzjXOSyQMgBrTkUBz+pVoYVlX3DUu24gWMZBcit+wOGg==", + "dependencies": { + "@smithy/types": "^2.6.0", + "@smithy/util-buffer-from": "^2.0.0", + "@smithy/util-utf8": "^2.0.2", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/invalid-dependency": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-2.0.14.tgz", + "integrity": "sha512-d8ohpwZo9RzTpGlAfsWtfm1SHBSU7+N4iuZ6MzR10xDTujJJWtmXYHK1uzcr7rggbpUTaWyHpPFgnf91q0EFqQ==", + "dependencies": { + "@smithy/types": "^2.6.0", + "tslib": "^2.5.0" + } + }, + "node_modules/@smithy/is-array-buffer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.0.0.tgz", + "integrity": "sha512-z3PjFjMyZNI98JFRJi/U0nGoLWMSJlDjAW4QUX2WNZLas5C0CmVV6LJ01JI0k90l7FvpmixjWxPFmENSClQ7ug==", + "dependencies": { + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/middleware-content-length": { + "version": "2.0.16", + "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-2.0.16.tgz", + "integrity": "sha512-9ddDia3pp1d3XzLXKcm7QebGxLq9iwKf+J1LapvlSOhpF8EM9SjMeSrMOOFgG+2TfW5K3+qz4IAJYYm7INYCng==", + "dependencies": { + "@smithy/protocol-http": "^3.0.10", + "@smithy/types": "^2.6.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/middleware-endpoint": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-2.2.1.tgz", + "integrity": "sha512-dVDS7HNJl/wb0lpByXor6whqDbb1YlLoaoWYoelyYzLHioXOE7y/0iDwJWtDcN36/tVCw9EPBFZ3aans84jLpg==", + "dependencies": { + "@smithy/middleware-serde": "^2.0.14", + "@smithy/node-config-provider": "^2.1.6", + "@smithy/shared-ini-file-loader": "^2.2.5", + "@smithy/types": "^2.6.0", + "@smithy/url-parser": "^2.0.14", + "@smithy/util-middleware": "^2.0.7", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/middleware-retry": { + "version": "2.0.21", + "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-2.0.21.tgz", + "integrity": "sha512-EZS1EXv1k6IJX6hyu/0yNQuPcPaXwG8SWljQHYueyRbOxmqYgoWMWPtfZj0xRRQ4YtLawQSpBgAeiJltq8/MPw==", + "dependencies": { + "@smithy/node-config-provider": "^2.1.6", + "@smithy/protocol-http": "^3.0.10", + "@smithy/service-error-classification": "^2.0.7", + "@smithy/types": "^2.6.0", + "@smithy/util-middleware": "^2.0.7", + "@smithy/util-retry": "^2.0.7", + "tslib": "^2.5.0", + "uuid": "^8.3.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/middleware-serde": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-2.0.14.tgz", + "integrity": "sha512-hFi3FqoYWDntCYA2IGY6gJ6FKjq2gye+1tfxF2HnIJB5uW8y2DhpRNBSUMoqP+qvYzRqZ6ntv4kgbG+o3pX57g==", + "dependencies": { + "@smithy/types": "^2.6.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/middleware-stack": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-2.0.8.tgz", + "integrity": "sha512-7/N59j0zWqVEKExJcA14MrLDZ/IeN+d6nbkN8ucs+eURyaDUXWYlZrQmMOd/TyptcQv0+RDlgag/zSTTV62y/Q==", + "dependencies": { + "@smithy/types": "^2.6.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/node-config-provider": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-2.1.6.tgz", + "integrity": "sha512-HLqTs6O78m3M3z1cPLFxddxhEPv5MkVatfPuxoVO3A+cHZanNd/H5I6btcdHy6N2CB1MJ/lihJC92h30SESsBA==", + "dependencies": { + "@smithy/property-provider": "^2.0.15", + "@smithy/shared-ini-file-loader": "^2.2.5", + "@smithy/types": "^2.6.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/node-http-handler": { + "version": "2.1.10", + "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-2.1.10.tgz", + "integrity": "sha512-lkALAwtN6odygIM4nB8aHDahINM6WXXjNrZmWQAh0RSossySRT2qa31cFv0ZBuAYVWeprskRk13AFvvLmf1WLw==", + "dependencies": { + "@smithy/abort-controller": "^2.0.14", + "@smithy/protocol-http": "^3.0.10", + "@smithy/querystring-builder": "^2.0.14", + "@smithy/types": "^2.6.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/property-provider": { + "version": "2.0.15", + "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-2.0.15.tgz", + "integrity": "sha512-YbRFBn8oiiC3o1Kn3a4KjGa6k47rCM9++5W9cWqYn9WnkyH+hBWgfJAckuxpyA2Hq6Ys4eFrWzXq6fqHEw7iew==", + "dependencies": { + "@smithy/types": "^2.6.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/protocol-http": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-3.0.10.tgz", + "integrity": "sha512-6+tjNk7rXW7YTeGo9qwxXj/2BFpJTe37kTj3EnZCoX/nH+NP/WLA7O83fz8XhkGqsaAhLUPo/bB12vvd47nsmg==", + "dependencies": { + "@smithy/types": "^2.6.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/querystring-builder": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-2.0.14.tgz", + "integrity": "sha512-lQ4pm9vTv9nIhl5jt6uVMPludr6syE2FyJmHsIJJuOD7QPIJnrf9HhUGf1iHh9KJ4CUv21tpOU3X6s0rB6uJ0g==", + "dependencies": { + "@smithy/types": "^2.6.0", + "@smithy/util-uri-escape": "^2.0.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/querystring-parser": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-2.0.14.tgz", + "integrity": "sha512-+cbtXWI9tNtQjlgQg3CA+pvL3zKTAxPnG3Pj6MP89CR3vi3QMmD0SOWoq84tqZDnJCxlsusbgIXk1ngMReXo+A==", + "dependencies": { + "@smithy/types": "^2.6.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/service-error-classification": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-2.0.7.tgz", + "integrity": "sha512-LLxgW12qGz8doYto15kZ4x1rHjtXl0BnCG6T6Wb8z2DI4PT9cJfOSvzbuLzy7+5I24PAepKgFeWHRd9GYy3Z9w==", + "dependencies": { + "@smithy/types": "^2.6.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/shared-ini-file-loader": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-2.2.5.tgz", + "integrity": "sha512-LHA68Iu7SmNwfAVe8egmjDCy648/7iJR/fK1UnVw+iAOUJoEYhX2DLgVd5pWllqdDiRbQQzgaHLcRokM+UFR1w==", + "dependencies": { + "@smithy/types": "^2.6.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/signature-v4": { + "version": "2.0.16", + "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-2.0.16.tgz", + "integrity": "sha512-ilLY85xS2kZZzTb83diQKYLIYALvart0KnBaKnIRnMBHAGEio5aHSlANQoxVn0VsonwmQ3CnWhnCT0sERD8uTg==", + "dependencies": { + "@smithy/eventstream-codec": "^2.0.14", + "@smithy/is-array-buffer": "^2.0.0", + "@smithy/types": "^2.6.0", + "@smithy/util-hex-encoding": "^2.0.0", + "@smithy/util-middleware": "^2.0.7", + "@smithy/util-uri-escape": "^2.0.0", + "@smithy/util-utf8": "^2.0.2", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/smithy-client": { + "version": "2.1.16", + "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-2.1.16.tgz", + "integrity": "sha512-Lw67+yQSpLl4YkDLUzI2KgS8TXclXmbzSeOJUmRFS4ueT56B4pw3RZRF/SRzvgyxM/HxgkUan8oSHXCujPDafQ==", + "dependencies": { + "@smithy/middleware-stack": "^2.0.8", + "@smithy/types": "^2.6.0", + "@smithy/util-stream": "^2.0.21", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/types": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-2.6.0.tgz", + "integrity": "sha512-PgqxJq2IcdMF9iAasxcqZqqoOXBHufEfmbEUdN1pmJrJltT42b0Sc8UiYSWWzKkciIp9/mZDpzYi4qYG1qqg6g==", + "dependencies": { + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/url-parser": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-2.0.14.tgz", + "integrity": "sha512-kbu17Y1AFXi5lNlySdDj7ZzmvupyWKCX/0jNZ8ffquRyGdbDZb+eBh0QnWqsSmnZa/ctyWaTf7n4l/pXLExrnw==", + "dependencies": { + "@smithy/querystring-parser": "^2.0.14", + "@smithy/types": "^2.6.0", + "tslib": "^2.5.0" + } + }, + "node_modules/@smithy/util-base64": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-2.0.1.tgz", + "integrity": "sha512-DlI6XFYDMsIVN+GH9JtcRp3j02JEVuWIn/QOZisVzpIAprdsxGveFed0bjbMRCqmIFe8uetn5rxzNrBtIGrPIQ==", + "dependencies": { + "@smithy/util-buffer-from": "^2.0.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/util-body-length-browser": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-body-length-browser/-/util-body-length-browser-2.0.0.tgz", + "integrity": "sha512-JdDuS4ircJt+FDnaQj88TzZY3+njZ6O+D3uakS32f2VNnDo3vyEuNdBOh/oFd8Df1zSZOuH1HEChk2AOYDezZg==", + "dependencies": { + "tslib": "^2.5.0" + } + }, + "node_modules/@smithy/util-body-length-node": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@smithy/util-body-length-node/-/util-body-length-node-2.1.0.tgz", + "integrity": "sha512-/li0/kj/y3fQ3vyzn36NTLGmUwAICb7Jbe/CsWCktW363gh1MOcpEcSO3mJ344Gv2dqz8YJCLQpb6hju/0qOWw==", + "dependencies": { + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/util-buffer-from": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.0.0.tgz", + "integrity": "sha512-/YNnLoHsR+4W4Vf2wL5lGv0ksg8Bmk3GEGxn2vEQt52AQaPSCuaO5PM5VM7lP1K9qHRKHwrPGktqVoAHKWHxzw==", + "dependencies": { + "@smithy/is-array-buffer": "^2.0.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/util-config-provider": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-config-provider/-/util-config-provider-2.0.0.tgz", + "integrity": "sha512-xCQ6UapcIWKxXHEU4Mcs2s7LcFQRiU3XEluM2WcCjjBtQkUN71Tb+ydGmJFPxMUrW/GWMgQEEGipLym4XG0jZg==", + "dependencies": { + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/util-defaults-mode-browser": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-2.0.20.tgz", + "integrity": "sha512-QJtnbTIl0/BbEASkx1MUFf6EaoWqWW1/IM90N++8NNscePvPf77GheYfpoPis6CBQawUWq8QepTP2QUSAdrVkw==", + "dependencies": { + "@smithy/property-provider": "^2.0.15", + "@smithy/smithy-client": "^2.1.16", + "@smithy/types": "^2.6.0", + "bowser": "^2.11.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@smithy/util-defaults-mode-node": { + "version": "2.0.26", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-2.0.26.tgz", + "integrity": "sha512-lGFPOFCHv1ql019oegYqa54BZH7HREw6EBqjDLbAr0wquMX0BDi2sg8TJ6Eq+JGLijkZbJB73m4+aK8OFAapMg==", + "dependencies": { + "@smithy/config-resolver": "^2.0.19", + "@smithy/credential-provider-imds": "^2.1.2", + "@smithy/node-config-provider": "^2.1.6", + "@smithy/property-provider": "^2.0.15", + "@smithy/smithy-client": "^2.1.16", + "@smithy/types": "^2.6.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@smithy/util-endpoints": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@smithy/util-endpoints/-/util-endpoints-1.0.5.tgz", + "integrity": "sha512-K7qNuCOD5K/90MjHvHm9kJldrfm40UxWYQxNEShMFxV/lCCCRIg8R4uu1PFAxRvPxNpIdcrh1uK6I1ISjDXZJw==", + "dependencies": { + "@smithy/node-config-provider": "^2.1.6", + "@smithy/types": "^2.6.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@smithy/util-hex-encoding": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-2.0.0.tgz", + "integrity": "sha512-c5xY+NUnFqG6d7HFh1IFfrm3mGl29lC+vF+geHv4ToiuJCBmIfzx6IeHLg+OgRdPFKDXIw6pvi+p3CsscaMcMA==", + "dependencies": { + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/util-middleware": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-2.0.7.tgz", + "integrity": "sha512-tRINOTlf1G9B0ECarFQAtTgMhpnrMPSa+5j4ZEwEawCLfTFTavk6757sxhE4RY5RMlD/I3x+DCS8ZUiR8ho9Pw==", + "dependencies": { + "@smithy/types": "^2.6.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/util-retry": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-2.0.7.tgz", + "integrity": "sha512-fIe5yARaF0+xVT1XKcrdnHKTJ1Vc4+3e3tLDjCuIcE9b6fkBzzGFY7AFiX4M+vj6yM98DrwkuZeHf7/hmtVp0Q==", + "dependencies": { + "@smithy/service-error-classification": "^2.0.7", + "@smithy/types": "^2.6.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@smithy/util-stream": { + "version": "2.0.21", + "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-2.0.21.tgz", + "integrity": "sha512-0BUE16d7n1x7pi1YluXJdB33jOTyBChT0j/BlOkFa9uxfg6YqXieHxjHNuCdJRARa7AZEj32LLLEPJ1fSa4inA==", + "dependencies": { + "@smithy/fetch-http-handler": "^2.2.7", + "@smithy/node-http-handler": "^2.1.10", + "@smithy/types": "^2.6.0", + "@smithy/util-base64": "^2.0.1", + "@smithy/util-buffer-from": "^2.0.0", + "@smithy/util-hex-encoding": "^2.0.0", + "@smithy/util-utf8": "^2.0.2", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/util-uri-escape": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-2.0.0.tgz", + "integrity": "sha512-ebkxsqinSdEooQduuk9CbKcI+wheijxEb3utGXkCoYQkJnwTnLbH1JXGimJtUkQwNQbsbuYwG2+aFVyZf5TLaw==", + "dependencies": { + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/util-utf8": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.0.2.tgz", + "integrity": "sha512-qOiVORSPm6Ce4/Yu6hbSgNHABLP2VMv8QOC3tTDNHHlWY19pPyc++fBTbZPtx6egPXi4HQxKDnMxVxpbtX2GoA==", + "dependencies": { + "@smithy/util-buffer-from": "^2.0.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/util-waiter": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/@smithy/util-waiter/-/util-waiter-2.0.14.tgz", + "integrity": "sha512-Q6gSz4GUNjNGhrfNg+2Mjy+7K4pEI3r82x1b/+3dSc03MQqobMiUrRVN/YK/4nHVagvBELCoXsiHAFQJNQ5BeA==", + "dependencies": { + "@smithy/abort-controller": "^2.0.14", + "@smithy/types": "^2.6.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/@types/istanbul-lib-coverage": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", @@ -1215,6 +2372,15 @@ "node": ">=0.10.0" } }, + "node_modules/assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "dev": true, + "engines": { + "node": "*" + } + }, "node_modules/available-typed-arrays": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", @@ -1265,6 +2431,11 @@ "integrity": "sha512-VHiNCbI1lKdl44tGrhNfU3lup0Tj/ZBMJB5/2ZbNXRCPuRCO7ed2mgcK4r17y+KB2EfuYuRaVlwNbAeaWGSpbw==", "dev": true }, + "node_modules/bowser": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.11.0.tgz", + "integrity": "sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA==" + }, "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -1416,6 +2587,24 @@ "node": ">= 10" } }, + "node_modules/chai": { + "version": "4.3.10", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.10.tgz", + "integrity": "sha512-0UXG04VuVbruMUYbJ6JctvH0YnC/4q3/AkT18q4NaITo91CUm0liMS9VqzT9vZhVQ/1eqPanMWjBM+Juhfb/9g==", + "dev": true, + "dependencies": { + "assertion-error": "^1.1.0", + "check-error": "^1.0.3", + "deep-eql": "^4.1.3", + "get-func-name": "^2.0.2", + "loupe": "^2.3.6", + "pathval": "^1.1.1", + "type-detect": "^4.0.8" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -1432,6 +2621,18 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/check-error": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz", + "integrity": "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==", + "dev": true, + "dependencies": { + "get-func-name": "^2.0.2" + }, + "engines": { + "node": "*" + } + }, "node_modules/chokidar": { "version": "3.5.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", @@ -2005,6 +3206,18 @@ "node": ">=0.10.0" } }, + "node_modules/deep-eql": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz", + "integrity": "sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==", + "dev": true, + "dependencies": { + "type-detect": "^4.0.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/deep-extend": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", @@ -2738,6 +3951,27 @@ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "dev": true }, + "node_modules/fast-xml-parser": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.2.5.tgz", + "integrity": "sha512-B9/wizE4WngqQftFPmdaMYlXoJlJOYxGQOanC77fq9k8+Z0v5dDSVh+3glErdIROP//s/jgb7ZuxKfB8nVyo0g==", + "funding": [ + { + "type": "paypal", + "url": "https://paypal.me/naturalintelligence" + }, + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "dependencies": { + "strnum": "^1.0.5" + }, + "bin": { + "fxparser": "src/cli/cli.js" + } + }, "node_modules/fastq": { "version": "1.15.0", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", @@ -2951,9 +4185,9 @@ ] }, "node_modules/fs-extra": { - "version": "11.1.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.1.1.tgz", - "integrity": "sha512-MGIE4HOvQCeUCzmlHs0vXpih4ysz4wg9qiSAu6cd42lVwPbTM1TjV7RusoyQqMmk/95gdQZX72u+YW+c3eEpFQ==", + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", + "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", "dev": true, "dependencies": { "graceful-fs": "^4.2.0", @@ -3038,6 +4272,15 @@ "node": "6.* || 8.* || >= 10.*" } }, + "node_modules/get-func-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", + "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", + "dev": true, + "engines": { + "node": "*" + } + }, "node_modules/get-intrinsic": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz", @@ -4569,6 +5812,15 @@ "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, + "node_modules/loupe": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz", + "integrity": "sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==", + "dev": true, + "dependencies": { + "get-func-name": "^2.0.1" + } + }, "node_modules/lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", @@ -4895,6 +6147,14 @@ "integrity": "sha512-xOE9xbICroUDmG1ye2h4bZ8WBie9EGmACaco8K8cx6RlkJJrxGIqjGqztAI+NMhexXBcdGbSEzI6N3EJPevxZw==", "dev": true }, + "node_modules/mnemonist": { + "version": "0.38.3", + "resolved": "https://registry.npmjs.org/mnemonist/-/mnemonist-0.38.3.tgz", + "integrity": "sha512-2K9QYubXx/NAjv4VLq1d1Ly8pWNC5L3BrixtdkyTegXWJIqY+zLNDhhX/A+ZwWt70tB1S8H4BE8FLYEFyNoOBw==", + "dependencies": { + "obliterator": "^1.6.1" + } + }, "node_modules/mocha": { "version": "10.2.0", "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.2.0.tgz", @@ -7927,6 +9187,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/obliterator": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/obliterator/-/obliterator-1.6.1.tgz", + "integrity": "sha512-9WXswnqINnnhOG/5SLimUlzuU1hFJUc8zkwyD59Sd+dPOMf05PmnYG/d6Q7HZ+KmgkZJa1PxRso6QdM3sTNHig==" + }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -8139,6 +9404,15 @@ "node": ">=8" } }, + "node_modules/pathval": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", + "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", + "dev": true, + "engines": { + "node": "*" + } + }, "node_modules/picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", @@ -9792,6 +11066,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/strnum": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz", + "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==" + }, "node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -10034,6 +11313,11 @@ "strip-bom": "^3.0.0" } }, + "node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -10046,6 +11330,15 @@ "node": ">= 0.8.0" } }, + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, "node_modules/type-fest": { "version": "0.20.2", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", @@ -10217,6 +11510,14 @@ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", "dev": true }, + "node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/v8-to-istanbul": { "version": "9.2.0", "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.2.0.tgz", @@ -10567,9 +11868,19 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "packages/spacecat-shared-dynamo": { + "name": "@adobe/spacecat-shared-dynamo", + "version": "1.0.0", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/client-dynamodb": "3.454.0", + "@aws-sdk/lib-dynamodb": "3.454.0" + }, + "devDependencies": {} + }, "packages/spacecat-shared-example": { "name": "@adobe/spacecat-shared-example", - "version": "0.0.0-semantic-release", + "version": "1.0.0", "license": "Apache-2.0", "dependencies": { "@adobe/fetch": "4.1.1", @@ -10580,6 +11891,14 @@ "optionalDependencies": { "@adobe/helix-universal": "4.4.1" } + }, + "packages/spacecat-shared-utils": { + "name": "@adobe/spacecat-shared-utils", + "version": "1.0.0", + "license": "Apache-2.0", + "devDependencies": { + "chai": "4.3.10" + } } } } diff --git a/package.json b/package.json index 47171151..585e1c46 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "type": "module", "scripts": { "docs:api": "jsdoc2md -c .jsdoc.json --files packages/*/src/*.js > docs/API.md", - "docs": "npm run docs:schema && npm run docs:api", + "docs": "npm run docs:api", "test": "npm test -ws", "lint": "npm run lint -ws", "semantic-release": "npx --no-install -ws semantic-release -e semantic-release-monorepo", diff --git a/packages/spacecat-shared-dynamo/.jsdoc.json b/packages/spacecat-shared-dynamo/.jsdoc.json new file mode 100644 index 00000000..405090f4 --- /dev/null +++ b/packages/spacecat-shared-dynamo/.jsdoc.json @@ -0,0 +1,17 @@ +{ + "plugins": [], + "recurseDepth": 10, + "source": { + "includePattern": ".+\\.js(doc|x)?$", + "excludePattern": "(^|\\/|\\\\)_" + }, + "sourceType": "module", + "tags": { + "allowUnknownTags": true, + "dictionaries": ["jsdoc","closure"] + }, + "templates": { + "cleverLinks": false, + "monospaceLinks": false + } +} \ No newline at end of file diff --git a/packages/spacecat-shared-dynamo/.mocha-multi.json b/packages/spacecat-shared-dynamo/.mocha-multi.json new file mode 100644 index 00000000..aa2be2a2 --- /dev/null +++ b/packages/spacecat-shared-dynamo/.mocha-multi.json @@ -0,0 +1,6 @@ +{ + "reporterEnabled": "spec,xunit", + "xunitReporterOptions": { + "output": "junit/test-results.xml" + } +} diff --git a/packages/spacecat-shared-dynamo/.npmignore b/packages/spacecat-shared-dynamo/.npmignore new file mode 100644 index 00000000..868317d2 --- /dev/null +++ b/packages/spacecat-shared-dynamo/.npmignore @@ -0,0 +1,9 @@ +coverage/ +node_modules/ +junit/ +test/ +docs/ +logs/ +test-results.xml +renovate.json +.* diff --git a/packages/spacecat-shared-dynamo/.nycrc.json b/packages/spacecat-shared-dynamo/.nycrc.json new file mode 100644 index 00000000..78e7a0b1 --- /dev/null +++ b/packages/spacecat-shared-dynamo/.nycrc.json @@ -0,0 +1,10 @@ +{ + "reporter": [ + "lcov", + "text" + ], + "check-coverage": true, + "lines": 100, + "branches": 97, + "statements": 100 +} diff --git a/packages/spacecat-shared-dynamo/CHANGELOG.md b/packages/spacecat-shared-dynamo/CHANGELOG.md new file mode 100644 index 00000000..93177fb1 --- /dev/null +++ b/packages/spacecat-shared-dynamo/CHANGELOG.md @@ -0,0 +1,18 @@ +# @adobe/spacecat-shared-example-v1.0.0 (2023-11-27) + + +### Bug Fixes + +* bogus change to force release ([e77e830](https://github.com/adobe-rnd/spacecat-shared/commit/e77e8305c96ac2504aeb22af44d45cb4acbcae56)) +* package name to "adobe" ([475434e](https://github.com/adobe-rnd/spacecat-shared/commit/475434e6619c2128ba1a8308a4eed23cf3d40691)) +* remove unneeded import (force release) ([49964f9](https://github.com/adobe-rnd/spacecat-shared/commit/49964f99906d5a0fafeb68b460cb19f98a51fc86)) +* repo reference ([881487d](https://github.com/adobe-rnd/spacecat-shared/commit/881487dce4c840ac2bf02a285f17cac511d39c88)) +* roll-back esm monorepo ([ab77518](https://github.com/adobe-rnd/spacecat-shared/commit/ab775187dc79a7f2cdb0ca4fa31198202be78143)) +* set package version to semantic, remove dev deps ([bf62c5f](https://github.com/adobe-rnd/spacecat-shared/commit/bf62c5fe013dbbb7425eb21cffa23e7f01322aee)) +* set to semantic-release versioning ([9209799](https://github.com/adobe-rnd/spacecat-shared/commit/92097995b657207996dd6a35277fdfcd3f3e8fb9)) +* variouss ([ea9d44f](https://github.com/adobe-rnd/spacecat-shared/commit/ea9d44f6071c1a53d2c31515966e7cdf44be7ae9)) + + +### Features + +* test ([bd3cc5d](https://github.com/adobe-rnd/spacecat-shared/commit/bd3cc5df89ccde75b86b000e8495893f4b099b5b)) diff --git a/packages/spacecat-shared-dynamo/LICENSE.txt b/packages/spacecat-shared-dynamo/LICENSE.txt new file mode 100644 index 00000000..883ab098 --- /dev/null +++ b/packages/spacecat-shared-dynamo/LICENSE.txt @@ -0,0 +1,264 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +APACHE JACKRABBIT SUBCOMPONENTS + +Apache Jackrabbit includes parts with separate copyright notices and license +terms. Your use of these subcomponents is subject to the terms and conditions +of the following licenses: + + XPath 2.0/XQuery 1.0 Parser: + http://www.w3.org/2002/11/xquery-xpath-applets/xgrammar.zip + + Copyright (C) 2002 World Wide Web Consortium, (Massachusetts Institute of + Technology, European Research Consortium for Informatics and Mathematics, + Keio University). All Rights Reserved. + + This work is distributed under the W3C(R) Software License in the hope + that it will be useful, but WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + W3C(R) SOFTWARE NOTICE AND LICENSE + http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231 + + This work (and included software, documentation such as READMEs, or + other related items) is being provided by the copyright holders under + the following license. By obtaining, using and/or copying this work, + you (the licensee) agree that you have read, understood, and will comply + with the following terms and conditions. + + Permission to copy, modify, and distribute this software and its + documentation, with or without modification, for any purpose and + without fee or royalty is hereby granted, provided that you include + the following on ALL copies of the software and documentation or + portions thereof, including modifications: + + 1. The full text of this NOTICE in a location viewable to users + of the redistributed or derivative work. + + 2. Any pre-existing intellectual property disclaimers, notices, + or terms and conditions. If none exist, the W3C Software Short + Notice should be included (hypertext is preferred, text is + permitted) within the body of any redistributed or derivative code. + + 3. Notice of any changes or modifications to the files, including + the date changes were made. (We recommend you provide URIs to the + location from which the code is derived.) + + THIS SOFTWARE AND DOCUMENTATION IS PROVIDED "AS IS," AND COPYRIGHT + HOLDERS MAKE NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, + INCLUDING BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS + FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF THE SOFTWARE OR + DOCUMENTATION WILL NOT INFRINGE ANY THIRD PARTY PATENTS, COPYRIGHTS, + TRADEMARKS OR OTHER RIGHTS. + + COPYRIGHT HOLDERS WILL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL + OR CONSEQUENTIAL DAMAGES ARISING OUT OF ANY USE OF THE SOFTWARE OR + DOCUMENTATION. + + The name and trademarks of copyright holders may NOT be used in + advertising or publicity pertaining to the software without specific, + written prior permission. Title to copyright in this software and + any associated documentation will at all times remain with + copyright holders. diff --git a/packages/spacecat-shared-dynamo/README.md b/packages/spacecat-shared-dynamo/README.md new file mode 100644 index 00000000..d9047069 --- /dev/null +++ b/packages/spacecat-shared-dynamo/README.md @@ -0,0 +1,15 @@ +# Spacecat Shared - DynamoDB Client + +TBD + +## Usage + +```js +import { createClient } from '@adobe/spacecat-shared-dynamo'; + +const dynamoDbClient = createClient(); + +const result = await dynamoDbClient.query(...); +... + +``` diff --git a/packages/spacecat-shared-dynamo/package.json b/packages/spacecat-shared-dynamo/package.json new file mode 100644 index 00000000..520ec762 --- /dev/null +++ b/packages/spacecat-shared-dynamo/package.json @@ -0,0 +1,38 @@ +{ + "name": "@adobe/spacecat-shared-dynamo", + "version": "1.0.0", + "description": "Shared modules of the Spacecat Services - DynamoDB client", + "type": "module", + "main": "src/indeex.js", + "types": "src/index.d.ts", + "scripts": { + "test": "c8 mocha", + "lint": "eslint .", + "clean": "rm -rf package-lock.json node_modules" + }, + "mocha": { + "reporter": "mocha-multi-reporters", + "reporter-options": "configFile=.mocha-multi.json", + "spec": "test/**/*.test.js" + }, + "repository": { + "type": "git", + "url": "https://github.com/adobe-rnd/spacecat-shared.git" + }, + "author": "", + "license": "Apache-2.0", + "bugs": { + "url": "https://github.com/adobe-rnd/spacecat-shared/issues" + }, + "homepage": "https://github.com/adobe-rnd/spacecat-shared#readme", + "publishConfig": { + "access": "public" + }, + "dependencies": { + "@aws-sdk/client-dynamodb": "3.454.0", + "@aws-sdk/lib-dynamodb": "3.454.0" + }, + "devDependencies": { + "chai": "4.3.10" + } +} diff --git a/packages/spacecat-shared-dynamo/src/index.d.ts b/packages/spacecat-shared-dynamo/src/index.d.ts new file mode 100644 index 00000000..98a79528 --- /dev/null +++ b/packages/spacecat-shared-dynamo/src/index.d.ts @@ -0,0 +1,33 @@ +/* + * Copyright 2023 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +import { DynamoDB } from '@aws-sdk/client-dynamodb'; +import { DynamoDBDocumentClient, QueryCommandInput } from '@aws-sdk/lib-dynamodb'; + +export declare interface Logger { + error(message: string, ...args: any[]): void; + info(message: string, ...args: any[]): void; +} + +export declare interface DynamoDbKey { + partitionKey: string; + sortKey?: string; +} + +export declare interface DynamoDbClient { + query(originalParams: QueryCommandInput): Promise; + getItem(tableName: string, key: DynamoDbKey): Promise; + putItem(tableName: string, item: object): Promise<{ message: string }>; + removeItem(tableName: string, key: DynamoDbKey): Promise<{ message: string }>; +} + +export function createClient(logger: Logger, dbClient?: DynamoDB, docClient?: DynamoDBDocumentClient): DynamoDbClient; diff --git a/packages/spacecat-shared-dynamo/src/index.js b/packages/spacecat-shared-dynamo/src/index.js new file mode 100644 index 00000000..6b09ed72 --- /dev/null +++ b/packages/spacecat-shared-dynamo/src/index.js @@ -0,0 +1,40 @@ +/* + * Copyright 2023 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +import { DynamoDB } from '@aws-sdk/client-dynamodb'; +import { DynamoDBDocumentClient } from '@aws-sdk/lib-dynamodb'; + +import query from './modules/query.js'; +import getItem from './modules/getItem.js'; +import putItem from './modules/putItem.js'; +import removeItem from './modules/removeItem.js'; + +/** + * Creates a client object for interacting with DynamoDB. + * + * @param {Object} log - The logging object, defaults to console. + * @param {DynamoDB} dbClient - The AWS SDK DynamoDB client instance. + * @param {DynamoDBDocumentClient} docClient - The AWS SDK DynamoDB Document client instance. + * @returns {Object} A client object with methods to interact with DynamoDB. + */ +const createClient = ( + log = console, + dbClient = new DynamoDB(), + docClient = DynamoDBDocumentClient.from(dbClient), +) => ({ + query: (params) => query(docClient, params, log), + getItem: (tableName, key) => getItem(docClient, tableName, key, log), + putItem: (tableName, item) => putItem(docClient, tableName, item, log), + removeItem: (tableName, key) => removeItem(docClient, tableName, key, log), +}); + +export { createClient }; diff --git a/packages/spacecat-shared-dynamo/src/modules/getItem.js b/packages/spacecat-shared-dynamo/src/modules/getItem.js new file mode 100644 index 00000000..eaa64a3f --- /dev/null +++ b/packages/spacecat-shared-dynamo/src/modules/getItem.js @@ -0,0 +1,56 @@ +/* + * Copyright 2023 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +import { performance } from 'perf_hooks'; + +/** + * Retrieves an item from DynamoDB using a table name and key object. + * + * @param {DynamoDBDocumentClient} docClient - The AWS SDK DynamoDB Document client instance. + * @param {string} tableName - The name of the DynamoDB table. + * @param {DynamoDbKey} key - The key object containing partitionKey and optionally sortKey. + * @param {Logger} log - The logging object, defaults to console. + * @returns {Promise} A promise that resolves to the retrieved item. + * @throws {Error} Throws an error if the DynamoDB get operation fails or input validation fails. + */ +async function getItem(docClient, tableName, key, log = console) { + if (!tableName || typeof tableName !== 'string') { + throw new Error('Invalid tableName: must be a non-empty string.'); + } + + if (!key || typeof key !== 'object' || !key.partitionKey) { + throw new Error('Invalid key: must be an object with a partitionKey.'); + } + + const params = { + TableName: tableName, + Key: key, + }; + + try { + const startTime = performance.now(); + + const data = await docClient.get(params); + + const endTime = performance.now(); + const duration = endTime - startTime; + + log.info(`GetItem execution time: ${duration.toFixed(2)} ms for query: ${JSON.stringify(params)}`); + + return data.Item; + } catch (error) { + log.error('DB Get Item Error:', error); + throw error; + } +} + +export default getItem; diff --git a/packages/spacecat-shared-dynamo/src/modules/putItem.js b/packages/spacecat-shared-dynamo/src/modules/putItem.js new file mode 100644 index 00000000..39fb28ea --- /dev/null +++ b/packages/spacecat-shared-dynamo/src/modules/putItem.js @@ -0,0 +1,52 @@ +/* + * Copyright 2023 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +import { performance } from 'perf_hooks'; + +/** + * Inserts or updates an item in a DynamoDB table. + * + * @param {DynamoDBDocumentClient} docClient - The AWS SDK DynamoDB Document client instance. + * @param {string} tableName - The name of the DynamoDB table. + * @param {Object} item - The item to insert or update in the table. + * @param {Logger} log - The logging object, defaults to console. + * @returns {Promise} A promise that resolves to a message indicating success. + * @throws {Error} Throws an error if the DynamoDB put operation fails. + */ +async function putItem(docClient, tableName, item, log = console) { + if (!tableName || typeof tableName !== 'string') { + throw new Error('Invalid tableName: must be a non-empty string.'); + } + + const params = { + TableName: tableName, + Item: item, + }; + + try { + const startTime = performance.now(); + + await docClient.put(params); + + const endTime = performance.now(); + const duration = endTime - startTime; + + log.info(`PutItem execution time: ${duration.toFixed(2)} ms for query: ${JSON.stringify(params)}`); + + return { message: 'Item inserted/updated successfully.' }; + } catch (error) { + log.error('DB Put Item Error:', error); + throw error; + } +} + +export default putItem; diff --git a/packages/spacecat-shared-dynamo/src/modules/query.js b/packages/spacecat-shared-dynamo/src/modules/query.js new file mode 100644 index 00000000..0bec8a76 --- /dev/null +++ b/packages/spacecat-shared-dynamo/src/modules/query.js @@ -0,0 +1,65 @@ +/* + * Copyright 2023 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +import { performance } from 'perf_hooks'; + +/** + * Queries DynamoDB and automatically handles pagination to retrieve all items. + * + * @param {DynamoDBDocumentClient} docClient - The AWS SDK DynamoDB Document client instance. + * @param {Object} originalParams - The parameters for the DynamoDB query. + * @param {Logger} log - The logging object, defaults to console. + * @returns {Promise} A promise that resolves to an array of items retrieved from DynamoDB. + * @throws {Error} Throws an error if the DynamoDB query operation fails. + */ +async function query(docClient, originalParams, log = console) { + let items = []; + const params = { ...originalParams }; + + let totalTime = 0; + let paginationCount = 0; + + try { + let data; + do { + const startTime = performance.now(); + + /* + This is one of the scenarios where it's appropriate to disable + the ESLint rule for this specific case. + In this case, it's necessary because each query depends on the + result of the previous one (to get the LastEvaluatedKey). + */ + // eslint-disable-next-line no-await-in-loop + data = await docClient.query(params); + + const endTime = performance.now(); // End timing + const duration = endTime - startTime; + totalTime += duration; + paginationCount += 1; + + log.info(`Pagination ${paginationCount} query time: ${duration.toFixed(2)} ms`); + + items = items.concat(data.Items); + params.ExclusiveStartKey = data.LastEvaluatedKey; + } while (data.LastEvaluatedKey); + } catch (error) { + log.error('DB Query Error:', error); + throw error; + } + + log.info(`Total query time: ${totalTime.toFixed(2)} ms with ${paginationCount} paginations for query: ${JSON.stringify(params)}`); + + return items; +} + +export default query; diff --git a/packages/spacecat-shared-dynamo/src/modules/removeItem.js b/packages/spacecat-shared-dynamo/src/modules/removeItem.js new file mode 100644 index 00000000..a89a4ace --- /dev/null +++ b/packages/spacecat-shared-dynamo/src/modules/removeItem.js @@ -0,0 +1,56 @@ +/* + * Copyright 2023 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +import { performance } from 'perf_hooks'; + +/** + * Removes an item from a DynamoDB table. + * + * @param {DynamoDBDocumentClient} docClient - The AWS SDK DynamoDB Document client instance. + * @param {string} tableName - The name of the DynamoDB table. + * @param {DynamoDbKey} key - The key object containing partitionKey and optionally sortKey. + * @param {Logger} log - The logging object, defaults to console. + * @returns {Promise} A promise that resolves to a message indicating successful removal. + * @throws {Error} Throws an error if the DynamoDB delete operation fails or input validation fails. + */ +async function removeItem(docClient, tableName, key, log = console) { + if (!tableName || typeof tableName !== 'string') { + throw new Error('Invalid tableName: must be a non-empty string.'); + } + + if (!key || typeof key !== 'object' || !key.partitionKey) { + throw new Error('Invalid key: must be an object with a partitionKey.'); + } + + const params = { + TableName: tableName, + Key: key, + }; + + try { + const startTime = performance.now(); + + await docClient.delete(params); + + const endTime = performance.now(); + const duration = endTime - startTime; + + log.info(`RemoveItem execution time: ${duration.toFixed(2)} ms for query: ${JSON.stringify(params)}`); + + return { message: 'Item removed successfully.' }; + } catch (error) { + log.error('DB Remove Item Error:', error); + throw error; + } +} + +export default removeItem; diff --git a/packages/spacecat-shared-dynamo/test/index.test.js b/packages/spacecat-shared-dynamo/test/index.test.js new file mode 100644 index 00000000..6999524b --- /dev/null +++ b/packages/spacecat-shared-dynamo/test/index.test.js @@ -0,0 +1,56 @@ +/* + * Copyright 2023 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +/* eslint-env mocha */ +import { expect } from 'chai'; +import { DynamoDB } from '@aws-sdk/client-dynamodb'; +import { DynamoDBDocumentClient } from '@aws-sdk/lib-dynamodb'; +import { createClient } from '../src/index.js'; + +describe('createClient', () => { + let dbClient; + let docClient; + + beforeEach(() => { + dbClient = new DynamoDB(); + docClient = DynamoDBDocumentClient.from(dbClient); + }); + + it('should create a DynamoDB client with query method', () => { + const client = createClient(console, dbClient, docClient); + expect(client).to.have.property('query'); + expect(client.query).to.be.a('function'); + }); + + it('should create a DynamoDB client with getItem method', () => { + const client = createClient(console, dbClient, docClient); + expect(client).to.have.property('getItem'); + expect(client.getItem).to.be.a('function'); + }); + + it('should create a DynamoDB client with putItem method', () => { + const client = createClient(console, dbClient, docClient); + expect(client).to.have.property('putItem'); + expect(client.putItem).to.be.a('function'); + }); + + it('should create a DynamoDB client with removeItem method', () => { + const client = createClient(console, dbClient, docClient); + expect(client).to.have.property('removeItem'); + expect(client.removeItem).to.be.a('function'); + }); + + it('should use default parameters if none are provided', () => { + const client = createClient(); + expect(client).to.have.all.keys('query', 'getItem', 'putItem', 'removeItem'); + }); +}); diff --git a/packages/spacecat-shared-dynamo/test/modules/getItem.test.js b/packages/spacecat-shared-dynamo/test/modules/getItem.test.js new file mode 100644 index 00000000..16fdbd28 --- /dev/null +++ b/packages/spacecat-shared-dynamo/test/modules/getItem.test.js @@ -0,0 +1,73 @@ +/* + * Copyright 2023 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +/* eslint-env mocha */ + +import { expect } from 'chai'; +import { createClient } from '../../src/index.js'; + +describe('getItem', () => { + let dynamoDbClient; + let mockDocClient; + + beforeEach(() => { + mockDocClient = { + get: async () => ({ Item: {} }), + }; + + dynamoDbClient = createClient(console, undefined, mockDocClient); + }); + + it('gets an item from the database', async () => { + const key = { partitionKey: 'testPartitionKey' }; + const result = await dynamoDbClient.getItem('TestTable', key); + expect(result).to.be.an('object'); + }); + + it('gets an item from the database with sort key', async () => { + const key = { partitionKey: 'testPartitionKey', sortKey: 'testSortKey' }; + const result = await dynamoDbClient.getItem('TestTable', key); + expect(result).to.be.an('object'); + }); + + it('throws an error for getItem with invalid tableName', async () => { + const key = { partitionKey: 'testPartitionKey' }; + try { + await dynamoDbClient.getItem('', key); + expect.fail('getItem did not throw with empty tableName'); + } catch (error) { + expect(error.message).to.equal('Invalid tableName: must be a non-empty string.'); + } + }); + + it('throws an error for getItem with invalid key', async () => { + try { + await dynamoDbClient.getItem('TestTable', null); + expect.fail('getItem did not throw with invalid key'); + } catch (error) { + expect(error.message).to.equal('Invalid key: must be an object with a partitionKey.'); + } + }); + + it('handles errors in getItem', async () => { + mockDocClient.get = async () => { + throw new Error('Get failed'); + }; + + try { + await dynamoDbClient.getItem('TestTable', { partitionKey: 'testPartitionKey' }); + expect.fail('getItem did not throw as expected'); + } catch (error) { + expect(error.message).to.equal('Get failed'); + } + }); +}); diff --git a/packages/spacecat-shared-dynamo/test/modules/putItem.test.js b/packages/spacecat-shared-dynamo/test/modules/putItem.test.js new file mode 100644 index 00000000..2c32df75 --- /dev/null +++ b/packages/spacecat-shared-dynamo/test/modules/putItem.test.js @@ -0,0 +1,56 @@ +/* + * Copyright 2023 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +/* eslint-env mocha */ + +import { expect } from 'chai'; +import { createClient } from '../../src/index.js'; + +describe('putItem', () => { + let dynamoDbClient; + let mockDocClient; + + beforeEach(() => { + mockDocClient = { + put: async () => ({}), + }; + + dynamoDbClient = createClient(console, undefined, mockDocClient); + }); + + it('puts an item into the database', async () => { + const result = await dynamoDbClient.putItem('TestTable', { someKey: 'someValue' }); + expect(result).to.deep.equal({ message: 'Item inserted/updated successfully.' }); + }); + + it('throws an error for putItem with invalid tableName', async () => { + try { + await dynamoDbClient.putItem('', { someKey: 'someValue' }); + expect.fail('putItem did not throw with empty tableName'); + } catch (error) { + expect(error.message).to.equal('Invalid tableName: must be a non-empty string.'); + } + }); + + it('handles errors in putItem', async () => { + mockDocClient.put = async () => { + throw new Error('Put failed'); + }; + + try { + await dynamoDbClient.putItem('TestTable', { someKey: 'someValue' }); + expect.fail('putItem did not throw as expected'); + } catch (error) { + expect(error.message).to.equal('Put failed'); + } + }); +}); diff --git a/packages/spacecat-shared-dynamo/test/modules/query.test.js b/packages/spacecat-shared-dynamo/test/modules/query.test.js new file mode 100644 index 00000000..3424f47d --- /dev/null +++ b/packages/spacecat-shared-dynamo/test/modules/query.test.js @@ -0,0 +1,60 @@ +/* + * Copyright 2023 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +/* eslint-env mocha */ + +import { expect } from 'chai'; +import { createClient } from '../../src/index.js'; + +describe('query', () => { + let dynamoDbClient; + let mockDocClient; + + beforeEach(() => { + mockDocClient = { + query: async (params) => { + // Check if LastEvaluatedKey is provided and simulate pagination + if (params.ExclusiveStartKey === 'key2') { + return { Items: ['item3'], LastEvaluatedKey: undefined }; + } else { + return { Items: ['item1', 'item2'], LastEvaluatedKey: 'key2' }; + } + }, + }; + + dynamoDbClient = createClient(console, undefined, mockDocClient); + }); + + it('queries items from the database', async () => { + const result = await dynamoDbClient.query({ TableName: 'TestTable' }); + expect(result).to.be.an('array'); + }); + + it('queries items from the database with pagination', async () => { + const result = await dynamoDbClient.query({ TableName: 'TestTable' }); + expect(result).to.have.lengthOf(3); + expect(result).to.deep.equal(['item1', 'item2', 'item3']); + }); + + it('handles errors in query', async () => { + mockDocClient.query = async () => { + throw new Error('Query failed'); + }; + + try { + await dynamoDbClient.query({ TableName: 'TestTable' }); + expect.fail('queryDb did not throw as expected'); + } catch (error) { + expect(error.message).to.equal('Query failed'); + } + }); +}); diff --git a/packages/spacecat-shared-dynamo/test/modules/removeItem.test.js b/packages/spacecat-shared-dynamo/test/modules/removeItem.test.js new file mode 100644 index 00000000..f1c772f7 --- /dev/null +++ b/packages/spacecat-shared-dynamo/test/modules/removeItem.test.js @@ -0,0 +1,73 @@ +/* + * Copyright 2023 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +/* eslint-env mocha */ + +import { expect } from 'chai'; +import { createClient } from '../../src/index.js'; + +describe('removeItem', () => { + let dynamoDbClient; + let mockDocClient; + + beforeEach(() => { + mockDocClient = { + delete: async () => ({}), + }; + + dynamoDbClient = createClient(console, undefined, mockDocClient); + }); + + it('removes an item from the database', async () => { + const key = { partitionKey: 'testPartitionKey' }; + const result = await dynamoDbClient.removeItem('TestTable', key); + expect(result).to.deep.equal({ message: 'Item removed successfully.' }); + }); + + it('removes an item from the database with sort key', async () => { + const key = { partitionKey: 'testPartitionKey', sortKey: 'testSortKey' }; + const result = await dynamoDbClient.removeItem('TestTable', key); + expect(result).to.deep.equal({ message: 'Item removed successfully.' }); + }); + + it('throws an error for removeItem with invalid tableName', async () => { + const key = { partitionKey: 'testPartitionKey' }; + try { + await dynamoDbClient.removeItem('', key); + expect.fail('removeItem did not throw with empty tableName'); + } catch (error) { + expect(error.message).to.equal('Invalid tableName: must be a non-empty string.'); + } + }); + + it('throws an error for removeItem with invalid key', async () => { + try { + await dynamoDbClient.removeItem('TestTable', null); + expect.fail('removeItem did not throw with invalid key'); + } catch (error) { + expect(error.message).to.equal('Invalid key: must be an object with a partitionKey.'); + } + }); + + it('handles errors in removeItem', async () => { + mockDocClient.delete = async () => { + throw new Error('Remove failed'); + }; + + try { + await dynamoDbClient.removeItem('TestTable', { partitionKey: 'testPartitionKey' }); + expect.fail('removeItem did not throw as expected'); + } catch (error) { + expect(error.message).to.equal('Remove failed'); + } + }); +}); diff --git a/packages/spacecat-shared-utils/.jsdoc.json b/packages/spacecat-shared-utils/.jsdoc.json new file mode 100644 index 00000000..405090f4 --- /dev/null +++ b/packages/spacecat-shared-utils/.jsdoc.json @@ -0,0 +1,17 @@ +{ + "plugins": [], + "recurseDepth": 10, + "source": { + "includePattern": ".+\\.js(doc|x)?$", + "excludePattern": "(^|\\/|\\\\)_" + }, + "sourceType": "module", + "tags": { + "allowUnknownTags": true, + "dictionaries": ["jsdoc","closure"] + }, + "templates": { + "cleverLinks": false, + "monospaceLinks": false + } +} \ No newline at end of file diff --git a/packages/spacecat-shared-utils/.mocha-multi.json b/packages/spacecat-shared-utils/.mocha-multi.json new file mode 100644 index 00000000..aa2be2a2 --- /dev/null +++ b/packages/spacecat-shared-utils/.mocha-multi.json @@ -0,0 +1,6 @@ +{ + "reporterEnabled": "spec,xunit", + "xunitReporterOptions": { + "output": "junit/test-results.xml" + } +} diff --git a/packages/spacecat-shared-utils/.npmignore b/packages/spacecat-shared-utils/.npmignore new file mode 100644 index 00000000..868317d2 --- /dev/null +++ b/packages/spacecat-shared-utils/.npmignore @@ -0,0 +1,9 @@ +coverage/ +node_modules/ +junit/ +test/ +docs/ +logs/ +test-results.xml +renovate.json +.* diff --git a/packages/spacecat-shared-utils/.nycrc.json b/packages/spacecat-shared-utils/.nycrc.json new file mode 100644 index 00000000..78e7a0b1 --- /dev/null +++ b/packages/spacecat-shared-utils/.nycrc.json @@ -0,0 +1,10 @@ +{ + "reporter": [ + "lcov", + "text" + ], + "check-coverage": true, + "lines": 100, + "branches": 97, + "statements": 100 +} diff --git a/packages/spacecat-shared-utils/CHANGELOG.md b/packages/spacecat-shared-utils/CHANGELOG.md new file mode 100644 index 00000000..93177fb1 --- /dev/null +++ b/packages/spacecat-shared-utils/CHANGELOG.md @@ -0,0 +1,18 @@ +# @adobe/spacecat-shared-example-v1.0.0 (2023-11-27) + + +### Bug Fixes + +* bogus change to force release ([e77e830](https://github.com/adobe-rnd/spacecat-shared/commit/e77e8305c96ac2504aeb22af44d45cb4acbcae56)) +* package name to "adobe" ([475434e](https://github.com/adobe-rnd/spacecat-shared/commit/475434e6619c2128ba1a8308a4eed23cf3d40691)) +* remove unneeded import (force release) ([49964f9](https://github.com/adobe-rnd/spacecat-shared/commit/49964f99906d5a0fafeb68b460cb19f98a51fc86)) +* repo reference ([881487d](https://github.com/adobe-rnd/spacecat-shared/commit/881487dce4c840ac2bf02a285f17cac511d39c88)) +* roll-back esm monorepo ([ab77518](https://github.com/adobe-rnd/spacecat-shared/commit/ab775187dc79a7f2cdb0ca4fa31198202be78143)) +* set package version to semantic, remove dev deps ([bf62c5f](https://github.com/adobe-rnd/spacecat-shared/commit/bf62c5fe013dbbb7425eb21cffa23e7f01322aee)) +* set to semantic-release versioning ([9209799](https://github.com/adobe-rnd/spacecat-shared/commit/92097995b657207996dd6a35277fdfcd3f3e8fb9)) +* variouss ([ea9d44f](https://github.com/adobe-rnd/spacecat-shared/commit/ea9d44f6071c1a53d2c31515966e7cdf44be7ae9)) + + +### Features + +* test ([bd3cc5d](https://github.com/adobe-rnd/spacecat-shared/commit/bd3cc5df89ccde75b86b000e8495893f4b099b5b)) diff --git a/packages/spacecat-shared-utils/LICENSE.txt b/packages/spacecat-shared-utils/LICENSE.txt new file mode 100644 index 00000000..883ab098 --- /dev/null +++ b/packages/spacecat-shared-utils/LICENSE.txt @@ -0,0 +1,264 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +APACHE JACKRABBIT SUBCOMPONENTS + +Apache Jackrabbit includes parts with separate copyright notices and license +terms. Your use of these subcomponents is subject to the terms and conditions +of the following licenses: + + XPath 2.0/XQuery 1.0 Parser: + http://www.w3.org/2002/11/xquery-xpath-applets/xgrammar.zip + + Copyright (C) 2002 World Wide Web Consortium, (Massachusetts Institute of + Technology, European Research Consortium for Informatics and Mathematics, + Keio University). All Rights Reserved. + + This work is distributed under the W3C(R) Software License in the hope + that it will be useful, but WITHOUT ANY WARRANTY; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + W3C(R) SOFTWARE NOTICE AND LICENSE + http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231 + + This work (and included software, documentation such as READMEs, or + other related items) is being provided by the copyright holders under + the following license. By obtaining, using and/or copying this work, + you (the licensee) agree that you have read, understood, and will comply + with the following terms and conditions. + + Permission to copy, modify, and distribute this software and its + documentation, with or without modification, for any purpose and + without fee or royalty is hereby granted, provided that you include + the following on ALL copies of the software and documentation or + portions thereof, including modifications: + + 1. The full text of this NOTICE in a location viewable to users + of the redistributed or derivative work. + + 2. Any pre-existing intellectual property disclaimers, notices, + or terms and conditions. If none exist, the W3C Software Short + Notice should be included (hypertext is preferred, text is + permitted) within the body of any redistributed or derivative code. + + 3. Notice of any changes or modifications to the files, including + the date changes were made. (We recommend you provide URIs to the + location from which the code is derived.) + + THIS SOFTWARE AND DOCUMENTATION IS PROVIDED "AS IS," AND COPYRIGHT + HOLDERS MAKE NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, + INCLUDING BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS + FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF THE SOFTWARE OR + DOCUMENTATION WILL NOT INFRINGE ANY THIRD PARTY PATENTS, COPYRIGHTS, + TRADEMARKS OR OTHER RIGHTS. + + COPYRIGHT HOLDERS WILL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL + OR CONSEQUENTIAL DAMAGES ARISING OUT OF ANY USE OF THE SOFTWARE OR + DOCUMENTATION. + + The name and trademarks of copyright holders may NOT be used in + advertising or publicity pertaining to the software without specific, + written prior permission. Title to copyright in this software and + any associated documentation will at all times remain with + copyright holders. diff --git a/packages/spacecat-shared-utils/README.md b/packages/spacecat-shared-utils/README.md new file mode 100644 index 00000000..219cd85e --- /dev/null +++ b/packages/spacecat-shared-utils/README.md @@ -0,0 +1,3 @@ +# Spacecat Shared - Utils + +A collection of utility functions. diff --git a/packages/spacecat-shared-utils/package.json b/packages/spacecat-shared-utils/package.json new file mode 100644 index 00000000..1dc38699 --- /dev/null +++ b/packages/spacecat-shared-utils/package.json @@ -0,0 +1,34 @@ +{ + "name": "@adobe/spacecat-shared-utils", + "version": "1.0.0", + "description": "Shared modules of the Spacecat Services - utils", + "type": "module", + "main": "src/index.js", + "types": "src/index.d.ts", + "scripts": { + "test": "c8 mocha", + "lint": "eslint .", + "clean": "rm -rf package-lock.json node_modules" + }, + "mocha": { + "reporter": "mocha-multi-reporters", + "reporter-options": "configFile=.mocha-multi.json", + "spec": "test/*.test.js" + }, + "repository": { + "type": "git", + "url": "https://github.com/adobe-rnd/spacecat-shared.git" + }, + "author": "", + "license": "Apache-2.0", + "bugs": { + "url": "https://github.com/adobe-rnd/spacecat-shared/issues" + }, + "homepage": "https://github.com/adobe-rnd/spacecat-shared#readme", + "publishConfig": { + "access": "public" + }, + "devDependencies": { + "chai": "4.3.10" + } +} diff --git a/packages/spacecat-shared-utils/src/functions.js b/packages/spacecat-shared-utils/src/functions.js new file mode 100644 index 00000000..4e877714 --- /dev/null +++ b/packages/spacecat-shared-utils/src/functions.js @@ -0,0 +1,171 @@ +/* + * Copyright 2023 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +// Precompile regular expressions +const REGEX_ISO_DATE = /\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3}Z/; +const REGEX_TIME_OFFSET_DATE = /\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3}(Z|[+-]\d{2}:\d{2})/; + +/** + * Determines case-insensitively if the given value is a boolean or a string + * representation of a boolean. + * + * @param {*} value - The value to check. + * @returns {boolean} True if the value is a boolean or a string representation of a boolean. + */ +function isBoolean(value) { + const lowerCaseValue = String(value).toLowerCase(); + return typeof value === 'boolean' || lowerCaseValue === 'true' || lowerCaseValue === 'false'; +} + +/** + * Checks if the given value is an integer. + * + * @param {*} value - The value to check. + * @returns {boolean} True if the value is an integer, false otherwise. + */ +function isInteger(value) { + return typeof value === 'number' && Number.isInteger(value); +} + +/** + * Determines if the given value is a number. + * + * @param {*} value - The value to check. + * @returns {boolean} True if the value is a finite number, false otherwise. + */ +function isNumber(value) { + return typeof value === 'number' && Number.isFinite(value); +} + +/** + * Checks if the given parameter is an object and not an array or null. + * + * @param {*} obj - The object to check. + * @returns {boolean} True if the parameter is an object, false otherwise. + */ +function isObject(obj) { + return !Array.isArray(obj) && obj !== null && typeof obj === 'object'; +} + +/** + * Determines if the given parameter is a string. + * + * @param {*} str - The string to check. + * @returns {boolean} True if the parameter is a string, false otherwise. + */ +function isString(str) { + return (!!str || str === '') && typeof str === 'string'; +} + +/** + * Checks if the given string is not empty. + * + * @param {*} str - The string to check. + * @returns {boolean} True if the string is not empty, false otherwise. + */ +function hasText(str) { + return !!str && typeof str === 'string'; +} + +/** + * Checks whether the given object is a valid JavaScript Date. + * + * @param {*} obj - The object to check. + * @returns {boolean} True if the given object is a valid Date object, false otherwise. + */ +function isValidDate(obj) { + return obj instanceof Date && !Number.isNaN(obj.getTime()); +} + +/** + * Validates whether the given string is a JavaScript ISO date string in + * Zulu (UTC) timezone. Used for persisting system dates, which must be + * independent of any user timezone. + * + * @param {string} str - The string to validate. + * @returns {boolean} True if the given string validates successfully. + */ +function isIsoDate(str) { + if (!REGEX_ISO_DATE.test(str)) { + return false; + } + + const date = new Date(str); + return isValidDate(date) && date.toISOString() === str; +} + +/** + * Validates whether the given string is a JavaScript ISO date string + * following UTC time offsets format. + * + * @param {string} str - The string to validate. + * @returns {boolean} True if the given string validates successfully. + */ +function isIsoTimeOffsetsDate(str) { + return REGEX_TIME_OFFSET_DATE.test(str); +} + +/** + * Validates whether the given string is a valid URL with http or https protocol. + * + * @param {string} urlString - The string to validate. + * @returns {boolean} True if the given string validates successfully. + */ +function isValidUrl(urlString) { + try { + const url = new URL(urlString); + return url.protocol === 'http:' || url.protocol === 'https:'; + } catch (e) { + return false; + } +} + +/** + * Converts a given value to a boolean. Throws an error if the value is not a boolean. + * + * @param {*} value - The value to convert. + * @returns {boolean} The converted boolean value. + * @throws {Error} If the value is not a boolean or a boolean-like string. + */ +function toBoolean(value) { + if (!isBoolean(value)) { + throw new Error('Not a boolean value'); + } + return JSON.parse(String(value).toLowerCase()); +} + +/** + * Compares two arrays for equality. Supports primitive array item types only. + * + * @param {Array} a - The first array to compare. + * @param {Array} b - The second array to compare. + * @returns {boolean} True if the arrays are equal, false otherwise. + */ +const arrayEquals = (a, b) => Array.isArray(a) + && Array.isArray(b) + && a.length === b.length + && a.every((val, index) => val === b[index]); + +export { + arrayEquals, + hasText, + isBoolean, + isInteger, + isValidDate, + isIsoDate, + isIsoTimeOffsetsDate, + isNumber, + isObject, + isString, + toBoolean, + isValidUrl, +}; diff --git a/packages/spacecat-shared-utils/test/functions.test.js b/packages/spacecat-shared-utils/test/functions.test.js new file mode 100644 index 00000000..f346cf72 --- /dev/null +++ b/packages/spacecat-shared-utils/test/functions.test.js @@ -0,0 +1,263 @@ +/* + * Copyright 2023 Adobe. All rights reserved. + * This file is licensed to you under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under + * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS + * OF ANY KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ + +/* eslint-env mocha */ +/* eslint-disable no-unused-expressions */ + +import { expect } from 'chai'; + +import { + hasText, + isBoolean, + isInteger, + isValidDate, + isIsoDate, + isIsoTimeOffsetsDate, + isNumber, + isObject, + isString, + toBoolean, + arrayEquals, + isValidUrl, +} from '../src/functions.js'; + +describe('Shared functions', () => { + describe('Commons', () => { + it('is iso date', () => { + const invalidDates = [ + '', + '2011-10-05', + '2011-10-05T14:48:00.000', + 'Wed Oct 05 2011 16:48:00 GMT+0200 (CEST)', + '2011-13-01T14:48:00.000Z', + '2011-00-01T14:48:00.000Z', + ]; + + invalidDates.forEach((date) => expect(isIsoDate(date)).to.be.false); + + expect(isIsoDate('2011-10-05T14:48:00.000Z')).to.be.true; + }); + + it('is iso date with time offset', () => { + const invalidOffsetDates = [ + '', + '2019-11-15', + '2019-11-05T14:43:00.000', + 'Wed Oct 11 2019 14:43:00 GMT+0200 (CEST)', + ]; + + invalidOffsetDates.forEach((date) => expect(isIsoTimeOffsetsDate(date)).to.be.false); + + expect(isIsoTimeOffsetsDate('2019-11-11T14:43:00.000Z')).to.be.true; + expect(isIsoTimeOffsetsDate('2019-11-11T14:43:00.000-00:00')).to.be.true; + expect(isIsoTimeOffsetsDate('2019-11-11T14:43:00.000+05:11')).to.be.true; + }); + + it('has text', () => { + const invalidTexts = [ + null, + undefined, + 123, + [], + ['dasd'], + {}, + { asd: 'dsa' }, + '', + ]; + + invalidTexts.forEach((value) => expect(hasText(value)).to.be.false); + + expect(hasText('a')).to.be.true; + expect(hasText('1')).to.be.true; + expect(hasText('a12dsamklda')).to.be.true; + }); + + it('is boolean', () => { + const invalidBooleans = [ + null, + undefined, + [], + ['dasd'], + {}, + { asd: 'dsa' }, + '', + 'dasd', + NaN, + Infinity, + -Infinity, + 123, + ]; + + invalidBooleans.forEach((value) => expect(isBoolean(value)).to.be.false); + + expect(isBoolean('true')).to.be.true; + expect(isBoolean('True')).to.be.true; + expect(isBoolean('false')).to.be.true; + expect(isBoolean('False')).to.be.true; + expect(isBoolean(true)).to.be.true; + expect(isBoolean(false)).to.be.true; + }); + + it('is number', () => { + const invalidNumbers = [ + null, + undefined, + [], + ['dasd'], + {}, + { asd: 'dsa' }, + '', + 'dasd', + NaN, + Infinity, + -Infinity, + ]; + + invalidNumbers.forEach((value) => expect(isNumber(value)).to.be.false); + + expect(isNumber(0)).to.be.true; + expect(isNumber(123)).to.be.true; + expect(isNumber(-123)).to.be.true; + expect(isNumber(12.3)).to.be.true; + }); + + it('is integer', () => { + const invalidIntegers = [ + null, + undefined, + [], + ['dasd'], + {}, + { asd: 'dsa' }, + '', + 'dasd', + NaN, + Infinity, + -Infinity, + 12.3, + ]; + + invalidIntegers.forEach((value) => expect(isInteger(value)).to.be.false); + + expect(isInteger(0)).to.be.true; + expect(isInteger(123)).to.be.true; + expect(isInteger(-123)).to.be.true; + }); + + it('is object', () => { + const invalidObjects = [ + null, + undefined, + 123, + 'dasd', + [], + ['dasd'], + ]; + + invalidObjects.forEach((value) => expect(isObject(value)).to.be.false); + + expect(isObject({})).to.be.true; + expect(isObject({ asd: 'dsa' })).to.be.true; + }); + + it('is string', () => { + const invalidStrings = [ + null, + undefined, + 123, + [], + ['dasd'], + {}, + { asd: 'dsa' }, + ]; + + invalidStrings.forEach((value) => expect(isString(value)).to.be.false); + + expect(isString('')).to.be.true; + expect(isString('dasd')).to.be.true; + }); + + it('toBoolean', () => { + const invalidBooleans = [ + undefined, + null, + [], + 'foo', + {}, + NaN, + Infinity, + -Infinity, + 123, + ]; + + invalidBooleans.forEach((value) => expect(() => toBoolean(value)).to.throw(Error, 'Not a boolean value')); + + expect(toBoolean('true')).to.be.true; + expect(toBoolean('True')).to.be.true; + expect(toBoolean('false')).to.be.false; + expect(toBoolean('False')).to.be.false; + expect(toBoolean(true)).to.be.true; + expect(toBoolean(false)).to.be.false; + }); + + it('array equals', () => { + expect(arrayEquals([], 1)).to.be.false; + expect(arrayEquals(1, [])).to.be.false; + expect(arrayEquals([1], [2, 3])).to.be.false; + expect(arrayEquals([1, 4], [2, 3])).to.be.false; + expect(arrayEquals([1, 2], [1, 2])).to.be.true; + }); + }); + + describe('isValidUrl', () => { + it('returns false for invalid Url', async () => { + const invalidUrls = [ + null, + undefined, + 1234, + true, + 'example.com', + 'www.example.com', + '255.255.255.256', + 'ftp://abc.com', + ]; + + invalidUrls.forEach((url) => expect(isValidUrl(url)).to.be.false); + }); + + it('returns true for valid url', async () => { + expect(isValidUrl('http://abc.xyz')).to.be.true; + expect(isValidUrl('https://abc.xyz')).to.be.true; + }); + }); + + describe('isValidDate', () => { + it('returns false for invalid date', async () => { + const invalidDates = [ + null, + undefined, + 1234, + true, + '2019-11-11T14:43:89.000-00:00', + 'invalid date', + ]; + + invalidDates.forEach((date) => expect(isValidDate(date)).to.be.false); + }); + + it('returns true for valid date', async () => { + expect(isValidDate(new Date())).to.be.true; + expect(isValidDate(new Date('2022-01-01T01:23:45.678-00:00'))).to.be.true; + expect(isValidDate(new Date('2022-01-01T01:23:45.678Z'))).to.be.true; + }); + }); +});