From 9bbe48c387d6cb106e8e49efa8ca714cdc557975 Mon Sep 17 00:00:00 2001 From: Aish1990 Date: Mon, 22 Apr 2024 16:11:11 +0530 Subject: [PATCH 01/89] Pnpm version upgrade --- common/scripts/install-run-rush-pnpm.js | 31 ++ common/scripts/install-run-rush.js | 214 +++++++-- common/scripts/install-run-rushx.js | 23 +- common/scripts/install-run.js | 582 +++++++++++++++++------- rush.json | 4 +- 5 files changed, 641 insertions(+), 213 deletions(-) create mode 100644 common/scripts/install-run-rush-pnpm.js diff --git a/common/scripts/install-run-rush-pnpm.js b/common/scripts/install-run-rush-pnpm.js new file mode 100644 index 000000000..2356649f4 --- /dev/null +++ b/common/scripts/install-run-rush-pnpm.js @@ -0,0 +1,31 @@ +// THIS FILE WAS GENERATED BY A TOOL. ANY MANUAL MODIFICATIONS WILL GET OVERWRITTEN WHENEVER RUSH IS UPGRADED. +// +// This script is intended for usage in an automated build environment where the Rush command may not have +// been preinstalled, or may have an unpredictable version. This script will automatically install the version of Rush +// specified in the rush.json configuration file (if not already installed), and then pass a command-line to the +// rush-pnpm command. +// +// An example usage would be: +// +// node common/scripts/install-run-rush-pnpm.js pnpm-command +// +// For more information, see: https://rushjs.io/pages/maintainer/setup_new_repo/ +// +// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. +// See the @microsoft/rush package's LICENSE file for details. + +/******/ (() => { // webpackBootstrap +/******/ "use strict"; +var __webpack_exports__ = {}; +/*!*****************************************************!*\ + !*** ./lib-esnext/scripts/install-run-rush-pnpm.js ***! + \*****************************************************/ + +// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. +// See LICENSE in the project root for license information. +require('./install-run-rush'); +//# sourceMappingURL=install-run-rush-pnpm.js.map +module.exports = __webpack_exports__; +/******/ })() +; +//# sourceMappingURL=install-run-rush-pnpm.js.map \ No newline at end of file diff --git a/common/scripts/install-run-rush.js b/common/scripts/install-run-rush.js index 2903c6f00..9676fc718 100644 --- a/common/scripts/install-run-rush.js +++ b/common/scripts/install-run-rush.js @@ -1,26 +1,3 @@ -"use strict"; -// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. -// See the @microsoft/rush package's LICENSE file for license information. -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { - Object.defineProperty(o, "default", { enumerable: true, value: v }); -}) : function(o, v) { - o["default"] = v; -}); -var __importStar = (this && this.__importStar) || function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); - __setModuleDefault(result, mod); - return result; -}; -Object.defineProperty(exports, "__esModule", { value: true }); // THIS FILE WAS GENERATED BY A TOOL. ANY MANUAL MODIFICATIONS WILL GET OVERWRITTEN WHENEVER RUSH IS UPGRADED. // // This script is intended for usage in an automated build environment where the Rush command may not have @@ -31,44 +8,189 @@ Object.defineProperty(exports, "__esModule", { value: true }); // node common/scripts/install-run-rush.js install // // For more information, see: https://rushjs.io/pages/maintainer/setup_new_repo/ -const path = __importStar(require("path")); -const fs = __importStar(require("fs")); -const install_run_1 = require("./install-run"); +// +// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. +// See the @microsoft/rush package's LICENSE file for details. + +/******/ (() => { // webpackBootstrap +/******/ "use strict"; +/******/ var __webpack_modules__ = ({ + +/***/ 657147: +/*!*********************!*\ + !*** external "fs" ***! + \*********************/ +/***/ ((module) => { + +module.exports = require("fs"); + +/***/ }), + +/***/ 371017: +/*!***********************!*\ + !*** external "path" ***! + \***********************/ +/***/ ((module) => { + +module.exports = require("path"); + +/***/ }) + +/******/ }); +/************************************************************************/ +/******/ // The module cache +/******/ var __webpack_module_cache__ = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ // Check if module is in cache +/******/ var cachedModule = __webpack_module_cache__[moduleId]; +/******/ if (cachedModule !== undefined) { +/******/ return cachedModule.exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = __webpack_module_cache__[moduleId] = { +/******/ // no module.id needed +/******/ // no module.loaded needed +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__); +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/************************************************************************/ +/******/ /* webpack/runtime/compat get default export */ +/******/ (() => { +/******/ // getDefaultExport function for compatibility with non-harmony modules +/******/ __webpack_require__.n = (module) => { +/******/ var getter = module && module.__esModule ? +/******/ () => (module['default']) : +/******/ () => (module); +/******/ __webpack_require__.d(getter, { a: getter }); +/******/ return getter; +/******/ }; +/******/ })(); +/******/ +/******/ /* webpack/runtime/define property getters */ +/******/ (() => { +/******/ // define getter functions for harmony exports +/******/ __webpack_require__.d = (exports, definition) => { +/******/ for(var key in definition) { +/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) { +/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] }); +/******/ } +/******/ } +/******/ }; +/******/ })(); +/******/ +/******/ /* webpack/runtime/hasOwnProperty shorthand */ +/******/ (() => { +/******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop)) +/******/ })(); +/******/ +/******/ /* webpack/runtime/make namespace object */ +/******/ (() => { +/******/ // define __esModule on exports +/******/ __webpack_require__.r = (exports) => { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ })(); +/******/ +/************************************************************************/ +var __webpack_exports__ = {}; +// This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk. +(() => { +/*!************************************************!*\ + !*** ./lib-esnext/scripts/install-run-rush.js ***! + \************************************************/ +__webpack_require__.r(__webpack_exports__); +/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! path */ 371017); +/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_0__); +/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! fs */ 657147); +/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(fs__WEBPACK_IMPORTED_MODULE_1__); +// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. +// See LICENSE in the project root for license information. +/* eslint-disable no-console */ + + +const { installAndRun, findRushJsonFolder, RUSH_JSON_FILENAME, runWithErrorAndStatusCode } = require('./install-run'); const PACKAGE_NAME = '@microsoft/rush'; const RUSH_PREVIEW_VERSION = 'RUSH_PREVIEW_VERSION'; -function _getRushVersion() { +const INSTALL_RUN_RUSH_LOCKFILE_PATH_VARIABLE = 'INSTALL_RUN_RUSH_LOCKFILE_PATH'; +function _getRushVersion(logger) { const rushPreviewVersion = process.env[RUSH_PREVIEW_VERSION]; if (rushPreviewVersion !== undefined) { - console.log(`Using Rush version from environment variable ${RUSH_PREVIEW_VERSION}=${rushPreviewVersion}`); + logger.info(`Using Rush version from environment variable ${RUSH_PREVIEW_VERSION}=${rushPreviewVersion}`); return rushPreviewVersion; } - const rushJsonFolder = install_run_1.findRushJsonFolder(); - const rushJsonPath = path.join(rushJsonFolder, install_run_1.RUSH_JSON_FILENAME); + const rushJsonFolder = findRushJsonFolder(); + const rushJsonPath = path__WEBPACK_IMPORTED_MODULE_0__.join(rushJsonFolder, RUSH_JSON_FILENAME); try { - const rushJsonContents = fs.readFileSync(rushJsonPath, 'utf-8'); + const rushJsonContents = fs__WEBPACK_IMPORTED_MODULE_1__.readFileSync(rushJsonPath, 'utf-8'); // Use a regular expression to parse out the rushVersion value because rush.json supports comments, // but JSON.parse does not and we don't want to pull in more dependencies than we need to in this script. const rushJsonMatches = rushJsonContents.match(/\"rushVersion\"\s*\:\s*\"([0-9a-zA-Z.+\-]+)\"/); return rushJsonMatches[1]; } catch (e) { - throw new Error(`Unable to determine the required version of Rush from rush.json (${rushJsonFolder}). ` + - "The 'rushVersion' field is either not assigned in rush.json or was specified " + + throw new Error(`Unable to determine the required version of Rush from ${RUSH_JSON_FILENAME} (${rushJsonFolder}). ` + + `The 'rushVersion' field is either not assigned in ${RUSH_JSON_FILENAME} or was specified ` + 'using an unexpected syntax.'); } } +function _getBin(scriptName) { + switch (scriptName.toLowerCase()) { + case 'install-run-rush-pnpm.js': + return 'rush-pnpm'; + case 'install-run-rushx.js': + return 'rushx'; + default: + return 'rush'; + } +} function _run() { const [nodePath /* Ex: /bin/node */, scriptPath /* /repo/common/scripts/install-run-rush.js */, ...packageBinArgs /* [build, --to, myproject] */] = process.argv; // Detect if this script was directly invoked, or if the install-run-rushx script was invokved to select the // appropriate binary inside the rush package to run - const scriptName = path.basename(scriptPath); - const bin = scriptName.toLowerCase() === 'install-run-rushx.js' ? 'rushx' : 'rush'; + const scriptName = path__WEBPACK_IMPORTED_MODULE_0__.basename(scriptPath); + const bin = _getBin(scriptName); if (!nodePath || !scriptPath) { throw new Error('Unexpected exception: could not detect node path or script path'); } - if (process.argv.length < 3) { + let commandFound = false; + let logger = { info: console.log, error: console.error }; + for (const arg of packageBinArgs) { + if (arg === '-q' || arg === '--quiet') { + // The -q/--quiet flag is supported by both `rush` and `rushx`, and will suppress + // any normal informational/diagnostic information printed during startup. + // + // To maintain the same user experience, the install-run* scripts pass along this + // flag but also use it to suppress any diagnostic information normally printed + // to stdout. + logger = { + info: () => { }, + error: console.error + }; + } + else if (!arg.startsWith('-') || arg === '-h' || arg === '--help') { + // We either found something that looks like a command (i.e. - doesn't start with a "-"), + // or we found the -h/--help flag, which can be run without a command + commandFound = true; + } + } + if (!commandFound) { console.log(`Usage: ${scriptName} [args...]`); - if (scriptName === 'install-run-rush.js') { + if (scriptName === 'install-run-rush-pnpm.js') { + console.log(`Example: ${scriptName} pnpm-command`); + } + else if (scriptName === 'install-run-rush.js') { console.log(`Example: ${scriptName} build --to myproject`); } else { @@ -76,11 +198,21 @@ function _run() { } process.exit(1); } - install_run_1.runWithErrorAndStatusCode(() => { - const version = _getRushVersion(); - console.log(`The rush.json configuration requests Rush version ${version}`); - return install_run_1.installAndRun(PACKAGE_NAME, version, bin, packageBinArgs); + runWithErrorAndStatusCode(logger, () => { + const version = _getRushVersion(logger); + logger.info(`The ${RUSH_JSON_FILENAME} configuration requests Rush version ${version}`); + const lockFilePath = process.env[INSTALL_RUN_RUSH_LOCKFILE_PATH_VARIABLE]; + if (lockFilePath) { + logger.info(`Found ${INSTALL_RUN_RUSH_LOCKFILE_PATH_VARIABLE}="${lockFilePath}", installing with lockfile.`); + } + return installAndRun(logger, PACKAGE_NAME, version, bin, packageBinArgs, lockFilePath); }); } _run(); +//# sourceMappingURL=install-run-rush.js.map +})(); + +module.exports = __webpack_exports__; +/******/ })() +; //# sourceMappingURL=install-run-rush.js.map \ No newline at end of file diff --git a/common/scripts/install-run-rushx.js b/common/scripts/install-run-rushx.js index bf26eb5e5..6581521f3 100755 --- a/common/scripts/install-run-rushx.js +++ b/common/scripts/install-run-rushx.js @@ -1,7 +1,3 @@ -"use strict"; -// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. -// See the @microsoft/rush package's LICENSE file for license information. -Object.defineProperty(exports, "__esModule", { value: true }); // THIS FILE WAS GENERATED BY A TOOL. ANY MANUAL MODIFICATIONS WILL GET OVERWRITTEN WHENEVER RUSH IS UPGRADED. // // This script is intended for usage in an automated build environment where the Rush command may not have @@ -14,5 +10,22 @@ Object.defineProperty(exports, "__esModule", { value: true }); // node common/scripts/install-run-rushx.js custom-command // // For more information, see: https://rushjs.io/pages/maintainer/setup_new_repo/ -require("./install-run-rush"); +// +// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. +// See the @microsoft/rush package's LICENSE file for details. + +/******/ (() => { // webpackBootstrap +/******/ "use strict"; +var __webpack_exports__ = {}; +/*!*************************************************!*\ + !*** ./lib-esnext/scripts/install-run-rushx.js ***! + \*************************************************/ + +// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. +// See LICENSE in the project root for license information. +require('./install-run-rush'); +//# sourceMappingURL=install-run-rushx.js.map +module.exports = __webpack_exports__; +/******/ })() +; //# sourceMappingURL=install-run-rushx.js.map \ No newline at end of file diff --git a/common/scripts/install-run.js b/common/scripts/install-run.js index fa5522e84..9f54b3eed 100644 --- a/common/scripts/install-run.js +++ b/common/scripts/install-run.js @@ -1,27 +1,3 @@ -"use strict"; -// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. -// See the @microsoft/rush package's LICENSE file for license information. -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { - Object.defineProperty(o, "default", { enumerable: true, value: v }); -}) : function(o, v) { - o["default"] = v; -}); -var __importStar = (this && this.__importStar) || function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); - __setModuleDefault(result, mod); - return result; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.runWithErrorAndStatusCode = exports.installAndRun = exports.findRushJsonFolder = exports.getNpmPath = exports.RUSH_JSON_FILENAME = void 0; // THIS FILE WAS GENERATED BY A TOOL. ANY MANUAL MODIFICATIONS WILL GET OVERWRITTEN WHENEVER RUSH IS UPGRADED. // // This script is intended for usage in an automated build environment where a Node tool may not have @@ -32,57 +8,59 @@ exports.runWithErrorAndStatusCode = exports.installAndRun = exports.findRushJson // node common/scripts/install-run.js qrcode@1.2.2 qrcode https://rushjs.io // // For more information, see: https://rushjs.io/pages/maintainer/setup_new_repo/ -const childProcess = __importStar(require("child_process")); -const fs = __importStar(require("fs")); -const os = __importStar(require("os")); -const path = __importStar(require("path")); -exports.RUSH_JSON_FILENAME = 'rush.json'; -const RUSH_TEMP_FOLDER_ENV_VARIABLE_NAME = 'RUSH_TEMP_FOLDER'; -const INSTALLED_FLAG_FILENAME = 'installed.flag'; -const NODE_MODULES_FOLDER_NAME = 'node_modules'; -const PACKAGE_JSON_FILENAME = 'package.json'; +// +// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. +// See the @microsoft/rush package's LICENSE file for details. + +/******/ (() => { // webpackBootstrap +/******/ "use strict"; +/******/ var __webpack_modules__ = ({ + +/***/ 679877: +/*!************************************************!*\ + !*** ./lib-esnext/utilities/npmrcUtilities.js ***! + \************************************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ "isVariableSetInNpmrcFile": () => (/* binding */ isVariableSetInNpmrcFile), +/* harmony export */ "syncNpmrc": () => (/* binding */ syncNpmrc) +/* harmony export */ }); +/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! fs */ 657147); +/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(fs__WEBPACK_IMPORTED_MODULE_0__); +/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! path */ 371017); +/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_1__); +// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. +// See LICENSE in the project root for license information. +// IMPORTANT - do not use any non-built-in libraries in this file + + /** - * Parse a package specifier (in the form of name\@version) into name and version parts. + * This function reads the content for given .npmrc file path, and also trims + * unusable lines from the .npmrc file. + * + * @returns + * The text of the the .npmrc. */ -function _parsePackageSpecifier(rawPackageSpecifier) { - rawPackageSpecifier = (rawPackageSpecifier || '').trim(); - const separatorIndex = rawPackageSpecifier.lastIndexOf('@'); - let name; - let version = undefined; - if (separatorIndex === 0) { - // The specifier starts with a scope and doesn't have a version specified - name = rawPackageSpecifier; +// create a global _combinedNpmrc for cache purpose +const _combinedNpmrcMap = new Map(); +function _trimNpmrcFile(options) { + const { sourceNpmrcPath, linesToPrepend, linesToAppend } = options; + const combinedNpmrcFromCache = _combinedNpmrcMap.get(sourceNpmrcPath); + if (combinedNpmrcFromCache !== undefined) { + return combinedNpmrcFromCache; } - else if (separatorIndex === -1) { - // The specifier doesn't have a version - name = rawPackageSpecifier; + let npmrcFileLines = []; + if (linesToPrepend) { + npmrcFileLines.push(...linesToPrepend); } - else { - name = rawPackageSpecifier.substring(0, separatorIndex); - version = rawPackageSpecifier.substring(separatorIndex + 1); + if (fs__WEBPACK_IMPORTED_MODULE_0__.existsSync(sourceNpmrcPath)) { + npmrcFileLines.push(...fs__WEBPACK_IMPORTED_MODULE_0__.readFileSync(sourceNpmrcPath).toString().split('\n')); } - if (!name) { - throw new Error(`Invalid package specifier: ${rawPackageSpecifier}`); + if (linesToAppend) { + npmrcFileLines.push(...linesToAppend); } - return { name, version }; -} -/** - * As a workaround, copyAndTrimNpmrcFile() copies the .npmrc file to the target folder, and also trims - * unusable lines from the .npmrc file. - * - * Why are we trimming the .npmrc lines? NPM allows environment variables to be specified in - * the .npmrc file to provide different authentication tokens for different registry. - * However, if the environment variable is undefined, it expands to an empty string, which - * produces a valid-looking mapping with an invalid URL that causes an error. Instead, - * we'd prefer to skip that line and continue looking in other places such as the user's - * home directory. - * - * IMPORTANT: THIS CODE SHOULD BE KEPT UP TO DATE WITH Utilities.copyAndTrimNpmrcFile() - */ -function _copyAndTrimNpmrcFile(sourceNpmrcPath, targetNpmrcPath) { - console.log(`Transforming ${sourceNpmrcPath}`); // Verbose - console.log(` --> "${targetNpmrcPath}"`); - let npmrcFileLines = fs.readFileSync(sourceNpmrcPath).toString().split('\n'); npmrcFileLines = npmrcFileLines.map((line) => (line || '').trim()); const resultLines = []; // This finds environment variable tokens that look like "${VAR_NAME}" @@ -90,8 +68,13 @@ function _copyAndTrimNpmrcFile(sourceNpmrcPath, targetNpmrcPath) { // Comment lines start with "#" or ";" const commentRegExp = /^\s*[#;]/; // Trim out lines that reference environment variables that aren't defined - for (const line of npmrcFileLines) { + for (let line of npmrcFileLines) { let lineShouldBeTrimmed = false; + //remove spaces before or after key and value + line = line + .split('=') + .map((lineToTrim) => lineToTrim.trim()) + .join('='); // Ignore comment lines if (!commentRegExp.test(line)) { const environmentVariables = line.match(expansionRegExp); @@ -117,31 +100,240 @@ function _copyAndTrimNpmrcFile(sourceNpmrcPath, targetNpmrcPath) { resultLines.push(line); } } - fs.writeFileSync(targetNpmrcPath, resultLines.join(os.EOL)); + const combinedNpmrc = resultLines.join('\n'); + //save the cache + _combinedNpmrcMap.set(sourceNpmrcPath, combinedNpmrc); + return combinedNpmrc; } -/** - * syncNpmrc() copies the .npmrc file to the target folder, and also trims unusable lines from the .npmrc file. - * If the source .npmrc file not exist, then syncNpmrc() will delete an .npmrc that is found in the target folder. - * - * IMPORTANT: THIS CODE SHOULD BE KEPT UP TO DATE WITH Utilities._syncNpmrc() - */ -function _syncNpmrc(sourceNpmrcFolder, targetNpmrcFolder, useNpmrcPublish) { - const sourceNpmrcPath = path.join(sourceNpmrcFolder, !useNpmrcPublish ? '.npmrc' : '.npmrc-publish'); - const targetNpmrcPath = path.join(targetNpmrcFolder, '.npmrc'); +function _copyAndTrimNpmrcFile(options) { + const { logger, sourceNpmrcPath, targetNpmrcPath, linesToPrepend, linesToAppend } = options; + logger.info(`Transforming ${sourceNpmrcPath}`); // Verbose + logger.info(` --> "${targetNpmrcPath}"`); + const combinedNpmrc = _trimNpmrcFile({ + sourceNpmrcPath, + linesToPrepend, + linesToAppend + }); + fs__WEBPACK_IMPORTED_MODULE_0__.writeFileSync(targetNpmrcPath, combinedNpmrc); + return combinedNpmrc; +} +function syncNpmrc(options) { + const { sourceNpmrcFolder, targetNpmrcFolder, useNpmrcPublish, logger = { + // eslint-disable-next-line no-console + info: console.log, + // eslint-disable-next-line no-console + error: console.error + }, createIfMissing = false, linesToAppend, linesToPrepend } = options; + const sourceNpmrcPath = path__WEBPACK_IMPORTED_MODULE_1__.join(sourceNpmrcFolder, !useNpmrcPublish ? '.npmrc' : '.npmrc-publish'); + const targetNpmrcPath = path__WEBPACK_IMPORTED_MODULE_1__.join(targetNpmrcFolder, '.npmrc'); try { - if (fs.existsSync(sourceNpmrcPath)) { - _copyAndTrimNpmrcFile(sourceNpmrcPath, targetNpmrcPath); + if (fs__WEBPACK_IMPORTED_MODULE_0__.existsSync(sourceNpmrcPath) || createIfMissing) { + // Ensure the target folder exists + if (!fs__WEBPACK_IMPORTED_MODULE_0__.existsSync(targetNpmrcFolder)) { + fs__WEBPACK_IMPORTED_MODULE_0__.mkdirSync(targetNpmrcFolder, { recursive: true }); + } + return _copyAndTrimNpmrcFile({ + sourceNpmrcPath, + targetNpmrcPath, + logger, + linesToAppend, + linesToPrepend + }); } - else if (fs.existsSync(targetNpmrcPath)) { + else if (fs__WEBPACK_IMPORTED_MODULE_0__.existsSync(targetNpmrcPath)) { // If the source .npmrc doesn't exist and there is one in the target, delete the one in the target - console.log(`Deleting ${targetNpmrcPath}`); // Verbose - fs.unlinkSync(targetNpmrcPath); + logger.info(`Deleting ${targetNpmrcPath}`); // Verbose + fs__WEBPACK_IMPORTED_MODULE_0__.unlinkSync(targetNpmrcPath); } } catch (e) { throw new Error(`Error syncing .npmrc file: ${e}`); } } +function isVariableSetInNpmrcFile(sourceNpmrcFolder, variableKey) { + const sourceNpmrcPath = `${sourceNpmrcFolder}/.npmrc`; + //if .npmrc file does not exist, return false directly + if (!fs__WEBPACK_IMPORTED_MODULE_0__.existsSync(sourceNpmrcPath)) { + return false; + } + const trimmedNpmrcFile = _trimNpmrcFile({ sourceNpmrcPath }); + const variableKeyRegExp = new RegExp(`^${variableKey}=`, 'm'); + return trimmedNpmrcFile.match(variableKeyRegExp) !== null; +} +//# sourceMappingURL=npmrcUtilities.js.map + +/***/ }), + +/***/ 532081: +/*!********************************!*\ + !*** external "child_process" ***! + \********************************/ +/***/ ((module) => { + +module.exports = require("child_process"); + +/***/ }), + +/***/ 657147: +/*!*********************!*\ + !*** external "fs" ***! + \*********************/ +/***/ ((module) => { + +module.exports = require("fs"); + +/***/ }), + +/***/ 822037: +/*!*********************!*\ + !*** external "os" ***! + \*********************/ +/***/ ((module) => { + +module.exports = require("os"); + +/***/ }), + +/***/ 371017: +/*!***********************!*\ + !*** external "path" ***! + \***********************/ +/***/ ((module) => { + +module.exports = require("path"); + +/***/ }) + +/******/ }); +/************************************************************************/ +/******/ // The module cache +/******/ var __webpack_module_cache__ = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ // Check if module is in cache +/******/ var cachedModule = __webpack_module_cache__[moduleId]; +/******/ if (cachedModule !== undefined) { +/******/ return cachedModule.exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = __webpack_module_cache__[moduleId] = { +/******/ // no module.id needed +/******/ // no module.loaded needed +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__); +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/************************************************************************/ +/******/ /* webpack/runtime/compat get default export */ +/******/ (() => { +/******/ // getDefaultExport function for compatibility with non-harmony modules +/******/ __webpack_require__.n = (module) => { +/******/ var getter = module && module.__esModule ? +/******/ () => (module['default']) : +/******/ () => (module); +/******/ __webpack_require__.d(getter, { a: getter }); +/******/ return getter; +/******/ }; +/******/ })(); +/******/ +/******/ /* webpack/runtime/define property getters */ +/******/ (() => { +/******/ // define getter functions for harmony exports +/******/ __webpack_require__.d = (exports, definition) => { +/******/ for(var key in definition) { +/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) { +/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] }); +/******/ } +/******/ } +/******/ }; +/******/ })(); +/******/ +/******/ /* webpack/runtime/hasOwnProperty shorthand */ +/******/ (() => { +/******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop)) +/******/ })(); +/******/ +/******/ /* webpack/runtime/make namespace object */ +/******/ (() => { +/******/ // define __esModule on exports +/******/ __webpack_require__.r = (exports) => { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ })(); +/******/ +/************************************************************************/ +var __webpack_exports__ = {}; +// This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk. +(() => { +/*!*******************************************!*\ + !*** ./lib-esnext/scripts/install-run.js ***! + \*******************************************/ +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ "RUSH_JSON_FILENAME": () => (/* binding */ RUSH_JSON_FILENAME), +/* harmony export */ "findRushJsonFolder": () => (/* binding */ findRushJsonFolder), +/* harmony export */ "getNpmPath": () => (/* binding */ getNpmPath), +/* harmony export */ "installAndRun": () => (/* binding */ installAndRun), +/* harmony export */ "runWithErrorAndStatusCode": () => (/* binding */ runWithErrorAndStatusCode) +/* harmony export */ }); +/* harmony import */ var child_process__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! child_process */ 532081); +/* harmony import */ var child_process__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(child_process__WEBPACK_IMPORTED_MODULE_0__); +/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! fs */ 657147); +/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(fs__WEBPACK_IMPORTED_MODULE_1__); +/* harmony import */ var os__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! os */ 822037); +/* harmony import */ var os__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(os__WEBPACK_IMPORTED_MODULE_2__); +/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! path */ 371017); +/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(path__WEBPACK_IMPORTED_MODULE_3__); +/* harmony import */ var _utilities_npmrcUtilities__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../utilities/npmrcUtilities */ 679877); +// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. +// See LICENSE in the project root for license information. +/* eslint-disable no-console */ + + + + + +const RUSH_JSON_FILENAME = 'rush.json'; +const RUSH_TEMP_FOLDER_ENV_VARIABLE_NAME = 'RUSH_TEMP_FOLDER'; +const INSTALL_RUN_LOCKFILE_PATH_VARIABLE = 'INSTALL_RUN_LOCKFILE_PATH'; +const INSTALLED_FLAG_FILENAME = 'installed.flag'; +const NODE_MODULES_FOLDER_NAME = 'node_modules'; +const PACKAGE_JSON_FILENAME = 'package.json'; +/** + * Parse a package specifier (in the form of name\@version) into name and version parts. + */ +function _parsePackageSpecifier(rawPackageSpecifier) { + rawPackageSpecifier = (rawPackageSpecifier || '').trim(); + const separatorIndex = rawPackageSpecifier.lastIndexOf('@'); + let name; + let version = undefined; + if (separatorIndex === 0) { + // The specifier starts with a scope and doesn't have a version specified + name = rawPackageSpecifier; + } + else if (separatorIndex === -1) { + // The specifier doesn't have a version + name = rawPackageSpecifier; + } + else { + name = rawPackageSpecifier.substring(0, separatorIndex); + version = rawPackageSpecifier.substring(separatorIndex + 1); + } + if (!name) { + throw new Error(`Invalid package specifier: ${rawPackageSpecifier}`); + } + return { name, version }; +} let _npmPath = undefined; /** * Get the absolute path to the npm executable @@ -149,35 +341,34 @@ let _npmPath = undefined; function getNpmPath() { if (!_npmPath) { try { - if (os.platform() === 'win32') { + if (os__WEBPACK_IMPORTED_MODULE_2__.platform() === 'win32') { // We're on Windows - const whereOutput = childProcess.execSync('where npm', { stdio: [] }).toString(); - const lines = whereOutput.split(os.EOL).filter((line) => !!line); + const whereOutput = child_process__WEBPACK_IMPORTED_MODULE_0__.execSync('where npm', { stdio: [] }).toString(); + const lines = whereOutput.split(os__WEBPACK_IMPORTED_MODULE_2__.EOL).filter((line) => !!line); // take the last result, we are looking for a .cmd command // see https://github.com/microsoft/rushstack/issues/759 _npmPath = lines[lines.length - 1]; } else { // We aren't on Windows - assume we're on *NIX or Darwin - _npmPath = childProcess.execSync('command -v npm', { stdio: [] }).toString(); + _npmPath = child_process__WEBPACK_IMPORTED_MODULE_0__.execSync('command -v npm', { stdio: [] }).toString(); } } catch (e) { throw new Error(`Unable to determine the path to the NPM tool: ${e}`); } _npmPath = _npmPath.trim(); - if (!fs.existsSync(_npmPath)) { + if (!fs__WEBPACK_IMPORTED_MODULE_1__.existsSync(_npmPath)) { throw new Error('The NPM executable does not exist'); } } return _npmPath; } -exports.getNpmPath = getNpmPath; function _ensureFolder(folderPath) { - if (!fs.existsSync(folderPath)) { - const parentDir = path.dirname(folderPath); + if (!fs__WEBPACK_IMPORTED_MODULE_1__.existsSync(folderPath)) { + const parentDir = path__WEBPACK_IMPORTED_MODULE_3__.dirname(folderPath); _ensureFolder(parentDir); - fs.mkdirSync(folderPath); + fs__WEBPACK_IMPORTED_MODULE_1__.mkdirSync(folderPath); } } /** @@ -191,14 +382,14 @@ function _ensureAndJoinPath(baseFolder, ...pathSegments) { try { for (let pathSegment of pathSegments) { pathSegment = pathSegment.replace(/[\\\/]/g, '+'); - joinedPath = path.join(joinedPath, pathSegment); - if (!fs.existsSync(joinedPath)) { - fs.mkdirSync(joinedPath); + joinedPath = path__WEBPACK_IMPORTED_MODULE_3__.join(joinedPath, pathSegment); + if (!fs__WEBPACK_IMPORTED_MODULE_1__.existsSync(joinedPath)) { + fs__WEBPACK_IMPORTED_MODULE_1__.mkdirSync(joinedPath); } } } catch (e) { - throw new Error(`Error building local installation folder (${path.join(baseFolder, ...pathSegments)}): ${e}`); + throw new Error(`Error building local installation folder (${path__WEBPACK_IMPORTED_MODULE_3__.join(baseFolder, ...pathSegments)}): ${e}`); } return joinedPath; } @@ -212,10 +403,27 @@ function _getRushTempFolder(rushCommonFolder) { return _ensureAndJoinPath(rushCommonFolder, 'temp'); } } +/** + * Compare version strings according to semantic versioning. + * Returns a positive integer if "a" is a later version than "b", + * a negative integer if "b" is later than "a", + * and 0 otherwise. + */ +function _compareVersionStrings(a, b) { + const aParts = a.split(/[.-]/); + const bParts = b.split(/[.-]/); + const numberOfParts = Math.max(aParts.length, bParts.length); + for (let i = 0; i < numberOfParts; i++) { + if (aParts[i] !== bParts[i]) { + return (Number(aParts[i]) || 0) - (Number(bParts[i]) || 0); + } + } + return 0; +} /** * Resolve a package specifier to a static version */ -function _resolvePackageVersion(rushCommonFolder, { name, version }) { +function _resolvePackageVersion(logger, rushCommonFolder, { name, version }) { if (!version) { version = '*'; // If no version is specified, use the latest version } @@ -228,16 +436,31 @@ function _resolvePackageVersion(rushCommonFolder, { name, version }) { // version resolves to try { const rushTempFolder = _getRushTempFolder(rushCommonFolder); - const sourceNpmrcFolder = path.join(rushCommonFolder, 'config', 'rush'); - _syncNpmrc(sourceNpmrcFolder, rushTempFolder); + const sourceNpmrcFolder = path__WEBPACK_IMPORTED_MODULE_3__.join(rushCommonFolder, 'config', 'rush'); + (0,_utilities_npmrcUtilities__WEBPACK_IMPORTED_MODULE_4__.syncNpmrc)({ + sourceNpmrcFolder, + targetNpmrcFolder: rushTempFolder, + logger + }); const npmPath = getNpmPath(); // This returns something that looks like: - // @microsoft/rush@3.0.0 '3.0.0' - // @microsoft/rush@3.0.1 '3.0.1' - // ... - // @microsoft/rush@3.0.20 '3.0.20' - // - const npmVersionSpawnResult = childProcess.spawnSync(npmPath, ['view', `${name}@${version}`, 'version', '--no-update-notifier'], { + // ``` + // [ + // "3.0.0", + // "3.0.1", + // ... + // "3.0.20" + // ] + // ``` + // + // if multiple versions match the selector, or + // + // ``` + // "3.0.0" + // ``` + // + // if only a single version matches. + const npmVersionSpawnResult = child_process__WEBPACK_IMPORTED_MODULE_0__.spawnSync(npmPath, ['view', `${name}@${version}`, 'version', '--no-update-notifier', '--json'], { cwd: rushTempFolder, stdio: [] }); @@ -245,16 +468,21 @@ function _resolvePackageVersion(rushCommonFolder, { name, version }) { throw new Error(`"npm view" returned error code ${npmVersionSpawnResult.status}`); } const npmViewVersionOutput = npmVersionSpawnResult.stdout.toString(); - const versionLines = npmViewVersionOutput.split('\n').filter((line) => !!line); - const latestVersion = versionLines[versionLines.length - 1]; + const parsedVersionOutput = JSON.parse(npmViewVersionOutput); + const versions = Array.isArray(parsedVersionOutput) + ? parsedVersionOutput + : [parsedVersionOutput]; + let latestVersion = versions[0]; + for (let i = 1; i < versions.length; i++) { + const latestVersionCandidate = versions[i]; + if (_compareVersionStrings(latestVersionCandidate, latestVersion) > 0) { + latestVersion = latestVersionCandidate; + } + } if (!latestVersion) { throw new Error('No versions found for the specified version range.'); } - const versionMatches = latestVersion.match(/^.+\s\'(.+)\'$/); - if (!versionMatches) { - throw new Error(`Invalid npm output ${latestVersion}`); - } - return versionMatches[1]; + return latestVersion; } catch (e) { throw new Error(`Unable to resolve version ${version} of package ${name}: ${e}`); @@ -270,58 +498,72 @@ function findRushJsonFolder() { let basePath = __dirname; let tempPath = __dirname; do { - const testRushJsonPath = path.join(basePath, exports.RUSH_JSON_FILENAME); - if (fs.existsSync(testRushJsonPath)) { + const testRushJsonPath = path__WEBPACK_IMPORTED_MODULE_3__.join(basePath, RUSH_JSON_FILENAME); + if (fs__WEBPACK_IMPORTED_MODULE_1__.existsSync(testRushJsonPath)) { _rushJsonFolder = basePath; break; } else { basePath = tempPath; } - } while (basePath !== (tempPath = path.dirname(basePath))); // Exit the loop when we hit the disk root + } while (basePath !== (tempPath = path__WEBPACK_IMPORTED_MODULE_3__.dirname(basePath))); // Exit the loop when we hit the disk root if (!_rushJsonFolder) { - throw new Error('Unable to find rush.json.'); + throw new Error(`Unable to find ${RUSH_JSON_FILENAME}.`); } } return _rushJsonFolder; } -exports.findRushJsonFolder = findRushJsonFolder; /** * Detects if the package in the specified directory is installed */ function _isPackageAlreadyInstalled(packageInstallFolder) { try { - const flagFilePath = path.join(packageInstallFolder, INSTALLED_FLAG_FILENAME); - if (!fs.existsSync(flagFilePath)) { + const flagFilePath = path__WEBPACK_IMPORTED_MODULE_3__.join(packageInstallFolder, INSTALLED_FLAG_FILENAME); + if (!fs__WEBPACK_IMPORTED_MODULE_1__.existsSync(flagFilePath)) { return false; } - const fileContents = fs.readFileSync(flagFilePath).toString(); + const fileContents = fs__WEBPACK_IMPORTED_MODULE_1__.readFileSync(flagFilePath).toString(); return fileContents.trim() === process.version; } catch (e) { return false; } } +/** + * Delete a file. Fail silently if it does not exist. + */ +function _deleteFile(file) { + try { + fs__WEBPACK_IMPORTED_MODULE_1__.unlinkSync(file); + } + catch (err) { + if (err.code !== 'ENOENT' && err.code !== 'ENOTDIR') { + throw err; + } + } +} /** * Removes the following files and directories under the specified folder path: * - installed.flag * - * - node_modules */ -function _cleanInstallFolder(rushTempFolder, packageInstallFolder) { +function _cleanInstallFolder(rushTempFolder, packageInstallFolder, lockFilePath) { try { - const flagFile = path.resolve(packageInstallFolder, INSTALLED_FLAG_FILENAME); - if (fs.existsSync(flagFile)) { - fs.unlinkSync(flagFile); - } - const packageLockFile = path.resolve(packageInstallFolder, 'package-lock.json'); - if (fs.existsSync(packageLockFile)) { - fs.unlinkSync(packageLockFile); + const flagFile = path__WEBPACK_IMPORTED_MODULE_3__.resolve(packageInstallFolder, INSTALLED_FLAG_FILENAME); + _deleteFile(flagFile); + const packageLockFile = path__WEBPACK_IMPORTED_MODULE_3__.resolve(packageInstallFolder, 'package-lock.json'); + if (lockFilePath) { + fs__WEBPACK_IMPORTED_MODULE_1__.copyFileSync(lockFilePath, packageLockFile); } - const nodeModulesFolder = path.resolve(packageInstallFolder, NODE_MODULES_FOLDER_NAME); - if (fs.existsSync(nodeModulesFolder)) { - const rushRecyclerFolder = _ensureAndJoinPath(rushTempFolder, 'rush-recycler'); - fs.renameSync(nodeModulesFolder, path.join(rushRecyclerFolder, `install-run-${Date.now().toString()}`)); + else { + // Not running `npm ci`, so need to cleanup + _deleteFile(packageLockFile); + const nodeModulesFolder = path__WEBPACK_IMPORTED_MODULE_3__.resolve(packageInstallFolder, NODE_MODULES_FOLDER_NAME); + if (fs__WEBPACK_IMPORTED_MODULE_1__.existsSync(nodeModulesFolder)) { + const rushRecyclerFolder = _ensureAndJoinPath(rushTempFolder, 'rush-recycler'); + fs__WEBPACK_IMPORTED_MODULE_1__.renameSync(nodeModulesFolder, path__WEBPACK_IMPORTED_MODULE_3__.join(rushRecyclerFolder, `install-run-${Date.now().toString()}`)); + } } } catch (e) { @@ -340,8 +582,8 @@ function _createPackageJson(packageInstallFolder, name, version) { repository: "DON'T WARN", license: 'MIT' }; - const packageJsonPath = path.join(packageInstallFolder, PACKAGE_JSON_FILENAME); - fs.writeFileSync(packageJsonPath, JSON.stringify(packageJsonContents, undefined, 2)); + const packageJsonPath = path__WEBPACK_IMPORTED_MODULE_3__.join(packageInstallFolder, PACKAGE_JSON_FILENAME); + fs__WEBPACK_IMPORTED_MODULE_1__.writeFileSync(packageJsonPath, JSON.stringify(packageJsonContents, undefined, 2)); } catch (e) { throw new Error(`Unable to create package.json: ${e}`); @@ -350,19 +592,19 @@ function _createPackageJson(packageInstallFolder, name, version) { /** * Run "npm install" in the package install folder. */ -function _installPackage(packageInstallFolder, name, version) { +function _installPackage(logger, packageInstallFolder, name, version, command) { try { - console.log(`Installing ${name}...`); + logger.info(`Installing ${name}...`); const npmPath = getNpmPath(); - const result = childProcess.spawnSync(npmPath, ['install'], { + const result = child_process__WEBPACK_IMPORTED_MODULE_0__.spawnSync(npmPath, [command], { stdio: 'inherit', cwd: packageInstallFolder, env: process.env }); if (result.status !== 0) { - throw new Error('"npm install" encountered an error'); + throw new Error(`"npm ${command}" encountered an error`); } - console.log(`Successfully installed ${name}@${version}`); + logger.info(`Successfully installed ${name}@${version}`); } catch (e) { throw new Error(`Unable to install package: ${e}`); @@ -372,41 +614,46 @@ function _installPackage(packageInstallFolder, name, version) { * Get the ".bin" path for the package. */ function _getBinPath(packageInstallFolder, binName) { - const binFolderPath = path.resolve(packageInstallFolder, NODE_MODULES_FOLDER_NAME, '.bin'); - const resolvedBinName = os.platform() === 'win32' ? `${binName}.cmd` : binName; - return path.resolve(binFolderPath, resolvedBinName); + const binFolderPath = path__WEBPACK_IMPORTED_MODULE_3__.resolve(packageInstallFolder, NODE_MODULES_FOLDER_NAME, '.bin'); + const resolvedBinName = os__WEBPACK_IMPORTED_MODULE_2__.platform() === 'win32' ? `${binName}.cmd` : binName; + return path__WEBPACK_IMPORTED_MODULE_3__.resolve(binFolderPath, resolvedBinName); } /** * Write a flag file to the package's install directory, signifying that the install was successful. */ function _writeFlagFile(packageInstallFolder) { try { - const flagFilePath = path.join(packageInstallFolder, INSTALLED_FLAG_FILENAME); - fs.writeFileSync(flagFilePath, process.version); + const flagFilePath = path__WEBPACK_IMPORTED_MODULE_3__.join(packageInstallFolder, INSTALLED_FLAG_FILENAME); + fs__WEBPACK_IMPORTED_MODULE_1__.writeFileSync(flagFilePath, process.version); } catch (e) { throw new Error(`Unable to create installed.flag file in ${packageInstallFolder}`); } } -function installAndRun(packageName, packageVersion, packageBinName, packageBinArgs) { +function installAndRun(logger, packageName, packageVersion, packageBinName, packageBinArgs, lockFilePath = process.env[INSTALL_RUN_LOCKFILE_PATH_VARIABLE]) { const rushJsonFolder = findRushJsonFolder(); - const rushCommonFolder = path.join(rushJsonFolder, 'common'); + const rushCommonFolder = path__WEBPACK_IMPORTED_MODULE_3__.join(rushJsonFolder, 'common'); const rushTempFolder = _getRushTempFolder(rushCommonFolder); const packageInstallFolder = _ensureAndJoinPath(rushTempFolder, 'install-run', `${packageName}@${packageVersion}`); if (!_isPackageAlreadyInstalled(packageInstallFolder)) { // The package isn't already installed - _cleanInstallFolder(rushTempFolder, packageInstallFolder); - const sourceNpmrcFolder = path.join(rushCommonFolder, 'config', 'rush'); - _syncNpmrc(sourceNpmrcFolder, packageInstallFolder); + _cleanInstallFolder(rushTempFolder, packageInstallFolder, lockFilePath); + const sourceNpmrcFolder = path__WEBPACK_IMPORTED_MODULE_3__.join(rushCommonFolder, 'config', 'rush'); + (0,_utilities_npmrcUtilities__WEBPACK_IMPORTED_MODULE_4__.syncNpmrc)({ + sourceNpmrcFolder, + targetNpmrcFolder: packageInstallFolder, + logger + }); _createPackageJson(packageInstallFolder, packageName, packageVersion); - _installPackage(packageInstallFolder, packageName, packageVersion); + const command = lockFilePath ? 'ci' : 'install'; + _installPackage(logger, packageInstallFolder, packageName, packageVersion, command); _writeFlagFile(packageInstallFolder); } const statusMessage = `Invoking "${packageBinName} ${packageBinArgs.join(' ')}"`; const statusMessageLine = new Array(statusMessage.length + 1).join('-'); - console.log(os.EOL + statusMessage + os.EOL + statusMessageLine + os.EOL); + logger.info('\n' + statusMessage + '\n' + statusMessageLine + '\n'); const binPath = _getBinPath(packageInstallFolder, packageBinName); - const binFolderPath = path.resolve(packageInstallFolder, NODE_MODULES_FOLDER_NAME, '.bin'); + const binFolderPath = path__WEBPACK_IMPORTED_MODULE_3__.resolve(packageInstallFolder, NODE_MODULES_FOLDER_NAME, '.bin'); // Windows environment variables are case-insensitive. Instead of using SpawnSyncOptions.env, we need to // assign via the process.env proxy to ensure that we append to the right PATH key. const originalEnvPath = process.env.PATH || ''; @@ -414,10 +661,10 @@ function installAndRun(packageName, packageVersion, packageBinName, packageBinAr try { // Node.js on Windows can not spawn a file when the path has a space on it // unless the path gets wrapped in a cmd friendly way and shell mode is used - const shouldUseShell = binPath.includes(' ') && os.platform() === 'win32'; + const shouldUseShell = binPath.includes(' ') && os__WEBPACK_IMPORTED_MODULE_2__.platform() === 'win32'; const platformBinPath = shouldUseShell ? `"${binPath}"` : binPath; - process.env.PATH = [binFolderPath, originalEnvPath].join(path.delimiter); - result = childProcess.spawnSync(platformBinPath, packageBinArgs, { + process.env.PATH = [binFolderPath, originalEnvPath].join(path__WEBPACK_IMPORTED_MODULE_3__.delimiter); + result = child_process__WEBPACK_IMPORTED_MODULE_0__.spawnSync(platformBinPath, packageBinArgs, { stdio: 'inherit', windowsVerbatimArguments: false, shell: shouldUseShell, @@ -435,24 +682,22 @@ function installAndRun(packageName, packageVersion, packageBinName, packageBinAr throw result.error || new Error('An unknown error occurred.'); } } -exports.installAndRun = installAndRun; -function runWithErrorAndStatusCode(fn) { +function runWithErrorAndStatusCode(logger, fn) { process.exitCode = 1; try { const exitCode = fn(); process.exitCode = exitCode; } catch (e) { - console.error(os.EOL + os.EOL + e.toString() + os.EOL + os.EOL); + logger.error('\n\n' + e.toString() + '\n\n'); } } -exports.runWithErrorAndStatusCode = runWithErrorAndStatusCode; function _run() { const [nodePath /* Ex: /bin/node */, scriptPath /* /repo/common/scripts/install-run-rush.js */, rawPackageSpecifier /* qrcode@^1.2.0 */, packageBinName /* qrcode */, ...packageBinArgs /* [-f, myproject/lib] */] = process.argv; if (!nodePath) { throw new Error('Unexpected exception: could not detect node path'); } - if (path.basename(scriptPath).toLowerCase() !== 'install-run.js') { + if (path__WEBPACK_IMPORTED_MODULE_3__.basename(scriptPath).toLowerCase() !== 'install-run.js') { // If install-run.js wasn't directly invoked, don't execute the rest of this function. Return control // to the script that (presumably) imported this file return; @@ -462,17 +707,24 @@ function _run() { console.log('Example: install-run.js qrcode@1.2.2 qrcode https://rushjs.io'); process.exit(1); } - runWithErrorAndStatusCode(() => { + const logger = { info: console.log, error: console.error }; + runWithErrorAndStatusCode(logger, () => { const rushJsonFolder = findRushJsonFolder(); const rushCommonFolder = _ensureAndJoinPath(rushJsonFolder, 'common'); const packageSpecifier = _parsePackageSpecifier(rawPackageSpecifier); const name = packageSpecifier.name; - const version = _resolvePackageVersion(rushCommonFolder, packageSpecifier); + const version = _resolvePackageVersion(logger, rushCommonFolder, packageSpecifier); if (packageSpecifier.version !== version) { console.log(`Resolved to ${name}@${version}`); } - return installAndRun(name, version, packageBinName, packageBinArgs); + return installAndRun(logger, name, version, packageBinName, packageBinArgs); }); } _run(); +//# sourceMappingURL=install-run.js.map +})(); + +module.exports = __webpack_exports__; +/******/ })() +; //# sourceMappingURL=install-run.js.map \ No newline at end of file diff --git a/rush.json b/rush.json index ed79755cb..5b62e1394 100755 --- a/rush.json +++ b/rush.json @@ -15,7 +15,7 @@ * path segment in the "$schema" field for all your Rush config files. This will ensure * correct error-underlining and tab-completion for editors such as VS Code. */ - "rushVersion": "5.47.0", + "rushVersion": "5.120.0", /** * The next field selects which package manager should be installed and determines its version. * Rush installs its own local copy of the package manager to ensure that your build process @@ -24,7 +24,7 @@ * Specify one of: "pnpmVersion", "npmVersion", or "yarnVersion". See the Rush documentation * for details about these alternatives. */ - "pnpmVersion": "6.3.0", + "pnpmVersion": "7.30.5", // "npmVersion": "4.5.0", // "yarnVersion": "1.9.4", /** From 0a88406f07b1aa51ba90c34d09ebce7587686b51 Mon Sep 17 00:00:00 2001 From: Aish1990 Date: Wed, 24 Apr 2024 22:00:45 +0530 Subject: [PATCH 02/89] Removed @ts-ignore from main.ts --- apps/drec-api/src/main.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/apps/drec-api/src/main.ts b/apps/drec-api/src/main.ts index f208973db..1b711586f 100755 --- a/apps/drec-api/src/main.ts +++ b/apps/drec-api/src/main.ts @@ -1,12 +1,10 @@ import { startAPI } from '.'; import { Logger } from '@nestjs/common'; -// @ts-ignore process.setMaxListeners(0); const logger = new Logger(); -// @ts-ignore process.on('warning', (e) => { logger.warn('warning inside main.ts'); logger.warn(e.stack); From 03c3112ce840efa529fd0e36dead52577b49f7b4 Mon Sep 17 00:00:00 2001 From: Aish1990 Date: Wed, 24 Apr 2024 22:56:53 +0530 Subject: [PATCH 03/89] Removed @ts-ignore from auth module --- apps/drec-api/src/auth/client-jwt.strategy.ts | 4 +--- apps/drec-api/src/auth/jwt.strategy.ts | 3 +-- apps/drec-api/src/models/User.ts | 1 + 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/apps/drec-api/src/auth/client-jwt.strategy.ts b/apps/drec-api/src/auth/client-jwt.strategy.ts index 8dd776b73..931bb4b19 100644 --- a/apps/drec-api/src/auth/client-jwt.strategy.ts +++ b/apps/drec-api/src/auth/client-jwt.strategy.ts @@ -26,10 +26,8 @@ export class ClientJwtStrategy extends PassportStrategy( } async validate(request: Request, payload: IJWTPayload) { - // @ts-ignore - const token = request.headers.authorization?.split(' ')[1]; + const token = (request.headers as { authorization?: string }).authorization?.split(' ')[1]; const user = await this.userService.findByEmail(payload.email); - // @ts-ignore const publicKey = this.oauthClientService.get(user.api_user_id); const verifiedData = await this.jwtService.verify(token, { publicKey: (await publicKey).client_id, diff --git a/apps/drec-api/src/auth/jwt.strategy.ts b/apps/drec-api/src/auth/jwt.strategy.ts index 0a964cd3d..c489f3091 100755 --- a/apps/drec-api/src/auth/jwt.strategy.ts +++ b/apps/drec-api/src/auth/jwt.strategy.ts @@ -33,8 +33,7 @@ export class JwtStrategy extends PassportStrategy(Strategy, 'jwt') { payload: IJWTPayload, ): Promise { this.logger.verbose('With in validate'); - // @ts-ignore - const token = request.headers.authorization?.split(' ')[1]; + const token = (request.headers as { authorization?: string }).authorization?.split(' ')[1]; const tokeninvalidate = await this.authService.isTokenBlacklisted( token, payload, diff --git a/apps/drec-api/src/models/User.ts b/apps/drec-api/src/models/User.ts index d0e944a7e..86e7aa2b6 100755 --- a/apps/drec-api/src/models/User.ts +++ b/apps/drec-api/src/models/User.ts @@ -13,6 +13,7 @@ export interface IUserProperties { role: Role; roleId?: number; permissions?: PermissionString; + api_user_id?: string; } export interface IUserSeed extends IUser { From 91d37a2a33b8e429325e8f96a1b8f418799208ef Mon Sep 17 00:00:00 2001 From: Aish1990 Date: Wed, 24 Apr 2024 23:34:41 +0530 Subject: [PATCH 04/89] Removed @ts-ignore from Without AuthGuard --- apps/drec-api/src/guards/WithoutAuthGuard.ts | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/apps/drec-api/src/guards/WithoutAuthGuard.ts b/apps/drec-api/src/guards/WithoutAuthGuard.ts index 86d0ee200..4fa7c9036 100644 --- a/apps/drec-api/src/guards/WithoutAuthGuard.ts +++ b/apps/drec-api/src/guards/WithoutAuthGuard.ts @@ -42,17 +42,16 @@ export class WithoutAuthGuard implements CanActivate { }) ).user; } else if (request.url.split('/')[3] === 'register') { + const userData = await this.userService.findOne({ role: Role.Admin }); if ( !request.body.api_user_id && (request.body.organizationType === 'Developer' || request.body.organizationType === Role.Buyer) ) { - user = await this.userService.findOne({ role: Role.Admin }); + user = userData; } else if ( request.body.api_user_id && - request.body.api_user_id != - // @ts-ignore ts(2339) - (await this.userService.findOne({ role: Role.Admin }).api_user_id) && + request.body.api_user_id != user.api_user_id && (request.body.organizationType === 'Developer' || request.body.organizationType === Role.Buyer) ) { @@ -82,10 +81,7 @@ export class WithoutAuthGuard implements CanActivate { request.body.organizationType === undefined && user.role != Role.Admin && user.role != Role.ApiUser && - // @ts-ignore ts(2339) user.api_user_id != - // prettier-ignore - // @ts-ignore ts(2339) ((await this.userService.findOne({ role: Role.Admin })) as IUser).api_user_id ) { throw new UnauthorizedException({ From 96d28ef7c440ff853ba63d0758a20aeded723c80 Mon Sep 17 00:00:00 2001 From: Aish1990 Date: Wed, 24 Apr 2024 23:36:25 +0530 Subject: [PATCH 05/89] Removed @ts-ignore from ILoggedInUser type --- apps/drec-api/src/models/LoggedInUser.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/drec-api/src/models/LoggedInUser.ts b/apps/drec-api/src/models/LoggedInUser.ts index ba8c9886c..fbabc78fe 100755 --- a/apps/drec-api/src/models/LoggedInUser.ts +++ b/apps/drec-api/src/models/LoggedInUser.ts @@ -23,7 +23,6 @@ export class LoggedInUser implements ILoggedInUser { this.blockchainAccountAddress = user.organization?.blockchainAccountAddress; this.role = user.role; this.permissions = user.permissions; - // @ts-ignore this.api_user_id = user.api_user_id; } From 344610ddc75b4de000d5abcc0c53ec4649138d3e Mon Sep 17 00:00:00 2001 From: NamrataSweya Date: Thu, 25 Apr 2024 17:11:01 +0530 Subject: [PATCH 06/89] DR-758,worked on certificate issue,change in issuermeta data payload now added devcie internal_externalId instead of device row id --- apps/drec-api/private_key.pem | 28 ++++++++ .../certificate-log.service.ts | 20 +++++- .../src/pods/device/device.service.ts | 6 +- .../src/pods/issuer/issuer.service.ts | 67 +++++++++---------- apps/drec-api/src/pods/reads/reads.service.ts | 41 ++++++------ apps/drec-api/src/utils/types.ts | 2 +- 6 files changed, 105 insertions(+), 59 deletions(-) create mode 100644 apps/drec-api/private_key.pem diff --git a/apps/drec-api/private_key.pem b/apps/drec-api/private_key.pem new file mode 100644 index 000000000..499a6f211 --- /dev/null +++ b/apps/drec-api/private_key.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDFHMSNmqhrUKjp +5NkcKyvD/oT5obYYxceFkS3qpJRdsmBGebjcJYloYUH5temaI7ptfX+i1G1aZHiR +znnfbwALh7pOLCegzfQZxdSSCdqj2O8Rp49vkFOM50yt8YKUCh557tk7tcMzaDTi +ti65Lw2nEEyqFXZNrGr6VUB0sKOPU4wjWfR2acYH3Lm3QhFJiIq9l6KEQhT/LRue +RakHU2zOnpBlwTEVGPYVE8B0TIv9NjdM0watKdJKAvR7Q+daR2GMuBDWbavKF7xM +8zjTFeCT7nw0cy2B2ma9pG/tUHHfY3l4obIwoUmVmNZES9/drNFsXz+Uq4NSR0qL +VzOQ4EknAgMBAAECggEABXuiYAoAS1PoDvGFtIni4sXOrx73cML3pNh//Xnsgpq2 +oN877CvDIbsq2aZcxCPgSLFn/oCINi57SBsFOtjcmHWDEi+aPpfcBWeCXTmW8l3T +cJtHmyPZnx7D/Eauii2p4VxqgIWy01g/uFq2/AG6EH6ck1Kbgteb9jCu5VAQjKkK +yoD14meaHhadJeC3avpxlwSm/bEnJgDh295R82gPQhLE7GtWBTrh2UcY1XjHceSp +J+DveQeetC6+cd/M/cVD55BAVul2IZgvHBGfqJVI7CiqeWIDOfD/lX5Axe5vb/AB +GQpM8eGnj5uhtFRWd+KgI5n8elFc13gNhYJBpJ1LuQKBgQDibAKieULkRwlePRZJ +JP1oeBBSYlyr4uWFLogaP4gSmkGsDfrcclW8nONf1Doa3prMPyUxZ9xJmlRicQ0c +jreN9oqScwbp8/6x1z4WTkvaVW+h8XD6dc90UFp+9zzcd9AMetMYlrfMR1a9FNV2 +BIfIQOVypdNqKGWCdrd27RaCVQKBgQDe3JbhLIxWfgUJHhHC2W8b4zHufJeizeqk +y44eVgvbGUGmP03IIOFnyckBwbBLY/awfU5u51f2h1D1GFzd9BwE5p75GWyCNvLi +0tlDWYuaeUCN3LVws4qpncJkFhCVNjlEHuReUKo8HD0juRNwsqd9aYb9VoCW3sSS +64KBraBxiwKBgQCxoBRNC54bYVMLGBckmJ0n2JDNYJbczWpLmd5x4QdJuLPuWyVC +zXtPNTD225IdxCZiNuNhp93b6/NpKtEjZx6+gvvgudZhsOVM9NOjQhclmEK0I6oD +AmsWD3d/BUw8lM2lDLIQJyTXX9u/B9oR9Knkwmx+DXMWY8yGlcWFyacP5QKBgQCn +Rd6haDR1fuT8sOsX2ufAgMirfiy6b+AcjQRA1MjVTKGvzHfvLG7C3fvXK6/NBlzU +n1jNeSrWyT4EmKKrnVuieg78XQ7Ktb+cbDHSkVVtPnEriWtOChSbtuN/B+iudiKJ +dL5n5BfCQlfJhlKHFjEMurYtVE3z74SP2eD8wHtafQKBgFsg04triENjWPexrudE +aR97QVcdwjHYRBlEWL/fjvmx33nviFPdhOkUrArSa76YuFIYkl7mIo7Ew58o1bQ+ +KCre6htOXf5mowRjA6eGso6e+kQ8Ok9ezqUqrwDMdbQEPI97cSL2hAO3pKqbUCSj +Y2SKht7m6SCySscqOtUbKcPD +-----END PRIVATE KEY----- diff --git a/apps/drec-api/src/pods/certificate-log/certificate-log.service.ts b/apps/drec-api/src/pods/certificate-log/certificate-log.service.ts index 69f5e664f..c94eaa3de 100755 --- a/apps/drec-api/src/pods/certificate-log/certificate-log.service.ts +++ b/apps/drec-api/src/pods/certificate-log/certificate-log.service.ts @@ -203,8 +203,15 @@ export class CertificateLogService { ); //going back 1 second in start and going forward 1 second in end await Promise.all( - obj.deviceIds.map(async (deviceid: number) => { - const device = await this.deviceService.findOne(deviceid); + obj.deviceIds.map(async (deviceid) => { + let device: Device; + if(typeof deviceid==='number'){ + device = await this.deviceService.findOne(deviceid); + } + if (typeof deviceid==='string'){ + device = await this.deviceService.findReads(deviceid); + } + const devicelog = await this.getCheckCertificateIssueDateLogForDevice( parseInt(groupid), @@ -291,7 +298,14 @@ export class CertificateLogService { await Promise.all( obj.deviceIds.map(async (deviceid: number) => { - const device = await this.deviceService.findOne(deviceid); + let device: Device; + if(typeof deviceid==='number'){ + device = await this.deviceService.findOne(deviceid); + } + if (typeof deviceid==='string'){ + device = await this.deviceService.findReads(deviceid); + } + const devicelog = await this.getCheckCertificateIssueDateLogForDevice( parseInt(groupid), diff --git a/apps/drec-api/src/pods/device/device.service.ts b/apps/drec-api/src/pods/device/device.service.ts index 3c7ad2563..6cb1ddda0 100755 --- a/apps/drec-api/src/pods/device/device.service.ts +++ b/apps/drec-api/src/pods/device/device.service.ts @@ -460,11 +460,15 @@ export class DeviceService { return device; } - async findReads(meterId: string): Promise { + async findReads(meterId: string): Promise { this.logger.verbose(`With in findReads`); const result = await this.repository.findOne({ where: { externalId: meterId }, }); + result.timezone = await getLocalTimeZoneFromDevice( + result.createdAt, + result, + ); delete result['organization']; return result ?? null; diff --git a/apps/drec-api/src/pods/issuer/issuer.service.ts b/apps/drec-api/src/pods/issuer/issuer.service.ts index 538d104bd..bc551f395 100755 --- a/apps/drec-api/src/pods/issuer/issuer.service.ts +++ b/apps/drec-api/src/pods/issuer/issuer.service.ts @@ -63,7 +63,7 @@ export class IssuerService { private baseReadsService: BaseReadsService, private httpService: HttpService, private readonly offChainCertificateService: OffChainCertificateService, - ) {} + ) { } // @Cron(CronExpression.EVERY_30_SECONDS) // @Cron('0 00 21 * * *') // Every day at 23:30 - Server Time @@ -238,9 +238,9 @@ export class IssuerService { //returns first find which is minimum and between next frequency if ( new Date(ele.createdAt).getTime() > - new Date(start_date).getTime() && + new Date(start_date).getTime() && new Date(ele.createdAt).getTime() < - new Date(newEndDate).getTime() + new Date(newEndDate).getTime() ) { return true; } @@ -422,7 +422,7 @@ export class IssuerService { if (group.reservationExpiryDate !== null) { if ( group.reservationExpiryDate.getTime() <= - group.reservationEndDate.getTime() || + group.reservationEndDate.getTime() || group.reservationExpiryDate.getTime() <= new Date().getTime() ) { await this.deviceService.removeFromGroup(device.id, group.id); @@ -443,7 +443,7 @@ export class IssuerService { if (group.reservationExpiryDate !== null) { if ( group.reservationExpiryDate.getTime() <= - group.reservationEndDate.getTime() || + group.reservationEndDate.getTime() || group.reservationExpiryDate.getTime() <= new Date().getTime() ) { await this.deviceService.removeFromGroup(device.id, group.id); @@ -470,7 +470,7 @@ export class IssuerService { if (group.reservationExpiryDate !== null) { if ( group.reservationExpiryDate.getTime() <= - group.reservationEndDate.getTime() || + group.reservationEndDate.getTime() || group.reservationExpiryDate.getTime() <= new Date().getTime() ) { await this.groupService.deactiveReaservation(group); @@ -627,7 +627,7 @@ export class IssuerService { start: startDate.toString(), end: endDate.toString(), }; - // console.log(readsFilter) + let allReadsForDeviceBetweenTimeRange: Array<{ timestamp: Date; value: number; @@ -635,7 +635,7 @@ export class IssuerService { device.externalId, readsFilter, ); - //console.log("482readdata", index, allReadsForDeviceBetweenTimeRange); + // console.log("482readdata", index, allReadsForDeviceBetweenTimeRange); if (allReadsForDeviceBetweenTimeRange != undefined) { if ( device.meterReadtype === 'Delta' || @@ -660,7 +660,7 @@ export class IssuerService { new Date(startDate.toString()), new Date(endDate.toString()), ); - // console.log("502certifieddevices", certifieddevices); + // console.log("502certifieddevices", certifieddevices); if ( certifieddevices.length > 0 && allReadsForDeviceBetweenTimeRange.length > 0 @@ -671,13 +671,13 @@ export class IssuerService { certifieddevices.forEach((certifieddevicesEle) => { if ( ele.timestamp.getTime() >= - new Date( - certifieddevicesEle.certificate_issuance_startdate, - ).getTime() && + new Date( + certifieddevicesEle.certificate_issuance_startdate, + ).getTime() && ele.timestamp.getTime() <= - new Date( - certifieddevicesEle.certificate_issuance_enddate, - ).getTime() + new Date( + certifieddevicesEle.certificate_issuance_enddate, + ).getTime() ) { readingInBetween = true; } @@ -689,7 +689,7 @@ export class IssuerService { } }); } - // console.log("521afterallReadsForDeviceBetweenTimeRange", allReadsForDeviceBetweenTimeRange); + // console.log("521afterallReadsForDeviceBetweenTimeRange", allReadsForDeviceBetweenTimeRange); allDevicesCompleteReadsBetweenTimeRange[index] = allReadsForDeviceBetweenTimeRange; @@ -766,7 +766,7 @@ export class IssuerService { let certificateTransactionUID = uuid(); await Promise.all( group.devices.map(async (device: IDevice, index) => { - // console.log("came inside previous readings check", allDevicesCompleteReadsBetweenTimeRange[index]); + console.log("came inside previous readings check", allDevicesCompleteReadsBetweenTimeRange[index]); let previousReading: Array<{ timestamp: Date; value: number }> = []; if (allDevicesCompleteReadsBetweenTimeRange[index].length > 0) { let endTimestampToCheck = new Date( @@ -775,7 +775,6 @@ export class IssuerService { ][0].timestamp.getTime() - 1000, ); let startTimeToCheck = device.createdAt; - try { previousReading = await this.readservice.findLastReadForMeterWithinRange( @@ -783,7 +782,7 @@ export class IssuerService { new Date(startTimeToCheck), endTimestampToCheck, ); - + if (previousReading.length == 0) { if (device.meterReadtype === ReadType.Delta) { previousReading = [ @@ -827,7 +826,7 @@ export class IssuerService { (accumulator, currentValue) => accumulator + currentValue.value, 0, ); - + let devicecertificatelogDto = new CheckCertificateIssueDateLogForDeviceEntity(); (devicecertificatelogDto.externalId = device.externalId), @@ -899,7 +898,7 @@ export class IssuerService { buyerReservationId: group.devicegroup_uid, isStandardIssuanceRequested: StandardCompliance.IREC, type: CertificateType.REC, - deviceIds: group.devices.map((device: IDevice) => device.id), + deviceIds: group.devices.map((device: IDevice) => device.externalId), //deviceGroup, groupId: group.id?.toString() || null, certificateTransactionUID: certificateTransactionUID.toString(), @@ -917,8 +916,8 @@ export class IssuerService { if ( group.authorityToExceed === false && group.targetVolumeCertificateGenerationRequestedInMegaWattHour + - totalReadValueMegaWattHour >= - group.targetVolumeInMegaWattHour + totalReadValueMegaWattHour >= + group.targetVolumeInMegaWattHour ) { this.groupService.endReservation(group.id, group, grouprequest); } @@ -994,7 +993,7 @@ export class IssuerService { buyerReservationId: group.devicegroup_uid, isStandardIssuanceRequested: StandardCompliance.IREC, type: CertificateType.REC, - deviceIds: [device.id], + deviceIds: [device.externalId], //deviceGroup, certificateTransactionUID: certificateTransactionUID.toString(), groupId: group.id?.toString() || null, @@ -1078,7 +1077,7 @@ export class IssuerService { this.logger.verbose(`With in handleLeftoverReadsByCountryCode`); const totalReadValueKw = group.leftoverReadsByCountryCode[countryCodeKey] ? totalReadValueW / 10 ** 3 + - group.leftoverReadsByCountryCode[countryCodeKey] + group.leftoverReadsByCountryCode[countryCodeKey] : totalReadValueW / 10 ** 3; const { integralVal, decimalVal } = this.separateIntegerAndDecimalByCountryCode(totalReadValueKw); @@ -1425,13 +1424,13 @@ export class IssuerService { certifieddevices.forEach((certifieddevicesEle) => { if ( ele.timestamp.getTime() >= - new Date( - certifieddevicesEle.certificate_issuance_startdate, - ).getTime() && + new Date( + certifieddevicesEle.certificate_issuance_startdate, + ).getTime() && ele.timestamp.getTime() <= - new Date( - certifieddevicesEle.certificate_issuance_enddate, - ).getTime() + new Date( + certifieddevicesEle.certificate_issuance_enddate, + ).getTime() ) { readingInBetween = true; } @@ -1555,7 +1554,7 @@ export class IssuerService { buyerReservationId: group.devicegroup_uid, isStandardIssuanceRequested: StandardCompliance.IREC, type: CertificateType.REC, - deviceIds: group.devices.map((device: IDevice) => device.id), + deviceIds: group.devices.map((device: IDevice) => device.externalId), //deviceGroup, groupId: group.id?.toString() || null, certificateTransactionUID: certificateTransactionUID.toString(), @@ -1570,8 +1569,8 @@ export class IssuerService { if ( group.authorityToExceed === false && group.targetVolumeCertificateGenerationRequestedInMegaWattHour + - totalReadValueMegaWattHour >= - group.targetVolumeInMegaWattHour + totalReadValueMegaWattHour >= + group.targetVolumeInMegaWattHour ) { this.groupService.endReservation(group.id, group, grouprequest); } diff --git a/apps/drec-api/src/pods/reads/reads.service.ts b/apps/drec-api/src/pods/reads/reads.service.ts index 4032015ed..e91efbc9a 100755 --- a/apps/drec-api/src/pods/reads/reads.service.ts +++ b/apps/drec-api/src/pods/reads/reads.service.ts @@ -425,15 +425,15 @@ export class ReadsService { // @ts-ignore if ( requeststartdate <= - DateTime.fromISO(new Date(historyAge).toISOString()) || + DateTime.fromISO(new Date(historyAge).toISOString()) || // @ts-ignore requeststartdate >= - DateTime.fromISO(new Date(device?.createdAt).toISOString()) || + DateTime.fromISO(new Date(device?.createdAt).toISOString()) || requestcurrentend <= - DateTime.fromISO(new Date(historyAge).toISOString()) || + DateTime.fromISO(new Date(historyAge).toISOString()) || // @ts-ignore requestcurrentend >= - DateTime.fromISO(new Date(device?.createdAt).toISOString()) + DateTime.fromISO(new Date(device?.createdAt).toISOString()) ) { return reject( new ConflictException({ @@ -601,7 +601,7 @@ export class ReadsService { if ( new Date(element.endtimestamp).getTime() < - new Date(lastvalue[0].datetime).getTime() || + new Date(lastvalue[0].datetime).getTime() || element.value <= lastvalue[0].value ) { return reject( @@ -687,7 +687,7 @@ export class ReadsService { Delta = Math.abs(element.value - lastvalue[0].value); if ( new Date(element.endtimestamp).getTime() < - new Date(lastvalue[0].datetime).getTime() || + new Date(lastvalue[0].datetime).getTime() || element.value <= lastvalue[0].value ) { return reject( @@ -761,6 +761,7 @@ export class ReadsService { |> range(start: ${startdate.getTime()}, stop: ${enddate.getTime()}) |> filter(fn: (r) => r.meter == "${meterId}" and r._field == "read") |> last()`; + return await this.execute(fluxQuery); } @@ -1357,13 +1358,13 @@ export class ReadsService { if (new Date(deviceOnboarded).getTime() < new Date(filter.end).getTime()) { this.logger.verbose( 'offset::::::::::::' + - filter.offset + - '\nlimit:::::::::::::' + - filter.limit + - '\n device onboarded::::::::::' + - deviceOnboarded.toString() + - '\nend:::::::::' + - filter.end.toString(), + filter.offset + + '\nlimit:::::::::::::' + + filter.limit + + '\n device onboarded::::::::::' + + deviceOnboarded.toString() + + '\nend:::::::::' + + filter.end.toString(), ); let readsFilter: FilterDTO = { @@ -1391,7 +1392,7 @@ export class ReadsService { } if ( new Date(filter.start).getTime() < - new Date(deviceOnboarded).getTime() || + new Date(deviceOnboarded).getTime() || new Date(filter.end).getTime() > new Date(deviceOnboarded).getTime() ) { const finalongoing = await this.getPaginatedData( @@ -1460,12 +1461,12 @@ export class ReadsService { this.logger.verbose( 'count of ong reads:::::::::::::::::::::::::::::::::::' + - (await this.getnumberOfOngReads( - filter.start, - filter.end, - externalId, - deviceOnboarded, - )), + (await this.getnumberOfOngReads( + filter.start, + filter.end, + externalId, + deviceOnboarded, + )), ); if (typeof pageNumber === 'number' && !isNaN(pageNumber)) { return { diff --git a/apps/drec-api/src/utils/types.ts b/apps/drec-api/src/utils/types.ts index 6378d31af..7bb233186 100755 --- a/apps/drec-api/src/utils/types.ts +++ b/apps/drec-api/src/utils/types.ts @@ -4,7 +4,7 @@ import { StandardCompliance, CertificateType } from './enums'; export interface ICertificateMetadata { version: string; - deviceIds: number[]; + deviceIds: string[]; //deviceGroup: DeviceGroupDTO; groupId: null | string; buyerReservationId?: string; From 3b8a25c77d5b85e196f133cb79ad303fde0ef17e Mon Sep 17 00:00:00 2001 From: NamrataSweya Date: Thu, 25 Apr 2024 17:14:20 +0530 Subject: [PATCH 07/89] delete apiuser private key file --- apps/drec-api/private_key.pem | 28 ---------------------------- 1 file changed, 28 deletions(-) delete mode 100644 apps/drec-api/private_key.pem diff --git a/apps/drec-api/private_key.pem b/apps/drec-api/private_key.pem deleted file mode 100644 index 499a6f211..000000000 --- a/apps/drec-api/private_key.pem +++ /dev/null @@ -1,28 +0,0 @@ ------BEGIN PRIVATE KEY----- -MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDFHMSNmqhrUKjp -5NkcKyvD/oT5obYYxceFkS3qpJRdsmBGebjcJYloYUH5temaI7ptfX+i1G1aZHiR -znnfbwALh7pOLCegzfQZxdSSCdqj2O8Rp49vkFOM50yt8YKUCh557tk7tcMzaDTi -ti65Lw2nEEyqFXZNrGr6VUB0sKOPU4wjWfR2acYH3Lm3QhFJiIq9l6KEQhT/LRue -RakHU2zOnpBlwTEVGPYVE8B0TIv9NjdM0watKdJKAvR7Q+daR2GMuBDWbavKF7xM -8zjTFeCT7nw0cy2B2ma9pG/tUHHfY3l4obIwoUmVmNZES9/drNFsXz+Uq4NSR0qL -VzOQ4EknAgMBAAECggEABXuiYAoAS1PoDvGFtIni4sXOrx73cML3pNh//Xnsgpq2 -oN877CvDIbsq2aZcxCPgSLFn/oCINi57SBsFOtjcmHWDEi+aPpfcBWeCXTmW8l3T -cJtHmyPZnx7D/Eauii2p4VxqgIWy01g/uFq2/AG6EH6ck1Kbgteb9jCu5VAQjKkK -yoD14meaHhadJeC3avpxlwSm/bEnJgDh295R82gPQhLE7GtWBTrh2UcY1XjHceSp -J+DveQeetC6+cd/M/cVD55BAVul2IZgvHBGfqJVI7CiqeWIDOfD/lX5Axe5vb/AB -GQpM8eGnj5uhtFRWd+KgI5n8elFc13gNhYJBpJ1LuQKBgQDibAKieULkRwlePRZJ -JP1oeBBSYlyr4uWFLogaP4gSmkGsDfrcclW8nONf1Doa3prMPyUxZ9xJmlRicQ0c -jreN9oqScwbp8/6x1z4WTkvaVW+h8XD6dc90UFp+9zzcd9AMetMYlrfMR1a9FNV2 -BIfIQOVypdNqKGWCdrd27RaCVQKBgQDe3JbhLIxWfgUJHhHC2W8b4zHufJeizeqk -y44eVgvbGUGmP03IIOFnyckBwbBLY/awfU5u51f2h1D1GFzd9BwE5p75GWyCNvLi -0tlDWYuaeUCN3LVws4qpncJkFhCVNjlEHuReUKo8HD0juRNwsqd9aYb9VoCW3sSS -64KBraBxiwKBgQCxoBRNC54bYVMLGBckmJ0n2JDNYJbczWpLmd5x4QdJuLPuWyVC -zXtPNTD225IdxCZiNuNhp93b6/NpKtEjZx6+gvvgudZhsOVM9NOjQhclmEK0I6oD -AmsWD3d/BUw8lM2lDLIQJyTXX9u/B9oR9Knkwmx+DXMWY8yGlcWFyacP5QKBgQCn -Rd6haDR1fuT8sOsX2ufAgMirfiy6b+AcjQRA1MjVTKGvzHfvLG7C3fvXK6/NBlzU -n1jNeSrWyT4EmKKrnVuieg78XQ7Ktb+cbDHSkVVtPnEriWtOChSbtuN/B+iudiKJ -dL5n5BfCQlfJhlKHFjEMurYtVE3z74SP2eD8wHtafQKBgFsg04triENjWPexrudE -aR97QVcdwjHYRBlEWL/fjvmx33nviFPdhOkUrArSa76YuFIYkl7mIo7Ew58o1bQ+ -KCre6htOXf5mowRjA6eGso6e+kQ8Ok9ezqUqrwDMdbQEPI97cSL2hAO3pKqbUCSj -Y2SKht7m6SCySscqOtUbKcPD ------END PRIVATE KEY----- From abb5d99342148862044171aa7bb60bbb5c1ed265 Mon Sep 17 00:00:00 2001 From: Aish1990 Date: Thu, 25 Apr 2024 22:48:45 +0530 Subject: [PATCH 08/89] Removed ts-ignore from Certificate Log Service --- .../pods/certificate-log/certificate-log.service.ts | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/apps/drec-api/src/pods/certificate-log/certificate-log.service.ts b/apps/drec-api/src/pods/certificate-log/certificate-log.service.ts index 99313b2aa..23efbd6bb 100755 --- a/apps/drec-api/src/pods/certificate-log/certificate-log.service.ts +++ b/apps/drec-api/src/pods/certificate-log/certificate-log.service.ts @@ -117,8 +117,7 @@ export class CertificateLogService { const totalPages = Math.ceil(total / itemsPerPage); const request: IGetAllCertificatesOptions = { - // @ts-ignore - deviceId: parseInt(groupid), + deviceId: `${parseInt(groupid)}`, }; const certifiedreservation1: ICertificateReadModel[] = @@ -254,14 +253,11 @@ export class CertificateLogService { certifiedlist: ICertificateReadModel, index: number, ) => { - // @ts-ignore ts(2339) certificatesInReservationWithLog[index].certificateStartDate = new Date(certifiedlist.generationStartTime * 1000).toISOString(); - // @ts-ignore ts(2339) certificatesInReservationWithLog[index].certificateEndDate = new Date( certifiedlist.generationEndTime * 1000, ).toISOString(); - // @ts-ignore ts(2339) certificatesInReservationWithLog[index].perDeviceCertificateLog = []; try { if (typeof certifiedlist.metadata === 'string') { @@ -309,7 +305,6 @@ export class CertificateLogService { certificatesInReservationWithLog[ index - // @ts-ignore ts(2339) ].perDeviceCertificateLog.push(singleDeviceLogEle); }); @@ -830,15 +825,12 @@ export class CertificateLogService { certifiedlist: ICertificateReadModel, index: number, ) => { - // @ts-ignore ts(2339) certificatesInReservationWithLog[index].certificateStartDate = new Date( certifiedlist.generationStartTime * 1000, ).toISOString(); - // @ts-ignore ts(2339) certificatesInReservationWithLog[index].certificateEndDate = new Date(certifiedlist.generationEndTime * 1000).toISOString(); - // @ts-ignore ts(2339) certificatesInReservationWithLog[index].perDeviceCertificateLog = []; try { @@ -891,7 +883,6 @@ export class CertificateLogService { certificatesInReservationWithLog[ index - // @ts-ignore ts(2339) ].perDeviceCertificateLog.push(singleDeviceLogEle); }); } else { @@ -918,7 +909,6 @@ export class CertificateLogService { ); certificatesInReservationWithLog[ index - // @ts-ignore ts(2339) ].perDeviceCertificateLog.push(devicelog[0]); } } @@ -940,7 +930,6 @@ export class CertificateLogService { getLocalTimeZoneFromDevice(device.createdAt, device); certificatesInReservationWithLog[ index - // @ts-ignore ts(2339) ].perDeviceCertificateLog.push(singleDeviceLogEle); }); } From 59f10c034ac1ea8a7a299962b3d8171ea587ee59 Mon Sep 17 00:00:00 2001 From: Aish1990 Date: Thu, 25 Apr 2024 23:53:09 +0530 Subject: [PATCH 09/89] Removed ts-ignore from Device Controller --- .../src/pods/device/device.controller.ts | 2174 ++++++++--------- .../src/pods/device/dto/filter.dto.ts | 2 + .../src/pods/device/dto/new-device.dto.ts | 5 + 3 files changed, 1090 insertions(+), 1091 deletions(-) diff --git a/apps/drec-api/src/pods/device/device.controller.ts b/apps/drec-api/src/pods/device/device.controller.ts index 1566966a9..9cd7fa972 100755 --- a/apps/drec-api/src/pods/device/device.controller.ts +++ b/apps/drec-api/src/pods/device/device.controller.ts @@ -1,1091 +1,1083 @@ -import { - Controller, - Get, - Post, - Put, - Patch, - Delete, - HttpStatus, - Param, - Body, - UseGuards, - ValidationPipe, - Query, - ConflictException, - HttpException, - UnauthorizedException, - BadRequestException, - Logger, -} from '@nestjs/common'; - -import { - ApiBearerAuth, - ApiNotFoundResponse, - ApiResponse, - ApiOkResponse, - ApiSecurity, - ApiTags, - ApiQuery, - ApiBody, -} from '@nestjs/swagger'; -import { AuthGuard } from '@nestjs/passport'; -import { plainToClass } from 'class-transformer'; - -import { DeviceService } from './device.service'; -import { - FilterDTO, - NewDeviceDTO, - UpdateDeviceDTO, - DeviceDTO, - DeviceGroupByDTO, - GroupedDevicesDTO, -} from './dto'; -import { CSVBulkUploadDTO } from '../device-group/dto'; -import { Role } from '../../utils/enums'; -import { RolesGuard } from '../../guards/RolesGuard'; -import { PermissionGuard } from '../../guards/PermissionGuard'; -import { ILoggedInUser } from '../../models'; -import { CodeNameDTO } from './dto/code-name.dto'; -import { ActiveUserGuard } from '../../guards'; -import { Roles } from '../user/decorators/roles.decorator'; -import { UserDecorator } from '../user/decorators/user.decorator'; -import { DeviceGroupService } from '../device-group/device-group.service'; -import { Permission } from '../permission/decorators/permission.decorator'; -import { ACLModules } from '../access-control-layer-module-service/decorator/aclModule.decorator'; -import { CountrycodeService } from '../countrycode/countrycode.service'; -import { countryCodesList } from '../../models/country-code'; -import { isValidUTCDateFormat } from '../../utils/checkForISOStringFormat'; -import { DeviceGroup } from '../device-group/device-group.entity'; -import { - DeviceCsvFileProcessingJobsEntity, - StatusCSV, -} from '../device-group/device_csv_processing_jobs.entity'; -import { Device } from './device.entity'; -import { OrganizationService } from '../organization/organization.service'; -import { UserService } from '../user/user.service'; -import { FindOneOptions } from 'typeorm'; - -/** - * It is Controller of device with the endpoints of device operations. - */ -@ApiTags('device') -@ApiBearerAuth('access-token') -@ApiSecurity('drec') -@Controller('/device') -export class DeviceController { - private readonly logger = new Logger(DeviceController.name); - - constructor( - private readonly deviceGroupService: DeviceGroupService, - private readonly deviceService: DeviceService, - private readonly organizationService: OrganizationService, - private readonly userService: UserService, - ) {} - - /** - * It is GET api to list all devices with paginatiion and fiteration by organization and filterationDto - */ - @Get() - @UseGuards(AuthGuard('jwt'), ActiveUserGuard, RolesGuard, PermissionGuard) - @Roles(Role.Admin) - @Permission('Read') - @ACLModules('DEVICE_MANAGEMENT_CRUDL') - @ApiQuery({ name: 'pagenumber', type: Number, required: false }) - @ApiQuery({ name: 'OrganizationId', type: Number, required: false }) - @ApiOkResponse({ type: [DeviceDTO], description: 'Returns all Devices' }) - async getAll( - @Query(ValidationPipe) filterDto: FilterDTO, - @Query('pagenumber') pagenumber: number | null, - @Query('OrganizationId') OrgId: number | null, - ) /*: Promise*/ { - this.logger.verbose(`With in getAll`); - return this.deviceService.find(filterDto, pagenumber, OrgId); - } - - /** - * It is GET api to list all devices for reservation - * @return {Array} return array of devices for reservation - */ - @Get('/ungrouped/buyerreservation') - @UseGuards( - AuthGuard(['jwt', 'oauth2-client-password']), - PermissionGuard, - RolesGuard, - ) - @Permission('Read') - @ACLModules('DEVICE_MANAGEMENT_CRUDL') - @Roles(Role.Buyer, Role.SubBuyer, Role.ApiUser) - @ApiOkResponse({ type: [DeviceDTO], description: 'Returns all Devices' }) - async getAllDeviceForBuyer( - @Query(ValidationPipe) filterDto: FilterDTO, - @Query('pagenumber') pagenumber: number | null, - @UserDecorator() { organizationId, api_user_id, role }: ILoggedInUser, - ): Promise { - this.logger.verbose(`With in getAllDeviceForBuyer`); - // @ts-ignore ts(2339) - if (filterDto.organizationId) { - const organization = await this.organizationService.findOne( - // @ts-ignore ts(2339) - filterDto.organizationId, - ); - const orguser = await this.userService.findByEmail(organization.orgEmail); - if (role === Role.ApiUser) { - if (organization.api_user_id != api_user_id) { - this.logger.error( - `The requested organization is belongs to other apiuser`, - ); - throw new UnauthorizedException({ - success: false, - message: `The requested organization is belongs to other apiuser`, - }); - } - - if ( - orguser.role === Role.OrganizationAdmin || - orguser.role === Role.DeviceOwner - ) { - this.logger.error( - `Unauthorized... The requested user is developer or device owner`, - ); - throw new UnauthorizedException({ - success: false, - message: `Unauthorized`, - }); - } - } else { - if (organizationId != organization.id) { - this.logger.error( - `The requested organization is not same as user's organization`, - ); - throw new UnauthorizedException({ - success: false, - message: `The requested organization is not same as user's organization`, - }); - } - } - } - - if (role !== Role.ApiUser) { - api_user_id = null; - } - - return this.deviceService.finddeviceForBuyer( - filterDto, - pagenumber, - api_user_id, - ); - } - - /** - * It is GET api to list all ungrouped devices with filteration - * @return {GroupedDevicesDTO} returns ungrouped devices - */ - @Get('/ungrouped') - @UseGuards(AuthGuard('jwt'), ActiveUserGuard, RolesGuard, PermissionGuard) - @Roles(Role.Admin, Role.DeviceOwner) - @Permission('Read') - @ACLModules('DEVICE_MANAGEMENT_CRUDL') - @ApiOkResponse({ - type: [GroupedDevicesDTO], - description: 'Returns all ungrouped Devices', - }) - async getAllUngrouped( - @UserDecorator() { organizationId }: ILoggedInUser, - @Query(ValidationPipe) orderFilterDto: DeviceGroupByDTO, - ): Promise { - this.logger.verbose(`With in getAllUngrouped`); - return this.deviceService.findUngrouped(organizationId, orderFilterDto); - } - - /** - * It is GET to list all device code types in dropdown - * @returns {Array} - */ - @Get('/device-type') - @ApiResponse({ - status: HttpStatus.OK, - type: [CodeNameDTO], - description: 'Returns all IREC device types', - }) - getDeviceTypes(): CodeNameDTO[] { - this.logger.verbose(`With in getDeviceTypes`); - const deviceTypes = this.deviceService.getDeviceTypes(); - - return deviceTypes.map((deviceType) => - plainToClass(CodeNameDTO, deviceType), - ); - } - - /** - * It is GET api to list all fuel types in dropdown - * @returns {Array} - */ - @Get('/fuel-type') - @ApiResponse({ - status: HttpStatus.OK, - type: [CodeNameDTO], - description: 'Returns all IREC fuel types', - }) - getFuelTypes(): CodeNameDTO[] { - this.logger.verbose(`With in getFuelTypes`); - const fuelTypes = this.deviceService.getFuelTypes(); - return fuelTypes.map((fuelType) => plainToClass(CodeNameDTO, fuelType)); - } - - /** - * It is GET api to list all my devices with filteration and pagination - * @returns {Array} - */ - @Get('/my') - @UseGuards( - AuthGuard(['jwt', 'oauth2-client-password']), - ActiveUserGuard, - PermissionGuard, - ) - @Permission('Read') - @ACLModules('DEVICE_MANAGEMENT_CRUDL') - @ApiQuery({ name: 'pagenumber', type: Number, required: false }) - @ApiResponse({ - status: HttpStatus.OK, - type: [DeviceDTO], - description: 'Returns my Devices', - }) - async getMyDevices( - @Query(ValidationPipe) filterDto: FilterDTO, - @UserDecorator() { organizationId, api_user_id, role }: ILoggedInUser, - @Query('pagenumber') pagenumber: number | null, - ) /*: Promise*/ { - this.logger.verbose(`With in getMyDevices`); - if (filterDto.country) { - filterDto.country = filterDto.country.toUpperCase(); - - if ( - filterDto.country && - typeof filterDto.country === 'string' && - filterDto.country.length === 3 - ) { - const countries = countryCodesList; - if ( - countries.find((ele) => ele.countryCode === filterDto.country) === - undefined - ) { - this.logger.error( - `Invalid countryCode, some of the valid country codes are "GBR" - "United Kingdom of Great Britain and Northern Ireland", "CAN" - "Canada" "IND" - "India", "DEU"- "Germany"`, - ); - return new Promise((resolve, reject) => { - reject( - new ConflictException({ - success: false, - message: - ' Invalid countryCode, some of the valid country codes are "GBR" - "United Kingdom of Great Britain and Northern Ireland", "CAN" - "Canada" "IND" - "India", "DEU"- "Germany"', - }), - ); - }); - } - } else { - this.logger.error( - `Invalid countryCode, some of the valid country codes are "GBR" - "United Kingdom of Great Britain and Northern Ireland", "CAN" - "Canada" "IND" - "India", "DEU"- "Germany"`, - ); - return new Promise((resolve, reject) => { - reject( - new ConflictException({ - success: false, - message: - ' Invalid countryCode, some of the valid country codes are "GBR" - "United Kingdom of Great Britain and Northern Ireland", "CAN" - "Canada" "IND" - "India", "DEU"- "Germany"', - }), - ); - }); - } - } - // @ts-ignore - if (filterDto.organizationId) { - if (role === Role.ApiUser) { - const organization = await this.organizationService.findOne( - // @ts-ignore ts(2339) - filterDto.organizationId, - ); - const orguser = await this.userService.findByEmail( - organization.orgEmail, - ); - if (organization.api_user_id != api_user_id) { - this.logger.error( - `The organization Id in param is belongs to other apiuser`, - ); - throw new UnauthorizedException({ - success: false, - message: 'The organization Id in param is belongs to other apiuser', - }); - } else { - if (orguser.role != Role.OrganizationAdmin) { - this.logger.error(`Unauthorized`); - throw new UnauthorizedException({ - success: false, - message: 'Unauthorized', - }); - } - } - } else { - // @ts-ignore - if (filterDto.organizationId != organizationId) { - this.logger.error( - `The organization Id in param should be same as user's organization`, - ); - throw new UnauthorizedException({ - success: false, - message: `The organization Id in param should be same as user's organization`, - }); - } - } - - // @ts-ignore - organizationId = filterDto.organizationId; - } - - this.logger.log('In devices before calling service'); - return await this.deviceService.getOrganizationDevices( - organizationId, - api_user_id, - role, - filterDto, - pagenumber, - ); - } - - /** - * It is GET api to fetch an device by the deviceId in param - * @param id is deviceId in type number - * @returns {DeviceDTO | null} DeviceDto for success response and null when there is no device found by the id - */ - @Get('/:id') - @UseGuards( - AuthGuard(['jwt', 'oauth2-client-password']), - ActiveUserGuard, - PermissionGuard, - ) - @Permission('Read') - @ACLModules('DEVICE_MANAGEMENT_CRUDL') - @ApiQuery({ name: 'apiUserId', type: String, required: false }) - @ApiQuery({ name: 'organizationId', type: Number, required: false }) - @ApiOkResponse({ type: DeviceDTO, description: 'Returns a Device' }) - @ApiNotFoundResponse({ - description: `The device with the code doesn't exist`, - }) - async get( - @Param('id') id: number, - @Query('apiUserId') api_user_id: string | null, - @Query('organizationId') organizationId: number | null, - ): Promise { - this.logger.verbose(`With in get`); - let devicedata: Device; - if (api_user_id && organizationId) { - devicedata = await this.deviceService.findOne(id, { - api_user_id: api_user_id, - organizationId: organizationId, - } as FindOneOptions); - } else { - devicedata = await this.deviceService.findOne(id); - } - devicedata.externalId = devicedata.developerExternalId; - delete devicedata['developerExternalId']; - return devicedata; - } - - /** - * It is GET api to fetch an device by externalId in param - * @param id is externalId in device - * @param param1 - * @returns {DeviceDTO | null} DeviceDto for success response and null when there is no device found by the id - */ - @Get('externalId/:id') - @UseGuards(AuthGuard('jwt'), PermissionGuard) - @Permission('Read') - @ACLModules('DEVICE_MANAGEMENT_CRUDL') - @ApiOkResponse({ type: DeviceDTO, description: 'Returns a Device' }) - @ApiNotFoundResponse({ - description: `The device with the code doesn't exist`, - }) - async getByExternalId( - @Param('id') id: string, - @UserDecorator() { organizationId }: ILoggedInUser, - ): Promise { - this.logger.verbose(`With in getByExternalId`); - const devicedata = await this.deviceService.findDeviceByDeveloperExternalId( - id, - organizationId, - ); - devicedata.externalId = devicedata.developerExternalId; - delete devicedata['developerExternalId']; - return devicedata; - } - - /** - * It is POST api to create an device - * @param param0 It is organizationId from user at request - * @param deviceToRegister It is body payload to create device - * @returns {DeviceDTO} - */ - @Post() - @UseGuards(AuthGuard(['jwt', 'oauth2-client-password']), PermissionGuard) - @Permission('Write') - @ACLModules('DEVICE_MANAGEMENT_CRUDL') - @ApiResponse({ - status: HttpStatus.OK, - type: NewDeviceDTO, - description: 'Returns a new created Device id', - }) - public async create( - @UserDecorator() { organizationId, role, api_user_id }: ILoggedInUser, - @Body() deviceToRegister: NewDeviceDTO, - ): Promise { - this.logger.verbose(`With in create`); - deviceToRegister.externalId = deviceToRegister.externalId.trim(); - if (deviceToRegister.externalId.trim() === '') { - this.logger.error(`externalId should not be empty`); - return new Promise((resolve, reject) => { - reject( - new ConflictException({ - success: false, - message: `externalId should not be empty`, - }), - ); - }); - } - - if (!isValidUTCDateFormat(deviceToRegister.commissioningDate)) { - this.logger.error( - `Invalid commissioning date, valid format is YYYY-MM-DDThh:mm:ss.millisecondsZ example 2022-10-18T11:35:27.640Z`, - ); - return new Promise((resolve, reject) => { - reject( - new ConflictException({ - success: false, - message: - ' Invalid commissioning date, valid format is YYYY-MM-DDThh:mm:ss.millisecondsZ example 2022-10-18T11:35:27.640Z ', - }), - ); - }); - } - if ( - new Date(deviceToRegister.commissioningDate).getTime() > - new Date().getTime() - ) { - this.logger.error( - `Invalid commissioning date, commissioning is greater than current date`, - ); - return new Promise((resolve, reject) => { - reject( - new ConflictException({ - success: false, - message: ` Invalid commissioning date, commissioning is greater than current date`, - }), - ); - }); - } - if (deviceToRegister['groupId'] === 0 || deviceToRegister['groupId']) { - deviceToRegister['groupId'] = null; - } - deviceToRegister.countryCode = deviceToRegister.countryCode.toUpperCase(); - if ( - deviceToRegister.countryCode && - typeof deviceToRegister.countryCode === 'string' && - deviceToRegister.countryCode.length === 3 - ) { - const countries = countryCodesList; - if ( - countries.find( - (ele) => ele.countryCode === deviceToRegister.countryCode, - ) === undefined - ) { - this.logger.error( - `Invalid countryCode, some of the valid country codes are "GBR" - "United Kingdom of Great Britain and Northern Ireland", "CAN" - "Canada" "IND" - "India", "DEU"- "Germany"`, - ); - return new Promise((resolve, reject) => { - reject( - new ConflictException({ - success: false, - message: - ' Invalid countryCode, some of the valid country codes are "GBR" - "United Kingdom of Great Britain and Northern Ireland", "CAN" - "Canada" "IND" - "India", "DEU"- "Germany"', - }), - ); - }); - } - } else { - this.logger.error( - `Invalid countryCode, some of the valid country codes are "GBR" - "United Kingdom of Great Britain and Northern Ireland", "CAN" - "Canada" "IND" - "India", "DEU"- "Germany"`, - ); - return new Promise((resolve, reject) => { - reject( - new ConflictException({ - success: false, - message: - ' Invalid countryCode, some of the valid country codes are "GBR" - "United Kingdom of Great Britain and Northern Ireland", "CAN" - "Canada" "IND" - "India", "DEU"- "Germany"', - }), - ); - }); - } - if (isNaN(parseFloat(deviceToRegister.capacity.toString()))) { - this.logger.error(`Invalid Capacity or energy Storage Capacity`); - return new Promise((resolve, reject) => { - reject( - new ConflictException({ - success: false, - message: ' Invalid Capacity or energy Storage Capacity', - }), - ); - }); - } - if ( - deviceToRegister.capacity <= 0 || - deviceToRegister.energyStorageCapacity < 0 - ) { - this.logger.error( - `Invalid Capacity or energy Storage Capacity, it should be greater than 0`, - ); - return new Promise((resolve, reject) => { - reject( - new ConflictException({ - success: false, - message: - ' Invalid Capacity or energy Storage Capacity, it should be greater than 0', - }), - ); - }); - } - if ( - deviceToRegister.version === null || - deviceToRegister.version === undefined || - deviceToRegister.version === '0' - ) { - deviceToRegister.version = '1.0'; - } - if (role === Role.Admin || role === Role.ApiUser) { - // @ts-ignore - if (deviceToRegister.organizationId) { - this.logger.debug('Line No: 314'); - // @ts-ignore - organizationId = deviceToRegister.organizationId; - } else { - this.logger.error( - `Organization id is required,please add your developer's Organization`, - ); - return new Promise((resolve, reject) => { - reject( - new ConflictException({ - success: false, - message: `Organization id is required,please add your developer's Organization `, - }), - ); - }); - } - } - return await this.deviceService.register( - organizationId, - deviceToRegister, - api_user_id, - role, - ); - } - - /** - * It is PATCH api to update an device by externalId - * @param user is loggedin user from user at request - * @param externalId is unique external id in device entity - * @param deviceToUpdate is body payload to update an device - * @returns {DeviceDTO} - */ - @Patch('/:externalId') - @UseGuards(AuthGuard('jwt'), PermissionGuard) - @Permission('Update') - @ACLModules('DEVICE_MANAGEMENT_CRUDL') - @ApiResponse({ - status: HttpStatus.OK, - type: UpdateDeviceDTO, - description: 'Returns an updated Device', - }) - @ApiNotFoundResponse({ description: `No device found` }) - public async update( - @UserDecorator() user: ILoggedInUser, - @Param('externalId') externalId: string, - @Body() deviceToUpdate: UpdateDeviceDTO, - ): Promise { - this.logger.verbose(`With in update`); - - if (deviceToUpdate.externalId) { - deviceToUpdate.externalId = deviceToUpdate.externalId.trim(); - if (deviceToUpdate.externalId === '') { - this.logger.error(`externalId should not be empty`); - return new Promise((resolve, reject) => { - reject( - new ConflictException({ - success: false, - message: `externalId should not be empty`, - }), - ); - }); - } - - const checkexternalid = - await this.deviceService.findDeviceByDeveloperExternalId( - deviceToUpdate.externalId, - user.organizationId, - ); - if ( - checkexternalid != undefined && - checkexternalid.developerExternalId === externalId.trim() - ) { - this.logger.log('Line No: 236'); - return new Promise((resolve, reject) => { - reject( - new ConflictException({ - success: false, - message: `ExternalId already exist in this organization, can't update with same external id ${deviceToUpdate.externalId}`, - }), - ); - }); - } - } - - if (deviceToUpdate.countryCode != undefined) { - deviceToUpdate.countryCode = deviceToUpdate.countryCode.toUpperCase(); - if ( - deviceToUpdate.countryCode && - typeof deviceToUpdate.countryCode === 'string' && - deviceToUpdate.countryCode.length === 3 - ) { - const countries = countryCodesList; - if ( - countries.find( - (ele) => ele.countryCode === deviceToUpdate.countryCode, - ) === undefined - ) { - this.logger.error( - `Invalid countryCode, some of the valid country codes are "GBR" - "United Kingdom of Great Britain and Northern Ireland", "CAN" - "Canada" "IND" - "India", "DEU"- "Germany"`, - ); - return new Promise((resolve, reject) => { - reject( - new ConflictException({ - success: false, - message: - ' Invalid countryCode, some of the valid country codes are "GBR" - "United Kingdom of Great Britain and Northern Ireland", "CAN" - "Canada" "IND" - "India", "DEU"- "Germany"', - }), - ); - }); - } - } else { - this.logger.error( - `Invalid countryCode, some of the valid country codes are "GBR" - "United Kingdom of Great Britain and Northern Ireland", "CAN" - "Canada" "IND" - "India", "DEU"- "Germany"`, - ); - return new Promise((resolve, reject) => { - reject( - new ConflictException({ - success: false, - message: - ' Invalid countryCode, some of the valid country codes are "GBR" - "United Kingdom of Great Britain and Northern Ireland", "CAN" - "Canada" "IND" - "India", "DEU"- "Germany"', - }), - ); - }); - } - } - - if (deviceToUpdate.capacity <= 0) { - this.logger.error(`Invalid Capacity, it should be greater than 0`); - return new Promise((resolve, reject) => { - reject( - new ConflictException({ - success: false, - message: ' Invalid Capacity, it should be greater than 0', - }), - ); - }); - } - if ( - !isValidUTCDateFormat(deviceToUpdate.commissioningDate) && - deviceToUpdate.commissioningDate !== undefined - ) { - this.logger.error( - `Invalid commissioning date, valid format is YYYY-MM-DDThh:mm:ss.millisecondsZ example 2022-10-18T11:35:27.640Z`, - ); - return new Promise((resolve, reject) => { - reject( - new ConflictException({ - success: false, - message: - ' Invalid commissioning date, valid format is YYYY-MM-DDThh:mm:ss.millisecondsZ example 2022-10-18T11:35:27.640Z ', - }), - ); - }); - } - if ( - new Date(deviceToUpdate.commissioningDate).getTime() > - new Date().getTime() - ) { - this.logger.error( - `Invalid commissioning date, commissioning is greater than current date`, - ); - return new Promise((resolve, reject) => { - reject( - new ConflictException({ - success: false, - message: ` Invalid commissioning date, commissioning is greater than current date`, - }), - ); - }); - } - - if (deviceToUpdate.commissioningDate) { - const checkexternalid = - await this.deviceService.findDeviceByDeveloperExternalId( - externalId, - user.organizationId, - ); - const noOfHistRead: number = - await this.deviceService.getNumberOfHistReads( - checkexternalid.externalId, - ); - const noOfOnGoingRead: number = - await this.deviceService.getNumberOfOngReads( - checkexternalid.externalId, - checkexternalid.createdAt, - ); - - if ( - deviceToUpdate.commissioningDate != checkexternalid.commissioningDate - ) { - if (noOfHistRead > 0 || noOfOnGoingRead > 0) { - this.logger.error( - `Commissioning date cannot be changed due to existing meter reads available for ${checkexternalid.developerExternalId}`, - ); - throw new ConflictException({ - success: false, - message: ` Commissioning date cannot be changed due to existing meter reads available for ${checkexternalid.developerExternalId}`, - }); - } - - if ( - new Date(deviceToUpdate.commissioningDate).getTime() > - new Date(checkexternalid.createdAt).getTime() - ) { - this.logger.error( - `Invalid commissioning date, commissioning is greater than device onboarding date`, - ); - throw new ConflictException({ - success: false, - message: `Invalid commissioning date, commissioning is greater than device onboarding date`, - }); - } - } - } - return await this.deviceService.update( - user.organizationId, - user.role, - externalId, - deviceToUpdate, - ); - } - - /** - * It is DELETE api to delete an device by id - * @param id is deviceId - * @param param1 is getting organizationId and user role from user request - * @returns {any} - */ - @Delete('/:id') - @UseGuards(AuthGuard('jwt'), RolesGuard, PermissionGuard) - @Permission('Delete') - @ACLModules('DEVICE_MANAGEMENT_CRUDL') - @Roles(Role.OrganizationAdmin, Role.Admin) - @ApiResponse({ - status: HttpStatus.OK, - description: 'Remove device group', - }) - @ApiNotFoundResponse({ description: `No device group found` }) - public async remove( - @Param('id') id: number, - @UserDecorator() { organizationId, role }: ILoggedInUser, - ): Promise { - this.logger.verbose(`With in remove`); - const checkisungroup = this.deviceService.findUngroupedById(id); - if (checkisungroup) { - let fitlerop: any; - if (role === 'Admin') { - fitlerop = { - groupId: null, - }; - } else { - fitlerop = { - groupId: null, - organizationId: organizationId, - }; - } - return await this.deviceService.remove(id, fitlerop); - } - } - - /** - * It is GET api to list all total amount of reads by each devices grouped by organization - * @param param0 is getting organizationId from user request. - * @returns {Array} - */ - @Get('/my/totalamountread') - @UseGuards(AuthGuard('jwt'), ActiveUserGuard, PermissionGuard) - @Permission('Read') - @ACLModules('DEVICE_MANAGEMENT_CRUDL') - @ApiResponse({ - status: HttpStatus.OK, - type: [DeviceDTO], - description: 'Returns my Devices', - }) - async getMyDevicesTotal( - @UserDecorator() { organizationId }: ILoggedInUser, - ): Promise { - this.logger.verbose(`Wth in getMyDevicesTotal`); - return await this.deviceService.getOrganizationDevicesTotal(organizationId); - } - - /** - * It is PUT api tp update the device onboarding date by deviceId - * @param param0 is getting organizationId from user request - * @param deviceId is deviceId from device unique identifier - * @param givenDate is new onboarding date to be updated. - * @returns {} - */ - @Put('/my/deviceOnBoardingDate') - @UseGuards(AuthGuard('jwt'), PermissionGuard) - @Permission('Write') - @ACLModules('DEVICE_MANAGEMENT_CRUDL') - @ApiResponse({ - status: HttpStatus.OK, - description: "change the device's OnBoarding date", - }) - @ApiQuery({ name: 'deviceId', description: 'Device Id' }) - @ApiQuery({ - name: 'givenDate', - description: 'Update the OnBoarding date', - type: Date, - }) - async changeOnBoardingDate( - @UserDecorator() { organizationId }: ILoggedInUser, - @Query('deviceId') deviceId, - @Query('givenDate') givenDate, - ) { - this.logger.verbose(`With in changeOnBoardingDate`); - if (process.env.MODE != 'dev') { - this.logger.error(`Currently not in dev environment`); - throw new HttpException('Currently not in dev environment', 400); - } - const device: DeviceDTO | null = - await this.deviceService.findDeviceByDeveloperExternalId( - deviceId, - organizationId, - ); - this.logger.debug( - 'THE DEVICE FROM ExTERNALID IS::::::::::::' + device.externalId, - ); - if (!device) { - this.logger.error(`Device dosen't exist`); - throw new HttpException("Device dosen't exist", 400); - } - const deviceExternalId = device.externalId; - const deviceOnboardedDate = device.createdAt; - return this.deviceService.changeDeviceCreatedAt( - deviceExternalId, - deviceOnboardedDate, - givenDate, - ); - } - - /** - * It is GET api to list all devices with auto complete - * @param param0 is getting organizationId from user request - * @param externalId is unique identoifier of an device - * @returns {} - */ - @Get('/my/autocomplete') - @UseGuards(AuthGuard('jwt'), ActiveUserGuard, PermissionGuard) - @Permission('Read') - @ACLModules('DEVICE_MANAGEMENT_CRUDL') - @ApiResponse({ - status: HttpStatus.OK, - description: 'Returns Auto-Complete', - }) - @ApiQuery({ name: 'externalId', description: 'externalId', type: String }) - async autocomplete( - @UserDecorator() { organizationId }: ILoggedInUser, - @Query('externalId') externalId: string, - ) { - this.logger.verbose(`With in autocomplete`); - return await this.deviceService.atto(organizationId, externalId); - } - - /** - * It is GET api to fetch the certified device records with in the range of date - * @param user is loggedIn user at request - * @param externalId is unique identifier of device - * @param groupuId - * @returns {any} - */ - @Get('/certifiedlog/first&lastdate') - @UseGuards(AuthGuard('jwt'), PermissionGuard) - @Permission('Read') - @ACLModules('DEVICE_MANAGEMENT_CRUDL') - @ApiQuery({ name: 'externalId', type: Number, required: false }) - @ApiQuery({ name: 'pagenumber', type: Number, required: false }) - @ApiResponse({ - status: HttpStatus.OK, - description: 'Returns Certified log date rang of Device', - }) - async certifiedlogdaterang( - @UserDecorator() user: ILoggedInUser, - @Query('groupUid') groupuId: string, - @Query('pagenumber') pagenumber: number, - @Query('externalId') externalId?: number, - ): Promise { - this.logger.verbose(`With in certifiedlogdaterang`); - const regexExp = - /^[0-9a-fA-F]{8}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{12}$/; - if (groupuId === null || !regexExp.test(groupuId)) { - this.logger.error( - `Please Add the valid UID ,invalid group uid value was sent`, - ); - return new Promise((resolve, reject) => { - reject( - new ConflictException({ - success: false, - message: - ' Please Add the valid UID ,invalid group uid value was sent', - }), - ); - }); - } - - let group: DeviceGroup | null; - group = await this.deviceGroupService.findOne({ - devicegroup_uid: groupuId, - }); - if (group === null || group.buyerId != user.id) { - this.logger.error( - `Group UId is not of this buyer, invalid value was sent`, - ); - return new Promise((resolve, reject) => { - reject( - new ConflictException({ - success: false, - message: 'Group UId is not of this buyer, invalid value was sent', - }), - ); - }); - } - if (externalId != null || externalId != undefined) { - let device: DeviceDTO | null; - - device = await this.deviceService.findOne(externalId); - if (device === null) { - this.logger.error(`device not found, invalid value was sent`); - return new Promise((resolve, reject) => { - reject( - new ConflictException({ - success: false, - message: 'device not found, invalid value was sent', - }), - ); - }); - } - return await this.deviceService.getcertifieddevicedaterange( - device, - group.id, - ); - } else { - return await this.deviceService.getcertifieddevicedaterangeBygroupid( - group.id, - pagenumber, - ); - } - } - - /** - * It is POST api to create array of devices by uploading csv files with device data - * @param user is loggedIn user from request - * @param organizationId is organization unique identifier with number type to map with the respective organization - * @param fileToProcess is parsed data of uploaded csv file - * @returns {DeviceCsvFileProcessingJobsEntity} - */ - @Post('addByAdmin/process-creation-bulk-devices-csv/:organizationId') - @UseGuards(AuthGuard(['jwt', 'oauth2-client-password']), PermissionGuard) - @Permission('Write') - @ACLModules('DEVICE_BULK_MANAGEMENT_CRUDL') - @ApiResponse({ - status: HttpStatus.OK, - type: [DeviceCsvFileProcessingJobsEntity], - description: 'Returns created devices from csv', - }) - @ApiBody({ type: CSVBulkUploadDTO }) - public async processCreationBulkFromCSV( - @UserDecorator() user: ILoggedInUser, - @Param('organizationId') organizationId: number | null, - @Body() fileToProcess: CSVBulkUploadDTO, - ): Promise { - this.logger.verbose(`With in processCreationBulkFromCSV`); - if (organizationId === null || organizationId === undefined) { - this.logger.error(`User needs to have organization added`); - throw new ConflictException({ - success: false, - message: 'User needs to have organization added', - }); - } - - if (fileToProcess.fileName == undefined) { - this.logger.error(`File Not Found`); - throw new ConflictException({ - success: false, - message: 'File Not Found', - }); - } - if (!fileToProcess.fileName.endsWith('.csv')) { - this.logger.error(`Invalid file`); - throw new ConflictException({ - success: false, - message: 'Invalid file', - }); - } - - let jobCreated: any; - if (user.role === Role.ApiUser) { - const organization = - await this.organizationService.findOne(organizationId); - const orguser = await this.userService.findByEmail(organization.orgEmail); - if (organization.api_user_id != user.api_user_id) { - this.logger.error( - `The requested organization is belongs to other apiuser`, - ); - throw new BadRequestException({ - success: false, - message: 'The requested organization is belongs to other apiuser', - }); - } - - if (orguser.role != Role.OrganizationAdmin) { - this.logger.error(`Unauthorized`); - throw new UnauthorizedException({ - success: false, - message: 'Unauthorized', - }); - } - - jobCreated = await this.deviceGroupService.createCSVJobForFile( - user.id, - organizationId, - StatusCSV.Added, - fileToProcess.fileName, - user.api_user_id, - ); - } else { - jobCreated = await this.deviceGroupService.createCSVJobForFile( - user.id, - organizationId, - StatusCSV.Added, - fileToProcess.fileName, - ); - } - return jobCreated; - } -} +import { + Controller, + Get, + Post, + Put, + Patch, + Delete, + HttpStatus, + Param, + Body, + UseGuards, + ValidationPipe, + Query, + ConflictException, + HttpException, + UnauthorizedException, + BadRequestException, + Logger, +} from '@nestjs/common'; + +import { + ApiBearerAuth, + ApiNotFoundResponse, + ApiResponse, + ApiOkResponse, + ApiSecurity, + ApiTags, + ApiQuery, + ApiBody, +} from '@nestjs/swagger'; +import { AuthGuard } from '@nestjs/passport'; +import { plainToClass } from 'class-transformer'; + +import { DeviceService } from './device.service'; +import { + FilterDTO, + NewDeviceDTO, + UpdateDeviceDTO, + DeviceDTO, + DeviceGroupByDTO, + GroupedDevicesDTO, +} from './dto'; +import { CSVBulkUploadDTO } from '../device-group/dto'; +import { Role } from '../../utils/enums'; +import { RolesGuard } from '../../guards/RolesGuard'; +import { PermissionGuard } from '../../guards/PermissionGuard'; +import { ILoggedInUser } from '../../models'; +import { CodeNameDTO } from './dto/code-name.dto'; +import { ActiveUserGuard } from '../../guards'; +import { Roles } from '../user/decorators/roles.decorator'; +import { UserDecorator } from '../user/decorators/user.decorator'; +import { DeviceGroupService } from '../device-group/device-group.service'; +import { Permission } from '../permission/decorators/permission.decorator'; +import { ACLModules } from '../access-control-layer-module-service/decorator/aclModule.decorator'; +import { CountrycodeService } from '../countrycode/countrycode.service'; +import { countryCodesList } from '../../models/country-code'; +import { isValidUTCDateFormat } from '../../utils/checkForISOStringFormat'; +import { DeviceGroup } from '../device-group/device-group.entity'; +import { + DeviceCsvFileProcessingJobsEntity, + StatusCSV, +} from '../device-group/device_csv_processing_jobs.entity'; +import { Device } from './device.entity'; +import { OrganizationService } from '../organization/organization.service'; +import { UserService } from '../user/user.service'; +import { FindOneOptions } from 'typeorm'; + +/** + * It is Controller of device with the endpoints of device operations. + */ +@ApiTags('device') +@ApiBearerAuth('access-token') +@ApiSecurity('drec') +@Controller('/device') +export class DeviceController { + private readonly logger = new Logger(DeviceController.name); + + constructor( + private readonly deviceGroupService: DeviceGroupService, + private readonly deviceService: DeviceService, + private readonly organizationService: OrganizationService, + private readonly userService: UserService, + ) {} + + /** + * It is GET api to list all devices with paginatiion and fiteration by organization and filterationDto + */ + @Get() + @UseGuards(AuthGuard('jwt'), ActiveUserGuard, RolesGuard, PermissionGuard) + @Roles(Role.Admin) + @Permission('Read') + @ACLModules('DEVICE_MANAGEMENT_CRUDL') + @ApiQuery({ name: 'pagenumber', type: Number, required: false }) + @ApiQuery({ name: 'OrganizationId', type: Number, required: false }) + @ApiOkResponse({ type: [DeviceDTO], description: 'Returns all Devices' }) + async getAll( + @Query(ValidationPipe) filterDto: FilterDTO, + @Query('pagenumber') pagenumber: number | null, + @Query('OrganizationId') OrgId: number | null, + ) /*: Promise*/ { + this.logger.verbose(`With in getAll`); + return this.deviceService.find(filterDto, pagenumber, OrgId); + } + + /** + * It is GET api to list all devices for reservation + * @return {Array} return array of devices for reservation + */ + @Get('/ungrouped/buyerreservation') + @UseGuards( + AuthGuard(['jwt', 'oauth2-client-password']), + PermissionGuard, + RolesGuard, + ) + @Permission('Read') + @ACLModules('DEVICE_MANAGEMENT_CRUDL') + @Roles(Role.Buyer, Role.SubBuyer, Role.ApiUser) + @ApiOkResponse({ type: [DeviceDTO], description: 'Returns all Devices' }) + async getAllDeviceForBuyer( + @Query(ValidationPipe) filterDto: FilterDTO, + @Query('pagenumber') pagenumber: number | null, + @UserDecorator() { organizationId, api_user_id, role }: ILoggedInUser, + ): Promise { + this.logger.verbose(`With in getAllDeviceForBuyer`); + if (filterDto.organizationId) { + const organization = await this.organizationService.findOne( + filterDto.organizationId, + ); + const orguser = await this.userService.findByEmail(organization.orgEmail); + if (role === Role.ApiUser) { + if (organization.api_user_id != api_user_id) { + this.logger.error( + `The requested organization is belongs to other apiuser`, + ); + throw new UnauthorizedException({ + success: false, + message: `The requested organization is belongs to other apiuser`, + }); + } + + if ( + orguser.role === Role.OrganizationAdmin || + orguser.role === Role.DeviceOwner + ) { + this.logger.error( + `Unauthorized... The requested user is developer or device owner`, + ); + throw new UnauthorizedException({ + success: false, + message: `Unauthorized`, + }); + } + } else { + if (organizationId != organization.id) { + this.logger.error( + `The requested organization is not same as user's organization`, + ); + throw new UnauthorizedException({ + success: false, + message: `The requested organization is not same as user's organization`, + }); + } + } + } + + if (role !== Role.ApiUser) { + api_user_id = null; + } + + return this.deviceService.finddeviceForBuyer( + filterDto, + pagenumber, + api_user_id, + ); + } + + /** + * It is GET api to list all ungrouped devices with filteration + * @return {GroupedDevicesDTO} returns ungrouped devices + */ + @Get('/ungrouped') + @UseGuards(AuthGuard('jwt'), ActiveUserGuard, RolesGuard, PermissionGuard) + @Roles(Role.Admin, Role.DeviceOwner) + @Permission('Read') + @ACLModules('DEVICE_MANAGEMENT_CRUDL') + @ApiOkResponse({ + type: [GroupedDevicesDTO], + description: 'Returns all ungrouped Devices', + }) + async getAllUngrouped( + @UserDecorator() { organizationId }: ILoggedInUser, + @Query(ValidationPipe) orderFilterDto: DeviceGroupByDTO, + ): Promise { + this.logger.verbose(`With in getAllUngrouped`); + return this.deviceService.findUngrouped(organizationId, orderFilterDto); + } + + /** + * It is GET to list all device code types in dropdown + * @returns {Array} + */ + @Get('/device-type') + @ApiResponse({ + status: HttpStatus.OK, + type: [CodeNameDTO], + description: 'Returns all IREC device types', + }) + getDeviceTypes(): CodeNameDTO[] { + this.logger.verbose(`With in getDeviceTypes`); + const deviceTypes = this.deviceService.getDeviceTypes(); + + return deviceTypes.map((deviceType) => + plainToClass(CodeNameDTO, deviceType), + ); + } + + /** + * It is GET api to list all fuel types in dropdown + * @returns {Array} + */ + @Get('/fuel-type') + @ApiResponse({ + status: HttpStatus.OK, + type: [CodeNameDTO], + description: 'Returns all IREC fuel types', + }) + getFuelTypes(): CodeNameDTO[] { + this.logger.verbose(`With in getFuelTypes`); + const fuelTypes = this.deviceService.getFuelTypes(); + return fuelTypes.map((fuelType) => plainToClass(CodeNameDTO, fuelType)); + } + + /** + * It is GET api to list all my devices with filteration and pagination + * @returns {Array} + */ + @Get('/my') + @UseGuards( + AuthGuard(['jwt', 'oauth2-client-password']), + ActiveUserGuard, + PermissionGuard, + ) + @Permission('Read') + @ACLModules('DEVICE_MANAGEMENT_CRUDL') + @ApiQuery({ name: 'pagenumber', type: Number, required: false }) + @ApiResponse({ + status: HttpStatus.OK, + type: [DeviceDTO], + description: 'Returns my Devices', + }) + async getMyDevices( + @Query(ValidationPipe) filterDto: FilterDTO, + @UserDecorator() { organizationId, api_user_id, role }: ILoggedInUser, + @Query('pagenumber') pagenumber: number | null, + ) /*: Promise*/ { + this.logger.verbose(`With in getMyDevices`); + if (filterDto.country) { + filterDto.country = filterDto.country.toUpperCase(); + + if ( + filterDto.country && + typeof filterDto.country === 'string' && + filterDto.country.length === 3 + ) { + const countries = countryCodesList; + if ( + countries.find((ele) => ele.countryCode === filterDto.country) === + undefined + ) { + this.logger.error( + `Invalid countryCode, some of the valid country codes are "GBR" - "United Kingdom of Great Britain and Northern Ireland", "CAN" - "Canada" "IND" - "India", "DEU"- "Germany"`, + ); + return new Promise((resolve, reject) => { + reject( + new ConflictException({ + success: false, + message: + ' Invalid countryCode, some of the valid country codes are "GBR" - "United Kingdom of Great Britain and Northern Ireland", "CAN" - "Canada" "IND" - "India", "DEU"- "Germany"', + }), + ); + }); + } + } else { + this.logger.error( + `Invalid countryCode, some of the valid country codes are "GBR" - "United Kingdom of Great Britain and Northern Ireland", "CAN" - "Canada" "IND" - "India", "DEU"- "Germany"`, + ); + return new Promise((resolve, reject) => { + reject( + new ConflictException({ + success: false, + message: + ' Invalid countryCode, some of the valid country codes are "GBR" - "United Kingdom of Great Britain and Northern Ireland", "CAN" - "Canada" "IND" - "India", "DEU"- "Germany"', + }), + ); + }); + } + } + if (filterDto.organizationId) { + if (role === Role.ApiUser) { + const organization = await this.organizationService.findOne( + filterDto.organizationId, + ); + const orguser = await this.userService.findByEmail( + organization.orgEmail, + ); + if (organization.api_user_id != api_user_id) { + this.logger.error( + `The organization Id in param is belongs to other apiuser`, + ); + throw new UnauthorizedException({ + success: false, + message: 'The organization Id in param is belongs to other apiuser', + }); + } else { + if (orguser.role != Role.OrganizationAdmin) { + this.logger.error(`Unauthorized`); + throw new UnauthorizedException({ + success: false, + message: 'Unauthorized', + }); + } + } + } else { + if (filterDto.organizationId != organizationId) { + this.logger.error( + `The organization Id in param should be same as user's organization`, + ); + throw new UnauthorizedException({ + success: false, + message: `The organization Id in param should be same as user's organization`, + }); + } + } + + organizationId = filterDto.organizationId; + } + + this.logger.log('In devices before calling service'); + return await this.deviceService.getOrganizationDevices( + organizationId, + api_user_id, + role, + filterDto, + pagenumber, + ); + } + + /** + * It is GET api to fetch an device by the deviceId in param + * @param id is deviceId in type number + * @returns {DeviceDTO | null} DeviceDto for success response and null when there is no device found by the id + */ + @Get('/:id') + @UseGuards( + AuthGuard(['jwt', 'oauth2-client-password']), + ActiveUserGuard, + PermissionGuard, + ) + @Permission('Read') + @ACLModules('DEVICE_MANAGEMENT_CRUDL') + @ApiQuery({ name: 'apiUserId', type: String, required: false }) + @ApiQuery({ name: 'organizationId', type: Number, required: false }) + @ApiOkResponse({ type: DeviceDTO, description: 'Returns a Device' }) + @ApiNotFoundResponse({ + description: `The device with the code doesn't exist`, + }) + async get( + @Param('id') id: number, + @Query('apiUserId') api_user_id: string | null, + @Query('organizationId') organizationId: number | null, + ): Promise { + this.logger.verbose(`With in get`); + let devicedata: Device; + if (api_user_id && organizationId) { + devicedata = await this.deviceService.findOne(id, { + api_user_id: api_user_id, + organizationId: organizationId, + } as FindOneOptions); + } else { + devicedata = await this.deviceService.findOne(id); + } + devicedata.externalId = devicedata.developerExternalId; + delete devicedata['developerExternalId']; + return devicedata; + } + + /** + * It is GET api to fetch an device by externalId in param + * @param id is externalId in device + * @param param1 + * @returns {DeviceDTO | null} DeviceDto for success response and null when there is no device found by the id + */ + @Get('externalId/:id') + @UseGuards(AuthGuard('jwt'), PermissionGuard) + @Permission('Read') + @ACLModules('DEVICE_MANAGEMENT_CRUDL') + @ApiOkResponse({ type: DeviceDTO, description: 'Returns a Device' }) + @ApiNotFoundResponse({ + description: `The device with the code doesn't exist`, + }) + async getByExternalId( + @Param('id') id: string, + @UserDecorator() { organizationId }: ILoggedInUser, + ): Promise { + this.logger.verbose(`With in getByExternalId`); + const devicedata = await this.deviceService.findDeviceByDeveloperExternalId( + id, + organizationId, + ); + devicedata.externalId = devicedata.developerExternalId; + delete devicedata['developerExternalId']; + return devicedata; + } + + /** + * It is POST api to create an device + * @param param0 It is organizationId from user at request + * @param deviceToRegister It is body payload to create device + * @returns {DeviceDTO} + */ + @Post() + @UseGuards(AuthGuard(['jwt', 'oauth2-client-password']), PermissionGuard) + @Permission('Write') + @ACLModules('DEVICE_MANAGEMENT_CRUDL') + @ApiResponse({ + status: HttpStatus.OK, + type: NewDeviceDTO, + description: 'Returns a new created Device id', + }) + public async create( + @UserDecorator() { organizationId, role, api_user_id }: ILoggedInUser, + @Body() deviceToRegister: NewDeviceDTO, + ): Promise { + this.logger.verbose(`With in create`); + deviceToRegister.externalId = deviceToRegister.externalId.trim(); + if (deviceToRegister.externalId.trim() === '') { + this.logger.error(`externalId should not be empty`); + return new Promise((resolve, reject) => { + reject( + new ConflictException({ + success: false, + message: `externalId should not be empty`, + }), + ); + }); + } + + if (!isValidUTCDateFormat(deviceToRegister.commissioningDate)) { + this.logger.error( + `Invalid commissioning date, valid format is YYYY-MM-DDThh:mm:ss.millisecondsZ example 2022-10-18T11:35:27.640Z`, + ); + return new Promise((resolve, reject) => { + reject( + new ConflictException({ + success: false, + message: + ' Invalid commissioning date, valid format is YYYY-MM-DDThh:mm:ss.millisecondsZ example 2022-10-18T11:35:27.640Z ', + }), + ); + }); + } + if ( + new Date(deviceToRegister.commissioningDate).getTime() > + new Date().getTime() + ) { + this.logger.error( + `Invalid commissioning date, commissioning is greater than current date`, + ); + return new Promise((resolve, reject) => { + reject( + new ConflictException({ + success: false, + message: ` Invalid commissioning date, commissioning is greater than current date`, + }), + ); + }); + } + if (deviceToRegister['groupId'] === 0 || deviceToRegister['groupId']) { + deviceToRegister['groupId'] = null; + } + deviceToRegister.countryCode = deviceToRegister.countryCode.toUpperCase(); + if ( + deviceToRegister.countryCode && + typeof deviceToRegister.countryCode === 'string' && + deviceToRegister.countryCode.length === 3 + ) { + const countries = countryCodesList; + if ( + countries.find( + (ele) => ele.countryCode === deviceToRegister.countryCode, + ) === undefined + ) { + this.logger.error( + `Invalid countryCode, some of the valid country codes are "GBR" - "United Kingdom of Great Britain and Northern Ireland", "CAN" - "Canada" "IND" - "India", "DEU"- "Germany"`, + ); + return new Promise((resolve, reject) => { + reject( + new ConflictException({ + success: false, + message: + ' Invalid countryCode, some of the valid country codes are "GBR" - "United Kingdom of Great Britain and Northern Ireland", "CAN" - "Canada" "IND" - "India", "DEU"- "Germany"', + }), + ); + }); + } + } else { + this.logger.error( + `Invalid countryCode, some of the valid country codes are "GBR" - "United Kingdom of Great Britain and Northern Ireland", "CAN" - "Canada" "IND" - "India", "DEU"- "Germany"`, + ); + return new Promise((resolve, reject) => { + reject( + new ConflictException({ + success: false, + message: + ' Invalid countryCode, some of the valid country codes are "GBR" - "United Kingdom of Great Britain and Northern Ireland", "CAN" - "Canada" "IND" - "India", "DEU"- "Germany"', + }), + ); + }); + } + if (isNaN(parseFloat(deviceToRegister.capacity.toString()))) { + this.logger.error(`Invalid Capacity or energy Storage Capacity`); + return new Promise((resolve, reject) => { + reject( + new ConflictException({ + success: false, + message: ' Invalid Capacity or energy Storage Capacity', + }), + ); + }); + } + if ( + deviceToRegister.capacity <= 0 || + deviceToRegister.energyStorageCapacity < 0 + ) { + this.logger.error( + `Invalid Capacity or energy Storage Capacity, it should be greater than 0`, + ); + return new Promise((resolve, reject) => { + reject( + new ConflictException({ + success: false, + message: + ' Invalid Capacity or energy Storage Capacity, it should be greater than 0', + }), + ); + }); + } + if ( + deviceToRegister.version === null || + deviceToRegister.version === undefined || + deviceToRegister.version === '0' + ) { + deviceToRegister.version = '1.0'; + } + if (role === Role.Admin || role === Role.ApiUser) { + if (deviceToRegister.organizationId) { + this.logger.debug('Line No: 314'); + organizationId = deviceToRegister.organizationId; + } else { + this.logger.error( + `Organization id is required,please add your developer's Organization`, + ); + return new Promise((resolve, reject) => { + reject( + new ConflictException({ + success: false, + message: `Organization id is required,please add your developer's Organization `, + }), + ); + }); + } + } + return await this.deviceService.register( + organizationId, + deviceToRegister, + api_user_id, + role, + ); + } + + /** + * It is PATCH api to update an device by externalId + * @param user is loggedin user from user at request + * @param externalId is unique external id in device entity + * @param deviceToUpdate is body payload to update an device + * @returns {DeviceDTO} + */ + @Patch('/:externalId') + @UseGuards(AuthGuard('jwt'), PermissionGuard) + @Permission('Update') + @ACLModules('DEVICE_MANAGEMENT_CRUDL') + @ApiResponse({ + status: HttpStatus.OK, + type: UpdateDeviceDTO, + description: 'Returns an updated Device', + }) + @ApiNotFoundResponse({ description: `No device found` }) + public async update( + @UserDecorator() user: ILoggedInUser, + @Param('externalId') externalId: string, + @Body() deviceToUpdate: UpdateDeviceDTO, + ): Promise { + this.logger.verbose(`With in update`); + + if (deviceToUpdate.externalId) { + deviceToUpdate.externalId = deviceToUpdate.externalId.trim(); + if (deviceToUpdate.externalId === '') { + this.logger.error(`externalId should not be empty`); + return new Promise((resolve, reject) => { + reject( + new ConflictException({ + success: false, + message: `externalId should not be empty`, + }), + ); + }); + } + + const checkexternalid = + await this.deviceService.findDeviceByDeveloperExternalId( + deviceToUpdate.externalId, + user.organizationId, + ); + if ( + checkexternalid != undefined && + checkexternalid.developerExternalId === externalId.trim() + ) { + this.logger.log('Line No: 236'); + return new Promise((resolve, reject) => { + reject( + new ConflictException({ + success: false, + message: `ExternalId already exist in this organization, can't update with same external id ${deviceToUpdate.externalId}`, + }), + ); + }); + } + } + + if (deviceToUpdate.countryCode != undefined) { + deviceToUpdate.countryCode = deviceToUpdate.countryCode.toUpperCase(); + if ( + deviceToUpdate.countryCode && + typeof deviceToUpdate.countryCode === 'string' && + deviceToUpdate.countryCode.length === 3 + ) { + const countries = countryCodesList; + if ( + countries.find( + (ele) => ele.countryCode === deviceToUpdate.countryCode, + ) === undefined + ) { + this.logger.error( + `Invalid countryCode, some of the valid country codes are "GBR" - "United Kingdom of Great Britain and Northern Ireland", "CAN" - "Canada" "IND" - "India", "DEU"- "Germany"`, + ); + return new Promise((resolve, reject) => { + reject( + new ConflictException({ + success: false, + message: + ' Invalid countryCode, some of the valid country codes are "GBR" - "United Kingdom of Great Britain and Northern Ireland", "CAN" - "Canada" "IND" - "India", "DEU"- "Germany"', + }), + ); + }); + } + } else { + this.logger.error( + `Invalid countryCode, some of the valid country codes are "GBR" - "United Kingdom of Great Britain and Northern Ireland", "CAN" - "Canada" "IND" - "India", "DEU"- "Germany"`, + ); + return new Promise((resolve, reject) => { + reject( + new ConflictException({ + success: false, + message: + ' Invalid countryCode, some of the valid country codes are "GBR" - "United Kingdom of Great Britain and Northern Ireland", "CAN" - "Canada" "IND" - "India", "DEU"- "Germany"', + }), + ); + }); + } + } + + if (deviceToUpdate.capacity <= 0) { + this.logger.error(`Invalid Capacity, it should be greater than 0`); + return new Promise((resolve, reject) => { + reject( + new ConflictException({ + success: false, + message: ' Invalid Capacity, it should be greater than 0', + }), + ); + }); + } + if ( + !isValidUTCDateFormat(deviceToUpdate.commissioningDate) && + deviceToUpdate.commissioningDate !== undefined + ) { + this.logger.error( + `Invalid commissioning date, valid format is YYYY-MM-DDThh:mm:ss.millisecondsZ example 2022-10-18T11:35:27.640Z`, + ); + return new Promise((resolve, reject) => { + reject( + new ConflictException({ + success: false, + message: + ' Invalid commissioning date, valid format is YYYY-MM-DDThh:mm:ss.millisecondsZ example 2022-10-18T11:35:27.640Z ', + }), + ); + }); + } + if ( + new Date(deviceToUpdate.commissioningDate).getTime() > + new Date().getTime() + ) { + this.logger.error( + `Invalid commissioning date, commissioning is greater than current date`, + ); + return new Promise((resolve, reject) => { + reject( + new ConflictException({ + success: false, + message: ` Invalid commissioning date, commissioning is greater than current date`, + }), + ); + }); + } + + if (deviceToUpdate.commissioningDate) { + const checkexternalid = + await this.deviceService.findDeviceByDeveloperExternalId( + externalId, + user.organizationId, + ); + const noOfHistRead: number = + await this.deviceService.getNumberOfHistReads( + checkexternalid.externalId, + ); + const noOfOnGoingRead: number = + await this.deviceService.getNumberOfOngReads( + checkexternalid.externalId, + checkexternalid.createdAt, + ); + + if ( + deviceToUpdate.commissioningDate != checkexternalid.commissioningDate + ) { + if (noOfHistRead > 0 || noOfOnGoingRead > 0) { + this.logger.error( + `Commissioning date cannot be changed due to existing meter reads available for ${checkexternalid.developerExternalId}`, + ); + throw new ConflictException({ + success: false, + message: ` Commissioning date cannot be changed due to existing meter reads available for ${checkexternalid.developerExternalId}`, + }); + } + + if ( + new Date(deviceToUpdate.commissioningDate).getTime() > + new Date(checkexternalid.createdAt).getTime() + ) { + this.logger.error( + `Invalid commissioning date, commissioning is greater than device onboarding date`, + ); + throw new ConflictException({ + success: false, + message: `Invalid commissioning date, commissioning is greater than device onboarding date`, + }); + } + } + } + return await this.deviceService.update( + user.organizationId, + user.role, + externalId, + deviceToUpdate, + ); + } + + /** + * It is DELETE api to delete an device by id + * @param id is deviceId + * @param param1 is getting organizationId and user role from user request + * @returns {any} + */ + @Delete('/:id') + @UseGuards(AuthGuard('jwt'), RolesGuard, PermissionGuard) + @Permission('Delete') + @ACLModules('DEVICE_MANAGEMENT_CRUDL') + @Roles(Role.OrganizationAdmin, Role.Admin) + @ApiResponse({ + status: HttpStatus.OK, + description: 'Remove device group', + }) + @ApiNotFoundResponse({ description: `No device group found` }) + public async remove( + @Param('id') id: number, + @UserDecorator() { organizationId, role }: ILoggedInUser, + ): Promise { + this.logger.verbose(`With in remove`); + const checkisungroup = this.deviceService.findUngroupedById(id); + if (checkisungroup) { + let fitlerop: any; + if (role === 'Admin') { + fitlerop = { + groupId: null, + }; + } else { + fitlerop = { + groupId: null, + organizationId: organizationId, + }; + } + return await this.deviceService.remove(id, fitlerop); + } + } + + /** + * It is GET api to list all total amount of reads by each devices grouped by organization + * @param param0 is getting organizationId from user request. + * @returns {Array} + */ + @Get('/my/totalamountread') + @UseGuards(AuthGuard('jwt'), ActiveUserGuard, PermissionGuard) + @Permission('Read') + @ACLModules('DEVICE_MANAGEMENT_CRUDL') + @ApiResponse({ + status: HttpStatus.OK, + type: [DeviceDTO], + description: 'Returns my Devices', + }) + async getMyDevicesTotal( + @UserDecorator() { organizationId }: ILoggedInUser, + ): Promise { + this.logger.verbose(`Wth in getMyDevicesTotal`); + return await this.deviceService.getOrganizationDevicesTotal(organizationId); + } + + /** + * It is PUT api tp update the device onboarding date by deviceId + * @param param0 is getting organizationId from user request + * @param deviceId is deviceId from device unique identifier + * @param givenDate is new onboarding date to be updated. + * @returns {} + */ + @Put('/my/deviceOnBoardingDate') + @UseGuards(AuthGuard('jwt'), PermissionGuard) + @Permission('Write') + @ACLModules('DEVICE_MANAGEMENT_CRUDL') + @ApiResponse({ + status: HttpStatus.OK, + description: "change the device's OnBoarding date", + }) + @ApiQuery({ name: 'deviceId', description: 'Device Id' }) + @ApiQuery({ + name: 'givenDate', + description: 'Update the OnBoarding date', + type: Date, + }) + async changeOnBoardingDate( + @UserDecorator() { organizationId }: ILoggedInUser, + @Query('deviceId') deviceId, + @Query('givenDate') givenDate, + ) { + this.logger.verbose(`With in changeOnBoardingDate`); + if (process.env.MODE != 'dev') { + this.logger.error(`Currently not in dev environment`); + throw new HttpException('Currently not in dev environment', 400); + } + const device: DeviceDTO | null = + await this.deviceService.findDeviceByDeveloperExternalId( + deviceId, + organizationId, + ); + this.logger.debug( + 'THE DEVICE FROM ExTERNALID IS::::::::::::' + device.externalId, + ); + if (!device) { + this.logger.error(`Device dosen't exist`); + throw new HttpException("Device dosen't exist", 400); + } + const deviceExternalId = device.externalId; + const deviceOnboardedDate = device.createdAt; + return this.deviceService.changeDeviceCreatedAt( + deviceExternalId, + deviceOnboardedDate, + givenDate, + ); + } + + /** + * It is GET api to list all devices with auto complete + * @param param0 is getting organizationId from user request + * @param externalId is unique identoifier of an device + * @returns {} + */ + @Get('/my/autocomplete') + @UseGuards(AuthGuard('jwt'), ActiveUserGuard, PermissionGuard) + @Permission('Read') + @ACLModules('DEVICE_MANAGEMENT_CRUDL') + @ApiResponse({ + status: HttpStatus.OK, + description: 'Returns Auto-Complete', + }) + @ApiQuery({ name: 'externalId', description: 'externalId', type: String }) + async autocomplete( + @UserDecorator() { organizationId }: ILoggedInUser, + @Query('externalId') externalId: string, + ) { + this.logger.verbose(`With in autocomplete`); + return await this.deviceService.atto(organizationId, externalId); + } + + /** + * It is GET api to fetch the certified device records with in the range of date + * @param user is loggedIn user at request + * @param externalId is unique identifier of device + * @param groupuId + * @returns {any} + */ + @Get('/certifiedlog/first&lastdate') + @UseGuards(AuthGuard('jwt'), PermissionGuard) + @Permission('Read') + @ACLModules('DEVICE_MANAGEMENT_CRUDL') + @ApiQuery({ name: 'externalId', type: Number, required: false }) + @ApiQuery({ name: 'pagenumber', type: Number, required: false }) + @ApiResponse({ + status: HttpStatus.OK, + description: 'Returns Certified log date rang of Device', + }) + async certifiedlogdaterang( + @UserDecorator() user: ILoggedInUser, + @Query('groupUid') groupuId: string, + @Query('pagenumber') pagenumber: number, + @Query('externalId') externalId?: number, + ): Promise { + this.logger.verbose(`With in certifiedlogdaterang`); + const regexExp = + /^[0-9a-fA-F]{8}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{12}$/; + if (groupuId === null || !regexExp.test(groupuId)) { + this.logger.error( + `Please Add the valid UID ,invalid group uid value was sent`, + ); + return new Promise((resolve, reject) => { + reject( + new ConflictException({ + success: false, + message: + ' Please Add the valid UID ,invalid group uid value was sent', + }), + ); + }); + } + + let group: DeviceGroup | null; + group = await this.deviceGroupService.findOne({ + devicegroup_uid: groupuId, + }); + if (group === null || group.buyerId != user.id) { + this.logger.error( + `Group UId is not of this buyer, invalid value was sent`, + ); + return new Promise((resolve, reject) => { + reject( + new ConflictException({ + success: false, + message: 'Group UId is not of this buyer, invalid value was sent', + }), + ); + }); + } + if (externalId != null || externalId != undefined) { + let device: DeviceDTO | null; + + device = await this.deviceService.findOne(externalId); + if (device === null) { + this.logger.error(`device not found, invalid value was sent`); + return new Promise((resolve, reject) => { + reject( + new ConflictException({ + success: false, + message: 'device not found, invalid value was sent', + }), + ); + }); + } + return await this.deviceService.getcertifieddevicedaterange( + device, + group.id, + ); + } else { + return await this.deviceService.getcertifieddevicedaterangeBygroupid( + group.id, + pagenumber, + ); + } + } + + /** + * It is POST api to create array of devices by uploading csv files with device data + * @param user is loggedIn user from request + * @param organizationId is organization unique identifier with number type to map with the respective organization + * @param fileToProcess is parsed data of uploaded csv file + * @returns {DeviceCsvFileProcessingJobsEntity} + */ + @Post('addByAdmin/process-creation-bulk-devices-csv/:organizationId') + @UseGuards(AuthGuard(['jwt', 'oauth2-client-password']), PermissionGuard) + @Permission('Write') + @ACLModules('DEVICE_BULK_MANAGEMENT_CRUDL') + @ApiResponse({ + status: HttpStatus.OK, + type: [DeviceCsvFileProcessingJobsEntity], + description: 'Returns created devices from csv', + }) + @ApiBody({ type: CSVBulkUploadDTO }) + public async processCreationBulkFromCSV( + @UserDecorator() user: ILoggedInUser, + @Param('organizationId') organizationId: number | null, + @Body() fileToProcess: CSVBulkUploadDTO, + ): Promise { + this.logger.verbose(`With in processCreationBulkFromCSV`); + if (organizationId === null || organizationId === undefined) { + this.logger.error(`User needs to have organization added`); + throw new ConflictException({ + success: false, + message: 'User needs to have organization added', + }); + } + + if (fileToProcess.fileName == undefined) { + this.logger.error(`File Not Found`); + throw new ConflictException({ + success: false, + message: 'File Not Found', + }); + } + if (!fileToProcess.fileName.endsWith('.csv')) { + this.logger.error(`Invalid file`); + throw new ConflictException({ + success: false, + message: 'Invalid file', + }); + } + + let jobCreated: any; + if (user.role === Role.ApiUser) { + const organization = + await this.organizationService.findOne(organizationId); + const orguser = await this.userService.findByEmail(organization.orgEmail); + if (organization.api_user_id != user.api_user_id) { + this.logger.error( + `The requested organization is belongs to other apiuser`, + ); + throw new BadRequestException({ + success: false, + message: 'The requested organization is belongs to other apiuser', + }); + } + + if (orguser.role != Role.OrganizationAdmin) { + this.logger.error(`Unauthorized`); + throw new UnauthorizedException({ + success: false, + message: 'Unauthorized', + }); + } + + jobCreated = await this.deviceGroupService.createCSVJobForFile( + user.id, + organizationId, + StatusCSV.Added, + fileToProcess.fileName, + user.api_user_id, + ); + } else { + jobCreated = await this.deviceGroupService.createCSVJobForFile( + user.id, + organizationId, + StatusCSV.Added, + fileToProcess.fileName, + ); + } + return jobCreated; + } +} diff --git a/apps/drec-api/src/pods/device/dto/filter.dto.ts b/apps/drec-api/src/pods/device/dto/filter.dto.ts index 4e13559a7..060f8112b 100755 --- a/apps/drec-api/src/pods/device/dto/filter.dto.ts +++ b/apps/drec-api/src/pods/device/dto/filter.dto.ts @@ -99,6 +99,8 @@ export class FilterDTO { isArray: true, }) SDGBenefits?: string[] | undefined; + + organizationId?: number; } export class BuyerDeviceFilterDTO { @IsOptional() diff --git a/apps/drec-api/src/pods/device/dto/new-device.dto.ts b/apps/drec-api/src/pods/device/dto/new-device.dto.ts index 112f3124f..e132146ab 100755 --- a/apps/drec-api/src/pods/device/dto/new-device.dto.ts +++ b/apps/drec-api/src/pods/device/dto/new-device.dto.ts @@ -197,4 +197,9 @@ export class NewDeviceDTO @IsString() @IsOptional() version = '1.0'; + + @ApiProperty() + @IsOptional() + @IsNumber() + organizationId?: number | null; } From 3ee2f45645b66584c4e583af5a2bfdda433f8ed1 Mon Sep 17 00:00:00 2001 From: Aish1990 Date: Fri, 26 Apr 2024 00:17:00 +0530 Subject: [PATCH 10/89] Removed ts-ignore from Device Service --- .../src/pods/device/device.service.ts | 20 +++---------------- 1 file changed, 3 insertions(+), 17 deletions(-) diff --git a/apps/drec-api/src/pods/device/device.service.ts b/apps/drec-api/src/pods/device/device.service.ts index 91265687d..5641cd17a 100755 --- a/apps/drec-api/src/pods/device/device.service.ts +++ b/apps/drec-api/src/pods/device/device.service.ts @@ -149,7 +149,6 @@ export class DeviceService { const query = await this.getFilteredQuery(filterDto); let where: any = query.where; if (role == Role.ApiUser) { - //@ts-ignore if (filterDto.organizationId) { where = { ...where, organizationId }; } else { @@ -554,8 +553,7 @@ export class DeviceService { newDevice.developerExternalId = newDevice.externalId; newDevice.externalId = uuid(); - // @ts-ignore - if (newDevice.SDGBenefits === 0 || newDevice.SDGBenefits === 1) { + if (newDevice.SDGBenefits && (newDevice.SDGBenefits.includes('0') || newDevice.SDGBenefits.includes('1'))) { newDevice.SDGBenefits = []; } else if (Array.isArray(newDevice.SDGBenefits)) { newDevice.SDGBenefits.forEach((sdgbname: string, index: number) => { @@ -634,10 +632,8 @@ export class DeviceService { const sdgbbenifitslist = SDGBenefits; if ( - // @ts-ignore ts(2367) - updateDeviceDTO.SDGBenefits === 0 || - // @ts-ignore ts(2367) - updateDeviceDTO.SDGBenefits === 1 + updateDeviceDTO.SDGBenefits.includes('0') || + updateDeviceDTO.SDGBenefits.includes('1') ) { updateDeviceDTO.SDGBenefits = []; } else if (Array.isArray(updateDeviceDTO.SDGBenefits)) { @@ -727,7 +723,6 @@ export class DeviceService { const deviceKey: DeviceKey = DeviceSortPropertyMapper[ order ] as DeviceKey; - // @ts-ignore return item[deviceKey]; } }), @@ -774,7 +769,6 @@ export class DeviceService { if (deviceKey === 'deviceTypeCode') { return getDeviceTypeFromCode(devices[0][deviceKey]); } - // @ts-ignore return devices[0][deviceKey]; })}`; return name; @@ -795,14 +789,10 @@ export class DeviceService { if (orgId != null || orgId != undefined) { where.organizationId = orgId; } - //@ts-ignore else if ( - // @ts-ignore ts(2339) filter.organizationId != null && - // @ts-ignore ts(2339) filter.organizationId != undefined ) { - //@ts-ignore where.organizationId = filter.organizationId; } if (filter.start_date != null && filter.end_date === undefined) { @@ -1174,14 +1164,10 @@ export class DeviceService { })); } get dbReader() { - // @ts-ignore const url = process.env.INFLUXDB_URL; - // @ts-ignore const token = process.env.INFLUXDB_TOKEN; - // @ts-ignore const org = process.env.INFLUXDB_ORG; - // @ts-ignore return new InfluxDB({ url, token }).getQueryApi(org); } From 309f537da0c053bb950829a3f78ea8a0f6132e01 Mon Sep 17 00:00:00 2001 From: Aish1990 Date: Fri, 26 Apr 2024 00:20:36 +0530 Subject: [PATCH 11/89] Removed ts-ignore from Buyer Reservation Controller --- .../src/pods/device-group/buyer-reservation.controller.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/drec-api/src/pods/device-group/buyer-reservation.controller.ts b/apps/drec-api/src/pods/device-group/buyer-reservation.controller.ts index 4e8b23b11..1b20d55c4 100644 --- a/apps/drec-api/src/pods/device-group/buyer-reservation.controller.ts +++ b/apps/drec-api/src/pods/device-group/buyer-reservation.controller.ts @@ -553,7 +553,6 @@ export class BuyerReservationController { organizationId, deviceGroupToRegister, user.id, - // @ts-ignore process.env.DREC_BLOCKCHAIN_ADDRESS, ); } From 2238b3e419a7f8a6b78d255f105d97553f44b8b3 Mon Sep 17 00:00:00 2001 From: Aish1990 Date: Mon, 29 Apr 2024 20:27:04 +0530 Subject: [PATCH 12/89] Removed ts-ignore from deviceGroup Service --- .../pods/device-group/device-group.service.ts | 56 ++++++++----------- .../device_csv_processing_jobs.entity.ts | 4 ++ .../src/pods/device/dto/new-device.dto.ts | 5 ++ 3 files changed, 33 insertions(+), 32 deletions(-) diff --git a/apps/drec-api/src/pods/device-group/device-group.service.ts b/apps/drec-api/src/pods/device-group/device-group.service.ts index 86caf3500..14b3eee51 100755 --- a/apps/drec-api/src/pods/device-group/device-group.service.ts +++ b/apps/drec-api/src/pods/device-group/device-group.service.ts @@ -19,6 +19,7 @@ import { Between, Brackets, SelectQueryBuilder, + UpdateResult, } from 'typeorm'; import { DeviceService } from '../device/device.service'; import { @@ -39,6 +40,8 @@ import { DeviceDescription, IDevice, BuyerReservationCertificateGenerationFrequency, + IFullOrganization, + IUser, } from '../../models'; import { DeviceDTO, NewDeviceDTO, FilterDTO } from '../device/dto'; import { @@ -49,6 +52,8 @@ import { FuelCode, DevicetypeCode, Role, + OrganizationStatus, + UserStatus, } from '../../utils/enums'; import moment from 'moment'; @@ -796,7 +801,6 @@ export class DeviceGroupService { const organization = await this.organizationService.findOne( csvjob.organizationId, ); - // @ts-ignore csvjob.organization = { name: organization.name, }; @@ -848,7 +852,6 @@ export class DeviceGroupService { const organization = await this.organizationService.findOne( csvjob.organizationId, ); - // @ts-ignore csvjob.organization = { name: organization.name, }; @@ -1369,7 +1372,6 @@ export class DeviceGroupService { ); if (existingDevices && existingDevices.length > 0) { - // @ts-ignore existingDevices.forEach((ele) => existingDeviceIds.push(ele?.developerExternalId), ); @@ -1545,7 +1547,6 @@ export class DeviceGroupService { fuelCode: fuelCode, countryCode: countryCode, deviceTypeCodes: deviceTypeCodes, - // @ts-ignore offTakers: offTakers, gridInterconnection, aggregatedCapacity, @@ -1618,10 +1619,19 @@ export class DeviceGroupService { status: StatusCSV, ): Promise { this.logger.verbose(`With in updateJobStatus`); - // @ts-ignore - return await this.repositoyCSVJobProcessing.update(jobId, { - status: status, + const updateResult: UpdateResult = await this.repositoyCSVJobProcessing.update({ jobId: jobId }, + { status: status }, + ); + + if (updateResult.affected === 0) { + throw new Error(`No job found with ID ${jobId}`); + } + + const updatedJob: DeviceCsvFileProcessingJobsEntity = await this.repositoyCSVJobProcessing.findOne({ + where: { jobId: jobId } }); + + return updatedJob; } @Cron(CronExpression.EVERY_30_SECONDS) @@ -1637,11 +1647,9 @@ export class DeviceGroupService { return; } - const data = new LoggedInUser({ - id: filesAddedForProcessing.userId, - // @ts-ignore - organization: { id: filesAddedForProcessing.organizationId }, - }); + const user = await this.userService.findById(filesAddedForProcessing.userId); + + const data = new LoggedInUser(user); data.id = filesAddedForProcessing.userId; data.organizationId = filesAddedForProcessing.organizationId; const response = await this.fileService.GetuploadS3( @@ -1722,24 +1730,17 @@ export class DeviceGroupService { if (key === 'SDGBenefits' || key === 'version') { continue; } - // @ts-ignore if (typeof dataKeyForValidation[key] === 'string') { - // @ts-ignore dataToStore[key] = data[key]; } - // @ts-ignore else if (typeof dataKeyForValidation[key] === 'boolean') { - // @ts-ignore dataToStore[key] = data[key].toLowerCase() === 'true' ? true : false; } - // @ts-ignore else if (typeof dataKeyForValidation[key] === 'number') { - // @ts-ignore dataToStore[key] = Number.isNaN(data[key]) ? 0 : parseFloat(data[key]); - // @ts-ignore if (key == 'yieldValue' && dataToStore[key] === 0) { dataToStore[key] = 2000; } @@ -1748,13 +1749,11 @@ export class DeviceGroupService { const yieldByCountryCode = await this.yieldConfigService.findByCountryCode(data.countryCode); if (yieldByCountryCode) { - // @ts-ignore dataToStore.yieldValue = yieldByCountryCode.yieldValue; } } } for (const key in dataToStore) { - // @ts-ignore dataToStore[key] === '' ? (dataToStore[key] = null) : ''; } records.push(dataToStore); @@ -2004,15 +2003,12 @@ export class DeviceGroupService { ); devicesRegistered - // @ts-ignore ts(2339) - .filter((ele) => ele.isError === undefined) + .filter((ele) => (ele as any).isError === undefined) .forEach((ele) => { successfullyAddedRowsAndExternalIds.push({ - // @ts-ignore ts(2339) - externalId: ele.externalId, + externalId: (ele as any).externalId, rowNumber: records.findIndex( - // @ts-ignore ts(2339) - (recEle) => recEle.developerExternalId === ele.externalId, + (recEle) => recEle.developerExternalId === (ele as any).externalId, ), }); }); @@ -2103,12 +2099,10 @@ export class DeviceGroupService { // directly the value is stored for (const j in headers) { if (properties[j].includes(', ')) { - // @ts-ignore obj[headers[j]] = properties[j] .split(', ') .map((item) => item.trim()); } else { - // @ts-ignore obj[headers[j]] = properties[j]; } } @@ -2186,9 +2180,8 @@ export class DeviceGroupService { deviceGroupIssueNextDateDTO = await this.getGroupiCertificateIssueDate({ groupId: groupId, }); - // @ts-ignore - this.endReservation(groupId, group, deviceGroupIssueNextDateDTO); + this.endReservation(groupId, group as DeviceGroup, deviceGroupIssueNextDateDTO); return; } } @@ -3004,7 +2997,6 @@ export class DeviceGroupService { const organization = await this.organizationService.findOne( csvjob.organizationId, ); - // @ts-ignore csvjob.organization = { name: organization.name, }; diff --git a/apps/drec-api/src/pods/device-group/device_csv_processing_jobs.entity.ts b/apps/drec-api/src/pods/device-group/device_csv_processing_jobs.entity.ts index 2b27b06d4..74096ae0d 100755 --- a/apps/drec-api/src/pods/device-group/device_csv_processing_jobs.entity.ts +++ b/apps/drec-api/src/pods/device-group/device_csv_processing_jobs.entity.ts @@ -38,6 +38,10 @@ export class DeviceCsvFileProcessingJobsEntity extends ExtendedBaseEntity { @IsNumber() organizationId: number; + organization?: { + name: string; + }; + @Column() @IsEnum(StatusCSV) status: StatusCSV; diff --git a/apps/drec-api/src/pods/device/dto/new-device.dto.ts b/apps/drec-api/src/pods/device/dto/new-device.dto.ts index e132146ab..9192808ba 100755 --- a/apps/drec-api/src/pods/device/dto/new-device.dto.ts +++ b/apps/drec-api/src/pods/device/dto/new-device.dto.ts @@ -202,4 +202,9 @@ export class NewDeviceDTO @IsOptional() @IsNumber() organizationId?: number | null; + + @ApiProperty() + @IsOptional() + @IsNumber() + yieldValue?: number | null; } From 6372f4beac832304ae6dba6e31fe82ee0413f54c Mon Sep 17 00:00:00 2001 From: Aish1990 Date: Mon, 29 Apr 2024 22:34:56 +0530 Subject: [PATCH 13/89] Removed ts-ignore from email-cnf Service, invitation Service, drec-issuer controller, issuer Service, organization controller, permission Service, create-user Dto, Oauth_client Service --- .../pods/email-confirmation/email-confirmation.service.ts | 1 - apps/drec-api/src/pods/invitation/invitation.service.ts | 3 +-- apps/drec-api/src/pods/issuer/drec-issuer.controller.ts | 1 - apps/drec-api/src/pods/issuer/issuer.service.ts | 6 ++---- .../src/pods/organization/organization.controller.ts | 1 - apps/drec-api/src/pods/permission/permission.service.ts | 2 -- apps/drec-api/src/pods/user/dto/create-user.dto.ts | 3 +++ apps/drec-api/src/pods/user/oauth_client.service.ts | 1 - 8 files changed, 6 insertions(+), 12 deletions(-) diff --git a/apps/drec-api/src/pods/email-confirmation/email-confirmation.service.ts b/apps/drec-api/src/pods/email-confirmation/email-confirmation.service.ts index cceb21409..30bc093f9 100755 --- a/apps/drec-api/src/pods/email-confirmation/email-confirmation.service.ts +++ b/apps/drec-api/src/pods/email-confirmation/email-confirmation.service.ts @@ -37,7 +37,6 @@ export class EmailConfirmationService { public async create(user: User): Promise { this.logger.verbose(`With in create`); - // @ts-ignore if ( (await this.userService.findOne({ role: Role.Admin, diff --git a/apps/drec-api/src/pods/invitation/invitation.service.ts b/apps/drec-api/src/pods/invitation/invitation.service.ts index 3868aa8d4..a9343f2e4 100644 --- a/apps/drec-api/src/pods/invitation/invitation.service.ts +++ b/apps/drec-api/src/pods/invitation/invitation.service.ts @@ -154,8 +154,7 @@ export class InvitationService { password: this.randPassword, orgName: organization.name, organizationType: organization.organizationType, - // @ts-ignore - orgid: organization.id | undefined, + orgid: organization.id || undefined, }; let userid: any; this.logger.debug('invitee'); diff --git a/apps/drec-api/src/pods/issuer/drec-issuer.controller.ts b/apps/drec-api/src/pods/issuer/drec-issuer.controller.ts index 09c238a3b..53b3ac7d7 100755 --- a/apps/drec-api/src/pods/issuer/drec-issuer.controller.ts +++ b/apps/drec-api/src/pods/issuer/drec-issuer.controller.ts @@ -83,7 +83,6 @@ export class DrecIssuerController { this.logger.verbose(`With in reIssueCertificates`); return new Promise((resolve, reject) => { - // @ts-ignore this.issuerService.issueCertificateFromAPI(certificateData); this.logger.log(`hit the issueance data`); resolve('hit the issueance data'); diff --git a/apps/drec-api/src/pods/issuer/issuer.service.ts b/apps/drec-api/src/pods/issuer/issuer.service.ts index 538d104bd..024adc64c 100755 --- a/apps/drec-api/src/pods/issuer/issuer.service.ts +++ b/apps/drec-api/src/pods/issuer/issuer.service.ts @@ -229,8 +229,7 @@ export class IssuerService { allDevicesOfGroup.sort(function (a, b) { // Turn your strings into dates, and then subtract them // to get a value that is either negative, positive, or zero. - //@ts-ignore - return new Date(b.createdAt) - new Date(a.createdAt); + return new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime(); }); // console.log("192", allDevicesOfGroup); let deviceOnBoardedWhichIsInBetweenNextIssuance: Device = @@ -861,8 +860,7 @@ export class IssuerService { } if (allPreviousReadingsOfDevices.length > 1) { allPreviousReadingsOfDevices.sort(function (a, b) { - //@ts-ignore - return a.timestamp - b.timestamp; + return Number(a.timestamp) - Number(b.timestamp); }); minimumStartDate = allPreviousReadingsOfDevices[0].timestamp; } diff --git a/apps/drec-api/src/pods/organization/organization.controller.ts b/apps/drec-api/src/pods/organization/organization.controller.ts index ae4a3c968..149caae5a 100644 --- a/apps/drec-api/src/pods/organization/organization.controller.ts +++ b/apps/drec-api/src/pods/organization/organization.controller.ts @@ -366,7 +366,6 @@ export class OrganizationController { const user = await this.userService.findById(userid); if ( loggedUser.role === Role.ApiUser && - // @ts-ignore ts(2339) loggedUser.api_user_id != user.api_user_id ) { throw new NotFoundException('User does not exist in this organization'); diff --git a/apps/drec-api/src/pods/permission/permission.service.ts b/apps/drec-api/src/pods/permission/permission.service.ts index 334aacd9b..2ddf6b22b 100755 --- a/apps/drec-api/src/pods/permission/permission.service.ts +++ b/apps/drec-api/src/pods/permission/permission.service.ts @@ -294,7 +294,6 @@ export class PermissionService { let permissionIds: any = []; const api_userpermission = await this.userService.getApiuser( - // @ts-ignore ts(2339) api_user.api_user_id, ); @@ -314,7 +313,6 @@ export class PermissionService { }), ); await this.userService.apiuser_permission_request( - // @ts-ignore ts(2339) api_user.api_user_id, permissionIds, ); diff --git a/apps/drec-api/src/pods/user/dto/create-user.dto.ts b/apps/drec-api/src/pods/user/dto/create-user.dto.ts index 180649c28..815439351 100755 --- a/apps/drec-api/src/pods/user/dto/create-user.dto.ts +++ b/apps/drec-api/src/pods/user/dto/create-user.dto.ts @@ -89,4 +89,7 @@ export class CreateUserORGDTO @IsUUID('all', { message: 'Invalid UUID format' }) @IsOptional() api_user_id?: string; + + @IsOptional() + orgid?: number; } diff --git a/apps/drec-api/src/pods/user/oauth_client.service.ts b/apps/drec-api/src/pods/user/oauth_client.service.ts index b6938c64a..f954a0da1 100755 --- a/apps/drec-api/src/pods/user/oauth_client.service.ts +++ b/apps/drec-api/src/pods/user/oauth_client.service.ts @@ -23,7 +23,6 @@ export class OauthClientCredentialsService { ) {} async createAPIUser(): Promise { - // @ts-ignore return await this.apiUserEntityRepository.save({ api_user_id: uuid() }); } From 4e2dcd36acce6be950f7651353e47d27151cb2b1 Mon Sep 17 00:00:00 2001 From: Aish1990 Date: Tue, 30 Apr 2024 00:13:48 +0530 Subject: [PATCH 14/89] Removed ts-ignore from Reads Controller --- .../src/pods/device/dto/device.dto.ts | 4 + .../src/pods/reads/reads.controller.ts | 172 +++++++----------- 2 files changed, 72 insertions(+), 104 deletions(-) diff --git a/apps/drec-api/src/pods/device/dto/device.dto.ts b/apps/drec-api/src/pods/device/dto/device.dto.ts index 103a923f4..45180a391 100755 --- a/apps/drec-api/src/pods/device/dto/device.dto.ts +++ b/apps/drec-api/src/pods/device/dto/device.dto.ts @@ -204,4 +204,8 @@ export class DeviceDTO implements IDevice { @IsOptional() createdAt?: Date; + + @IsString() + @IsOptional() + api_user_id?: string; } diff --git a/apps/drec-api/src/pods/reads/reads.controller.ts b/apps/drec-api/src/pods/reads/reads.controller.ts index d6dd6f719..49088bdf3 100644 --- a/apps/drec-api/src/pods/reads/reads.controller.ts +++ b/apps/drec-api/src/pods/reads/reads.controller.ts @@ -228,13 +228,10 @@ export class ReadsController extends BaseReadsController { }); } device = await this.deviceService.findOne(parseInt(meterId)); - // @ts-ignore if ( orguser != undefined && - // @ts-ignore ts(2339) device.api_user_id === null && - // @ts-ignore ts(2304) - orguser.role === enums_1.Role.Buyer + orguser.role === Role.Buyer ) { this.logger.error( `An buyer of apiuser can't view the reads of direct organization`, @@ -245,7 +242,6 @@ export class ReadsController extends BaseReadsController { }); } if (user.role === Role.Buyer) { - // @ts-ignore if (device.api_user_id != null) { this.logger.error( `An buyer can't view the reads of apiuser's organization`, @@ -395,7 +391,6 @@ export class ReadsController extends BaseReadsController { ); }); } else { - // @ts-ignore user.organizationId = measurements.organizationId; } } @@ -464,80 +459,69 @@ export class ReadsController extends BaseReadsController { for (const key in ele) { if (key === 'starttimestamp' || key === 'endtimestamp') { if (ele[key]) { + let dateString = ele[key].toISOString(); const dateTimeRegex = /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.{0,1}\d{0,3}$/; - // @ts-ignore ts(2339) - if (ele[key].includes('.')) { + if (dateString.includes('.')) { if ( Number.isNaN( parseFloat( - // @ts-ignore ts(2339) - ele[key].substring( - // @ts-ignore ts(2339) - ele[key].indexOf('.'), - // @ts-ignore ts(2339) - ele[key].length, + dateString.substring( + dateString.indexOf('.'), + dateString.length, ), ), ) ) { this.logger.error( - `Invalid date sent ${ele[key]}` + + `Invalid date sent ${dateString}` + ` please sent valid date, format for dates is YYYY-MM-DD hh:mm:ss example 2020-02-19 19:20:55 or to include milliseconds add dot and upto 3 digits after seconds example 2020-02-19 19:20:55.2 or 2020-02-19 19:20:54.333`, ); throw new ConflictException({ success: false, message: - `Invalid date sent ${ele[key]}` + + `Invalid date sent ${dateString}` + ` please sent valid date, format for dates is YYYY-MM-DD hh:mm:ss example 2020-02-19 19:20:55 or to include milliseconds add dot and upto 3 digits after seconds example 2020-02-19 19:20:55.2 or 2020-02-19 19:20:54.333`, }); } } - // @ts-ignore - if (!dateTimeRegex.test(ele[key])) { + if (!dateTimeRegex.test(dateString)) { dateInvalid = true; this.logger.error( - `Invalid date sent ${ele[key]}` + + `Invalid date sent ${dateString}` + ` please sent valid date, format for dates is YYYY-MM-DD hh:mm:ss example 2020-02-19 19:20:55 or to include milliseconds add dot and upto 3 digits after seconds example 2020-02-19 19:20:55.2 or 2020-02-19 19:20:54.333`, ); throw new ConflictException({ success: false, message: - `Invalid date sent ${ele[key]}` + + `Invalid date sent ${dateString}` + ` please sent valid date, format for dates is YYYY-MM-DD hh:mm:ss example 2020-02-19 19:20:55 or to include milliseconds add dot and upto 3 digits after seconds example 2020-02-19 19:20:55.2 or 2020-02-19 19:20:54.333`, }); } else { let dateTime; - dateTime = momentTimeZone.tz(ele[key], measurements.timezone); + dateTime = momentTimeZone.tz(dateString, measurements.timezone); if (!dateTime.isValid()) { dateInvalid = true; - this.logger.error(`Invalid date sent ${ele[key]}`); + this.logger.error(`Invalid date sent ${dateString}`); throw new ConflictException({ success: false, - message: `Invalid date sent ${ele[key]}`, + message: `Invalid date sent ${dateString}`, }); } else { let milliSeondsToAddSentInRequest = ''; if ( - // @ts-ignore ts(2339) - ele[key].includes('.') && + dateString.includes('.') && parseInt( - // @ts-ignore ts(2339) - ele[key].substring( - // @ts-ignore ts(2339) - ele[key].indexOf('.'), - // @ts-ignore ts(2339) - ele[key].length, + dateString.substring( + dateString.indexOf('.'), + dateString.length, ), ) != NaN ) { - // @ts-ignore - milliSeondsToAddSentInRequest = ele[key].substring( - // @ts-ignore ts(2339) - ele[key].indexOf('.'), - // @ts-ignore ts(2339) - ele[key].length, + milliSeondsToAddSentInRequest = dateString.substring( + dateString.indexOf('.'), + dateString.length, ); } let utcString: string = dateTime.clone().utc().format(); @@ -551,8 +535,7 @@ export class ReadsController extends BaseReadsController { utcString = utcString.substring(0, utcString.length - 1) + '.000Z'; } - // @ts-ignore - ele[key] = utcString; + dateString = utcString; } } } @@ -590,24 +573,21 @@ export class ReadsController extends BaseReadsController { let historyallStartDatesAreAftercommissioningDate = true; let historyallEndDatesAreAftercommissioningDate = true; measurements.reads.forEach((ele) => { - // @ts-ignore if ( - ele.starttimestamp === null || + (ele.starttimestamp instanceof Date && + (ele.starttimestamp === null || ele.starttimestamp === undefined || - // @ts-ignore ts(2367) - ele.starttimestamp === '' || - ele.endtimestamp === null || + isNaN(ele.starttimestamp.getTime()))) || + (ele.endtimestamp instanceof Date && + (ele.endtimestamp === null || ele.endtimestamp === undefined || - // @ts-ignore ts(2367) - ele.endtimestamp === '' + isNaN(ele.endtimestamp.getTime()))) ) { datesContainingNullOrEmptyValues = true; } - // @ts-ignore - const startdateformate = isValidUTCDateFormat(ele.starttimestamp); + const startdateformate = isValidUTCDateFormat(ele.starttimestamp.toISOString()); //dateFormateToCheck.test(ele.starttimestamp); - // @ts-ignore - const enddateformate = isValidUTCDateFormat(ele.endtimestamp); + const enddateformate = isValidUTCDateFormat(ele.endtimestamp.toISOString()); if (!startdateformate || !enddateformate) { datevalid = false; @@ -762,15 +742,14 @@ export class ReadsController extends BaseReadsController { measurements.reads.forEach((ele) => { this.logger.log('Line No: 512'); if ( - ele.endtimestamp === null || + ele.endtimestamp instanceof Date && + (ele.endtimestamp === null || ele.endtimestamp === undefined || - // @ts-ignore ts(2339) - ele.endtimestamp === '' + isNaN(ele.endtimestamp.getTime())) ) { datesContainingNullOrEmptyValues = true; } - // @ts-ignore - const enddateformate = isValidUTCDateFormat(ele.endtimestamp); + const enddateformate = isValidUTCDateFormat(ele.endtimestamp.toISOString()); if (!enddateformate) { datevalid1 = false; @@ -1040,80 +1019,69 @@ export class ReadsController extends BaseReadsController { for (const key in ele) { if (key === 'starttimestamp' || key === 'endtimestamp') { if (ele[key]) { + let dateString = ele[key].toISOString(); const dateTimeRegex = /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.{0,1}\d{0,3}$/; - // @ts-ignore ts(2339) - if (ele[key].includes('.')) { + if (dateString.includes('.')) { if ( Number.isNaN( parseFloat( - // @ts-ignore ts(2339) - ele[key].substring( - // @ts-ignore ts(2339) - ele[key].indexOf('.'), - // @ts-ignore ts(2339) - ele[key].length, + dateString.substring( + dateString.indexOf('.'), + dateString.length, ), ), ) ) { this.logger.error( - `Invalid date sent ${ele[key]}` + + `Invalid date sent ${dateString}` + ` please sent valid date, format for dates is YYYY-MM-DD hh:mm:ss example 2020-02-19 19:20:55 or to include milliseconds add dot and upto 3 digits after seconds example 2020-02-19 19:20:55.2 or 2020-02-19 19:20:54.333`, ); throw new ConflictException({ success: false, message: - `Invalid date sent ${ele[key]}` + + `Invalid date sent ${dateString}` + ` please sent valid date, format for dates is YYYY-MM-DD hh:mm:ss example 2020-02-19 19:20:55 or to include milliseconds add dot and upto 3 digits after seconds example 2020-02-19 19:20:55.2 or 2020-02-19 19:20:54.333`, }); } } - // @ts-ignore - if (!dateTimeRegex.test(ele[key])) { + if (!dateTimeRegex.test(dateString)) { dateInvalid = true; this.logger.error( - `Invalid date sent ${ele[key]}` + + `Invalid date sent ${dateString}` + ` please sent valid date, format for dates is YYYY-MM-DD hh:mm:ss example 2020-02-19 19:20:55 or to include milliseconds add dot and upto 3 digits after seconds example 2020-02-19 19:20:55.2 or 2020-02-19 19:20:54.333`, ); throw new ConflictException({ success: false, message: - `Invalid date sent ${ele[key]}` + + `Invalid date sent ${dateString}` + ` please sent valid date, format for dates is YYYY-MM-DD hh:mm:ss example 2020-02-19 19:20:55 or to include milliseconds add dot and upto 3 digits after seconds example 2020-02-19 19:20:55.2 or 2020-02-19 19:20:54.333`, }); } else { let dateTime; - dateTime = momentTimeZone.tz(ele[key], measurements.timezone); + dateTime = momentTimeZone.tz(dateString, measurements.timezone); if (!dateTime.isValid()) { - this.logger.error(`Invalid date sent ${ele[key]}`); + this.logger.error(`Invalid date sent ${dateString}`); dateInvalid = true; throw new ConflictException({ success: false, - message: `Invalid date sent ${ele[key]}`, + message: `Invalid date sent ${dateString}`, }); } else { let milliSeondsToAddSentInRequest = ''; if ( - // @ts-ignore ts(2339) - ele[key].includes('.') && + dateString.includes('.') && parseInt( - // @ts-ignore ts(2339) - ele[key].substring( - // @ts-ignore ts(2339) - ele[key].indexOf('.'), - // @ts-ignore ts(2339) - ele[key].length, + dateString.substring( + dateString.indexOf('.'), + dateString.length, ), ) != NaN ) { - // @ts-ignore - milliSeondsToAddSentInRequest = ele[key].substring( - // @ts-ignore - ele[key].indexOf('.'), - // @ts-ignore - ele[key].length, + milliSeondsToAddSentInRequest = dateString.substring( + dateString.indexOf('.'), + dateString.length, ); } let utcString: string = dateTime.clone().utc().format(); @@ -1127,8 +1095,7 @@ export class ReadsController extends BaseReadsController { utcString = utcString.substring(0, utcString.length - 1) + '.000Z'; } - // @ts-ignore - ele[key] = utcString; + dateString = utcString; } } } @@ -1167,22 +1134,20 @@ export class ReadsController extends BaseReadsController { let historyallEndDatesAreAftercommissioningDate = true; measurements.reads.forEach((ele) => { if ( - ele.starttimestamp === null || + (ele.starttimestamp instanceof Date && + (ele.starttimestamp === null || ele.starttimestamp === undefined || - // @ts-ignore ts(2367) - ele.starttimestamp === '' || - ele.endtimestamp === null || + isNaN(ele.starttimestamp.getTime()))) || + (ele.endtimestamp instanceof Date && + (ele.endtimestamp === null || ele.endtimestamp === undefined || - // @ts-ignore ts(2367) - ele.endtimestamp === '' + isNaN(ele.endtimestamp.getTime()))) ) { datesContainingNullOrEmptyValues = true; } - // @ts-ignore - const startdateformate = isValidUTCDateFormat(ele.starttimestamp); + const startdateformate = isValidUTCDateFormat(ele.starttimestamp.toISOString()); - // @ts-ignore - const enddateformate = isValidUTCDateFormat(ele.endtimestamp); + const enddateformate = isValidUTCDateFormat(ele.endtimestamp.toISOString()); if (!startdateformate || !enddateformate) { datevalid = false; @@ -1335,15 +1300,14 @@ export class ReadsController extends BaseReadsController { measurements.reads.forEach((ele) => { this.logger.log('Line No: 512'); if ( - ele.endtimestamp === null || - ele.endtimestamp === undefined || - // @ts-ignore ts(2367) - ele.endtimestamp === '' + (ele.endtimestamp instanceof Date && + (ele.endtimestamp === null || + ele.endtimestamp === undefined || + isNaN(ele.endtimestamp.getTime()))) ) { datesContainingNullOrEmptyValues = true; } - // @ts-ignore - const enddateformate = isValidUTCDateFormat(ele.endtimestamp); + const enddateformate = isValidUTCDateFormat(ele.endtimestamp.toISOString()); if (!enddateformate) { datevalid1 = false; From 05ebdf53556cceca2eb89679b0a9949ac35529cb Mon Sep 17 00:00:00 2001 From: Aish1990 Date: Tue, 30 Apr 2024 10:32:11 +0530 Subject: [PATCH 15/89] Removed ts-ignore from Reads Service --- apps/drec-api/src/pods/reads/reads.service.ts | 41 +++---------------- 1 file changed, 5 insertions(+), 36 deletions(-) diff --git a/apps/drec-api/src/pods/reads/reads.service.ts b/apps/drec-api/src/pods/reads/reads.service.ts index 4032015ed..014a48485 100755 --- a/apps/drec-api/src/pods/reads/reads.service.ts +++ b/apps/drec-api/src/pods/reads/reads.service.ts @@ -93,11 +93,8 @@ export class ReadsService { private readonly organizationService: OrganizationService, private readonly eventBus: EventBus, ) { - // @ts-ignore const url = process.env.INFLUXDB_URL; - // @ts-ignore const token = process.env.INFLUXDB_TOKEN; - // @ts-ignore const org = process.env.INFLUXDB_ORG; this.influxDB = new InfluxDB({ url, token }); @@ -384,7 +381,6 @@ export class ReadsService { measurement: NewIntmediateMeterReadDTO, device: DeviceDTO, ): Promise { - // @ts-ignore const final = await this.NewfindLatestRead(deviceId, device.createdAt); this.logger.verbose(`final: ${final}`); const reads: any = []; @@ -408,7 +404,6 @@ export class ReadsService { element.starttimestamp, element.endtimestamp, ); - // @ts-ignore const historyAge = new Date(device.createdAt); historyAge.setFullYear(historyAge.getFullYear() - 3); this.logger.verbose('historyAge'); @@ -422,23 +417,19 @@ export class ReadsService { ); } - // @ts-ignore if ( requeststartdate <= DateTime.fromISO(new Date(historyAge).toISOString()) || - // @ts-ignore requeststartdate >= DateTime.fromISO(new Date(device?.createdAt).toISOString()) || requestcurrentend <= DateTime.fromISO(new Date(historyAge).toISOString()) || - // @ts-ignore requestcurrentend >= DateTime.fromISO(new Date(device?.createdAt).toISOString()) ) { return reject( new ConflictException({ success: false, - // @ts-ignore message: `For History Type Reads of devices start time and/or end time should be within 3 year of device onboarding, ex: device onboarded date: ${device?.createdAt}maximum date allowed for start and end date should be within 3 year in past from onboarded date, ${device?.createdAt}`, }), ); @@ -484,7 +475,6 @@ export class ReadsService { await new Promise((resolve, reject) => { measurement.reads.forEach(async (element, measurmentreadindex) => { if (final && final['timestamp']) { - // @ts-ignore if ( new Date(element.endtimestamp).getTime() < new Date(final.timestamp).getTime() @@ -493,7 +483,6 @@ export class ReadsService { new ConflictException({ success: false, message: - // @ts-ignore `The sent date for reading ${element.endtimestamp} is less than last sent meter read date ${final.timestamp}`, }), ); @@ -541,7 +530,6 @@ export class ReadsService { timestamp: ${final.timestamp.toISOString()} ${typeof final.timestamp.toISOString()}`); if (final && final['timestamp']) { - // @ts-ignore if ( new Date(element.endtimestamp).getTime() < new Date(final.timestamp).getTime() @@ -550,7 +538,6 @@ export class ReadsService { new ConflictException({ success: false, message: - // @ts-ignore `The sent date for reading ${element.endtimestamp} is less than last sent meter read date ${final.timestamp.toISOString()}`, }), ); @@ -698,7 +685,6 @@ export class ReadsService { ); } - // @ts-ignore const read: ReadDTO = { timestamp: new Date(element.endtimestamp), value: Delta, @@ -743,7 +729,6 @@ export class ReadsService { meterId: string, deviceregisterdate: Date, ): Promise { - // @ts-ignore const fluxQuery = `from(bucket: "${process.env.INFLUXDB_BUCKET}") |> range(start: ${deviceregisterdate}, stop: now()) |> filter(fn: (r) => r.meter == "${meterId}" and r._field == "read") @@ -772,14 +757,10 @@ export class ReadsService { })); } get dbReader() { - // @ts-ignore const url = process.env.INFLUXDB_URL; - // @ts-ignore const token = process.env.INFLUXDB_TOKEN; - // @ts-ignore const org = process.env.INFLUXDB_ORG; - // @ts-ignore return new InfluxDB({ url, token }).getQueryApi(org); } @@ -871,9 +852,7 @@ export class ReadsService { deviceAge = 1; } const currentRead = DateTime.fromISO(read.timestamp.toISOString()); - // @ts-ignore const lastRead = DateTime.fromISO(new Date(device.createdAt).toISOString()); - // @ts-ignore const meteredTimePeriod = Math.abs( currentRead.diff(lastRead, ['hours']).toObject()?.hours || 0, @@ -1052,12 +1031,10 @@ export class ReadsService { if (historynextissue != undefined) { const stdate = new Date(startdate).getTime(); const eddate = new Date(enddate).getTime(); - // @ts-ignore const reservSdate = new Date( historynextissue.reservationStartDate, ).getTime(); this.logger.verbose(reservSdate); - // @ts-ignore const reservEdate = new Date( historynextissue.reservationEndDate, ).getTime(); @@ -1070,7 +1047,6 @@ export class ReadsService { eddate <= reservEdate && eddate > reservSdate ) { - // @ts-ignore this.deviceGroupService.HistoryUpdatecertificateissuedate( historynextissue.id, HistoryNextInssuanceStatus.Pending, @@ -1283,7 +1259,6 @@ export class ReadsService { if (numberOfHistReads > 0) { numberOfPages = Math.ceil(numberOfHistReads / sizeOfPage); } - // @ts-ignore if (typeof pageNumber === 'number' && !isNaN(pageNumber)) { filter.offset = sizeOfPage * (pageNumber - 1); @@ -1409,11 +1384,9 @@ export class ReadsService { previousPage, ); if (previousPageData.length > 0) { - // @ts-ignore ts(2339) - previousReadTime = previousPageData[0].timestamp; + previousReadTime = (previousPageData[0] as any).timestamp; this.logger.verbose( - // @ts-ignore ts(2339) - 'previous page read data[0]::::' + previousPageData[0].timestamp, + 'previous page read data[0]::::' + (previousPageData[0] as any).timestamp, ); } else { previousReadTime = null; @@ -1431,26 +1404,22 @@ export class ReadsService { ), ); } else if (i == 0 && pageNumber != 1) { - // @ts-ignore startdate = previousReadTime; } else { startdate = transformedFinalOngoing[i - 1].enddate; } - // @ts-ignore - const enddate = finalongoing[i].timestamp; + const enddate = (finalongoing[i] as any).timestamp; if (i > 1) { transformedFinalOngoing.push({ startdate: transformedFinalOngoing[i - 1].enddate, enddate: enddate, - // @ts-ignore - value: currentRead.value, + value: (currentRead as any).value, }); } else { transformedFinalOngoing.push({ startdate: startdate, enddate: enddate, - // @ts-ignore - value: currentRead.value, + value: (currentRead as any).value, }); } } From 6762a7d7e8c40b53c96325eaf1bc24806f30fe2a Mon Sep 17 00:00:00 2001 From: Aish1990 Date: Tue, 30 Apr 2024 11:13:51 +0530 Subject: [PATCH 16/89] Removed ts-ignore from User Controller, User Service --- .../drec-api/src/pods/user/user.controller.ts | 4 +- apps/drec-api/src/pods/user/user.service.ts | 1493 ++++++++--------- 2 files changed, 743 insertions(+), 754 deletions(-) diff --git a/apps/drec-api/src/pods/user/user.controller.ts b/apps/drec-api/src/pods/user/user.controller.ts index 9985285c7..bf840177f 100755 --- a/apps/drec-api/src/pods/user/user.controller.ts +++ b/apps/drec-api/src/pods/user/user.controller.ts @@ -145,7 +145,6 @@ export class UserController { ); }); } - // @ts-ignore if ( userRegistrationData.organizationType.toLowerCase() != 'Buyer'.toLowerCase() && @@ -174,8 +173,7 @@ export class UserController { }); } if (!userRegistrationData.api_user_id) { - // @ts-ignore - userRegistrationData.api_user_id = user.api_user_id; + userRegistrationData.api_user_id = (user as any).api_user_id; } return this.userService.newcreate(userRegistrationData); } diff --git a/apps/drec-api/src/pods/user/user.service.ts b/apps/drec-api/src/pods/user/user.service.ts index d3811542d..8e5e42286 100755 --- a/apps/drec-api/src/pods/user/user.service.ts +++ b/apps/drec-api/src/pods/user/user.service.ts @@ -1,751 +1,742 @@ -import { - ConflictException, - Injectable, - Inject, - Logger, - UnprocessableEntityException, - UnauthorizedException, - NotFoundException, - InternalServerErrorException, - forwardRef, -} from '@nestjs/common'; -import { InjectRepository } from '@nestjs/typeorm'; -import bcrypt from 'bcryptjs'; -import { - FindOptionsWhere, - Repository, - FindManyOptions, - SelectQueryBuilder, - Not, -} from 'typeorm'; -import { - ILoggedInUser, - IUser, - UserPasswordUpdate, - UserChangePasswordUpdate, -} from '../../models'; -import { Role, UserStatus, UserPermissionStatus } from '../../utils/enums'; -import { CreateUserORGDTO } from './dto/create-user.dto'; -import { ExtendedBaseEntity } from '@energyweb/origin-backend-utils'; -import { validate } from 'class-validator'; -import { UserRole } from './user_role.entity'; -import { UserDTO } from './dto/user.dto'; -import { User } from './user.entity'; -import { UpdateUserProfileDTO } from './dto/update-user-profile.dto'; -import { EmailConfirmationService } from '../email-confirmation/email-confirmation.service'; -import { UpdateUserDTO } from '../admin/dto/update-user.dto'; -import { UserFilterDTO } from '../admin/dto/user-filter.dto'; -import { OrganizationService } from '../organization/organization.service'; -import { IEmailConfirmationToken, ISuccessResponse } from '../../models'; -import { OauthClientCredentialsService } from './oauth_client.service'; -export type TUserBaseEntity = ExtendedBaseEntity & IUser; -import { ApiUserEntity } from './api-user.entity'; -import { UserLoginSessionEntity } from './user_login_session.entity'; -@Injectable() -export class UserService { - private readonly logger = new Logger(UserService.name); - - constructor( - @InjectRepository(User) private readonly repository: Repository, - @InjectRepository(UserRole) private rolerepository: Repository, - private readonly emailConfirmationService: EmailConfirmationService, - private readonly oauthClientCredentialsService: OauthClientCredentialsService, - @Inject(forwardRef(() => OrganizationService)) - private organizationService: OrganizationService, - @InjectRepository(ApiUserEntity) - private readonly apiUserEntityRepository: Repository, - @InjectRepository(UserLoginSessionEntity) - private readonly userloginSessionRepository: Repository, - ) {} - - public async seed( - data: CreateUserORGDTO, - - organizationId: number | null, - role?: Role, - status?: UserStatus, - ): Promise { - await this.checkForExistingUser(data.email); - - return this.repository.save({ - // title: data.title, - firstName: data.firstName, - lastName: data.lastName, - email: data.email.toLowerCase(), - // telephone: data.telephone, - password: this.hashPassword(data.password), - role: role || Role.Admin, - status: status || UserStatus.Active, - organization: organizationId ? { id: organizationId } : {}, - }); - } - - public async newcreate( - data: CreateUserORGDTO, - status?: UserStatus, - inviteuser?: boolean, - ): Promise { - await this.checkForExistingUser(data.email.toLowerCase()); - // @ts-ignore - const api_user = - await this.oauthClientCredentialsService.findOneByApiUserId( - data.api_user_id, - ); - - let org_id; - if (!inviteuser) { - const orgdata = { - name: data.orgName !== undefined ? data.orgName : '', - organizationType: data.organizationType, - orgEmail: data.email, - address: data.orgAddress, - }; - - orgdata['api_user_id'] = api_user.api_user_id; - if (await this.organizationService.isNameAlreadyTaken(orgdata.name)) { - throw new ConflictException({ - success: false, - message: `Organization "${data.orgName}" is already existed,please use another Organization name`, - }); - } else { - const org = await this.organizationService.newcreate(orgdata); - org_id = org.id; - this.logger.debug( - `Successfully registered a new organization with id ${JSON.stringify(org.id)}`, - ); - } - } - // @ts-ignore - if (data.orgid) { - // @ts-ignore - org_id = data.orgid; - } - let role; - let roleId; - if ( - data.organizationType === 'Buyer' || - data.organizationType === 'buyer' - ) { - role = Role.Buyer; - roleId = 4; - } else if ( - data.organizationType === 'Developer' || - data.organizationType === 'Developer' - ) { - role = Role.OrganizationAdmin; - roleId = 2; - } else if ( - data.organizationType === 'ApiUser' || - data.organizationType === 'apiuser' - ) { - role = Role.ApiUser; - roleId = 6; - } - - const user = await this.repository.save({ - firstName: data.firstName, - lastName: data.lastName, - email: data.email.toLowerCase(), - password: this.hashPassword(data.password), - notifications: true, - status: status || UserStatus.Active, - role: role, - roleId: roleId, - organization: org_id ? { id: org_id } : {}, - api_user_id: api_user ? api_user.api_user_id : null, - }); - const { password, ...userData } = user; - this.logger.debug( - `Successfully registered a new user with id ${JSON.stringify(userData.id)}`, - ); - - await this.emailConfirmationService.create(user); - return user; - } - - public async adminnewcreate( - data: CreateUserORGDTO, - status?: UserStatus, - inviteuser?: boolean, - ): Promise { - await this.checkForExistingUser(data.email.toLowerCase()); - let org_id; - if (!inviteuser) { - const orgdata = { - name: data.orgName !== undefined ? data.orgName : '', - organizationType: data.organizationType, - // secretKey: data.secretKey, - orgEmail: data.email, - address: data.orgAddress, - }; - - if (await this.organizationService.isNameAlreadyTaken(orgdata.name)) { - throw new ConflictException({ - success: false, - message: `Organization "${data.orgName}" is already existed,please use another Organization name`, - }); - } else { - const org = await this.organizationService.newcreate(orgdata); - org_id = org.id; - this.logger.debug( - `Successfully registered a new organization with id ${JSON.stringify(org.id)}`, - ); - } - } - - let role; - let roleId; - if ( - data.organizationType === 'Buyer' || - data.organizationType === 'buyer' - ) { - role = Role.Buyer; - roleId = 4; - } else { - role = Role.OrganizationAdmin; - roleId = 2; - } - const user = await this.repository.save({ - firstName: data.firstName, - lastName: data.lastName, - email: data.email.toLowerCase(), - password: this.hashPassword(data.password), - notifications: true, - status: status || UserStatus.Active, - role: role, - roleId: roleId, - organization: org_id ? { id: org_id } : {}, - }); - const { password, ...userData } = user; - this.logger.debug( - `Successfully registered a new user with id ${JSON.stringify(userData.id)}`, - ); - await this.emailConfirmationService.admincreate(user, data.password); - - return new User(user); - } - - public async checkForExistingUser(email: string): Promise { - const isExistingUser = await this.hasUser({ email }); - - if (isExistingUser) { - const message = `User with email ${email} already exists`; - - this.logger.error(message); - throw new ConflictException({ - success: false, - message, - }); - } - } - - public async getAll(options?: FindManyOptions): Promise { - return this.repository.find(options); - } - - async findById(id: number): Promise { - const user = await this.findOne({ id }); - if (!user) { - throw new NotFoundException(`No user found with id ${id}`); - } - - if (user.role === Role.ApiUser) { - const api_user = await this.get_apiuser_permission_status( - // @ts-ignore ts(2339) - user.api_user_id, - ); - user['permission_status'] = api_user.permission_status; - } - return user; - } - - public async findByIds(ids: number[]): Promise { - return await this.repository.findByIds(ids); - } - - async findByEmail(email: string): Promise { - const lowerCaseEmail = email.toLowerCase(); - - return this.findOne({ email: lowerCaseEmail }); - } - - async getUserAndPasswordByEmail( - email: string, - ): Promise<(Pick & { password: string }) | null> { - const user = await this.repository.findOne({ - where: { - email, - }, - select: ['id', 'email', 'password'], - }); - - return user ?? null; - } - - async findOne(conditions: FindOptionsWhere): Promise { - const user = await (this.repository.findOne({ - where: conditions as FindOptionsWhere, - relations: ['organization'], - }) as Promise as Promise); - - if (user) { - const emailConfirmation = await this.emailConfirmationService.get( - user.id, - ); - - user.emailConfirmed = emailConfirmation?.confirmed || false; - } - - return user ?? null; - } - - private hashPassword(password: string) { - return bcrypt.hashSync(password, 8); - } - - private async hasUser(conditions: FindOptionsWhere) { - return Boolean(await this.findOne(conditions)); - } - - async setNotifications( - id: number, - notifications: boolean, - ): Promise { - await this.repository.update(id, { notifications }); - - return this.findById(id); - } - - async addToOrganization( - userId: number, - organizationId: number, - ): Promise { - await this.repository.update(userId, { - organization: { id: organizationId }, - status: UserStatus.Active, - }); - } - - public getatleastoneotheruserinOrg( - organizationId: number, - userId: number, - ): Promise { - return this.repository.find({ - where: { - id: Not(userId), - organization: { - id: organizationId, - }, - }, - order: { - id: 'DESC', - }, - take: 1, - }); - } - - async removeFromOrganization(userId: number): Promise { - await this.repository.update(userId, { organization: undefined }); - } - - async remove(userId: number): Promise { - await this.emailConfirmationService.remove(userId); - await this.repository.delete(userId); - } - - async updateProfile( - id: number, - { firstName, lastName, email }: UpdateUserProfileDTO, - ): Promise { - const updateEntity = new User({ - firstName, - lastName, - email: email.toLowerCase(), - }); - - const validationErrors = await validate(updateEntity, { - skipUndefinedProperties: true, - }); - - if (validationErrors.length > 0) { - throw new UnprocessableEntityException({ - success: false, - errors: validationErrors, - }); - } - const updateuser = await this.findById(id); - // @ts-ignore - if (!(updateuser.email === email.toLowerCase())) { - // @ts-ignore - await this.checkForExistingUser(email.toLowerCase()); - } - await this.repository.update(id, updateEntity); - - return this.findOne({ id }); - } - - async updatePassword( - email: string, - user: UserPasswordUpdate, - ): Promise { - const _user = await this.getUserAndPasswordByEmail(email); - - if (_user && bcrypt.compareSync(user.oldPassword, _user.password)) { - const updateEntity = new User({ - password: this.hashPassword(user.newPassword), - }); - - const validationErrors = await validate(updateEntity, { - skipUndefinedProperties: true, - }); - - if (validationErrors.length > 0) { - throw new UnprocessableEntityException({ - success: false, - errors: validationErrors, - }); - } - - await this.repository.update(_user.id, updateEntity); - return this.findOne({ id: _user.id }); - } - - throw new ConflictException({ - success: false, - errors: `Incorrect current password.`, - }); - } - - async updatechangePassword( - emailConfirmation: UserDTO, - user: UserChangePasswordUpdate, - ): Promise { - if (emailConfirmation) { - const updateEntity = new User({ - password: this.hashPassword(user.newPassword), - }); - - const validationErrors = await validate(updateEntity, { - skipUndefinedProperties: true, - }); - - if (validationErrors.length > 0) { - throw new UnprocessableEntityException({ - success: false, - errors: validationErrors, - }); - } - - await this.repository.update(emailConfirmation.id, updateEntity); - return emailConfirmation; - } - - throw new ConflictException({ - success: false, - errors: `User Not exist .`, - }); - } - - public async changeRole( - userId: number, - role: Role, - ): Promise { - this.logger.log(`Changing user role for userId=${userId} to ${role}`); - const getrole = await this.rolerepository.findOne({ - where: { - name: role, - }, - }); - await this.repository.update(userId, { role, roleId: getrole.id }); - return this.findOne({ id: userId }); - } - - async getPlatformAdmin(): Promise { - return this.findOne({ role: Role.Admin }); - } - - public async getUsersByFilter( - filterDto: UserFilterDTO, - pageNumber: number, - limit: number, - ): Promise<{ - users: IUser[]; - currentPage: number; - totalPages: number; - totalCount: number; - }> { - const query = await this.getFilteredQuery(filterDto); - try { - const [users, totalCount] = await query - .andWhere(`role != :role`, { role: Role.ApiUser }) - .skip((pageNumber - 1) * limit) - .take(limit) - .getManyAndCount(); - const totalPages = Math.ceil(totalCount / limit); - - return { - users: users, - currentPage: pageNumber, - totalPages, - totalCount, - }; - } catch (error) { - this.logger.error(`Failed to retrieve users`, error.stack); - throw new InternalServerErrorException('Failed to retrieve users'); - } - } - - private getFilteredQuery(filterDto: UserFilterDTO): SelectQueryBuilder { - const { organizationName, status } = filterDto; - const query = this.repository - .createQueryBuilder('user') - .leftJoinAndSelect('user.organization', 'organization') - .orderBy('user.createdAt', 'DESC'); - if (organizationName) { - const baseQuery = 'organization.name ILIKE :organizationName'; - query.andWhere(baseQuery, { organizationName: `%${organizationName}%` }); - } - if (status) { - query.andWhere(`user.status = '${status}'`); - } - return query; - } - - async update( - id: number, - data: UpdateUserDTO, - ): Promise { - const validationErrors = await validate(data, { - skipUndefinedProperties: true, - }); - if (validationErrors.length > 0) { - throw new UnprocessableEntityException({ - success: false, - errors: validationErrors, - }); - } - - const updateuser = await this.findById(id); - // @ts-ignore - if (!(updateuser.email === data.email)) { - // @ts-ignore - await this.checkForExistingUser(data.email); - } - - await this.repository.update(id, { - firstName: data.firstName, - lastName: data.lastName, - email: data.email, - status: data.status, - }); - - return this.findOne({ id }); - } - - public async canViewUserData( - userId: IUser['id'], - loggedInUser: ILoggedInUser, - ): Promise { - const user = await this.findById(userId); - - const isOwnUser = loggedInUser.id === userId; - const isOrgAdmin = - loggedInUser.organizationId === user.organization?.id && - loggedInUser.hasRole(Role.OrganizationAdmin); - const isAdmin = loggedInUser.hasRole(Role.Admin); - - const canViewUserData = isOwnUser || isOrgAdmin || isAdmin; - - if (!canViewUserData) { - throw new UnauthorizedException({ - success: false, - message: `Unable to fetch user data. Unauthorized.`, - }); - } - if (user.role === Role.ApiUser) { - const api_user = await this.get_apiuser_permission_status( - // @ts-ignore ts(2339) - user.api_user_id, - ); - user['permission_status'] = api_user.permission_status; - } - return user; - } - public async geytokenforResetPassword(email): Promise { - return await this.emailConfirmationService.ConfirmationEmailForResetPassword( - email, - ); - } - - public async sentinvitiontoUser(inviteuser, email, invitationId) { - const getcurrenttoken = - await this.emailConfirmationService.getByEmail(email); - if (!getcurrenttoken) { - return { - message: 'Token not found', - success: false, - }; - } - const { id, confirmed } = getcurrenttoken; - const { token, expiryTimestamp } = - await this.emailConfirmationService.generatetoken(getcurrenttoken, id); - await this.emailConfirmationService.sendInvitation( - inviteuser, - email, - invitationId, - ); - } - - public async findUserByOrganization( - organizationId: number, - pageNumber: number, - limit: number, - ) { - return await this.repository - .createQueryBuilder('user') - .leftJoinAndSelect('user.organization', 'organization') - .where('organization.id = :organizationId', { organizationId }) - .orderBy('user.createdAt', 'DESC') - .skip((pageNumber - 1) * limit) - .take(limit) - .getManyAndCount(); - } - /**get all user of apiuser */ - public async findUserByApiUserId( - api_user_id: string, - pageNumber: number, - limit: number, - org_id?, - ) { - return await this.repository - .createQueryBuilder('user') - .leftJoinAndSelect('user.organization', 'organization') - .where('user.api_user_id = :api_user_id', { api_user_id }) - .andWhere(`role != :role`, { role: Role.ApiUser }) - .orderBy('user.createdAt', 'DESC') - .skip((pageNumber - 1) * limit) - .take(limit) - .getManyAndCount(); - } - /** ApiUser Fuction*/ - - async getApiuser(api_id: string): Promise { - return await this.apiUserEntityRepository.findOne({ - where: { - api_user_id: api_id, - }, - }); - } - /** - * This Function added for request of permission to apiuser in apiuser table - * @param api_id - * @param permissionIds - */ - async apiuser_permission_request(api_id, permissionIds) { - await this.apiUserEntityRepository.update(api_id, { - permissionIds: permissionIds, - permission_status: UserPermissionStatus.Request, - }); - } - async apiuser_permission_accepted_byadmin( - api_id: string, - status: UserPermissionStatus, - ) { - await this.apiUserEntityRepository.update(api_id, { - permission_status: status, - }); - return await this.apiUserEntityRepository.findOne({ - where: { - api_user_id: api_id, - }, - }); - } - /** - * This service method use for get info of permission request status(Request,Active and Deactive) - * @param api_id - * @returns - */ - async get_apiuser_permission_status(api_id: string) { - const status_apiuser_permissiom = - await this.apiUserEntityRepository.findOne({ - where: { - api_user_id: api_id, - }, - }); - - return status_apiuser_permissiom; - } - - /** - * this function create for get user list of ApiUser - * @param organizationName - * @param pageNumber - * @param limit - * @returns - */ - public async getApiUsers( - organizationName: string, - pageNumber: number, - limit: number, - ): Promise<{ - users: IUser[]; - currentPage: number; - totalPages: number; - totalCount: number; - }> { - const filterDto = new UserFilterDTO(); - filterDto.organizationName = organizationName; - const query = await this.getFilteredQuery(filterDto); - try { - const [apiusers, totalCount] = await query - .andWhere(`user.role = :role`, { role: Role.ApiUser }) - .skip((pageNumber - 1) * limit) - .take(limit) - .getManyAndCount(); - - const totalPages = Math.ceil(totalCount / limit); - return { - users: apiusers, - currentPage: pageNumber, - totalPages, - totalCount, - }; - } catch (error) { - this.logger.error(`Failed to retrieve apiusers`, error.stack); - throw new InternalServerErrorException('Failed to retrieve apiusers'); - } - } - - /** - * - * @param email - * @param token - * @returns - */ - - async createUserSession(user: any, token: string) { - await this.userloginSessionRepository.save({ - userId: user.id, - accesstoken_hash: token, - }); - return; - } - /** - * - * @param userId - * @returns - */ - async removeUsersession(userId: number) { - return await this.userloginSessionRepository.delete({ userId: userId }); - } - - async hasgetUserTokenvalid( - conditions: FindOptionsWhere, - ) { - return Boolean( - await this.userloginSessionRepository.findOne({ - where: conditions as FindOptionsWhere, - }), - ); - } -} +import { + ConflictException, + Injectable, + Inject, + Logger, + UnprocessableEntityException, + UnauthorizedException, + NotFoundException, + InternalServerErrorException, + forwardRef, +} from '@nestjs/common'; +import { InjectRepository } from '@nestjs/typeorm'; +import bcrypt from 'bcryptjs'; +import { + FindOptionsWhere, + Repository, + FindManyOptions, + SelectQueryBuilder, + Not, +} from 'typeorm'; +import { + ILoggedInUser, + IUser, + UserPasswordUpdate, + UserChangePasswordUpdate, +} from '../../models'; +import { Role, UserStatus, UserPermissionStatus } from '../../utils/enums'; +import { CreateUserORGDTO } from './dto/create-user.dto'; +import { ExtendedBaseEntity } from '@energyweb/origin-backend-utils'; +import { validate } from 'class-validator'; +import { UserRole } from './user_role.entity'; +import { UserDTO } from './dto/user.dto'; +import { User } from './user.entity'; +import { UpdateUserProfileDTO } from './dto/update-user-profile.dto'; +import { EmailConfirmationService } from '../email-confirmation/email-confirmation.service'; +import { UpdateUserDTO } from '../admin/dto/update-user.dto'; +import { UserFilterDTO } from '../admin/dto/user-filter.dto'; +import { OrganizationService } from '../organization/organization.service'; +import { IEmailConfirmationToken, ISuccessResponse } from '../../models'; +import { OauthClientCredentialsService } from './oauth_client.service'; +export type TUserBaseEntity = ExtendedBaseEntity & IUser; +import { ApiUserEntity } from './api-user.entity'; +import { UserLoginSessionEntity } from './user_login_session.entity'; +@Injectable() +export class UserService { + private readonly logger = new Logger(UserService.name); + + constructor( + @InjectRepository(User) private readonly repository: Repository, + @InjectRepository(UserRole) private rolerepository: Repository, + private readonly emailConfirmationService: EmailConfirmationService, + private readonly oauthClientCredentialsService: OauthClientCredentialsService, + @Inject(forwardRef(() => OrganizationService)) + private organizationService: OrganizationService, + @InjectRepository(ApiUserEntity) + private readonly apiUserEntityRepository: Repository, + @InjectRepository(UserLoginSessionEntity) + private readonly userloginSessionRepository: Repository, + ) {} + + public async seed( + data: CreateUserORGDTO, + + organizationId: number | null, + role?: Role, + status?: UserStatus, + ): Promise { + await this.checkForExistingUser(data.email); + + return this.repository.save({ + // title: data.title, + firstName: data.firstName, + lastName: data.lastName, + email: data.email.toLowerCase(), + // telephone: data.telephone, + password: this.hashPassword(data.password), + role: role || Role.Admin, + status: status || UserStatus.Active, + organization: organizationId ? { id: organizationId } : {}, + }); + } + + public async newcreate( + data: CreateUserORGDTO, + status?: UserStatus, + inviteuser?: boolean, + ): Promise { + await this.checkForExistingUser(data.email.toLowerCase()); + const api_user = + await this.oauthClientCredentialsService.findOneByApiUserId( + data.api_user_id, + ); + + let org_id; + if (!inviteuser) { + const orgdata = { + name: data.orgName !== undefined ? data.orgName : '', + organizationType: data.organizationType, + orgEmail: data.email, + address: data.orgAddress, + }; + + orgdata['api_user_id'] = api_user.api_user_id; + if (await this.organizationService.isNameAlreadyTaken(orgdata.name)) { + throw new ConflictException({ + success: false, + message: `Organization "${data.orgName}" is already existed,please use another Organization name`, + }); + } else { + const org = await this.organizationService.newcreate(orgdata); + org_id = org.id; + this.logger.debug( + `Successfully registered a new organization with id ${JSON.stringify(org.id)}`, + ); + } + } + if (data.orgid) { + org_id = data.orgid; + } + let role; + let roleId; + if ( + data.organizationType === 'Buyer' || + data.organizationType === 'buyer' + ) { + role = Role.Buyer; + roleId = 4; + } else if ( + data.organizationType === 'Developer' || + data.organizationType === 'Developer' + ) { + role = Role.OrganizationAdmin; + roleId = 2; + } else if ( + data.organizationType === 'ApiUser' || + data.organizationType === 'apiuser' + ) { + role = Role.ApiUser; + roleId = 6; + } + + const user = await this.repository.save({ + firstName: data.firstName, + lastName: data.lastName, + email: data.email.toLowerCase(), + password: this.hashPassword(data.password), + notifications: true, + status: status || UserStatus.Active, + role: role, + roleId: roleId, + organization: org_id ? { id: org_id } : {}, + api_user_id: api_user ? api_user.api_user_id : null, + }); + const { password, ...userData } = user; + this.logger.debug( + `Successfully registered a new user with id ${JSON.stringify(userData.id)}`, + ); + + await this.emailConfirmationService.create(user); + return user; + } + + public async adminnewcreate( + data: CreateUserORGDTO, + status?: UserStatus, + inviteuser?: boolean, + ): Promise { + await this.checkForExistingUser(data.email.toLowerCase()); + let org_id; + if (!inviteuser) { + const orgdata = { + name: data.orgName !== undefined ? data.orgName : '', + organizationType: data.organizationType, + // secretKey: data.secretKey, + orgEmail: data.email, + address: data.orgAddress, + }; + + if (await this.organizationService.isNameAlreadyTaken(orgdata.name)) { + throw new ConflictException({ + success: false, + message: `Organization "${data.orgName}" is already existed,please use another Organization name`, + }); + } else { + const org = await this.organizationService.newcreate(orgdata); + org_id = org.id; + this.logger.debug( + `Successfully registered a new organization with id ${JSON.stringify(org.id)}`, + ); + } + } + + let role; + let roleId; + if ( + data.organizationType === 'Buyer' || + data.organizationType === 'buyer' + ) { + role = Role.Buyer; + roleId = 4; + } else { + role = Role.OrganizationAdmin; + roleId = 2; + } + const user = await this.repository.save({ + firstName: data.firstName, + lastName: data.lastName, + email: data.email.toLowerCase(), + password: this.hashPassword(data.password), + notifications: true, + status: status || UserStatus.Active, + role: role, + roleId: roleId, + organization: org_id ? { id: org_id } : {}, + }); + const { password, ...userData } = user; + this.logger.debug( + `Successfully registered a new user with id ${JSON.stringify(userData.id)}`, + ); + await this.emailConfirmationService.admincreate(user, data.password); + + return new User(user); + } + + public async checkForExistingUser(email: string): Promise { + const isExistingUser = await this.hasUser({ email }); + + if (isExistingUser) { + const message = `User with email ${email} already exists`; + + this.logger.error(message); + throw new ConflictException({ + success: false, + message, + }); + } + } + + public async getAll(options?: FindManyOptions): Promise { + return this.repository.find(options); + } + + async findById(id: number): Promise { + const user = await this.findOne({ id }); + if (!user) { + throw new NotFoundException(`No user found with id ${id}`); + } + + if (user.role === Role.ApiUser) { + const api_user = await this.get_apiuser_permission_status( + user.api_user_id, + ); + user['permission_status'] = api_user.permission_status; + } + return user; + } + + public async findByIds(ids: number[]): Promise { + return await this.repository.findByIds(ids); + } + + async findByEmail(email: string): Promise { + const lowerCaseEmail = email.toLowerCase(); + + return this.findOne({ email: lowerCaseEmail }); + } + + async getUserAndPasswordByEmail( + email: string, + ): Promise<(Pick & { password: string }) | null> { + const user = await this.repository.findOne({ + where: { + email, + }, + select: ['id', 'email', 'password'], + }); + + return user ?? null; + } + + async findOne(conditions: FindOptionsWhere): Promise { + const user = await (this.repository.findOne({ + where: conditions as FindOptionsWhere, + relations: ['organization'], + }) as Promise as Promise); + + if (user) { + const emailConfirmation = await this.emailConfirmationService.get( + user.id, + ); + + user.emailConfirmed = emailConfirmation?.confirmed || false; + } + + return user ?? null; + } + + private hashPassword(password: string) { + return bcrypt.hashSync(password, 8); + } + + private async hasUser(conditions: FindOptionsWhere) { + return Boolean(await this.findOne(conditions)); + } + + async setNotifications( + id: number, + notifications: boolean, + ): Promise { + await this.repository.update(id, { notifications }); + + return this.findById(id); + } + + async addToOrganization( + userId: number, + organizationId: number, + ): Promise { + await this.repository.update(userId, { + organization: { id: organizationId }, + status: UserStatus.Active, + }); + } + + public getatleastoneotheruserinOrg( + organizationId: number, + userId: number, + ): Promise { + return this.repository.find({ + where: { + id: Not(userId), + organization: { + id: organizationId, + }, + }, + order: { + id: 'DESC', + }, + take: 1, + }); + } + + async removeFromOrganization(userId: number): Promise { + await this.repository.update(userId, { organization: undefined }); + } + + async remove(userId: number): Promise { + await this.emailConfirmationService.remove(userId); + await this.repository.delete(userId); + } + + async updateProfile( + id: number, + { firstName, lastName, email }: UpdateUserProfileDTO, + ): Promise { + const updateEntity = new User({ + firstName, + lastName, + email: email.toLowerCase(), + }); + + const validationErrors = await validate(updateEntity, { + skipUndefinedProperties: true, + }); + + if (validationErrors.length > 0) { + throw new UnprocessableEntityException({ + success: false, + errors: validationErrors, + }); + } + const updateuser = await this.findById(id); + if (!(updateuser.email === email.toLowerCase())) { + await this.checkForExistingUser(email.toLowerCase()); + } + await this.repository.update(id, updateEntity); + + return this.findOne({ id }); + } + + async updatePassword( + email: string, + user: UserPasswordUpdate, + ): Promise { + const _user = await this.getUserAndPasswordByEmail(email); + + if (_user && bcrypt.compareSync(user.oldPassword, _user.password)) { + const updateEntity = new User({ + password: this.hashPassword(user.newPassword), + }); + + const validationErrors = await validate(updateEntity, { + skipUndefinedProperties: true, + }); + + if (validationErrors.length > 0) { + throw new UnprocessableEntityException({ + success: false, + errors: validationErrors, + }); + } + + await this.repository.update(_user.id, updateEntity); + return this.findOne({ id: _user.id }); + } + + throw new ConflictException({ + success: false, + errors: `Incorrect current password.`, + }); + } + + async updatechangePassword( + emailConfirmation: UserDTO, + user: UserChangePasswordUpdate, + ): Promise { + if (emailConfirmation) { + const updateEntity = new User({ + password: this.hashPassword(user.newPassword), + }); + + const validationErrors = await validate(updateEntity, { + skipUndefinedProperties: true, + }); + + if (validationErrors.length > 0) { + throw new UnprocessableEntityException({ + success: false, + errors: validationErrors, + }); + } + + await this.repository.update(emailConfirmation.id, updateEntity); + return emailConfirmation; + } + + throw new ConflictException({ + success: false, + errors: `User Not exist .`, + }); + } + + public async changeRole( + userId: number, + role: Role, + ): Promise { + this.logger.log(`Changing user role for userId=${userId} to ${role}`); + const getrole = await this.rolerepository.findOne({ + where: { + name: role, + }, + }); + await this.repository.update(userId, { role, roleId: getrole.id }); + return this.findOne({ id: userId }); + } + + async getPlatformAdmin(): Promise { + return this.findOne({ role: Role.Admin }); + } + + public async getUsersByFilter( + filterDto: UserFilterDTO, + pageNumber: number, + limit: number, + ): Promise<{ + users: IUser[]; + currentPage: number; + totalPages: number; + totalCount: number; + }> { + const query = await this.getFilteredQuery(filterDto); + try { + const [users, totalCount] = await query + .andWhere(`role != :role`, { role: Role.ApiUser }) + .skip((pageNumber - 1) * limit) + .take(limit) + .getManyAndCount(); + const totalPages = Math.ceil(totalCount / limit); + + return { + users: users, + currentPage: pageNumber, + totalPages, + totalCount, + }; + } catch (error) { + this.logger.error(`Failed to retrieve users`, error.stack); + throw new InternalServerErrorException('Failed to retrieve users'); + } + } + + private getFilteredQuery(filterDto: UserFilterDTO): SelectQueryBuilder { + const { organizationName, status } = filterDto; + const query = this.repository + .createQueryBuilder('user') + .leftJoinAndSelect('user.organization', 'organization') + .orderBy('user.createdAt', 'DESC'); + if (organizationName) { + const baseQuery = 'organization.name ILIKE :organizationName'; + query.andWhere(baseQuery, { organizationName: `%${organizationName}%` }); + } + if (status) { + query.andWhere(`user.status = '${status}'`); + } + return query; + } + + async update( + id: number, + data: UpdateUserDTO, + ): Promise { + const validationErrors = await validate(data, { + skipUndefinedProperties: true, + }); + if (validationErrors.length > 0) { + throw new UnprocessableEntityException({ + success: false, + errors: validationErrors, + }); + } + + const updateuser = await this.findById(id); + if (!(updateuser.email === data.email)) { + await this.checkForExistingUser(data.email); + } + + await this.repository.update(id, { + firstName: data.firstName, + lastName: data.lastName, + email: data.email, + status: data.status, + }); + + return this.findOne({ id }); + } + + public async canViewUserData( + userId: IUser['id'], + loggedInUser: ILoggedInUser, + ): Promise { + const user = await this.findById(userId); + + const isOwnUser = loggedInUser.id === userId; + const isOrgAdmin = + loggedInUser.organizationId === user.organization?.id && + loggedInUser.hasRole(Role.OrganizationAdmin); + const isAdmin = loggedInUser.hasRole(Role.Admin); + + const canViewUserData = isOwnUser || isOrgAdmin || isAdmin; + + if (!canViewUserData) { + throw new UnauthorizedException({ + success: false, + message: `Unable to fetch user data. Unauthorized.`, + }); + } + if (user.role === Role.ApiUser) { + const api_user = await this.get_apiuser_permission_status( + user.api_user_id, + ); + user['permission_status'] = api_user.permission_status; + } + return user; + } + public async geytokenforResetPassword(email): Promise { + return await this.emailConfirmationService.ConfirmationEmailForResetPassword( + email, + ); + } + + public async sentinvitiontoUser(inviteuser, email, invitationId) { + const getcurrenttoken = + await this.emailConfirmationService.getByEmail(email); + if (!getcurrenttoken) { + return { + message: 'Token not found', + success: false, + }; + } + const { id, confirmed } = getcurrenttoken; + const { token, expiryTimestamp } = + await this.emailConfirmationService.generatetoken(getcurrenttoken, id); + await this.emailConfirmationService.sendInvitation( + inviteuser, + email, + invitationId, + ); + } + + public async findUserByOrganization( + organizationId: number, + pageNumber: number, + limit: number, + ) { + return await this.repository + .createQueryBuilder('user') + .leftJoinAndSelect('user.organization', 'organization') + .where('organization.id = :organizationId', { organizationId }) + .orderBy('user.createdAt', 'DESC') + .skip((pageNumber - 1) * limit) + .take(limit) + .getManyAndCount(); + } + /**get all user of apiuser */ + public async findUserByApiUserId( + api_user_id: string, + pageNumber: number, + limit: number, + org_id?, + ) { + return await this.repository + .createQueryBuilder('user') + .leftJoinAndSelect('user.organization', 'organization') + .where('user.api_user_id = :api_user_id', { api_user_id }) + .andWhere(`role != :role`, { role: Role.ApiUser }) + .orderBy('user.createdAt', 'DESC') + .skip((pageNumber - 1) * limit) + .take(limit) + .getManyAndCount(); + } + /** ApiUser Fuction*/ + + async getApiuser(api_id: string): Promise { + return await this.apiUserEntityRepository.findOne({ + where: { + api_user_id: api_id, + }, + }); + } + /** + * This Function added for request of permission to apiuser in apiuser table + * @param api_id + * @param permissionIds + */ + async apiuser_permission_request(api_id, permissionIds) { + await this.apiUserEntityRepository.update(api_id, { + permissionIds: permissionIds, + permission_status: UserPermissionStatus.Request, + }); + } + async apiuser_permission_accepted_byadmin( + api_id: string, + status: UserPermissionStatus, + ) { + await this.apiUserEntityRepository.update(api_id, { + permission_status: status, + }); + return await this.apiUserEntityRepository.findOne({ + where: { + api_user_id: api_id, + }, + }); + } + /** + * This service method use for get info of permission request status(Request,Active and Deactive) + * @param api_id + * @returns + */ + async get_apiuser_permission_status(api_id: string) { + const status_apiuser_permissiom = + await this.apiUserEntityRepository.findOne({ + where: { + api_user_id: api_id, + }, + }); + + return status_apiuser_permissiom; + } + + /** + * this function create for get user list of ApiUser + * @param organizationName + * @param pageNumber + * @param limit + * @returns + */ + public async getApiUsers( + organizationName: string, + pageNumber: number, + limit: number, + ): Promise<{ + users: IUser[]; + currentPage: number; + totalPages: number; + totalCount: number; + }> { + const filterDto = new UserFilterDTO(); + filterDto.organizationName = organizationName; + const query = await this.getFilteredQuery(filterDto); + try { + const [apiusers, totalCount] = await query + .andWhere(`user.role = :role`, { role: Role.ApiUser }) + .skip((pageNumber - 1) * limit) + .take(limit) + .getManyAndCount(); + + const totalPages = Math.ceil(totalCount / limit); + return { + users: apiusers, + currentPage: pageNumber, + totalPages, + totalCount, + }; + } catch (error) { + this.logger.error(`Failed to retrieve apiusers`, error.stack); + throw new InternalServerErrorException('Failed to retrieve apiusers'); + } + } + + /** + * + * @param email + * @param token + * @returns + */ + + async createUserSession(user: any, token: string) { + await this.userloginSessionRepository.save({ + userId: user.id, + accesstoken_hash: token, + }); + return; + } + /** + * + * @param userId + * @returns + */ + async removeUsersession(userId: number) { + return await this.userloginSessionRepository.delete({ userId: userId }); + } + + async hasgetUserTokenvalid( + conditions: FindOptionsWhere, + ) { + return Boolean( + await this.userloginSessionRepository.findOne({ + where: conditions as FindOptionsWhere, + }), + ); + } +} From 4d29bf2eea08c6fc2647af2aa60f4fac6eede3e8 Mon Sep 17 00:00:00 2001 From: Aish1990 Date: Tue, 30 Apr 2024 11:19:34 +0530 Subject: [PATCH 17/89] Restored previous User Service --- apps/drec-api/src/pods/user/user.service.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/apps/drec-api/src/pods/user/user.service.ts b/apps/drec-api/src/pods/user/user.service.ts index 8e5e42286..0e8f76565 100755 --- a/apps/drec-api/src/pods/user/user.service.ts +++ b/apps/drec-api/src/pods/user/user.service.ts @@ -86,6 +86,7 @@ export class UserService { inviteuser?: boolean, ): Promise { await this.checkForExistingUser(data.email.toLowerCase()); + // @ts-ignore const api_user = await this.oauthClientCredentialsService.findOneByApiUserId( data.api_user_id, @@ -114,7 +115,9 @@ export class UserService { ); } } + // @ts-ignore if (data.orgid) { + // @ts-ignore org_id = data.orgid; } let role; @@ -248,6 +251,7 @@ export class UserService { if (user.role === Role.ApiUser) { const api_user = await this.get_apiuser_permission_status( + // @ts-ignore ts(2339) user.api_user_id, ); user['permission_status'] = api_user.permission_status; @@ -370,7 +374,9 @@ export class UserService { }); } const updateuser = await this.findById(id); + // @ts-ignore if (!(updateuser.email === email.toLowerCase())) { + // @ts-ignore await this.checkForExistingUser(email.toLowerCase()); } await this.repository.update(id, updateEntity); @@ -520,7 +526,9 @@ export class UserService { } const updateuser = await this.findById(id); + // @ts-ignore if (!(updateuser.email === data.email)) { + // @ts-ignore await this.checkForExistingUser(data.email); } @@ -556,6 +564,7 @@ export class UserService { } if (user.role === Role.ApiUser) { const api_user = await this.get_apiuser_permission_status( + // @ts-ignore ts(2339) user.api_user_id, ); user['permission_status'] = api_user.permission_status; From 60f84512a77faf8783fdb41c5abbc926247d90d9 Mon Sep 17 00:00:00 2001 From: Aish1990 Date: Tue, 30 Apr 2024 11:33:34 +0530 Subject: [PATCH 18/89] Removed ts-ignore from User Service --- apps/drec-api/src/pods/user/user.service.ts | 9 --------- 1 file changed, 9 deletions(-) diff --git a/apps/drec-api/src/pods/user/user.service.ts b/apps/drec-api/src/pods/user/user.service.ts index 0e8f76565..8e5e42286 100755 --- a/apps/drec-api/src/pods/user/user.service.ts +++ b/apps/drec-api/src/pods/user/user.service.ts @@ -86,7 +86,6 @@ export class UserService { inviteuser?: boolean, ): Promise { await this.checkForExistingUser(data.email.toLowerCase()); - // @ts-ignore const api_user = await this.oauthClientCredentialsService.findOneByApiUserId( data.api_user_id, @@ -115,9 +114,7 @@ export class UserService { ); } } - // @ts-ignore if (data.orgid) { - // @ts-ignore org_id = data.orgid; } let role; @@ -251,7 +248,6 @@ export class UserService { if (user.role === Role.ApiUser) { const api_user = await this.get_apiuser_permission_status( - // @ts-ignore ts(2339) user.api_user_id, ); user['permission_status'] = api_user.permission_status; @@ -374,9 +370,7 @@ export class UserService { }); } const updateuser = await this.findById(id); - // @ts-ignore if (!(updateuser.email === email.toLowerCase())) { - // @ts-ignore await this.checkForExistingUser(email.toLowerCase()); } await this.repository.update(id, updateEntity); @@ -526,9 +520,7 @@ export class UserService { } const updateuser = await this.findById(id); - // @ts-ignore if (!(updateuser.email === data.email)) { - // @ts-ignore await this.checkForExistingUser(data.email); } @@ -564,7 +556,6 @@ export class UserService { } if (user.role === Role.ApiUser) { const api_user = await this.get_apiuser_permission_status( - // @ts-ignore ts(2339) user.api_user_id, ); user['permission_status'] = api_user.permission_status; From ec326efebc003672850dacb0d5ca964a2d0a4db6 Mon Sep 17 00:00:00 2001 From: Aish1990 Date: Tue, 30 Apr 2024 11:47:34 +0530 Subject: [PATCH 19/89] Removed ts-ignore from get-lastread-influx.ts, PowerFormatter.ts --- apps/drec-api/src/utils/PowerFormatter.ts | 4 +--- apps/drec-api/src/utils/get-lastread-influx.ts | 8 -------- 2 files changed, 1 insertion(+), 11 deletions(-) diff --git a/apps/drec-api/src/utils/PowerFormatter.ts b/apps/drec-api/src/utils/PowerFormatter.ts index 185181ae1..bebfd73d6 100755 --- a/apps/drec-api/src/utils/PowerFormatter.ts +++ b/apps/drec-api/src/utils/PowerFormatter.ts @@ -23,10 +23,9 @@ export class PowerFormatter { } static getBaseValueFromValueInDisplayUnitInEthers(amount): string { - // @ts-ignore return BigNumberEthers.from( PowerFormatter.getBaseValueFromValueInDisplayUnit(Number(amount)), - ); + ).toString(); } static format(powerInWatt: number, includeDisplayUnit?: boolean): string { @@ -47,7 +46,6 @@ export class PowerFormatter { powerInWatt: number, includeDisplayUnit?: boolean, ): string { - // @ts-ignore return `${PowerFormatter.formatter.format(powerInWatt / Unit[PowerFormatter.displayUnit])}${ includeDisplayUnit ? ' ' + PowerFormatter.capacityDisplayUnit : '' }`; diff --git a/apps/drec-api/src/utils/get-lastread-influx.ts b/apps/drec-api/src/utils/get-lastread-influx.ts index 15c1d9503..f9d49b08f 100755 --- a/apps/drec-api/src/utils/get-lastread-influx.ts +++ b/apps/drec-api/src/utils/get-lastread-influx.ts @@ -14,12 +14,8 @@ export const NewfindLatestRead = async ( ): Promise => { const logger = new Logger('NewfindLatestRead'); - // @ts-ignore - // @ts-ignore const url = process.env.INFLUXDB_URL; - // @ts-ignore const token = process.env.INFLUXDB_TOKEN; - // @ts-ignore const org = process.env.INFLUXDB_ORG; logger.log('Connecting to InfluxDB...'); @@ -78,13 +74,9 @@ export const dbReader: any = () => { // const token = 'admin:admin' // const org = ''; - // @ts-ignore const url = process.env.INFLUXDB_URL; - // @ts-ignore const token = process.env.INFLUXDB_TOKEN; - // @ts-ignore const org = process.env.INFLUXDB_ORG; - // @ts-ignore return new InfluxDB({ url, token }).getQueryApi(org); }; From e3a004ce9eb85c781911d7c12a63d54bd14caf54 Mon Sep 17 00:00:00 2001 From: Aish1990 Date: Tue, 30 Apr 2024 13:44:00 +0530 Subject: [PATCH 20/89] Partially Removed ts-ignore from test/seed.ts --- apps/drec-api/test/seed.ts | 72 +++++++------------------------------- 1 file changed, 12 insertions(+), 60 deletions(-) diff --git a/apps/drec-api/test/seed.ts b/apps/drec-api/test/seed.ts index 89390c47b..112216901 100755 --- a/apps/drec-api/test/seed.ts +++ b/apps/drec-api/test/seed.ts @@ -1,10 +1,11 @@ import { OrganizationService } from '../src/pods/organization/organization.service'; import { UserService } from '../src/pods/user/user.service'; -// @ts-ignore ts(2305) -import { CreateUserDTO } from '../src/pods/user/dto/create-user.dto'; +import { CreateUserORGDTO } from '../src/pods/user/dto/create-user.dto'; import { Role } from '../src/utils/enums/role.enum'; import { DeviceDTO, NewDeviceDTO } from '../src/pods/device/dto'; import { + DevicetypeCode, + FuelCode, Installation, OffTaker, OrganizationStatus, @@ -23,19 +24,9 @@ export const testOrgs: OrganizationDTO[] = [ zipCode: 'Zip code', city: 'City', country: 'DE', - // @ts-ignore ts(2353) - businessType: 'Issuer', - tradeRegistryCompanyNumber: '987654321', - vatNumber: 'DE1000', status: OrganizationStatus.Active, blockchainAccountAddress: 'blockchainAccountAddress111', - signatoryFullName: 'Jane Williams', - signatoryAddress: 'Address', - signatoryZipCode: 'Zip Code', - signatoryCity: 'City', - signatoryCountry: 'DE', - signatoryEmail: 'owner2@mailinator.com', - signatoryPhoneNumber: 'Phone number', + organizationType: 'Developer', }, { id: 11, @@ -44,19 +35,9 @@ export const testOrgs: OrganizationDTO[] = [ zipCode: 'Zip code', city: 'City', country: 'null', - // @ts-ignore ts(2353) - businessType: 'Issuer', - tradeRegistryCompanyNumber: '987654321', - vatNumber: 'DE1000', status: OrganizationStatus.Active, blockchainAccountAddress: 'blockchainAccountAddress222', - signatoryFullName: 'John Smith', - signatoryAddress: 'Address', - signatoryZipCode: 'Zip Code', - signatoryCity: 'City', - signatoryCountry: 'DE', - signatoryEmail: 'buyer2@mailinator.com', - signatoryPhoneNumber: 'Phone number', + organizationType: 'Buyer', }, { id: 12, @@ -65,19 +46,9 @@ export const testOrgs: OrganizationDTO[] = [ zipCode: 'Zip code', city: 'City', country: 'DE', - // @ts-ignore ts(2353) - businessType: 'Issuer', - tradeRegistryCompanyNumber: '987654321', - vatNumber: 'DE1000', status: OrganizationStatus.Active, blockchainAccountAddress: 'blockchainAccountAddress333', - signatoryFullName: 'Jane Doe', - signatoryAddress: 'Address', - signatoryZipCode: 'Zip Code', - signatoryCity: 'City', - signatoryCountry: 'DE', - signatoryEmail: 'admin2@mailinator.com', - signatoryPhoneNumber: 'Phone number', + organizationType: 'Admin', }, { id: 13, @@ -86,54 +57,40 @@ export const testOrgs: OrganizationDTO[] = [ zipCode: 'Zip code', city: 'City', country: 'DE', - // @ts-ignore ts(2353) - businessType: 'Issuer', - tradeRegistryCompanyNumber: '987654321', - vatNumber: 'DE1000', status: OrganizationStatus.Active, blockchainAccountAddress: 'blockchainAccountAddress444', - signatoryFullName: 'Maria Robbins', - signatoryAddress: 'Address', - signatoryZipCode: 'Zip Code', - signatoryCity: 'City', - signatoryCountry: 'DE', - signatoryEmail: 'owner3@mailinator.com', - signatoryPhoneNumber: 'Phone number', + organizationType: 'Developer', }, ]; -export const testUsers: Omit[] = [ +export const testUsers: Omit[] = [ { - title: 'Mrs', firstName: 'Jane', lastName: 'Williams', email: 'owner2@mailinator.com', - telephone: 'telephone', password: '******123', + organizationType: 'Developer', }, { - title: 'Mr', firstName: 'John', lastName: 'Buyer', email: 'buyer2@mailinator.com', - telephone: 'telephone', password: '******123', + organizationType: 'Buyer' }, { - title: 'Mr', firstName: 'Joe', lastName: 'Miller2', email: 'admin2@mailinator.com', - telephone: 'telephone', password: '******123', + organizationType: 'ApiUser', }, { - title: 'Mrs', firstName: 'Maria', lastName: 'Williams', email: 'owner3@mailinator.com', - telephone: 'telephone', password: '******123', + organizationType: 'Developer', }, ]; @@ -155,13 +112,8 @@ const testDevices: Omit[] = [ commissioningDate: '2012-07-01', gridInterconnection: true, offTaker: OffTaker.HealthFacility, - sector: Sector.Agriculture, - standardCompliance: StandardCompliance.REC, yieldValue: 1000, - generatorsIds: [], - labels: '', impactStory: '', - data: '', images: [], }, { From 7cb0f26f5ecc335f212f6a4ec7aee96544f4ff38 Mon Sep 17 00:00:00 2001 From: Aish1990 Date: Fri, 3 May 2024 14:16:21 +0530 Subject: [PATCH 21/89] removed @ts-ignore from spec files and e2e test files --- apps/drec-api/src/models/User.ts | 3 +- .../certificate-log.service.spec.ts | 84 ++++++---- .../src/pods/device/device.service.spec.ts | 10 -- .../invitation/invitation.service.spec.ts | 12 +- apps/drec-api/src/pods/user/user.entity.ts | 5 +- .../src/pods/user/user.service.spec.ts | 19 --- apps/drec-api/test/device.e2e-spec.ts | 39 ++--- apps/drec-api/test/group-devices.e2e-spec.ts | 137 ++++++++------- apps/drec-api/test/organization.e2e-spec.ts | 22 +-- apps/drec-api/test/seed.ts | 156 +++++++----------- apps/drec-api/test/user.e2e-spec.ts | 22 +-- 11 files changed, 228 insertions(+), 281 deletions(-) diff --git a/apps/drec-api/src/models/User.ts b/apps/drec-api/src/models/User.ts index 86e7aa2b6..b2ad20c7c 100755 --- a/apps/drec-api/src/models/User.ts +++ b/apps/drec-api/src/models/User.ts @@ -1,5 +1,5 @@ import { IEmailConfirmation, IFullOrganization } from '.'; -import { Role, UserStatus, PermissionString } from '../utils/enums'; +import { Role, UserStatus, PermissionString, UserPermissionStatus } from '../utils/enums'; import { IModulePermissionsConfig } from './ACLModulesPermission'; export interface IUserProperties { id: number; @@ -14,6 +14,7 @@ export interface IUserProperties { roleId?: number; permissions?: PermissionString; api_user_id?: string; + permission_status?: UserPermissionStatus; } export interface IUserSeed extends IUser { diff --git a/apps/drec-api/src/pods/certificate-log/certificate-log.service.spec.ts b/apps/drec-api/src/pods/certificate-log/certificate-log.service.spec.ts index f25ccf16e..8ccdc0313 100644 --- a/apps/drec-api/src/pods/certificate-log/certificate-log.service.spec.ts +++ b/apps/drec-api/src/pods/certificate-log/certificate-log.service.spec.ts @@ -102,35 +102,41 @@ describe('CertificateLogService', () => { it('should create CSV file and send it as response', async () => { const mockData: CheckCertificateIssueDateLogForDeviceEntity[] = [ { + id: 1, certificate_issuance_startdate: new Date('2023-11-06T12:48:18.405Z'), certificate_issuance_enddate: new Date('2023-11-10T04:15:58.000Z'), readvalue_watthour: 10000, certificateTransactionUID: '14f8bcd3-095b-4659-90d8-bbc7523d14b4', - // @ts-ignore - reservation_name: 'secondreservation', externalId: 'Ext2', - blockchainCertificateId: 3, - }, + groupId: 2, + status: "Active", + ongoing_start_date: '2023-11-06T12:48:18.405Z', + ongoing_end_date: '2023-11-10T04:15:58.000Z', + } as CheckCertificateIssueDateLogForDeviceEntity, { + id: 2, certificate_issuance_startdate: new Date('2023-11-06T12:48:18.405Z'), certificate_issuance_enddate: new Date('2023-11-09T04:15:58.000Z'), readvalue_watthour: 10000, certificateTransactionUID: '37aa312a-405d-4e37-97f3-8af06a0b1e10', - // @ts-ignore - reservation_name: 'secondreservation', externalId: 'Ext2', - blockchainCertificateId: 2, - }, + groupId: 3, + status: 'Active', + ongoing_start_date: '2023-11-06T12:48:18.405Z', + ongoing_end_date: '2023-11-10T04:15:58.000Z', + } as CheckCertificateIssueDateLogForDeviceEntity, { + id: 3, certificate_issuance_startdate: new Date('2022-11-26T11:01:00.000Z'), certificate_issuance_enddate: new Date('2023-11-06T08:27:44.000Z'), readvalue_watthour: 10000, certificateTransactionUID: '770d39fd-fbb3-4eb9-82df-260a740b5151', - // @ts-ignore - reservation_name: 'secondreservation', externalId: 'Ext2', - blockchainCertificateId: 1, - }, + groupId: 4, + status: 'Pending', + ongoing_start_date: '2023-11-06T12:48:18.405Z', + ongoing_end_date: '2023-11-10T04:15:58.000Z', + } as CheckCertificateIssueDateLogForDeviceEntity, ]; jest @@ -175,35 +181,41 @@ describe('CertificateLogService', () => { const expectedLogs: CheckCertificateIssueDateLogForDeviceEntity[] = [ { + id: 1, + groupId: 2, certificate_issuance_startdate: new Date('2023-11-06T12:48:18.405Z'), certificate_issuance_enddate: new Date('2023-11-10T04:15:58.000Z'), readvalue_watthour: 10000, certificateTransactionUID: '14f8bcd3-095b-4659-90d8-bbc7523d14b4', - // @ts-ignore - reservation_name: 'secondreservation', externalId: 'Ext2', - blockchainCertificateId: 3, - }, + status: 'Active', + ongoing_start_date: '2023-11-06T12:48:18.405Z', + ongoing_end_date: '2023-11-10T04:15:58.000Z', + } as CheckCertificateIssueDateLogForDeviceEntity, { + id: 2, + groupId: 3, certificate_issuance_startdate: new Date('2023-11-06T12:48:18.405Z'), certificate_issuance_enddate: new Date('2023-11-09T04:15:58.000Z'), readvalue_watthour: 10000, certificateTransactionUID: '37aa312a-405d-4e37-97f3-8af06a0b1e10', - // @ts-ignore - reservation_name: 'secondreservation', externalId: 'Ext2', - blockchainCertificateId: 2, - }, + status: 'pending', + ongoing_start_date: '2023-11-06T12:48:18.405Z', + ongoing_end_date: '2023-11-09T04:15:58.000Z', + } as CheckCertificateIssueDateLogForDeviceEntity, { + id: 3, + groupId: 4, certificate_issuance_startdate: new Date('2022-11-26T11:01:00.000Z'), certificate_issuance_enddate: new Date('2023-11-06T08:27:44.000Z'), readvalue_watthour: 10000, certificateTransactionUID: '770d39fd-fbb3-4eb9-82df-260a740b5151', - // @ts-ignore - reservation_name: 'secondreservation', externalId: 'Ext2', - blockchainCertificateId: 1, - }, + status: 'pending', + ongoing_start_date: '2023-11-06T12:48:18.405Z', + ongoing_end_date: '2023-11-09T04:15:58.000Z', + } as CheckCertificateIssueDateLogForDeviceEntity, ]; jest @@ -268,8 +280,10 @@ describe('CertificateLogService', () => { }, ownerId: '', hasOrganization: false, - // @ts-ignore - hasPermission: true, + permissions: PermissionString.Write, + hasPermission: function (...permissions: PermissionString[]): boolean { + throw new Error('Function not implemented.'); + }, api_user_id: 'apiuserId', }; const filterDto: FilterDTO = { @@ -326,7 +340,6 @@ describe('CertificateLogService', () => { certificate_issuance_enddate: new Date('2023-11-10T04:15:58.000Z'), readvalue_watthour: 10000, certificateTransactionUID: '14f8bcd3-095b-4659-90d8-bbc7523d14b4', - // @ts-ignore reservation_name: 'secondreservation', externalId: 'Ext2', blockchainCertificateId: 3, @@ -338,7 +351,6 @@ describe('CertificateLogService', () => { certificate_issuance_enddate: new Date('2023-11-09T04:15:58.000Z'), readvalue_watthour: 10000, certificateTransactionUID: '37aa312a-405d-4e37-97f3-8af06a0b1e10', - // @ts-ignore reservation_name: 'secondreservation', externalId: 'Ext2', blockchainCertificateId: 2, @@ -350,7 +362,6 @@ describe('CertificateLogService', () => { certificate_issuance_enddate: new Date('2023-11-06T08:27:44.000Z'), readvalue_watthour: 10000, certificateTransactionUID: '770d39fd-fbb3-4eb9-82df-260a740b5151', - // @ts-ignore reservation_name: 'secondreservation', externalId: 'Ext2', blockchainCertificateId: 1, @@ -401,8 +412,10 @@ describe('CertificateLogService', () => { }, ownerId: '', hasOrganization: false, - // @ts-ignore - hasPermission: true, + permissions: PermissionString.Write, + hasPermission: function (...permissions: PermissionString[]): boolean { + throw new Error('Function not implemented.'); + }, api_user_id: 'apiuserId', }; const filterDto: FilterDTO = { @@ -459,7 +472,6 @@ describe('CertificateLogService', () => { certificate_issuance_enddate: new Date('2023-11-10T04:15:58.000Z'), readvalue_watthour: 10000, certificateTransactionUID: '14f8bcd3-095b-4659-90d8-bbc7523d14b4', - //@ts-ignore reservation_name: 'secondreservation', externalId: 'Ext2', blockchainCertificateId: 3, @@ -471,7 +483,6 @@ describe('CertificateLogService', () => { certificate_issuance_enddate: new Date('2023-11-09T04:15:58.000Z'), readvalue_watthour: 10000, certificateTransactionUID: '37aa312a-405d-4e37-97f3-8af06a0b1e10', - //@ts-ignore reservation_name: 'secondreservation', externalId: 'Ext2', blockchainCertificateId: 2, @@ -483,7 +494,6 @@ describe('CertificateLogService', () => { certificate_issuance_enddate: new Date('2023-11-06T08:27:44.000Z'), readvalue_watthour: 10000, certificateTransactionUID: '770d39fd-fbb3-4eb9-82df-260a740b5151', - //@ts-ignore reservation_name: 'secondreservation', externalId: 'Ext2', blockchainCertificateId: 1, @@ -523,8 +533,10 @@ describe('CertificateLogService', () => { }, ownerId: '', hasOrganization: false, - // @ts-ignore - hasPermission: true, + permissions: PermissionString.Write, + hasPermission: function (...permissions: PermissionString[]): boolean { + throw new Error('Function not implemented.'); + }, api_user_id: 'apiuserId', }; const filterDto: FilterDTO = { diff --git a/apps/drec-api/src/pods/device/device.service.spec.ts b/apps/drec-api/src/pods/device/device.service.spec.ts index ef6c49c69..f7b0d7673 100644 --- a/apps/drec-api/src/pods/device/device.service.spec.ts +++ b/apps/drec-api/src/pods/device/device.service.spec.ts @@ -107,8 +107,6 @@ describe('DeviceService', () => { address: 'Bangalore', latitude: '23.65362', longitude: '25.43647', - // @ts-ignore - countryCodename: 'India', fuelCode: FuelCode.ES100, //'ES100', deviceTypeCode: DevicetypeCode.TC110, //'TC110', capacity: 2500, @@ -116,7 +114,6 @@ describe('DeviceService', () => { gridInterconnection: true, offTaker: OffTaker.School, //'School', impactStory: null, - data: null, images: null, deviceDescription: DeviceDescription.SolarLantern, //'Solar Lantern', energyStorage: true, @@ -190,8 +187,6 @@ describe('DeviceService', () => { address: 'Bangalore', latitude: '23.65362', longitude: '25.43647', - // @ts-ignore - countryCodename: 'India', fuelCode: FuelCode.ES100, //'ES100', deviceTypeCode: DevicetypeCode.TC110, //'TC110', capacity: 2500, @@ -199,7 +194,6 @@ describe('DeviceService', () => { gridInterconnection: true, offTaker: OffTaker.School, //'School', impactStory: null, - data: null, images: null, deviceDescription: DeviceDescription.SolarLantern, //'Solar Lantern', energyStorage: true, @@ -272,9 +266,7 @@ describe('DeviceService', () => { const organizationEntity = { id: 1, name: 'orgName', - // @ts-ignore organizationType: Role.OrganizationAdmin, - // @ts-ignore orgEmail: 'testsweya@gmail.com', address: 'Chennai', zipCode: '600001', @@ -611,9 +603,7 @@ describe('DeviceService', () => { const organizationEntity = { id: 1, name: 'orgName', - // @ts-ignore organizationType: Role.OrganizationAdmin, - // @ts-ignore orgEmail: 'testsweya@gmail.com', address: 'Chennai', zipCode: '600001', diff --git a/apps/drec-api/src/pods/invitation/invitation.service.spec.ts b/apps/drec-api/src/pods/invitation/invitation.service.spec.ts index d4ff3d53e..8dd04fd69 100644 --- a/apps/drec-api/src/pods/invitation/invitation.service.spec.ts +++ b/apps/drec-api/src/pods/invitation/invitation.service.spec.ts @@ -255,6 +255,7 @@ describe('InvitationService', () => { }); await expect(newcreatespy).toHaveBeenCalledWith( { + api_user_id: inviteeOrganization.api_user_id, firstName: firstName, lastName: lastName, email: email, @@ -262,9 +263,6 @@ describe('InvitationService', () => { orgName: inviteeOrganization.name, organizationType: inviteeOrganization.organizationType, orgid: orgId, - client: { - api_user_id: inviteeOrganization.api_user_id, - }, } as CreateUserORGDTO, UserStatus.Pending, true, @@ -278,9 +276,7 @@ describe('InvitationService', () => { orgName: inviteeOrganization.name, organizationType: inviteeOrganization.organizationType, orgid: orgId, - client: { - api_user_id: inviteeOrganization.api_user_id, - }, + api_user_id: inviteeOrganization.api_user_id, } as CreateUserORGDTO, email, mockinvitedUser.id, @@ -485,9 +481,7 @@ describe('InvitationService', () => { orgName: inviteeOrganization.name, organizationType: inviteeOrganization.organizationType, orgid: orgId, - client: { - api_user_id: inviteeOrganization.api_user_id, - }, + api_user_id: inviteeOrganization.api_user_id, } as CreateUserORGDTO, UserStatus.Pending, true, diff --git a/apps/drec-api/src/pods/user/user.entity.ts b/apps/drec-api/src/pods/user/user.entity.ts index 43ce6085d..ccd6bd9d9 100755 --- a/apps/drec-api/src/pods/user/user.entity.ts +++ b/apps/drec-api/src/pods/user/user.entity.ts @@ -9,7 +9,7 @@ import { import { Exclude } from 'class-transformer'; import { ExtendedBaseEntity } from '@energyweb/origin-backend-utils'; import { ApiProperty } from '@nestjs/swagger'; -import { Role, UserStatus, PermissionString } from '../../utils/enums'; +import { Role, UserStatus, PermissionString, UserPermissionStatus } from '../../utils/enums'; import { IsEnum, IsString } from 'class-validator'; import { IUser } from '../../models'; import { Organization } from '../organization/organization.entity'; @@ -98,4 +98,7 @@ export class User extends ExtendedBaseEntity implements IUser { // updateTimestamp() { // this.updatedAt = new Date(); // Set the updatedAt field to the current date and time // } + + @IsEnum(UserPermissionStatus) + permission_status?: UserPermissionStatus; } diff --git a/apps/drec-api/src/pods/user/user.service.spec.ts b/apps/drec-api/src/pods/user/user.service.spec.ts index 53c473d2f..a0b686819 100644 --- a/apps/drec-api/src/pods/user/user.service.spec.ts +++ b/apps/drec-api/src/pods/user/user.service.spec.ts @@ -122,9 +122,7 @@ describe('UserService', () => { const orgData: Organization = { id: 1, name: userData.orgName, - // @ts-ignore organizationType: userData.organizationType, - // @ts-ignore orgEmail: userData.email, address: userData.orgAddress, zipCode: null, @@ -165,7 +163,6 @@ describe('UserService', () => { const result = await service.newcreate(userData); expect(result).toBeDefined(); - // @ts-ignore expect(service.checkForExistingUser).toHaveBeenCalledWith( userData.email.toLowerCase(), ); @@ -178,9 +175,7 @@ describe('UserService', () => { expect(organizationService.newcreate).toHaveBeenCalledWith( expect.objectContaining({ name: userData.orgName, - // @ts-ignore organizationType: userData.organizationType, - // @ts-ignore orgEmail: userData.email, address: userData.orgAddress, api_user_id: userData.api_user_id, @@ -189,11 +184,8 @@ describe('UserService', () => { expect(repository.save).toHaveBeenCalledWith( expect.objectContaining({ - // @ts-ignore firstName: userData.firstName, - // @ts-ignore lastName: userData.lastName, - // @ts-ignore email: userData.email.toLowerCase(), password: expect.any(String), notifications: true, @@ -298,9 +290,7 @@ describe('UserService', () => { id: 1, api_user_id: userData.api_user_id, name: userData.orgName, - // @ts-ignore organizationType: userData.organizationType, - // @ts-ignore orgEmail: userData.email, address: userData.orgAddress, zipCode: null, @@ -334,7 +324,6 @@ describe('UserService', () => { const resultPromise = service.adminnewcreate(userData); await expect(resultPromise).resolves.toBeDefined(); - // @ts-ignore await expect(service.checkForExistingUser).toHaveBeenCalledWith( userData.email.toLowerCase(), ); @@ -343,19 +332,14 @@ describe('UserService', () => { ); await expect(organizationService.newcreate).toHaveBeenCalledWith({ name: userData.orgName, - //@ts-ignore organizationType: userData.organizationType, - // @ts-ignore orgEmail: userData.email, address: userData.orgAddress, }); await expect(repository.save).toHaveBeenCalledWith( expect.objectContaining({ - // @ts-ignore firstName: userData.firstName, - // @ts-ignore lastName: userData.lastName, - // @ts-ignore email: userData.email.toLowerCase(), password: expect.any(String), notifications: true, @@ -679,7 +663,6 @@ describe('UserService', () => { it('should include permission_status when the found user has a role of Role.ApiUser', async () => { const userId = 1; - // @ts-ignore mockuserEntity.permission_status = UserPermissionStatus.Active; const findOneSpy = jest .spyOn(service, 'findOne') @@ -697,7 +680,6 @@ describe('UserService', () => { expect(permission_statusSpy).toHaveBeenCalledWith( mockuserEntity.api_user_id, ); - // @ts-ignore expect(user.permission_status).toBe(UserPermissionStatus.Request); }); @@ -752,7 +734,6 @@ describe('UserService', () => { const user = await service.findById(userId); expect(findOneSpy).toHaveBeenCalledWith({ id: userId }); - // @ts-ignore expect(user.permission_status).toBeUndefined(); }); }); diff --git a/apps/drec-api/test/device.e2e-spec.ts b/apps/drec-api/test/device.e2e-spec.ts index 2a994ce09..62b09f8bf 100755 --- a/apps/drec-api/test/device.e2e-spec.ts +++ b/apps/drec-api/test/device.e2e-spec.ts @@ -18,6 +18,8 @@ import { import { DeviceService } from '../src/pods/device/device.service'; import { DeviceOrderBy, + DevicetypeCode, + FuelCode, Installation, OffTaker, Sector, @@ -122,24 +124,19 @@ describe('Device tests', () => { latitude: '34.921213', longitude: '135.717309', countryCode: 'DE', - zipCode: '111111', - // @ts-ignore ts(2322) - fuelCode: 'ES100', - // @ts-ignore ts(2322) - deviceTypeCode: 'TC110', - installationConfiguration: Installation.StandAlone, + fuelCode: FuelCode.ES100, + deviceTypeCode: DevicetypeCode.TC110, capacity: 1340, commissioningDate: '2012-07-01', gridInterconnection: true, offTaker: OffTaker.Commercial, - sector: Sector.Agriculture, - standardCompliance: StandardCompliance.IREC, yieldValue: 1000, - generatorsIds: [], - labels: '', impactStory: '', - data: '', images: [], + energyStorage: true, + energyStorageCapacity: 900, + qualityLabels: '', + version:'1.0', }; await loginUser(loggedUser); const { body: updatedDevice } = await postDevice( @@ -180,25 +177,20 @@ describe('Device tests', () => { address: 'Somewhere far away', latitude: '34.921213', longitude: '135.717309', - // @ts-ignore ts(2322) - fuelCode: 'ES100', - // @ts-ignore ts(2322) - deviceTypeCode: 'TC110', - installationConfiguration: Installation.StandAlone, + fuelCode: FuelCode.ES100, + deviceTypeCode: DevicetypeCode.TC110, capacity: 1340, countryCode: 'DE', - zipCode: '111111', commissioningDate: '2012-07-01', gridInterconnection: true, offTaker: OffTaker.Commercial, - sector: Sector.Agriculture, - standardCompliance: StandardCompliance.IREC, yieldValue: 1000, - generatorsIds: [], - labels: '', impactStory: '', - data: '', images: [], + energyStorage: true, + energyStorageCapacity: 900, + qualityLabels: '', + version:'1.0', }; await loginUser(loggedUser); await postDevice('', HttpStatus.FORBIDDEN, partialDevice); @@ -211,8 +203,7 @@ describe('Device tests', () => { }; await loginUser(loggedUser); const orderFilter: Partial = { - // @ts-ignore ts(2339) - orderBy: [DeviceOrderBy.Sector, DeviceOrderBy.OffTaker], + orderBy: [DeviceOrderBy.Country, DeviceOrderBy.OffTaker], }; const { body: deviceGroups } = await requestUngrouppedDevice( HttpStatus.OK, diff --git a/apps/drec-api/test/group-devices.e2e-spec.ts b/apps/drec-api/test/group-devices.e2e-spec.ts index dbf9755c3..99b693536 100755 --- a/apps/drec-api/test/group-devices.e2e-spec.ts +++ b/apps/drec-api/test/group-devices.e2e-spec.ts @@ -18,10 +18,11 @@ import { UpdateDeviceGroupDTO, } from '../src/pods/device-group/dto'; import { Device } from '../src/pods/device'; -import { IFullOrganization } from '../src/models'; +import { BuyerReservationCertificateGenerationFrequency, IFullOrganization } from '../src/models'; import { CapacityRange, CommissioningDateRange } from '../src/utils/enums'; import TestDevicesToGroup from './test-devices-for-grouping.json'; import { NewDeviceDTO } from '../src/pods/device/dto'; +import { OrganizationFilterDTO } from 'src/pods/admin/dto/organization-filter.dto'; describe('Device Group tests', () => { let app: INestApplication; @@ -100,39 +101,34 @@ describe('Device Group tests', () => { email: 'admin2@mailinator.com', password: '******123', }; + const filterDto : OrganizationFilterDTO = { + organizationName: undefined, + }; + const pageNumber = 1; + const limit = 5; await loginUser(loggedUser); const { body: devices } = await requestDevice('', HttpStatus.OK); - // @ts-ignore ts(2554) - const orgs = await organizationService.getAll(); + const orgs = await organizationService.getAll(filterDto, pageNumber, limit); const firstBatch = devices.filter((device: Device) => - // @ts-ignore ts(2339) - orgs.map((o: IFullOrganization) => device.organizationId === o.id), + orgs.organizations.map((o: IFullOrganization) => device.organizationId === o.id), ); const secondBatch = firstBatch.filter( (device: Device) => device.organizationId !== firstBatch[0].organizationId, ); - const newDeviceGroup: NewDeviceGroupDTO = { + const newDeviceGroup: AddGroupDTO = { name: 'test-device-group-2', deviceIds: [firstBatch[0].id, secondBatch[0].id], - countryCode: firstBatch[0]?.countryCode, - fuelCode: firstBatch[0]?.fuelCode, - // @ts-ignore ts(2353) - standardCompliance: firstBatch[0]?.standardCompliance, - deviceTypeCodes: [firstBatch[0]?.deviceTypeCode], - offTakers: [firstBatch[0]?.offTaker], - installationConfigurations: [firstBatch[0]?.installationConfiguration], - sectors: [firstBatch[0]?.sector], - gridInterconnection: firstBatch[0]?.gridInterconnection, - aggregatedCapacity: firstBatch[0]?.capacity, - // @ts-ignore ts(2339) - capacityRange: CapacityRange.Between_51_500_w, - commissioningDateRange: [CommissioningDateRange.Between_years_6_10], - yieldValue: firstBatch[0]?.yieldValue, - labels: [firstBatch[0]?.labels], + targetCapacityInMegaWattHour: 1000, + reservationStartDate: new Date('2024-05-03T05:26:14.620Z'), + reservationEndDate: new Date('2024-05-03T05:26:14.620Z'), + reservationExpiryDate: new Date('2024-05-30T05:26:14.620Z'), + authorityToExceed: true, + frequency: BuyerReservationCertificateGenerationFrequency.daily, + continueWithReservationIfOneOrMoreDevicesUnavailableForReservation: false, + continueWithReservationIfTargetCapacityIsLessThanDeviceTotalCapacityBetweenDuration: false, }; - // @ts-ignore ts(2345) await postDeviceGroup('', HttpStatus.NOT_ACCEPTABLE, newDeviceGroup); }); @@ -182,33 +178,28 @@ describe('Device Group tests', () => { }; await loginUser(loggedUser); const { body: devices } = await requestDevice('', HttpStatus.OK); - // @ts-ignore ts(2554) - const orgs = await organizationService.getAll(); + const filterDto : OrganizationFilterDTO = { + organizationName: undefined, + }; + const pageNumber = 1; + const limit = 5; + const orgs = await organizationService.getAll(filterDto, pageNumber, limit); const firstBatch = devices.filter((device: Device) => - // @ts-ignore ts(2339) - orgs.map((o: IFullOrganization) => device.organizationId === o.id), + orgs.organizations.map((o: IFullOrganization) => device.organizationId === o.id), ); - const newDeviceGroup: NewDeviceGroupDTO = { + const newDeviceGroup: AddGroupDTO = { name: 'test-device-group-2', deviceIds: [firstBatch[0]?.id], - countryCode: firstBatch[0]?.countryCode, - fuelCode: firstBatch[0]?.fuelCode, - // @ts-ignore ts(2322) - standardCompliance: firstBatch[0]?.standardCompliance, - deviceTypeCodes: [firstBatch[0]?.deviceTypeCode], - offTakers: [firstBatch[0]?.offTaker], - installationConfigurations: [firstBatch[0]?.installationConfiguration], - sectors: [firstBatch[0]?.sector], - gridInterconnection: firstBatch[0]?.gridInterconnection, - aggregatedCapacity: firstBatch[0]?.capacity, - // @ts-ignore ts(2339) - capacityRange: CapacityRange.Between_51_500_w, - commissioningDateRange: [CommissioningDateRange.Between_years_6_10], - yieldValue: firstBatch[0]?.yieldValue, - labels: [firstBatch[0]?.labels], + targetCapacityInMegaWattHour: 1000, + reservationStartDate: new Date('2024-05-03T05:26:14.620Z'), + reservationEndDate: new Date('2024-05-03T05:26:14.620Z'), + reservationExpiryDate: new Date('2024-05-30T05:26:14.620Z'), + authorityToExceed: true, + frequency: BuyerReservationCertificateGenerationFrequency.daily, + continueWithReservationIfOneOrMoreDevicesUnavailableForReservation: false, + continueWithReservationIfTargetCapacityIsLessThanDeviceTotalCapacityBetweenDuration: false, }; - // @ts-ignore ts(2345) await postDeviceGroup('', HttpStatus.CREATED, newDeviceGroup); const { body: deviceGroups } = await requestDeviceGroup('', HttpStatus.OK); const { body: deviceGroup } = await requestDeviceGroup( @@ -234,17 +225,27 @@ describe('Device Group tests', () => { }; await loginUser(loggedUser); const { body: devices } = await requestDevice('', HttpStatus.OK); - // @ts-ignore ts(2554) - const orgs = await organizationService.getAll(); + const filterDto : OrganizationFilterDTO = { + organizationName: undefined, + }; + const pageNumber = 1; + const limit = 5; + const orgs = await organizationService.getAll(filterDto, pageNumber, limit); const firstBatch = devices.filter((device: Device) => - // @ts-ignore ts(2339) - orgs.map((o: IFullOrganization) => device.organizationId === o.id), + orgs.organizations.map((o: IFullOrganization) => device.organizationId === o.id), ); - // @ts-ignore ts(2740) const newDeviceGroup: AddGroupDTO = { name: 'test-device-group-3', deviceIds: [firstBatch[0].id], + targetCapacityInMegaWattHour: 1000, + reservationStartDate: new Date('2024-05-03T05:26:14.620Z'), + reservationEndDate: new Date('2024-05-03T05:26:14.620Z'), + reservationExpiryDate: new Date('2024-05-30T05:26:14.620Z'), + authorityToExceed: true, + frequency: BuyerReservationCertificateGenerationFrequency.daily, + continueWithReservationIfOneOrMoreDevicesUnavailableForReservation: false, + continueWithReservationIfTargetCapacityIsLessThanDeviceTotalCapacityBetweenDuration: false, }; await postDeviceGroup('', HttpStatus.CREATED, newDeviceGroup); const { body: deviceGroups } = await requestDeviceGroup('', HttpStatus.OK); @@ -271,17 +272,27 @@ describe('Device Group tests', () => { }; await loginUser(loggedUser); const { body: devices } = await requestDevice('', HttpStatus.OK); - // @ts-ignore ts(2554) - const orgs = await organizationService.getAll(); + const filterDto : OrganizationFilterDTO = { + organizationName: undefined, + }; + const pageNumber = 1; + const limit = 5; + const orgs = await organizationService.getAll(filterDto, pageNumber, limit); const firstBatch = devices.filter((device: Device) => - // @ts-ignore ts(2339) - orgs.map((o: IFullOrganization) => device.organizationId === o.id), + orgs.organizations.map((o: IFullOrganization) => device.organizationId === o.id), ); - // @ts-ignore ts(2740) const newDeviceGroup: AddGroupDTO = { name: 'test-device-group-3', deviceIds: [firstBatch[0].id], + targetCapacityInMegaWattHour: 1000, + reservationStartDate: new Date('2024-05-03T05:26:14.620Z'), + reservationEndDate: new Date('2024-05-03T05:26:14.620Z'), + reservationExpiryDate: new Date('2024-05-30T05:26:14.620Z'), + authorityToExceed: true, + frequency: BuyerReservationCertificateGenerationFrequency.daily, + continueWithReservationIfOneOrMoreDevicesUnavailableForReservation: false, + continueWithReservationIfTargetCapacityIsLessThanDeviceTotalCapacityBetweenDuration: false, }; await postDeviceGroup('', HttpStatus.CREATED, newDeviceGroup); @@ -315,16 +326,26 @@ describe('Device Group tests', () => { }; await loginUser(loggedUser); const { body: devices } = await requestDevice('', HttpStatus.OK); - // @ts-ignore ts(2554) - const orgs = await organizationService.getAll(); + const filterDto : OrganizationFilterDTO = { + organizationName: undefined, + }; + const pageNumber = 1; + const limit = 5; + const orgs = await organizationService.getAll(filterDto, pageNumber, limit); const firstBatch = devices.filter((device: Device) => - // @ts-ignore ts(2339) - orgs.map((o: IFullOrganization) => device.organizationId === o.id), + orgs.organizations.map((o: IFullOrganization) => device.organizationId === o.id), ); - // @ts-ignore ts(2740) const newDeviceGroup: AddGroupDTO = { name: 'test-device-group', deviceIds: [firstBatch[0]?.id], + targetCapacityInMegaWattHour: 1000, + reservationStartDate: new Date('2024-05-03T05:26:14.620Z'), + reservationEndDate: new Date('2024-05-03T05:26:14.620Z'), + reservationExpiryDate: new Date('2024-05-30T05:26:14.620Z'), + authorityToExceed: true, + frequency: BuyerReservationCertificateGenerationFrequency.daily, + continueWithReservationIfOneOrMoreDevicesUnavailableForReservation: false, + continueWithReservationIfTargetCapacityIsLessThanDeviceTotalCapacityBetweenDuration: false, }; return await postDeviceGroup('', HttpStatus.CREATED, newDeviceGroup); }; diff --git a/apps/drec-api/test/organization.e2e-spec.ts b/apps/drec-api/test/organization.e2e-spec.ts index 71e378ce2..bade95189 100755 --- a/apps/drec-api/test/organization.e2e-spec.ts +++ b/apps/drec-api/test/organization.e2e-spec.ts @@ -15,6 +15,7 @@ import { UpdateOrganizationDTO, } from '../src/pods/organization/dto'; import { DeviceService } from '../src/pods/device/device.service'; +import { OrganizationFilterDTO } from 'src/pods/admin/dto/organization-filter.dto'; describe('Organization tests', () => { let app: INestApplication; @@ -111,8 +112,13 @@ describe('Organization tests', () => { const partialOrg = { name: 'Device Owner - Update', }; - // @ts-ignore ts(2554) - const orgs = await organizationService.getAll(); + const filterDto: OrganizationFilterDTO = { + organizationName: undefined, + organizationType: undefined, + }; + const pageNumber = 1; + const limit = 5; + const orgs = await organizationService.getAll(filterDto, pageNumber, limit); await loginUser(loggedUser); const { body: updatedOrg } = await updateAdminOrganization( orgs[0]?.id.toString(), @@ -148,17 +154,7 @@ describe('Organization tests', () => { zipCode: 'Zip code', city: 'City', country: 'DE', - // @ts-ignore ts(2353) - businessType: 'Issuer', - tradeRegistryCompanyNumber: '987654321', - vatNumber: 'DE1000', - signatoryFullName: 'New user', - signatoryAddress: 'Address', - signatoryZipCode: 'Zip Code', - signatoryCity: 'City', - signatoryCountry: 'DE', - signatoryEmail: 'owner3@mailinator.com', - signatoryPhoneNumber: 'Phone number', + organizationType: 'DeviceOwner', }; await loginUser(loggedUser); await postOrganization('', HttpStatus.FORBIDDEN, partialOrg); diff --git a/apps/drec-api/test/seed.ts b/apps/drec-api/test/seed.ts index 112216901..5ca7bece7 100755 --- a/apps/drec-api/test/seed.ts +++ b/apps/drec-api/test/seed.ts @@ -102,12 +102,8 @@ const testDevices: Omit[] = [ latitude: '34.921213', longitude: '135.717309', countryCode: 'DE', - zipCode: '111111', - // @ts-ignore ts(2322) - fuelCode: 'ES200', - // @ts-ignore ts(2322) - deviceTypeCode: 'T020001', - installationConfiguration: Installation.StandAlone, + fuelCode: FuelCode.ES100, + deviceTypeCode: DevicetypeCode.TC110, capacity: 1500, commissioningDate: '2012-07-01', gridInterconnection: true, @@ -115,6 +111,12 @@ const testDevices: Omit[] = [ yieldValue: 1000, impactStory: '', images: [], + api_user_id: 'b8047b28-13f5-485e-963c-7c7fdc43300d', + developerExternalId: 'b8047b28-13f5-485e-963c-7c7fdc43300d', + energyStorage: true, + energyStorageCapacity: 900, + qualityLabels: '', + timezone: '', }, { externalId: 'DREC03', @@ -123,24 +125,21 @@ const testDevices: Omit[] = [ latitude: '34.921213', longitude: '135.717309', countryCode: 'DE', - zipCode: '111111', - // @ts-ignore ts(2322) - fuelCode: 'ES200', - // @ts-ignore ts(2322) - deviceTypeCode: 'TC110', - installationConfiguration: Installation.StandAlone, + fuelCode: FuelCode.ES100, + deviceTypeCode: DevicetypeCode.TC110, capacity: 1600, commissioningDate: '2012-07-01', gridInterconnection: true, offTaker: OffTaker.PublicSector, - sector: Sector.Education, - standardCompliance: StandardCompliance.REC, yieldValue: 1000, - generatorsIds: [], - labels: '', impactStory: '', - data: '', images: [], + api_user_id: 'b8047b28-13f5-485e-963c-7c7fdc43300d', + developerExternalId: 'b8047b28-13f5-485e-963c-7c7fdc43300d', + energyStorage: true, + energyStorageCapacity: 900, + qualityLabels: '', + timezone: '', }, { externalId: 'DREC04', @@ -149,24 +148,21 @@ const testDevices: Omit[] = [ latitude: '34.921213', longitude: '135.717309', countryCode: 'DE', - zipCode: '111111', - // @ts-ignore ts(2322) - fuelCode: 'ES200', - // @ts-ignore ts(2322) - deviceTypeCode: 'TC110', - installationConfiguration: Installation.StandAlone, + fuelCode: FuelCode.ES100, + deviceTypeCode: DevicetypeCode.TC110, capacity: 1750, commissioningDate: '2012-07-01', gridInterconnection: true, offTaker: OffTaker.Commercial, - sector: Sector.PublicServices, - standardCompliance: StandardCompliance.REC, yieldValue: 1000, - generatorsIds: [], - labels: '', impactStory: '', - data: '', images: [], + api_user_id: 'b8047b28-13f5-485e-963c-7c7fdc43300d', + developerExternalId: 'b8047b28-13f5-485e-963c-7c7fdc43300d', + energyStorage: true, + energyStorageCapacity: 900, + qualityLabels: '', + timezone: '', }, { externalId: 'DREC05', @@ -175,24 +171,21 @@ const testDevices: Omit[] = [ latitude: '34.921213', longitude: '135.717309', countryCode: 'DE', - zipCode: '111111', - // @ts-ignore ts(2322) - fuelCode: 'ES200', - // @ts-ignore ts(2322) - deviceTypeCode: 'TC110', - installationConfiguration: Installation.StandAlone, + fuelCode: FuelCode.ES100, + deviceTypeCode: DevicetypeCode.TC110, capacity: 1750, commissioningDate: '2012-07-01', gridInterconnection: true, offTaker: OffTaker.Residential, - sector: Sector.Health, - standardCompliance: StandardCompliance.REC, yieldValue: 1000, - generatorsIds: [], - labels: '', impactStory: '', - data: '', images: [], + api_user_id: 'b8047b28-13f5-485e-963c-7c7fdc43300d', + developerExternalId: 'b8047b28-13f5-485e-963c-7c7fdc43300d', + energyStorage: true, + energyStorageCapacity: 900, + qualityLabels: '', + timezone: '', }, ]; @@ -204,24 +197,19 @@ export const batchDevices: NewDeviceDTO[] = [ latitude: '34.921213', longitude: '135.717309', countryCode: 'DE', - zipCode: '111111', - // @ts-ignore ts(2322) - fuelCode: 'ES200', - // @ts-ignore ts(2322) - deviceTypeCode: 'T020001', - installationConfiguration: Installation.StandAlone, + fuelCode: FuelCode.ES100, + deviceTypeCode: DevicetypeCode.TC110, capacity: 1500, commissioningDate: '2012-07-01', gridInterconnection: true, offTaker: OffTaker.Industrial, - sector: Sector.Agriculture, - standardCompliance: StandardCompliance.REC, yieldValue: 1000, - generatorsIds: [], - labels: '', impactStory: '', - data: '', images: [], + energyStorage: true, + energyStorageCapacity: 900, + qualityLabels: '', + version:'1.0', }, { externalId: 'DREC32', @@ -230,24 +218,19 @@ export const batchDevices: NewDeviceDTO[] = [ latitude: '34.921213', longitude: '135.717309', countryCode: 'DE', - zipCode: '111111', - // @ts-ignore ts(2322) - fuelCode: 'ES200', - // @ts-ignore ts(2322) - deviceTypeCode: 'TC110', - installationConfiguration: Installation.StandAlone, + fuelCode: FuelCode.ES100, + deviceTypeCode: DevicetypeCode.TC110, capacity: 1600, commissioningDate: '2012-07-01', gridInterconnection: true, offTaker: OffTaker.Commercial, - sector: Sector.Manufacturing, - standardCompliance: StandardCompliance.REC, yieldValue: 1000, - generatorsIds: [], - labels: '', impactStory: '', - data: '', images: [], + energyStorage: true, + energyStorageCapacity: 900, + qualityLabels: '', + version:'1.0', }, { externalId: 'DREC33', @@ -256,24 +239,19 @@ export const batchDevices: NewDeviceDTO[] = [ latitude: '34.921213', longitude: '135.717309', countryCode: 'DE', - zipCode: '111111', - // @ts-ignore ts(2322) - fuelCode: 'ES200', - // @ts-ignore ts(2322) - deviceTypeCode: 'TC110', - installationConfiguration: Installation.StandAlone, + fuelCode: FuelCode.ES100, + deviceTypeCode: DevicetypeCode.TC110, capacity: 1750, commissioningDate: '2012-07-01', gridInterconnection: true, offTaker: OffTaker.Residential, - sector: Sector.Financial, - standardCompliance: StandardCompliance.REC, yieldValue: 1000, - generatorsIds: [], - labels: '', impactStory: '', - data: '', images: [], + energyStorage: true, + energyStorageCapacity: 900, + qualityLabels: '', + version:'1.0', }, { externalId: 'DREC34', @@ -282,24 +260,19 @@ export const batchDevices: NewDeviceDTO[] = [ latitude: '34.921213', longitude: '135.717309', countryCode: 'DE', - zipCode: '111111', - // @ts-ignore ts(2322) - fuelCode: 'ES200', - // @ts-ignore ts(2322) - deviceTypeCode: 'TC110', - installationConfiguration: Installation.StandAlone, + fuelCode: FuelCode.ES100, + deviceTypeCode: DevicetypeCode.TC110, capacity: 1750, commissioningDate: '2012-07-01', gridInterconnection: true, offTaker: OffTaker.School, - sector: Sector.Education, - standardCompliance: StandardCompliance.REC, yieldValue: 1000, - generatorsIds: [], - labels: '', impactStory: '', - data: '', images: [], + energyStorage: true, + energyStorageCapacity: 900, + qualityLabels: '', + version: '1.0', }, ]; @@ -324,28 +297,24 @@ export const seed = async ({ const [user1, user2, user3, user4] = testUsers; await userService.seed( - // @ts-ignore ts(2345) user1, createdOrg1.id, Role.DeviceOwner, UserStatus.Active, ); await userService.seed( - // @ts-ignore ts(2345) user2, createdOrg2.id, Role.Buyer, UserStatus.Active, ); await userService.seed( - // @ts-ignore ts(2345) user3, createdOrg3.id, Role.Admin, UserStatus.Active, ); await userService.seed( - // @ts-ignore ts(2345) user4, createdOrg4.id, Role.DeviceOwner, @@ -353,13 +322,10 @@ export const seed = async ({ ); const [device1, device2, device3, device4] = testDevices; + const [ batchdevice1, batchdevice2, batchdevice3, batchdevice4 ] = batchDevices; - // @ts-ignore ts(2345) - await deviceService.seed(createdOrg1.id, device1); - // @ts-ignore ts(2345) - await deviceService.seed(createdOrg1.id, device3); - // @ts-ignore ts(2345) - await deviceService.seed(createdOrg4.id, device2); - // @ts-ignore ts(2345) - await deviceService.seed(createdOrg4.id, device4); + await deviceService.seed(createdOrg1.id, batchdevice1); + await deviceService.seed(createdOrg1.id, batchdevice2); + await deviceService.seed(createdOrg4.id, batchdevice3); + await deviceService.seed(createdOrg4.id, batchdevice4); }; diff --git a/apps/drec-api/test/user.e2e-spec.ts b/apps/drec-api/test/user.e2e-spec.ts index b8428a522..bd1396dc9 100755 --- a/apps/drec-api/test/user.e2e-spec.ts +++ b/apps/drec-api/test/user.e2e-spec.ts @@ -10,8 +10,7 @@ import { OrganizationService } from '../src/pods/organization/organization.servi import { seed } from './seed'; import { expect } from 'chai'; import { DeviceService } from '../src/pods/device/device.service'; -// @ts-ignore ts(2305) -import { CreateUserDTO } from '../src/pods/user/dto/create-user.dto'; +import { CreateUserORGDTO } from '../src/pods/user/dto/create-user.dto'; import { UserRegistrationData } from '../src/models'; import { UpdateUserProfileDTO } from '../src/pods/user/dto/update-user-profile.dto'; import { UpdateOwnUserSettingsDTO } from '../src/pods/user/dto/update-own-user-settings.dto'; @@ -88,37 +87,32 @@ describe('Users tests', () => { password: 'Password123', }; await loginUser(loggedUser); - const partialUser: CreateUserDTO = { - title: 'Mr', + const partialUser: CreateUserORGDTO = { firstName: 'test', lastName: 'user2021', email: 'test-1-2021@mailinator.com', - telephone: 'telephone', password: 'testUser2', + organizationType: 'Developer', }; await postAdminUser('', HttpStatus.CREATED, partialUser); }); it('should register a new user', async () => { - const partialUser: CreateUserDTO = { - title: 'Mr', + const partialUser: CreateUserORGDTO = { firstName: 'test', lastName: 'user2021', email: 'test-2-2021@mailinator.com', - telephone: 'telephone', password: 'testUser2', + organizationType: 'Developer', }; await postUser('register', HttpStatus.CREATED, partialUser); }); it('should update profile for user', async () => { const partialUser: UpdateUserProfileDTO = { - // @ts-ignore ts(2353) - title: 'Mr', firstName: 'Updated first name', lastName: 'Updated last name', email: 'updated@mailinator.com', - telephone: 'Updated telephone', }; const { body: updatedUser } = await request(app.getHttpServer()) .put(`/user/profile`) @@ -128,8 +122,6 @@ describe('Users tests', () => { expect(updatedUser.firstName).to.eq(partialUser.firstName); expect(updatedUser.lastName).to.eq(partialUser.lastName); expect(updatedUser.email).to.eq(partialUser.email); - // @ts-ignore ts(2339) - expect(updatedUser.telephone).to.eq(partialUser.telephone); }); it('should update notifications for user', async () => { @@ -153,7 +145,7 @@ describe('Users tests', () => { const postAdminUser = async ( url: string, status: HttpStatus, - body: CreateUserDTO, + body: CreateUserORGDTO, ): Promise => await request(app.getHttpServer()) .post(`/admin/users/${url}`) @@ -166,7 +158,7 @@ describe('Users tests', () => { const postUser = async ( url: string, status: HttpStatus, - body: CreateUserDTO, + body: CreateUserORGDTO, ): Promise => await request(app.getHttpServer()) .post(`/user/${url}`) From 664e5586e298cf6752086709040ee446b1e2b28a Mon Sep 17 00:00:00 2001 From: Aish1990 Date: Fri, 3 May 2024 14:20:08 +0530 Subject: [PATCH 22/89] prettier fix --- apps/drec-api/src/auth/client-jwt.strategy.ts | 4 +- apps/drec-api/src/auth/jwt.strategy.ts | 4 +- apps/drec-api/src/guards/WithoutAuthGuard.ts | 3 +- apps/drec-api/src/models/User.ts | 7 +- .../certificate-log.service.spec.ts | 2 +- .../pods/device-group/device-group.service.ts | 36 +- .../src/pods/device/device.controller.ts | 2166 ++++++++--------- .../src/pods/device/device.service.ts | 9 +- .../src/pods/issuer/issuer.service.ts | 5 +- .../src/pods/reads/reads.controller.ts | 58 +- apps/drec-api/src/pods/reads/reads.service.ts | 9 +- apps/drec-api/src/pods/user/user.entity.ts | 7 +- apps/drec-api/src/pods/user/user.service.ts | 1484 +++++------ apps/drec-api/test/device.e2e-spec.ts | 4 +- apps/drec-api/test/group-devices.e2e-spec.ts | 50 +- apps/drec-api/test/seed.ts | 24 +- 16 files changed, 1960 insertions(+), 1912 deletions(-) diff --git a/apps/drec-api/src/auth/client-jwt.strategy.ts b/apps/drec-api/src/auth/client-jwt.strategy.ts index 931bb4b19..351ca4f4f 100644 --- a/apps/drec-api/src/auth/client-jwt.strategy.ts +++ b/apps/drec-api/src/auth/client-jwt.strategy.ts @@ -26,7 +26,9 @@ export class ClientJwtStrategy extends PassportStrategy( } async validate(request: Request, payload: IJWTPayload) { - const token = (request.headers as { authorization?: string }).authorization?.split(' ')[1]; + const token = ( + request.headers as { authorization?: string } + ).authorization?.split(' ')[1]; const user = await this.userService.findByEmail(payload.email); const publicKey = this.oauthClientService.get(user.api_user_id); const verifiedData = await this.jwtService.verify(token, { diff --git a/apps/drec-api/src/auth/jwt.strategy.ts b/apps/drec-api/src/auth/jwt.strategy.ts index c489f3091..adc4d8297 100755 --- a/apps/drec-api/src/auth/jwt.strategy.ts +++ b/apps/drec-api/src/auth/jwt.strategy.ts @@ -33,7 +33,9 @@ export class JwtStrategy extends PassportStrategy(Strategy, 'jwt') { payload: IJWTPayload, ): Promise { this.logger.verbose('With in validate'); - const token = (request.headers as { authorization?: string }).authorization?.split(' ')[1]; + const token = ( + request.headers as { authorization?: string } + ).authorization?.split(' ')[1]; const tokeninvalidate = await this.authService.isTokenBlacklisted( token, payload, diff --git a/apps/drec-api/src/guards/WithoutAuthGuard.ts b/apps/drec-api/src/guards/WithoutAuthGuard.ts index 4fa7c9036..91058b27c 100644 --- a/apps/drec-api/src/guards/WithoutAuthGuard.ts +++ b/apps/drec-api/src/guards/WithoutAuthGuard.ts @@ -82,7 +82,8 @@ export class WithoutAuthGuard implements CanActivate { user.role != Role.Admin && user.role != Role.ApiUser && user.api_user_id != - ((await this.userService.findOne({ role: Role.Admin })) as IUser).api_user_id + ((await this.userService.findOne({ role: Role.Admin })) as IUser) + .api_user_id ) { throw new UnauthorizedException({ statusCode: 401, diff --git a/apps/drec-api/src/models/User.ts b/apps/drec-api/src/models/User.ts index b2ad20c7c..66877d845 100755 --- a/apps/drec-api/src/models/User.ts +++ b/apps/drec-api/src/models/User.ts @@ -1,5 +1,10 @@ import { IEmailConfirmation, IFullOrganization } from '.'; -import { Role, UserStatus, PermissionString, UserPermissionStatus } from '../utils/enums'; +import { + Role, + UserStatus, + PermissionString, + UserPermissionStatus, +} from '../utils/enums'; import { IModulePermissionsConfig } from './ACLModulesPermission'; export interface IUserProperties { id: number; diff --git a/apps/drec-api/src/pods/certificate-log/certificate-log.service.spec.ts b/apps/drec-api/src/pods/certificate-log/certificate-log.service.spec.ts index 8ccdc0313..290796eab 100644 --- a/apps/drec-api/src/pods/certificate-log/certificate-log.service.spec.ts +++ b/apps/drec-api/src/pods/certificate-log/certificate-log.service.spec.ts @@ -109,7 +109,7 @@ describe('CertificateLogService', () => { certificateTransactionUID: '14f8bcd3-095b-4659-90d8-bbc7523d14b4', externalId: 'Ext2', groupId: 2, - status: "Active", + status: 'Active', ongoing_start_date: '2023-11-06T12:48:18.405Z', ongoing_end_date: '2023-11-10T04:15:58.000Z', } as CheckCertificateIssueDateLogForDeviceEntity, diff --git a/apps/drec-api/src/pods/device-group/device-group.service.ts b/apps/drec-api/src/pods/device-group/device-group.service.ts index 14b3eee51..9e0383ea3 100755 --- a/apps/drec-api/src/pods/device-group/device-group.service.ts +++ b/apps/drec-api/src/pods/device-group/device-group.service.ts @@ -1619,18 +1619,21 @@ export class DeviceGroupService { status: StatusCSV, ): Promise { this.logger.verbose(`With in updateJobStatus`); - const updateResult: UpdateResult = await this.repositoyCSVJobProcessing.update({ jobId: jobId }, - { status: status }, - ); + const updateResult: UpdateResult = + await this.repositoyCSVJobProcessing.update( + { jobId: jobId }, + { status: status }, + ); if (updateResult.affected === 0) { throw new Error(`No job found with ID ${jobId}`); } - const updatedJob: DeviceCsvFileProcessingJobsEntity = await this.repositoyCSVJobProcessing.findOne({ - where: { jobId: jobId } - }); - + const updatedJob: DeviceCsvFileProcessingJobsEntity = + await this.repositoyCSVJobProcessing.findOne({ + where: { jobId: jobId }, + }); + return updatedJob; } @@ -1647,7 +1650,9 @@ export class DeviceGroupService { return; } - const user = await this.userService.findById(filesAddedForProcessing.userId); + const user = await this.userService.findById( + filesAddedForProcessing.userId, + ); const data = new LoggedInUser(user); data.id = filesAddedForProcessing.userId; @@ -1732,12 +1737,10 @@ export class DeviceGroupService { } if (typeof dataKeyForValidation[key] === 'string') { dataToStore[key] = data[key]; - } - else if (typeof dataKeyForValidation[key] === 'boolean') { + } else if (typeof dataKeyForValidation[key] === 'boolean') { dataToStore[key] = data[key].toLowerCase() === 'true' ? true : false; - } - else if (typeof dataKeyForValidation[key] === 'number') { + } else if (typeof dataKeyForValidation[key] === 'number') { dataToStore[key] = Number.isNaN(data[key]) ? 0 : parseFloat(data[key]); @@ -2008,7 +2011,8 @@ export class DeviceGroupService { successfullyAddedRowsAndExternalIds.push({ externalId: (ele as any).externalId, rowNumber: records.findIndex( - (recEle) => recEle.developerExternalId === (ele as any).externalId, + (recEle) => + recEle.developerExternalId === (ele as any).externalId, ), }); }); @@ -2181,7 +2185,11 @@ export class DeviceGroupService { groupId: groupId, }); - this.endReservation(groupId, group as DeviceGroup, deviceGroupIssueNextDateDTO); + this.endReservation( + groupId, + group as DeviceGroup, + deviceGroupIssueNextDateDTO, + ); return; } } diff --git a/apps/drec-api/src/pods/device/device.controller.ts b/apps/drec-api/src/pods/device/device.controller.ts index 9cd7fa972..2e1512b94 100755 --- a/apps/drec-api/src/pods/device/device.controller.ts +++ b/apps/drec-api/src/pods/device/device.controller.ts @@ -1,1083 +1,1083 @@ -import { - Controller, - Get, - Post, - Put, - Patch, - Delete, - HttpStatus, - Param, - Body, - UseGuards, - ValidationPipe, - Query, - ConflictException, - HttpException, - UnauthorizedException, - BadRequestException, - Logger, -} from '@nestjs/common'; - -import { - ApiBearerAuth, - ApiNotFoundResponse, - ApiResponse, - ApiOkResponse, - ApiSecurity, - ApiTags, - ApiQuery, - ApiBody, -} from '@nestjs/swagger'; -import { AuthGuard } from '@nestjs/passport'; -import { plainToClass } from 'class-transformer'; - -import { DeviceService } from './device.service'; -import { - FilterDTO, - NewDeviceDTO, - UpdateDeviceDTO, - DeviceDTO, - DeviceGroupByDTO, - GroupedDevicesDTO, -} from './dto'; -import { CSVBulkUploadDTO } from '../device-group/dto'; -import { Role } from '../../utils/enums'; -import { RolesGuard } from '../../guards/RolesGuard'; -import { PermissionGuard } from '../../guards/PermissionGuard'; -import { ILoggedInUser } from '../../models'; -import { CodeNameDTO } from './dto/code-name.dto'; -import { ActiveUserGuard } from '../../guards'; -import { Roles } from '../user/decorators/roles.decorator'; -import { UserDecorator } from '../user/decorators/user.decorator'; -import { DeviceGroupService } from '../device-group/device-group.service'; -import { Permission } from '../permission/decorators/permission.decorator'; -import { ACLModules } from '../access-control-layer-module-service/decorator/aclModule.decorator'; -import { CountrycodeService } from '../countrycode/countrycode.service'; -import { countryCodesList } from '../../models/country-code'; -import { isValidUTCDateFormat } from '../../utils/checkForISOStringFormat'; -import { DeviceGroup } from '../device-group/device-group.entity'; -import { - DeviceCsvFileProcessingJobsEntity, - StatusCSV, -} from '../device-group/device_csv_processing_jobs.entity'; -import { Device } from './device.entity'; -import { OrganizationService } from '../organization/organization.service'; -import { UserService } from '../user/user.service'; -import { FindOneOptions } from 'typeorm'; - -/** - * It is Controller of device with the endpoints of device operations. - */ -@ApiTags('device') -@ApiBearerAuth('access-token') -@ApiSecurity('drec') -@Controller('/device') -export class DeviceController { - private readonly logger = new Logger(DeviceController.name); - - constructor( - private readonly deviceGroupService: DeviceGroupService, - private readonly deviceService: DeviceService, - private readonly organizationService: OrganizationService, - private readonly userService: UserService, - ) {} - - /** - * It is GET api to list all devices with paginatiion and fiteration by organization and filterationDto - */ - @Get() - @UseGuards(AuthGuard('jwt'), ActiveUserGuard, RolesGuard, PermissionGuard) - @Roles(Role.Admin) - @Permission('Read') - @ACLModules('DEVICE_MANAGEMENT_CRUDL') - @ApiQuery({ name: 'pagenumber', type: Number, required: false }) - @ApiQuery({ name: 'OrganizationId', type: Number, required: false }) - @ApiOkResponse({ type: [DeviceDTO], description: 'Returns all Devices' }) - async getAll( - @Query(ValidationPipe) filterDto: FilterDTO, - @Query('pagenumber') pagenumber: number | null, - @Query('OrganizationId') OrgId: number | null, - ) /*: Promise*/ { - this.logger.verbose(`With in getAll`); - return this.deviceService.find(filterDto, pagenumber, OrgId); - } - - /** - * It is GET api to list all devices for reservation - * @return {Array} return array of devices for reservation - */ - @Get('/ungrouped/buyerreservation') - @UseGuards( - AuthGuard(['jwt', 'oauth2-client-password']), - PermissionGuard, - RolesGuard, - ) - @Permission('Read') - @ACLModules('DEVICE_MANAGEMENT_CRUDL') - @Roles(Role.Buyer, Role.SubBuyer, Role.ApiUser) - @ApiOkResponse({ type: [DeviceDTO], description: 'Returns all Devices' }) - async getAllDeviceForBuyer( - @Query(ValidationPipe) filterDto: FilterDTO, - @Query('pagenumber') pagenumber: number | null, - @UserDecorator() { organizationId, api_user_id, role }: ILoggedInUser, - ): Promise { - this.logger.verbose(`With in getAllDeviceForBuyer`); - if (filterDto.organizationId) { - const organization = await this.organizationService.findOne( - filterDto.organizationId, - ); - const orguser = await this.userService.findByEmail(organization.orgEmail); - if (role === Role.ApiUser) { - if (organization.api_user_id != api_user_id) { - this.logger.error( - `The requested organization is belongs to other apiuser`, - ); - throw new UnauthorizedException({ - success: false, - message: `The requested organization is belongs to other apiuser`, - }); - } - - if ( - orguser.role === Role.OrganizationAdmin || - orguser.role === Role.DeviceOwner - ) { - this.logger.error( - `Unauthorized... The requested user is developer or device owner`, - ); - throw new UnauthorizedException({ - success: false, - message: `Unauthorized`, - }); - } - } else { - if (organizationId != organization.id) { - this.logger.error( - `The requested organization is not same as user's organization`, - ); - throw new UnauthorizedException({ - success: false, - message: `The requested organization is not same as user's organization`, - }); - } - } - } - - if (role !== Role.ApiUser) { - api_user_id = null; - } - - return this.deviceService.finddeviceForBuyer( - filterDto, - pagenumber, - api_user_id, - ); - } - - /** - * It is GET api to list all ungrouped devices with filteration - * @return {GroupedDevicesDTO} returns ungrouped devices - */ - @Get('/ungrouped') - @UseGuards(AuthGuard('jwt'), ActiveUserGuard, RolesGuard, PermissionGuard) - @Roles(Role.Admin, Role.DeviceOwner) - @Permission('Read') - @ACLModules('DEVICE_MANAGEMENT_CRUDL') - @ApiOkResponse({ - type: [GroupedDevicesDTO], - description: 'Returns all ungrouped Devices', - }) - async getAllUngrouped( - @UserDecorator() { organizationId }: ILoggedInUser, - @Query(ValidationPipe) orderFilterDto: DeviceGroupByDTO, - ): Promise { - this.logger.verbose(`With in getAllUngrouped`); - return this.deviceService.findUngrouped(organizationId, orderFilterDto); - } - - /** - * It is GET to list all device code types in dropdown - * @returns {Array} - */ - @Get('/device-type') - @ApiResponse({ - status: HttpStatus.OK, - type: [CodeNameDTO], - description: 'Returns all IREC device types', - }) - getDeviceTypes(): CodeNameDTO[] { - this.logger.verbose(`With in getDeviceTypes`); - const deviceTypes = this.deviceService.getDeviceTypes(); - - return deviceTypes.map((deviceType) => - plainToClass(CodeNameDTO, deviceType), - ); - } - - /** - * It is GET api to list all fuel types in dropdown - * @returns {Array} - */ - @Get('/fuel-type') - @ApiResponse({ - status: HttpStatus.OK, - type: [CodeNameDTO], - description: 'Returns all IREC fuel types', - }) - getFuelTypes(): CodeNameDTO[] { - this.logger.verbose(`With in getFuelTypes`); - const fuelTypes = this.deviceService.getFuelTypes(); - return fuelTypes.map((fuelType) => plainToClass(CodeNameDTO, fuelType)); - } - - /** - * It is GET api to list all my devices with filteration and pagination - * @returns {Array} - */ - @Get('/my') - @UseGuards( - AuthGuard(['jwt', 'oauth2-client-password']), - ActiveUserGuard, - PermissionGuard, - ) - @Permission('Read') - @ACLModules('DEVICE_MANAGEMENT_CRUDL') - @ApiQuery({ name: 'pagenumber', type: Number, required: false }) - @ApiResponse({ - status: HttpStatus.OK, - type: [DeviceDTO], - description: 'Returns my Devices', - }) - async getMyDevices( - @Query(ValidationPipe) filterDto: FilterDTO, - @UserDecorator() { organizationId, api_user_id, role }: ILoggedInUser, - @Query('pagenumber') pagenumber: number | null, - ) /*: Promise*/ { - this.logger.verbose(`With in getMyDevices`); - if (filterDto.country) { - filterDto.country = filterDto.country.toUpperCase(); - - if ( - filterDto.country && - typeof filterDto.country === 'string' && - filterDto.country.length === 3 - ) { - const countries = countryCodesList; - if ( - countries.find((ele) => ele.countryCode === filterDto.country) === - undefined - ) { - this.logger.error( - `Invalid countryCode, some of the valid country codes are "GBR" - "United Kingdom of Great Britain and Northern Ireland", "CAN" - "Canada" "IND" - "India", "DEU"- "Germany"`, - ); - return new Promise((resolve, reject) => { - reject( - new ConflictException({ - success: false, - message: - ' Invalid countryCode, some of the valid country codes are "GBR" - "United Kingdom of Great Britain and Northern Ireland", "CAN" - "Canada" "IND" - "India", "DEU"- "Germany"', - }), - ); - }); - } - } else { - this.logger.error( - `Invalid countryCode, some of the valid country codes are "GBR" - "United Kingdom of Great Britain and Northern Ireland", "CAN" - "Canada" "IND" - "India", "DEU"- "Germany"`, - ); - return new Promise((resolve, reject) => { - reject( - new ConflictException({ - success: false, - message: - ' Invalid countryCode, some of the valid country codes are "GBR" - "United Kingdom of Great Britain and Northern Ireland", "CAN" - "Canada" "IND" - "India", "DEU"- "Germany"', - }), - ); - }); - } - } - if (filterDto.organizationId) { - if (role === Role.ApiUser) { - const organization = await this.organizationService.findOne( - filterDto.organizationId, - ); - const orguser = await this.userService.findByEmail( - organization.orgEmail, - ); - if (organization.api_user_id != api_user_id) { - this.logger.error( - `The organization Id in param is belongs to other apiuser`, - ); - throw new UnauthorizedException({ - success: false, - message: 'The organization Id in param is belongs to other apiuser', - }); - } else { - if (orguser.role != Role.OrganizationAdmin) { - this.logger.error(`Unauthorized`); - throw new UnauthorizedException({ - success: false, - message: 'Unauthorized', - }); - } - } - } else { - if (filterDto.organizationId != organizationId) { - this.logger.error( - `The organization Id in param should be same as user's organization`, - ); - throw new UnauthorizedException({ - success: false, - message: `The organization Id in param should be same as user's organization`, - }); - } - } - - organizationId = filterDto.organizationId; - } - - this.logger.log('In devices before calling service'); - return await this.deviceService.getOrganizationDevices( - organizationId, - api_user_id, - role, - filterDto, - pagenumber, - ); - } - - /** - * It is GET api to fetch an device by the deviceId in param - * @param id is deviceId in type number - * @returns {DeviceDTO | null} DeviceDto for success response and null when there is no device found by the id - */ - @Get('/:id') - @UseGuards( - AuthGuard(['jwt', 'oauth2-client-password']), - ActiveUserGuard, - PermissionGuard, - ) - @Permission('Read') - @ACLModules('DEVICE_MANAGEMENT_CRUDL') - @ApiQuery({ name: 'apiUserId', type: String, required: false }) - @ApiQuery({ name: 'organizationId', type: Number, required: false }) - @ApiOkResponse({ type: DeviceDTO, description: 'Returns a Device' }) - @ApiNotFoundResponse({ - description: `The device with the code doesn't exist`, - }) - async get( - @Param('id') id: number, - @Query('apiUserId') api_user_id: string | null, - @Query('organizationId') organizationId: number | null, - ): Promise { - this.logger.verbose(`With in get`); - let devicedata: Device; - if (api_user_id && organizationId) { - devicedata = await this.deviceService.findOne(id, { - api_user_id: api_user_id, - organizationId: organizationId, - } as FindOneOptions); - } else { - devicedata = await this.deviceService.findOne(id); - } - devicedata.externalId = devicedata.developerExternalId; - delete devicedata['developerExternalId']; - return devicedata; - } - - /** - * It is GET api to fetch an device by externalId in param - * @param id is externalId in device - * @param param1 - * @returns {DeviceDTO | null} DeviceDto for success response and null when there is no device found by the id - */ - @Get('externalId/:id') - @UseGuards(AuthGuard('jwt'), PermissionGuard) - @Permission('Read') - @ACLModules('DEVICE_MANAGEMENT_CRUDL') - @ApiOkResponse({ type: DeviceDTO, description: 'Returns a Device' }) - @ApiNotFoundResponse({ - description: `The device with the code doesn't exist`, - }) - async getByExternalId( - @Param('id') id: string, - @UserDecorator() { organizationId }: ILoggedInUser, - ): Promise { - this.logger.verbose(`With in getByExternalId`); - const devicedata = await this.deviceService.findDeviceByDeveloperExternalId( - id, - organizationId, - ); - devicedata.externalId = devicedata.developerExternalId; - delete devicedata['developerExternalId']; - return devicedata; - } - - /** - * It is POST api to create an device - * @param param0 It is organizationId from user at request - * @param deviceToRegister It is body payload to create device - * @returns {DeviceDTO} - */ - @Post() - @UseGuards(AuthGuard(['jwt', 'oauth2-client-password']), PermissionGuard) - @Permission('Write') - @ACLModules('DEVICE_MANAGEMENT_CRUDL') - @ApiResponse({ - status: HttpStatus.OK, - type: NewDeviceDTO, - description: 'Returns a new created Device id', - }) - public async create( - @UserDecorator() { organizationId, role, api_user_id }: ILoggedInUser, - @Body() deviceToRegister: NewDeviceDTO, - ): Promise { - this.logger.verbose(`With in create`); - deviceToRegister.externalId = deviceToRegister.externalId.trim(); - if (deviceToRegister.externalId.trim() === '') { - this.logger.error(`externalId should not be empty`); - return new Promise((resolve, reject) => { - reject( - new ConflictException({ - success: false, - message: `externalId should not be empty`, - }), - ); - }); - } - - if (!isValidUTCDateFormat(deviceToRegister.commissioningDate)) { - this.logger.error( - `Invalid commissioning date, valid format is YYYY-MM-DDThh:mm:ss.millisecondsZ example 2022-10-18T11:35:27.640Z`, - ); - return new Promise((resolve, reject) => { - reject( - new ConflictException({ - success: false, - message: - ' Invalid commissioning date, valid format is YYYY-MM-DDThh:mm:ss.millisecondsZ example 2022-10-18T11:35:27.640Z ', - }), - ); - }); - } - if ( - new Date(deviceToRegister.commissioningDate).getTime() > - new Date().getTime() - ) { - this.logger.error( - `Invalid commissioning date, commissioning is greater than current date`, - ); - return new Promise((resolve, reject) => { - reject( - new ConflictException({ - success: false, - message: ` Invalid commissioning date, commissioning is greater than current date`, - }), - ); - }); - } - if (deviceToRegister['groupId'] === 0 || deviceToRegister['groupId']) { - deviceToRegister['groupId'] = null; - } - deviceToRegister.countryCode = deviceToRegister.countryCode.toUpperCase(); - if ( - deviceToRegister.countryCode && - typeof deviceToRegister.countryCode === 'string' && - deviceToRegister.countryCode.length === 3 - ) { - const countries = countryCodesList; - if ( - countries.find( - (ele) => ele.countryCode === deviceToRegister.countryCode, - ) === undefined - ) { - this.logger.error( - `Invalid countryCode, some of the valid country codes are "GBR" - "United Kingdom of Great Britain and Northern Ireland", "CAN" - "Canada" "IND" - "India", "DEU"- "Germany"`, - ); - return new Promise((resolve, reject) => { - reject( - new ConflictException({ - success: false, - message: - ' Invalid countryCode, some of the valid country codes are "GBR" - "United Kingdom of Great Britain and Northern Ireland", "CAN" - "Canada" "IND" - "India", "DEU"- "Germany"', - }), - ); - }); - } - } else { - this.logger.error( - `Invalid countryCode, some of the valid country codes are "GBR" - "United Kingdom of Great Britain and Northern Ireland", "CAN" - "Canada" "IND" - "India", "DEU"- "Germany"`, - ); - return new Promise((resolve, reject) => { - reject( - new ConflictException({ - success: false, - message: - ' Invalid countryCode, some of the valid country codes are "GBR" - "United Kingdom of Great Britain and Northern Ireland", "CAN" - "Canada" "IND" - "India", "DEU"- "Germany"', - }), - ); - }); - } - if (isNaN(parseFloat(deviceToRegister.capacity.toString()))) { - this.logger.error(`Invalid Capacity or energy Storage Capacity`); - return new Promise((resolve, reject) => { - reject( - new ConflictException({ - success: false, - message: ' Invalid Capacity or energy Storage Capacity', - }), - ); - }); - } - if ( - deviceToRegister.capacity <= 0 || - deviceToRegister.energyStorageCapacity < 0 - ) { - this.logger.error( - `Invalid Capacity or energy Storage Capacity, it should be greater than 0`, - ); - return new Promise((resolve, reject) => { - reject( - new ConflictException({ - success: false, - message: - ' Invalid Capacity or energy Storage Capacity, it should be greater than 0', - }), - ); - }); - } - if ( - deviceToRegister.version === null || - deviceToRegister.version === undefined || - deviceToRegister.version === '0' - ) { - deviceToRegister.version = '1.0'; - } - if (role === Role.Admin || role === Role.ApiUser) { - if (deviceToRegister.organizationId) { - this.logger.debug('Line No: 314'); - organizationId = deviceToRegister.organizationId; - } else { - this.logger.error( - `Organization id is required,please add your developer's Organization`, - ); - return new Promise((resolve, reject) => { - reject( - new ConflictException({ - success: false, - message: `Organization id is required,please add your developer's Organization `, - }), - ); - }); - } - } - return await this.deviceService.register( - organizationId, - deviceToRegister, - api_user_id, - role, - ); - } - - /** - * It is PATCH api to update an device by externalId - * @param user is loggedin user from user at request - * @param externalId is unique external id in device entity - * @param deviceToUpdate is body payload to update an device - * @returns {DeviceDTO} - */ - @Patch('/:externalId') - @UseGuards(AuthGuard('jwt'), PermissionGuard) - @Permission('Update') - @ACLModules('DEVICE_MANAGEMENT_CRUDL') - @ApiResponse({ - status: HttpStatus.OK, - type: UpdateDeviceDTO, - description: 'Returns an updated Device', - }) - @ApiNotFoundResponse({ description: `No device found` }) - public async update( - @UserDecorator() user: ILoggedInUser, - @Param('externalId') externalId: string, - @Body() deviceToUpdate: UpdateDeviceDTO, - ): Promise { - this.logger.verbose(`With in update`); - - if (deviceToUpdate.externalId) { - deviceToUpdate.externalId = deviceToUpdate.externalId.trim(); - if (deviceToUpdate.externalId === '') { - this.logger.error(`externalId should not be empty`); - return new Promise((resolve, reject) => { - reject( - new ConflictException({ - success: false, - message: `externalId should not be empty`, - }), - ); - }); - } - - const checkexternalid = - await this.deviceService.findDeviceByDeveloperExternalId( - deviceToUpdate.externalId, - user.organizationId, - ); - if ( - checkexternalid != undefined && - checkexternalid.developerExternalId === externalId.trim() - ) { - this.logger.log('Line No: 236'); - return new Promise((resolve, reject) => { - reject( - new ConflictException({ - success: false, - message: `ExternalId already exist in this organization, can't update with same external id ${deviceToUpdate.externalId}`, - }), - ); - }); - } - } - - if (deviceToUpdate.countryCode != undefined) { - deviceToUpdate.countryCode = deviceToUpdate.countryCode.toUpperCase(); - if ( - deviceToUpdate.countryCode && - typeof deviceToUpdate.countryCode === 'string' && - deviceToUpdate.countryCode.length === 3 - ) { - const countries = countryCodesList; - if ( - countries.find( - (ele) => ele.countryCode === deviceToUpdate.countryCode, - ) === undefined - ) { - this.logger.error( - `Invalid countryCode, some of the valid country codes are "GBR" - "United Kingdom of Great Britain and Northern Ireland", "CAN" - "Canada" "IND" - "India", "DEU"- "Germany"`, - ); - return new Promise((resolve, reject) => { - reject( - new ConflictException({ - success: false, - message: - ' Invalid countryCode, some of the valid country codes are "GBR" - "United Kingdom of Great Britain and Northern Ireland", "CAN" - "Canada" "IND" - "India", "DEU"- "Germany"', - }), - ); - }); - } - } else { - this.logger.error( - `Invalid countryCode, some of the valid country codes are "GBR" - "United Kingdom of Great Britain and Northern Ireland", "CAN" - "Canada" "IND" - "India", "DEU"- "Germany"`, - ); - return new Promise((resolve, reject) => { - reject( - new ConflictException({ - success: false, - message: - ' Invalid countryCode, some of the valid country codes are "GBR" - "United Kingdom of Great Britain and Northern Ireland", "CAN" - "Canada" "IND" - "India", "DEU"- "Germany"', - }), - ); - }); - } - } - - if (deviceToUpdate.capacity <= 0) { - this.logger.error(`Invalid Capacity, it should be greater than 0`); - return new Promise((resolve, reject) => { - reject( - new ConflictException({ - success: false, - message: ' Invalid Capacity, it should be greater than 0', - }), - ); - }); - } - if ( - !isValidUTCDateFormat(deviceToUpdate.commissioningDate) && - deviceToUpdate.commissioningDate !== undefined - ) { - this.logger.error( - `Invalid commissioning date, valid format is YYYY-MM-DDThh:mm:ss.millisecondsZ example 2022-10-18T11:35:27.640Z`, - ); - return new Promise((resolve, reject) => { - reject( - new ConflictException({ - success: false, - message: - ' Invalid commissioning date, valid format is YYYY-MM-DDThh:mm:ss.millisecondsZ example 2022-10-18T11:35:27.640Z ', - }), - ); - }); - } - if ( - new Date(deviceToUpdate.commissioningDate).getTime() > - new Date().getTime() - ) { - this.logger.error( - `Invalid commissioning date, commissioning is greater than current date`, - ); - return new Promise((resolve, reject) => { - reject( - new ConflictException({ - success: false, - message: ` Invalid commissioning date, commissioning is greater than current date`, - }), - ); - }); - } - - if (deviceToUpdate.commissioningDate) { - const checkexternalid = - await this.deviceService.findDeviceByDeveloperExternalId( - externalId, - user.organizationId, - ); - const noOfHistRead: number = - await this.deviceService.getNumberOfHistReads( - checkexternalid.externalId, - ); - const noOfOnGoingRead: number = - await this.deviceService.getNumberOfOngReads( - checkexternalid.externalId, - checkexternalid.createdAt, - ); - - if ( - deviceToUpdate.commissioningDate != checkexternalid.commissioningDate - ) { - if (noOfHistRead > 0 || noOfOnGoingRead > 0) { - this.logger.error( - `Commissioning date cannot be changed due to existing meter reads available for ${checkexternalid.developerExternalId}`, - ); - throw new ConflictException({ - success: false, - message: ` Commissioning date cannot be changed due to existing meter reads available for ${checkexternalid.developerExternalId}`, - }); - } - - if ( - new Date(deviceToUpdate.commissioningDate).getTime() > - new Date(checkexternalid.createdAt).getTime() - ) { - this.logger.error( - `Invalid commissioning date, commissioning is greater than device onboarding date`, - ); - throw new ConflictException({ - success: false, - message: `Invalid commissioning date, commissioning is greater than device onboarding date`, - }); - } - } - } - return await this.deviceService.update( - user.organizationId, - user.role, - externalId, - deviceToUpdate, - ); - } - - /** - * It is DELETE api to delete an device by id - * @param id is deviceId - * @param param1 is getting organizationId and user role from user request - * @returns {any} - */ - @Delete('/:id') - @UseGuards(AuthGuard('jwt'), RolesGuard, PermissionGuard) - @Permission('Delete') - @ACLModules('DEVICE_MANAGEMENT_CRUDL') - @Roles(Role.OrganizationAdmin, Role.Admin) - @ApiResponse({ - status: HttpStatus.OK, - description: 'Remove device group', - }) - @ApiNotFoundResponse({ description: `No device group found` }) - public async remove( - @Param('id') id: number, - @UserDecorator() { organizationId, role }: ILoggedInUser, - ): Promise { - this.logger.verbose(`With in remove`); - const checkisungroup = this.deviceService.findUngroupedById(id); - if (checkisungroup) { - let fitlerop: any; - if (role === 'Admin') { - fitlerop = { - groupId: null, - }; - } else { - fitlerop = { - groupId: null, - organizationId: organizationId, - }; - } - return await this.deviceService.remove(id, fitlerop); - } - } - - /** - * It is GET api to list all total amount of reads by each devices grouped by organization - * @param param0 is getting organizationId from user request. - * @returns {Array} - */ - @Get('/my/totalamountread') - @UseGuards(AuthGuard('jwt'), ActiveUserGuard, PermissionGuard) - @Permission('Read') - @ACLModules('DEVICE_MANAGEMENT_CRUDL') - @ApiResponse({ - status: HttpStatus.OK, - type: [DeviceDTO], - description: 'Returns my Devices', - }) - async getMyDevicesTotal( - @UserDecorator() { organizationId }: ILoggedInUser, - ): Promise { - this.logger.verbose(`Wth in getMyDevicesTotal`); - return await this.deviceService.getOrganizationDevicesTotal(organizationId); - } - - /** - * It is PUT api tp update the device onboarding date by deviceId - * @param param0 is getting organizationId from user request - * @param deviceId is deviceId from device unique identifier - * @param givenDate is new onboarding date to be updated. - * @returns {} - */ - @Put('/my/deviceOnBoardingDate') - @UseGuards(AuthGuard('jwt'), PermissionGuard) - @Permission('Write') - @ACLModules('DEVICE_MANAGEMENT_CRUDL') - @ApiResponse({ - status: HttpStatus.OK, - description: "change the device's OnBoarding date", - }) - @ApiQuery({ name: 'deviceId', description: 'Device Id' }) - @ApiQuery({ - name: 'givenDate', - description: 'Update the OnBoarding date', - type: Date, - }) - async changeOnBoardingDate( - @UserDecorator() { organizationId }: ILoggedInUser, - @Query('deviceId') deviceId, - @Query('givenDate') givenDate, - ) { - this.logger.verbose(`With in changeOnBoardingDate`); - if (process.env.MODE != 'dev') { - this.logger.error(`Currently not in dev environment`); - throw new HttpException('Currently not in dev environment', 400); - } - const device: DeviceDTO | null = - await this.deviceService.findDeviceByDeveloperExternalId( - deviceId, - organizationId, - ); - this.logger.debug( - 'THE DEVICE FROM ExTERNALID IS::::::::::::' + device.externalId, - ); - if (!device) { - this.logger.error(`Device dosen't exist`); - throw new HttpException("Device dosen't exist", 400); - } - const deviceExternalId = device.externalId; - const deviceOnboardedDate = device.createdAt; - return this.deviceService.changeDeviceCreatedAt( - deviceExternalId, - deviceOnboardedDate, - givenDate, - ); - } - - /** - * It is GET api to list all devices with auto complete - * @param param0 is getting organizationId from user request - * @param externalId is unique identoifier of an device - * @returns {} - */ - @Get('/my/autocomplete') - @UseGuards(AuthGuard('jwt'), ActiveUserGuard, PermissionGuard) - @Permission('Read') - @ACLModules('DEVICE_MANAGEMENT_CRUDL') - @ApiResponse({ - status: HttpStatus.OK, - description: 'Returns Auto-Complete', - }) - @ApiQuery({ name: 'externalId', description: 'externalId', type: String }) - async autocomplete( - @UserDecorator() { organizationId }: ILoggedInUser, - @Query('externalId') externalId: string, - ) { - this.logger.verbose(`With in autocomplete`); - return await this.deviceService.atto(organizationId, externalId); - } - - /** - * It is GET api to fetch the certified device records with in the range of date - * @param user is loggedIn user at request - * @param externalId is unique identifier of device - * @param groupuId - * @returns {any} - */ - @Get('/certifiedlog/first&lastdate') - @UseGuards(AuthGuard('jwt'), PermissionGuard) - @Permission('Read') - @ACLModules('DEVICE_MANAGEMENT_CRUDL') - @ApiQuery({ name: 'externalId', type: Number, required: false }) - @ApiQuery({ name: 'pagenumber', type: Number, required: false }) - @ApiResponse({ - status: HttpStatus.OK, - description: 'Returns Certified log date rang of Device', - }) - async certifiedlogdaterang( - @UserDecorator() user: ILoggedInUser, - @Query('groupUid') groupuId: string, - @Query('pagenumber') pagenumber: number, - @Query('externalId') externalId?: number, - ): Promise { - this.logger.verbose(`With in certifiedlogdaterang`); - const regexExp = - /^[0-9a-fA-F]{8}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{12}$/; - if (groupuId === null || !regexExp.test(groupuId)) { - this.logger.error( - `Please Add the valid UID ,invalid group uid value was sent`, - ); - return new Promise((resolve, reject) => { - reject( - new ConflictException({ - success: false, - message: - ' Please Add the valid UID ,invalid group uid value was sent', - }), - ); - }); - } - - let group: DeviceGroup | null; - group = await this.deviceGroupService.findOne({ - devicegroup_uid: groupuId, - }); - if (group === null || group.buyerId != user.id) { - this.logger.error( - `Group UId is not of this buyer, invalid value was sent`, - ); - return new Promise((resolve, reject) => { - reject( - new ConflictException({ - success: false, - message: 'Group UId is not of this buyer, invalid value was sent', - }), - ); - }); - } - if (externalId != null || externalId != undefined) { - let device: DeviceDTO | null; - - device = await this.deviceService.findOne(externalId); - if (device === null) { - this.logger.error(`device not found, invalid value was sent`); - return new Promise((resolve, reject) => { - reject( - new ConflictException({ - success: false, - message: 'device not found, invalid value was sent', - }), - ); - }); - } - return await this.deviceService.getcertifieddevicedaterange( - device, - group.id, - ); - } else { - return await this.deviceService.getcertifieddevicedaterangeBygroupid( - group.id, - pagenumber, - ); - } - } - - /** - * It is POST api to create array of devices by uploading csv files with device data - * @param user is loggedIn user from request - * @param organizationId is organization unique identifier with number type to map with the respective organization - * @param fileToProcess is parsed data of uploaded csv file - * @returns {DeviceCsvFileProcessingJobsEntity} - */ - @Post('addByAdmin/process-creation-bulk-devices-csv/:organizationId') - @UseGuards(AuthGuard(['jwt', 'oauth2-client-password']), PermissionGuard) - @Permission('Write') - @ACLModules('DEVICE_BULK_MANAGEMENT_CRUDL') - @ApiResponse({ - status: HttpStatus.OK, - type: [DeviceCsvFileProcessingJobsEntity], - description: 'Returns created devices from csv', - }) - @ApiBody({ type: CSVBulkUploadDTO }) - public async processCreationBulkFromCSV( - @UserDecorator() user: ILoggedInUser, - @Param('organizationId') organizationId: number | null, - @Body() fileToProcess: CSVBulkUploadDTO, - ): Promise { - this.logger.verbose(`With in processCreationBulkFromCSV`); - if (organizationId === null || organizationId === undefined) { - this.logger.error(`User needs to have organization added`); - throw new ConflictException({ - success: false, - message: 'User needs to have organization added', - }); - } - - if (fileToProcess.fileName == undefined) { - this.logger.error(`File Not Found`); - throw new ConflictException({ - success: false, - message: 'File Not Found', - }); - } - if (!fileToProcess.fileName.endsWith('.csv')) { - this.logger.error(`Invalid file`); - throw new ConflictException({ - success: false, - message: 'Invalid file', - }); - } - - let jobCreated: any; - if (user.role === Role.ApiUser) { - const organization = - await this.organizationService.findOne(organizationId); - const orguser = await this.userService.findByEmail(organization.orgEmail); - if (organization.api_user_id != user.api_user_id) { - this.logger.error( - `The requested organization is belongs to other apiuser`, - ); - throw new BadRequestException({ - success: false, - message: 'The requested organization is belongs to other apiuser', - }); - } - - if (orguser.role != Role.OrganizationAdmin) { - this.logger.error(`Unauthorized`); - throw new UnauthorizedException({ - success: false, - message: 'Unauthorized', - }); - } - - jobCreated = await this.deviceGroupService.createCSVJobForFile( - user.id, - organizationId, - StatusCSV.Added, - fileToProcess.fileName, - user.api_user_id, - ); - } else { - jobCreated = await this.deviceGroupService.createCSVJobForFile( - user.id, - organizationId, - StatusCSV.Added, - fileToProcess.fileName, - ); - } - return jobCreated; - } -} +import { + Controller, + Get, + Post, + Put, + Patch, + Delete, + HttpStatus, + Param, + Body, + UseGuards, + ValidationPipe, + Query, + ConflictException, + HttpException, + UnauthorizedException, + BadRequestException, + Logger, +} from '@nestjs/common'; + +import { + ApiBearerAuth, + ApiNotFoundResponse, + ApiResponse, + ApiOkResponse, + ApiSecurity, + ApiTags, + ApiQuery, + ApiBody, +} from '@nestjs/swagger'; +import { AuthGuard } from '@nestjs/passport'; +import { plainToClass } from 'class-transformer'; + +import { DeviceService } from './device.service'; +import { + FilterDTO, + NewDeviceDTO, + UpdateDeviceDTO, + DeviceDTO, + DeviceGroupByDTO, + GroupedDevicesDTO, +} from './dto'; +import { CSVBulkUploadDTO } from '../device-group/dto'; +import { Role } from '../../utils/enums'; +import { RolesGuard } from '../../guards/RolesGuard'; +import { PermissionGuard } from '../../guards/PermissionGuard'; +import { ILoggedInUser } from '../../models'; +import { CodeNameDTO } from './dto/code-name.dto'; +import { ActiveUserGuard } from '../../guards'; +import { Roles } from '../user/decorators/roles.decorator'; +import { UserDecorator } from '../user/decorators/user.decorator'; +import { DeviceGroupService } from '../device-group/device-group.service'; +import { Permission } from '../permission/decorators/permission.decorator'; +import { ACLModules } from '../access-control-layer-module-service/decorator/aclModule.decorator'; +import { CountrycodeService } from '../countrycode/countrycode.service'; +import { countryCodesList } from '../../models/country-code'; +import { isValidUTCDateFormat } from '../../utils/checkForISOStringFormat'; +import { DeviceGroup } from '../device-group/device-group.entity'; +import { + DeviceCsvFileProcessingJobsEntity, + StatusCSV, +} from '../device-group/device_csv_processing_jobs.entity'; +import { Device } from './device.entity'; +import { OrganizationService } from '../organization/organization.service'; +import { UserService } from '../user/user.service'; +import { FindOneOptions } from 'typeorm'; + +/** + * It is Controller of device with the endpoints of device operations. + */ +@ApiTags('device') +@ApiBearerAuth('access-token') +@ApiSecurity('drec') +@Controller('/device') +export class DeviceController { + private readonly logger = new Logger(DeviceController.name); + + constructor( + private readonly deviceGroupService: DeviceGroupService, + private readonly deviceService: DeviceService, + private readonly organizationService: OrganizationService, + private readonly userService: UserService, + ) {} + + /** + * It is GET api to list all devices with paginatiion and fiteration by organization and filterationDto + */ + @Get() + @UseGuards(AuthGuard('jwt'), ActiveUserGuard, RolesGuard, PermissionGuard) + @Roles(Role.Admin) + @Permission('Read') + @ACLModules('DEVICE_MANAGEMENT_CRUDL') + @ApiQuery({ name: 'pagenumber', type: Number, required: false }) + @ApiQuery({ name: 'OrganizationId', type: Number, required: false }) + @ApiOkResponse({ type: [DeviceDTO], description: 'Returns all Devices' }) + async getAll( + @Query(ValidationPipe) filterDto: FilterDTO, + @Query('pagenumber') pagenumber: number | null, + @Query('OrganizationId') OrgId: number | null, + ) /*: Promise*/ { + this.logger.verbose(`With in getAll`); + return this.deviceService.find(filterDto, pagenumber, OrgId); + } + + /** + * It is GET api to list all devices for reservation + * @return {Array} return array of devices for reservation + */ + @Get('/ungrouped/buyerreservation') + @UseGuards( + AuthGuard(['jwt', 'oauth2-client-password']), + PermissionGuard, + RolesGuard, + ) + @Permission('Read') + @ACLModules('DEVICE_MANAGEMENT_CRUDL') + @Roles(Role.Buyer, Role.SubBuyer, Role.ApiUser) + @ApiOkResponse({ type: [DeviceDTO], description: 'Returns all Devices' }) + async getAllDeviceForBuyer( + @Query(ValidationPipe) filterDto: FilterDTO, + @Query('pagenumber') pagenumber: number | null, + @UserDecorator() { organizationId, api_user_id, role }: ILoggedInUser, + ): Promise { + this.logger.verbose(`With in getAllDeviceForBuyer`); + if (filterDto.organizationId) { + const organization = await this.organizationService.findOne( + filterDto.organizationId, + ); + const orguser = await this.userService.findByEmail(organization.orgEmail); + if (role === Role.ApiUser) { + if (organization.api_user_id != api_user_id) { + this.logger.error( + `The requested organization is belongs to other apiuser`, + ); + throw new UnauthorizedException({ + success: false, + message: `The requested organization is belongs to other apiuser`, + }); + } + + if ( + orguser.role === Role.OrganizationAdmin || + orguser.role === Role.DeviceOwner + ) { + this.logger.error( + `Unauthorized... The requested user is developer or device owner`, + ); + throw new UnauthorizedException({ + success: false, + message: `Unauthorized`, + }); + } + } else { + if (organizationId != organization.id) { + this.logger.error( + `The requested organization is not same as user's organization`, + ); + throw new UnauthorizedException({ + success: false, + message: `The requested organization is not same as user's organization`, + }); + } + } + } + + if (role !== Role.ApiUser) { + api_user_id = null; + } + + return this.deviceService.finddeviceForBuyer( + filterDto, + pagenumber, + api_user_id, + ); + } + + /** + * It is GET api to list all ungrouped devices with filteration + * @return {GroupedDevicesDTO} returns ungrouped devices + */ + @Get('/ungrouped') + @UseGuards(AuthGuard('jwt'), ActiveUserGuard, RolesGuard, PermissionGuard) + @Roles(Role.Admin, Role.DeviceOwner) + @Permission('Read') + @ACLModules('DEVICE_MANAGEMENT_CRUDL') + @ApiOkResponse({ + type: [GroupedDevicesDTO], + description: 'Returns all ungrouped Devices', + }) + async getAllUngrouped( + @UserDecorator() { organizationId }: ILoggedInUser, + @Query(ValidationPipe) orderFilterDto: DeviceGroupByDTO, + ): Promise { + this.logger.verbose(`With in getAllUngrouped`); + return this.deviceService.findUngrouped(organizationId, orderFilterDto); + } + + /** + * It is GET to list all device code types in dropdown + * @returns {Array} + */ + @Get('/device-type') + @ApiResponse({ + status: HttpStatus.OK, + type: [CodeNameDTO], + description: 'Returns all IREC device types', + }) + getDeviceTypes(): CodeNameDTO[] { + this.logger.verbose(`With in getDeviceTypes`); + const deviceTypes = this.deviceService.getDeviceTypes(); + + return deviceTypes.map((deviceType) => + plainToClass(CodeNameDTO, deviceType), + ); + } + + /** + * It is GET api to list all fuel types in dropdown + * @returns {Array} + */ + @Get('/fuel-type') + @ApiResponse({ + status: HttpStatus.OK, + type: [CodeNameDTO], + description: 'Returns all IREC fuel types', + }) + getFuelTypes(): CodeNameDTO[] { + this.logger.verbose(`With in getFuelTypes`); + const fuelTypes = this.deviceService.getFuelTypes(); + return fuelTypes.map((fuelType) => plainToClass(CodeNameDTO, fuelType)); + } + + /** + * It is GET api to list all my devices with filteration and pagination + * @returns {Array} + */ + @Get('/my') + @UseGuards( + AuthGuard(['jwt', 'oauth2-client-password']), + ActiveUserGuard, + PermissionGuard, + ) + @Permission('Read') + @ACLModules('DEVICE_MANAGEMENT_CRUDL') + @ApiQuery({ name: 'pagenumber', type: Number, required: false }) + @ApiResponse({ + status: HttpStatus.OK, + type: [DeviceDTO], + description: 'Returns my Devices', + }) + async getMyDevices( + @Query(ValidationPipe) filterDto: FilterDTO, + @UserDecorator() { organizationId, api_user_id, role }: ILoggedInUser, + @Query('pagenumber') pagenumber: number | null, + ) /*: Promise*/ { + this.logger.verbose(`With in getMyDevices`); + if (filterDto.country) { + filterDto.country = filterDto.country.toUpperCase(); + + if ( + filterDto.country && + typeof filterDto.country === 'string' && + filterDto.country.length === 3 + ) { + const countries = countryCodesList; + if ( + countries.find((ele) => ele.countryCode === filterDto.country) === + undefined + ) { + this.logger.error( + `Invalid countryCode, some of the valid country codes are "GBR" - "United Kingdom of Great Britain and Northern Ireland", "CAN" - "Canada" "IND" - "India", "DEU"- "Germany"`, + ); + return new Promise((resolve, reject) => { + reject( + new ConflictException({ + success: false, + message: + ' Invalid countryCode, some of the valid country codes are "GBR" - "United Kingdom of Great Britain and Northern Ireland", "CAN" - "Canada" "IND" - "India", "DEU"- "Germany"', + }), + ); + }); + } + } else { + this.logger.error( + `Invalid countryCode, some of the valid country codes are "GBR" - "United Kingdom of Great Britain and Northern Ireland", "CAN" - "Canada" "IND" - "India", "DEU"- "Germany"`, + ); + return new Promise((resolve, reject) => { + reject( + new ConflictException({ + success: false, + message: + ' Invalid countryCode, some of the valid country codes are "GBR" - "United Kingdom of Great Britain and Northern Ireland", "CAN" - "Canada" "IND" - "India", "DEU"- "Germany"', + }), + ); + }); + } + } + if (filterDto.organizationId) { + if (role === Role.ApiUser) { + const organization = await this.organizationService.findOne( + filterDto.organizationId, + ); + const orguser = await this.userService.findByEmail( + organization.orgEmail, + ); + if (organization.api_user_id != api_user_id) { + this.logger.error( + `The organization Id in param is belongs to other apiuser`, + ); + throw new UnauthorizedException({ + success: false, + message: 'The organization Id in param is belongs to other apiuser', + }); + } else { + if (orguser.role != Role.OrganizationAdmin) { + this.logger.error(`Unauthorized`); + throw new UnauthorizedException({ + success: false, + message: 'Unauthorized', + }); + } + } + } else { + if (filterDto.organizationId != organizationId) { + this.logger.error( + `The organization Id in param should be same as user's organization`, + ); + throw new UnauthorizedException({ + success: false, + message: `The organization Id in param should be same as user's organization`, + }); + } + } + + organizationId = filterDto.organizationId; + } + + this.logger.log('In devices before calling service'); + return await this.deviceService.getOrganizationDevices( + organizationId, + api_user_id, + role, + filterDto, + pagenumber, + ); + } + + /** + * It is GET api to fetch an device by the deviceId in param + * @param id is deviceId in type number + * @returns {DeviceDTO | null} DeviceDto for success response and null when there is no device found by the id + */ + @Get('/:id') + @UseGuards( + AuthGuard(['jwt', 'oauth2-client-password']), + ActiveUserGuard, + PermissionGuard, + ) + @Permission('Read') + @ACLModules('DEVICE_MANAGEMENT_CRUDL') + @ApiQuery({ name: 'apiUserId', type: String, required: false }) + @ApiQuery({ name: 'organizationId', type: Number, required: false }) + @ApiOkResponse({ type: DeviceDTO, description: 'Returns a Device' }) + @ApiNotFoundResponse({ + description: `The device with the code doesn't exist`, + }) + async get( + @Param('id') id: number, + @Query('apiUserId') api_user_id: string | null, + @Query('organizationId') organizationId: number | null, + ): Promise { + this.logger.verbose(`With in get`); + let devicedata: Device; + if (api_user_id && organizationId) { + devicedata = await this.deviceService.findOne(id, { + api_user_id: api_user_id, + organizationId: organizationId, + } as FindOneOptions); + } else { + devicedata = await this.deviceService.findOne(id); + } + devicedata.externalId = devicedata.developerExternalId; + delete devicedata['developerExternalId']; + return devicedata; + } + + /** + * It is GET api to fetch an device by externalId in param + * @param id is externalId in device + * @param param1 + * @returns {DeviceDTO | null} DeviceDto for success response and null when there is no device found by the id + */ + @Get('externalId/:id') + @UseGuards(AuthGuard('jwt'), PermissionGuard) + @Permission('Read') + @ACLModules('DEVICE_MANAGEMENT_CRUDL') + @ApiOkResponse({ type: DeviceDTO, description: 'Returns a Device' }) + @ApiNotFoundResponse({ + description: `The device with the code doesn't exist`, + }) + async getByExternalId( + @Param('id') id: string, + @UserDecorator() { organizationId }: ILoggedInUser, + ): Promise { + this.logger.verbose(`With in getByExternalId`); + const devicedata = await this.deviceService.findDeviceByDeveloperExternalId( + id, + organizationId, + ); + devicedata.externalId = devicedata.developerExternalId; + delete devicedata['developerExternalId']; + return devicedata; + } + + /** + * It is POST api to create an device + * @param param0 It is organizationId from user at request + * @param deviceToRegister It is body payload to create device + * @returns {DeviceDTO} + */ + @Post() + @UseGuards(AuthGuard(['jwt', 'oauth2-client-password']), PermissionGuard) + @Permission('Write') + @ACLModules('DEVICE_MANAGEMENT_CRUDL') + @ApiResponse({ + status: HttpStatus.OK, + type: NewDeviceDTO, + description: 'Returns a new created Device id', + }) + public async create( + @UserDecorator() { organizationId, role, api_user_id }: ILoggedInUser, + @Body() deviceToRegister: NewDeviceDTO, + ): Promise { + this.logger.verbose(`With in create`); + deviceToRegister.externalId = deviceToRegister.externalId.trim(); + if (deviceToRegister.externalId.trim() === '') { + this.logger.error(`externalId should not be empty`); + return new Promise((resolve, reject) => { + reject( + new ConflictException({ + success: false, + message: `externalId should not be empty`, + }), + ); + }); + } + + if (!isValidUTCDateFormat(deviceToRegister.commissioningDate)) { + this.logger.error( + `Invalid commissioning date, valid format is YYYY-MM-DDThh:mm:ss.millisecondsZ example 2022-10-18T11:35:27.640Z`, + ); + return new Promise((resolve, reject) => { + reject( + new ConflictException({ + success: false, + message: + ' Invalid commissioning date, valid format is YYYY-MM-DDThh:mm:ss.millisecondsZ example 2022-10-18T11:35:27.640Z ', + }), + ); + }); + } + if ( + new Date(deviceToRegister.commissioningDate).getTime() > + new Date().getTime() + ) { + this.logger.error( + `Invalid commissioning date, commissioning is greater than current date`, + ); + return new Promise((resolve, reject) => { + reject( + new ConflictException({ + success: false, + message: ` Invalid commissioning date, commissioning is greater than current date`, + }), + ); + }); + } + if (deviceToRegister['groupId'] === 0 || deviceToRegister['groupId']) { + deviceToRegister['groupId'] = null; + } + deviceToRegister.countryCode = deviceToRegister.countryCode.toUpperCase(); + if ( + deviceToRegister.countryCode && + typeof deviceToRegister.countryCode === 'string' && + deviceToRegister.countryCode.length === 3 + ) { + const countries = countryCodesList; + if ( + countries.find( + (ele) => ele.countryCode === deviceToRegister.countryCode, + ) === undefined + ) { + this.logger.error( + `Invalid countryCode, some of the valid country codes are "GBR" - "United Kingdom of Great Britain and Northern Ireland", "CAN" - "Canada" "IND" - "India", "DEU"- "Germany"`, + ); + return new Promise((resolve, reject) => { + reject( + new ConflictException({ + success: false, + message: + ' Invalid countryCode, some of the valid country codes are "GBR" - "United Kingdom of Great Britain and Northern Ireland", "CAN" - "Canada" "IND" - "India", "DEU"- "Germany"', + }), + ); + }); + } + } else { + this.logger.error( + `Invalid countryCode, some of the valid country codes are "GBR" - "United Kingdom of Great Britain and Northern Ireland", "CAN" - "Canada" "IND" - "India", "DEU"- "Germany"`, + ); + return new Promise((resolve, reject) => { + reject( + new ConflictException({ + success: false, + message: + ' Invalid countryCode, some of the valid country codes are "GBR" - "United Kingdom of Great Britain and Northern Ireland", "CAN" - "Canada" "IND" - "India", "DEU"- "Germany"', + }), + ); + }); + } + if (isNaN(parseFloat(deviceToRegister.capacity.toString()))) { + this.logger.error(`Invalid Capacity or energy Storage Capacity`); + return new Promise((resolve, reject) => { + reject( + new ConflictException({ + success: false, + message: ' Invalid Capacity or energy Storage Capacity', + }), + ); + }); + } + if ( + deviceToRegister.capacity <= 0 || + deviceToRegister.energyStorageCapacity < 0 + ) { + this.logger.error( + `Invalid Capacity or energy Storage Capacity, it should be greater than 0`, + ); + return new Promise((resolve, reject) => { + reject( + new ConflictException({ + success: false, + message: + ' Invalid Capacity or energy Storage Capacity, it should be greater than 0', + }), + ); + }); + } + if ( + deviceToRegister.version === null || + deviceToRegister.version === undefined || + deviceToRegister.version === '0' + ) { + deviceToRegister.version = '1.0'; + } + if (role === Role.Admin || role === Role.ApiUser) { + if (deviceToRegister.organizationId) { + this.logger.debug('Line No: 314'); + organizationId = deviceToRegister.organizationId; + } else { + this.logger.error( + `Organization id is required,please add your developer's Organization`, + ); + return new Promise((resolve, reject) => { + reject( + new ConflictException({ + success: false, + message: `Organization id is required,please add your developer's Organization `, + }), + ); + }); + } + } + return await this.deviceService.register( + organizationId, + deviceToRegister, + api_user_id, + role, + ); + } + + /** + * It is PATCH api to update an device by externalId + * @param user is loggedin user from user at request + * @param externalId is unique external id in device entity + * @param deviceToUpdate is body payload to update an device + * @returns {DeviceDTO} + */ + @Patch('/:externalId') + @UseGuards(AuthGuard('jwt'), PermissionGuard) + @Permission('Update') + @ACLModules('DEVICE_MANAGEMENT_CRUDL') + @ApiResponse({ + status: HttpStatus.OK, + type: UpdateDeviceDTO, + description: 'Returns an updated Device', + }) + @ApiNotFoundResponse({ description: `No device found` }) + public async update( + @UserDecorator() user: ILoggedInUser, + @Param('externalId') externalId: string, + @Body() deviceToUpdate: UpdateDeviceDTO, + ): Promise { + this.logger.verbose(`With in update`); + + if (deviceToUpdate.externalId) { + deviceToUpdate.externalId = deviceToUpdate.externalId.trim(); + if (deviceToUpdate.externalId === '') { + this.logger.error(`externalId should not be empty`); + return new Promise((resolve, reject) => { + reject( + new ConflictException({ + success: false, + message: `externalId should not be empty`, + }), + ); + }); + } + + const checkexternalid = + await this.deviceService.findDeviceByDeveloperExternalId( + deviceToUpdate.externalId, + user.organizationId, + ); + if ( + checkexternalid != undefined && + checkexternalid.developerExternalId === externalId.trim() + ) { + this.logger.log('Line No: 236'); + return new Promise((resolve, reject) => { + reject( + new ConflictException({ + success: false, + message: `ExternalId already exist in this organization, can't update with same external id ${deviceToUpdate.externalId}`, + }), + ); + }); + } + } + + if (deviceToUpdate.countryCode != undefined) { + deviceToUpdate.countryCode = deviceToUpdate.countryCode.toUpperCase(); + if ( + deviceToUpdate.countryCode && + typeof deviceToUpdate.countryCode === 'string' && + deviceToUpdate.countryCode.length === 3 + ) { + const countries = countryCodesList; + if ( + countries.find( + (ele) => ele.countryCode === deviceToUpdate.countryCode, + ) === undefined + ) { + this.logger.error( + `Invalid countryCode, some of the valid country codes are "GBR" - "United Kingdom of Great Britain and Northern Ireland", "CAN" - "Canada" "IND" - "India", "DEU"- "Germany"`, + ); + return new Promise((resolve, reject) => { + reject( + new ConflictException({ + success: false, + message: + ' Invalid countryCode, some of the valid country codes are "GBR" - "United Kingdom of Great Britain and Northern Ireland", "CAN" - "Canada" "IND" - "India", "DEU"- "Germany"', + }), + ); + }); + } + } else { + this.logger.error( + `Invalid countryCode, some of the valid country codes are "GBR" - "United Kingdom of Great Britain and Northern Ireland", "CAN" - "Canada" "IND" - "India", "DEU"- "Germany"`, + ); + return new Promise((resolve, reject) => { + reject( + new ConflictException({ + success: false, + message: + ' Invalid countryCode, some of the valid country codes are "GBR" - "United Kingdom of Great Britain and Northern Ireland", "CAN" - "Canada" "IND" - "India", "DEU"- "Germany"', + }), + ); + }); + } + } + + if (deviceToUpdate.capacity <= 0) { + this.logger.error(`Invalid Capacity, it should be greater than 0`); + return new Promise((resolve, reject) => { + reject( + new ConflictException({ + success: false, + message: ' Invalid Capacity, it should be greater than 0', + }), + ); + }); + } + if ( + !isValidUTCDateFormat(deviceToUpdate.commissioningDate) && + deviceToUpdate.commissioningDate !== undefined + ) { + this.logger.error( + `Invalid commissioning date, valid format is YYYY-MM-DDThh:mm:ss.millisecondsZ example 2022-10-18T11:35:27.640Z`, + ); + return new Promise((resolve, reject) => { + reject( + new ConflictException({ + success: false, + message: + ' Invalid commissioning date, valid format is YYYY-MM-DDThh:mm:ss.millisecondsZ example 2022-10-18T11:35:27.640Z ', + }), + ); + }); + } + if ( + new Date(deviceToUpdate.commissioningDate).getTime() > + new Date().getTime() + ) { + this.logger.error( + `Invalid commissioning date, commissioning is greater than current date`, + ); + return new Promise((resolve, reject) => { + reject( + new ConflictException({ + success: false, + message: ` Invalid commissioning date, commissioning is greater than current date`, + }), + ); + }); + } + + if (deviceToUpdate.commissioningDate) { + const checkexternalid = + await this.deviceService.findDeviceByDeveloperExternalId( + externalId, + user.organizationId, + ); + const noOfHistRead: number = + await this.deviceService.getNumberOfHistReads( + checkexternalid.externalId, + ); + const noOfOnGoingRead: number = + await this.deviceService.getNumberOfOngReads( + checkexternalid.externalId, + checkexternalid.createdAt, + ); + + if ( + deviceToUpdate.commissioningDate != checkexternalid.commissioningDate + ) { + if (noOfHistRead > 0 || noOfOnGoingRead > 0) { + this.logger.error( + `Commissioning date cannot be changed due to existing meter reads available for ${checkexternalid.developerExternalId}`, + ); + throw new ConflictException({ + success: false, + message: ` Commissioning date cannot be changed due to existing meter reads available for ${checkexternalid.developerExternalId}`, + }); + } + + if ( + new Date(deviceToUpdate.commissioningDate).getTime() > + new Date(checkexternalid.createdAt).getTime() + ) { + this.logger.error( + `Invalid commissioning date, commissioning is greater than device onboarding date`, + ); + throw new ConflictException({ + success: false, + message: `Invalid commissioning date, commissioning is greater than device onboarding date`, + }); + } + } + } + return await this.deviceService.update( + user.organizationId, + user.role, + externalId, + deviceToUpdate, + ); + } + + /** + * It is DELETE api to delete an device by id + * @param id is deviceId + * @param param1 is getting organizationId and user role from user request + * @returns {any} + */ + @Delete('/:id') + @UseGuards(AuthGuard('jwt'), RolesGuard, PermissionGuard) + @Permission('Delete') + @ACLModules('DEVICE_MANAGEMENT_CRUDL') + @Roles(Role.OrganizationAdmin, Role.Admin) + @ApiResponse({ + status: HttpStatus.OK, + description: 'Remove device group', + }) + @ApiNotFoundResponse({ description: `No device group found` }) + public async remove( + @Param('id') id: number, + @UserDecorator() { organizationId, role }: ILoggedInUser, + ): Promise { + this.logger.verbose(`With in remove`); + const checkisungroup = this.deviceService.findUngroupedById(id); + if (checkisungroup) { + let fitlerop: any; + if (role === 'Admin') { + fitlerop = { + groupId: null, + }; + } else { + fitlerop = { + groupId: null, + organizationId: organizationId, + }; + } + return await this.deviceService.remove(id, fitlerop); + } + } + + /** + * It is GET api to list all total amount of reads by each devices grouped by organization + * @param param0 is getting organizationId from user request. + * @returns {Array} + */ + @Get('/my/totalamountread') + @UseGuards(AuthGuard('jwt'), ActiveUserGuard, PermissionGuard) + @Permission('Read') + @ACLModules('DEVICE_MANAGEMENT_CRUDL') + @ApiResponse({ + status: HttpStatus.OK, + type: [DeviceDTO], + description: 'Returns my Devices', + }) + async getMyDevicesTotal( + @UserDecorator() { organizationId }: ILoggedInUser, + ): Promise { + this.logger.verbose(`Wth in getMyDevicesTotal`); + return await this.deviceService.getOrganizationDevicesTotal(organizationId); + } + + /** + * It is PUT api tp update the device onboarding date by deviceId + * @param param0 is getting organizationId from user request + * @param deviceId is deviceId from device unique identifier + * @param givenDate is new onboarding date to be updated. + * @returns {} + */ + @Put('/my/deviceOnBoardingDate') + @UseGuards(AuthGuard('jwt'), PermissionGuard) + @Permission('Write') + @ACLModules('DEVICE_MANAGEMENT_CRUDL') + @ApiResponse({ + status: HttpStatus.OK, + description: "change the device's OnBoarding date", + }) + @ApiQuery({ name: 'deviceId', description: 'Device Id' }) + @ApiQuery({ + name: 'givenDate', + description: 'Update the OnBoarding date', + type: Date, + }) + async changeOnBoardingDate( + @UserDecorator() { organizationId }: ILoggedInUser, + @Query('deviceId') deviceId, + @Query('givenDate') givenDate, + ) { + this.logger.verbose(`With in changeOnBoardingDate`); + if (process.env.MODE != 'dev') { + this.logger.error(`Currently not in dev environment`); + throw new HttpException('Currently not in dev environment', 400); + } + const device: DeviceDTO | null = + await this.deviceService.findDeviceByDeveloperExternalId( + deviceId, + organizationId, + ); + this.logger.debug( + 'THE DEVICE FROM ExTERNALID IS::::::::::::' + device.externalId, + ); + if (!device) { + this.logger.error(`Device dosen't exist`); + throw new HttpException("Device dosen't exist", 400); + } + const deviceExternalId = device.externalId; + const deviceOnboardedDate = device.createdAt; + return this.deviceService.changeDeviceCreatedAt( + deviceExternalId, + deviceOnboardedDate, + givenDate, + ); + } + + /** + * It is GET api to list all devices with auto complete + * @param param0 is getting organizationId from user request + * @param externalId is unique identoifier of an device + * @returns {} + */ + @Get('/my/autocomplete') + @UseGuards(AuthGuard('jwt'), ActiveUserGuard, PermissionGuard) + @Permission('Read') + @ACLModules('DEVICE_MANAGEMENT_CRUDL') + @ApiResponse({ + status: HttpStatus.OK, + description: 'Returns Auto-Complete', + }) + @ApiQuery({ name: 'externalId', description: 'externalId', type: String }) + async autocomplete( + @UserDecorator() { organizationId }: ILoggedInUser, + @Query('externalId') externalId: string, + ) { + this.logger.verbose(`With in autocomplete`); + return await this.deviceService.atto(organizationId, externalId); + } + + /** + * It is GET api to fetch the certified device records with in the range of date + * @param user is loggedIn user at request + * @param externalId is unique identifier of device + * @param groupuId + * @returns {any} + */ + @Get('/certifiedlog/first&lastdate') + @UseGuards(AuthGuard('jwt'), PermissionGuard) + @Permission('Read') + @ACLModules('DEVICE_MANAGEMENT_CRUDL') + @ApiQuery({ name: 'externalId', type: Number, required: false }) + @ApiQuery({ name: 'pagenumber', type: Number, required: false }) + @ApiResponse({ + status: HttpStatus.OK, + description: 'Returns Certified log date rang of Device', + }) + async certifiedlogdaterang( + @UserDecorator() user: ILoggedInUser, + @Query('groupUid') groupuId: string, + @Query('pagenumber') pagenumber: number, + @Query('externalId') externalId?: number, + ): Promise { + this.logger.verbose(`With in certifiedlogdaterang`); + const regexExp = + /^[0-9a-fA-F]{8}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{12}$/; + if (groupuId === null || !regexExp.test(groupuId)) { + this.logger.error( + `Please Add the valid UID ,invalid group uid value was sent`, + ); + return new Promise((resolve, reject) => { + reject( + new ConflictException({ + success: false, + message: + ' Please Add the valid UID ,invalid group uid value was sent', + }), + ); + }); + } + + let group: DeviceGroup | null; + group = await this.deviceGroupService.findOne({ + devicegroup_uid: groupuId, + }); + if (group === null || group.buyerId != user.id) { + this.logger.error( + `Group UId is not of this buyer, invalid value was sent`, + ); + return new Promise((resolve, reject) => { + reject( + new ConflictException({ + success: false, + message: 'Group UId is not of this buyer, invalid value was sent', + }), + ); + }); + } + if (externalId != null || externalId != undefined) { + let device: DeviceDTO | null; + + device = await this.deviceService.findOne(externalId); + if (device === null) { + this.logger.error(`device not found, invalid value was sent`); + return new Promise((resolve, reject) => { + reject( + new ConflictException({ + success: false, + message: 'device not found, invalid value was sent', + }), + ); + }); + } + return await this.deviceService.getcertifieddevicedaterange( + device, + group.id, + ); + } else { + return await this.deviceService.getcertifieddevicedaterangeBygroupid( + group.id, + pagenumber, + ); + } + } + + /** + * It is POST api to create array of devices by uploading csv files with device data + * @param user is loggedIn user from request + * @param organizationId is organization unique identifier with number type to map with the respective organization + * @param fileToProcess is parsed data of uploaded csv file + * @returns {DeviceCsvFileProcessingJobsEntity} + */ + @Post('addByAdmin/process-creation-bulk-devices-csv/:organizationId') + @UseGuards(AuthGuard(['jwt', 'oauth2-client-password']), PermissionGuard) + @Permission('Write') + @ACLModules('DEVICE_BULK_MANAGEMENT_CRUDL') + @ApiResponse({ + status: HttpStatus.OK, + type: [DeviceCsvFileProcessingJobsEntity], + description: 'Returns created devices from csv', + }) + @ApiBody({ type: CSVBulkUploadDTO }) + public async processCreationBulkFromCSV( + @UserDecorator() user: ILoggedInUser, + @Param('organizationId') organizationId: number | null, + @Body() fileToProcess: CSVBulkUploadDTO, + ): Promise { + this.logger.verbose(`With in processCreationBulkFromCSV`); + if (organizationId === null || organizationId === undefined) { + this.logger.error(`User needs to have organization added`); + throw new ConflictException({ + success: false, + message: 'User needs to have organization added', + }); + } + + if (fileToProcess.fileName == undefined) { + this.logger.error(`File Not Found`); + throw new ConflictException({ + success: false, + message: 'File Not Found', + }); + } + if (!fileToProcess.fileName.endsWith('.csv')) { + this.logger.error(`Invalid file`); + throw new ConflictException({ + success: false, + message: 'Invalid file', + }); + } + + let jobCreated: any; + if (user.role === Role.ApiUser) { + const organization = + await this.organizationService.findOne(organizationId); + const orguser = await this.userService.findByEmail(organization.orgEmail); + if (organization.api_user_id != user.api_user_id) { + this.logger.error( + `The requested organization is belongs to other apiuser`, + ); + throw new BadRequestException({ + success: false, + message: 'The requested organization is belongs to other apiuser', + }); + } + + if (orguser.role != Role.OrganizationAdmin) { + this.logger.error(`Unauthorized`); + throw new UnauthorizedException({ + success: false, + message: 'Unauthorized', + }); + } + + jobCreated = await this.deviceGroupService.createCSVJobForFile( + user.id, + organizationId, + StatusCSV.Added, + fileToProcess.fileName, + user.api_user_id, + ); + } else { + jobCreated = await this.deviceGroupService.createCSVJobForFile( + user.id, + organizationId, + StatusCSV.Added, + fileToProcess.fileName, + ); + } + return jobCreated; + } +} diff --git a/apps/drec-api/src/pods/device/device.service.ts b/apps/drec-api/src/pods/device/device.service.ts index 5641cd17a..0882033c4 100755 --- a/apps/drec-api/src/pods/device/device.service.ts +++ b/apps/drec-api/src/pods/device/device.service.ts @@ -553,7 +553,11 @@ export class DeviceService { newDevice.developerExternalId = newDevice.externalId; newDevice.externalId = uuid(); - if (newDevice.SDGBenefits && (newDevice.SDGBenefits.includes('0') || newDevice.SDGBenefits.includes('1'))) { + if ( + newDevice.SDGBenefits && + (newDevice.SDGBenefits.includes('0') || + newDevice.SDGBenefits.includes('1')) + ) { newDevice.SDGBenefits = []; } else if (Array.isArray(newDevice.SDGBenefits)) { newDevice.SDGBenefits.forEach((sdgbname: string, index: number) => { @@ -788,8 +792,7 @@ export class DeviceService { }); if (orgId != null || orgId != undefined) { where.organizationId = orgId; - } - else if ( + } else if ( filter.organizationId != null && filter.organizationId != undefined ) { diff --git a/apps/drec-api/src/pods/issuer/issuer.service.ts b/apps/drec-api/src/pods/issuer/issuer.service.ts index 024adc64c..c733c6e38 100755 --- a/apps/drec-api/src/pods/issuer/issuer.service.ts +++ b/apps/drec-api/src/pods/issuer/issuer.service.ts @@ -229,7 +229,10 @@ export class IssuerService { allDevicesOfGroup.sort(function (a, b) { // Turn your strings into dates, and then subtract them // to get a value that is either negative, positive, or zero. - return new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime(); + return ( + new Date(b.createdAt).getTime() - + new Date(a.createdAt).getTime() + ); }); // console.log("192", allDevicesOfGroup); let deviceOnBoardedWhichIsInBetweenNextIssuance: Device = diff --git a/apps/drec-api/src/pods/reads/reads.controller.ts b/apps/drec-api/src/pods/reads/reads.controller.ts index 49088bdf3..7899b5b4d 100644 --- a/apps/drec-api/src/pods/reads/reads.controller.ts +++ b/apps/drec-api/src/pods/reads/reads.controller.ts @@ -575,19 +575,23 @@ export class ReadsController extends BaseReadsController { measurements.reads.forEach((ele) => { if ( (ele.starttimestamp instanceof Date && - (ele.starttimestamp === null || - ele.starttimestamp === undefined || - isNaN(ele.starttimestamp.getTime()))) || + (ele.starttimestamp === null || + ele.starttimestamp === undefined || + isNaN(ele.starttimestamp.getTime()))) || (ele.endtimestamp instanceof Date && - (ele.endtimestamp === null || - ele.endtimestamp === undefined || - isNaN(ele.endtimestamp.getTime()))) + (ele.endtimestamp === null || + ele.endtimestamp === undefined || + isNaN(ele.endtimestamp.getTime()))) ) { datesContainingNullOrEmptyValues = true; } - const startdateformate = isValidUTCDateFormat(ele.starttimestamp.toISOString()); + const startdateformate = isValidUTCDateFormat( + ele.starttimestamp.toISOString(), + ); //dateFormateToCheck.test(ele.starttimestamp); - const enddateformate = isValidUTCDateFormat(ele.endtimestamp.toISOString()); + const enddateformate = isValidUTCDateFormat( + ele.endtimestamp.toISOString(), + ); if (!startdateformate || !enddateformate) { datevalid = false; @@ -744,12 +748,14 @@ export class ReadsController extends BaseReadsController { if ( ele.endtimestamp instanceof Date && (ele.endtimestamp === null || - ele.endtimestamp === undefined || - isNaN(ele.endtimestamp.getTime())) + ele.endtimestamp === undefined || + isNaN(ele.endtimestamp.getTime())) ) { datesContainingNullOrEmptyValues = true; } - const enddateformate = isValidUTCDateFormat(ele.endtimestamp.toISOString()); + const enddateformate = isValidUTCDateFormat( + ele.endtimestamp.toISOString(), + ); if (!enddateformate) { datevalid1 = false; @@ -1135,19 +1141,23 @@ export class ReadsController extends BaseReadsController { measurements.reads.forEach((ele) => { if ( (ele.starttimestamp instanceof Date && - (ele.starttimestamp === null || - ele.starttimestamp === undefined || - isNaN(ele.starttimestamp.getTime()))) || + (ele.starttimestamp === null || + ele.starttimestamp === undefined || + isNaN(ele.starttimestamp.getTime()))) || (ele.endtimestamp instanceof Date && - (ele.endtimestamp === null || - ele.endtimestamp === undefined || - isNaN(ele.endtimestamp.getTime()))) + (ele.endtimestamp === null || + ele.endtimestamp === undefined || + isNaN(ele.endtimestamp.getTime()))) ) { datesContainingNullOrEmptyValues = true; } - const startdateformate = isValidUTCDateFormat(ele.starttimestamp.toISOString()); + const startdateformate = isValidUTCDateFormat( + ele.starttimestamp.toISOString(), + ); - const enddateformate = isValidUTCDateFormat(ele.endtimestamp.toISOString()); + const enddateformate = isValidUTCDateFormat( + ele.endtimestamp.toISOString(), + ); if (!startdateformate || !enddateformate) { datevalid = false; @@ -1300,14 +1310,16 @@ export class ReadsController extends BaseReadsController { measurements.reads.forEach((ele) => { this.logger.log('Line No: 512'); if ( - (ele.endtimestamp instanceof Date && - (ele.endtimestamp === null || + ele.endtimestamp instanceof Date && + (ele.endtimestamp === null || ele.endtimestamp === undefined || - isNaN(ele.endtimestamp.getTime()))) + isNaN(ele.endtimestamp.getTime())) ) { datesContainingNullOrEmptyValues = true; } - const enddateformate = isValidUTCDateFormat(ele.endtimestamp.toISOString()); + const enddateformate = isValidUTCDateFormat( + ele.endtimestamp.toISOString(), + ); if (!enddateformate) { datevalid1 = false; diff --git a/apps/drec-api/src/pods/reads/reads.service.ts b/apps/drec-api/src/pods/reads/reads.service.ts index 014a48485..b904f516d 100755 --- a/apps/drec-api/src/pods/reads/reads.service.ts +++ b/apps/drec-api/src/pods/reads/reads.service.ts @@ -482,8 +482,7 @@ export class ReadsService { return reject( new ConflictException({ success: false, - message: - `The sent date for reading ${element.endtimestamp} is less than last sent meter read date ${final.timestamp}`, + message: `The sent date for reading ${element.endtimestamp} is less than last sent meter read date ${final.timestamp}`, }), ); } @@ -537,8 +536,7 @@ export class ReadsService { return reject( new ConflictException({ success: false, - message: - `The sent date for reading ${element.endtimestamp} is less than last sent meter read date ${final.timestamp.toISOString()}`, + message: `The sent date for reading ${element.endtimestamp} is less than last sent meter read date ${final.timestamp.toISOString()}`, }), ); } @@ -1386,7 +1384,8 @@ export class ReadsService { if (previousPageData.length > 0) { previousReadTime = (previousPageData[0] as any).timestamp; this.logger.verbose( - 'previous page read data[0]::::' + (previousPageData[0] as any).timestamp, + 'previous page read data[0]::::' + + (previousPageData[0] as any).timestamp, ); } else { previousReadTime = null; diff --git a/apps/drec-api/src/pods/user/user.entity.ts b/apps/drec-api/src/pods/user/user.entity.ts index ccd6bd9d9..3343d6169 100755 --- a/apps/drec-api/src/pods/user/user.entity.ts +++ b/apps/drec-api/src/pods/user/user.entity.ts @@ -9,7 +9,12 @@ import { import { Exclude } from 'class-transformer'; import { ExtendedBaseEntity } from '@energyweb/origin-backend-utils'; import { ApiProperty } from '@nestjs/swagger'; -import { Role, UserStatus, PermissionString, UserPermissionStatus } from '../../utils/enums'; +import { + Role, + UserStatus, + PermissionString, + UserPermissionStatus, +} from '../../utils/enums'; import { IsEnum, IsString } from 'class-validator'; import { IUser } from '../../models'; import { Organization } from '../organization/organization.entity'; diff --git a/apps/drec-api/src/pods/user/user.service.ts b/apps/drec-api/src/pods/user/user.service.ts index 8e5e42286..2ac42a02c 100755 --- a/apps/drec-api/src/pods/user/user.service.ts +++ b/apps/drec-api/src/pods/user/user.service.ts @@ -1,742 +1,742 @@ -import { - ConflictException, - Injectable, - Inject, - Logger, - UnprocessableEntityException, - UnauthorizedException, - NotFoundException, - InternalServerErrorException, - forwardRef, -} from '@nestjs/common'; -import { InjectRepository } from '@nestjs/typeorm'; -import bcrypt from 'bcryptjs'; -import { - FindOptionsWhere, - Repository, - FindManyOptions, - SelectQueryBuilder, - Not, -} from 'typeorm'; -import { - ILoggedInUser, - IUser, - UserPasswordUpdate, - UserChangePasswordUpdate, -} from '../../models'; -import { Role, UserStatus, UserPermissionStatus } from '../../utils/enums'; -import { CreateUserORGDTO } from './dto/create-user.dto'; -import { ExtendedBaseEntity } from '@energyweb/origin-backend-utils'; -import { validate } from 'class-validator'; -import { UserRole } from './user_role.entity'; -import { UserDTO } from './dto/user.dto'; -import { User } from './user.entity'; -import { UpdateUserProfileDTO } from './dto/update-user-profile.dto'; -import { EmailConfirmationService } from '../email-confirmation/email-confirmation.service'; -import { UpdateUserDTO } from '../admin/dto/update-user.dto'; -import { UserFilterDTO } from '../admin/dto/user-filter.dto'; -import { OrganizationService } from '../organization/organization.service'; -import { IEmailConfirmationToken, ISuccessResponse } from '../../models'; -import { OauthClientCredentialsService } from './oauth_client.service'; -export type TUserBaseEntity = ExtendedBaseEntity & IUser; -import { ApiUserEntity } from './api-user.entity'; -import { UserLoginSessionEntity } from './user_login_session.entity'; -@Injectable() -export class UserService { - private readonly logger = new Logger(UserService.name); - - constructor( - @InjectRepository(User) private readonly repository: Repository, - @InjectRepository(UserRole) private rolerepository: Repository, - private readonly emailConfirmationService: EmailConfirmationService, - private readonly oauthClientCredentialsService: OauthClientCredentialsService, - @Inject(forwardRef(() => OrganizationService)) - private organizationService: OrganizationService, - @InjectRepository(ApiUserEntity) - private readonly apiUserEntityRepository: Repository, - @InjectRepository(UserLoginSessionEntity) - private readonly userloginSessionRepository: Repository, - ) {} - - public async seed( - data: CreateUserORGDTO, - - organizationId: number | null, - role?: Role, - status?: UserStatus, - ): Promise { - await this.checkForExistingUser(data.email); - - return this.repository.save({ - // title: data.title, - firstName: data.firstName, - lastName: data.lastName, - email: data.email.toLowerCase(), - // telephone: data.telephone, - password: this.hashPassword(data.password), - role: role || Role.Admin, - status: status || UserStatus.Active, - organization: organizationId ? { id: organizationId } : {}, - }); - } - - public async newcreate( - data: CreateUserORGDTO, - status?: UserStatus, - inviteuser?: boolean, - ): Promise { - await this.checkForExistingUser(data.email.toLowerCase()); - const api_user = - await this.oauthClientCredentialsService.findOneByApiUserId( - data.api_user_id, - ); - - let org_id; - if (!inviteuser) { - const orgdata = { - name: data.orgName !== undefined ? data.orgName : '', - organizationType: data.organizationType, - orgEmail: data.email, - address: data.orgAddress, - }; - - orgdata['api_user_id'] = api_user.api_user_id; - if (await this.organizationService.isNameAlreadyTaken(orgdata.name)) { - throw new ConflictException({ - success: false, - message: `Organization "${data.orgName}" is already existed,please use another Organization name`, - }); - } else { - const org = await this.organizationService.newcreate(orgdata); - org_id = org.id; - this.logger.debug( - `Successfully registered a new organization with id ${JSON.stringify(org.id)}`, - ); - } - } - if (data.orgid) { - org_id = data.orgid; - } - let role; - let roleId; - if ( - data.organizationType === 'Buyer' || - data.organizationType === 'buyer' - ) { - role = Role.Buyer; - roleId = 4; - } else if ( - data.organizationType === 'Developer' || - data.organizationType === 'Developer' - ) { - role = Role.OrganizationAdmin; - roleId = 2; - } else if ( - data.organizationType === 'ApiUser' || - data.organizationType === 'apiuser' - ) { - role = Role.ApiUser; - roleId = 6; - } - - const user = await this.repository.save({ - firstName: data.firstName, - lastName: data.lastName, - email: data.email.toLowerCase(), - password: this.hashPassword(data.password), - notifications: true, - status: status || UserStatus.Active, - role: role, - roleId: roleId, - organization: org_id ? { id: org_id } : {}, - api_user_id: api_user ? api_user.api_user_id : null, - }); - const { password, ...userData } = user; - this.logger.debug( - `Successfully registered a new user with id ${JSON.stringify(userData.id)}`, - ); - - await this.emailConfirmationService.create(user); - return user; - } - - public async adminnewcreate( - data: CreateUserORGDTO, - status?: UserStatus, - inviteuser?: boolean, - ): Promise { - await this.checkForExistingUser(data.email.toLowerCase()); - let org_id; - if (!inviteuser) { - const orgdata = { - name: data.orgName !== undefined ? data.orgName : '', - organizationType: data.organizationType, - // secretKey: data.secretKey, - orgEmail: data.email, - address: data.orgAddress, - }; - - if (await this.organizationService.isNameAlreadyTaken(orgdata.name)) { - throw new ConflictException({ - success: false, - message: `Organization "${data.orgName}" is already existed,please use another Organization name`, - }); - } else { - const org = await this.organizationService.newcreate(orgdata); - org_id = org.id; - this.logger.debug( - `Successfully registered a new organization with id ${JSON.stringify(org.id)}`, - ); - } - } - - let role; - let roleId; - if ( - data.organizationType === 'Buyer' || - data.organizationType === 'buyer' - ) { - role = Role.Buyer; - roleId = 4; - } else { - role = Role.OrganizationAdmin; - roleId = 2; - } - const user = await this.repository.save({ - firstName: data.firstName, - lastName: data.lastName, - email: data.email.toLowerCase(), - password: this.hashPassword(data.password), - notifications: true, - status: status || UserStatus.Active, - role: role, - roleId: roleId, - organization: org_id ? { id: org_id } : {}, - }); - const { password, ...userData } = user; - this.logger.debug( - `Successfully registered a new user with id ${JSON.stringify(userData.id)}`, - ); - await this.emailConfirmationService.admincreate(user, data.password); - - return new User(user); - } - - public async checkForExistingUser(email: string): Promise { - const isExistingUser = await this.hasUser({ email }); - - if (isExistingUser) { - const message = `User with email ${email} already exists`; - - this.logger.error(message); - throw new ConflictException({ - success: false, - message, - }); - } - } - - public async getAll(options?: FindManyOptions): Promise { - return this.repository.find(options); - } - - async findById(id: number): Promise { - const user = await this.findOne({ id }); - if (!user) { - throw new NotFoundException(`No user found with id ${id}`); - } - - if (user.role === Role.ApiUser) { - const api_user = await this.get_apiuser_permission_status( - user.api_user_id, - ); - user['permission_status'] = api_user.permission_status; - } - return user; - } - - public async findByIds(ids: number[]): Promise { - return await this.repository.findByIds(ids); - } - - async findByEmail(email: string): Promise { - const lowerCaseEmail = email.toLowerCase(); - - return this.findOne({ email: lowerCaseEmail }); - } - - async getUserAndPasswordByEmail( - email: string, - ): Promise<(Pick & { password: string }) | null> { - const user = await this.repository.findOne({ - where: { - email, - }, - select: ['id', 'email', 'password'], - }); - - return user ?? null; - } - - async findOne(conditions: FindOptionsWhere): Promise { - const user = await (this.repository.findOne({ - where: conditions as FindOptionsWhere, - relations: ['organization'], - }) as Promise as Promise); - - if (user) { - const emailConfirmation = await this.emailConfirmationService.get( - user.id, - ); - - user.emailConfirmed = emailConfirmation?.confirmed || false; - } - - return user ?? null; - } - - private hashPassword(password: string) { - return bcrypt.hashSync(password, 8); - } - - private async hasUser(conditions: FindOptionsWhere) { - return Boolean(await this.findOne(conditions)); - } - - async setNotifications( - id: number, - notifications: boolean, - ): Promise { - await this.repository.update(id, { notifications }); - - return this.findById(id); - } - - async addToOrganization( - userId: number, - organizationId: number, - ): Promise { - await this.repository.update(userId, { - organization: { id: organizationId }, - status: UserStatus.Active, - }); - } - - public getatleastoneotheruserinOrg( - organizationId: number, - userId: number, - ): Promise { - return this.repository.find({ - where: { - id: Not(userId), - organization: { - id: organizationId, - }, - }, - order: { - id: 'DESC', - }, - take: 1, - }); - } - - async removeFromOrganization(userId: number): Promise { - await this.repository.update(userId, { organization: undefined }); - } - - async remove(userId: number): Promise { - await this.emailConfirmationService.remove(userId); - await this.repository.delete(userId); - } - - async updateProfile( - id: number, - { firstName, lastName, email }: UpdateUserProfileDTO, - ): Promise { - const updateEntity = new User({ - firstName, - lastName, - email: email.toLowerCase(), - }); - - const validationErrors = await validate(updateEntity, { - skipUndefinedProperties: true, - }); - - if (validationErrors.length > 0) { - throw new UnprocessableEntityException({ - success: false, - errors: validationErrors, - }); - } - const updateuser = await this.findById(id); - if (!(updateuser.email === email.toLowerCase())) { - await this.checkForExistingUser(email.toLowerCase()); - } - await this.repository.update(id, updateEntity); - - return this.findOne({ id }); - } - - async updatePassword( - email: string, - user: UserPasswordUpdate, - ): Promise { - const _user = await this.getUserAndPasswordByEmail(email); - - if (_user && bcrypt.compareSync(user.oldPassword, _user.password)) { - const updateEntity = new User({ - password: this.hashPassword(user.newPassword), - }); - - const validationErrors = await validate(updateEntity, { - skipUndefinedProperties: true, - }); - - if (validationErrors.length > 0) { - throw new UnprocessableEntityException({ - success: false, - errors: validationErrors, - }); - } - - await this.repository.update(_user.id, updateEntity); - return this.findOne({ id: _user.id }); - } - - throw new ConflictException({ - success: false, - errors: `Incorrect current password.`, - }); - } - - async updatechangePassword( - emailConfirmation: UserDTO, - user: UserChangePasswordUpdate, - ): Promise { - if (emailConfirmation) { - const updateEntity = new User({ - password: this.hashPassword(user.newPassword), - }); - - const validationErrors = await validate(updateEntity, { - skipUndefinedProperties: true, - }); - - if (validationErrors.length > 0) { - throw new UnprocessableEntityException({ - success: false, - errors: validationErrors, - }); - } - - await this.repository.update(emailConfirmation.id, updateEntity); - return emailConfirmation; - } - - throw new ConflictException({ - success: false, - errors: `User Not exist .`, - }); - } - - public async changeRole( - userId: number, - role: Role, - ): Promise { - this.logger.log(`Changing user role for userId=${userId} to ${role}`); - const getrole = await this.rolerepository.findOne({ - where: { - name: role, - }, - }); - await this.repository.update(userId, { role, roleId: getrole.id }); - return this.findOne({ id: userId }); - } - - async getPlatformAdmin(): Promise { - return this.findOne({ role: Role.Admin }); - } - - public async getUsersByFilter( - filterDto: UserFilterDTO, - pageNumber: number, - limit: number, - ): Promise<{ - users: IUser[]; - currentPage: number; - totalPages: number; - totalCount: number; - }> { - const query = await this.getFilteredQuery(filterDto); - try { - const [users, totalCount] = await query - .andWhere(`role != :role`, { role: Role.ApiUser }) - .skip((pageNumber - 1) * limit) - .take(limit) - .getManyAndCount(); - const totalPages = Math.ceil(totalCount / limit); - - return { - users: users, - currentPage: pageNumber, - totalPages, - totalCount, - }; - } catch (error) { - this.logger.error(`Failed to retrieve users`, error.stack); - throw new InternalServerErrorException('Failed to retrieve users'); - } - } - - private getFilteredQuery(filterDto: UserFilterDTO): SelectQueryBuilder { - const { organizationName, status } = filterDto; - const query = this.repository - .createQueryBuilder('user') - .leftJoinAndSelect('user.organization', 'organization') - .orderBy('user.createdAt', 'DESC'); - if (organizationName) { - const baseQuery = 'organization.name ILIKE :organizationName'; - query.andWhere(baseQuery, { organizationName: `%${organizationName}%` }); - } - if (status) { - query.andWhere(`user.status = '${status}'`); - } - return query; - } - - async update( - id: number, - data: UpdateUserDTO, - ): Promise { - const validationErrors = await validate(data, { - skipUndefinedProperties: true, - }); - if (validationErrors.length > 0) { - throw new UnprocessableEntityException({ - success: false, - errors: validationErrors, - }); - } - - const updateuser = await this.findById(id); - if (!(updateuser.email === data.email)) { - await this.checkForExistingUser(data.email); - } - - await this.repository.update(id, { - firstName: data.firstName, - lastName: data.lastName, - email: data.email, - status: data.status, - }); - - return this.findOne({ id }); - } - - public async canViewUserData( - userId: IUser['id'], - loggedInUser: ILoggedInUser, - ): Promise { - const user = await this.findById(userId); - - const isOwnUser = loggedInUser.id === userId; - const isOrgAdmin = - loggedInUser.organizationId === user.organization?.id && - loggedInUser.hasRole(Role.OrganizationAdmin); - const isAdmin = loggedInUser.hasRole(Role.Admin); - - const canViewUserData = isOwnUser || isOrgAdmin || isAdmin; - - if (!canViewUserData) { - throw new UnauthorizedException({ - success: false, - message: `Unable to fetch user data. Unauthorized.`, - }); - } - if (user.role === Role.ApiUser) { - const api_user = await this.get_apiuser_permission_status( - user.api_user_id, - ); - user['permission_status'] = api_user.permission_status; - } - return user; - } - public async geytokenforResetPassword(email): Promise { - return await this.emailConfirmationService.ConfirmationEmailForResetPassword( - email, - ); - } - - public async sentinvitiontoUser(inviteuser, email, invitationId) { - const getcurrenttoken = - await this.emailConfirmationService.getByEmail(email); - if (!getcurrenttoken) { - return { - message: 'Token not found', - success: false, - }; - } - const { id, confirmed } = getcurrenttoken; - const { token, expiryTimestamp } = - await this.emailConfirmationService.generatetoken(getcurrenttoken, id); - await this.emailConfirmationService.sendInvitation( - inviteuser, - email, - invitationId, - ); - } - - public async findUserByOrganization( - organizationId: number, - pageNumber: number, - limit: number, - ) { - return await this.repository - .createQueryBuilder('user') - .leftJoinAndSelect('user.organization', 'organization') - .where('organization.id = :organizationId', { organizationId }) - .orderBy('user.createdAt', 'DESC') - .skip((pageNumber - 1) * limit) - .take(limit) - .getManyAndCount(); - } - /**get all user of apiuser */ - public async findUserByApiUserId( - api_user_id: string, - pageNumber: number, - limit: number, - org_id?, - ) { - return await this.repository - .createQueryBuilder('user') - .leftJoinAndSelect('user.organization', 'organization') - .where('user.api_user_id = :api_user_id', { api_user_id }) - .andWhere(`role != :role`, { role: Role.ApiUser }) - .orderBy('user.createdAt', 'DESC') - .skip((pageNumber - 1) * limit) - .take(limit) - .getManyAndCount(); - } - /** ApiUser Fuction*/ - - async getApiuser(api_id: string): Promise { - return await this.apiUserEntityRepository.findOne({ - where: { - api_user_id: api_id, - }, - }); - } - /** - * This Function added for request of permission to apiuser in apiuser table - * @param api_id - * @param permissionIds - */ - async apiuser_permission_request(api_id, permissionIds) { - await this.apiUserEntityRepository.update(api_id, { - permissionIds: permissionIds, - permission_status: UserPermissionStatus.Request, - }); - } - async apiuser_permission_accepted_byadmin( - api_id: string, - status: UserPermissionStatus, - ) { - await this.apiUserEntityRepository.update(api_id, { - permission_status: status, - }); - return await this.apiUserEntityRepository.findOne({ - where: { - api_user_id: api_id, - }, - }); - } - /** - * This service method use for get info of permission request status(Request,Active and Deactive) - * @param api_id - * @returns - */ - async get_apiuser_permission_status(api_id: string) { - const status_apiuser_permissiom = - await this.apiUserEntityRepository.findOne({ - where: { - api_user_id: api_id, - }, - }); - - return status_apiuser_permissiom; - } - - /** - * this function create for get user list of ApiUser - * @param organizationName - * @param pageNumber - * @param limit - * @returns - */ - public async getApiUsers( - organizationName: string, - pageNumber: number, - limit: number, - ): Promise<{ - users: IUser[]; - currentPage: number; - totalPages: number; - totalCount: number; - }> { - const filterDto = new UserFilterDTO(); - filterDto.organizationName = organizationName; - const query = await this.getFilteredQuery(filterDto); - try { - const [apiusers, totalCount] = await query - .andWhere(`user.role = :role`, { role: Role.ApiUser }) - .skip((pageNumber - 1) * limit) - .take(limit) - .getManyAndCount(); - - const totalPages = Math.ceil(totalCount / limit); - return { - users: apiusers, - currentPage: pageNumber, - totalPages, - totalCount, - }; - } catch (error) { - this.logger.error(`Failed to retrieve apiusers`, error.stack); - throw new InternalServerErrorException('Failed to retrieve apiusers'); - } - } - - /** - * - * @param email - * @param token - * @returns - */ - - async createUserSession(user: any, token: string) { - await this.userloginSessionRepository.save({ - userId: user.id, - accesstoken_hash: token, - }); - return; - } - /** - * - * @param userId - * @returns - */ - async removeUsersession(userId: number) { - return await this.userloginSessionRepository.delete({ userId: userId }); - } - - async hasgetUserTokenvalid( - conditions: FindOptionsWhere, - ) { - return Boolean( - await this.userloginSessionRepository.findOne({ - where: conditions as FindOptionsWhere, - }), - ); - } -} +import { + ConflictException, + Injectable, + Inject, + Logger, + UnprocessableEntityException, + UnauthorizedException, + NotFoundException, + InternalServerErrorException, + forwardRef, +} from '@nestjs/common'; +import { InjectRepository } from '@nestjs/typeorm'; +import bcrypt from 'bcryptjs'; +import { + FindOptionsWhere, + Repository, + FindManyOptions, + SelectQueryBuilder, + Not, +} from 'typeorm'; +import { + ILoggedInUser, + IUser, + UserPasswordUpdate, + UserChangePasswordUpdate, +} from '../../models'; +import { Role, UserStatus, UserPermissionStatus } from '../../utils/enums'; +import { CreateUserORGDTO } from './dto/create-user.dto'; +import { ExtendedBaseEntity } from '@energyweb/origin-backend-utils'; +import { validate } from 'class-validator'; +import { UserRole } from './user_role.entity'; +import { UserDTO } from './dto/user.dto'; +import { User } from './user.entity'; +import { UpdateUserProfileDTO } from './dto/update-user-profile.dto'; +import { EmailConfirmationService } from '../email-confirmation/email-confirmation.service'; +import { UpdateUserDTO } from '../admin/dto/update-user.dto'; +import { UserFilterDTO } from '../admin/dto/user-filter.dto'; +import { OrganizationService } from '../organization/organization.service'; +import { IEmailConfirmationToken, ISuccessResponse } from '../../models'; +import { OauthClientCredentialsService } from './oauth_client.service'; +export type TUserBaseEntity = ExtendedBaseEntity & IUser; +import { ApiUserEntity } from './api-user.entity'; +import { UserLoginSessionEntity } from './user_login_session.entity'; +@Injectable() +export class UserService { + private readonly logger = new Logger(UserService.name); + + constructor( + @InjectRepository(User) private readonly repository: Repository, + @InjectRepository(UserRole) private rolerepository: Repository, + private readonly emailConfirmationService: EmailConfirmationService, + private readonly oauthClientCredentialsService: OauthClientCredentialsService, + @Inject(forwardRef(() => OrganizationService)) + private organizationService: OrganizationService, + @InjectRepository(ApiUserEntity) + private readonly apiUserEntityRepository: Repository, + @InjectRepository(UserLoginSessionEntity) + private readonly userloginSessionRepository: Repository, + ) {} + + public async seed( + data: CreateUserORGDTO, + + organizationId: number | null, + role?: Role, + status?: UserStatus, + ): Promise { + await this.checkForExistingUser(data.email); + + return this.repository.save({ + // title: data.title, + firstName: data.firstName, + lastName: data.lastName, + email: data.email.toLowerCase(), + // telephone: data.telephone, + password: this.hashPassword(data.password), + role: role || Role.Admin, + status: status || UserStatus.Active, + organization: organizationId ? { id: organizationId } : {}, + }); + } + + public async newcreate( + data: CreateUserORGDTO, + status?: UserStatus, + inviteuser?: boolean, + ): Promise { + await this.checkForExistingUser(data.email.toLowerCase()); + const api_user = + await this.oauthClientCredentialsService.findOneByApiUserId( + data.api_user_id, + ); + + let org_id; + if (!inviteuser) { + const orgdata = { + name: data.orgName !== undefined ? data.orgName : '', + organizationType: data.organizationType, + orgEmail: data.email, + address: data.orgAddress, + }; + + orgdata['api_user_id'] = api_user.api_user_id; + if (await this.organizationService.isNameAlreadyTaken(orgdata.name)) { + throw new ConflictException({ + success: false, + message: `Organization "${data.orgName}" is already existed,please use another Organization name`, + }); + } else { + const org = await this.organizationService.newcreate(orgdata); + org_id = org.id; + this.logger.debug( + `Successfully registered a new organization with id ${JSON.stringify(org.id)}`, + ); + } + } + if (data.orgid) { + org_id = data.orgid; + } + let role; + let roleId; + if ( + data.organizationType === 'Buyer' || + data.organizationType === 'buyer' + ) { + role = Role.Buyer; + roleId = 4; + } else if ( + data.organizationType === 'Developer' || + data.organizationType === 'Developer' + ) { + role = Role.OrganizationAdmin; + roleId = 2; + } else if ( + data.organizationType === 'ApiUser' || + data.organizationType === 'apiuser' + ) { + role = Role.ApiUser; + roleId = 6; + } + + const user = await this.repository.save({ + firstName: data.firstName, + lastName: data.lastName, + email: data.email.toLowerCase(), + password: this.hashPassword(data.password), + notifications: true, + status: status || UserStatus.Active, + role: role, + roleId: roleId, + organization: org_id ? { id: org_id } : {}, + api_user_id: api_user ? api_user.api_user_id : null, + }); + const { password, ...userData } = user; + this.logger.debug( + `Successfully registered a new user with id ${JSON.stringify(userData.id)}`, + ); + + await this.emailConfirmationService.create(user); + return user; + } + + public async adminnewcreate( + data: CreateUserORGDTO, + status?: UserStatus, + inviteuser?: boolean, + ): Promise { + await this.checkForExistingUser(data.email.toLowerCase()); + let org_id; + if (!inviteuser) { + const orgdata = { + name: data.orgName !== undefined ? data.orgName : '', + organizationType: data.organizationType, + // secretKey: data.secretKey, + orgEmail: data.email, + address: data.orgAddress, + }; + + if (await this.organizationService.isNameAlreadyTaken(orgdata.name)) { + throw new ConflictException({ + success: false, + message: `Organization "${data.orgName}" is already existed,please use another Organization name`, + }); + } else { + const org = await this.organizationService.newcreate(orgdata); + org_id = org.id; + this.logger.debug( + `Successfully registered a new organization with id ${JSON.stringify(org.id)}`, + ); + } + } + + let role; + let roleId; + if ( + data.organizationType === 'Buyer' || + data.organizationType === 'buyer' + ) { + role = Role.Buyer; + roleId = 4; + } else { + role = Role.OrganizationAdmin; + roleId = 2; + } + const user = await this.repository.save({ + firstName: data.firstName, + lastName: data.lastName, + email: data.email.toLowerCase(), + password: this.hashPassword(data.password), + notifications: true, + status: status || UserStatus.Active, + role: role, + roleId: roleId, + organization: org_id ? { id: org_id } : {}, + }); + const { password, ...userData } = user; + this.logger.debug( + `Successfully registered a new user with id ${JSON.stringify(userData.id)}`, + ); + await this.emailConfirmationService.admincreate(user, data.password); + + return new User(user); + } + + public async checkForExistingUser(email: string): Promise { + const isExistingUser = await this.hasUser({ email }); + + if (isExistingUser) { + const message = `User with email ${email} already exists`; + + this.logger.error(message); + throw new ConflictException({ + success: false, + message, + }); + } + } + + public async getAll(options?: FindManyOptions): Promise { + return this.repository.find(options); + } + + async findById(id: number): Promise { + const user = await this.findOne({ id }); + if (!user) { + throw new NotFoundException(`No user found with id ${id}`); + } + + if (user.role === Role.ApiUser) { + const api_user = await this.get_apiuser_permission_status( + user.api_user_id, + ); + user['permission_status'] = api_user.permission_status; + } + return user; + } + + public async findByIds(ids: number[]): Promise { + return await this.repository.findByIds(ids); + } + + async findByEmail(email: string): Promise { + const lowerCaseEmail = email.toLowerCase(); + + return this.findOne({ email: lowerCaseEmail }); + } + + async getUserAndPasswordByEmail( + email: string, + ): Promise<(Pick & { password: string }) | null> { + const user = await this.repository.findOne({ + where: { + email, + }, + select: ['id', 'email', 'password'], + }); + + return user ?? null; + } + + async findOne(conditions: FindOptionsWhere): Promise { + const user = await (this.repository.findOne({ + where: conditions as FindOptionsWhere, + relations: ['organization'], + }) as Promise as Promise); + + if (user) { + const emailConfirmation = await this.emailConfirmationService.get( + user.id, + ); + + user.emailConfirmed = emailConfirmation?.confirmed || false; + } + + return user ?? null; + } + + private hashPassword(password: string) { + return bcrypt.hashSync(password, 8); + } + + private async hasUser(conditions: FindOptionsWhere) { + return Boolean(await this.findOne(conditions)); + } + + async setNotifications( + id: number, + notifications: boolean, + ): Promise { + await this.repository.update(id, { notifications }); + + return this.findById(id); + } + + async addToOrganization( + userId: number, + organizationId: number, + ): Promise { + await this.repository.update(userId, { + organization: { id: organizationId }, + status: UserStatus.Active, + }); + } + + public getatleastoneotheruserinOrg( + organizationId: number, + userId: number, + ): Promise { + return this.repository.find({ + where: { + id: Not(userId), + organization: { + id: organizationId, + }, + }, + order: { + id: 'DESC', + }, + take: 1, + }); + } + + async removeFromOrganization(userId: number): Promise { + await this.repository.update(userId, { organization: undefined }); + } + + async remove(userId: number): Promise { + await this.emailConfirmationService.remove(userId); + await this.repository.delete(userId); + } + + async updateProfile( + id: number, + { firstName, lastName, email }: UpdateUserProfileDTO, + ): Promise { + const updateEntity = new User({ + firstName, + lastName, + email: email.toLowerCase(), + }); + + const validationErrors = await validate(updateEntity, { + skipUndefinedProperties: true, + }); + + if (validationErrors.length > 0) { + throw new UnprocessableEntityException({ + success: false, + errors: validationErrors, + }); + } + const updateuser = await this.findById(id); + if (!(updateuser.email === email.toLowerCase())) { + await this.checkForExistingUser(email.toLowerCase()); + } + await this.repository.update(id, updateEntity); + + return this.findOne({ id }); + } + + async updatePassword( + email: string, + user: UserPasswordUpdate, + ): Promise { + const _user = await this.getUserAndPasswordByEmail(email); + + if (_user && bcrypt.compareSync(user.oldPassword, _user.password)) { + const updateEntity = new User({ + password: this.hashPassword(user.newPassword), + }); + + const validationErrors = await validate(updateEntity, { + skipUndefinedProperties: true, + }); + + if (validationErrors.length > 0) { + throw new UnprocessableEntityException({ + success: false, + errors: validationErrors, + }); + } + + await this.repository.update(_user.id, updateEntity); + return this.findOne({ id: _user.id }); + } + + throw new ConflictException({ + success: false, + errors: `Incorrect current password.`, + }); + } + + async updatechangePassword( + emailConfirmation: UserDTO, + user: UserChangePasswordUpdate, + ): Promise { + if (emailConfirmation) { + const updateEntity = new User({ + password: this.hashPassword(user.newPassword), + }); + + const validationErrors = await validate(updateEntity, { + skipUndefinedProperties: true, + }); + + if (validationErrors.length > 0) { + throw new UnprocessableEntityException({ + success: false, + errors: validationErrors, + }); + } + + await this.repository.update(emailConfirmation.id, updateEntity); + return emailConfirmation; + } + + throw new ConflictException({ + success: false, + errors: `User Not exist .`, + }); + } + + public async changeRole( + userId: number, + role: Role, + ): Promise { + this.logger.log(`Changing user role for userId=${userId} to ${role}`); + const getrole = await this.rolerepository.findOne({ + where: { + name: role, + }, + }); + await this.repository.update(userId, { role, roleId: getrole.id }); + return this.findOne({ id: userId }); + } + + async getPlatformAdmin(): Promise { + return this.findOne({ role: Role.Admin }); + } + + public async getUsersByFilter( + filterDto: UserFilterDTO, + pageNumber: number, + limit: number, + ): Promise<{ + users: IUser[]; + currentPage: number; + totalPages: number; + totalCount: number; + }> { + const query = await this.getFilteredQuery(filterDto); + try { + const [users, totalCount] = await query + .andWhere(`role != :role`, { role: Role.ApiUser }) + .skip((pageNumber - 1) * limit) + .take(limit) + .getManyAndCount(); + const totalPages = Math.ceil(totalCount / limit); + + return { + users: users, + currentPage: pageNumber, + totalPages, + totalCount, + }; + } catch (error) { + this.logger.error(`Failed to retrieve users`, error.stack); + throw new InternalServerErrorException('Failed to retrieve users'); + } + } + + private getFilteredQuery(filterDto: UserFilterDTO): SelectQueryBuilder { + const { organizationName, status } = filterDto; + const query = this.repository + .createQueryBuilder('user') + .leftJoinAndSelect('user.organization', 'organization') + .orderBy('user.createdAt', 'DESC'); + if (organizationName) { + const baseQuery = 'organization.name ILIKE :organizationName'; + query.andWhere(baseQuery, { organizationName: `%${organizationName}%` }); + } + if (status) { + query.andWhere(`user.status = '${status}'`); + } + return query; + } + + async update( + id: number, + data: UpdateUserDTO, + ): Promise { + const validationErrors = await validate(data, { + skipUndefinedProperties: true, + }); + if (validationErrors.length > 0) { + throw new UnprocessableEntityException({ + success: false, + errors: validationErrors, + }); + } + + const updateuser = await this.findById(id); + if (!(updateuser.email === data.email)) { + await this.checkForExistingUser(data.email); + } + + await this.repository.update(id, { + firstName: data.firstName, + lastName: data.lastName, + email: data.email, + status: data.status, + }); + + return this.findOne({ id }); + } + + public async canViewUserData( + userId: IUser['id'], + loggedInUser: ILoggedInUser, + ): Promise { + const user = await this.findById(userId); + + const isOwnUser = loggedInUser.id === userId; + const isOrgAdmin = + loggedInUser.organizationId === user.organization?.id && + loggedInUser.hasRole(Role.OrganizationAdmin); + const isAdmin = loggedInUser.hasRole(Role.Admin); + + const canViewUserData = isOwnUser || isOrgAdmin || isAdmin; + + if (!canViewUserData) { + throw new UnauthorizedException({ + success: false, + message: `Unable to fetch user data. Unauthorized.`, + }); + } + if (user.role === Role.ApiUser) { + const api_user = await this.get_apiuser_permission_status( + user.api_user_id, + ); + user['permission_status'] = api_user.permission_status; + } + return user; + } + public async geytokenforResetPassword(email): Promise { + return await this.emailConfirmationService.ConfirmationEmailForResetPassword( + email, + ); + } + + public async sentinvitiontoUser(inviteuser, email, invitationId) { + const getcurrenttoken = + await this.emailConfirmationService.getByEmail(email); + if (!getcurrenttoken) { + return { + message: 'Token not found', + success: false, + }; + } + const { id, confirmed } = getcurrenttoken; + const { token, expiryTimestamp } = + await this.emailConfirmationService.generatetoken(getcurrenttoken, id); + await this.emailConfirmationService.sendInvitation( + inviteuser, + email, + invitationId, + ); + } + + public async findUserByOrganization( + organizationId: number, + pageNumber: number, + limit: number, + ) { + return await this.repository + .createQueryBuilder('user') + .leftJoinAndSelect('user.organization', 'organization') + .where('organization.id = :organizationId', { organizationId }) + .orderBy('user.createdAt', 'DESC') + .skip((pageNumber - 1) * limit) + .take(limit) + .getManyAndCount(); + } + /**get all user of apiuser */ + public async findUserByApiUserId( + api_user_id: string, + pageNumber: number, + limit: number, + org_id?, + ) { + return await this.repository + .createQueryBuilder('user') + .leftJoinAndSelect('user.organization', 'organization') + .where('user.api_user_id = :api_user_id', { api_user_id }) + .andWhere(`role != :role`, { role: Role.ApiUser }) + .orderBy('user.createdAt', 'DESC') + .skip((pageNumber - 1) * limit) + .take(limit) + .getManyAndCount(); + } + /** ApiUser Fuction*/ + + async getApiuser(api_id: string): Promise { + return await this.apiUserEntityRepository.findOne({ + where: { + api_user_id: api_id, + }, + }); + } + /** + * This Function added for request of permission to apiuser in apiuser table + * @param api_id + * @param permissionIds + */ + async apiuser_permission_request(api_id, permissionIds) { + await this.apiUserEntityRepository.update(api_id, { + permissionIds: permissionIds, + permission_status: UserPermissionStatus.Request, + }); + } + async apiuser_permission_accepted_byadmin( + api_id: string, + status: UserPermissionStatus, + ) { + await this.apiUserEntityRepository.update(api_id, { + permission_status: status, + }); + return await this.apiUserEntityRepository.findOne({ + where: { + api_user_id: api_id, + }, + }); + } + /** + * This service method use for get info of permission request status(Request,Active and Deactive) + * @param api_id + * @returns + */ + async get_apiuser_permission_status(api_id: string) { + const status_apiuser_permissiom = + await this.apiUserEntityRepository.findOne({ + where: { + api_user_id: api_id, + }, + }); + + return status_apiuser_permissiom; + } + + /** + * this function create for get user list of ApiUser + * @param organizationName + * @param pageNumber + * @param limit + * @returns + */ + public async getApiUsers( + organizationName: string, + pageNumber: number, + limit: number, + ): Promise<{ + users: IUser[]; + currentPage: number; + totalPages: number; + totalCount: number; + }> { + const filterDto = new UserFilterDTO(); + filterDto.organizationName = organizationName; + const query = await this.getFilteredQuery(filterDto); + try { + const [apiusers, totalCount] = await query + .andWhere(`user.role = :role`, { role: Role.ApiUser }) + .skip((pageNumber - 1) * limit) + .take(limit) + .getManyAndCount(); + + const totalPages = Math.ceil(totalCount / limit); + return { + users: apiusers, + currentPage: pageNumber, + totalPages, + totalCount, + }; + } catch (error) { + this.logger.error(`Failed to retrieve apiusers`, error.stack); + throw new InternalServerErrorException('Failed to retrieve apiusers'); + } + } + + /** + * + * @param email + * @param token + * @returns + */ + + async createUserSession(user: any, token: string) { + await this.userloginSessionRepository.save({ + userId: user.id, + accesstoken_hash: token, + }); + return; + } + /** + * + * @param userId + * @returns + */ + async removeUsersession(userId: number) { + return await this.userloginSessionRepository.delete({ userId: userId }); + } + + async hasgetUserTokenvalid( + conditions: FindOptionsWhere, + ) { + return Boolean( + await this.userloginSessionRepository.findOne({ + where: conditions as FindOptionsWhere, + }), + ); + } +} diff --git a/apps/drec-api/test/device.e2e-spec.ts b/apps/drec-api/test/device.e2e-spec.ts index 62b09f8bf..bf3910db2 100755 --- a/apps/drec-api/test/device.e2e-spec.ts +++ b/apps/drec-api/test/device.e2e-spec.ts @@ -136,7 +136,7 @@ describe('Device tests', () => { energyStorage: true, energyStorageCapacity: 900, qualityLabels: '', - version:'1.0', + version: '1.0', }; await loginUser(loggedUser); const { body: updatedDevice } = await postDevice( @@ -190,7 +190,7 @@ describe('Device tests', () => { energyStorage: true, energyStorageCapacity: 900, qualityLabels: '', - version:'1.0', + version: '1.0', }; await loginUser(loggedUser); await postDevice('', HttpStatus.FORBIDDEN, partialDevice); diff --git a/apps/drec-api/test/group-devices.e2e-spec.ts b/apps/drec-api/test/group-devices.e2e-spec.ts index 99b693536..6db9cf8c8 100755 --- a/apps/drec-api/test/group-devices.e2e-spec.ts +++ b/apps/drec-api/test/group-devices.e2e-spec.ts @@ -18,7 +18,10 @@ import { UpdateDeviceGroupDTO, } from '../src/pods/device-group/dto'; import { Device } from '../src/pods/device'; -import { BuyerReservationCertificateGenerationFrequency, IFullOrganization } from '../src/models'; +import { + BuyerReservationCertificateGenerationFrequency, + IFullOrganization, +} from '../src/models'; import { CapacityRange, CommissioningDateRange } from '../src/utils/enums'; import TestDevicesToGroup from './test-devices-for-grouping.json'; import { NewDeviceDTO } from '../src/pods/device/dto'; @@ -101,7 +104,7 @@ describe('Device Group tests', () => { email: 'admin2@mailinator.com', password: '******123', }; - const filterDto : OrganizationFilterDTO = { + const filterDto: OrganizationFilterDTO = { organizationName: undefined, }; const pageNumber = 1; @@ -111,7 +114,9 @@ describe('Device Group tests', () => { const orgs = await organizationService.getAll(filterDto, pageNumber, limit); const firstBatch = devices.filter((device: Device) => - orgs.organizations.map((o: IFullOrganization) => device.organizationId === o.id), + orgs.organizations.map( + (o: IFullOrganization) => device.organizationId === o.id, + ), ); const secondBatch = firstBatch.filter( (device: Device) => @@ -127,7 +132,8 @@ describe('Device Group tests', () => { authorityToExceed: true, frequency: BuyerReservationCertificateGenerationFrequency.daily, continueWithReservationIfOneOrMoreDevicesUnavailableForReservation: false, - continueWithReservationIfTargetCapacityIsLessThanDeviceTotalCapacityBetweenDuration: false, + continueWithReservationIfTargetCapacityIsLessThanDeviceTotalCapacityBetweenDuration: + false, }; await postDeviceGroup('', HttpStatus.NOT_ACCEPTABLE, newDeviceGroup); }); @@ -178,7 +184,7 @@ describe('Device Group tests', () => { }; await loginUser(loggedUser); const { body: devices } = await requestDevice('', HttpStatus.OK); - const filterDto : OrganizationFilterDTO = { + const filterDto: OrganizationFilterDTO = { organizationName: undefined, }; const pageNumber = 1; @@ -186,7 +192,9 @@ describe('Device Group tests', () => { const orgs = await organizationService.getAll(filterDto, pageNumber, limit); const firstBatch = devices.filter((device: Device) => - orgs.organizations.map((o: IFullOrganization) => device.organizationId === o.id), + orgs.organizations.map( + (o: IFullOrganization) => device.organizationId === o.id, + ), ); const newDeviceGroup: AddGroupDTO = { name: 'test-device-group-2', @@ -198,7 +206,8 @@ describe('Device Group tests', () => { authorityToExceed: true, frequency: BuyerReservationCertificateGenerationFrequency.daily, continueWithReservationIfOneOrMoreDevicesUnavailableForReservation: false, - continueWithReservationIfTargetCapacityIsLessThanDeviceTotalCapacityBetweenDuration: false, + continueWithReservationIfTargetCapacityIsLessThanDeviceTotalCapacityBetweenDuration: + false, }; await postDeviceGroup('', HttpStatus.CREATED, newDeviceGroup); const { body: deviceGroups } = await requestDeviceGroup('', HttpStatus.OK); @@ -225,7 +234,7 @@ describe('Device Group tests', () => { }; await loginUser(loggedUser); const { body: devices } = await requestDevice('', HttpStatus.OK); - const filterDto : OrganizationFilterDTO = { + const filterDto: OrganizationFilterDTO = { organizationName: undefined, }; const pageNumber = 1; @@ -233,7 +242,9 @@ describe('Device Group tests', () => { const orgs = await organizationService.getAll(filterDto, pageNumber, limit); const firstBatch = devices.filter((device: Device) => - orgs.organizations.map((o: IFullOrganization) => device.organizationId === o.id), + orgs.organizations.map( + (o: IFullOrganization) => device.organizationId === o.id, + ), ); const newDeviceGroup: AddGroupDTO = { name: 'test-device-group-3', @@ -245,7 +256,8 @@ describe('Device Group tests', () => { authorityToExceed: true, frequency: BuyerReservationCertificateGenerationFrequency.daily, continueWithReservationIfOneOrMoreDevicesUnavailableForReservation: false, - continueWithReservationIfTargetCapacityIsLessThanDeviceTotalCapacityBetweenDuration: false, + continueWithReservationIfTargetCapacityIsLessThanDeviceTotalCapacityBetweenDuration: + false, }; await postDeviceGroup('', HttpStatus.CREATED, newDeviceGroup); const { body: deviceGroups } = await requestDeviceGroup('', HttpStatus.OK); @@ -272,7 +284,7 @@ describe('Device Group tests', () => { }; await loginUser(loggedUser); const { body: devices } = await requestDevice('', HttpStatus.OK); - const filterDto : OrganizationFilterDTO = { + const filterDto: OrganizationFilterDTO = { organizationName: undefined, }; const pageNumber = 1; @@ -280,7 +292,9 @@ describe('Device Group tests', () => { const orgs = await organizationService.getAll(filterDto, pageNumber, limit); const firstBatch = devices.filter((device: Device) => - orgs.organizations.map((o: IFullOrganization) => device.organizationId === o.id), + orgs.organizations.map( + (o: IFullOrganization) => device.organizationId === o.id, + ), ); const newDeviceGroup: AddGroupDTO = { name: 'test-device-group-3', @@ -292,7 +306,8 @@ describe('Device Group tests', () => { authorityToExceed: true, frequency: BuyerReservationCertificateGenerationFrequency.daily, continueWithReservationIfOneOrMoreDevicesUnavailableForReservation: false, - continueWithReservationIfTargetCapacityIsLessThanDeviceTotalCapacityBetweenDuration: false, + continueWithReservationIfTargetCapacityIsLessThanDeviceTotalCapacityBetweenDuration: + false, }; await postDeviceGroup('', HttpStatus.CREATED, newDeviceGroup); @@ -326,14 +341,16 @@ describe('Device Group tests', () => { }; await loginUser(loggedUser); const { body: devices } = await requestDevice('', HttpStatus.OK); - const filterDto : OrganizationFilterDTO = { + const filterDto: OrganizationFilterDTO = { organizationName: undefined, }; const pageNumber = 1; const limit = 5; const orgs = await organizationService.getAll(filterDto, pageNumber, limit); const firstBatch = devices.filter((device: Device) => - orgs.organizations.map((o: IFullOrganization) => device.organizationId === o.id), + orgs.organizations.map( + (o: IFullOrganization) => device.organizationId === o.id, + ), ); const newDeviceGroup: AddGroupDTO = { name: 'test-device-group', @@ -345,7 +362,8 @@ describe('Device Group tests', () => { authorityToExceed: true, frequency: BuyerReservationCertificateGenerationFrequency.daily, continueWithReservationIfOneOrMoreDevicesUnavailableForReservation: false, - continueWithReservationIfTargetCapacityIsLessThanDeviceTotalCapacityBetweenDuration: false, + continueWithReservationIfTargetCapacityIsLessThanDeviceTotalCapacityBetweenDuration: + false, }; return await postDeviceGroup('', HttpStatus.CREATED, newDeviceGroup); }; diff --git a/apps/drec-api/test/seed.ts b/apps/drec-api/test/seed.ts index 5ca7bece7..deccf3f3e 100755 --- a/apps/drec-api/test/seed.ts +++ b/apps/drec-api/test/seed.ts @@ -76,7 +76,7 @@ export const testUsers: Omit[] = [ lastName: 'Buyer', email: 'buyer2@mailinator.com', password: '******123', - organizationType: 'Buyer' + organizationType: 'Buyer', }, { firstName: 'Joe', @@ -209,7 +209,7 @@ export const batchDevices: NewDeviceDTO[] = [ energyStorage: true, energyStorageCapacity: 900, qualityLabels: '', - version:'1.0', + version: '1.0', }, { externalId: 'DREC32', @@ -230,7 +230,7 @@ export const batchDevices: NewDeviceDTO[] = [ energyStorage: true, energyStorageCapacity: 900, qualityLabels: '', - version:'1.0', + version: '1.0', }, { externalId: 'DREC33', @@ -251,7 +251,7 @@ export const batchDevices: NewDeviceDTO[] = [ energyStorage: true, energyStorageCapacity: 900, qualityLabels: '', - version:'1.0', + version: '1.0', }, { externalId: 'DREC34', @@ -302,18 +302,8 @@ export const seed = async ({ Role.DeviceOwner, UserStatus.Active, ); - await userService.seed( - user2, - createdOrg2.id, - Role.Buyer, - UserStatus.Active, - ); - await userService.seed( - user3, - createdOrg3.id, - Role.Admin, - UserStatus.Active, - ); + await userService.seed(user2, createdOrg2.id, Role.Buyer, UserStatus.Active); + await userService.seed(user3, createdOrg3.id, Role.Admin, UserStatus.Active); await userService.seed( user4, createdOrg4.id, @@ -322,7 +312,7 @@ export const seed = async ({ ); const [device1, device2, device3, device4] = testDevices; - const [ batchdevice1, batchdevice2, batchdevice3, batchdevice4 ] = batchDevices; + const [batchdevice1, batchdevice2, batchdevice3, batchdevice4] = batchDevices; await deviceService.seed(createdOrg1.id, batchdevice1); await deviceService.seed(createdOrg1.id, batchdevice2); From a1e30353874ec6fe1020be0eaf19b665aba1284a Mon Sep 17 00:00:00 2001 From: Aish1990 Date: Fri, 3 May 2024 14:44:20 +0530 Subject: [PATCH 23/89] fix: pnpm version upgrade at check.yml, deploy-gh-pages.yaml, Dockerfile --- .github/workflows/check.yml | 6 +++--- .github/workflows/deploy-gh-pages.yaml | 2 +- apps/drec-api/Dockerfile | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index bde5e5bd2..689784400 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -23,7 +23,7 @@ jobs: - name: Install tooling run: | npm i -g @microsoft/rush - npm i -g pnpm@6 + npm i -g pnpm@7 - name: Install drec-origin run: | @@ -47,7 +47,7 @@ jobs: - name: Install tooling run: | npm i -g @microsoft/rush - npm i -g pnpm@6 + npm i -g pnpm@7 - name: Install drec-origin run: | @@ -72,7 +72,7 @@ jobs: - name: Install tooling run: | npm i -g @microsoft/rush - npm i -g pnpm@6 + npm i -g pnpm@7 - name: Install drec-origin run: | diff --git a/.github/workflows/deploy-gh-pages.yaml b/.github/workflows/deploy-gh-pages.yaml index b49731f9b..efb5c1824 100644 --- a/.github/workflows/deploy-gh-pages.yaml +++ b/.github/workflows/deploy-gh-pages.yaml @@ -38,7 +38,7 @@ jobs: - name: Install tooling run: | npm i -g @microsoft/rush - npm i -g pnpm@6 + npm i -g pnpm@7 - name: Install drec-api working-directory: apps/drec-api diff --git a/apps/drec-api/Dockerfile b/apps/drec-api/Dockerfile index d87256fb6..23ea4fa59 100755 --- a/apps/drec-api/Dockerfile +++ b/apps/drec-api/Dockerfile @@ -7,7 +7,7 @@ RUN npm cache clean --force COPY . . RUN npm i -g @microsoft/rush -RUN npm i -g pnpm@6 +RUN npm i -g pnpm@7 WORKDIR /dist/src/app/apps/drec-api From 8680e0781975cefbfed0f0f0f5de5435ee4fdbd3 Mon Sep 17 00:00:00 2001 From: Aish1990 Date: Mon, 6 May 2024 08:46:30 +0530 Subject: [PATCH 24/89] fix: withoutahuthguard, readsController createReads, Register api's fix --- apps/drec-api/src/guards/WithoutAuthGuard.ts | 6 +++--- apps/drec-api/src/pods/reads/reads.controller.ts | 14 +++++++------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/apps/drec-api/src/guards/WithoutAuthGuard.ts b/apps/drec-api/src/guards/WithoutAuthGuard.ts index 91058b27c..0a45b950a 100644 --- a/apps/drec-api/src/guards/WithoutAuthGuard.ts +++ b/apps/drec-api/src/guards/WithoutAuthGuard.ts @@ -44,14 +44,14 @@ export class WithoutAuthGuard implements CanActivate { } else if (request.url.split('/')[3] === 'register') { const userData = await this.userService.findOne({ role: Role.Admin }); if ( - !request.body.api_user_id && + request.body.api_user_id == undefined && (request.body.organizationType === 'Developer' || request.body.organizationType === Role.Buyer) ) { user = userData; } else if ( - request.body.api_user_id && - request.body.api_user_id != user.api_user_id && + request.body.api_user_id != undefined && + request.body.api_user_id != userData.api_user_id && (request.body.organizationType === 'Developer' || request.body.organizationType === Role.Buyer) ) { diff --git a/apps/drec-api/src/pods/reads/reads.controller.ts b/apps/drec-api/src/pods/reads/reads.controller.ts index 7899b5b4d..c51e7d999 100644 --- a/apps/drec-api/src/pods/reads/reads.controller.ts +++ b/apps/drec-api/src/pods/reads/reads.controller.ts @@ -459,7 +459,7 @@ export class ReadsController extends BaseReadsController { for (const key in ele) { if (key === 'starttimestamp' || key === 'endtimestamp') { if (ele[key]) { - let dateString = ele[key].toISOString(); + let dateString = ele[key].toString(); const dateTimeRegex = /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.{0,1}\d{0,3}$/; if (dateString.includes('.')) { @@ -586,11 +586,11 @@ export class ReadsController extends BaseReadsController { datesContainingNullOrEmptyValues = true; } const startdateformate = isValidUTCDateFormat( - ele.starttimestamp.toISOString(), + new Date(ele.starttimestamp).toISOString(), ); //dateFormateToCheck.test(ele.starttimestamp); const enddateformate = isValidUTCDateFormat( - ele.endtimestamp.toISOString(), + new Date(ele.endtimestamp).toISOString(), ); if (!startdateformate || !enddateformate) { @@ -754,7 +754,7 @@ export class ReadsController extends BaseReadsController { datesContainingNullOrEmptyValues = true; } const enddateformate = isValidUTCDateFormat( - ele.endtimestamp.toISOString(), + new Date(ele.endtimestamp).toISOString(), ); if (!enddateformate) { @@ -1025,7 +1025,7 @@ export class ReadsController extends BaseReadsController { for (const key in ele) { if (key === 'starttimestamp' || key === 'endtimestamp') { if (ele[key]) { - let dateString = ele[key].toISOString(); + let dateString = new Date(ele[key]).toISOString(); const dateTimeRegex = /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.{0,1}\d{0,3}$/; if (dateString.includes('.')) { @@ -1152,11 +1152,11 @@ export class ReadsController extends BaseReadsController { datesContainingNullOrEmptyValues = true; } const startdateformate = isValidUTCDateFormat( - ele.starttimestamp.toISOString(), + ele.starttimestamp.toString(), ); const enddateformate = isValidUTCDateFormat( - ele.endtimestamp.toISOString(), + ele.endtimestamp.toString(), ); if (!startdateformate || !enddateformate) { From d9618a1bacd3df0de5fd62089d17ce56ce2ceba1 Mon Sep 17 00:00:00 2001 From: Aish1990 Date: Wed, 8 May 2024 12:33:52 +0530 Subject: [PATCH 25/89] Migration file for old issuer certificates --- .../migrations/1715146626520-OldIssuerLog.ts | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 apps/drec-api/migrations/1715146626520-OldIssuerLog.ts diff --git a/apps/drec-api/migrations/1715146626520-OldIssuerLog.ts b/apps/drec-api/migrations/1715146626520-OldIssuerLog.ts new file mode 100644 index 000000000..6c9173be3 --- /dev/null +++ b/apps/drec-api/migrations/1715146626520-OldIssuerLog.ts @@ -0,0 +1,28 @@ +import {MigrationInterface, QueryRunner} from "typeorm"; + +export class OldIssuerLog1715146626520 implements MigrationInterface { + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(` + CREATE TABLE old_issuer_log ( + "id" integer PRIMARY KEY, + "createdAt" timestamp with time zone NOT NULL DEFAULT now(), + "updatedAt" timestamp with time zone NOT NULL DEFAULT now(), + "deviceId" character varying NOT NULL, + "generationStartTime" integer NOT NULL, + "generationEndTime" integer NOT NULL, + "creationTime" integer NOT NULL, + "creationBlockHash" character varying, + "owners" text NOT NULL, + "claimers" text, + "claims" text, + "latestCommitment" text, + "issuedPrivately" boolean NOT NULL, + "blockchainNetId" integer, + "metadata" character varying NOT NULL)`); + } + + public async down(queryRunner: QueryRunner): Promise { + } + +} From b8d47177e74aadb1ccdb2fd7c5ca7d423904766b Mon Sep 17 00:00:00 2001 From: Aish1990 Date: Wed, 8 May 2024 12:46:26 +0530 Subject: [PATCH 26/89] Prettier fix --- .../migrations/1715146626520-OldIssuerLog.ts | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/apps/drec-api/migrations/1715146626520-OldIssuerLog.ts b/apps/drec-api/migrations/1715146626520-OldIssuerLog.ts index 6c9173be3..5bc50250c 100644 --- a/apps/drec-api/migrations/1715146626520-OldIssuerLog.ts +++ b/apps/drec-api/migrations/1715146626520-OldIssuerLog.ts @@ -1,9 +1,8 @@ -import {MigrationInterface, QueryRunner} from "typeorm"; +import { MigrationInterface, QueryRunner } from 'typeorm'; export class OldIssuerLog1715146626520 implements MigrationInterface { - - public async up(queryRunner: QueryRunner): Promise { - await queryRunner.query(` + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(` CREATE TABLE old_issuer_log ( "id" integer PRIMARY KEY, "createdAt" timestamp with time zone NOT NULL DEFAULT now(), @@ -20,9 +19,7 @@ export class OldIssuerLog1715146626520 implements MigrationInterface { "issuedPrivately" boolean NOT NULL, "blockchainNetId" integer, "metadata" character varying NOT NULL)`); - } - - public async down(queryRunner: QueryRunner): Promise { - } + } + public async down(queryRunner: QueryRunner): Promise {} } From 7c12ab740dd813de972d28b7311792238840d26b Mon Sep 17 00:00:00 2001 From: Daniel Mohns Date: Wed, 8 May 2024 15:52:41 +0200 Subject: [PATCH 27/89] Add VitePress documentation --- docs/.vitepress/config.mjs | 60 + docs/.vitepress/theme/custom.css | 70 + docs/.vitepress/theme/index.js | 17 + docs/dev_docs/ACL-module.md | 1 + docs/dev_docs/developer-onboarding.md | 0 docs/dev_docs/functional-requirements.md | 0 docs/img/D-REC-banner.png | Bin 0 -> 16047 bytes docs/img/D-REC-logo.png | Bin 0 -> 14066 bytes docs/index.md | 33 + docs/introduction/dre-project-developers.md | 0 docs/introduction/rec-buyers.md | 0 docs/introduction/technology-overview.md | 0 docs/package-lock.json | 2646 ++++++++++++++++++ docs/package.json | 17 + docs/public/favicon.png | Bin 0 -> 14066 bytes docs/usage_guide/api-user-manual.md | 0 docs/usage_guide/buyer-manual.md | 0 docs/usage_guide/project-developer-manual.md | 0 18 files changed, 2844 insertions(+) create mode 100644 docs/.vitepress/config.mjs create mode 100644 docs/.vitepress/theme/custom.css create mode 100644 docs/.vitepress/theme/index.js create mode 100644 docs/dev_docs/ACL-module.md create mode 100644 docs/dev_docs/developer-onboarding.md create mode 100644 docs/dev_docs/functional-requirements.md create mode 100644 docs/img/D-REC-banner.png create mode 100644 docs/img/D-REC-logo.png create mode 100644 docs/index.md create mode 100644 docs/introduction/dre-project-developers.md create mode 100644 docs/introduction/rec-buyers.md create mode 100644 docs/introduction/technology-overview.md create mode 100644 docs/package-lock.json create mode 100644 docs/package.json create mode 100644 docs/public/favicon.png create mode 100644 docs/usage_guide/api-user-manual.md create mode 100644 docs/usage_guide/buyer-manual.md create mode 100644 docs/usage_guide/project-developer-manual.md diff --git a/docs/.vitepress/config.mjs b/docs/.vitepress/config.mjs new file mode 100644 index 000000000..cfaf2d5da --- /dev/null +++ b/docs/.vitepress/config.mjs @@ -0,0 +1,60 @@ +import { defineConfig } from 'vitepress'; + +// https://vitepress.dev/reference/site-config +export default defineConfig({ + title: 'D-REC Docs', + description: 'Documentation for the D-REC (Distributed Renewable Energy Certificates) platform', + + /* prettier-ignore */ + head: [ + ['link', { rel: 'icon', type: 'image/png', href: 'favicon.png' }], + ], + + themeConfig: { + // https://vitepress.dev/reference/default-theme-config + logo: 'img/D-REC-banner.png', + nav: [ + { text: 'Home', link: '/' }, + { text: 'Documentation', link: '/introduction/technology-overview' } + ], + footer: { + message: 'Built with VitePress ❤️.', + copyright: `Copyright © ${new Date().getFullYear()} D-REC Initiative.` + }, + + sidebar: [ + { + text: 'Introduction', + items: [ + { text: 'Technology Overview', link: '/introduction/technology-overview' }, + { + text: 'DRE Project Developers', + link: '/introduction/dre-project-developers' + }, + { text: 'REC Buyers', link: '/introduction/rec-buyers' } + ] + }, + { + text: 'Usage Guide', + items: [ + { text: 'Buyer Manual', link: '/usage_guide/buyer-manual.md' }, + { + text: 'Project Developer Manual', + link: '/usage_guide/project-developer-manual.md' + }, + { text: 'API User Manual', link: '/usage_guide/api-user-manual' } + ] + }, + { + text: 'Developer Documentation', + items: [ + { text: 'Function Requirements', link: '/dev_docs/functional-requirements' }, + { text: 'Developer Onboarding', link: '/dev_docs/developer-onboarding' }, + { text: 'ACL Module', link: '/dev_docs/ACL-module' } + ] + } + ], + + socialLinks: [{ icon: 'github', link: 'https://github.com/d-rec/drec-origin' }] + } +}); diff --git a/docs/.vitepress/theme/custom.css b/docs/.vitepress/theme/custom.css new file mode 100644 index 000000000..2c96feb78 --- /dev/null +++ b/docs/.vitepress/theme/custom.css @@ -0,0 +1,70 @@ +/** + * Customize default theme styling by overriding CSS variables: + * https://github.com/vuejs/vitepress/blob/main/src/client/theme-default/styles/vars.css + */ + +/** + * Colors + * + * Each colors have exact same color scale system with 3 levels of solid + * colors with different brightness, and 1 soft color. + * + * - `XXX-1`: The most solid color used mainly for colored text. It must + * satisfy the contrast ratio against when used on top of `XXX-soft`. + * + * - `XXX-2`: The color used mainly for hover state of the button. + * + * - `XXX-3`: The color for solid background, such as bg color of the button. + * It must satisfy the contrast ratio with pure white (#ffffff) text on + * top of it. + * + * - `XXX-soft`: The color used for subtle background such as custom container + * or badges. It must satisfy the contrast ratio when putting `XXX-1` colors + * on top of it. + * + * The soft color must be semi transparent alpha channel. This is crucial + * because it allows adding multiple "soft" colors on top of each other + * to create a accent, such as when having inline code block inside + * custom containers. + * + * - `default`: The color used purely for subtle indication without any + * special meanings attched to it such as bg color for menu hover state. + * + * - `brand`: Used for primary brand colors, such as link text, button with + * brand theme, etc. + * + * - `tip`: Used to indicate useful information. The default theme uses the + * brand color for this by default. + * + * - `warning`: Used to indicate warning to the users. Used in custom + * container, badges, etc. + * + * - `danger`: Used to show error, or dangerous message to the users. Used + * in custom container, badges, etc. + * -------------------------------------------------------------------------- */ + +:root { + --vp-c-brand-1: #eac046; + --vp-c-brand-2: #c47f2e; + --vp-c-brand-3: #eac046; + /* --vp-c-brand-soft: var(--vp-c-indigo-soft); */ +} + +/** + * Component: Home + * -------------------------------------------------------------------------- */ +:root { + --vp-home-hero-name-color: transparent; + --vp-home-hero-name-background: -webkit-linear-gradient( + 120deg, + var(--vp-c-brand-2) 30%, + var(--vp-c-brand-1) + ); + + --vp-home-hero-image-background-image: linear-gradient( + -45deg, + var(--vp-c-gray-1), + var(--vp-c-brand-1) 100% + ); + --vp-home-hero-image-filter: blur(44px); +} diff --git a/docs/.vitepress/theme/index.js b/docs/.vitepress/theme/index.js new file mode 100644 index 000000000..457050c73 --- /dev/null +++ b/docs/.vitepress/theme/index.js @@ -0,0 +1,17 @@ +// https://vitepress.dev/guide/custom-theme +import { h } from 'vue'; +import DefaultTheme from 'vitepress/theme'; +import './custom.css'; + +/** @type {import('vitepress').Theme} */ +export default { + extends: DefaultTheme, + Layout: () => { + return h(DefaultTheme.Layout, null, { + // https://vitepress.dev/guide/extending-default-theme#layout-slots + }); + }, + enhanceApp({ app, router, siteData }) { + // ... + } +}; diff --git a/docs/dev_docs/ACL-module.md b/docs/dev_docs/ACL-module.md new file mode 100644 index 000000000..e0b71a501 --- /dev/null +++ b/docs/dev_docs/ACL-module.md @@ -0,0 +1 @@ +# ACL Module documentation diff --git a/docs/dev_docs/developer-onboarding.md b/docs/dev_docs/developer-onboarding.md new file mode 100644 index 000000000..e69de29bb diff --git a/docs/dev_docs/functional-requirements.md b/docs/dev_docs/functional-requirements.md new file mode 100644 index 000000000..e69de29bb diff --git a/docs/img/D-REC-banner.png b/docs/img/D-REC-banner.png new file mode 100644 index 0000000000000000000000000000000000000000..8b516310834317c65136e78f7b042e298259a3e3 GIT binary patch literal 16047 zcmbum1CS;`v@Y2FcTd~4ZQJf?+qQe!wvA~U)3$Bfwrz7~?!E8b8~b)6HexFys!rwk z4)SDHRz*~N;qtQLuuxb~KtMpSk`f|{KtR9(e`Q+;u)k+j!7=r}7hp$4aUr0pDV)>4 zH}WRxlBO~;KvaKa2p|A35)jBg$lnGOY5@fLA2JXS+21P=5J)cYe`|9A|4R!jkPGs^ zWFXsrz(IPczy1JB7Ru^Q>N3(?Ms_xI2F7-VCUkB#_WuAtJZ@ZnMH>?*0|GZ2Yg(75&Q?l$%>aqT}GZj*v`R(fQ^oUj)8~|ihzKC$HCZ?OHoAZzs&#M z@e-LkIoWg3)4RI5(z!Cz**TceGjeir(lap8GcnQrMbJ9B+d3Jz(b_r^|EH7xp#Qs{By=7Z{cQQts!DzV`A(0H#I&+4kn)e2=jkv{yWkCVX6M# zmaI&i|I_k+X#Ve(!gkhn4odb0MkaiW|7G$&y8Z|HU*24D4i+YVOZu;H|KR^e-+$qG z=>Jvqe^mKDr|>^||IQ&F6c7FXUJrawTKQk+KtSBnk|Ki2Zorq`keN7x&aNtY%=OQ_ z?bN^k(3Pp^Z1rqK^TnC9j_QUBmiV@%;kXC3L`!lp9FxB-&6D<8o@M)3I{nM|s+5Rn`9X;!@hY z|Ieo1OWcF*27iEg*?g-r@p9>Pxj90`o5z*pv!L>eF_$8_QmPN*yq;KPLifyQsUJjI z+nKc{|;Dk6 zuy#g-1vE-@5`tbJl%hOMv;azJ2{vKhB6_wF*RlHfGE0Rn*9(wSt3>O2NHLC({1l?r z7Si|O!s!UtOAg;pgXy2^GidL)dQRqX{xGdlAxbB$_;dhqGyrrmP%Fuz;}ErgvGg8N zpt2hK@lu7U&=%QsgqXDfMnKUBOr{xhuk3H*rj@2Nkwje$!$zk4#)JtuHrij|qokSf zE}>Lwc+8!Kp>B$+t;>8E+HH}TUbv29X-X-c|7JwLm$1ejGR~1P34;&v#o`m!Cjk2w zsPVFE_tWIqSgxTs!2{u|Tyij9a!j(F6t0kE+f;C?l)UsSG&k`ChZ^@pWM_PIG`Mp8TD6%z)UPO33O>{ zyC2dTNM;_O-&T{?zD^5!@DaG3?JHzx&ZK=BHLd*GplB!nQr3Vl=hT4gixJB-|0eK= z_I@RKIN>mI7XwGf`rCba=PWwOI}aQ!5k(y@MSbQb(C^8Wpoi0+)t{f~KcD`D+ZzI+ zx|4mVQ!U2zMdC~)?7tkt(!OV>JzeNefe@$S1dw&k@f;ED5h?gVe~S6-{V2lPO-{5K z%8-#3o+tfLcNR1?ES}#p2UI|0sazs+6IN2`^zXPb~_Fh zc<8LqfdH+pgcM95j309SBAaW;GtRXJ#si6Z@YCsE3|0VX8Xz%-ZsxFCHt7|2C*Bl; zWRA@6%u+P!wdGs3w(2?tGht`fD({{cd9d*3&CTu#J6DxE2ehcP%y{n9it}xbvg`_i zF^@%vvKw^8aEgfa_vLlv_51dqS}gvDGMa_iqG&Nxy)5@JS+xGZ=_W)uctl*=H%-uwv@a&4G=Tq$Co3saFpi9p3iusq3! zcXr|K)?bfZB_*HMHj55G2S_89M*^U*Eg8)?v4)B`N@?td;;K4O2v6^(JEg=KV+!`B zeq~pTeE3q8y~q^AE-w|gPw`$8?GVXxf&LWo`*BG}2|Zs(g$k;jE8-KJ`-D}&{Mw|c z@=M&_Q`+Th53jx=+#rJpXX=Q%?o(#G1@*G2mivTLf|OClP-bdGtshDP#9{*-;hWC%C#9hpoi=nRBX;I zjifik9TlAwng}korB7aEBocbT(>0*n!uNJI8LzD(QCBtEwuy=aq7KKF2DW!CO8xw~ zJv3x~PRr0sM}$iZ$^%(0@&&k}lCn?%k4Mrjr6wf!A|)b}{-P5wG89eFm1oCLQgO+n zENmyra%P8M^yqO;3@1GBX@mHU=Kn*+Z#l1fhxc)71K6=HzO# z9ru-PW%bQKgA9-f@NhWP?j5Cf(XvR8@eou&OUdZ75@%c399cPOuf4x2j`WKZI7Jv? z2Oc9J9R{B|e~dua^Fq9n+fCTM=8uH_f+eKJvP8scrlgY|D1WhApLDsl-vfpc`G}nK zFHRRq&|pMf6elSu-7D}2CTD0WI2u}W914wG1#6~52S)dAg*ZqAdKJY*&oX56t~GF! zW@~MAxm?qMP~>83Ui-lD$GdjWNM2r>+Hk3p#=O@t&{)5<68Etjm7^SJZ6k)PlUp^g zi(O&-lJS9qJ}!1@M)~Je8(|~^5!4@&%3151z2edvgPO+&`0$(FTIXASPVDdm13;A4 zg=A2}5wG`wf0j9w*zkpvNg#<(E>0r4=Zg%{qotDz912I#kq|mjL<62YY!R(>t&lE{5m|(PmQ@ zx?5Xg=|uW5+py?PESP`CDG;e7lTE(|taOMQHN=R}9Of}3>L)Dq7ACY)(^iqz2RlG%0g@^awL0ViZY&Aew+c~-nsQU z5<3ygO7jbps(he=`@@<|aHN1cVH`VPqrpPyCO?v{4Y>CSOFBqSjD0dBB;<3nP0QQo zx@q&d20fPFP|hgsI7ycj~5M zqO^Kl9YQMSv5;7ap3e5d*=~nP|b2^b7UT?wL-?{=WbH(;#j(&(qfSEbdBRLlmvn97b-;2?JH!sg1>RXH9J1 zgHUQ-+zKPcP4z~~-y6Hk`9R>0X@DbOC;BzlOxQRvvsP<0wojeb4>t|wb|-lhbTqtw z&Oyb7APXuu|_B_DN%6Ks#JcUxK|N-jkuDhk*dmZbN2+P_!W+bmY~|RgA2J%UXD~m z_PJQ@0gjYCeVg0k@p4;ldB#)Ltb1I6syd%Ya6@YpQpZ76PgYcW29>1ZPic;>wOfy% zDzc(Jr-|y_wsBKKU zU0hGqF~8;Lf(?F;USSma@_INq(qm-1QRO?cxTCe$SABug*MxRNqyt!stfo~U+Z*ZHt;T}E}_PZf@rIk!>3aM@*X(QT#)HIpG|?c$VbRT=xzGx@f2NtUxVlwjODLK zcHX03RbLTQV+smMTS>?Z2`faN3hHCDd_aKyL{b08Kq}$M!?FT>z4D14G`r#1VGyrk zV~bzDh@PCs$S^6tuIW`D3FL}_t>FZR>kMM3dSHm9>It|ZWf)}5E~$7e8#ROc>9)~7 zZ^b#yD+028Np&!IB^$L0u64Ux`Yd9)Kmce!#)t6Bt*QHT7LIpu0S!k@?#HOkUj5+U z4Lm2JaCpf416@OdE}upEsW^bfF9<%<4Xf#j4|bbBIK(ysp%Na}W+um`!|6qT&LJUl zBpoR9F~l^sugkA1zFKdM;l0iureMt!cxyXHdsDHQ242}MX*lwuuCuV;Y zTI_&~3vbkdK=0S|IkTmfhgJr-yI9GJwb4B7&@>rbxU3*iNwolLUwkHNAI`6!x<*JnNp{&hc6q4*-Cas-~&E^fxO9sF+qqXSD@EzB{5D>fV2^DPxfQ&-g zvyRjy{y;=B1?~F-Uasti3R(DY1%_y7EMsu?TWidh!YR4zrT`|-8)mW%8{V>&#fFW> z92Iu&1@z9=uf`WIQ&0`~z=}lX%{jO9Fus?g8p$;W%5E8Gwl>Zz8KlUy-d*|nNYg+fX-P8 zPwda+1*5v(b2^({Kz=3Kz+4$szJY@rlB$%kI+_TC(+ECJ;Nd*7T*Fsp?FUtEeW%{) zQE@2WPgf8{1h9i&2<_jpNiU+wXPx|Whp$Oy`ucjUl7XvFjOQOM#ZwP4j-vZZCSe** z*7b{DuJjwrn~i&s;zir!tKgvZU+^MP-GfH!BJ@u}=5r+mnPa1AOqwyVjmdoUnH(ffHH+k=6x~lL5HjFKI<%YI*Fj6PL39j)3(&X@wbO znrCi}#&r1lr+yG4BWn)}*Yc#q;JIm%aRHLHw_|j&a(0K-h6ao6=?h9}Dp>;5`BgW*PD{?sijJw?F9=1Db<$|{zOS!E4PJ~V<^ z?V-B>pp&(si%8@engw;iSai6ojh!*cUdX1G3Nk)jJeRvLY#Nh129;vugXy!g(cl!U zo6RH2q%_3{%jd`MhHLS(=v4IL{l%#Banb@BXiRP!-CzO8SUM+4{~}&Djaj@2wH?|` zFYSWwrDnDVUZtz0J?$$kvSkE9H9xTQLoL0c$+L%U?ijwL~|B^!I3@73Dxj~NY4$b@(gRr?eRF7o6&pb_%a%KzZ(ui zzlNv4Oll*mGJbN6*b@w)3!NoUR1LOW!|wyPmTTN^(=0tZPyW8zuci#$4xde3XX=ZY z8FzZhO}x`JRV%|g^!-KnIm!K}&6g8Z*83+L0TK!Yo)PN4P#fOREPZbqo!q$q@#5qx|4ie8gaotKxnVj!`;p00PW>vdejsxAntpeuW@#E*S#!kcYU-<~R18&L*KL8pNCW0kkC>wAa_<3VW zR#m%WI~`S-o=K9$aq)%tph3JUi7&1JGPHVrdeoA8CTYen5;XN**wZG`jLgMZ3~%Os z!u>`X{yV~tEq1IAxnxWTlO3ref{Q`$x`)1SkJBNqZNFxX0^iXI(+I_In9s)#xxFrS z>T~PCW=viTJa*aBkGQCNsq*?Nee>`mDN!i;^xC`m#hG(_(L3CH-&Fz;LB zBhb$Pgo0>w14IDB@!8-2?9b4h5_j%oX8KSHc!P=&NYp+5zI#$S!AX8vD>wp~raB_S#6Qfs?yIByI&|wLjyGS?x=Q{rUrApIKq|VFc5Odifb)UCv*Q&Zd`* zPqERL>jFL>dT{klKHg_qc#YbpOk3wn6t zE6j%%N)en&5tVuH>%sE6I6?{#xtYka}PH1gziqMK6 zy?>J!u=H~|CJ`~#j-lWy*4Okz`B=~-=qXQ=1-7t5lS$^YR8Pvvr?$5%x`O)APaxRq zR%Je&ns;^&k1K7@owZcr?8oyz=i%@rN+*lG`Ah{U=_GJhRUl896mP3;BzDE zBQubbHg7T)$Cmc1YiMvVbtn^<{g0}d zHc8j`{9%Hue9ufE`>Rab;>_qu4f6UgF5y-$e_zWYnY0D7C%#zcAw2~e3&sU5e3I>D zWymv79)!8k5$5Z6s}Z6;@R=D0iWP=lL;0Q3mvm{zNZ?xGcwD@(UGLh*1 zpWv1U88gjZi_JyH{?;RQrmK&*o$m!?-)*)d%W5tU8{8%nnQ5fu*BVlOgzCnPU{7&s zM(BZmSUd`ff4U`$ikN|S=r*zP;j4B%5~z>LW{}uw!r@5489qf$KH?$yN+nxT{eCAW zdTUKJ)h32f4~bkvQWmM=Ya^T@AazWuDtDeS?0U$Q)EI z-61mJBngPkaX8!a9dsD#EWM*Ebj*WvR1*!}uS{xN#n_K4lwui{+-#7Zf?HyJot=~# zF;Ah3uY%jV%C(hhUamU*yAnQ5r{tnJv0U$EF%bzayS0>*h&_4mem%k$TvS=XdwH*p z9(hQ(6e7r_5u9ly8+WTd8g$_9D?Xm(vG>U}>zS>p(hhV>`Y?jB_g1K|4heSU=Qsh8 zO3hFQF;=#s;&Q+ujZ@lBQfg|M6T60Kj<2{&)dbmp z-ZXUstO62Gc*vkhC}%*dnh_VP2jkb7DvB=Z4JL~eIusPSI9MdRke*-N=A}2aIu00= zPy{O^zg;GuwgRvo9R!JKfvdDz>n004_+n-+ekj!bv?F~Vo8HEMSedJ4yIfhwk@{0> z#Q+QB5d#{J&K8@LF+H7b19B~0@xTwtyG;2?!>*$tf>2XShi4Mcb@2Ctt?)}(Z{~jO zWhnXDfbg41om@`(xzAo=?kFWJ`s?~O^3AYq$Z6*Hqq~%ZnYr7^{NpBL*7|*4f za%R$$p8FT3P}&A5TyRIN^ZC*OSy38A@(uT9!*29jbxr(wG(#AR+1~N**ds1epP}-@ zlFg92r{jVN!`}*(Ssm2+-M2FFK?0~gWuQKO0;z$T^PPTd7nj#2se10 zRLIddlQ@X5l%I;hFakX+EP>(XU_VS!NiXc4*NfbtydD(w7&#|Hr7B-67F)gVk&+eF ze!s6afJ%6J*-tty6f#42984$+hO_Z=&0F$&T(u@4*L|9(B4GI#vBG`pehK(h=qDJ3DC!xvuG z2!1g&%U3WF^K$`W0o&8@meWLzy%8H9 zVsAdVQJ3qNz+4DmlCJ7dn4gU%XbDd=IUg>sn=>qON1LH@xZ|aOJ}n&}P5LtbI|EX5 zINwH7Rkg1^7tHl=B0)F3&90~wU6)gafT`@!i?O?rLGCAUGPd{T-7N1P8rKqB)MEK< zJ3Je@QEhh`q0b-LAic8R`w|p_c*eeH%4oRi!zvlJUUAQ$cx65lug8}F5ucSJIdSdS9yyBhz?pXIwkdh|K`MjJshfLe3=u^roW0~?b)~*Z_6N2i^i($ z`qAVI9Qo-1>3oS0K04{N!Ur=-4RT~Je|S^%0L}GHPmW~-U=(%CTO9cn2$!rFEVG}jI2dXY^r)9`~wE!n)#9Hn{D z^#?mZ{)`Q697CEI=1NJ0GF_#q*lE-azPjD7q9#N+8*pG8lVV6*Nj1Wv>5#|GyI3@@ zFnwBBn3-sA6t-X?!;)2WJ+++~

|Af}(VQ@PyheH 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 YN1fk0Zhj=Q|D%6Pipq*q3F!y?Un8??ivR!s literal 0 HcmV?d00001 diff --git a/docs/img/D-REC-logo.png b/docs/img/D-REC-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..38b1c219bae7f1d83311ca52ec271453778a51b8 GIT binary patch literal 14066 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 literal 0 HcmV?d00001 diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 000000000..2c63ca78d --- /dev/null +++ b/docs/index.md @@ -0,0 +1,33 @@ +--- +# https://vitepress.dev/reference/default-theme-home-page +layout: home + +hero: + name: 'D-REC Initiative' + text: 'Documentation for the D-REC platform' + tagline: Distributed Renewable Energy Certificates + actions: + - theme: brand + text: Documentation + link: /introduction/technology-overview + - theme: alt + text: Get Started + link: https://drecs.org + - theme: alt + text: D-REC Homepage + link: https://drecs.org + image: + src: img/D-REC-logo.png + alt: VitePress + +features: + - icon: 👥 + title: What we do + details: Our core mechanism, the Distributed Renewable Energy Certificate (D-REC), is an innovative market instrument designed to issue Environmental Attribute Certificates (EACs) from small-scale DRE resources. These D-RECs represent a tangible commitment not only to environmental sustainability but also to energy access with a correlation to socio-economic upliftment in underserved communities. + - icon: ⚡️ + title: Our impact + details: The D-REC Organization is more than just a facilitator of RECs. Through D-RECs, we deepen the corporate climate action to enable small-scale DRE projects to become economically viable and environmentally impactful. Our work not only contributes to meeting global sustainability targets but also ensures that the benefits of renewable energy reach those who need it most. + - icon: 🙏 + title: Our approach + details: Leveraging technology and innovation, we have built a robust platform that streamlines the aggregation and verification process of DRE projects, enabling their certification by relevant bodies. +--- diff --git a/docs/introduction/dre-project-developers.md b/docs/introduction/dre-project-developers.md new file mode 100644 index 000000000..e69de29bb diff --git a/docs/introduction/rec-buyers.md b/docs/introduction/rec-buyers.md new file mode 100644 index 000000000..e69de29bb diff --git a/docs/introduction/technology-overview.md b/docs/introduction/technology-overview.md new file mode 100644 index 000000000..e69de29bb diff --git a/docs/package-lock.json b/docs/package-lock.json new file mode 100644 index 000000000..a41d88368 --- /dev/null +++ b/docs/package-lock.json @@ -0,0 +1,2646 @@ +{ + "name": "docs", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "docs", + "version": "1.0.0", + "license": "ISC", + "devDependencies": { + "vitepress": "^1.1.4" + } + }, + "node_modules/@algolia/autocomplete-core": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-core/-/autocomplete-core-1.9.3.tgz", + "integrity": "sha512-009HdfugtGCdC4JdXUbVJClA0q0zh24yyePn+KUGk3rP7j8FEe/m5Yo/z65gn6nP/cM39PxpzqKrL7A6fP6PPw==", + "dev": true, + "dependencies": { + "@algolia/autocomplete-plugin-algolia-insights": "1.9.3", + "@algolia/autocomplete-shared": "1.9.3" + } + }, + "node_modules/@algolia/autocomplete-plugin-algolia-insights": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-plugin-algolia-insights/-/autocomplete-plugin-algolia-insights-1.9.3.tgz", + "integrity": "sha512-a/yTUkcO/Vyy+JffmAnTWbr4/90cLzw+CC3bRbhnULr/EM0fGNvM13oQQ14f2moLMcVDyAx/leczLlAOovhSZg==", + "dev": true, + "dependencies": { + "@algolia/autocomplete-shared": "1.9.3" + }, + "peerDependencies": { + "search-insights": ">= 1 < 3" + } + }, + "node_modules/@algolia/autocomplete-preset-algolia": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-preset-algolia/-/autocomplete-preset-algolia-1.9.3.tgz", + "integrity": "sha512-d4qlt6YmrLMYy95n5TB52wtNDr6EgAIPH81dvvvW8UmuWRgxEtY0NJiPwl/h95JtG2vmRM804M0DSwMCNZlzRA==", + "dev": true, + "dependencies": { + "@algolia/autocomplete-shared": "1.9.3" + }, + "peerDependencies": { + "@algolia/client-search": ">= 4.9.1 < 6", + "algoliasearch": ">= 4.9.1 < 6" + } + }, + "node_modules/@algolia/autocomplete-shared": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-shared/-/autocomplete-shared-1.9.3.tgz", + "integrity": "sha512-Wnm9E4Ye6Rl6sTTqjoymD+l8DjSTHsHboVRYrKgEt8Q7UHm9nYbqhN/i0fhUYA3OAEH7WA8x3jfpnmJm3rKvaQ==", + "dev": true, + "peerDependencies": { + "@algolia/client-search": ">= 4.9.1 < 6", + "algoliasearch": ">= 4.9.1 < 6" + } + }, + "node_modules/@algolia/cache-browser-local-storage": { + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/@algolia/cache-browser-local-storage/-/cache-browser-local-storage-4.23.3.tgz", + "integrity": "sha512-vRHXYCpPlTDE7i6UOy2xE03zHF2C8MEFjPN2v7fRbqVpcOvAUQK81x3Kc21xyb5aSIpYCjWCZbYZuz8Glyzyyg==", + "dev": true, + "dependencies": { + "@algolia/cache-common": "4.23.3" + } + }, + "node_modules/@algolia/cache-common": { + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/@algolia/cache-common/-/cache-common-4.23.3.tgz", + "integrity": "sha512-h9XcNI6lxYStaw32pHpB1TMm0RuxphF+Ik4o7tcQiodEdpKK+wKufY6QXtba7t3k8eseirEMVB83uFFF3Nu54A==", + "dev": true + }, + "node_modules/@algolia/cache-in-memory": { + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/@algolia/cache-in-memory/-/cache-in-memory-4.23.3.tgz", + "integrity": "sha512-yvpbuUXg/+0rbcagxNT7un0eo3czx2Uf0y4eiR4z4SD7SiptwYTpbuS0IHxcLHG3lq22ukx1T6Kjtk/rT+mqNg==", + "dev": true, + "dependencies": { + "@algolia/cache-common": "4.23.3" + } + }, + "node_modules/@algolia/client-account": { + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/@algolia/client-account/-/client-account-4.23.3.tgz", + "integrity": "sha512-hpa6S5d7iQmretHHF40QGq6hz0anWEHGlULcTIT9tbUssWUriN9AUXIFQ8Ei4w9azD0hc1rUok9/DeQQobhQMA==", + "dev": true, + "dependencies": { + "@algolia/client-common": "4.23.3", + "@algolia/client-search": "4.23.3", + "@algolia/transporter": "4.23.3" + } + }, + "node_modules/@algolia/client-analytics": { + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-4.23.3.tgz", + "integrity": "sha512-LBsEARGS9cj8VkTAVEZphjxTjMVCci+zIIiRhpFun9jGDUlS1XmhCW7CTrnaWeIuCQS/2iPyRqSy1nXPjcBLRA==", + "dev": true, + "dependencies": { + "@algolia/client-common": "4.23.3", + "@algolia/client-search": "4.23.3", + "@algolia/requester-common": "4.23.3", + "@algolia/transporter": "4.23.3" + } + }, + "node_modules/@algolia/client-common": { + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-4.23.3.tgz", + "integrity": "sha512-l6EiPxdAlg8CYhroqS5ybfIczsGUIAC47slLPOMDeKSVXYG1n0qGiz4RjAHLw2aD0xzh2EXZ7aRguPfz7UKDKw==", + "dev": true, + "dependencies": { + "@algolia/requester-common": "4.23.3", + "@algolia/transporter": "4.23.3" + } + }, + "node_modules/@algolia/client-personalization": { + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-4.23.3.tgz", + "integrity": "sha512-3E3yF3Ocr1tB/xOZiuC3doHQBQ2zu2MPTYZ0d4lpfWads2WTKG7ZzmGnsHmm63RflvDeLK/UVx7j2b3QuwKQ2g==", + "dev": true, + "dependencies": { + "@algolia/client-common": "4.23.3", + "@algolia/requester-common": "4.23.3", + "@algolia/transporter": "4.23.3" + } + }, + "node_modules/@algolia/client-search": { + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-4.23.3.tgz", + "integrity": "sha512-P4VAKFHqU0wx9O+q29Q8YVuaowaZ5EM77rxfmGnkHUJggh28useXQdopokgwMeYw2XUht49WX5RcTQ40rZIabw==", + "dev": true, + "dependencies": { + "@algolia/client-common": "4.23.3", + "@algolia/requester-common": "4.23.3", + "@algolia/transporter": "4.23.3" + } + }, + "node_modules/@algolia/logger-common": { + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/@algolia/logger-common/-/logger-common-4.23.3.tgz", + "integrity": "sha512-y9kBtmJwiZ9ZZ+1Ek66P0M68mHQzKRxkW5kAAXYN/rdzgDN0d2COsViEFufxJ0pb45K4FRcfC7+33YB4BLrZ+g==", + "dev": true + }, + "node_modules/@algolia/logger-console": { + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/@algolia/logger-console/-/logger-console-4.23.3.tgz", + "integrity": "sha512-8xoiseoWDKuCVnWP8jHthgaeobDLolh00KJAdMe9XPrWPuf1by732jSpgy2BlsLTaT9m32pHI8CRfrOqQzHv3A==", + "dev": true, + "dependencies": { + "@algolia/logger-common": "4.23.3" + } + }, + "node_modules/@algolia/recommend": { + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/@algolia/recommend/-/recommend-4.23.3.tgz", + "integrity": "sha512-9fK4nXZF0bFkdcLBRDexsnGzVmu4TSYZqxdpgBW2tEyfuSSY54D4qSRkLmNkrrz4YFvdh2GM1gA8vSsnZPR73w==", + "dev": true, + "dependencies": { + "@algolia/cache-browser-local-storage": "4.23.3", + "@algolia/cache-common": "4.23.3", + "@algolia/cache-in-memory": "4.23.3", + "@algolia/client-common": "4.23.3", + "@algolia/client-search": "4.23.3", + "@algolia/logger-common": "4.23.3", + "@algolia/logger-console": "4.23.3", + "@algolia/requester-browser-xhr": "4.23.3", + "@algolia/requester-common": "4.23.3", + "@algolia/requester-node-http": "4.23.3", + "@algolia/transporter": "4.23.3" + } + }, + "node_modules/@algolia/requester-browser-xhr": { + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.23.3.tgz", + "integrity": "sha512-jDWGIQ96BhXbmONAQsasIpTYWslyjkiGu0Quydjlowe+ciqySpiDUrJHERIRfELE5+wFc7hc1Q5hqjGoV7yghw==", + "dev": true, + "dependencies": { + "@algolia/requester-common": "4.23.3" + } + }, + "node_modules/@algolia/requester-common": { + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/@algolia/requester-common/-/requester-common-4.23.3.tgz", + "integrity": "sha512-xloIdr/bedtYEGcXCiF2muajyvRhwop4cMZo+K2qzNht0CMzlRkm8YsDdj5IaBhshqfgmBb3rTg4sL4/PpvLYw==", + "dev": true + }, + "node_modules/@algolia/requester-node-http": { + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-4.23.3.tgz", + "integrity": "sha512-zgu++8Uj03IWDEJM3fuNl34s746JnZOWn1Uz5taV1dFyJhVM/kTNw9Ik7YJWiUNHJQXcaD8IXD1eCb0nq/aByA==", + "dev": true, + "dependencies": { + "@algolia/requester-common": "4.23.3" + } + }, + "node_modules/@algolia/transporter": { + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/@algolia/transporter/-/transporter-4.23.3.tgz", + "integrity": "sha512-Wjl5gttqnf/gQKJA+dafnD0Y6Yw97yvfY8R9h0dQltX1GXTgNs1zWgvtWW0tHl1EgMdhAyw189uWiZMnL3QebQ==", + "dev": true, + "dependencies": { + "@algolia/cache-common": "4.23.3", + "@algolia/logger-common": "4.23.3", + "@algolia/requester-common": "4.23.3" + } + }, + "node_modules/@babel/parser": { + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.5.tgz", + "integrity": "sha512-EOv5IK8arwh3LI47dz1b0tKUb/1uhHAnHJOrjgtQMIpu1uXd9mlFrJg9IUgGUgZ41Ch0K8REPTYpO7B76b4vJg==", + "dev": true, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@docsearch/css": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/@docsearch/css/-/css-3.6.0.tgz", + "integrity": "sha512-+sbxb71sWre+PwDK7X2T8+bhS6clcVMLwBPznX45Qu6opJcgRjAp7gYSDzVFp187J+feSj5dNBN1mJoi6ckkUQ==", + "dev": true + }, + "node_modules/@docsearch/js": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/@docsearch/js/-/js-3.6.0.tgz", + "integrity": "sha512-QujhqINEElrkIfKwyyyTfbsfMAYCkylInLYMRqHy7PHc8xTBQCow73tlo/Kc7oIwBrCLf0P3YhjlOeV4v8hevQ==", + "dev": true, + "dependencies": { + "@docsearch/react": "3.6.0", + "preact": "^10.0.0" + } + }, + "node_modules/@docsearch/react": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/@docsearch/react/-/react-3.6.0.tgz", + "integrity": "sha512-HUFut4ztcVNmqy9gp/wxNbC7pTOHhgVVkHVGCACTuLhUKUhKAF9KYHJtMiLUJxEqiFLQiuri1fWF8zqwM/cu1w==", + "dev": true, + "dependencies": { + "@algolia/autocomplete-core": "1.9.3", + "@algolia/autocomplete-preset-algolia": "1.9.3", + "@docsearch/css": "3.6.0", + "algoliasearch": "^4.19.1" + }, + "peerDependencies": { + "@types/react": ">= 16.8.0 < 19.0.0", + "react": ">= 16.8.0 < 19.0.0", + "react-dom": ">= 16.8.0 < 19.0.0", + "search-insights": ">= 1 < 3" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "react": { + "optional": true + }, + "react-dom": { + "optional": true + }, + "search-insights": { + "optional": true + } + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.20.2.tgz", + "integrity": "sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.20.2.tgz", + "integrity": "sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.20.2.tgz", + "integrity": "sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.20.2.tgz", + "integrity": "sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.20.2.tgz", + "integrity": "sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.20.2.tgz", + "integrity": "sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.2.tgz", + "integrity": "sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.20.2.tgz", + "integrity": "sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.20.2.tgz", + "integrity": "sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.20.2.tgz", + "integrity": "sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.20.2.tgz", + "integrity": "sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.20.2.tgz", + "integrity": "sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.20.2.tgz", + "integrity": "sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.20.2.tgz", + "integrity": "sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.20.2.tgz", + "integrity": "sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.20.2.tgz", + "integrity": "sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.20.2.tgz", + "integrity": "sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.20.2.tgz", + "integrity": "sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.20.2.tgz", + "integrity": "sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.20.2.tgz", + "integrity": "sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.20.2.tgz", + "integrity": "sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.20.2.tgz", + "integrity": "sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.20.2.tgz", + "integrity": "sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "dev": true + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.17.2.tgz", + "integrity": "sha512-NM0jFxY8bB8QLkoKxIQeObCaDlJKewVlIEkuyYKm5An1tdVZ966w2+MPQ2l8LBZLjR+SgyV+nRkTIunzOYBMLQ==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.17.2.tgz", + "integrity": "sha512-yeX/Usk7daNIVwkq2uGoq2BYJKZY1JfyLTaHO/jaiSwi/lsf8fTFoQW/n6IdAsx5tx+iotu2zCJwz8MxI6D/Bw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.17.2.tgz", + "integrity": "sha512-kcMLpE6uCwls023+kknm71ug7MZOrtXo+y5p/tsg6jltpDtgQY1Eq5sGfHcQfb+lfuKwhBmEURDga9N0ol4YPw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.17.2.tgz", + "integrity": "sha512-AtKwD0VEx0zWkL0ZjixEkp5tbNLzX+FCqGG1SvOu993HnSz4qDI6S4kGzubrEJAljpVkhRSlg5bzpV//E6ysTQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.17.2.tgz", + "integrity": "sha512-3reX2fUHqN7sffBNqmEyMQVj/CKhIHZd4y631duy0hZqI8Qoqf6lTtmAKvJFYa6bhU95B1D0WgzHkmTg33In0A==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.17.2.tgz", + "integrity": "sha512-uSqpsp91mheRgw96xtyAGP9FW5ChctTFEoXP0r5FAzj/3ZRv3Uxjtc7taRQSaQM/q85KEKjKsZuiZM3GyUivRg==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.17.2.tgz", + "integrity": "sha512-EMMPHkiCRtE8Wdk3Qhtciq6BndLtstqZIroHiiGzB3C5LDJmIZcSzVtLRbwuXuUft1Cnv+9fxuDtDxz3k3EW2A==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.17.2.tgz", + "integrity": "sha512-NMPylUUZ1i0z/xJUIx6VUhISZDRT+uTWpBcjdv0/zkp7b/bQDF+NfnfdzuTiB1G6HTodgoFa93hp0O1xl+/UbA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.17.2.tgz", + "integrity": "sha512-T19My13y8uYXPw/L/k0JYaX1fJKFT/PWdXiHr8mTbXWxjVF1t+8Xl31DgBBvEKclw+1b00Chg0hxE2O7bTG7GQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.17.2.tgz", + "integrity": "sha512-BOaNfthf3X3fOWAB+IJ9kxTgPmMqPPH5f5k2DcCsRrBIbWnaJCgX2ll77dV1TdSy9SaXTR5iDXRL8n7AnoP5cg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.17.2.tgz", + "integrity": "sha512-W0UP/x7bnn3xN2eYMql2T/+wpASLE5SjObXILTMPUBDB/Fg/FxC+gX4nvCfPBCbNhz51C+HcqQp2qQ4u25ok6g==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.17.2.tgz", + "integrity": "sha512-Hy7pLwByUOuyaFC6mAr7m+oMC+V7qyifzs/nW2OJfC8H4hbCzOX07Ov0VFk/zP3kBsELWNFi7rJtgbKYsav9QQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.17.2.tgz", + "integrity": "sha512-h1+yTWeYbRdAyJ/jMiVw0l6fOOm/0D1vNLui9iPuqgRGnXA0u21gAqOyB5iHjlM9MMfNOm9RHCQ7zLIzT0x11Q==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.17.2.tgz", + "integrity": "sha512-tmdtXMfKAjy5+IQsVtDiCfqbynAQE/TQRpWdVataHmhMb9DCoJxp9vLcCBjEQWMiUYxO1QprH/HbY9ragCEFLA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.17.2.tgz", + "integrity": "sha512-7II/QCSTAHuE5vdZaQEwJq2ZACkBpQDOmQsE6D6XUbnBHW8IAhm4eTufL6msLJorzrHDFv3CF8oCA/hSIRuZeQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.17.2.tgz", + "integrity": "sha512-TGGO7v7qOq4CYmSBVEYpI1Y5xDuCEnbVC5Vth8mOsW0gDSzxNrVERPc790IGHsrT2dQSimgMr9Ub3Y1Jci5/8w==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@shikijs/core": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-1.4.0.tgz", + "integrity": "sha512-CxpKLntAi64h3j+TwWqVIQObPTED0FyXLHTTh3MKXtqiQNn2JGcMQQ362LftDbc9kYbDtrksNMNoVmVXzKFYUQ==", + "dev": true + }, + "node_modules/@shikijs/transformers": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@shikijs/transformers/-/transformers-1.4.0.tgz", + "integrity": "sha512-kzvlWmWYYSeaLKRce/kgmFFORUtBtFahfXRKndor0b60ocYiXufBQM6d6w1PlMuUkdk55aor9xLvy9wy7hTEJg==", + "dev": true, + "dependencies": { + "shiki": "1.4.0" + } + }, + "node_modules/@types/estree": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", + "dev": true + }, + "node_modules/@types/linkify-it": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-5.0.0.tgz", + "integrity": "sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==", + "dev": true + }, + "node_modules/@types/markdown-it": { + "version": "14.1.1", + "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-14.1.1.tgz", + "integrity": "sha512-4NpsnpYl2Gt1ljyBGrKMxFYAYvpqbnnkgP/i/g+NLpjEUa3obn1XJCur9YbEXKDAkaXqsR1LbDnGEJ0MmKFxfg==", + "dev": true, + "dependencies": { + "@types/linkify-it": "^5", + "@types/mdurl": "^2" + } + }, + "node_modules/@types/mdurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-2.0.0.tgz", + "integrity": "sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==", + "dev": true + }, + "node_modules/@types/web-bluetooth": { + "version": "0.0.20", + "resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.20.tgz", + "integrity": "sha512-g9gZnnXVq7gM7v3tJCWV/qw7w+KeOlSHAhgF9RytFyifW6AF61hdT2ucrYhPq9hLs5JIryeupHV3qGk95dH9ow==", + "dev": true + }, + "node_modules/@vitejs/plugin-vue": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-5.0.4.tgz", + "integrity": "sha512-WS3hevEszI6CEVEx28F8RjTX97k3KsrcY6kvTg7+Whm5y3oYvcqzVeGCU3hxSAn4uY2CLCkeokkGKpoctccilQ==", + "dev": true, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "peerDependencies": { + "vite": "^5.0.0", + "vue": "^3.2.25" + } + }, + "node_modules/@vue/compiler-core": { + "version": "3.4.27", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.4.27.tgz", + "integrity": "sha512-E+RyqY24KnyDXsCuQrI+mlcdW3ALND6U7Gqa/+bVwbcpcR3BRRIckFoz7Qyd4TTlnugtwuI7YgjbvsLmxb+yvg==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.24.4", + "@vue/shared": "3.4.27", + "entities": "^4.5.0", + "estree-walker": "^2.0.2", + "source-map-js": "^1.2.0" + } + }, + "node_modules/@vue/compiler-dom": { + "version": "3.4.27", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.4.27.tgz", + "integrity": "sha512-kUTvochG/oVgE1w5ViSr3KUBh9X7CWirebA3bezTbB5ZKBQZwR2Mwj9uoSKRMFcz4gSMzzLXBPD6KpCLb9nvWw==", + "dev": true, + "dependencies": { + "@vue/compiler-core": "3.4.27", + "@vue/shared": "3.4.27" + } + }, + "node_modules/@vue/compiler-sfc": { + "version": "3.4.27", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.4.27.tgz", + "integrity": "sha512-nDwntUEADssW8e0rrmE0+OrONwmRlegDA1pD6QhVeXxjIytV03yDqTey9SBDiALsvAd5U4ZrEKbMyVXhX6mCGA==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.24.4", + "@vue/compiler-core": "3.4.27", + "@vue/compiler-dom": "3.4.27", + "@vue/compiler-ssr": "3.4.27", + "@vue/shared": "3.4.27", + "estree-walker": "^2.0.2", + "magic-string": "^0.30.10", + "postcss": "^8.4.38", + "source-map-js": "^1.2.0" + } + }, + "node_modules/@vue/compiler-ssr": { + "version": "3.4.27", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.4.27.tgz", + "integrity": "sha512-CVRzSJIltzMG5FcidsW0jKNQnNRYC8bT21VegyMMtHmhW3UOI7knmUehzswXLrExDLE6lQCZdrhD4ogI7c+vuw==", + "dev": true, + "dependencies": { + "@vue/compiler-dom": "3.4.27", + "@vue/shared": "3.4.27" + } + }, + "node_modules/@vue/devtools-api": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-7.1.3.tgz", + "integrity": "sha512-W8IwFJ/o5iUk78jpqhvScbgCsPiOp2uileDVC0NDtW38gCWhsnu9SeBTjcdu3lbwLdsjc+H1c5Msd/x9ApbcFA==", + "dev": true, + "dependencies": { + "@vue/devtools-kit": "^7.1.3" + } + }, + "node_modules/@vue/devtools-kit": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/@vue/devtools-kit/-/devtools-kit-7.1.3.tgz", + "integrity": "sha512-NFskFSJMVCBXTkByuk2llzI3KD3Blcm7WqiRorWjD6nClHPgkH5BobDH08rfulqq5ocRt5xV+3qOT1Q9FXJrwQ==", + "dev": true, + "dependencies": { + "@vue/devtools-shared": "^7.1.3", + "hookable": "^5.5.3", + "mitt": "^3.0.1", + "perfect-debounce": "^1.0.0", + "speakingurl": "^14.0.1" + }, + "peerDependencies": { + "vue": "^3.0.0" + } + }, + "node_modules/@vue/devtools-shared": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/@vue/devtools-shared/-/devtools-shared-7.1.3.tgz", + "integrity": "sha512-KJ3AfgjTn3tJz/XKF+BlVShNPecim3G21oHRue+YQOsooW+0s+qXvm09U09aO7yBza5SivL1QgxSrzAbiKWjhQ==", + "dev": true, + "dependencies": { + "rfdc": "^1.3.1" + } + }, + "node_modules/@vue/reactivity": { + "version": "3.4.27", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.4.27.tgz", + "integrity": "sha512-kK0g4NknW6JX2yySLpsm2jlunZJl2/RJGZ0H9ddHdfBVHcNzxmQ0sS0b09ipmBoQpY8JM2KmUw+a6sO8Zo+zIA==", + "dev": true, + "dependencies": { + "@vue/shared": "3.4.27" + } + }, + "node_modules/@vue/runtime-core": { + "version": "3.4.27", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.4.27.tgz", + "integrity": "sha512-7aYA9GEbOOdviqVvcuweTLe5Za4qBZkUY7SvET6vE8kyypxVgaT1ixHLg4urtOlrApdgcdgHoTZCUuTGap/5WA==", + "dev": true, + "dependencies": { + "@vue/reactivity": "3.4.27", + "@vue/shared": "3.4.27" + } + }, + "node_modules/@vue/runtime-dom": { + "version": "3.4.27", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.4.27.tgz", + "integrity": "sha512-ScOmP70/3NPM+TW9hvVAz6VWWtZJqkbdf7w6ySsws+EsqtHvkhxaWLecrTorFxsawelM5Ys9FnDEMt6BPBDS0Q==", + "dev": true, + "dependencies": { + "@vue/runtime-core": "3.4.27", + "@vue/shared": "3.4.27", + "csstype": "^3.1.3" + } + }, + "node_modules/@vue/server-renderer": { + "version": "3.4.27", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.4.27.tgz", + "integrity": "sha512-dlAMEuvmeA3rJsOMJ2J1kXU7o7pOxgsNHVr9K8hB3ImIkSuBrIdy0vF66h8gf8Tuinf1TK3mPAz2+2sqyf3KzA==", + "dev": true, + "dependencies": { + "@vue/compiler-ssr": "3.4.27", + "@vue/shared": "3.4.27" + }, + "peerDependencies": { + "vue": "3.4.27" + } + }, + "node_modules/@vue/shared": { + "version": "3.4.27", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.27.tgz", + "integrity": "sha512-DL3NmY2OFlqmYYrzp39yi3LDkKxa5vZVwxWdQ3rG0ekuWscHraeIbnI8t+aZK7qhYqEqWKTUdijadunb9pnrgA==", + "dev": true + }, + "node_modules/@vueuse/core": { + "version": "10.9.0", + "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-10.9.0.tgz", + "integrity": "sha512-/1vjTol8SXnx6xewDEKfS0Ra//ncg4Hb0DaZiwKf7drgfMsKFExQ+FnnENcN6efPen+1kIzhLQoGSy0eDUVOMg==", + "dev": true, + "dependencies": { + "@types/web-bluetooth": "^0.0.20", + "@vueuse/metadata": "10.9.0", + "@vueuse/shared": "10.9.0", + "vue-demi": ">=0.14.7" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@vueuse/core/node_modules/vue-demi": { + "version": "0.14.7", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.7.tgz", + "integrity": "sha512-EOG8KXDQNwkJILkx/gPcoL/7vH+hORoBaKgGe+6W7VFMvCYJfmF2dGbvgDroVnI8LU7/kTu8mbjRZGBU1z9NTA==", + "dev": true, + "hasInstallScript": true, + "bin": { + "vue-demi-fix": "bin/vue-demi-fix.js", + "vue-demi-switch": "bin/vue-demi-switch.js" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "@vue/composition-api": "^1.0.0-rc.1", + "vue": "^3.0.0-0 || ^2.6.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + } + } + }, + "node_modules/@vueuse/integrations": { + "version": "10.9.0", + "resolved": "https://registry.npmjs.org/@vueuse/integrations/-/integrations-10.9.0.tgz", + "integrity": "sha512-acK+A01AYdWSvL4BZmCoJAcyHJ6EqhmkQEXbQLwev1MY7NBnS+hcEMx/BzVoR9zKI+UqEPMD9u6PsyAuiTRT4Q==", + "dev": true, + "dependencies": { + "@vueuse/core": "10.9.0", + "@vueuse/shared": "10.9.0", + "vue-demi": ">=0.14.7" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "async-validator": "*", + "axios": "*", + "change-case": "*", + "drauu": "*", + "focus-trap": "*", + "fuse.js": "*", + "idb-keyval": "*", + "jwt-decode": "*", + "nprogress": "*", + "qrcode": "*", + "sortablejs": "*", + "universal-cookie": "*" + }, + "peerDependenciesMeta": { + "async-validator": { + "optional": true + }, + "axios": { + "optional": true + }, + "change-case": { + "optional": true + }, + "drauu": { + "optional": true + }, + "focus-trap": { + "optional": true + }, + "fuse.js": { + "optional": true + }, + "idb-keyval": { + "optional": true + }, + "jwt-decode": { + "optional": true + }, + "nprogress": { + "optional": true + }, + "qrcode": { + "optional": true + }, + "sortablejs": { + "optional": true + }, + "universal-cookie": { + "optional": true + } + } + }, + "node_modules/@vueuse/integrations/node_modules/vue-demi": { + "version": "0.14.7", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.7.tgz", + "integrity": "sha512-EOG8KXDQNwkJILkx/gPcoL/7vH+hORoBaKgGe+6W7VFMvCYJfmF2dGbvgDroVnI8LU7/kTu8mbjRZGBU1z9NTA==", + "dev": true, + "hasInstallScript": true, + "bin": { + "vue-demi-fix": "bin/vue-demi-fix.js", + "vue-demi-switch": "bin/vue-demi-switch.js" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "@vue/composition-api": "^1.0.0-rc.1", + "vue": "^3.0.0-0 || ^2.6.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + } + } + }, + "node_modules/@vueuse/metadata": { + "version": "10.9.0", + "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-10.9.0.tgz", + "integrity": "sha512-iddNbg3yZM0X7qFY2sAotomgdHK7YJ6sKUvQqbvwnf7TmaVPxS4EJydcNsVejNdS8iWCtDk+fYXr7E32nyTnGA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@vueuse/shared": { + "version": "10.9.0", + "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-10.9.0.tgz", + "integrity": "sha512-Uud2IWncmAfJvRaFYzv5OHDli+FbOzxiVEQdLCKQKLyhz94PIyFC3CHcH7EDMwIn8NPtD06+PNbC/PiO0LGLtw==", + "dev": true, + "dependencies": { + "vue-demi": ">=0.14.7" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@vueuse/shared/node_modules/vue-demi": { + "version": "0.14.7", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.7.tgz", + "integrity": "sha512-EOG8KXDQNwkJILkx/gPcoL/7vH+hORoBaKgGe+6W7VFMvCYJfmF2dGbvgDroVnI8LU7/kTu8mbjRZGBU1z9NTA==", + "dev": true, + "hasInstallScript": true, + "bin": { + "vue-demi-fix": "bin/vue-demi-fix.js", + "vue-demi-switch": "bin/vue-demi-switch.js" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "@vue/composition-api": "^1.0.0-rc.1", + "vue": "^3.0.0-0 || ^2.6.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + } + } + }, + "node_modules/algoliasearch": { + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-4.23.3.tgz", + "integrity": "sha512-Le/3YgNvjW9zxIQMRhUHuhiUjAlKY/zsdZpfq4dlLqg6mEm0nL6yk+7f2hDOtLpxsgE4jSzDmvHL7nXdBp5feg==", + "dev": true, + "dependencies": { + "@algolia/cache-browser-local-storage": "4.23.3", + "@algolia/cache-common": "4.23.3", + "@algolia/cache-in-memory": "4.23.3", + "@algolia/client-account": "4.23.3", + "@algolia/client-analytics": "4.23.3", + "@algolia/client-common": "4.23.3", + "@algolia/client-personalization": "4.23.3", + "@algolia/client-search": "4.23.3", + "@algolia/logger-common": "4.23.3", + "@algolia/logger-console": "4.23.3", + "@algolia/recommend": "4.23.3", + "@algolia/requester-browser-xhr": "4.23.3", + "@algolia/requester-common": "4.23.3", + "@algolia/requester-node-http": "4.23.3", + "@algolia/transporter": "4.23.3" + } + }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", + "dev": true + }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "dev": true, + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/esbuild": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.2.tgz", + "integrity": "sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.20.2", + "@esbuild/android-arm": "0.20.2", + "@esbuild/android-arm64": "0.20.2", + "@esbuild/android-x64": "0.20.2", + "@esbuild/darwin-arm64": "0.20.2", + "@esbuild/darwin-x64": "0.20.2", + "@esbuild/freebsd-arm64": "0.20.2", + "@esbuild/freebsd-x64": "0.20.2", + "@esbuild/linux-arm": "0.20.2", + "@esbuild/linux-arm64": "0.20.2", + "@esbuild/linux-ia32": "0.20.2", + "@esbuild/linux-loong64": "0.20.2", + "@esbuild/linux-mips64el": "0.20.2", + "@esbuild/linux-ppc64": "0.20.2", + "@esbuild/linux-riscv64": "0.20.2", + "@esbuild/linux-s390x": "0.20.2", + "@esbuild/linux-x64": "0.20.2", + "@esbuild/netbsd-x64": "0.20.2", + "@esbuild/openbsd-x64": "0.20.2", + "@esbuild/sunos-x64": "0.20.2", + "@esbuild/win32-arm64": "0.20.2", + "@esbuild/win32-ia32": "0.20.2", + "@esbuild/win32-x64": "0.20.2" + } + }, + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "dev": true + }, + "node_modules/focus-trap": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/focus-trap/-/focus-trap-7.5.4.tgz", + "integrity": "sha512-N7kHdlgsO/v+iD/dMoJKtsSqs5Dz/dXZVebRgJw23LDk+jMi/974zyiOYDziY2JPp8xivq9BmUGwIJMiuSBi7w==", + "dev": true, + "dependencies": { + "tabbable": "^6.2.0" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/hookable": { + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/hookable/-/hookable-5.5.3.tgz", + "integrity": "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==", + "dev": true + }, + "node_modules/magic-string": { + "version": "0.30.10", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.10.tgz", + "integrity": "sha512-iIRwTIf0QKV3UAnYK4PU8uiEc4SRh5jX0mwpIwETPpHdhVM4f53RSwS/vXvN1JhGX+Cs7B8qIq3d6AH49O5fAQ==", + "dev": true, + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.4.15" + } + }, + "node_modules/mark.js": { + "version": "8.11.1", + "resolved": "https://registry.npmjs.org/mark.js/-/mark.js-8.11.1.tgz", + "integrity": "sha512-1I+1qpDt4idfgLQG+BNWmrqku+7/2bi5nLf4YwF8y8zXvmfiTBY3PV3ZibfrjBueCByROpuBjLLFCajqkgYoLQ==", + "dev": true + }, + "node_modules/minisearch": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/minisearch/-/minisearch-6.3.0.tgz", + "integrity": "sha512-ihFnidEeU8iXzcVHy74dhkxh/dn8Dc08ERl0xwoMMGqp4+LvRSCgicb+zGqWthVokQKvCSxITlh3P08OzdTYCQ==", + "dev": true + }, + "node_modules/mitt": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz", + "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==", + "dev": true + }, + "node_modules/nanoid": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/perfect-debounce": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-1.0.0.tgz", + "integrity": "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==", + "dev": true + }, + "node_modules/picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, + "node_modules/postcss": { + "version": "8.4.38", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz", + "integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "nanoid": "^3.3.7", + "picocolors": "^1.0.0", + "source-map-js": "^1.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/preact": { + "version": "10.21.0", + "resolved": "https://registry.npmjs.org/preact/-/preact-10.21.0.tgz", + "integrity": "sha512-aQAIxtzWEwH8ou+OovWVSVNlFImL7xUCwJX3YMqA3U8iKCNC34999fFOnWjYNsylgfPgMexpbk7WYOLtKr/mxg==", + "dev": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/preact" + } + }, + "node_modules/rfdc": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.1.tgz", + "integrity": "sha512-r5a3l5HzYlIC68TpmYKlxWjmOP6wiPJ1vWv2HeLhNsRZMrCkxeqxiHlQ21oXmQ4F3SiryXBHhAD7JZqvOJjFmg==", + "dev": true + }, + "node_modules/rollup": { + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.17.2.tgz", + "integrity": "sha512-/9ClTJPByC0U4zNLowV1tMBe8yMEAxewtR3cUNX5BoEpGH3dQEWpJLr6CLp0fPdYRF/fzVOgvDb1zXuakwF5kQ==", + "dev": true, + "dependencies": { + "@types/estree": "1.0.5" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.17.2", + "@rollup/rollup-android-arm64": "4.17.2", + "@rollup/rollup-darwin-arm64": "4.17.2", + "@rollup/rollup-darwin-x64": "4.17.2", + "@rollup/rollup-linux-arm-gnueabihf": "4.17.2", + "@rollup/rollup-linux-arm-musleabihf": "4.17.2", + "@rollup/rollup-linux-arm64-gnu": "4.17.2", + "@rollup/rollup-linux-arm64-musl": "4.17.2", + "@rollup/rollup-linux-powerpc64le-gnu": "4.17.2", + "@rollup/rollup-linux-riscv64-gnu": "4.17.2", + "@rollup/rollup-linux-s390x-gnu": "4.17.2", + "@rollup/rollup-linux-x64-gnu": "4.17.2", + "@rollup/rollup-linux-x64-musl": "4.17.2", + "@rollup/rollup-win32-arm64-msvc": "4.17.2", + "@rollup/rollup-win32-ia32-msvc": "4.17.2", + "@rollup/rollup-win32-x64-msvc": "4.17.2", + "fsevents": "~2.3.2" + } + }, + "node_modules/search-insights": { + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/search-insights/-/search-insights-2.13.0.tgz", + "integrity": "sha512-Orrsjf9trHHxFRuo9/rzm0KIWmgzE8RMlZMzuhZOJ01Rnz3D0YBAe+V6473t6/H6c7irs6Lt48brULAiRWb3Vw==", + "dev": true, + "peer": true + }, + "node_modules/shiki": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-1.4.0.tgz", + "integrity": "sha512-5WIn0OL8PWm7JhnTwRWXniy6eEDY234mRrERVlFa646V2ErQqwIFd2UML7e0Pq9eqSKLoMa3Ke+xbsF+DAuy+Q==", + "dev": true, + "dependencies": { + "@shikijs/core": "1.4.0" + } + }, + "node_modules/source-map-js": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", + "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/speakingurl": { + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/speakingurl/-/speakingurl-14.0.1.tgz", + "integrity": "sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/tabbable": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.2.0.tgz", + "integrity": "sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==", + "dev": true + }, + "node_modules/vite": { + "version": "5.2.11", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.2.11.tgz", + "integrity": "sha512-HndV31LWW05i1BLPMUCE1B9E9GFbOu1MbenhS58FuK6owSO5qHm7GiCotrNY1YE5rMeQSFBGmT5ZaLEjFizgiQ==", + "dev": true, + "dependencies": { + "esbuild": "^0.20.1", + "postcss": "^8.4.38", + "rollup": "^4.13.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || >=20.0.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, + "node_modules/vitepress": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/vitepress/-/vitepress-1.1.4.tgz", + "integrity": "sha512-bWIzFZXpPB6NIDBuWnS20aMADH+FcFKDfQNYFvbOWij03PR29eImTceQHIzCKordjXYBhM/TjE5VKFTUJ3EheA==", + "dev": true, + "dependencies": { + "@docsearch/css": "^3.6.0", + "@docsearch/js": "^3.6.0", + "@shikijs/core": "^1.3.0", + "@shikijs/transformers": "^1.3.0", + "@types/markdown-it": "^14.0.1", + "@vitejs/plugin-vue": "^5.0.4", + "@vue/devtools-api": "^7.0.27", + "@vueuse/core": "^10.9.0", + "@vueuse/integrations": "^10.9.0", + "focus-trap": "^7.5.4", + "mark.js": "8.11.1", + "minisearch": "^6.3.0", + "shiki": "^1.3.0", + "vite": "^5.2.10", + "vue": "^3.4.25" + }, + "bin": { + "vitepress": "bin/vitepress.js" + }, + "peerDependencies": { + "markdown-it-mathjax3": "^4", + "postcss": "^8" + }, + "peerDependenciesMeta": { + "markdown-it-mathjax3": { + "optional": true + }, + "postcss": { + "optional": true + } + } + }, + "node_modules/vue": { + "version": "3.4.27", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.4.27.tgz", + "integrity": "sha512-8s/56uK6r01r1icG/aEOHqyMVxd1bkYcSe9j8HcKtr/xTOFWvnzIVTehNW+5Yt89f+DLBe4A569pnZLS5HzAMA==", + "dev": true, + "dependencies": { + "@vue/compiler-dom": "3.4.27", + "@vue/compiler-sfc": "3.4.27", + "@vue/runtime-dom": "3.4.27", + "@vue/server-renderer": "3.4.27", + "@vue/shared": "3.4.27" + }, + "peerDependencies": { + "typescript": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + } + }, + "dependencies": { + "@algolia/autocomplete-core": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-core/-/autocomplete-core-1.9.3.tgz", + "integrity": "sha512-009HdfugtGCdC4JdXUbVJClA0q0zh24yyePn+KUGk3rP7j8FEe/m5Yo/z65gn6nP/cM39PxpzqKrL7A6fP6PPw==", + "dev": true, + "requires": { + "@algolia/autocomplete-plugin-algolia-insights": "1.9.3", + "@algolia/autocomplete-shared": "1.9.3" + } + }, + "@algolia/autocomplete-plugin-algolia-insights": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-plugin-algolia-insights/-/autocomplete-plugin-algolia-insights-1.9.3.tgz", + "integrity": "sha512-a/yTUkcO/Vyy+JffmAnTWbr4/90cLzw+CC3bRbhnULr/EM0fGNvM13oQQ14f2moLMcVDyAx/leczLlAOovhSZg==", + "dev": true, + "requires": { + "@algolia/autocomplete-shared": "1.9.3" + } + }, + "@algolia/autocomplete-preset-algolia": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-preset-algolia/-/autocomplete-preset-algolia-1.9.3.tgz", + "integrity": "sha512-d4qlt6YmrLMYy95n5TB52wtNDr6EgAIPH81dvvvW8UmuWRgxEtY0NJiPwl/h95JtG2vmRM804M0DSwMCNZlzRA==", + "dev": true, + "requires": { + "@algolia/autocomplete-shared": "1.9.3" + } + }, + "@algolia/autocomplete-shared": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-shared/-/autocomplete-shared-1.9.3.tgz", + "integrity": "sha512-Wnm9E4Ye6Rl6sTTqjoymD+l8DjSTHsHboVRYrKgEt8Q7UHm9nYbqhN/i0fhUYA3OAEH7WA8x3jfpnmJm3rKvaQ==", + "dev": true, + "requires": {} + }, + "@algolia/cache-browser-local-storage": { + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/@algolia/cache-browser-local-storage/-/cache-browser-local-storage-4.23.3.tgz", + "integrity": "sha512-vRHXYCpPlTDE7i6UOy2xE03zHF2C8MEFjPN2v7fRbqVpcOvAUQK81x3Kc21xyb5aSIpYCjWCZbYZuz8Glyzyyg==", + "dev": true, + "requires": { + "@algolia/cache-common": "4.23.3" + } + }, + "@algolia/cache-common": { + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/@algolia/cache-common/-/cache-common-4.23.3.tgz", + "integrity": "sha512-h9XcNI6lxYStaw32pHpB1TMm0RuxphF+Ik4o7tcQiodEdpKK+wKufY6QXtba7t3k8eseirEMVB83uFFF3Nu54A==", + "dev": true + }, + "@algolia/cache-in-memory": { + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/@algolia/cache-in-memory/-/cache-in-memory-4.23.3.tgz", + "integrity": "sha512-yvpbuUXg/+0rbcagxNT7un0eo3czx2Uf0y4eiR4z4SD7SiptwYTpbuS0IHxcLHG3lq22ukx1T6Kjtk/rT+mqNg==", + "dev": true, + "requires": { + "@algolia/cache-common": "4.23.3" + } + }, + "@algolia/client-account": { + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/@algolia/client-account/-/client-account-4.23.3.tgz", + "integrity": "sha512-hpa6S5d7iQmretHHF40QGq6hz0anWEHGlULcTIT9tbUssWUriN9AUXIFQ8Ei4w9azD0hc1rUok9/DeQQobhQMA==", + "dev": true, + "requires": { + "@algolia/client-common": "4.23.3", + "@algolia/client-search": "4.23.3", + "@algolia/transporter": "4.23.3" + } + }, + "@algolia/client-analytics": { + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-4.23.3.tgz", + "integrity": "sha512-LBsEARGS9cj8VkTAVEZphjxTjMVCci+zIIiRhpFun9jGDUlS1XmhCW7CTrnaWeIuCQS/2iPyRqSy1nXPjcBLRA==", + "dev": true, + "requires": { + "@algolia/client-common": "4.23.3", + "@algolia/client-search": "4.23.3", + "@algolia/requester-common": "4.23.3", + "@algolia/transporter": "4.23.3" + } + }, + "@algolia/client-common": { + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-4.23.3.tgz", + "integrity": "sha512-l6EiPxdAlg8CYhroqS5ybfIczsGUIAC47slLPOMDeKSVXYG1n0qGiz4RjAHLw2aD0xzh2EXZ7aRguPfz7UKDKw==", + "dev": true, + "requires": { + "@algolia/requester-common": "4.23.3", + "@algolia/transporter": "4.23.3" + } + }, + "@algolia/client-personalization": { + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-4.23.3.tgz", + "integrity": "sha512-3E3yF3Ocr1tB/xOZiuC3doHQBQ2zu2MPTYZ0d4lpfWads2WTKG7ZzmGnsHmm63RflvDeLK/UVx7j2b3QuwKQ2g==", + "dev": true, + "requires": { + "@algolia/client-common": "4.23.3", + "@algolia/requester-common": "4.23.3", + "@algolia/transporter": "4.23.3" + } + }, + "@algolia/client-search": { + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-4.23.3.tgz", + "integrity": "sha512-P4VAKFHqU0wx9O+q29Q8YVuaowaZ5EM77rxfmGnkHUJggh28useXQdopokgwMeYw2XUht49WX5RcTQ40rZIabw==", + "dev": true, + "requires": { + "@algolia/client-common": "4.23.3", + "@algolia/requester-common": "4.23.3", + "@algolia/transporter": "4.23.3" + } + }, + "@algolia/logger-common": { + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/@algolia/logger-common/-/logger-common-4.23.3.tgz", + "integrity": "sha512-y9kBtmJwiZ9ZZ+1Ek66P0M68mHQzKRxkW5kAAXYN/rdzgDN0d2COsViEFufxJ0pb45K4FRcfC7+33YB4BLrZ+g==", + "dev": true + }, + "@algolia/logger-console": { + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/@algolia/logger-console/-/logger-console-4.23.3.tgz", + "integrity": "sha512-8xoiseoWDKuCVnWP8jHthgaeobDLolh00KJAdMe9XPrWPuf1by732jSpgy2BlsLTaT9m32pHI8CRfrOqQzHv3A==", + "dev": true, + "requires": { + "@algolia/logger-common": "4.23.3" + } + }, + "@algolia/recommend": { + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/@algolia/recommend/-/recommend-4.23.3.tgz", + "integrity": "sha512-9fK4nXZF0bFkdcLBRDexsnGzVmu4TSYZqxdpgBW2tEyfuSSY54D4qSRkLmNkrrz4YFvdh2GM1gA8vSsnZPR73w==", + "dev": true, + "requires": { + "@algolia/cache-browser-local-storage": "4.23.3", + "@algolia/cache-common": "4.23.3", + "@algolia/cache-in-memory": "4.23.3", + "@algolia/client-common": "4.23.3", + "@algolia/client-search": "4.23.3", + "@algolia/logger-common": "4.23.3", + "@algolia/logger-console": "4.23.3", + "@algolia/requester-browser-xhr": "4.23.3", + "@algolia/requester-common": "4.23.3", + "@algolia/requester-node-http": "4.23.3", + "@algolia/transporter": "4.23.3" + } + }, + "@algolia/requester-browser-xhr": { + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.23.3.tgz", + "integrity": "sha512-jDWGIQ96BhXbmONAQsasIpTYWslyjkiGu0Quydjlowe+ciqySpiDUrJHERIRfELE5+wFc7hc1Q5hqjGoV7yghw==", + "dev": true, + "requires": { + "@algolia/requester-common": "4.23.3" + } + }, + "@algolia/requester-common": { + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/@algolia/requester-common/-/requester-common-4.23.3.tgz", + "integrity": "sha512-xloIdr/bedtYEGcXCiF2muajyvRhwop4cMZo+K2qzNht0CMzlRkm8YsDdj5IaBhshqfgmBb3rTg4sL4/PpvLYw==", + "dev": true + }, + "@algolia/requester-node-http": { + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-4.23.3.tgz", + "integrity": "sha512-zgu++8Uj03IWDEJM3fuNl34s746JnZOWn1Uz5taV1dFyJhVM/kTNw9Ik7YJWiUNHJQXcaD8IXD1eCb0nq/aByA==", + "dev": true, + "requires": { + "@algolia/requester-common": "4.23.3" + } + }, + "@algolia/transporter": { + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/@algolia/transporter/-/transporter-4.23.3.tgz", + "integrity": "sha512-Wjl5gttqnf/gQKJA+dafnD0Y6Yw97yvfY8R9h0dQltX1GXTgNs1zWgvtWW0tHl1EgMdhAyw189uWiZMnL3QebQ==", + "dev": true, + "requires": { + "@algolia/cache-common": "4.23.3", + "@algolia/logger-common": "4.23.3", + "@algolia/requester-common": "4.23.3" + } + }, + "@babel/parser": { + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.5.tgz", + "integrity": "sha512-EOv5IK8arwh3LI47dz1b0tKUb/1uhHAnHJOrjgtQMIpu1uXd9mlFrJg9IUgGUgZ41Ch0K8REPTYpO7B76b4vJg==", + "dev": true + }, + "@docsearch/css": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/@docsearch/css/-/css-3.6.0.tgz", + "integrity": "sha512-+sbxb71sWre+PwDK7X2T8+bhS6clcVMLwBPznX45Qu6opJcgRjAp7gYSDzVFp187J+feSj5dNBN1mJoi6ckkUQ==", + "dev": true + }, + "@docsearch/js": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/@docsearch/js/-/js-3.6.0.tgz", + "integrity": "sha512-QujhqINEElrkIfKwyyyTfbsfMAYCkylInLYMRqHy7PHc8xTBQCow73tlo/Kc7oIwBrCLf0P3YhjlOeV4v8hevQ==", + "dev": true, + "requires": { + "@docsearch/react": "3.6.0", + "preact": "^10.0.0" + } + }, + "@docsearch/react": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/@docsearch/react/-/react-3.6.0.tgz", + "integrity": "sha512-HUFut4ztcVNmqy9gp/wxNbC7pTOHhgVVkHVGCACTuLhUKUhKAF9KYHJtMiLUJxEqiFLQiuri1fWF8zqwM/cu1w==", + "dev": true, + "requires": { + "@algolia/autocomplete-core": "1.9.3", + "@algolia/autocomplete-preset-algolia": "1.9.3", + "@docsearch/css": "3.6.0", + "algoliasearch": "^4.19.1" + } + }, + "@esbuild/aix-ppc64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.20.2.tgz", + "integrity": "sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==", + "dev": true, + "optional": true + }, + "@esbuild/android-arm": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.20.2.tgz", + "integrity": "sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w==", + "dev": true, + "optional": true + }, + "@esbuild/android-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.20.2.tgz", + "integrity": "sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg==", + "dev": true, + "optional": true + }, + "@esbuild/android-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.20.2.tgz", + "integrity": "sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==", + "dev": true, + "optional": true + }, + "@esbuild/darwin-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.20.2.tgz", + "integrity": "sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA==", + "dev": true, + "optional": true + }, + "@esbuild/darwin-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.20.2.tgz", + "integrity": "sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA==", + "dev": true, + "optional": true + }, + "@esbuild/freebsd-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.2.tgz", + "integrity": "sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==", + "dev": true, + "optional": true + }, + "@esbuild/freebsd-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.20.2.tgz", + "integrity": "sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw==", + "dev": true, + "optional": true + }, + "@esbuild/linux-arm": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.20.2.tgz", + "integrity": "sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==", + "dev": true, + "optional": true + }, + "@esbuild/linux-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.20.2.tgz", + "integrity": "sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A==", + "dev": true, + "optional": true + }, + "@esbuild/linux-ia32": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.20.2.tgz", + "integrity": "sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==", + "dev": true, + "optional": true + }, + "@esbuild/linux-loong64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.20.2.tgz", + "integrity": "sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ==", + "dev": true, + "optional": true + }, + "@esbuild/linux-mips64el": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.20.2.tgz", + "integrity": "sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA==", + "dev": true, + "optional": true + }, + "@esbuild/linux-ppc64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.20.2.tgz", + "integrity": "sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg==", + "dev": true, + "optional": true + }, + "@esbuild/linux-riscv64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.20.2.tgz", + "integrity": "sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg==", + "dev": true, + "optional": true + }, + "@esbuild/linux-s390x": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.20.2.tgz", + "integrity": "sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ==", + "dev": true, + "optional": true + }, + "@esbuild/linux-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.20.2.tgz", + "integrity": "sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==", + "dev": true, + "optional": true + }, + "@esbuild/netbsd-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.20.2.tgz", + "integrity": "sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==", + "dev": true, + "optional": true + }, + "@esbuild/openbsd-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.20.2.tgz", + "integrity": "sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ==", + "dev": true, + "optional": true + }, + "@esbuild/sunos-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.20.2.tgz", + "integrity": "sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w==", + "dev": true, + "optional": true + }, + "@esbuild/win32-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.20.2.tgz", + "integrity": "sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ==", + "dev": true, + "optional": true + }, + "@esbuild/win32-ia32": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.20.2.tgz", + "integrity": "sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ==", + "dev": true, + "optional": true + }, + "@esbuild/win32-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.20.2.tgz", + "integrity": "sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==", + "dev": true, + "optional": true + }, + "@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "dev": true + }, + "@rollup/rollup-android-arm-eabi": { + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.17.2.tgz", + "integrity": "sha512-NM0jFxY8bB8QLkoKxIQeObCaDlJKewVlIEkuyYKm5An1tdVZ966w2+MPQ2l8LBZLjR+SgyV+nRkTIunzOYBMLQ==", + "dev": true, + "optional": true + }, + "@rollup/rollup-android-arm64": { + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.17.2.tgz", + "integrity": "sha512-yeX/Usk7daNIVwkq2uGoq2BYJKZY1JfyLTaHO/jaiSwi/lsf8fTFoQW/n6IdAsx5tx+iotu2zCJwz8MxI6D/Bw==", + "dev": true, + "optional": true + }, + "@rollup/rollup-darwin-arm64": { + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.17.2.tgz", + "integrity": "sha512-kcMLpE6uCwls023+kknm71ug7MZOrtXo+y5p/tsg6jltpDtgQY1Eq5sGfHcQfb+lfuKwhBmEURDga9N0ol4YPw==", + "dev": true, + "optional": true + }, + "@rollup/rollup-darwin-x64": { + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.17.2.tgz", + "integrity": "sha512-AtKwD0VEx0zWkL0ZjixEkp5tbNLzX+FCqGG1SvOu993HnSz4qDI6S4kGzubrEJAljpVkhRSlg5bzpV//E6ysTQ==", + "dev": true, + "optional": true + }, + "@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.17.2.tgz", + "integrity": "sha512-3reX2fUHqN7sffBNqmEyMQVj/CKhIHZd4y631duy0hZqI8Qoqf6lTtmAKvJFYa6bhU95B1D0WgzHkmTg33In0A==", + "dev": true, + "optional": true + }, + "@rollup/rollup-linux-arm-musleabihf": { + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.17.2.tgz", + "integrity": "sha512-uSqpsp91mheRgw96xtyAGP9FW5ChctTFEoXP0r5FAzj/3ZRv3Uxjtc7taRQSaQM/q85KEKjKsZuiZM3GyUivRg==", + "dev": true, + "optional": true + }, + "@rollup/rollup-linux-arm64-gnu": { + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.17.2.tgz", + "integrity": "sha512-EMMPHkiCRtE8Wdk3Qhtciq6BndLtstqZIroHiiGzB3C5LDJmIZcSzVtLRbwuXuUft1Cnv+9fxuDtDxz3k3EW2A==", + "dev": true, + "optional": true + }, + "@rollup/rollup-linux-arm64-musl": { + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.17.2.tgz", + "integrity": "sha512-NMPylUUZ1i0z/xJUIx6VUhISZDRT+uTWpBcjdv0/zkp7b/bQDF+NfnfdzuTiB1G6HTodgoFa93hp0O1xl+/UbA==", + "dev": true, + "optional": true + }, + "@rollup/rollup-linux-powerpc64le-gnu": { + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.17.2.tgz", + "integrity": "sha512-T19My13y8uYXPw/L/k0JYaX1fJKFT/PWdXiHr8mTbXWxjVF1t+8Xl31DgBBvEKclw+1b00Chg0hxE2O7bTG7GQ==", + "dev": true, + "optional": true + }, + "@rollup/rollup-linux-riscv64-gnu": { + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.17.2.tgz", + "integrity": "sha512-BOaNfthf3X3fOWAB+IJ9kxTgPmMqPPH5f5k2DcCsRrBIbWnaJCgX2ll77dV1TdSy9SaXTR5iDXRL8n7AnoP5cg==", + "dev": true, + "optional": true + }, + "@rollup/rollup-linux-s390x-gnu": { + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.17.2.tgz", + "integrity": "sha512-W0UP/x7bnn3xN2eYMql2T/+wpASLE5SjObXILTMPUBDB/Fg/FxC+gX4nvCfPBCbNhz51C+HcqQp2qQ4u25ok6g==", + "dev": true, + "optional": true + }, + "@rollup/rollup-linux-x64-gnu": { + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.17.2.tgz", + "integrity": "sha512-Hy7pLwByUOuyaFC6mAr7m+oMC+V7qyifzs/nW2OJfC8H4hbCzOX07Ov0VFk/zP3kBsELWNFi7rJtgbKYsav9QQ==", + "dev": true, + "optional": true + }, + "@rollup/rollup-linux-x64-musl": { + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.17.2.tgz", + "integrity": "sha512-h1+yTWeYbRdAyJ/jMiVw0l6fOOm/0D1vNLui9iPuqgRGnXA0u21gAqOyB5iHjlM9MMfNOm9RHCQ7zLIzT0x11Q==", + "dev": true, + "optional": true + }, + "@rollup/rollup-win32-arm64-msvc": { + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.17.2.tgz", + "integrity": "sha512-tmdtXMfKAjy5+IQsVtDiCfqbynAQE/TQRpWdVataHmhMb9DCoJxp9vLcCBjEQWMiUYxO1QprH/HbY9ragCEFLA==", + "dev": true, + "optional": true + }, + "@rollup/rollup-win32-ia32-msvc": { + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.17.2.tgz", + "integrity": "sha512-7II/QCSTAHuE5vdZaQEwJq2ZACkBpQDOmQsE6D6XUbnBHW8IAhm4eTufL6msLJorzrHDFv3CF8oCA/hSIRuZeQ==", + "dev": true, + "optional": true + }, + "@rollup/rollup-win32-x64-msvc": { + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.17.2.tgz", + "integrity": "sha512-TGGO7v7qOq4CYmSBVEYpI1Y5xDuCEnbVC5Vth8mOsW0gDSzxNrVERPc790IGHsrT2dQSimgMr9Ub3Y1Jci5/8w==", + "dev": true, + "optional": true + }, + "@shikijs/core": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-1.4.0.tgz", + "integrity": "sha512-CxpKLntAi64h3j+TwWqVIQObPTED0FyXLHTTh3MKXtqiQNn2JGcMQQ362LftDbc9kYbDtrksNMNoVmVXzKFYUQ==", + "dev": true + }, + "@shikijs/transformers": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@shikijs/transformers/-/transformers-1.4.0.tgz", + "integrity": "sha512-kzvlWmWYYSeaLKRce/kgmFFORUtBtFahfXRKndor0b60ocYiXufBQM6d6w1PlMuUkdk55aor9xLvy9wy7hTEJg==", + "dev": true, + "requires": { + "shiki": "1.4.0" + } + }, + "@types/estree": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", + "dev": true + }, + "@types/linkify-it": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-5.0.0.tgz", + "integrity": "sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==", + "dev": true + }, + "@types/markdown-it": { + "version": "14.1.1", + "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-14.1.1.tgz", + "integrity": "sha512-4NpsnpYl2Gt1ljyBGrKMxFYAYvpqbnnkgP/i/g+NLpjEUa3obn1XJCur9YbEXKDAkaXqsR1LbDnGEJ0MmKFxfg==", + "dev": true, + "requires": { + "@types/linkify-it": "^5", + "@types/mdurl": "^2" + } + }, + "@types/mdurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-2.0.0.tgz", + "integrity": "sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==", + "dev": true + }, + "@types/web-bluetooth": { + "version": "0.0.20", + "resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.20.tgz", + "integrity": "sha512-g9gZnnXVq7gM7v3tJCWV/qw7w+KeOlSHAhgF9RytFyifW6AF61hdT2ucrYhPq9hLs5JIryeupHV3qGk95dH9ow==", + "dev": true + }, + "@vitejs/plugin-vue": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-5.0.4.tgz", + "integrity": "sha512-WS3hevEszI6CEVEx28F8RjTX97k3KsrcY6kvTg7+Whm5y3oYvcqzVeGCU3hxSAn4uY2CLCkeokkGKpoctccilQ==", + "dev": true, + "requires": {} + }, + "@vue/compiler-core": { + "version": "3.4.27", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.4.27.tgz", + "integrity": "sha512-E+RyqY24KnyDXsCuQrI+mlcdW3ALND6U7Gqa/+bVwbcpcR3BRRIckFoz7Qyd4TTlnugtwuI7YgjbvsLmxb+yvg==", + "dev": true, + "requires": { + "@babel/parser": "^7.24.4", + "@vue/shared": "3.4.27", + "entities": "^4.5.0", + "estree-walker": "^2.0.2", + "source-map-js": "^1.2.0" + } + }, + "@vue/compiler-dom": { + "version": "3.4.27", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.4.27.tgz", + "integrity": "sha512-kUTvochG/oVgE1w5ViSr3KUBh9X7CWirebA3bezTbB5ZKBQZwR2Mwj9uoSKRMFcz4gSMzzLXBPD6KpCLb9nvWw==", + "dev": true, + "requires": { + "@vue/compiler-core": "3.4.27", + "@vue/shared": "3.4.27" + } + }, + "@vue/compiler-sfc": { + "version": "3.4.27", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.4.27.tgz", + "integrity": "sha512-nDwntUEADssW8e0rrmE0+OrONwmRlegDA1pD6QhVeXxjIytV03yDqTey9SBDiALsvAd5U4ZrEKbMyVXhX6mCGA==", + "dev": true, + "requires": { + "@babel/parser": "^7.24.4", + "@vue/compiler-core": "3.4.27", + "@vue/compiler-dom": "3.4.27", + "@vue/compiler-ssr": "3.4.27", + "@vue/shared": "3.4.27", + "estree-walker": "^2.0.2", + "magic-string": "^0.30.10", + "postcss": "^8.4.38", + "source-map-js": "^1.2.0" + } + }, + "@vue/compiler-ssr": { + "version": "3.4.27", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.4.27.tgz", + "integrity": "sha512-CVRzSJIltzMG5FcidsW0jKNQnNRYC8bT21VegyMMtHmhW3UOI7knmUehzswXLrExDLE6lQCZdrhD4ogI7c+vuw==", + "dev": true, + "requires": { + "@vue/compiler-dom": "3.4.27", + "@vue/shared": "3.4.27" + } + }, + "@vue/devtools-api": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-7.1.3.tgz", + "integrity": "sha512-W8IwFJ/o5iUk78jpqhvScbgCsPiOp2uileDVC0NDtW38gCWhsnu9SeBTjcdu3lbwLdsjc+H1c5Msd/x9ApbcFA==", + "dev": true, + "requires": { + "@vue/devtools-kit": "^7.1.3" + } + }, + "@vue/devtools-kit": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/@vue/devtools-kit/-/devtools-kit-7.1.3.tgz", + "integrity": "sha512-NFskFSJMVCBXTkByuk2llzI3KD3Blcm7WqiRorWjD6nClHPgkH5BobDH08rfulqq5ocRt5xV+3qOT1Q9FXJrwQ==", + "dev": true, + "requires": { + "@vue/devtools-shared": "^7.1.3", + "hookable": "^5.5.3", + "mitt": "^3.0.1", + "perfect-debounce": "^1.0.0", + "speakingurl": "^14.0.1" + } + }, + "@vue/devtools-shared": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/@vue/devtools-shared/-/devtools-shared-7.1.3.tgz", + "integrity": "sha512-KJ3AfgjTn3tJz/XKF+BlVShNPecim3G21oHRue+YQOsooW+0s+qXvm09U09aO7yBza5SivL1QgxSrzAbiKWjhQ==", + "dev": true, + "requires": { + "rfdc": "^1.3.1" + } + }, + "@vue/reactivity": { + "version": "3.4.27", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.4.27.tgz", + "integrity": "sha512-kK0g4NknW6JX2yySLpsm2jlunZJl2/RJGZ0H9ddHdfBVHcNzxmQ0sS0b09ipmBoQpY8JM2KmUw+a6sO8Zo+zIA==", + "dev": true, + "requires": { + "@vue/shared": "3.4.27" + } + }, + "@vue/runtime-core": { + "version": "3.4.27", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.4.27.tgz", + "integrity": "sha512-7aYA9GEbOOdviqVvcuweTLe5Za4qBZkUY7SvET6vE8kyypxVgaT1ixHLg4urtOlrApdgcdgHoTZCUuTGap/5WA==", + "dev": true, + "requires": { + "@vue/reactivity": "3.4.27", + "@vue/shared": "3.4.27" + } + }, + "@vue/runtime-dom": { + "version": "3.4.27", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.4.27.tgz", + "integrity": "sha512-ScOmP70/3NPM+TW9hvVAz6VWWtZJqkbdf7w6ySsws+EsqtHvkhxaWLecrTorFxsawelM5Ys9FnDEMt6BPBDS0Q==", + "dev": true, + "requires": { + "@vue/runtime-core": "3.4.27", + "@vue/shared": "3.4.27", + "csstype": "^3.1.3" + } + }, + "@vue/server-renderer": { + "version": "3.4.27", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.4.27.tgz", + "integrity": "sha512-dlAMEuvmeA3rJsOMJ2J1kXU7o7pOxgsNHVr9K8hB3ImIkSuBrIdy0vF66h8gf8Tuinf1TK3mPAz2+2sqyf3KzA==", + "dev": true, + "requires": { + "@vue/compiler-ssr": "3.4.27", + "@vue/shared": "3.4.27" + } + }, + "@vue/shared": { + "version": "3.4.27", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.27.tgz", + "integrity": "sha512-DL3NmY2OFlqmYYrzp39yi3LDkKxa5vZVwxWdQ3rG0ekuWscHraeIbnI8t+aZK7qhYqEqWKTUdijadunb9pnrgA==", + "dev": true + }, + "@vueuse/core": { + "version": "10.9.0", + "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-10.9.0.tgz", + "integrity": "sha512-/1vjTol8SXnx6xewDEKfS0Ra//ncg4Hb0DaZiwKf7drgfMsKFExQ+FnnENcN6efPen+1kIzhLQoGSy0eDUVOMg==", + "dev": true, + "requires": { + "@types/web-bluetooth": "^0.0.20", + "@vueuse/metadata": "10.9.0", + "@vueuse/shared": "10.9.0", + "vue-demi": ">=0.14.7" + }, + "dependencies": { + "vue-demi": { + "version": "0.14.7", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.7.tgz", + "integrity": "sha512-EOG8KXDQNwkJILkx/gPcoL/7vH+hORoBaKgGe+6W7VFMvCYJfmF2dGbvgDroVnI8LU7/kTu8mbjRZGBU1z9NTA==", + "dev": true, + "requires": {} + } + } + }, + "@vueuse/integrations": { + "version": "10.9.0", + "resolved": "https://registry.npmjs.org/@vueuse/integrations/-/integrations-10.9.0.tgz", + "integrity": "sha512-acK+A01AYdWSvL4BZmCoJAcyHJ6EqhmkQEXbQLwev1MY7NBnS+hcEMx/BzVoR9zKI+UqEPMD9u6PsyAuiTRT4Q==", + "dev": true, + "requires": { + "@vueuse/core": "10.9.0", + "@vueuse/shared": "10.9.0", + "vue-demi": ">=0.14.7" + }, + "dependencies": { + "vue-demi": { + "version": "0.14.7", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.7.tgz", + "integrity": "sha512-EOG8KXDQNwkJILkx/gPcoL/7vH+hORoBaKgGe+6W7VFMvCYJfmF2dGbvgDroVnI8LU7/kTu8mbjRZGBU1z9NTA==", + "dev": true, + "requires": {} + } + } + }, + "@vueuse/metadata": { + "version": "10.9.0", + "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-10.9.0.tgz", + "integrity": "sha512-iddNbg3yZM0X7qFY2sAotomgdHK7YJ6sKUvQqbvwnf7TmaVPxS4EJydcNsVejNdS8iWCtDk+fYXr7E32nyTnGA==", + "dev": true + }, + "@vueuse/shared": { + "version": "10.9.0", + "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-10.9.0.tgz", + "integrity": "sha512-Uud2IWncmAfJvRaFYzv5OHDli+FbOzxiVEQdLCKQKLyhz94PIyFC3CHcH7EDMwIn8NPtD06+PNbC/PiO0LGLtw==", + "dev": true, + "requires": { + "vue-demi": ">=0.14.7" + }, + "dependencies": { + "vue-demi": { + "version": "0.14.7", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.7.tgz", + "integrity": "sha512-EOG8KXDQNwkJILkx/gPcoL/7vH+hORoBaKgGe+6W7VFMvCYJfmF2dGbvgDroVnI8LU7/kTu8mbjRZGBU1z9NTA==", + "dev": true, + "requires": {} + } + } + }, + "algoliasearch": { + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-4.23.3.tgz", + "integrity": "sha512-Le/3YgNvjW9zxIQMRhUHuhiUjAlKY/zsdZpfq4dlLqg6mEm0nL6yk+7f2hDOtLpxsgE4jSzDmvHL7nXdBp5feg==", + "dev": true, + "requires": { + "@algolia/cache-browser-local-storage": "4.23.3", + "@algolia/cache-common": "4.23.3", + "@algolia/cache-in-memory": "4.23.3", + "@algolia/client-account": "4.23.3", + "@algolia/client-analytics": "4.23.3", + "@algolia/client-common": "4.23.3", + "@algolia/client-personalization": "4.23.3", + "@algolia/client-search": "4.23.3", + "@algolia/logger-common": "4.23.3", + "@algolia/logger-console": "4.23.3", + "@algolia/recommend": "4.23.3", + "@algolia/requester-browser-xhr": "4.23.3", + "@algolia/requester-common": "4.23.3", + "@algolia/requester-node-http": "4.23.3", + "@algolia/transporter": "4.23.3" + } + }, + "csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", + "dev": true + }, + "entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "dev": true + }, + "esbuild": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.2.tgz", + "integrity": "sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==", + "dev": true, + "requires": { + "@esbuild/aix-ppc64": "0.20.2", + "@esbuild/android-arm": "0.20.2", + "@esbuild/android-arm64": "0.20.2", + "@esbuild/android-x64": "0.20.2", + "@esbuild/darwin-arm64": "0.20.2", + "@esbuild/darwin-x64": "0.20.2", + "@esbuild/freebsd-arm64": "0.20.2", + "@esbuild/freebsd-x64": "0.20.2", + "@esbuild/linux-arm": "0.20.2", + "@esbuild/linux-arm64": "0.20.2", + "@esbuild/linux-ia32": "0.20.2", + "@esbuild/linux-loong64": "0.20.2", + "@esbuild/linux-mips64el": "0.20.2", + "@esbuild/linux-ppc64": "0.20.2", + "@esbuild/linux-riscv64": "0.20.2", + "@esbuild/linux-s390x": "0.20.2", + "@esbuild/linux-x64": "0.20.2", + "@esbuild/netbsd-x64": "0.20.2", + "@esbuild/openbsd-x64": "0.20.2", + "@esbuild/sunos-x64": "0.20.2", + "@esbuild/win32-arm64": "0.20.2", + "@esbuild/win32-ia32": "0.20.2", + "@esbuild/win32-x64": "0.20.2" + } + }, + "estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "dev": true + }, + "focus-trap": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/focus-trap/-/focus-trap-7.5.4.tgz", + "integrity": "sha512-N7kHdlgsO/v+iD/dMoJKtsSqs5Dz/dXZVebRgJw23LDk+jMi/974zyiOYDziY2JPp8xivq9BmUGwIJMiuSBi7w==", + "dev": true, + "requires": { + "tabbable": "^6.2.0" + } + }, + "fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "optional": true + }, + "hookable": { + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/hookable/-/hookable-5.5.3.tgz", + "integrity": "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==", + "dev": true + }, + "magic-string": { + "version": "0.30.10", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.10.tgz", + "integrity": "sha512-iIRwTIf0QKV3UAnYK4PU8uiEc4SRh5jX0mwpIwETPpHdhVM4f53RSwS/vXvN1JhGX+Cs7B8qIq3d6AH49O5fAQ==", + "dev": true, + "requires": { + "@jridgewell/sourcemap-codec": "^1.4.15" + } + }, + "mark.js": { + "version": "8.11.1", + "resolved": "https://registry.npmjs.org/mark.js/-/mark.js-8.11.1.tgz", + "integrity": "sha512-1I+1qpDt4idfgLQG+BNWmrqku+7/2bi5nLf4YwF8y8zXvmfiTBY3PV3ZibfrjBueCByROpuBjLLFCajqkgYoLQ==", + "dev": true + }, + "minisearch": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/minisearch/-/minisearch-6.3.0.tgz", + "integrity": "sha512-ihFnidEeU8iXzcVHy74dhkxh/dn8Dc08ERl0xwoMMGqp4+LvRSCgicb+zGqWthVokQKvCSxITlh3P08OzdTYCQ==", + "dev": true + }, + "mitt": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz", + "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==", + "dev": true + }, + "nanoid": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "dev": true + }, + "perfect-debounce": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-1.0.0.tgz", + "integrity": "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==", + "dev": true + }, + "picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, + "postcss": { + "version": "8.4.38", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz", + "integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==", + "dev": true, + "requires": { + "nanoid": "^3.3.7", + "picocolors": "^1.0.0", + "source-map-js": "^1.2.0" + } + }, + "preact": { + "version": "10.21.0", + "resolved": "https://registry.npmjs.org/preact/-/preact-10.21.0.tgz", + "integrity": "sha512-aQAIxtzWEwH8ou+OovWVSVNlFImL7xUCwJX3YMqA3U8iKCNC34999fFOnWjYNsylgfPgMexpbk7WYOLtKr/mxg==", + "dev": true + }, + "rfdc": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.1.tgz", + "integrity": "sha512-r5a3l5HzYlIC68TpmYKlxWjmOP6wiPJ1vWv2HeLhNsRZMrCkxeqxiHlQ21oXmQ4F3SiryXBHhAD7JZqvOJjFmg==", + "dev": true + }, + "rollup": { + "version": "4.17.2", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.17.2.tgz", + "integrity": "sha512-/9ClTJPByC0U4zNLowV1tMBe8yMEAxewtR3cUNX5BoEpGH3dQEWpJLr6CLp0fPdYRF/fzVOgvDb1zXuakwF5kQ==", + "dev": true, + "requires": { + "@rollup/rollup-android-arm-eabi": "4.17.2", + "@rollup/rollup-android-arm64": "4.17.2", + "@rollup/rollup-darwin-arm64": "4.17.2", + "@rollup/rollup-darwin-x64": "4.17.2", + "@rollup/rollup-linux-arm-gnueabihf": "4.17.2", + "@rollup/rollup-linux-arm-musleabihf": "4.17.2", + "@rollup/rollup-linux-arm64-gnu": "4.17.2", + "@rollup/rollup-linux-arm64-musl": "4.17.2", + "@rollup/rollup-linux-powerpc64le-gnu": "4.17.2", + "@rollup/rollup-linux-riscv64-gnu": "4.17.2", + "@rollup/rollup-linux-s390x-gnu": "4.17.2", + "@rollup/rollup-linux-x64-gnu": "4.17.2", + "@rollup/rollup-linux-x64-musl": "4.17.2", + "@rollup/rollup-win32-arm64-msvc": "4.17.2", + "@rollup/rollup-win32-ia32-msvc": "4.17.2", + "@rollup/rollup-win32-x64-msvc": "4.17.2", + "@types/estree": "1.0.5", + "fsevents": "~2.3.2" + } + }, + "search-insights": { + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/search-insights/-/search-insights-2.13.0.tgz", + "integrity": "sha512-Orrsjf9trHHxFRuo9/rzm0KIWmgzE8RMlZMzuhZOJ01Rnz3D0YBAe+V6473t6/H6c7irs6Lt48brULAiRWb3Vw==", + "dev": true, + "peer": true + }, + "shiki": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-1.4.0.tgz", + "integrity": "sha512-5WIn0OL8PWm7JhnTwRWXniy6eEDY234mRrERVlFa646V2ErQqwIFd2UML7e0Pq9eqSKLoMa3Ke+xbsF+DAuy+Q==", + "dev": true, + "requires": { + "@shikijs/core": "1.4.0" + } + }, + "source-map-js": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", + "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", + "dev": true + }, + "speakingurl": { + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/speakingurl/-/speakingurl-14.0.1.tgz", + "integrity": "sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ==", + "dev": true + }, + "tabbable": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.2.0.tgz", + "integrity": "sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==", + "dev": true + }, + "vite": { + "version": "5.2.11", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.2.11.tgz", + "integrity": "sha512-HndV31LWW05i1BLPMUCE1B9E9GFbOu1MbenhS58FuK6owSO5qHm7GiCotrNY1YE5rMeQSFBGmT5ZaLEjFizgiQ==", + "dev": true, + "requires": { + "esbuild": "^0.20.1", + "fsevents": "~2.3.3", + "postcss": "^8.4.38", + "rollup": "^4.13.0" + } + }, + "vitepress": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/vitepress/-/vitepress-1.1.4.tgz", + "integrity": "sha512-bWIzFZXpPB6NIDBuWnS20aMADH+FcFKDfQNYFvbOWij03PR29eImTceQHIzCKordjXYBhM/TjE5VKFTUJ3EheA==", + "dev": true, + "requires": { + "@docsearch/css": "^3.6.0", + "@docsearch/js": "^3.6.0", + "@shikijs/core": "^1.3.0", + "@shikijs/transformers": "^1.3.0", + "@types/markdown-it": "^14.0.1", + "@vitejs/plugin-vue": "^5.0.4", + "@vue/devtools-api": "^7.0.27", + "@vueuse/core": "^10.9.0", + "@vueuse/integrations": "^10.9.0", + "focus-trap": "^7.5.4", + "mark.js": "8.11.1", + "minisearch": "^6.3.0", + "shiki": "^1.3.0", + "vite": "^5.2.10", + "vue": "^3.4.25" + } + }, + "vue": { + "version": "3.4.27", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.4.27.tgz", + "integrity": "sha512-8s/56uK6r01r1icG/aEOHqyMVxd1bkYcSe9j8HcKtr/xTOFWvnzIVTehNW+5Yt89f+DLBe4A569pnZLS5HzAMA==", + "dev": true, + "requires": { + "@vue/compiler-dom": "3.4.27", + "@vue/compiler-sfc": "3.4.27", + "@vue/runtime-dom": "3.4.27", + "@vue/server-renderer": "3.4.27", + "@vue/shared": "3.4.27" + } + } + } +} diff --git a/docs/package.json b/docs/package.json new file mode 100644 index 000000000..5302f861e --- /dev/null +++ b/docs/package.json @@ -0,0 +1,17 @@ +{ + "name": "docs", + "version": "1.0.0", + "description": "Documentation for the D-REC (Distributed Renewable Energy Certificates) platform", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1", + "docs:dev": "vitepress dev", + "docs:build": "vitepress build", + "docs:preview": "vitepress preview" + }, + "author": "", + "license": "ISC", + "devDependencies": { + "vitepress": "^1.1.4" + } +} \ No newline at end of file diff --git a/docs/public/favicon.png b/docs/public/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..38b1c219bae7f1d83311ca52ec271453778a51b8 GIT binary patch literal 14066 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 literal 0 HcmV?d00001 diff --git a/docs/usage_guide/api-user-manual.md b/docs/usage_guide/api-user-manual.md new file mode 100644 index 000000000..e69de29bb diff --git a/docs/usage_guide/buyer-manual.md b/docs/usage_guide/buyer-manual.md new file mode 100644 index 000000000..e69de29bb diff --git a/docs/usage_guide/project-developer-manual.md b/docs/usage_guide/project-developer-manual.md new file mode 100644 index 000000000..e69de29bb From 8855d5a836b88704d3a80494db33b7f5f5ce45df Mon Sep 17 00:00:00 2001 From: Daniel Mohns Date: Wed, 8 May 2024 17:21:46 +0200 Subject: [PATCH 28/89] Add deploy job --- .github/workflows/deploy-gh-pages.yaml | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/.github/workflows/deploy-gh-pages.yaml b/.github/workflows/deploy-gh-pages.yaml index b49731f9b..49ceb43e5 100644 --- a/.github/workflows/deploy-gh-pages.yaml +++ b/.github/workflows/deploy-gh-pages.yaml @@ -26,7 +26,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Setup Pages uses: actions/configure-pages@v2 @@ -36,23 +36,17 @@ jobs: node-version: lts/gallium - name: Install tooling - run: | - npm i -g @microsoft/rush - npm i -g pnpm@6 + working-directory: docs + run: npm install - - name: Install drec-api - working-directory: apps/drec-api - run: | - rush install - - - name: Build docs with compodoc - working-directory: apps/drec-api - run: pnpm run compodoc + - name: Build docs with VitePress + working-directory: docs + run: npm run docs:build - name: Upload artifact uses: actions/upload-pages-artifact@v1 with: - path: apps/drec-api/documentation/ + path: docs/.vitepress/dist/ # Deployment job deploy: From fa218d8d9d438e1b130bd000fd2097bee3809a36 Mon Sep 17 00:00:00 2001 From: Daniel Mohns Date: Wed, 8 May 2024 17:25:37 +0200 Subject: [PATCH 29/89] Update for Github pages --- docs/.vitepress/config.mjs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/docs/.vitepress/config.mjs b/docs/.vitepress/config.mjs index cfaf2d5da..0d76bb6c1 100644 --- a/docs/.vitepress/config.mjs +++ b/docs/.vitepress/config.mjs @@ -5,10 +5,11 @@ export default defineConfig({ title: 'D-REC Docs', description: 'Documentation for the D-REC (Distributed Renewable Energy Certificates) platform', - /* prettier-ignore */ - head: [ - ['link', { rel: 'icon', type: 'image/png', href: 'favicon.png' }], - ], + head: [['link', { rel: 'icon', type: 'image/png', href: 'favicon.png' }]], + + // For hosting on Github pages + // https://vitepress.dev/guide/deploy#github-pages + base: '/drec-origin/', themeConfig: { // https://vitepress.dev/reference/default-theme-config From 7d59e6314587a471f80427f98f976b9c390346a9 Mon Sep 17 00:00:00 2001 From: Daniel Mohns Date: Wed, 8 May 2024 17:36:34 +0200 Subject: [PATCH 30/89] Fix links and deploy options --- docs/.vitepress/config.mjs | 8 ++++++-- docs/index.md | 2 +- docs/{img => public}/D-REC-banner.png | Bin docs/{img => public}/D-REC-logo.png | Bin 4 files changed, 7 insertions(+), 3 deletions(-) rename docs/{img => public}/D-REC-banner.png (100%) rename docs/{img => public}/D-REC-logo.png (100%) diff --git a/docs/.vitepress/config.mjs b/docs/.vitepress/config.mjs index 0d76bb6c1..e0f59930d 100644 --- a/docs/.vitepress/config.mjs +++ b/docs/.vitepress/config.mjs @@ -13,7 +13,7 @@ export default defineConfig({ themeConfig: { // https://vitepress.dev/reference/default-theme-config - logo: 'img/D-REC-banner.png', + logo: '/D-REC-banner.png', nav: [ { text: 'Home', link: '/' }, { text: 'Documentation', link: '/introduction/technology-overview' } @@ -56,6 +56,10 @@ export default defineConfig({ } ], - socialLinks: [{ icon: 'github', link: 'https://github.com/d-rec/drec-origin' }] + socialLinks: [{ icon: 'github', link: 'https://github.com/d-rec/drec-origin' }], + + search: { + provider: 'local' + } } }); diff --git a/docs/index.md b/docs/index.md index 2c63ca78d..c402b367a 100644 --- a/docs/index.md +++ b/docs/index.md @@ -17,7 +17,7 @@ hero: text: D-REC Homepage link: https://drecs.org image: - src: img/D-REC-logo.png + src: /D-REC-logo.png alt: VitePress features: diff --git a/docs/img/D-REC-banner.png b/docs/public/D-REC-banner.png similarity index 100% rename from docs/img/D-REC-banner.png rename to docs/public/D-REC-banner.png diff --git a/docs/img/D-REC-logo.png b/docs/public/D-REC-logo.png similarity index 100% rename from docs/img/D-REC-logo.png rename to docs/public/D-REC-logo.png From b39ebd10b28dc903d854e3777c76c687565a031c Mon Sep 17 00:00:00 2001 From: Daniel Mohns Date: Wed, 8 May 2024 17:46:45 +0200 Subject: [PATCH 31/89] Add API docs and Get Started --- docs/.vitepress/config.mjs | 1 + docs/index.md | 6 +++--- docs/usage_guide/get-started.md | 0 3 files changed, 4 insertions(+), 3 deletions(-) create mode 100644 docs/usage_guide/get-started.md diff --git a/docs/.vitepress/config.mjs b/docs/.vitepress/config.mjs index e0f59930d..990d95ccc 100644 --- a/docs/.vitepress/config.mjs +++ b/docs/.vitepress/config.mjs @@ -38,6 +38,7 @@ export default defineConfig({ { text: 'Usage Guide', items: [ + { text: 'Get Started', link: '/usage_guide/get-started.md' }, { text: 'Buyer Manual', link: '/usage_guide/buyer-manual.md' }, { text: 'Project Developer Manual', diff --git a/docs/index.md b/docs/index.md index c402b367a..541a5120d 100644 --- a/docs/index.md +++ b/docs/index.md @@ -12,10 +12,10 @@ hero: link: /introduction/technology-overview - theme: alt text: Get Started - link: https://drecs.org + link: /usage_guide/get-started - theme: alt - text: D-REC Homepage - link: https://drecs.org + text: API Documentation + link: https://dev-api.drecs.org/swagger/ image: src: /D-REC-logo.png alt: VitePress diff --git a/docs/usage_guide/get-started.md b/docs/usage_guide/get-started.md new file mode 100644 index 000000000..e69de29bb From 3f83ce6c66c38bfe2fbdbfe5695d951ecf5d8425 Mon Sep 17 00:00:00 2001 From: NamrataSweya Date: Fri, 10 May 2024 19:06:56 +0530 Subject: [PATCH 32/89] update new version --- version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version b/version index 4fa9ef0f5..8f2d53630 100755 --- a/version +++ b/version @@ -1 +1 @@ -0.0.109 +0.0.110 From 69146b17cad4f6c071441067560d303be10c03f2 Mon Sep 17 00:00:00 2001 From: Daniel Mohns Date: Sun, 12 May 2024 22:27:06 +0200 Subject: [PATCH 33/89] Simplify Sidebar generation --- docs/.vitepress/config.mjs | 44 +++++--------------- docs/dev_docs/ACL-module.md | 6 ++- docs/dev_docs/developer-onboarding.md | 5 +++ docs/dev_docs/functional-requirements.md | 5 +++ docs/dev_docs/index.md | 5 +++ docs/introduction/dre-project-developers.md | 5 +++ docs/introduction/index.md | 5 +++ docs/introduction/rec-buyers.md | 5 +++ docs/introduction/technology-overview.md | 5 +++ docs/usage_guide/api-user-manual.md | 5 +++ docs/usage_guide/buyer-manual.md | 5 +++ docs/usage_guide/get-started.md | 5 +++ docs/usage_guide/index.md | 5 +++ docs/usage_guide/project-developer-manual.md | 5 +++ 14 files changed, 76 insertions(+), 34 deletions(-) create mode 100644 docs/dev_docs/index.md create mode 100644 docs/introduction/index.md create mode 100644 docs/usage_guide/index.md diff --git a/docs/.vitepress/config.mjs b/docs/.vitepress/config.mjs index 990d95ccc..bf1c8573e 100644 --- a/docs/.vitepress/config.mjs +++ b/docs/.vitepress/config.mjs @@ -1,4 +1,14 @@ import { defineConfig } from 'vitepress'; +import { generateSidebar } from 'vitepress-sidebar'; + +// https://vitepress-sidebar.jooy2.com/getting-started +const vitepressSidebarOptions = { + excludeFilesByFrontmatter: true, + sortMenusByFrontmatterOrder: true, + useFolderTitleFromIndexFile: true, + useTitleFromFileHeading: true, + useTitleFromFrontmatter: true +}; // https://vitepress.dev/reference/site-config export default defineConfig({ @@ -23,39 +33,7 @@ export default defineConfig({ copyright: `Copyright © ${new Date().getFullYear()} D-REC Initiative.` }, - sidebar: [ - { - text: 'Introduction', - items: [ - { text: 'Technology Overview', link: '/introduction/technology-overview' }, - { - text: 'DRE Project Developers', - link: '/introduction/dre-project-developers' - }, - { text: 'REC Buyers', link: '/introduction/rec-buyers' } - ] - }, - { - text: 'Usage Guide', - items: [ - { text: 'Get Started', link: '/usage_guide/get-started.md' }, - { text: 'Buyer Manual', link: '/usage_guide/buyer-manual.md' }, - { - text: 'Project Developer Manual', - link: '/usage_guide/project-developer-manual.md' - }, - { text: 'API User Manual', link: '/usage_guide/api-user-manual' } - ] - }, - { - text: 'Developer Documentation', - items: [ - { text: 'Function Requirements', link: '/dev_docs/functional-requirements' }, - { text: 'Developer Onboarding', link: '/dev_docs/developer-onboarding' }, - { text: 'ACL Module', link: '/dev_docs/ACL-module' } - ] - } - ], + sidebar: generateSidebar(vitepressSidebarOptions), socialLinks: [{ icon: 'github', link: 'https://github.com/d-rec/drec-origin' }], diff --git a/docs/dev_docs/ACL-module.md b/docs/dev_docs/ACL-module.md index e0b71a501..584f88c7f 100644 --- a/docs/dev_docs/ACL-module.md +++ b/docs/dev_docs/ACL-module.md @@ -1 +1,5 @@ -# ACL Module documentation +--- +order: 3 +--- + +# ACL Module diff --git a/docs/dev_docs/developer-onboarding.md b/docs/dev_docs/developer-onboarding.md index e69de29bb..85c8c2f6a 100644 --- a/docs/dev_docs/developer-onboarding.md +++ b/docs/dev_docs/developer-onboarding.md @@ -0,0 +1,5 @@ +--- +order: 2 +--- + +# Developer Onboarding diff --git a/docs/dev_docs/functional-requirements.md b/docs/dev_docs/functional-requirements.md index e69de29bb..183a149b0 100644 --- a/docs/dev_docs/functional-requirements.md +++ b/docs/dev_docs/functional-requirements.md @@ -0,0 +1,5 @@ +--- +order: 1 +--- + +# Functional Requirements diff --git a/docs/dev_docs/index.md b/docs/dev_docs/index.md new file mode 100644 index 000000000..0ec97d1de --- /dev/null +++ b/docs/dev_docs/index.md @@ -0,0 +1,5 @@ +--- +order: 3 +--- + +# Developer Documentation diff --git a/docs/introduction/dre-project-developers.md b/docs/introduction/dre-project-developers.md index e69de29bb..bd7a6ccab 100644 --- a/docs/introduction/dre-project-developers.md +++ b/docs/introduction/dre-project-developers.md @@ -0,0 +1,5 @@ +--- +order: 2 +--- + +# DRE Project Developers diff --git a/docs/introduction/index.md b/docs/introduction/index.md new file mode 100644 index 000000000..9ba38311f --- /dev/null +++ b/docs/introduction/index.md @@ -0,0 +1,5 @@ +--- +order: 1 +--- + +# Introduction diff --git a/docs/introduction/rec-buyers.md b/docs/introduction/rec-buyers.md index e69de29bb..07679da71 100644 --- a/docs/introduction/rec-buyers.md +++ b/docs/introduction/rec-buyers.md @@ -0,0 +1,5 @@ +--- +order: 3 +--- + +# REC Buyers diff --git a/docs/introduction/technology-overview.md b/docs/introduction/technology-overview.md index e69de29bb..65ef0fc7b 100644 --- a/docs/introduction/technology-overview.md +++ b/docs/introduction/technology-overview.md @@ -0,0 +1,5 @@ +--- +order: 1 +--- + +# Technology Overview diff --git a/docs/usage_guide/api-user-manual.md b/docs/usage_guide/api-user-manual.md index e69de29bb..d6017edea 100644 --- a/docs/usage_guide/api-user-manual.md +++ b/docs/usage_guide/api-user-manual.md @@ -0,0 +1,5 @@ +--- +order: 4 +--- + +# API User Manual diff --git a/docs/usage_guide/buyer-manual.md b/docs/usage_guide/buyer-manual.md index e69de29bb..7d409e916 100644 --- a/docs/usage_guide/buyer-manual.md +++ b/docs/usage_guide/buyer-manual.md @@ -0,0 +1,5 @@ +--- +order: 2 +--- + +# Buyer Manual diff --git a/docs/usage_guide/get-started.md b/docs/usage_guide/get-started.md index e69de29bb..ce67f4500 100644 --- a/docs/usage_guide/get-started.md +++ b/docs/usage_guide/get-started.md @@ -0,0 +1,5 @@ +--- +order: 1 +--- + +# Get Started diff --git a/docs/usage_guide/index.md b/docs/usage_guide/index.md new file mode 100644 index 000000000..7c31d4cbe --- /dev/null +++ b/docs/usage_guide/index.md @@ -0,0 +1,5 @@ +--- +order: 2 +--- + +# Usage Guide diff --git a/docs/usage_guide/project-developer-manual.md b/docs/usage_guide/project-developer-manual.md index e69de29bb..171437f80 100644 --- a/docs/usage_guide/project-developer-manual.md +++ b/docs/usage_guide/project-developer-manual.md @@ -0,0 +1,5 @@ +--- +order: 3 +--- + +# Project Developer Manual From 38bea2514159f0b013739a32178b1eb07f2fbde6 Mon Sep 17 00:00:00 2001 From: Daniel Mohns Date: Sun, 12 May 2024 22:27:18 +0200 Subject: [PATCH 34/89] Add deps --- docs/package-lock.json | 212 ++++++++++++++++++++++++++++++++++++++++- docs/package.json | 5 +- 2 files changed, 214 insertions(+), 3 deletions(-) diff --git a/docs/package-lock.json b/docs/package-lock.json index a41d88368..b2971ef67 100644 --- a/docs/package-lock.json +++ b/docs/package-lock.json @@ -9,7 +9,8 @@ "version": "1.0.0", "license": "ISC", "devDependencies": { - "vitepress": "^1.1.4" + "vitepress": "^1.1.4", + "vitepress-sidebar": "^1.22.0" } }, "node_modules/@algolia/autocomplete-core": { @@ -1245,6 +1246,15 @@ "@algolia/transporter": "4.23.3" } }, + "node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, "node_modules/csstype": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", @@ -1301,12 +1311,37 @@ "@esbuild/win32-x64": "0.20.2" } }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/estree-walker": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", "dev": true }, + "node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/focus-trap": { "version": "7.5.4", "resolved": "https://registry.npmjs.org/focus-trap/-/focus-trap-7.5.4.tgz", @@ -1330,12 +1365,58 @@ "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, + "node_modules/gray-matter": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/gray-matter/-/gray-matter-4.0.3.tgz", + "integrity": "sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==", + "dev": true, + "dependencies": { + "js-yaml": "^3.13.1", + "kind-of": "^6.0.2", + "section-matter": "^1.0.0", + "strip-bom-string": "^1.0.0" + }, + "engines": { + "node": ">=6.0" + } + }, "node_modules/hookable": { "version": "5.5.3", "resolved": "https://registry.npmjs.org/hookable/-/hookable-5.5.3.tgz", "integrity": "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==", "dev": true }, + "node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/magic-string": { "version": "0.30.10", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.10.tgz", @@ -1479,6 +1560,19 @@ "dev": true, "peer": true }, + "node_modules/section-matter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/section-matter/-/section-matter-1.0.0.tgz", + "integrity": "sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==", + "dev": true, + "dependencies": { + "extend-shallow": "^2.0.1", + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/shiki": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/shiki/-/shiki-1.4.0.tgz", @@ -1506,6 +1600,21 @@ "node": ">=0.10.0" } }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true + }, + "node_modules/strip-bom-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-1.0.0.tgz", + "integrity": "sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/tabbable": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.2.0.tgz", @@ -1605,6 +1714,18 @@ } } }, + "node_modules/vitepress-sidebar": { + "version": "1.22.0", + "resolved": "https://registry.npmjs.org/vitepress-sidebar/-/vitepress-sidebar-1.22.0.tgz", + "integrity": "sha512-qweTBD1D+KRM2PJA8gHhSE3Nf6yXOdW49MgPm6Hpq/zJUWTEBVmwN3u+wZ8fWInckS5zp254jLjmXxhgBGwlSw==", + "dev": true, + "dependencies": { + "gray-matter": "^4.0.3" + }, + "engines": { + "node": ">=18.0.0" + } + }, "node_modules/vue": { "version": "3.4.27", "resolved": "https://registry.npmjs.org/vue/-/vue-3.4.27.tgz", @@ -2395,6 +2516,15 @@ "@algolia/transporter": "4.23.3" } }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, "csstype": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", @@ -2438,12 +2568,27 @@ "@esbuild/win32-x64": "0.20.2" } }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + }, "estree-walker": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", "dev": true }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, "focus-trap": { "version": "7.5.4", "resolved": "https://registry.npmjs.org/focus-trap/-/focus-trap-7.5.4.tgz", @@ -2460,12 +2605,46 @@ "dev": true, "optional": true }, + "gray-matter": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/gray-matter/-/gray-matter-4.0.3.tgz", + "integrity": "sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==", + "dev": true, + "requires": { + "js-yaml": "^3.13.1", + "kind-of": "^6.0.2", + "section-matter": "^1.0.0", + "strip-bom-string": "^1.0.0" + } + }, "hookable": { "version": "5.5.3", "resolved": "https://registry.npmjs.org/hookable/-/hookable-5.5.3.tgz", "integrity": "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==", "dev": true }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", + "dev": true + }, + "js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true + }, "magic-string": { "version": "0.30.10", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.10.tgz", @@ -2567,6 +2746,16 @@ "dev": true, "peer": true }, + "section-matter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/section-matter/-/section-matter-1.0.0.tgz", + "integrity": "sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "kind-of": "^6.0.0" + } + }, "shiki": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/shiki/-/shiki-1.4.0.tgz", @@ -2588,6 +2777,18 @@ "integrity": "sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ==", "dev": true }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true + }, + "strip-bom-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-1.0.0.tgz", + "integrity": "sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g==", + "dev": true + }, "tabbable": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.2.0.tgz", @@ -2629,6 +2830,15 @@ "vue": "^3.4.25" } }, + "vitepress-sidebar": { + "version": "1.22.0", + "resolved": "https://registry.npmjs.org/vitepress-sidebar/-/vitepress-sidebar-1.22.0.tgz", + "integrity": "sha512-qweTBD1D+KRM2PJA8gHhSE3Nf6yXOdW49MgPm6Hpq/zJUWTEBVmwN3u+wZ8fWInckS5zp254jLjmXxhgBGwlSw==", + "dev": true, + "requires": { + "gray-matter": "^4.0.3" + } + }, "vue": { "version": "3.4.27", "resolved": "https://registry.npmjs.org/vue/-/vue-3.4.27.tgz", diff --git a/docs/package.json b/docs/package.json index 5302f861e..2115b0e46 100644 --- a/docs/package.json +++ b/docs/package.json @@ -12,6 +12,7 @@ "author": "", "license": "ISC", "devDependencies": { - "vitepress": "^1.1.4" + "vitepress": "^1.1.4", + "vitepress-sidebar": "^1.22.0" } -} \ No newline at end of file +} From d23cfec58d363ced78f1a3dfb10e6091c0a329bc Mon Sep 17 00:00:00 2001 From: Aish1990 Date: Mon, 13 May 2024 14:06:40 +0530 Subject: [PATCH 35/89] Added migration file fix --- apps/drec-api/migrations/1715146626520-OldIssuerLog.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/apps/drec-api/migrations/1715146626520-OldIssuerLog.ts b/apps/drec-api/migrations/1715146626520-OldIssuerLog.ts index 5bc50250c..1deac0ac4 100644 --- a/apps/drec-api/migrations/1715146626520-OldIssuerLog.ts +++ b/apps/drec-api/migrations/1715146626520-OldIssuerLog.ts @@ -3,10 +3,10 @@ import { MigrationInterface, QueryRunner } from 'typeorm'; export class OldIssuerLog1715146626520 implements MigrationInterface { public async up(queryRunner: QueryRunner): Promise { await queryRunner.query(` - CREATE TABLE old_issuer_log ( - "id" integer PRIMARY KEY, + CREATE TABLE old_issuer_certificate ( "createdAt" timestamp with time zone NOT NULL DEFAULT now(), "updatedAt" timestamp with time zone NOT NULL DEFAULT now(), + "id" SERIAL NOT NULL, "deviceId" character varying NOT NULL, "generationStartTime" integer NOT NULL, "generationEndTime" integer NOT NULL, @@ -18,7 +18,8 @@ export class OldIssuerLog1715146626520 implements MigrationInterface { "latestCommitment" text, "issuedPrivately" boolean NOT NULL, "blockchainNetId" integer, - "metadata" character varying NOT NULL)`); + "metadata" character varying NOT NULL, + )`); } public async down(queryRunner: QueryRunner): Promise {} From 6aa96c11653e3bd46b611d2b7622c159358cc006 Mon Sep 17 00:00:00 2001 From: Daniel Mohns Date: Mon, 13 May 2024 13:14:46 +0200 Subject: [PATCH 36/89] DR-767 Increase ESLint rule level (#238) --- .github/workflows/check.yml | 7 ++++++- apps/drec-api/.eslintrc.js | 5 ++--- apps/drec-api/package.json | 5 +++-- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index bde5e5bd2..4845d6430 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -53,7 +53,12 @@ jobs: run: | rush install - - name: Run ESLint + - name: Run ESLint (error) + working-directory: apps/drec-api + run: pnpm run lint:error + continue-on-error: true + + - name: Run ESLint (all) working-directory: apps/drec-api run: pnpm run lint continue-on-error: true diff --git a/apps/drec-api/.eslintrc.js b/apps/drec-api/.eslintrc.js index b4227b477..7e0d271eb 100755 --- a/apps/drec-api/.eslintrc.js +++ b/apps/drec-api/.eslintrc.js @@ -7,9 +7,8 @@ module.exports = { }, plugins: ['@typescript-eslint/eslint-plugin'], extends: [ - // Temporarily disable `eslint:recommended` until other lint issues have been fixed - // 'eslint:recommended', - // 'plugin:@typescript-eslint/eslint-recommended', + 'eslint:recommended', + 'plugin:@typescript-eslint/eslint-recommended', 'plugin:@typescript-eslint/recommended', 'prettier', 'prettier/@typescript-eslint', diff --git a/apps/drec-api/package.json b/apps/drec-api/package.json index f7cd36372..19d5b6600 100755 --- a/apps/drec-api/package.json +++ b/apps/drec-api/package.json @@ -21,8 +21,9 @@ "redis:drop": "redis-cli flushall", "prettier": "prettier --check --config-precedence file-override './{src,migrations,test}/**/*'", "prettier:fix": "prettier --write --config-precedence file-override './{src,migrations,test}/**/*'", - "lint": "eslint \"{src,migrations,test}/**/*{.ts,.tsx}\" --no-error-on-unmatched-pattern", - "lint:fix": "eslint \"{src,migrations,test}/**/*{.ts,.tsx}\" --fix --no-error-on-unmatched-pattern", + "lint": "eslint \"{src,migrations,test}/**/*{.ts,.tsx}\"", + "lint:error": "eslint \"{src,migrations,test}/**/*{.ts,.tsx}\" --quiet", + "lint:fix": "eslint \"{src,migrations,test}/**/*{.ts,.tsx}\" --fix", "migrate": "pnpm typeorm:run:issuer && pnpm typeorm:run && pnpm typeorm:run:certificate", "migrate:docker": "pnpm typeorm:run:issuer && node_modules/typeorm/cli.js --config dist/js/ormconfig.js migration:run", "typeorm": "ts-node -r tsconfig-paths/register node_modules/typeorm/cli.js --config ormconfig-dev.ts", From 03dbbc319ff4c387999b75eb3016c0f1ba4214f5 Mon Sep 17 00:00:00 2001 From: Aish1990 Date: Mon, 13 May 2024 18:52:45 +0530 Subject: [PATCH 37/89] Important comment added in the migration file --- apps/drec-api/migrations/1715146626520-OldIssuerLog.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/apps/drec-api/migrations/1715146626520-OldIssuerLog.ts b/apps/drec-api/migrations/1715146626520-OldIssuerLog.ts index 1deac0ac4..fe60be587 100644 --- a/apps/drec-api/migrations/1715146626520-OldIssuerLog.ts +++ b/apps/drec-api/migrations/1715146626520-OldIssuerLog.ts @@ -2,6 +2,9 @@ import { MigrationInterface, QueryRunner } from 'typeorm'; export class OldIssuerLog1715146626520 implements MigrationInterface { public async up(queryRunner: QueryRunner): Promise { + //IMPORTANT NOTE: We have generated this entity to have a backup of our old certificate logs + //generated before upgraded the @energyweb/issuer-api... because the old certificate logs are + //not compatible with newly upgraded issuer-certificates struture.. await queryRunner.query(` CREATE TABLE old_issuer_certificate ( "createdAt" timestamp with time zone NOT NULL DEFAULT now(), From feb104ac0d34fb29af5ed204d6389f5c860acad7 Mon Sep 17 00:00:00 2001 From: Daniel Mohns Date: Mon, 13 May 2024 16:15:48 +0200 Subject: [PATCH 38/89] Add documentation on-boarding (#239) --- docs/{public => .public}/D-REC-banner.png | Bin docs/{public => .public}/D-REC-logo.png | Bin docs/{public => .public}/favicon.png | Bin docs/.vitepress/config.mjs | 4 +++ docs/README.md | 33 ++++++++++++++++++++++ 5 files changed, 37 insertions(+) rename docs/{public => .public}/D-REC-banner.png (100%) rename docs/{public => .public}/D-REC-logo.png (100%) rename docs/{public => .public}/favicon.png (100%) create mode 100644 docs/README.md diff --git a/docs/public/D-REC-banner.png b/docs/.public/D-REC-banner.png similarity index 100% rename from docs/public/D-REC-banner.png rename to docs/.public/D-REC-banner.png diff --git a/docs/public/D-REC-logo.png b/docs/.public/D-REC-logo.png similarity index 100% rename from docs/public/D-REC-logo.png rename to docs/.public/D-REC-logo.png diff --git a/docs/public/favicon.png b/docs/.public/favicon.png similarity index 100% rename from docs/public/favicon.png rename to docs/.public/favicon.png diff --git a/docs/.vitepress/config.mjs b/docs/.vitepress/config.mjs index bf1c8573e..efca03fb4 100644 --- a/docs/.vitepress/config.mjs +++ b/docs/.vitepress/config.mjs @@ -21,6 +21,10 @@ export default defineConfig({ // https://vitepress.dev/guide/deploy#github-pages base: '/drec-origin/', + vite: { + publicDir: '.public' + }, + themeConfig: { // https://vitepress.dev/reference/default-theme-config logo: '/D-REC-banner.png', diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 000000000..32e9c1f38 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,33 @@ +# D-REC Origin Documention + +This D-REC Origin Documention website is built using [VitePress](https://vitepress.dev/), a Vite & Vue Powered Static Site Generator. + +## Pre-requisites + +- [NodeJS](https://nodejs.org/en) + +## Installation + +```sh +cd docs/ +npm install +``` + +## Local Development + +```sh +npm run docs:dev +``` + +Then open [docs](http://localhost:5173/drec-origin/) in a local web browser. +This command starts a local development server and opens up a browser window. Most changes are reflected live without having to restart the server. + +## Deployment + +Deployment is done using Github Actions and does not involve manual steps. +Check out `.github/workflows` folder of the root repository. + +## Further Read + +- [Markdown Features](https://vitepress.dev/guide/markdown) +- [Markdown Front Matter](https://vitepress.dev/guide/frontmatter) From 6a3ba72ccf5bd62c215bd55dcc3b10d18fb0a3ad Mon Sep 17 00:00:00 2001 From: Daniel Mohns Date: Mon, 13 May 2024 16:34:44 +0200 Subject: [PATCH 39/89] Fix docs build (#240) --- docs/.vitepress/config.mjs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/.vitepress/config.mjs b/docs/.vitepress/config.mjs index efca03fb4..cd8cda849 100644 --- a/docs/.vitepress/config.mjs +++ b/docs/.vitepress/config.mjs @@ -3,6 +3,7 @@ import { generateSidebar } from 'vitepress-sidebar'; // https://vitepress-sidebar.jooy2.com/getting-started const vitepressSidebarOptions = { + excludeFiles: 'README.md', excludeFilesByFrontmatter: true, sortMenusByFrontmatterOrder: true, useFolderTitleFromIndexFile: true, @@ -20,10 +21,10 @@ export default defineConfig({ // For hosting on Github pages // https://vitepress.dev/guide/deploy#github-pages base: '/drec-origin/', - vite: { publicDir: '.public' }, + srcExclude: ['README.md'], themeConfig: { // https://vitepress.dev/reference/default-theme-config From 00d095b520dbac7b767a379c6fada3c4ddacc176 Mon Sep 17 00:00:00 2001 From: Daniel Mohns Date: Mon, 13 May 2024 17:18:11 +0200 Subject: [PATCH 40/89] Customise block colors (#242) --- docs/.vitepress/theme/custom.css | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/docs/.vitepress/theme/custom.css b/docs/.vitepress/theme/custom.css index 2c96feb78..6bb308006 100644 --- a/docs/.vitepress/theme/custom.css +++ b/docs/.vitepress/theme/custom.css @@ -48,6 +48,22 @@ --vp-c-brand-2: #c47f2e; --vp-c-brand-3: #eac046; /* --vp-c-brand-soft: var(--vp-c-indigo-soft); */ + + /* Custom block colors inspired by Github colors*/ + --vp-custom-block-info-border: transparent; + --vp-custom-block-info-text: var(--vp-c-text-1); + --vp-custom-block-info-bg: var(--vp-c-indigo-soft); + --vp-custom-block-info-code-bg: var(--vp-c-indigo-soft); + + --vp-custom-block-note-border: transparent; + --vp-custom-block-note-text: var(--vp-c-text-1); + --vp-custom-block-note-bg: var(--vp-c-default-soft); + --vp-custom-block-note-code-bg: var(--vp-c-default-soft); + + --vp-custom-block-tip-border: transparent; + --vp-custom-block-tip-text: var(--vp-c-text-1); + --vp-custom-block-tip-bg: var(--vp-c-green-soft); + --vp-custom-block-tip-code-bg: var(--vp-c-green-soft); } /** From 4a7d233f97f9ebc21376180ecfd5fa29d6e8f2b5 Mon Sep 17 00:00:00 2001 From: Daniel Mohns Date: Tue, 14 May 2024 09:27:51 +0200 Subject: [PATCH 41/89] Add Docusaurus style alert borders (#244) --- docs/.vitepress/theme/custom.css | 88 ++++++++++++++++++++++++++------ 1 file changed, 72 insertions(+), 16 deletions(-) diff --git a/docs/.vitepress/theme/custom.css b/docs/.vitepress/theme/custom.css index 6bb308006..c34a419f8 100644 --- a/docs/.vitepress/theme/custom.css +++ b/docs/.vitepress/theme/custom.css @@ -48,22 +48,6 @@ --vp-c-brand-2: #c47f2e; --vp-c-brand-3: #eac046; /* --vp-c-brand-soft: var(--vp-c-indigo-soft); */ - - /* Custom block colors inspired by Github colors*/ - --vp-custom-block-info-border: transparent; - --vp-custom-block-info-text: var(--vp-c-text-1); - --vp-custom-block-info-bg: var(--vp-c-indigo-soft); - --vp-custom-block-info-code-bg: var(--vp-c-indigo-soft); - - --vp-custom-block-note-border: transparent; - --vp-custom-block-note-text: var(--vp-c-text-1); - --vp-custom-block-note-bg: var(--vp-c-default-soft); - --vp-custom-block-note-code-bg: var(--vp-c-default-soft); - - --vp-custom-block-tip-border: transparent; - --vp-custom-block-tip-text: var(--vp-c-text-1); - --vp-custom-block-tip-bg: var(--vp-c-green-soft); - --vp-custom-block-tip-code-bg: var(--vp-c-green-soft); } /** @@ -84,3 +68,75 @@ ); --vp-home-hero-image-filter: blur(44px); } + +/** + * Component: Custom Block + * -------------------------------------------------------------------------- */ +:root { + /* Custom block colors inspired by Github colors*/ + --vp-custom-block-info-border: transparent; + --vp-custom-block-info-text: var(--vp-c-text-1); + --vp-custom-block-info-bg: var(--vp-c-indigo-soft); + --vp-custom-block-info-code-bg: var(--vp-c-indigo-soft); + + --vp-custom-block-note-border: transparent; + --vp-custom-block-note-text: var(--vp-c-text-1); + --vp-custom-block-note-bg: var(--vp-c-default-soft); + --vp-custom-block-note-code-bg: var(--vp-c-default-soft); + + --vp-custom-block-tip-border: transparent; + --vp-custom-block-tip-text: var(--vp-c-text-1); + --vp-custom-block-tip-bg: var(--vp-c-green-soft); + --vp-custom-block-tip-code-bg: var(--vp-c-green-soft); +} + +/* Docusaurus style borders */ +.custom-block.note { + border: 0px solid; + /* --vp-c-gray-1 is too light*/ + border-color: var(--vp-c-gray-1); + border-left-width: 5px; + box-shadow: var(--vp-shadow-1); +} + +.custom-block.info { + border: 0px solid; + border-color: var(--vp-c-indigo-3); + border-left-width: 5px; + box-shadow: var(--vp-shadow-1); +} + +.custom-block.warning { + border: 0px solid; + border-color: var(--vp-c-yellow-3); + border-left-width: 5px; + box-shadow: var(--vp-shadow-1); +} + +.custom-block.tip { + border: 0px solid; + border-color: var(--vp-c-green-3); + border-left-width: 5px; + box-shadow: var(--vp-shadow-1); +} + +.custom-block.important { + border: 0px solid; + border-color: var(--vp-c-purple-3); + border-left-width: 5px; + box-shadow: var(--vp-shadow-1); +} + +.custom-block.caution { + border: 0px solid; + border-color: var(--vp-c-red-3); + border-left-width: 5px; + box-shadow: var(--vp-shadow-1); +} + +.custom-block.danger { + border: 0px solid; + border-color: var(--vp-c-red-3); + border-left-width: 5px; + box-shadow: var(--vp-shadow-1); +} From 3b5043a296dd0eef67598053b70fe7dff141bbe7 Mon Sep 17 00:00:00 2001 From: Aish1990 Date: Tue, 14 May 2024 16:08:34 +0530 Subject: [PATCH 42/89] version upgrade --- version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version b/version index 8f2d53630..0abba19ec 100755 --- a/version +++ b/version @@ -1 +1 @@ -0.0.110 +0.0.111 From 1ff04079b26f28e2a5cf04378678160080673e3a Mon Sep 17 00:00:00 2001 From: Aish1990 Date: Tue, 14 May 2024 18:00:53 +0530 Subject: [PATCH 43/89] Version upgrade --- version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version b/version index 0abba19ec..16b5f2641 100755 --- a/version +++ b/version @@ -1 +1 @@ -0.0.111 +0.0.112 From 6a5ed22a1ed87afb2a92e5f3d7c2c0745138c50f Mon Sep 17 00:00:00 2001 From: Aish1990 Date: Wed, 15 May 2024 09:11:33 +0530 Subject: [PATCH 44/89] migration files code changes --- .../1658924656241-IntermideatryTableFields.ts | 4 ++- ...1659507181646-DeviceMreterReadTypeField.ts | 4 ++- ...61178024560-DeviceGroupIssueCertificate.ts | 4 ++- ...DeviceGroupNewFieldsForBuyerReservation.ts | 14 ++++++++++- ...70745-CheckcretificatelogforDeviceField.ts | 4 ++- ...-CheckcretificatelogforDeviceGroupField.ts | 4 ++- .../1663219743369-DeviceGroupNewIdField.ts | 5 +++- .../migrations/1663329270791-Sdgbenefit.ts | 4 ++- .../1665143885251-AddNewFieldDeviceLog.ts | 4 ++- ...1665490980305-HistoryIntermideateFirlds.ts | 5 +++- ...1665639446819-History_next_issuance_log.ts | 4 ++- .../1669270905713-delta_firstread.ts | 4 ++- .../1669278431805-delta_firstread.ts | 4 ++- .../1669979907621-Deviceexternalidcitext.ts | 5 +++- .../1671692507995-devicesdgbdatatypechange.ts | 4 ++- .../1673435097445-devicesIdscolumn.ts | 4 ++- .../1676611071793-add_developer_externalId.ts | 5 +++- ...1678690129095-certificateTransactionUID.ts | 6 ++++- .../1681791249032-Secretkeyremove.ts | 6 ++++- .../1681978992039-clean-up-dtofield.ts | 16 +++++++++++- .../migrations/1682658608261-updateTable.ts | 11 +++++++- .../1682659987637-updateColumnvaluinNew.ts | 5 +++- ...683004757319-addReservationActiveCloumn.ts | 6 ++++- .../1683267973604-addDeviceTimezone.ts | 9 ++++++- ...683279891527-renamedeviceIdtoexternalId.ts | 15 ++++++++++- .../1684472228595-updateAndcopyColumn.ts | 25 ++++++++++++++++++- ...1695380379771-api_user_idtableandcolumn.ts | 6 ++++- .../1698645660886-AddColumnDevice.ts | 7 +++++- ...1700980514026-ApiUserIdFieldDeviceGroup.ts | 7 +++++- .../1702494120002-addFieldDeviceCSVFile.ts | 7 +++++- ...93-expiry_date_column_devicegroup_table.ts | 7 +++++- .../1707301134758-user_login_session.ts | 6 ++++- ...708000840858-alterOAuthClientCredential.ts | 14 ++++++++++- ...evice_lateongoingCertificatecycle_table.ts | 7 +++++- .../drec-api/migrations/9999999999999-Seed.ts | 2 +- 35 files changed, 209 insertions(+), 35 deletions(-) diff --git a/apps/drec-api/migrations/1658924656241-IntermideatryTableFields.ts b/apps/drec-api/migrations/1658924656241-IntermideatryTableFields.ts index 57a3bbc5a..e868291fa 100755 --- a/apps/drec-api/migrations/1658924656241-IntermideatryTableFields.ts +++ b/apps/drec-api/migrations/1658924656241-IntermideatryTableFields.ts @@ -21,5 +21,7 @@ export class IntermideatryTableFields1658924656241 ); } - public async down(queryRunner: QueryRunner): Promise {} + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`DROP TABLE IF EXISTS aggregate_meterread`); + } } diff --git a/apps/drec-api/migrations/1659507181646-DeviceMreterReadTypeField.ts b/apps/drec-api/migrations/1659507181646-DeviceMreterReadTypeField.ts index 7ae06584c..20d67eb58 100755 --- a/apps/drec-api/migrations/1659507181646-DeviceMreterReadTypeField.ts +++ b/apps/drec-api/migrations/1659507181646-DeviceMreterReadTypeField.ts @@ -10,5 +10,7 @@ export class DeviceMreterReadTypeField1659507181646 ); } - public async down(queryRunner: QueryRunner): Promise {} + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE "device" DROP COLUMN "meterReadtype"`); + } } diff --git a/apps/drec-api/migrations/1661178024560-DeviceGroupIssueCertificate.ts b/apps/drec-api/migrations/1661178024560-DeviceGroupIssueCertificate.ts index d892d6ba1..81a99027a 100755 --- a/apps/drec-api/migrations/1661178024560-DeviceGroupIssueCertificate.ts +++ b/apps/drec-api/migrations/1661178024560-DeviceGroupIssueCertificate.ts @@ -21,5 +21,7 @@ export class DeviceGroupIssueCertificate1661178024560 ); } - public async down(queryRunner: QueryRunner): Promise {} + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`DROP TABLE IF EXISTS public.next_issuance_date_log_for_device_group`); + } } diff --git a/apps/drec-api/migrations/1661776597766-DeviceGroupNewFieldsForBuyerReservation.ts b/apps/drec-api/migrations/1661776597766-DeviceGroupNewFieldsForBuyerReservation.ts index 156425469..f4a4dd418 100755 --- a/apps/drec-api/migrations/1661776597766-DeviceGroupNewFieldsForBuyerReservation.ts +++ b/apps/drec-api/migrations/1661776597766-DeviceGroupNewFieldsForBuyerReservation.ts @@ -19,5 +19,17 @@ export class DeviceGroupNewFieldsForBuyerReservation1661776597766 `); } - public async down(queryRunner: QueryRunner): Promise {} + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE "device_group" + DROP COLUMN IF EXISTS "frequency", + DROP COLUMN IF EXISTS "reservationStartDate", + DROP COLUMN IF EXISTS "reservationEndDate", + DROP COLUMN IF EXISTS "targetVolumeInMegaWattHour", + DROP COLUMN IF EXISTS "targetVolumeCertificateGenerationRequestedInMegaWattHour", + DROP COLUMN IF EXISTS "targetVolumeCertificateGenerationSucceededInMegaWattHour", + DROP COLUMN IF EXISTS "targetVolumeCertificateGenerationFailedInMegaWattHour", + DROP COLUMN IF EXISTS "authorityToExceed", + DROP COLUMN IF EXISTS "leftoverReadsByCountryCode" + `); + } } diff --git a/apps/drec-api/migrations/1662610170745-CheckcretificatelogforDeviceField.ts b/apps/drec-api/migrations/1662610170745-CheckcretificatelogforDeviceField.ts index 6b72d2d0d..082c51034 100755 --- a/apps/drec-api/migrations/1662610170745-CheckcretificatelogforDeviceField.ts +++ b/apps/drec-api/migrations/1662610170745-CheckcretificatelogforDeviceField.ts @@ -23,5 +23,7 @@ export class CheckcretificatelogforDeviceField1662610170745 ); } - public async down(queryRunner: QueryRunner): Promise {} + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`DROP TABLE IF EXISTS public.check_certificate_issue_date_log_for_device`); + } } diff --git a/apps/drec-api/migrations/1663162320749-CheckcretificatelogforDeviceGroupField.ts b/apps/drec-api/migrations/1663162320749-CheckcretificatelogforDeviceGroupField.ts index 868702463..f3ec20c16 100755 --- a/apps/drec-api/migrations/1663162320749-CheckcretificatelogforDeviceGroupField.ts +++ b/apps/drec-api/migrations/1663162320749-CheckcretificatelogforDeviceGroupField.ts @@ -24,5 +24,7 @@ export class CheckcretificatelogforDeviceGroupField1663162320749 ); } - public async down(queryRunner: QueryRunner): Promise {} + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`DROP TABLE IF EXISTS public.check_certificate_issue_date_log_for_device_group`); + } } diff --git a/apps/drec-api/migrations/1663219743369-DeviceGroupNewIdField.ts b/apps/drec-api/migrations/1663219743369-DeviceGroupNewIdField.ts index 46ad76a49..78aa4f89d 100755 --- a/apps/drec-api/migrations/1663219743369-DeviceGroupNewIdField.ts +++ b/apps/drec-api/migrations/1663219743369-DeviceGroupNewIdField.ts @@ -10,5 +10,8 @@ export class DeviceGroupNewIdField1663219743369 implements MigrationInterface { `); } - public async down(queryRunner: QueryRunner): Promise {} + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE "device_group" DROP COLUMN "devicegroup_uid"`); + await queryRunner.query(`ALTER TABLE "check_certificate_issue_date_log_for_device_group" DROP COLUMN "countryCode"`); + } } diff --git a/apps/drec-api/migrations/1663329270791-Sdgbenefit.ts b/apps/drec-api/migrations/1663329270791-Sdgbenefit.ts index d833e3796..f58869501 100755 --- a/apps/drec-api/migrations/1663329270791-Sdgbenefit.ts +++ b/apps/drec-api/migrations/1663329270791-Sdgbenefit.ts @@ -18,5 +18,7 @@ export class Sdgbenefit1663329270791 implements MigrationInterface { ); } - public async down(queryRunner: QueryRunner): Promise {} + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`DROP TABLE IF EXISTS public.sdgbenefit`); + } } diff --git a/apps/drec-api/migrations/1665143885251-AddNewFieldDeviceLog.ts b/apps/drec-api/migrations/1665143885251-AddNewFieldDeviceLog.ts index 455cb7f27..c3db75ff3 100755 --- a/apps/drec-api/migrations/1665143885251-AddNewFieldDeviceLog.ts +++ b/apps/drec-api/migrations/1665143885251-AddNewFieldDeviceLog.ts @@ -7,5 +7,7 @@ export class AddNewFieldDeviceLog1665143885251 implements MigrationInterface { ADD "groupId" integer`); } - public async down(queryRunner: QueryRunner): Promise {} + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE "check_certificate_issue_date_log_for_device" DROP COLUMN "groupId"`); + } } diff --git a/apps/drec-api/migrations/1665490980305-HistoryIntermideateFirlds.ts b/apps/drec-api/migrations/1665490980305-HistoryIntermideateFirlds.ts index bd70bcd94..679fc5566 100755 --- a/apps/drec-api/migrations/1665490980305-HistoryIntermideateFirlds.ts +++ b/apps/drec-api/migrations/1665490980305-HistoryIntermideateFirlds.ts @@ -30,5 +30,8 @@ export class HistoryIntermideateFirlds1665490980305 ADD "type" character varying`); } - public async down(queryRunner: QueryRunner): Promise {} + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`DROP TABLE IF EXISTS public.history_intermediate_meteread`); + await queryRunner.query(`ALTER TABLE "device_group" DROP COLUMN IF EXISTS "type"`); + } } diff --git a/apps/drec-api/migrations/1665639446819-History_next_issuance_log.ts b/apps/drec-api/migrations/1665639446819-History_next_issuance_log.ts index 7ac39435e..b7a9a8c3b 100755 --- a/apps/drec-api/migrations/1665639446819-History_next_issuance_log.ts +++ b/apps/drec-api/migrations/1665639446819-History_next_issuance_log.ts @@ -20,5 +20,7 @@ export class HistoryNextIssuanceLog1665639446819 implements MigrationInterface { ); } - public async down(queryRunner: QueryRunner): Promise {} + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`DROP TABLE IF EXISTS public.history_next_issuance_log`); + } } diff --git a/apps/drec-api/migrations/1669270905713-delta_firstread.ts b/apps/drec-api/migrations/1669270905713-delta_firstread.ts index ed08271cd..18ced3141 100755 --- a/apps/drec-api/migrations/1669270905713-delta_firstread.ts +++ b/apps/drec-api/migrations/1669270905713-delta_firstread.ts @@ -18,5 +18,7 @@ export class deltaFirstread1669270905713 implements MigrationInterface { ); } - public async down(queryRunner: QueryRunner): Promise {} + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`DROP TABLE IF EXISTS public.delta_firstread`); + } } diff --git a/apps/drec-api/migrations/1669278431805-delta_firstread.ts b/apps/drec-api/migrations/1669278431805-delta_firstread.ts index 1bb7425bd..6e4f0dec5 100755 --- a/apps/drec-api/migrations/1669278431805-delta_firstread.ts +++ b/apps/drec-api/migrations/1669278431805-delta_firstread.ts @@ -18,5 +18,7 @@ export class deltaFirstread1669278431805 implements MigrationInterface { ); } - public async down(queryRunner: QueryRunner): Promise {} + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`DROP TABLE IF EXISTS public.delta_firstread`); + } } diff --git a/apps/drec-api/migrations/1669979907621-Deviceexternalidcitext.ts b/apps/drec-api/migrations/1669979907621-Deviceexternalidcitext.ts index 7534d5a0b..49d4d48e8 100755 --- a/apps/drec-api/migrations/1669979907621-Deviceexternalidcitext.ts +++ b/apps/drec-api/migrations/1669979907621-Deviceexternalidcitext.ts @@ -9,5 +9,8 @@ export class Deviceexternalidcitext1669979907621 implements MigrationInterface { ); } - public async down(queryRunner: QueryRunner): Promise {} + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE "device" ALTER COLUMN "externalId" TYPE varchar`); + await queryRunner.query(`DROP EXTENSION IF EXISTS citext`); + } } diff --git a/apps/drec-api/migrations/1671692507995-devicesdgbdatatypechange.ts b/apps/drec-api/migrations/1671692507995-devicesdgbdatatypechange.ts index 54c480173..7ba4d702e 100755 --- a/apps/drec-api/migrations/1671692507995-devicesdgbdatatypechange.ts +++ b/apps/drec-api/migrations/1671692507995-devicesdgbdatatypechange.ts @@ -10,5 +10,7 @@ export class devicesdgbdatatypechange1671692507995 ); } - public async down(queryRunner: QueryRunner): Promise {} + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE "device" ALTER COLUMN "SDGBenefits" TYPE jsonb`); + } } diff --git a/apps/drec-api/migrations/1673435097445-devicesIdscolumn.ts b/apps/drec-api/migrations/1673435097445-devicesIdscolumn.ts index 1e1119a9b..f64124f27 100755 --- a/apps/drec-api/migrations/1673435097445-devicesIdscolumn.ts +++ b/apps/drec-api/migrations/1673435097445-devicesIdscolumn.ts @@ -8,5 +8,7 @@ export class devicesIdscolumn1673435097445 implements MigrationInterface { ); } - public async down(queryRunner: QueryRunner): Promise {} + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE "device_group" DROP COLUMN "deviceIds"`); + } } diff --git a/apps/drec-api/migrations/1676611071793-add_developer_externalId.ts b/apps/drec-api/migrations/1676611071793-add_developer_externalId.ts index 63ce8a5d4..cc06840b6 100755 --- a/apps/drec-api/migrations/1676611071793-add_developer_externalId.ts +++ b/apps/drec-api/migrations/1676611071793-add_developer_externalId.ts @@ -9,5 +9,8 @@ export class addDeveloperExternalId1676611071793 implements MigrationInterface { ); } - public async down(queryRunner: QueryRunner): Promise {} + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE "device" DROP COLUMN IF EXISTS "developerExternalId"`); + await queryRunner.query(`DROP EXTENSION IF EXISTS citext`); + } } diff --git a/apps/drec-api/migrations/1678690129095-certificateTransactionUID.ts b/apps/drec-api/migrations/1678690129095-certificateTransactionUID.ts index ea0f85f0c..eeaa2b842 100755 --- a/apps/drec-api/migrations/1678690129095-certificateTransactionUID.ts +++ b/apps/drec-api/migrations/1678690129095-certificateTransactionUID.ts @@ -14,5 +14,9 @@ export class certificateTransactionUID1678690129095 ); } - public async down(queryRunner: QueryRunner): Promise {} + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE "check_certificate_issue_date_log_for_device_group" DROP COLUMN IF EXISTS "certificateTransactionUID"`); + await queryRunner.query(`ALTER TABLE "check_certificate_issue_date_log_for_device" DROP COLUMN IF EXISTS "certificateTransactionUID"`); + await queryRunner.query(`DROP EXTENSION IF EXISTS citext`); + } } diff --git a/apps/drec-api/migrations/1681791249032-Secretkeyremove.ts b/apps/drec-api/migrations/1681791249032-Secretkeyremove.ts index 61e4fd19b..bea853bc6 100755 --- a/apps/drec-api/migrations/1681791249032-Secretkeyremove.ts +++ b/apps/drec-api/migrations/1681791249032-Secretkeyremove.ts @@ -8,5 +8,9 @@ export class Secretkeyremove1681791249032 implements MigrationInterface { ); } - public async down(queryRunner: QueryRunner): Promise {} + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "organization" ADD "secretKey" character varying`, + ); + } } diff --git a/apps/drec-api/migrations/1681978992039-clean-up-dtofield.ts b/apps/drec-api/migrations/1681978992039-clean-up-dtofield.ts index 6b6950857..fda5cc483 100755 --- a/apps/drec-api/migrations/1681978992039-clean-up-dtofield.ts +++ b/apps/drec-api/migrations/1681978992039-clean-up-dtofield.ts @@ -18,5 +18,19 @@ export class cleanUpDtofield1681978992039 implements MigrationInterface { ); } - public async down(queryRunner: QueryRunner): Promise {} + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "device" + ADD COLUMN "status" character varying, + ADD COLUMN "data" jsonb, + ADD COLUMN "integrator" character varying`, + ); + await queryRunner.query( + `ALTER TABLE "device_group" + ADD COLUMN "standardCompliance" jsonb, + ADD COLUMN "installationConfigurations" jsonb, + ADD COLUMN "sectors" jsonb, + ADD COLUMN "labels" jsonb`, + ); + } } diff --git a/apps/drec-api/migrations/1682658608261-updateTable.ts b/apps/drec-api/migrations/1682658608261-updateTable.ts index cbf214c5b..b55af85b9 100755 --- a/apps/drec-api/migrations/1682658608261-updateTable.ts +++ b/apps/drec-api/migrations/1682658608261-updateTable.ts @@ -11,5 +11,14 @@ export class updateTable1682658608261 implements MigrationInterface { ); } - public async down(queryRunner: QueryRunner): Promise {} + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `CREATE TABLE "developer_specific_manageGroupDevices_notFor_buyerReservation" ( + -- Define table columns here if needed + )`, + ); + await queryRunner.query( + `ALTER TABLE device_group DROP COLUMN IF EXISTS "deviceIdsInt"`, + ); + } } diff --git a/apps/drec-api/migrations/1682659987637-updateColumnvaluinNew.ts b/apps/drec-api/migrations/1682659987637-updateColumnvaluinNew.ts index 0a5bd2138..997a6c435 100755 --- a/apps/drec-api/migrations/1682659987637-updateColumnvaluinNew.ts +++ b/apps/drec-api/migrations/1682659987637-updateColumnvaluinNew.ts @@ -14,5 +14,8 @@ export class updateColumnvaluinNew1682659987637 implements MigrationInterface { ); } - public async down(queryRunner: QueryRunner): Promise {} + public async down(queryRunner: QueryRunner): Promise { + // Since updating column values in a down migration can lead to data loss or inconsistency, + // and reverting the update operation is complex and risky, leaving the down method empty. + } } diff --git a/apps/drec-api/migrations/1683004757319-addReservationActiveCloumn.ts b/apps/drec-api/migrations/1683004757319-addReservationActiveCloumn.ts index b8375ccf4..b96aa9a19 100755 --- a/apps/drec-api/migrations/1683004757319-addReservationActiveCloumn.ts +++ b/apps/drec-api/migrations/1683004757319-addReservationActiveCloumn.ts @@ -10,5 +10,9 @@ export class addReservationActiveCloumn1683004757319 ); } - public async down(queryRunner: QueryRunner): Promise {} + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "device_group" DROP COLUMN IF EXISTS "reservationActive"`, + ); + } } diff --git a/apps/drec-api/migrations/1683267973604-addDeviceTimezone.ts b/apps/drec-api/migrations/1683267973604-addDeviceTimezone.ts index 1cbb2e092..70fe7b2f4 100755 --- a/apps/drec-api/migrations/1683267973604-addDeviceTimezone.ts +++ b/apps/drec-api/migrations/1683267973604-addDeviceTimezone.ts @@ -11,5 +11,12 @@ export class addDeviceTimezone1683267973604 implements MigrationInterface { ); } - public async down(queryRunner: QueryRunner): Promise {} + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "device" DROP COLUMN IF EXISTS "timezone"`, + ); + await queryRunner.query( + `ALTER TABLE "device" DROP COLUMN IF EXISTS "version"`, + ); + } } diff --git a/apps/drec-api/migrations/1683279891527-renamedeviceIdtoexternalId.ts b/apps/drec-api/migrations/1683279891527-renamedeviceIdtoexternalId.ts index b3355048b..4a5d174e5 100755 --- a/apps/drec-api/migrations/1683279891527-renamedeviceIdtoexternalId.ts +++ b/apps/drec-api/migrations/1683279891527-renamedeviceIdtoexternalId.ts @@ -18,5 +18,18 @@ export class renamedeviceIdtoexternalId1683279891527 ); } - public async down(queryRunner: QueryRunner): Promise {} + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "aggregate_meterread" RENAME COLUMN "externalId" TO "deviceId"`, + ); + await queryRunner.query( + `ALTER TABLE "check_certificate_issue_date_log_for_device" RENAME COLUMN "externalId" TO "deviceid"`, + ); + await queryRunner.query( + `ALTER TABLE "delta_firstread" RENAME COLUMN "externalId" TO "deviceId"`, + ); + await queryRunner.query( + `ALTER TABLE "history_intermediate_meteread" RENAME COLUMN "externalId" TO "deviceId"`, + ); + } } diff --git a/apps/drec-api/migrations/1684472228595-updateAndcopyColumn.ts b/apps/drec-api/migrations/1684472228595-updateAndcopyColumn.ts index 510ea8595..db3adef05 100755 --- a/apps/drec-api/migrations/1684472228595-updateAndcopyColumn.ts +++ b/apps/drec-api/migrations/1684472228595-updateAndcopyColumn.ts @@ -27,5 +27,28 @@ export class updateAndcopyColumn1684472228595 implements MigrationInterface { ); } - public async down(queryRunner: QueryRunner): Promise {} + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE device_group DROP COLUMN "countryCode_new" text[]`, + ); + await queryRunner.query( + `ALTER TABLE device_group ADD COLUMN "countryCode"`, + ); + await queryRunner.query( + `UPDATE device_group SET "countryCode" = ARRAY["countryCode_new"] WHERE "countryCode_new" IS NOT NULL`, + ); + await queryRunner.query( + `ALTER TABLE device_group RENAME COLUMN "countryCode" TO "countryCode_new"`, + ); + await queryRunner.query( + `ALTER TABLE device_group DROP COLUMN "fuelCode_new" text[]`, + ); + await queryRunner.query(`ALTER TABLE device_group ADD COLUMN "fuelCode"`); + await queryRunner.query( + `UPDATE device_group SET "fuelCode" = ARRAY["fuelCode_new"] WHERE "fuelCode_new" IS NOT NULL`, + ); + await queryRunner.query( + `ALTER TABLE device_group RENAME COLUMN "fuelCode" TO "fuelCode_new"`, + ); + } } diff --git a/apps/drec-api/migrations/1695380379771-api_user_idtableandcolumn.ts b/apps/drec-api/migrations/1695380379771-api_user_idtableandcolumn.ts index 2ad070dec..3367df682 100755 --- a/apps/drec-api/migrations/1695380379771-api_user_idtableandcolumn.ts +++ b/apps/drec-api/migrations/1695380379771-api_user_idtableandcolumn.ts @@ -20,5 +20,9 @@ export class apiUserIdtableandcolumn1695380379771 `); } - public async down(queryRunner: QueryRunner): Promise {} + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`DROP TABLE api_user`); + await queryRunner.query(`ALTER TABLE "organization" DROP COLUMN "api_user_id"`); + await queryRunner.query(`ALTER TABLE "user" DROP COLUMN "api_user_id"`); + } } diff --git a/apps/drec-api/migrations/1698645660886-AddColumnDevice.ts b/apps/drec-api/migrations/1698645660886-AddColumnDevice.ts index fbf3a93d1..5deba8615 100644 --- a/apps/drec-api/migrations/1698645660886-AddColumnDevice.ts +++ b/apps/drec-api/migrations/1698645660886-AddColumnDevice.ts @@ -7,5 +7,10 @@ export class AddColumnDevice1698645660886 implements MigrationInterface { `); } - public async down(queryRunner: QueryRunner): Promise {} + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(` + ALTER TABLE "device" + DROP COLUMN "api_user_id" + `); + } } diff --git a/apps/drec-api/migrations/1700980514026-ApiUserIdFieldDeviceGroup.ts b/apps/drec-api/migrations/1700980514026-ApiUserIdFieldDeviceGroup.ts index a02d63bf6..a82a108c4 100644 --- a/apps/drec-api/migrations/1700980514026-ApiUserIdFieldDeviceGroup.ts +++ b/apps/drec-api/migrations/1700980514026-ApiUserIdFieldDeviceGroup.ts @@ -9,5 +9,10 @@ export class ApiUserIdFieldDeviceGroup1700980514026 `); } - public async down(queryRunner: QueryRunner): Promise {} + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(` + ALTER TABLE "device_group" + DROP COLUMN "api_user_id" + `); + } } diff --git a/apps/drec-api/migrations/1702494120002-addFieldDeviceCSVFile.ts b/apps/drec-api/migrations/1702494120002-addFieldDeviceCSVFile.ts index a4c77c478..a0b99fa17 100644 --- a/apps/drec-api/migrations/1702494120002-addFieldDeviceCSVFile.ts +++ b/apps/drec-api/migrations/1702494120002-addFieldDeviceCSVFile.ts @@ -6,5 +6,10 @@ export class addFieldDeviceCSVFile1702494120002 implements MigrationInterface { ADD "api_user_id" uuid DEFAULT NULL`); } - public async down(queryRunner: QueryRunner): Promise {} + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(` + ALTER TABLE "device_csv_file_processing_jobs" + DROP COLUMN "api_user_id" + `); + } } diff --git a/apps/drec-api/migrations/1703838718793-expiry_date_column_devicegroup_table.ts b/apps/drec-api/migrations/1703838718793-expiry_date_column_devicegroup_table.ts index 6f3079dee..d5c192efe 100644 --- a/apps/drec-api/migrations/1703838718793-expiry_date_column_devicegroup_table.ts +++ b/apps/drec-api/migrations/1703838718793-expiry_date_column_devicegroup_table.ts @@ -10,5 +10,10 @@ export class expiryDateColumnDevicegroupTable1703838718793 ); } - public async down(queryRunner: QueryRunner): Promise {} + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(` + ALTER TABLE "device_group" + DROP COLUMN "reservationExpiryDate" + `); + } } diff --git a/apps/drec-api/migrations/1707301134758-user_login_session.ts b/apps/drec-api/migrations/1707301134758-user_login_session.ts index f5b204d23..2f9abddf6 100644 --- a/apps/drec-api/migrations/1707301134758-user_login_session.ts +++ b/apps/drec-api/migrations/1707301134758-user_login_session.ts @@ -15,5 +15,9 @@ export class userLoginSession1707301134758 implements MigrationInterface { `); } - public async down(queryRunner: QueryRunner): Promise {} + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(` + DROP TABLE IF EXISTS user_login_session + `); + } } diff --git a/apps/drec-api/migrations/1708000840858-alterOAuthClientCredential.ts b/apps/drec-api/migrations/1708000840858-alterOAuthClientCredential.ts index 88e02caf2..54d066e1e 100644 --- a/apps/drec-api/migrations/1708000840858-alterOAuthClientCredential.ts +++ b/apps/drec-api/migrations/1708000840858-alterOAuthClientCredential.ts @@ -18,5 +18,17 @@ export class alterOAuthClientCredential1708000840858 ); } - public async down(queryRunner: QueryRunner): Promise {} + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "oauth_client_credentials" ADD COLUMN "client_secret" TEXT`, + ); + await queryRunner.query(`ALTER TABLE "oauth_client_credentials" + DROP CONSTRAINT "UQ_oauth_client_credentials_client_id"`); + + await queryRunner.query(`ALTER TABLE "oauth_client_credentials" + ALTER COLUMN "client_id" DROP NOT NULL`); + + await queryRunner.query(`ALTER TABLE "oauth_client_credentials" + ALTER COLUMN "client_id" TYPE VARCHAR`); + } } diff --git a/apps/drec-api/migrations/1708936214832-device_lateongoingCertificatecycle_table.ts b/apps/drec-api/migrations/1708936214832-device_lateongoingCertificatecycle_table.ts index 7abc32b34..a6e795fb5 100755 --- a/apps/drec-api/migrations/1708936214832-device_lateongoingCertificatecycle_table.ts +++ b/apps/drec-api/migrations/1708936214832-device_lateongoingCertificatecycle_table.ts @@ -20,5 +20,10 @@ export class deviceLateongoingCertificatecycleTable1708936214832 ADD "ongoing_end_date" character varying `); } - public async down(queryRunner: QueryRunner): Promise {} + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`DROP TABLE IF EXISTS device_lateongoing_certificate_cycle`); + await queryRunner.query(`ALTER TABLE "check_certificate_issue_date_log_for_device" + DROP COLUMN IF EXISTS "ongoing_start_date", + DROP COLUMN IF EXISTS "ongoing_end_date"`); + } } diff --git a/apps/drec-api/migrations/9999999999999-Seed.ts b/apps/drec-api/migrations/9999999999999-Seed.ts index a67988bbc..2797ce312 100644 --- a/apps/drec-api/migrations/9999999999999-Seed.ts +++ b/apps/drec-api/migrations/9999999999999-Seed.ts @@ -283,7 +283,7 @@ export class Seed9999999999999 implements MigrationInterface { Delete: false, Update: false, }; - for (var key in addedPermissionList) { + for (let key in addedPermissionList) { aclModule.permissions.map((myArr, index) => { if (myArr === key) { addedPermissionList[key] = true; From 7944e42ec1ddd58a53aff309038c88be322d12d2 Mon Sep 17 00:00:00 2001 From: Aish1990 Date: Wed, 15 May 2024 09:17:14 +0530 Subject: [PATCH 45/89] prettier fix --- .../1661178024560-DeviceGroupIssueCertificate.ts | 4 +++- .../1662610170745-CheckcretificatelogforDeviceField.ts | 4 +++- ...162320749-CheckcretificatelogforDeviceGroupField.ts | 4 +++- .../migrations/1663219743369-DeviceGroupNewIdField.ts | 8 ++++++-- .../migrations/1665143885251-AddNewFieldDeviceLog.ts | 4 +++- .../1665490980305-HistoryIntermideateFirlds.ts | 8 ++++++-- .../1665639446819-History_next_issuance_log.ts | 4 +++- .../migrations/1669979907621-Deviceexternalidcitext.ts | 6 ++++-- .../1671692507995-devicesdgbdatatypechange.ts | 4 +++- .../migrations/1673435097445-devicesIdscolumn.ts | 4 +++- .../1676611071793-add_developer_externalId.ts | 6 ++++-- .../1678690129095-certificateTransactionUID.ts | 10 +++++++--- .../migrations/1681791249032-Secretkeyremove.ts | 2 +- .../1683004757319-addReservationActiveCloumn.ts | 2 +- .../migrations/1683267973604-addDeviceTimezone.ts | 2 +- .../1695380379771-api_user_idtableandcolumn.ts | 8 +++++--- ...6214832-device_lateongoingCertificatecycle_table.ts | 4 +++- 17 files changed, 59 insertions(+), 25 deletions(-) diff --git a/apps/drec-api/migrations/1661178024560-DeviceGroupIssueCertificate.ts b/apps/drec-api/migrations/1661178024560-DeviceGroupIssueCertificate.ts index 81a99027a..b15b9ac50 100755 --- a/apps/drec-api/migrations/1661178024560-DeviceGroupIssueCertificate.ts +++ b/apps/drec-api/migrations/1661178024560-DeviceGroupIssueCertificate.ts @@ -22,6 +22,8 @@ export class DeviceGroupIssueCertificate1661178024560 } public async down(queryRunner: QueryRunner): Promise { - await queryRunner.query(`DROP TABLE IF EXISTS public.next_issuance_date_log_for_device_group`); + await queryRunner.query( + `DROP TABLE IF EXISTS public.next_issuance_date_log_for_device_group`, + ); } } diff --git a/apps/drec-api/migrations/1662610170745-CheckcretificatelogforDeviceField.ts b/apps/drec-api/migrations/1662610170745-CheckcretificatelogforDeviceField.ts index 082c51034..f21108e8c 100755 --- a/apps/drec-api/migrations/1662610170745-CheckcretificatelogforDeviceField.ts +++ b/apps/drec-api/migrations/1662610170745-CheckcretificatelogforDeviceField.ts @@ -24,6 +24,8 @@ export class CheckcretificatelogforDeviceField1662610170745 } public async down(queryRunner: QueryRunner): Promise { - await queryRunner.query(`DROP TABLE IF EXISTS public.check_certificate_issue_date_log_for_device`); + await queryRunner.query( + `DROP TABLE IF EXISTS public.check_certificate_issue_date_log_for_device`, + ); } } diff --git a/apps/drec-api/migrations/1663162320749-CheckcretificatelogforDeviceGroupField.ts b/apps/drec-api/migrations/1663162320749-CheckcretificatelogforDeviceGroupField.ts index f3ec20c16..3ca638d55 100755 --- a/apps/drec-api/migrations/1663162320749-CheckcretificatelogforDeviceGroupField.ts +++ b/apps/drec-api/migrations/1663162320749-CheckcretificatelogforDeviceGroupField.ts @@ -25,6 +25,8 @@ export class CheckcretificatelogforDeviceGroupField1663162320749 } public async down(queryRunner: QueryRunner): Promise { - await queryRunner.query(`DROP TABLE IF EXISTS public.check_certificate_issue_date_log_for_device_group`); + await queryRunner.query( + `DROP TABLE IF EXISTS public.check_certificate_issue_date_log_for_device_group`, + ); } } diff --git a/apps/drec-api/migrations/1663219743369-DeviceGroupNewIdField.ts b/apps/drec-api/migrations/1663219743369-DeviceGroupNewIdField.ts index 78aa4f89d..efe308d6b 100755 --- a/apps/drec-api/migrations/1663219743369-DeviceGroupNewIdField.ts +++ b/apps/drec-api/migrations/1663219743369-DeviceGroupNewIdField.ts @@ -11,7 +11,11 @@ export class DeviceGroupNewIdField1663219743369 implements MigrationInterface { } public async down(queryRunner: QueryRunner): Promise { - await queryRunner.query(`ALTER TABLE "device_group" DROP COLUMN "devicegroup_uid"`); - await queryRunner.query(`ALTER TABLE "check_certificate_issue_date_log_for_device_group" DROP COLUMN "countryCode"`); + await queryRunner.query( + `ALTER TABLE "device_group" DROP COLUMN "devicegroup_uid"`, + ); + await queryRunner.query( + `ALTER TABLE "check_certificate_issue_date_log_for_device_group" DROP COLUMN "countryCode"`, + ); } } diff --git a/apps/drec-api/migrations/1665143885251-AddNewFieldDeviceLog.ts b/apps/drec-api/migrations/1665143885251-AddNewFieldDeviceLog.ts index c3db75ff3..82cfa2d59 100755 --- a/apps/drec-api/migrations/1665143885251-AddNewFieldDeviceLog.ts +++ b/apps/drec-api/migrations/1665143885251-AddNewFieldDeviceLog.ts @@ -8,6 +8,8 @@ export class AddNewFieldDeviceLog1665143885251 implements MigrationInterface { } public async down(queryRunner: QueryRunner): Promise { - await queryRunner.query(`ALTER TABLE "check_certificate_issue_date_log_for_device" DROP COLUMN "groupId"`); + await queryRunner.query( + `ALTER TABLE "check_certificate_issue_date_log_for_device" DROP COLUMN "groupId"`, + ); } } diff --git a/apps/drec-api/migrations/1665490980305-HistoryIntermideateFirlds.ts b/apps/drec-api/migrations/1665490980305-HistoryIntermideateFirlds.ts index 679fc5566..68acfcf18 100755 --- a/apps/drec-api/migrations/1665490980305-HistoryIntermideateFirlds.ts +++ b/apps/drec-api/migrations/1665490980305-HistoryIntermideateFirlds.ts @@ -31,7 +31,11 @@ export class HistoryIntermideateFirlds1665490980305 } public async down(queryRunner: QueryRunner): Promise { - await queryRunner.query(`DROP TABLE IF EXISTS public.history_intermediate_meteread`); - await queryRunner.query(`ALTER TABLE "device_group" DROP COLUMN IF EXISTS "type"`); + await queryRunner.query( + `DROP TABLE IF EXISTS public.history_intermediate_meteread`, + ); + await queryRunner.query( + `ALTER TABLE "device_group" DROP COLUMN IF EXISTS "type"`, + ); } } diff --git a/apps/drec-api/migrations/1665639446819-History_next_issuance_log.ts b/apps/drec-api/migrations/1665639446819-History_next_issuance_log.ts index b7a9a8c3b..083583cf8 100755 --- a/apps/drec-api/migrations/1665639446819-History_next_issuance_log.ts +++ b/apps/drec-api/migrations/1665639446819-History_next_issuance_log.ts @@ -21,6 +21,8 @@ export class HistoryNextIssuanceLog1665639446819 implements MigrationInterface { } public async down(queryRunner: QueryRunner): Promise { - await queryRunner.query(`DROP TABLE IF EXISTS public.history_next_issuance_log`); + await queryRunner.query( + `DROP TABLE IF EXISTS public.history_next_issuance_log`, + ); } } diff --git a/apps/drec-api/migrations/1669979907621-Deviceexternalidcitext.ts b/apps/drec-api/migrations/1669979907621-Deviceexternalidcitext.ts index 49d4d48e8..c26449988 100755 --- a/apps/drec-api/migrations/1669979907621-Deviceexternalidcitext.ts +++ b/apps/drec-api/migrations/1669979907621-Deviceexternalidcitext.ts @@ -10,7 +10,9 @@ export class Deviceexternalidcitext1669979907621 implements MigrationInterface { } public async down(queryRunner: QueryRunner): Promise { - await queryRunner.query(`ALTER TABLE "device" ALTER COLUMN "externalId" TYPE varchar`); - await queryRunner.query(`DROP EXTENSION IF EXISTS citext`); + await queryRunner.query( + `ALTER TABLE "device" ALTER COLUMN "externalId" TYPE varchar`, + ); + await queryRunner.query(`DROP EXTENSION IF EXISTS citext`); } } diff --git a/apps/drec-api/migrations/1671692507995-devicesdgbdatatypechange.ts b/apps/drec-api/migrations/1671692507995-devicesdgbdatatypechange.ts index 7ba4d702e..347ad517b 100755 --- a/apps/drec-api/migrations/1671692507995-devicesdgbdatatypechange.ts +++ b/apps/drec-api/migrations/1671692507995-devicesdgbdatatypechange.ts @@ -11,6 +11,8 @@ export class devicesdgbdatatypechange1671692507995 } public async down(queryRunner: QueryRunner): Promise { - await queryRunner.query(`ALTER TABLE "device" ALTER COLUMN "SDGBenefits" TYPE jsonb`); + await queryRunner.query( + `ALTER TABLE "device" ALTER COLUMN "SDGBenefits" TYPE jsonb`, + ); } } diff --git a/apps/drec-api/migrations/1673435097445-devicesIdscolumn.ts b/apps/drec-api/migrations/1673435097445-devicesIdscolumn.ts index f64124f27..c224aaef3 100755 --- a/apps/drec-api/migrations/1673435097445-devicesIdscolumn.ts +++ b/apps/drec-api/migrations/1673435097445-devicesIdscolumn.ts @@ -9,6 +9,8 @@ export class devicesIdscolumn1673435097445 implements MigrationInterface { } public async down(queryRunner: QueryRunner): Promise { - await queryRunner.query(`ALTER TABLE "device_group" DROP COLUMN "deviceIds"`); + await queryRunner.query( + `ALTER TABLE "device_group" DROP COLUMN "deviceIds"`, + ); } } diff --git a/apps/drec-api/migrations/1676611071793-add_developer_externalId.ts b/apps/drec-api/migrations/1676611071793-add_developer_externalId.ts index cc06840b6..c93bfe955 100755 --- a/apps/drec-api/migrations/1676611071793-add_developer_externalId.ts +++ b/apps/drec-api/migrations/1676611071793-add_developer_externalId.ts @@ -10,7 +10,9 @@ export class addDeveloperExternalId1676611071793 implements MigrationInterface { } public async down(queryRunner: QueryRunner): Promise { - await queryRunner.query(`ALTER TABLE "device" DROP COLUMN IF EXISTS "developerExternalId"`); - await queryRunner.query(`DROP EXTENSION IF EXISTS citext`); + await queryRunner.query( + `ALTER TABLE "device" DROP COLUMN IF EXISTS "developerExternalId"`, + ); + await queryRunner.query(`DROP EXTENSION IF EXISTS citext`); } } diff --git a/apps/drec-api/migrations/1678690129095-certificateTransactionUID.ts b/apps/drec-api/migrations/1678690129095-certificateTransactionUID.ts index eeaa2b842..67cbc8b8d 100755 --- a/apps/drec-api/migrations/1678690129095-certificateTransactionUID.ts +++ b/apps/drec-api/migrations/1678690129095-certificateTransactionUID.ts @@ -15,8 +15,12 @@ export class certificateTransactionUID1678690129095 } public async down(queryRunner: QueryRunner): Promise { - await queryRunner.query(`ALTER TABLE "check_certificate_issue_date_log_for_device_group" DROP COLUMN IF EXISTS "certificateTransactionUID"`); - await queryRunner.query(`ALTER TABLE "check_certificate_issue_date_log_for_device" DROP COLUMN IF EXISTS "certificateTransactionUID"`); - await queryRunner.query(`DROP EXTENSION IF EXISTS citext`); + await queryRunner.query( + `ALTER TABLE "check_certificate_issue_date_log_for_device_group" DROP COLUMN IF EXISTS "certificateTransactionUID"`, + ); + await queryRunner.query( + `ALTER TABLE "check_certificate_issue_date_log_for_device" DROP COLUMN IF EXISTS "certificateTransactionUID"`, + ); + await queryRunner.query(`DROP EXTENSION IF EXISTS citext`); } } diff --git a/apps/drec-api/migrations/1681791249032-Secretkeyremove.ts b/apps/drec-api/migrations/1681791249032-Secretkeyremove.ts index bea853bc6..3e454a5a7 100755 --- a/apps/drec-api/migrations/1681791249032-Secretkeyremove.ts +++ b/apps/drec-api/migrations/1681791249032-Secretkeyremove.ts @@ -11,6 +11,6 @@ export class Secretkeyremove1681791249032 implements MigrationInterface { public async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "organization" ADD "secretKey" character varying`, - ); + ); } } diff --git a/apps/drec-api/migrations/1683004757319-addReservationActiveCloumn.ts b/apps/drec-api/migrations/1683004757319-addReservationActiveCloumn.ts index b96aa9a19..80c80c54b 100755 --- a/apps/drec-api/migrations/1683004757319-addReservationActiveCloumn.ts +++ b/apps/drec-api/migrations/1683004757319-addReservationActiveCloumn.ts @@ -13,6 +13,6 @@ export class addReservationActiveCloumn1683004757319 public async down(queryRunner: QueryRunner): Promise { await queryRunner.query( `ALTER TABLE "device_group" DROP COLUMN IF EXISTS "reservationActive"`, - ); + ); } } diff --git a/apps/drec-api/migrations/1683267973604-addDeviceTimezone.ts b/apps/drec-api/migrations/1683267973604-addDeviceTimezone.ts index 70fe7b2f4..0fd762de2 100755 --- a/apps/drec-api/migrations/1683267973604-addDeviceTimezone.ts +++ b/apps/drec-api/migrations/1683267973604-addDeviceTimezone.ts @@ -17,6 +17,6 @@ export class addDeviceTimezone1683267973604 implements MigrationInterface { ); await queryRunner.query( `ALTER TABLE "device" DROP COLUMN IF EXISTS "version"`, - ); + ); } } diff --git a/apps/drec-api/migrations/1695380379771-api_user_idtableandcolumn.ts b/apps/drec-api/migrations/1695380379771-api_user_idtableandcolumn.ts index 3367df682..e5f7c2ac1 100755 --- a/apps/drec-api/migrations/1695380379771-api_user_idtableandcolumn.ts +++ b/apps/drec-api/migrations/1695380379771-api_user_idtableandcolumn.ts @@ -21,8 +21,10 @@ export class apiUserIdtableandcolumn1695380379771 } public async down(queryRunner: QueryRunner): Promise { - await queryRunner.query(`DROP TABLE api_user`); - await queryRunner.query(`ALTER TABLE "organization" DROP COLUMN "api_user_id"`); - await queryRunner.query(`ALTER TABLE "user" DROP COLUMN "api_user_id"`); + await queryRunner.query(`DROP TABLE api_user`); + await queryRunner.query( + `ALTER TABLE "organization" DROP COLUMN "api_user_id"`, + ); + await queryRunner.query(`ALTER TABLE "user" DROP COLUMN "api_user_id"`); } } diff --git a/apps/drec-api/migrations/1708936214832-device_lateongoingCertificatecycle_table.ts b/apps/drec-api/migrations/1708936214832-device_lateongoingCertificatecycle_table.ts index a6e795fb5..e08b46221 100755 --- a/apps/drec-api/migrations/1708936214832-device_lateongoingCertificatecycle_table.ts +++ b/apps/drec-api/migrations/1708936214832-device_lateongoingCertificatecycle_table.ts @@ -21,7 +21,9 @@ export class deviceLateongoingCertificatecycleTable1708936214832 } public async down(queryRunner: QueryRunner): Promise { - await queryRunner.query(`DROP TABLE IF EXISTS device_lateongoing_certificate_cycle`); + await queryRunner.query( + `DROP TABLE IF EXISTS device_lateongoing_certificate_cycle`, + ); await queryRunner.query(`ALTER TABLE "check_certificate_issue_date_log_for_device" DROP COLUMN IF EXISTS "ongoing_start_date", DROP COLUMN IF EXISTS "ongoing_end_date"`); From b47d02c0068e7e0946a213e2611c64895ccbd60a Mon Sep 17 00:00:00 2001 From: Aish1990 Date: Wed, 15 May 2024 10:29:05 +0530 Subject: [PATCH 46/89] migration seed file fix --- apps/drec-api/migrations/9999999999999-Seed.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/drec-api/migrations/9999999999999-Seed.ts b/apps/drec-api/migrations/9999999999999-Seed.ts index 2797ce312..b875d30a1 100644 --- a/apps/drec-api/migrations/9999999999999-Seed.ts +++ b/apps/drec-api/migrations/9999999999999-Seed.ts @@ -283,7 +283,7 @@ export class Seed9999999999999 implements MigrationInterface { Delete: false, Update: false, }; - for (let key in addedPermissionList) { + for (const key in addedPermissionList) { aclModule.permissions.map((myArr, index) => { if (myArr === key) { addedPermissionList[key] = true; From a40fdbebb5605605604ae106d81c3d459dba1688 Mon Sep 17 00:00:00 2001 From: Aish1990 Date: Wed, 15 May 2024 12:26:41 +0530 Subject: [PATCH 47/89] code changes in aclservice --- .../access-control-layer-module-service.service.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/drec-api/src/pods/access-control-layer-module-service/access-control-layer-module-service.service.ts b/apps/drec-api/src/pods/access-control-layer-module-service/access-control-layer-module-service.service.ts index b233efe3e..9ecbcdf55 100755 --- a/apps/drec-api/src/pods/access-control-layer-module-service/access-control-layer-module-service.service.ts +++ b/apps/drec-api/src/pods/access-control-layer-module-service/access-control-layer-module-service.service.ts @@ -36,7 +36,7 @@ export class AccessControlLayerModuleServiceService { Delete: false, Update: false, }; - for (var key in addedPermissionList) { + for (const key in addedPermissionList) { data.permissions.map((myArr, index) => { if (myArr === key) { addedPermissionList[key] = true; @@ -110,7 +110,7 @@ export class AccessControlLayerModuleServiceService { Delete: false, Update: false, }; - for (var key in addedPermissionList) { + for (const key in addedPermissionList) { data.permissions.map((myArr, index) => { if (myArr === key) { addedPermissionList[key] = true; From 9d4f1b617ac9bb3564fd58e94fdcc6ee160eded9 Mon Sep 17 00:00:00 2001 From: Aish1990 Date: Wed, 15 May 2024 13:42:40 +0530 Subject: [PATCH 48/89] Insert query change in seed file due to the difference in entity stucture when issuer-api version upgraded --- apps/drec-api/migrations/9999999999999-Seed.ts | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/apps/drec-api/migrations/9999999999999-Seed.ts b/apps/drec-api/migrations/9999999999999-Seed.ts index a67988bbc..fedbcb92d 100644 --- a/apps/drec-api/migrations/9999999999999-Seed.ts +++ b/apps/drec-api/migrations/9999999999999-Seed.ts @@ -83,13 +83,17 @@ export class Seed9999999999999 implements MigrationInterface { if (provider && contractsLookup) { await queryRunner.query( - `INSERT INTO public.issuer_blockchain_properties ("netId", "registry", "issuer", "rpcNode", "rpcNodeFallback", "platformOperatorPrivateKey") VALUES (${ + `INSERT INTO public.issuer_blockchain_properties ("netId", "registry", "issuer", "rpcNode", "rpcNodeFallback") VALUES (${ provider.network.chainId }, '${contractsLookup.registry}', '${ contractsLookup.issuer - }', '${primaryRpc}', '${fallbackRpc ?? ''}', '${ - issuerAccount.privateKey - }')`, + }', '${primaryRpc}', '${fallbackRpc ?? ''}' + )`, + ); + + await queryRunner.query( + `INSERT INTO public.issuer_signer ("blockchainNetId", "platformOperatorPrivateKey", "isEncrypted") VALUES (${provider.network.chainId}, '${issuerAccount.privateKey}', false + )`, ); } From 093ef9e887a8d44baedc5903f2625e531877a3df Mon Sep 17 00:00:00 2001 From: Aish1990 Date: Wed, 15 May 2024 14:44:06 +0530 Subject: [PATCH 49/89] changes in certificate-log-controller --- .../src/pods/certificate-log/certificate-log.controller.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/drec-api/src/pods/certificate-log/certificate-log.controller.ts b/apps/drec-api/src/pods/certificate-log/certificate-log.controller.ts index 96d6f2534..ea9642f97 100755 --- a/apps/drec-api/src/pods/certificate-log/certificate-log.controller.ts +++ b/apps/drec-api/src/pods/certificate-log/certificate-log.controller.ts @@ -120,7 +120,7 @@ export class CertificateLogController { @Query(ValidationPipe) filterDto: GroupIDBasedFilteringDTO, ): Promise { this.logger.verbose(`With in getByGroupId`); - if (parseInt(filterDto.groupId) === NaN) { + if (isNaN(parseInt(filterDto.groupId))) { this.logger.error(`Group Id is a number, invalid value was sent`); return new Promise((resolve, reject) => { reject( From d940610cbf7158d95a792e6ac49c07ccca914825 Mon Sep 17 00:00:00 2001 From: Aish1990 Date: Wed, 15 May 2024 19:03:18 +0530 Subject: [PATCH 50/89] ESLINT: code changes fixed in certificateLogService,BuyerReservationController --- .../src/pods/certificate-log/certificate-log.service.ts | 2 +- .../src/pods/device-group/buyer-reservation.controller.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/drec-api/src/pods/certificate-log/certificate-log.service.ts b/apps/drec-api/src/pods/certificate-log/certificate-log.service.ts index bb52e4211..052a3846d 100755 --- a/apps/drec-api/src/pods/certificate-log/certificate-log.service.ts +++ b/apps/drec-api/src/pods/certificate-log/certificate-log.service.ts @@ -100,7 +100,7 @@ export class CertificateLogService { if (pageNumber === undefined || pageNumber === null) { pageNumber = 1; } - let page = pageNumber; // Specify the page number you want to retrieve + const page = pageNumber; // Specify the page number you want to retrieve const itemsPerPage = 20; // Specify the number of items per page const [certifiedreservation, total] = diff --git a/apps/drec-api/src/pods/device-group/buyer-reservation.controller.ts b/apps/drec-api/src/pods/device-group/buyer-reservation.controller.ts index 1b20d55c4..a9c617ab8 100644 --- a/apps/drec-api/src/pods/device-group/buyer-reservation.controller.ts +++ b/apps/drec-api/src/pods/device-group/buyer-reservation.controller.ts @@ -408,7 +408,7 @@ export class BuyerReservationController { if ( isNaN(deviceGroupToRegister.targetCapacityInMegaWattHour) || deviceGroupToRegister.targetCapacityInMegaWattHour <= 0 || - deviceGroupToRegister.targetCapacityInMegaWattHour == -0 + deviceGroupToRegister.targetCapacityInMegaWattHour === -0 ) { this.logger.error( `targetCapacityInMegaWattHour should be valid number can include decimal but should be greater than 0`, From ce6cdeb6fafec250900b96c2a711440fbc94de4e Mon Sep 17 00:00:00 2001 From: Aish1990 Date: Wed, 15 May 2024 19:22:23 +0530 Subject: [PATCH 51/89] Updated pnpm-locke file for Pnpm version upgrade --- common/config/rush/pnpm-lock.yaml | 409 +++++++++++++++--------------- 1 file changed, 199 insertions(+), 210 deletions(-) diff --git a/common/config/rush/pnpm-lock.yaml b/common/config/rush/pnpm-lock.yaml index f65c5d227..ae6c597d7 100644 --- a/common/config/rush/pnpm-lock.yaml +++ b/common/config/rush/pnpm-lock.yaml @@ -1,4 +1,4 @@ -lockfileVersion: 5.3 +lockfileVersion: 5.4 specifiers: '@compodoc/compodoc': ^1.1.22 @@ -125,13 +125,13 @@ specifiers: dependencies: '@compodoc/compodoc': 1.1.22_typescript@4.1.3 - '@energyweb/energy-api-influxdb': 0.8.3_ecb5cc502df3a2ec088b43091bdea01d + '@energyweb/energy-api-influxdb': 0.8.3_5s24yubn6oroycelimerxxvadu '@energyweb/issuer': 6.0.2-alpha.1646058469.0 - '@energyweb/issuer-api': 0.6.2-alpha.1646058469.0_9c842d4fc4d476aa587d8ada10de896e - '@energyweb/origin-247-certificate': 4.1.5_802429b3c4725e564012d632dc79ab7f + '@energyweb/issuer-api': 0.6.2-alpha.1646058469.0_tscc2t6e2r3kuwd5rlnbbxujny + '@energyweb/origin-247-certificate': 4.1.5_qasctm6eojpfmqas2yzny6nlp4 '@energyweb/origin-backend': 11.0.2-alpha.1634225870.0_swagger-ui-express@4.1.6 '@energyweb/origin-backend-core': 8.0.4-alpha.1634225870.0 - '@energyweb/origin-backend-utils': 1.6.2-alpha.1634225870.0_2a17c88284d8d688902b984a9679d264 + '@energyweb/origin-backend-utils': 1.6.2-alpha.1634225870.0_fil4raue3dlirebltbfjm6osmq '@energyweb/utils-general': 11.0.5-alpha.1634225870.0 '@ethersproject/abi': 5.3.1 '@ethersproject/abstract-provider': 5.3.0 @@ -142,21 +142,21 @@ dependencies: '@ethersproject/wallet': 5.3.0 '@influxdata/influxdb-client': 1.9.0 '@mapbox/timespace': 2.0.4 - '@nestjs-modules/mailer': 1.9.1_ce851543783f0b1ad29d2f4cf992494a - '@nestjs/axios': 0.0.8_3933966b9561a99a78287997461c7d33 - '@nestjs/bull': 0.4.2_9569caea4829e1e6a54e03a46e955ce7 + '@nestjs-modules/mailer': 1.9.1_z2crkq3yh4frvuu5f5gptesjji + '@nestjs/axios': 0.0.8_hezzm24vmguzu6bipglumhd5gm + '@nestjs/bull': 0.4.2_svu4v2sifhq6njkoaosg5fk444 '@nestjs/cli': 7.5.4_uglify-js@2.6.0 - '@nestjs/common': 8.1.1_2740f8938661f2cae724ea514b5f5851 - '@nestjs/config': 1.0.1_3933966b9561a99a78287997461c7d33 - '@nestjs/core': 8.1.1_8d2cb968665aca547518d0a2ac09c447 - '@nestjs/cqrs': 8.0.0_dae37da4bb6dfb5aedde8e4363b0927b + '@nestjs/common': 8.1.1_e5apre4gmhzmvzze5jiuwx2yke + '@nestjs/config': 1.0.1_hezzm24vmguzu6bipglumhd5gm + '@nestjs/core': 8.1.1_ruwls2dgllffi5iy2crkycoei4 + '@nestjs/cqrs': 8.0.0_3lrx3jf3nx5vv3o6rzbwhmespm '@nestjs/jwt': 8.0.0_@nestjs+common@8.1.1 - '@nestjs/passport': 8.0.1_657ee20e3f09dafcc3e7bc216f04f9ef - '@nestjs/platform-express': 8.1.1_9569caea4829e1e6a54e03a46e955ce7 - '@nestjs/schedule': 1.0.1_ca8a8c4fec30006bad441fa41a3f81c3 - '@nestjs/swagger': 5.2.1_b8f974227d6d1a64d7a7c786b02f817e - '@nestjs/testing': 8.1.1_89e103a9c7054b932bde2e86d9ce498a - '@nestjs/typeorm': 8.0.2_85f7579bf0bba64591092ed7ff32bf76 + '@nestjs/passport': 8.0.1_mv7oedr7bhnpzq7hxqqw6bhz54 + '@nestjs/platform-express': 8.1.1_svu4v2sifhq6njkoaosg5fk444 + '@nestjs/schedule': 1.0.1_zkfiyt7mgaagxlked6sbup4bym + '@nestjs/swagger': 5.2.1_xd4xiit5nungjv5hy6dlal4bpy + '@nestjs/testing': 8.1.1_rhqqhkohavfzgk66f2dnttsjri + '@nestjs/typeorm': 8.0.2_qx3vpg7qxoteleijf3l76mv7oy '@rush-temp/origin-drec-api': file:projects/origin-drec-api.tgz '@types/bcryptjs': 2.4.2 '@types/bull': 3.15.1 @@ -176,8 +176,8 @@ dependencies: '@types/passport-strategy': 0.2.35 '@types/supertest': 2.0.10 '@types/uuid': 8.3.0 - '@typescript-eslint/eslint-plugin': 3.10.1_78c90eb01c736ca8fc94478e2e2a5ff9 - '@typescript-eslint/parser': 3.10.1_eslint@7.15.0+typescript@4.1.3 + '@typescript-eslint/eslint-plugin': 3.10.1_pdeq5ma4onwkr7eui6hc4ks77e + '@typescript-eslint/parser': 3.10.1_aumck3adhgdxzbq4vr6p4tbife ansi-regex: 4.1.1 aws-sdk: 2.1469.0 axios: 0.28.0 @@ -237,7 +237,7 @@ dependencies: supertest: 6.0.1 swagger-ui-express: 4.1.6_express@4.19.2 terser: 5.21.0 - ts-jest: 26.5.6_jest@26.6.0+typescript@4.1.3 + ts-jest: 26.5.6_hsuqfnt62iydpitnsoiwlshifm ts-node: 9.1.0_typescript@4.1.3 typeorm: 0.2.41_pg@8.7.1 typescript: 4.1.3 @@ -1813,14 +1813,14 @@ packages: kuler: 2.0.0 dev: false - /@energyweb/energy-api-influxdb/0.8.3_ecb5cc502df3a2ec088b43091bdea01d: + /@energyweb/energy-api-influxdb/0.8.3_5s24yubn6oroycelimerxxvadu: resolution: {integrity: sha512-+/RUWugiFb2WT2nACMiXYqNC48Z6bfDYX5PWmVebVY40bK6L+aTTPHhOG1AA+3MDCc5WJt9aVEkQOK7oqUWz7A==} dependencies: '@influxdata/influxdb-client': 1.21.0 - '@nestjs/common': 8.2.4_e42525a0085ceab0eb009503da82e838 - '@nestjs/config': 1.1.6_947eef0805e788651766a5ee39d6841e - '@nestjs/core': 8.2.4_fe23ac443b5d7b3a23d1b563c4442b0a - '@nestjs/swagger': 5.1.5_51bf7f2893f74670309eb7b601093298 + '@nestjs/common': 8.2.4_4qssliailtvlb2yasub5vaxiha + '@nestjs/config': 1.1.6_sr7o6caf46egkf3guxxdtvuedy + '@nestjs/core': 8.2.4_7yr2yrb3lv5tui6rwvr4irblbi + '@nestjs/swagger': 5.1.5_kg7x6ket65dhame6w63accjsta class-transformer: 0.3.1 class-validator: 0.13.2 reflect-metadata: 0.1.13 @@ -1837,7 +1837,7 @@ packages: - swagger-ui-express dev: false - /@energyweb/issuer-api/0.6.2-alpha.1646058469.0_9c842d4fc4d476aa587d8ada10de896e: + /@energyweb/issuer-api/0.6.2-alpha.1646058469.0_tscc2t6e2r3kuwd5rlnbbxujny: resolution: {integrity: sha512-qBnBO5mm2A5qdsmT9Ma3hEr2vMdOP5+hk449B6NBD8dtp6p7VL+Oec0YzAEcZybvov+i4Sb0Z+fjW0zMtO9z6A==} hasBin: true peerDependencies: @@ -1848,16 +1848,16 @@ packages: dependencies: '@energyweb/issuer': 6.0.2-alpha.1646058469.0 '@energyweb/origin-backend-core': 8.2.2-alpha.1646058469.0 - '@energyweb/origin-backend-utils': 1.8.2-alpha.1646058469.0_fd3d872e92dcd8b1a1de9b9a0839d523 + '@energyweb/origin-backend-utils': 1.8.2-alpha.1646058469.0_7u6yolus3tmldio6tonaqoovem '@energyweb/utils-general': 11.2.2-alpha.1646058469.0 - '@nestjs/common': 8.1.1_2740f8938661f2cae724ea514b5f5851 - '@nestjs/config': 1.0.2_13adf4c855eac18d5ece2d7b1023f678 - '@nestjs/core': 8.1.1_8d2cb968665aca547518d0a2ac09c447 - '@nestjs/cqrs': 8.0.0_dae37da4bb6dfb5aedde8e4363b0927b - '@nestjs/passport': 8.0.1_657ee20e3f09dafcc3e7bc216f04f9ef - '@nestjs/schedule': 1.0.1_ca8a8c4fec30006bad441fa41a3f81c3 - '@nestjs/swagger': 5.1.4_d363bbd706e521888d454a50185f16ea - '@nestjs/typeorm': 8.0.2_85f7579bf0bba64591092ed7ff32bf76 + '@nestjs/common': 8.1.1_e5apre4gmhzmvzze5jiuwx2yke + '@nestjs/config': 1.0.2_cow7jscv5lay2xwofv5rai7wpa + '@nestjs/core': 8.1.1_ruwls2dgllffi5iy2crkycoei4 + '@nestjs/cqrs': 8.0.0_3lrx3jf3nx5vv3o6rzbwhmespm + '@nestjs/passport': 8.0.1_mv7oedr7bhnpzq7hxqqw6bhz54 + '@nestjs/schedule': 1.0.1_zkfiyt7mgaagxlked6sbup4bym + '@nestjs/swagger': 5.1.4_2nr3xvyg4uqyrdkfjjibqxyw5i + '@nestjs/typeorm': 8.0.2_qx3vpg7qxoteleijf3l76mv7oy class-validator: 0.13.2 cryptr: 6.0.2 ethers: 5.3.1 @@ -1914,7 +1914,7 @@ packages: - utf-8-validate dev: false - /@energyweb/origin-247-certificate/4.1.5_802429b3c4725e564012d632dc79ab7f: + /@energyweb/origin-247-certificate/4.1.5_qasctm6eojpfmqas2yzny6nlp4: resolution: {integrity: sha512-wTba6HlfulZi1KCazNjgTrGUy1CPZmFco4lXMYS1ZiPono8ddN0VlMoIFY8Efmo1/JYqrHYspt/di5dMP84VqA==} peerDependencies: '@energyweb/issuer': 6.0.2-alpha.1646058469.0 @@ -1925,11 +1925,11 @@ packages: '@nestjs/typeorm': 8.0.2 dependencies: '@energyweb/issuer': 6.0.2-alpha.1646058469.0 - '@nestjs/bull': 0.4.2_9569caea4829e1e6a54e03a46e955ce7 - '@nestjs/common': 8.1.1_2740f8938661f2cae724ea514b5f5851 - '@nestjs/core': 8.1.1_8d2cb968665aca547518d0a2ac09c447 - '@nestjs/cqrs': 8.0.0_dae37da4bb6dfb5aedde8e4363b0927b - '@nestjs/typeorm': 8.0.2_85f7579bf0bba64591092ed7ff32bf76 + '@nestjs/bull': 0.4.2_svu4v2sifhq6njkoaosg5fk444 + '@nestjs/common': 8.1.1_e5apre4gmhzmvzze5jiuwx2yke + '@nestjs/core': 8.1.1_ruwls2dgllffi5iy2crkycoei4 + '@nestjs/cqrs': 8.0.0_3lrx3jf3nx5vv3o6rzbwhmespm + '@nestjs/typeorm': 8.0.2_qx3vpg7qxoteleijf3l76mv7oy bull: 3.29.3 cache-manager-ioredis: 2.1.0 class-transformer: 0.4.0 @@ -1982,14 +1982,14 @@ packages: - utf-8-validate dev: false - /@energyweb/origin-backend-utils/1.6.2-alpha.1634225870.0_2a17c88284d8d688902b984a9679d264: + /@energyweb/origin-backend-utils/1.6.2-alpha.1634225870.0_fil4raue3dlirebltbfjm6osmq: resolution: {integrity: sha512-Mr00ZGyvFgiXK5IApe2WnSomXZgl3/EDAj8mIXTHWiMFnJ9CpB5Nld4JGATelPjX0/aoodB33aro3w8n74sKHw==} dependencies: '@energyweb/origin-backend-core': 8.0.4-alpha.1634225870.0 - '@nestjs/common': 7.6.18_fbc9982997ba253269f25bdc348cb93c - '@nestjs/config': 1.0.2_ad92c204621b18a69181da190abca121 - '@nestjs/core': 7.6.18_7aa1c9523b9facf2c6441cb266291e03 - '@nestjs/swagger': 4.8.2_d7a751e9d3f2b7adf81a9509448f2f4e + '@nestjs/common': 7.6.18_7pezqkmxxiste2pslpodjdfzhq + '@nestjs/config': 1.0.2_vwjmebdcdmmknemb3imqvpfbee + '@nestjs/core': 7.6.18_pkq4sur3t6wpfrsedszgmki6am + '@nestjs/swagger': 4.8.2_26tvd2ot6k3236a2sueujdzpjy bn.js: 5.2.0 class-validator: 0.13.1 pg: 8.7.1 @@ -2013,14 +2013,14 @@ packages: - utf-8-validate dev: false - /@energyweb/origin-backend-utils/1.6.2-alpha.1634225870.0_c7b4fd5a60aa4ccaca1dbb6491d2e70d: + /@energyweb/origin-backend-utils/1.6.2-alpha.1634225870.0_y62p2wtavjgmvsq5xnsjduxhbu: resolution: {integrity: sha512-Mr00ZGyvFgiXK5IApe2WnSomXZgl3/EDAj8mIXTHWiMFnJ9CpB5Nld4JGATelPjX0/aoodB33aro3w8n74sKHw==} dependencies: '@energyweb/origin-backend-core': 8.0.4-alpha.1634225870.0 - '@nestjs/common': 7.6.18_fbc9982997ba253269f25bdc348cb93c - '@nestjs/config': 1.0.2_ad92c204621b18a69181da190abca121 - '@nestjs/core': 7.6.18_cf22c14faf7a8288645a80ae61717d6f - '@nestjs/swagger': 4.8.2_d7a751e9d3f2b7adf81a9509448f2f4e + '@nestjs/common': 7.6.18_7pezqkmxxiste2pslpodjdfzhq + '@nestjs/config': 1.0.2_vwjmebdcdmmknemb3imqvpfbee + '@nestjs/core': 7.6.18_z4rmct5ppkbiqzc2qcxgc4l5n4 + '@nestjs/swagger': 4.8.2_26tvd2ot6k3236a2sueujdzpjy bn.js: 5.2.0 class-validator: 0.13.1 pg: 8.7.1 @@ -2044,17 +2044,17 @@ packages: - utf-8-validate dev: false - /@energyweb/origin-backend-utils/1.8.2-alpha.1646058469.0_fd3d872e92dcd8b1a1de9b9a0839d523: + /@energyweb/origin-backend-utils/1.8.2-alpha.1646058469.0_7u6yolus3tmldio6tonaqoovem: resolution: {integrity: sha512-c+v8qOOYlwUlispAiRLhOZGF70XGlVW7sqInWB1Tf9/arQl3hm606vWKAnAM31a41m2Yh+4aCLAYFAwNzJAyaA==} peerDependencies: '@nestjs/common': 8.1.1 '@nestjs/core': 8.1.1 dependencies: '@energyweb/origin-backend-core': 8.2.2-alpha.1646058469.0 - '@nestjs/common': 8.1.1_2740f8938661f2cae724ea514b5f5851 - '@nestjs/config': 1.0.2_13adf4c855eac18d5ece2d7b1023f678 - '@nestjs/core': 8.1.1_8d2cb968665aca547518d0a2ac09c447 - '@nestjs/swagger': 5.1.4_d363bbd706e521888d454a50185f16ea + '@nestjs/common': 8.1.1_e5apre4gmhzmvzze5jiuwx2yke + '@nestjs/config': 1.0.2_cow7jscv5lay2xwofv5rai7wpa + '@nestjs/core': 8.1.1_ruwls2dgllffi5iy2crkycoei4 + '@nestjs/swagger': 5.1.4_2nr3xvyg4uqyrdkfjjibqxyw5i bn.js: 5.2.0 class-validator: 0.13.2 pg: 8.7.1 @@ -2090,17 +2090,17 @@ packages: hasBin: true dependencies: '@energyweb/origin-backend-core': 8.0.4-alpha.1634225870.0 - '@energyweb/origin-backend-utils': 1.6.2-alpha.1634225870.0_c7b4fd5a60aa4ccaca1dbb6491d2e70d + '@energyweb/origin-backend-utils': 1.6.2-alpha.1634225870.0_y62p2wtavjgmvsq5xnsjduxhbu '@energyweb/utils-general': 11.0.5-alpha.1634225870.0 - '@nestjs/common': 7.6.18_fbc9982997ba253269f25bdc348cb93c - '@nestjs/config': 1.0.2_ad92c204621b18a69181da190abca121 - '@nestjs/core': 7.6.18_cf22c14faf7a8288645a80ae61717d6f - '@nestjs/cqrs': 7.0.1_b3355eaaab723e52e70bfca874d5ccb9 + '@nestjs/common': 7.6.18_7pezqkmxxiste2pslpodjdfzhq + '@nestjs/config': 1.0.2_vwjmebdcdmmknemb3imqvpfbee + '@nestjs/core': 7.6.18_z4rmct5ppkbiqzc2qcxgc4l5n4 + '@nestjs/cqrs': 7.0.1_wm2v5kvloi7ffzyl7suhjvomxe '@nestjs/jwt': 8.0.0_@nestjs+common@7.6.18 - '@nestjs/passport': 7.1.6_1b8f5eed36ce747133de95b67a6002a2 - '@nestjs/platform-express': 7.6.18_2664420588e0901c7943acb4693cbaf4 - '@nestjs/swagger': 4.8.2_d7a751e9d3f2b7adf81a9509448f2f4e - '@nestjs/typeorm': 7.1.5_770ecc3e0a72b32465b4dc73ad110208 + '@nestjs/passport': 7.1.6_dohv53jwzz2hcm66sw3huyacui + '@nestjs/platform-express': 7.6.18_ezseebmi4ciby6kdvs2gspf26q + '@nestjs/swagger': 4.8.2_26tvd2ot6k3236a2sueujdzpjy + '@nestjs/typeorm': 7.1.5_o4hmypqkokzsiznu3rz22eicba bcryptjs: 2.4.3 body-parser: 1.19.0 class-transformer: 0.3.1 @@ -2252,7 +2252,7 @@ packages: /@ethersproject/address/5.3.0: resolution: {integrity: sha512-29TgjzEBK+gUEUAOfWCG7s9IxLNLCqvr+oDSk6L9TXD0VLvZJKhJV479tKQqheVA81OeGxfpdxYtUVH8hqlCvA==} dependencies: - '@ethersproject/bignumber': 5.7.0 + '@ethersproject/bignumber': 5.3.0 '@ethersproject/bytes': 5.3.0 '@ethersproject/keccak256': 5.3.0 '@ethersproject/logger': 5.3.0 @@ -2326,7 +2326,7 @@ packages: /@ethersproject/constants/5.3.0: resolution: {integrity: sha512-4y1feNOwEpgjAfiCFWOHznvv6qUF/H6uI0UKp8xdhftb+H+FbKflXg1pOgH5qs4Sr7EYBL+zPyPb+YD5g1aEyw==} dependencies: - '@ethersproject/bignumber': 5.7.0 + '@ethersproject/bignumber': 5.3.0 dev: false /@ethersproject/constants/5.7.0: @@ -2370,7 +2370,7 @@ packages: dependencies: '@ethersproject/abstract-signer': 5.7.0 '@ethersproject/address': 5.3.0 - '@ethersproject/bignumber': 5.7.0 + '@ethersproject/bignumber': 5.3.0 '@ethersproject/bytes': 5.3.0 '@ethersproject/keccak256': 5.3.0 '@ethersproject/logger': 5.3.0 @@ -2397,7 +2397,7 @@ packages: dependencies: '@ethersproject/abstract-signer': 5.7.0 '@ethersproject/basex': 5.3.0 - '@ethersproject/bignumber': 5.7.0 + '@ethersproject/bignumber': 5.3.0 '@ethersproject/bytes': 5.3.0 '@ethersproject/logger': 5.3.0 '@ethersproject/pbkdf2': 5.3.0 @@ -2646,7 +2646,7 @@ packages: /@ethersproject/solidity/5.3.0: resolution: {integrity: sha512-uLRBaNUiISHbut94XKewJgQh6UmydWTBp71I7I21pkjVXfZO2dJ5EOo3jCnumJc01M4LOm79dlNNmF3oGIvweQ==} dependencies: - '@ethersproject/bignumber': 5.7.0 + '@ethersproject/bignumber': 5.3.0 '@ethersproject/bytes': 5.3.0 '@ethersproject/keccak256': 5.3.0 '@ethersproject/sha2': 5.3.0 @@ -2684,7 +2684,7 @@ packages: resolution: {integrity: sha512-cdfK8VVyW2oEBCXhURG0WQ6AICL/r6Gmjh0e4Bvbv6MCn/GBd8FeBH3rtl7ho+AW50csMKeGv3m3K1HSHB2jMQ==} dependencies: '@ethersproject/address': 5.3.0 - '@ethersproject/bignumber': 5.7.0 + '@ethersproject/bignumber': 5.3.0 '@ethersproject/bytes': 5.3.0 '@ethersproject/constants': 5.3.0 '@ethersproject/keccak256': 5.3.0 @@ -2711,7 +2711,7 @@ packages: /@ethersproject/units/5.3.0: resolution: {integrity: sha512-BkfccZGwfJ6Ob+AelpIrgAzuNhrN2VLp3AILnkqTOv+yBdsc83V4AYf25XC/u0rHnWl6f4POaietPwlMqP2vUg==} dependencies: - '@ethersproject/bignumber': 5.7.0 + '@ethersproject/bignumber': 5.3.0 '@ethersproject/constants': 5.3.0 '@ethersproject/logger': 5.3.0 dev: false @@ -2832,7 +2832,7 @@ packages: dependencies: '@foliojs-fork/fontkit': 1.9.1 '@foliojs-fork/linebreak': 1.1.1 - crypto-js: 4.1.1 + crypto-js: 4.2.0 png-js: 1.0.0 dev: false @@ -3142,15 +3142,15 @@ packages: tile-cover: 3.0.1 dev: false - /@nestjs-modules/mailer/1.9.1_ce851543783f0b1ad29d2f4cf992494a: + /@nestjs-modules/mailer/1.9.1_z2crkq3yh4frvuu5f5gptesjji: resolution: {integrity: sha512-9kSDgg4qA6+2BXOzfY4IltL70uMGXDeE8u/dhkzM2gnCCOKu8Y+wIxWmh8xyLGYcrFHQ3Mke+ap0O1T98Tyjaw==} peerDependencies: '@nestjs/common': ^7.0.9 || ^8.0.0 || ^9.0.0 || ^10.0.0 '@nestjs/core': ^7.0.9 || ^8.0.0 || ^9.0.0 || ^10.0.0 nodemailer: ^6.4.6 dependencies: - '@nestjs/common': 8.1.1_2740f8938661f2cae724ea514b5f5851 - '@nestjs/core': 8.1.1_8d2cb968665aca547518d0a2ac09c447 + '@nestjs/common': 8.1.1_e5apre4gmhzmvzze5jiuwx2yke + '@nestjs/core': 8.1.1_ruwls2dgllffi5iy2crkycoei4 glob: 10.3.3 inline-css: 4.0.2 mjml: 4.14.1 @@ -3167,14 +3167,14 @@ packages: - supports-color dev: false - /@nestjs/axios/0.0.8_3933966b9561a99a78287997461c7d33: + /@nestjs/axios/0.0.8_hezzm24vmguzu6bipglumhd5gm: resolution: {integrity: sha512-oJyfR9/h9tVk776il0829xyj3b2e81yTu6HjPraxynwNtMNGqZBHHmAQL24yMB3tVbBM0RvG3eUXH8+pRCGwlg==} peerDependencies: '@nestjs/common': ^7.0.0 || ^8.0.0 reflect-metadata: ^0.1.12 rxjs: ^6.0.0 || ^7.0.0 dependencies: - '@nestjs/common': 8.1.1_2740f8938661f2cae724ea514b5f5851 + '@nestjs/common': 8.1.1_e5apre4gmhzmvzze5jiuwx2yke axios: 0.27.2 reflect-metadata: 0.1.13 rxjs: 7.5.1 @@ -3182,15 +3182,15 @@ packages: - debug dev: false - /@nestjs/bull/0.4.2_9569caea4829e1e6a54e03a46e955ce7: + /@nestjs/bull/0.4.2_svu4v2sifhq6njkoaosg5fk444: resolution: {integrity: sha512-HYRMbgqoUIpGplXN8kaZ23E/yHn6TRrQ297ILRqaHTxBp4vO+XNLfL1qUmJ4Z6weufsNKGg0xcX4dSC5AhXV9g==} peerDependencies: '@nestjs/common': ^6.10.11 || ^7.0.0 || ^8.0.0 '@nestjs/core': ^6.10.11 || ^7.0.0 || ^8.0.0 bull: ^3.3 || ^3.22.0 dependencies: - '@nestjs/common': 8.1.1_2740f8938661f2cae724ea514b5f5851 - '@nestjs/core': 8.1.1_8d2cb968665aca547518d0a2ac09c447 + '@nestjs/common': 8.1.1_e5apre4gmhzmvzze5jiuwx2yke + '@nestjs/core': 8.1.1_ruwls2dgllffi5iy2crkycoei4 dev: false /@nestjs/cli/7.5.4_uglify-js@2.6.0: @@ -3227,7 +3227,7 @@ packages: - webpack-cli dev: false - /@nestjs/common/7.6.18_fbc9982997ba253269f25bdc348cb93c: + /@nestjs/common/7.6.18_7pezqkmxxiste2pslpodjdfzhq: resolution: {integrity: sha512-BUJQHNhWzwWOkS4Ryndzd4HTeRObcAWV2Fh+ermyo3q3xYQQzNoEWclJVL/wZec8AONELwIJ+PSpWI53VP0leg==} peerDependencies: cache-manager: '*' @@ -3255,7 +3255,7 @@ packages: - debug dev: false - /@nestjs/common/8.1.1_2740f8938661f2cae724ea514b5f5851: + /@nestjs/common/8.1.1_e5apre4gmhzmvzze5jiuwx2yke: resolution: {integrity: sha512-4do6SZrvBV4jz3Gf+uLz91kwkhXRxdAqe+jGLqNd4xMaArmT9L4xHngXdnv7wKOFCKb7Bc9EP4KfqS4z451npg==} peerDependencies: cache-manager: '*' @@ -3283,7 +3283,7 @@ packages: - debug dev: false - /@nestjs/common/8.2.4_e42525a0085ceab0eb009503da82e838: + /@nestjs/common/8.2.4_4qssliailtvlb2yasub5vaxiha: resolution: {integrity: sha512-zb6Y//Rd7tRsMsY2qDvX7qk/msr6sBid7V9YNvdePzGNYfMOvtwgNoqtHgbq2F6V4kCtMO7slmmM4/zptSghiQ==} peerDependencies: cache-manager: '*' @@ -3311,14 +3311,14 @@ packages: - debug dev: false - /@nestjs/config/1.0.1_3933966b9561a99a78287997461c7d33: + /@nestjs/config/1.0.1_hezzm24vmguzu6bipglumhd5gm: resolution: {integrity: sha512-azMl4uYlFIhYsywFxPJT81RxF3Pnn0TZW3EEmr0Wa0Wex8R2xpvBNrCcrOgW3TB1xGMP7eqBrlfsVh5ZP82szg==} peerDependencies: '@nestjs/common': ^7.0.0 || ^8.0.0 reflect-metadata: ^0.1.13 rxjs: ^6.0.0 || ^7.2.0 dependencies: - '@nestjs/common': 8.1.1_2740f8938661f2cae724ea514b5f5851 + '@nestjs/common': 8.1.1_e5apre4gmhzmvzze5jiuwx2yke dotenv: 10.0.0 dotenv-expand: 5.1.0 lodash.get: 4.4.2 @@ -3329,14 +3329,14 @@ packages: uuid: 8.3.2 dev: false - /@nestjs/config/1.0.2_13adf4c855eac18d5ece2d7b1023f678: + /@nestjs/config/1.0.2_cow7jscv5lay2xwofv5rai7wpa: resolution: {integrity: sha512-2q8CcI4UszJ110uDacZe09sj2EJzQztqEOvPXoYaoXoeWWMEwIovAF7cyiBpJWJS+LikpbZyHqtA6p3//mSiOg==} peerDependencies: '@nestjs/common': ^7.0.0 || ^8.0.0 reflect-metadata: ^0.1.13 rxjs: ^6.0.0 || ^7.2.0 dependencies: - '@nestjs/common': 8.1.1_2740f8938661f2cae724ea514b5f5851 + '@nestjs/common': 8.1.1_e5apre4gmhzmvzze5jiuwx2yke dotenv: 10.0.0 dotenv-expand: 5.1.0 lodash.get: 4.4.2 @@ -3347,14 +3347,14 @@ packages: uuid: 8.3.2 dev: false - /@nestjs/config/1.0.2_ad92c204621b18a69181da190abca121: + /@nestjs/config/1.0.2_vwjmebdcdmmknemb3imqvpfbee: resolution: {integrity: sha512-2q8CcI4UszJ110uDacZe09sj2EJzQztqEOvPXoYaoXoeWWMEwIovAF7cyiBpJWJS+LikpbZyHqtA6p3//mSiOg==} peerDependencies: '@nestjs/common': ^7.0.0 || ^8.0.0 reflect-metadata: ^0.1.13 rxjs: ^6.0.0 || ^7.2.0 dependencies: - '@nestjs/common': 7.6.18_fbc9982997ba253269f25bdc348cb93c + '@nestjs/common': 7.6.18_7pezqkmxxiste2pslpodjdfzhq dotenv: 10.0.0 dotenv-expand: 5.1.0 lodash.get: 4.4.2 @@ -3365,14 +3365,14 @@ packages: uuid: 8.3.2 dev: false - /@nestjs/config/1.1.6_947eef0805e788651766a5ee39d6841e: + /@nestjs/config/1.1.6_sr7o6caf46egkf3guxxdtvuedy: resolution: {integrity: sha512-HYizKt6Dr6gcZl8FmZbTfQxP0MG8oXMh+gVFT0XCwYDAq26BOKyhPsIxrKsryicVeKViRgetCUhlJY9EqaekZA==} peerDependencies: '@nestjs/common': ^7.0.0 || ^8.0.0 reflect-metadata: ^0.1.13 rxjs: ^6.0.0 || ^7.2.0 dependencies: - '@nestjs/common': 8.2.4_e42525a0085ceab0eb009503da82e838 + '@nestjs/common': 8.2.4_4qssliailtvlb2yasub5vaxiha dotenv: 10.0.0 dotenv-expand: 5.1.0 lodash: 4.17.21 @@ -3381,7 +3381,7 @@ packages: uuid: 8.3.2 dev: false - /@nestjs/core/7.6.18_7aa1c9523b9facf2c6441cb266291e03: + /@nestjs/core/7.6.18_pkq4sur3t6wpfrsedszgmki6am: resolution: {integrity: sha512-CGu20OjIxgFDY7RJT5t1TDGL8wSlTSlbZEkn8U5OlICZEB3WIpi98G7ajJpnRWmEgW8S4aDJmRKGjT+Ntj5U4A==} requiresBuild: true peerDependencies: @@ -3399,8 +3399,8 @@ packages: '@nestjs/websockets': optional: true dependencies: - '@nestjs/common': 7.6.18_fbc9982997ba253269f25bdc348cb93c - '@nestjs/platform-express': 8.1.1_9569caea4829e1e6a54e03a46e955ce7 + '@nestjs/common': 7.6.18_7pezqkmxxiste2pslpodjdfzhq + '@nestjs/platform-express': 8.1.1_svu4v2sifhq6njkoaosg5fk444 '@nuxtjs/opencollective': 0.3.2 fast-safe-stringify: 2.0.7 iterare: 1.2.1 @@ -3414,7 +3414,7 @@ packages: - encoding dev: false - /@nestjs/core/7.6.18_cf22c14faf7a8288645a80ae61717d6f: + /@nestjs/core/7.6.18_z4rmct5ppkbiqzc2qcxgc4l5n4: resolution: {integrity: sha512-CGu20OjIxgFDY7RJT5t1TDGL8wSlTSlbZEkn8U5OlICZEB3WIpi98G7ajJpnRWmEgW8S4aDJmRKGjT+Ntj5U4A==} requiresBuild: true peerDependencies: @@ -3432,8 +3432,8 @@ packages: '@nestjs/websockets': optional: true dependencies: - '@nestjs/common': 7.6.18_fbc9982997ba253269f25bdc348cb93c - '@nestjs/platform-express': 7.6.18_2664420588e0901c7943acb4693cbaf4 + '@nestjs/common': 7.6.18_7pezqkmxxiste2pslpodjdfzhq + '@nestjs/platform-express': 7.6.18_ezseebmi4ciby6kdvs2gspf26q '@nuxtjs/opencollective': 0.3.2 fast-safe-stringify: 2.0.7 iterare: 1.2.1 @@ -3447,7 +3447,7 @@ packages: - encoding dev: false - /@nestjs/core/8.1.1_8d2cb968665aca547518d0a2ac09c447: + /@nestjs/core/8.1.1_ruwls2dgllffi5iy2crkycoei4: resolution: {integrity: sha512-EnQcLVK5Ct2flMg86Iz4rR5SW8yiCxMQPUZmbPdAH64u5ZArtA1E6kwZXrEUkstUYu5en+W+Q/iwCC8l252b6Q==} requiresBuild: true peerDependencies: @@ -3465,8 +3465,8 @@ packages: '@nestjs/websockets': optional: true dependencies: - '@nestjs/common': 8.1.1_2740f8938661f2cae724ea514b5f5851 - '@nestjs/platform-express': 8.1.1_9569caea4829e1e6a54e03a46e955ce7 + '@nestjs/common': 8.1.1_e5apre4gmhzmvzze5jiuwx2yke + '@nestjs/platform-express': 8.1.1_svu4v2sifhq6njkoaosg5fk444 '@nuxtjs/opencollective': 0.3.2 fast-safe-stringify: 2.1.1 iterare: 1.2.1 @@ -3480,7 +3480,7 @@ packages: - encoding dev: false - /@nestjs/core/8.2.4_fe23ac443b5d7b3a23d1b563c4442b0a: + /@nestjs/core/8.2.4_7yr2yrb3lv5tui6rwvr4irblbi: resolution: {integrity: sha512-CWyS5Rj5tUxwtTGKkGei+ii6CvkGNhuo5hbKGBkCK3McfAMwpCq2pYDjSEFAqn6R2ylL4H3U5H9WU6OWJD1cVw==} requiresBuild: true peerDependencies: @@ -3498,8 +3498,8 @@ packages: '@nestjs/websockets': optional: true dependencies: - '@nestjs/common': 8.2.4_e42525a0085ceab0eb009503da82e838 - '@nestjs/platform-express': 8.1.1_9569caea4829e1e6a54e03a46e955ce7 + '@nestjs/common': 8.2.4_4qssliailtvlb2yasub5vaxiha + '@nestjs/platform-express': 8.1.1_svu4v2sifhq6njkoaosg5fk444 '@nuxtjs/opencollective': 0.3.2 fast-safe-stringify: 2.1.1 iterare: 1.2.1 @@ -3513,7 +3513,7 @@ packages: - encoding dev: false - /@nestjs/cqrs/7.0.1_b3355eaaab723e52e70bfca874d5ccb9: + /@nestjs/cqrs/7.0.1_wm2v5kvloi7ffzyl7suhjvomxe: resolution: {integrity: sha512-4UJAH3ryJvT+SDeuB5ls1OpJsPr3xqsyiuWCfVd1oyzCLazuxl04t/xup005HtWdxczwLgaAau7SIAb+XZotBQ==} peerDependencies: '@nestjs/common': ^6.0.0 || ^7.0.0 @@ -3521,13 +3521,13 @@ packages: reflect-metadata: 0.1.13 rxjs: ^6.4.0 dependencies: - '@nestjs/common': 7.6.18_fbc9982997ba253269f25bdc348cb93c - '@nestjs/core': 7.6.18_cf22c14faf7a8288645a80ae61717d6f + '@nestjs/common': 7.6.18_7pezqkmxxiste2pslpodjdfzhq + '@nestjs/core': 7.6.18_z4rmct5ppkbiqzc2qcxgc4l5n4 reflect-metadata: 0.1.13 rxjs: 6.6.7 dev: false - /@nestjs/cqrs/8.0.0_dae37da4bb6dfb5aedde8e4363b0927b: + /@nestjs/cqrs/8.0.0_3lrx3jf3nx5vv3o6rzbwhmespm: resolution: {integrity: sha512-6Fy0jgUZatRXirfAhDVy3Du2UYoBLrlT7yjK4ZX3L7rBMdfTYPqmn8wE2JH3kXW3yUqLDdnS9PotHf6Y0UzLxw==} peerDependencies: '@nestjs/common': ^8.0.0 @@ -3535,8 +3535,8 @@ packages: reflect-metadata: 0.1.13 rxjs: ^7.2.0 dependencies: - '@nestjs/common': 8.1.1_2740f8938661f2cae724ea514b5f5851 - '@nestjs/core': 8.1.1_8d2cb968665aca547518d0a2ac09c447 + '@nestjs/common': 8.1.1_e5apre4gmhzmvzze5jiuwx2yke + '@nestjs/core': 8.1.1_ruwls2dgllffi5iy2crkycoei4 reflect-metadata: 0.1.13 rxjs: 7.5.1 dev: false @@ -3546,7 +3546,7 @@ packages: peerDependencies: '@nestjs/common': ^6.0.0 || ^7.0.0 || ^8.0.0 dependencies: - '@nestjs/common': 7.6.18_fbc9982997ba253269f25bdc348cb93c + '@nestjs/common': 7.6.18_7pezqkmxxiste2pslpodjdfzhq '@types/jsonwebtoken': 8.5.4 jsonwebtoken: 8.5.1 dev: false @@ -3556,12 +3556,12 @@ packages: peerDependencies: '@nestjs/common': ^6.0.0 || ^7.0.0 || ^8.0.0 dependencies: - '@nestjs/common': 8.1.1_2740f8938661f2cae724ea514b5f5851 + '@nestjs/common': 8.1.1_e5apre4gmhzmvzze5jiuwx2yke '@types/jsonwebtoken': 8.5.4 jsonwebtoken: 8.5.1 dev: false - /@nestjs/mapped-types/0.4.1_e88b2f8bf29a96c28a073d859a3e1f58: + /@nestjs/mapped-types/0.4.1_5cfs7c7stklmfcqhhwczupq7la: resolution: {integrity: sha512-JXrw2LMangSU3vnaXWXVX47GRG1FbbNh4aVBbidDjxT3zlghsoNQY6qyWtT001MCl8lJGo8I6i6+DurBRRxl/Q==} peerDependencies: '@nestjs/common': ^7.0.8 @@ -3569,13 +3569,13 @@ packages: class-validator: ^0.11.1 || ^0.12.0 || ^0.13.0 reflect-metadata: ^0.1.12 dependencies: - '@nestjs/common': 7.6.18_fbc9982997ba253269f25bdc348cb93c + '@nestjs/common': 7.6.18_7pezqkmxxiste2pslpodjdfzhq class-transformer: 0.3.1 class-validator: 0.13.1 reflect-metadata: 0.1.13 dev: false - /@nestjs/mapped-types/1.0.0_a5670d67a7b60c9e2f95fea36d12949d: + /@nestjs/mapped-types/1.0.0_2oezunu47ma3lvo6snvn2nwzze: resolution: {integrity: sha512-26AW5jHadLXtvHs+M+Agd9KZ92dDlBrmD0rORlBlvn2KvsWs4JRaKl2mUsrW7YsdZeAu3Hc4ukqyYyDdyCmMWQ==} peerDependencies: '@nestjs/common': ^7.0.8 || ^8.0.0 @@ -3583,13 +3583,13 @@ packages: class-validator: ^0.11.1 || ^0.12.0 || ^0.13.0 reflect-metadata: ^0.1.12 dependencies: - '@nestjs/common': 8.1.1_2740f8938661f2cae724ea514b5f5851 + '@nestjs/common': 8.2.4_4qssliailtvlb2yasub5vaxiha class-transformer: 0.3.1 class-validator: 0.13.2 reflect-metadata: 0.1.13 dev: false - /@nestjs/mapped-types/1.0.0_d3899a369cfb01b5d5de936add36d9c9: + /@nestjs/mapped-types/1.0.0_uvtq2z5hwygj4l4v72rw2euutu: resolution: {integrity: sha512-26AW5jHadLXtvHs+M+Agd9KZ92dDlBrmD0rORlBlvn2KvsWs4JRaKl2mUsrW7YsdZeAu3Hc4ukqyYyDdyCmMWQ==} peerDependencies: '@nestjs/common': ^7.0.8 || ^8.0.0 @@ -3597,13 +3597,13 @@ packages: class-validator: ^0.11.1 || ^0.12.0 || ^0.13.0 reflect-metadata: ^0.1.12 dependencies: - '@nestjs/common': 8.2.4_e42525a0085ceab0eb009503da82e838 + '@nestjs/common': 8.1.1_e5apre4gmhzmvzze5jiuwx2yke class-transformer: 0.3.1 class-validator: 0.13.2 reflect-metadata: 0.1.13 dev: false - /@nestjs/mapped-types/1.0.1_8b60bd86c1975c9f7faec29f3af412ca: + /@nestjs/mapped-types/1.0.1_rnql3bwbs5oj675oykptv5aszi: resolution: {integrity: sha512-NFvofzSinp00j5rzUd4tf+xi9od6383iY0JP7o0Bnu1fuItAUkWBgc4EKuIQ3D+c2QI3i9pG1kDWAeY27EMGtg==} peerDependencies: '@nestjs/common': ^7.0.8 || ^8.0.0 @@ -3616,40 +3616,40 @@ packages: class-validator: optional: true dependencies: - '@nestjs/common': 8.1.1_2740f8938661f2cae724ea514b5f5851 + '@nestjs/common': 8.1.1_e5apre4gmhzmvzze5jiuwx2yke class-transformer: 0.3.1 class-validator: 0.14.0 reflect-metadata: 0.1.13 dev: false - /@nestjs/passport/7.1.6_1b8f5eed36ce747133de95b67a6002a2: + /@nestjs/passport/7.1.6_dohv53jwzz2hcm66sw3huyacui: resolution: {integrity: sha512-iHD/4D01CsKKWg7kUzo4yGNS4m90z1an0eUz+6nBlE5VeEOuCzhGFoBKAt0OKLJLOTEsJKuj4C2b5QfjqXVTyQ==} peerDependencies: '@nestjs/common': ^6.0.0 || ^7.0.0 passport: ^0.4.0 dependencies: - '@nestjs/common': 7.6.18_fbc9982997ba253269f25bdc348cb93c + '@nestjs/common': 7.6.18_7pezqkmxxiste2pslpodjdfzhq passport: 0.5.0 dev: false - /@nestjs/passport/8.0.1_657ee20e3f09dafcc3e7bc216f04f9ef: + /@nestjs/passport/8.0.1_mv7oedr7bhnpzq7hxqqw6bhz54: resolution: {integrity: sha512-vn/ZJLXQKvSf9D0BvEoNFJLfzl9AVqfGtDyQMfWDLbaNpoEB2FyeaHGxdiX6H71oLSrQV78c/yuhfantzwdjdg==} peerDependencies: '@nestjs/common': ^6.0.0 || ^7.0.0 || ^8.0.0 passport: ^0.4.0 dependencies: - '@nestjs/common': 8.1.1_2740f8938661f2cae724ea514b5f5851 + '@nestjs/common': 8.1.1_e5apre4gmhzmvzze5jiuwx2yke passport: 0.4.0 dev: false - /@nestjs/platform-express/7.6.18_2664420588e0901c7943acb4693cbaf4: + /@nestjs/platform-express/7.6.18_ezseebmi4ciby6kdvs2gspf26q: resolution: {integrity: sha512-Dty2bBhsW7EInMRPS1pkXKJ3GBBusEj6fnEpb0UfkaT3E7asay9c64kCmZE+8hU430qQjY+fhBb1RNWWPnUiwQ==} peerDependencies: '@nestjs/common': ^7.0.0 '@nestjs/core': ^7.0.0 dependencies: - '@nestjs/common': 7.6.18_fbc9982997ba253269f25bdc348cb93c - '@nestjs/core': 7.6.18_cf22c14faf7a8288645a80ae61717d6f + '@nestjs/common': 7.6.18_7pezqkmxxiste2pslpodjdfzhq + '@nestjs/core': 7.6.18_z4rmct5ppkbiqzc2qcxgc4l5n4 body-parser: 1.19.0 cors: 2.8.5 express: 4.17.1 @@ -3657,14 +3657,14 @@ packages: tslib: 2.2.0 dev: false - /@nestjs/platform-express/8.1.1_9569caea4829e1e6a54e03a46e955ce7: + /@nestjs/platform-express/8.1.1_svu4v2sifhq6njkoaosg5fk444: resolution: {integrity: sha512-AIZIYjlctGKdWW1f1TDMJSJiDjUtR06b40nwUkfk22d/ZR0XM4OFtxMjrKC+HyR14ctaKUVU4pmzqFcQxymwXQ==} peerDependencies: '@nestjs/common': ^8.0.0 '@nestjs/core': ^8.0.0 dependencies: - '@nestjs/common': 8.1.1_2740f8938661f2cae724ea514b5f5851 - '@nestjs/core': 8.1.1_8d2cb968665aca547518d0a2ac09c447 + '@nestjs/common': 8.1.1_e5apre4gmhzmvzze5jiuwx2yke + '@nestjs/core': 8.1.1_ruwls2dgllffi5iy2crkycoei4 body-parser: 1.19.0 cors: 2.8.5 express: 4.17.1 @@ -3672,15 +3672,15 @@ packages: tslib: 2.3.1 dev: false - /@nestjs/schedule/1.0.1_ca8a8c4fec30006bad441fa41a3f81c3: + /@nestjs/schedule/1.0.1_zkfiyt7mgaagxlked6sbup4bym: resolution: {integrity: sha512-EU2tB4rxuEgum8JlorAFvXkU982EYZm/IBa7n6kgkyps5BbxQSFf7iR1CLkP9zODO9ApZTWk5z3q9L3O7vrkoQ==} peerDependencies: '@nestjs/common': ^6.10.11 || ^7.0.0 || ^8.0.0 '@nestjs/core': ^7.0.0 || ^8.0.0 reflect-metadata: ^0.1.12 dependencies: - '@nestjs/common': 8.1.1_2740f8938661f2cae724ea514b5f5851 - '@nestjs/core': 8.1.1_8d2cb968665aca547518d0a2ac09c447 + '@nestjs/common': 8.1.1_e5apre4gmhzmvzze5jiuwx2yke + '@nestjs/core': 8.1.1_ruwls2dgllffi5iy2crkycoei4 cron: 1.7.2 reflect-metadata: 0.1.13 uuid: 8.3.2 @@ -3699,7 +3699,7 @@ packages: typescript: 4.0.5 dev: false - /@nestjs/swagger/4.8.2_d7a751e9d3f2b7adf81a9509448f2f4e: + /@nestjs/swagger/4.8.2_26tvd2ot6k3236a2sueujdzpjy: resolution: {integrity: sha512-RSUwcVxrzXF7/b/IZ5lXnYHJ6jIGS9wWRTJKIt1kIaCNWT+0wRfTlAyhQkzs2g35/PTXJEcdIwwY7mBO/bwHzw==} peerDependencies: '@nestjs/common': ^6.8.0 || ^7.0.0 @@ -3713,9 +3713,9 @@ packages: swagger-ui-express: optional: true dependencies: - '@nestjs/common': 7.6.18_fbc9982997ba253269f25bdc348cb93c - '@nestjs/core': 7.6.18_cf22c14faf7a8288645a80ae61717d6f - '@nestjs/mapped-types': 0.4.1_e88b2f8bf29a96c28a073d859a3e1f58 + '@nestjs/common': 7.6.18_7pezqkmxxiste2pslpodjdfzhq + '@nestjs/core': 7.6.18_z4rmct5ppkbiqzc2qcxgc4l5n4 + '@nestjs/mapped-types': 0.4.1_5cfs7c7stklmfcqhhwczupq7la lodash: 4.17.21 path-to-regexp: 3.2.0 reflect-metadata: 0.1.13 @@ -3725,7 +3725,7 @@ packages: - class-validator dev: false - /@nestjs/swagger/5.1.4_d363bbd706e521888d454a50185f16ea: + /@nestjs/swagger/5.1.4_2nr3xvyg4uqyrdkfjjibqxyw5i: resolution: {integrity: sha512-hwVo57Nhw+TyS3xXa8pQAMVOXQAoXBszJbnUAqLcKlVtQ8jqmSRKPTApefXSf/XDoG5LekRYi9Re2SOt1T2WlA==} peerDependencies: '@nestjs/common': ^8.0.0 @@ -3739,9 +3739,9 @@ packages: swagger-ui-express: optional: true dependencies: - '@nestjs/common': 8.1.1_2740f8938661f2cae724ea514b5f5851 - '@nestjs/core': 8.1.1_8d2cb968665aca547518d0a2ac09c447 - '@nestjs/mapped-types': 1.0.0_a5670d67a7b60c9e2f95fea36d12949d + '@nestjs/common': 8.1.1_e5apre4gmhzmvzze5jiuwx2yke + '@nestjs/core': 8.1.1_ruwls2dgllffi5iy2crkycoei4 + '@nestjs/mapped-types': 1.0.0_uvtq2z5hwygj4l4v72rw2euutu lodash: 4.17.21 path-to-regexp: 3.2.0 reflect-metadata: 0.1.13 @@ -3751,7 +3751,7 @@ packages: - class-validator dev: false - /@nestjs/swagger/5.1.5_51bf7f2893f74670309eb7b601093298: + /@nestjs/swagger/5.1.5_kg7x6ket65dhame6w63accjsta: resolution: {integrity: sha512-jvsgciVEFcYVVEuLdNAmgJDpFSQzIoukg+Ovz1vJ97OeCprx0sVhmocn13nCl/dEwIkwoM3eby9OiaccX0A+3A==} peerDependencies: '@nestjs/common': ^8.0.0 @@ -3765,9 +3765,9 @@ packages: swagger-ui-express: optional: true dependencies: - '@nestjs/common': 8.2.4_e42525a0085ceab0eb009503da82e838 - '@nestjs/core': 8.2.4_fe23ac443b5d7b3a23d1b563c4442b0a - '@nestjs/mapped-types': 1.0.0_d3899a369cfb01b5d5de936add36d9c9 + '@nestjs/common': 8.2.4_4qssliailtvlb2yasub5vaxiha + '@nestjs/core': 8.2.4_7yr2yrb3lv5tui6rwvr4irblbi + '@nestjs/mapped-types': 1.0.0_2oezunu47ma3lvo6snvn2nwzze lodash: 4.17.21 path-to-regexp: 3.2.0 reflect-metadata: 0.1.13 @@ -3777,7 +3777,7 @@ packages: - class-validator dev: false - /@nestjs/swagger/5.2.1_b8f974227d6d1a64d7a7c786b02f817e: + /@nestjs/swagger/5.2.1_xd4xiit5nungjv5hy6dlal4bpy: resolution: {integrity: sha512-7dNa08WCnTsW/oAk3Ujde+z64JMfNm19DhpXasFR8oJp/9pggYAbYU927HpA+GJsSFJX6adjIRZsCKUqaGWznw==} peerDependencies: '@nestjs/common': ^8.0.0 @@ -3791,9 +3791,9 @@ packages: swagger-ui-express: optional: true dependencies: - '@nestjs/common': 8.1.1_2740f8938661f2cae724ea514b5f5851 - '@nestjs/core': 8.1.1_8d2cb968665aca547518d0a2ac09c447 - '@nestjs/mapped-types': 1.0.1_8b60bd86c1975c9f7faec29f3af412ca + '@nestjs/common': 8.1.1_e5apre4gmhzmvzze5jiuwx2yke + '@nestjs/core': 8.1.1_ruwls2dgllffi5iy2crkycoei4 + '@nestjs/mapped-types': 1.0.1_rnql3bwbs5oj675oykptv5aszi lodash: 4.17.21 path-to-regexp: 3.2.0 reflect-metadata: 0.1.13 @@ -3803,7 +3803,7 @@ packages: - class-validator dev: false - /@nestjs/testing/8.1.1_89e103a9c7054b932bde2e86d9ce498a: + /@nestjs/testing/8.1.1_rhqqhkohavfzgk66f2dnttsjri: resolution: {integrity: sha512-5vW1xi8z2m0QHdsLIpyyLpgINIiHcHTikYiPl1jde3mI52iLrIpv9+v2aWUrp2aHQJf7+br2M7WqDlVLWRFonA==} peerDependencies: '@nestjs/common': ^8.0.0 @@ -3817,13 +3817,13 @@ packages: optional: true dependencies: optional: 0.1.4 - '@nestjs/common': 8.1.1_2740f8938661f2cae724ea514b5f5851 - '@nestjs/core': 8.1.1_8d2cb968665aca547518d0a2ac09c447 - '@nestjs/platform-express': 8.1.1_9569caea4829e1e6a54e03a46e955ce7 + '@nestjs/common': 8.1.1_e5apre4gmhzmvzze5jiuwx2yke + '@nestjs/core': 8.1.1_ruwls2dgllffi5iy2crkycoei4 + '@nestjs/platform-express': 8.1.1_svu4v2sifhq6njkoaosg5fk444 tslib: 2.3.1 dev: false - /@nestjs/typeorm/7.1.5_770ecc3e0a72b32465b4dc73ad110208: + /@nestjs/typeorm/7.1.5_o4hmypqkokzsiznu3rz22eicba: resolution: {integrity: sha512-utE1FkYM/gyCXUqw3zKYYS0YZ3DfkAnzsCx4T48cNnSDTCeWS+u3yt0FMDFjwSiQSaLrzpiSff/FaxJQvRlYow==} peerDependencies: '@nestjs/common': ^6.7.0 || ^7.0.0 @@ -3832,15 +3832,15 @@ packages: rxjs: ^6.0.0 typeorm: ^0.2.7 dependencies: - '@nestjs/common': 7.6.18_fbc9982997ba253269f25bdc348cb93c - '@nestjs/core': 7.6.18_cf22c14faf7a8288645a80ae61717d6f + '@nestjs/common': 7.6.18_7pezqkmxxiste2pslpodjdfzhq + '@nestjs/core': 7.6.18_z4rmct5ppkbiqzc2qcxgc4l5n4 reflect-metadata: 0.1.13 rxjs: 6.6.7 typeorm: 0.2.34 uuid: 8.3.1 dev: false - /@nestjs/typeorm/8.0.2_85f7579bf0bba64591092ed7ff32bf76: + /@nestjs/typeorm/8.0.2_qx3vpg7qxoteleijf3l76mv7oy: resolution: {integrity: sha512-UHn4IsRkzm22eNDir/uI+x8gmgo66EO7SxWfVOiPpeLSdrTfZHKYz6q/P9KRgYbwXs8TrywVdIbJhp+4C0tzjQ==} peerDependencies: '@nestjs/common': ^8.0.0 @@ -3849,8 +3849,8 @@ packages: rxjs: ^7.2.0 typeorm: ^0.2.34 dependencies: - '@nestjs/common': 8.1.1_2740f8938661f2cae724ea514b5f5851 - '@nestjs/core': 8.1.1_8d2cb968665aca547518d0a2ac09c447 + '@nestjs/common': 8.1.1_e5apre4gmhzmvzze5jiuwx2yke + '@nestjs/core': 8.1.1_ruwls2dgllffi5iy2crkycoei4 reflect-metadata: 0.1.13 rxjs: 7.5.1 typeorm: 0.2.41_pg@8.7.1 @@ -3897,6 +3897,7 @@ packages: /@pkgjs/parseargs/0.11.0: resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} engines: {node: '>=14'} + requiresBuild: true dev: false optional: true @@ -4073,6 +4074,7 @@ packages: /@types/ejs/3.1.3: resolution: {integrity: sha512-mv5T/JI/bu+pbfz1o+TLl1NF0NIBbjS0Vl6Ppz1YY9DkXfzZT0lelXpfS5i3ZS3U/p90it7uERQpBvLYoK8e4A==} + requiresBuild: true dev: false optional: true @@ -4111,15 +4113,6 @@ packages: '@types/send': 0.17.2 dev: false - /@types/express/4.17.18: - resolution: {integrity: sha512-Sxv8BSLLgsBYmcnGdGjjEjqET2U+AKAdCRODmMiq02FgjwuV75Ut85DRpvFjyw/Mk0vgUOliGRU0UUmuuZHByQ==} - dependencies: - '@types/body-parser': 1.19.3 - '@types/express-serve-static-core': 4.17.37 - '@types/qs': 6.9.8 - '@types/serve-static': 1.15.3 - dev: false - /@types/express/4.17.9: resolution: {integrity: sha512-SDzEIZInC4sivGIFY4Sz1GG6J9UObPwCInYJjko2jzOf/Imx/dlpume6Xxwj1ORL82tBbmN4cPDIDkLbWHk9hw==} dependencies: @@ -4268,7 +4261,7 @@ packages: /@types/passport/1.0.13: resolution: {integrity: sha512-XXURryL+EZAWtbQFOHX1eNB+RJwz5XMPPz1xrGpEKr2xUZCXM4NCPkHMtZQ3B2tTSG/1IRaAcTHjczRA4sSFCw==} dependencies: - '@types/express': 4.17.18 + '@types/express': 4.17.9 dev: false /@types/pbkdf2/3.1.0: @@ -4283,6 +4276,7 @@ packages: /@types/pug/2.0.6: resolution: {integrity: sha512-SnHmG9wN1UVmagJOnyo/qkk0Z7gejYxOYYmaAwr5u2yFYfsupN3sg10kyzN8Hep/2zbHxCnsumxOoRIRMBwKCg==} + requiresBuild: true dev: false optional: true @@ -4393,7 +4387,7 @@ packages: resolution: {integrity: sha512-fbF6oTd4sGGy0xjHPKAt+eS2CrxJ3+6gQ3FGcBoIJR2TLAyCkCyI8JqZNy+FeON0AhVgNJoUumVoZQjBFUqHkw==} dev: false - /@typescript-eslint/eslint-plugin/3.10.1_78c90eb01c736ca8fc94478e2e2a5ff9: + /@typescript-eslint/eslint-plugin/3.10.1_pdeq5ma4onwkr7eui6hc4ks77e: resolution: {integrity: sha512-PQg0emRtzZFWq6PxBcdxRH3QIQiyFO3WCVpRL3fgj5oQS3CDs3AeAKfv4DxNhzn8ITdNJGJ4D3Qw8eAJf3lXeQ==} engines: {node: ^10.12.0 || >=12.0.0} peerDependencies: @@ -4404,8 +4398,8 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/experimental-utils': 3.10.1_eslint@7.15.0+typescript@4.1.3 - '@typescript-eslint/parser': 3.10.1_eslint@7.15.0+typescript@4.1.3 + '@typescript-eslint/experimental-utils': 3.10.1_aumck3adhgdxzbq4vr6p4tbife + '@typescript-eslint/parser': 3.10.1_aumck3adhgdxzbq4vr6p4tbife debug: 4.3.4 eslint: 7.15.0 functional-red-black-tree: 1.0.1 @@ -4417,7 +4411,7 @@ packages: - supports-color dev: false - /@typescript-eslint/experimental-utils/3.10.1_eslint@7.15.0+typescript@4.1.3: + /@typescript-eslint/experimental-utils/3.10.1_aumck3adhgdxzbq4vr6p4tbife: resolution: {integrity: sha512-DewqIgscDzmAfd5nOGe4zm6Bl7PKtMG2Ad0KG8CUZAHlXfAKTF9Ol5PXhiMh39yRL2ChRH1cuuUGOcVyyrhQIw==} engines: {node: ^10.12.0 || >=12.0.0} peerDependencies: @@ -4434,7 +4428,7 @@ packages: - typescript dev: false - /@typescript-eslint/parser/3.10.1_eslint@7.15.0+typescript@4.1.3: + /@typescript-eslint/parser/3.10.1_aumck3adhgdxzbq4vr6p4tbife: resolution: {integrity: sha512-Ug1RcWcrJP02hmtaXVS3axPPTTPnZjupqhgj+NnZ6BCkwSImWk/283347+x9wN+lqOdK9Eo3vsyiyDHgsmiEJw==} engines: {node: ^10.12.0 || >=12.0.0} peerDependencies: @@ -4445,7 +4439,7 @@ packages: optional: true dependencies: '@types/eslint-visitor-keys': 1.0.0 - '@typescript-eslint/experimental-utils': 3.10.1_eslint@7.15.0+typescript@4.1.3 + '@typescript-eslint/experimental-utils': 3.10.1_aumck3adhgdxzbq4vr6p4tbife '@typescript-eslint/types': 3.10.1 '@typescript-eslint/typescript-estree': 3.10.1_typescript@4.1.3 eslint: 7.15.0 @@ -6309,10 +6303,6 @@ packages: which: 2.0.2 dev: false - /crypto-js/4.1.1: - resolution: {integrity: sha512-o2JlM7ydqd3Qk9CA0L4NL6mTzU2sdx96a+oOfPu8Mkl/PK51vSyoi8/rQ8NknZtk44vq15lmhAj9CIAGwgeWKw==} - dev: false - /crypto-js/4.2.0: resolution: {integrity: sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==} dev: false @@ -7445,7 +7435,7 @@ packages: '@ethersproject/abstract-signer': 5.7.0 '@ethersproject/address': 5.7.0 '@ethersproject/base64': 5.7.0 - '@ethersproject/bignumber': 5.7.0 + '@ethersproject/bignumber': 5.3.0 '@ethersproject/bytes': 5.7.0 '@ethersproject/constants': 5.7.0 '@ethersproject/contracts': 5.7.0 @@ -8132,6 +8122,7 @@ packages: engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} os: [darwin] deprecated: '"Please update to latest v2.3 or v2.2"' + requiresBuild: true dev: false optional: true @@ -8139,6 +8130,7 @@ packages: resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} os: [darwin] + requiresBuild: true dev: false optional: true @@ -11213,6 +11205,7 @@ packages: /node-notifier/8.0.2: resolution: {integrity: sha512-oJP/9NAdd9+x2Q+rfphB2RJCHjod70RcRLjosiPMMu5gjIfwVnOUGq2nbTjTUbmy0DJ/tFIVT30+Qe3nzl4TJg==} + requiresBuild: true dependencies: growly: 1.3.0 is-wsl: 2.2.0 @@ -11232,11 +11225,6 @@ packages: engines: {node: '>=6.0.0'} dev: false - /nodemailer/6.9.5: - resolution: {integrity: sha512-/dmdWo62XjumuLc5+AYQZeiRj+PRR8y8qKtFCOyuOl1k/hckZd8durUUHs/ucKx6/8kN+wFxqKJlQ/LK/qR5FA==} - engines: {node: '>=6.0.0'} - dev: false - /nodemailer/6.9.9: resolution: {integrity: sha512-dexTll8zqQoVJEZPwQAKzxxtFn0qTnjdQTchoU6Re9BUUGBJiOy3YMn/0ShTW6J5M0dfQ1NeDeRTTl4oIWgQMA==} engines: {node: '>=6.0.0'} @@ -12114,7 +12102,7 @@ packages: fixpack: 4.0.0 get-port: 5.1.1 mailparser: 3.6.5 - nodemailer: 6.9.5 + nodemailer: 6.9.9 open: 7.4.2 p-event: 4.2.0 p-wait-for: 3.2.0 @@ -13269,6 +13257,7 @@ packages: /source-map/0.1.43: resolution: {integrity: sha512-VtCvB9SIQhk3aF6h+N85EaqIaBFIAfZ9Cu+NJHHVvc8BbEcnvDcFw6sqQ2dQrT6SlOrZq3tIvyD9+EGq/lJryQ==} engines: {node: '>=0.8.0'} + requiresBuild: true dependencies: amdefine: 1.0.1 dev: false @@ -13781,7 +13770,7 @@ packages: supports-hyperlinks: 2.3.0 dev: false - /terser-webpack-plugin/5.3.9_uglify-js@2.6.0+webpack@5.9.0: + /terser-webpack-plugin/5.3.9_23c2jlns2l4zkdyxcvyt2vlxn4: resolution: {integrity: sha512-ZuXsqE07EcggTWQjXUj+Aot/OMcD0bMKGgF63f7UxYcu5/AJF53aIpK1YoP5xR9l6s/Hy2b+t1AM0bLNPRuhwA==} engines: {node: '>= 10.13.0'} peerDependencies: @@ -13995,7 +13984,7 @@ packages: engines: {node: '>= 14.0.0'} dev: false - /ts-jest/26.5.6_jest@26.6.0+typescript@4.1.3: + /ts-jest/26.5.6_hsuqfnt62iydpitnsoiwlshifm: resolution: {integrity: sha512-rua+rCP8DxpA8b4DQD/6X2HQS8Zy/xzViVYfEs2OQu68tkCuKLV0Md8pmX55+W24uRIyAsf/BajRfxOs+R2MKA==} engines: {node: '>= 10'} hasBin: true @@ -14730,7 +14719,7 @@ packages: pkg-dir: 4.2.0 schema-utils: 3.3.0 tapable: 2.2.1 - terser-webpack-plugin: 5.3.9_uglify-js@2.6.0+webpack@5.9.0 + terser-webpack-plugin: 5.3.9_23c2jlns2l4zkdyxcvyt2vlxn4 watchpack: 2.4.0 webpack-sources: 2.3.1 transitivePeerDependencies: @@ -15217,32 +15206,32 @@ packages: version: 0.0.0 dependencies: '@compodoc/compodoc': 1.1.22_typescript@4.1.3 - '@energyweb/energy-api-influxdb': 0.8.3_ecb5cc502df3a2ec088b43091bdea01d + '@energyweb/energy-api-influxdb': 0.8.3_5s24yubn6oroycelimerxxvadu '@energyweb/issuer': 6.0.2-alpha.1646058469.0 - '@energyweb/issuer-api': 0.6.2-alpha.1646058469.0_9c842d4fc4d476aa587d8ada10de896e - '@energyweb/origin-247-certificate': 4.1.5_802429b3c4725e564012d632dc79ab7f + '@energyweb/issuer-api': 0.6.2-alpha.1646058469.0_tscc2t6e2r3kuwd5rlnbbxujny + '@energyweb/origin-247-certificate': 4.1.5_qasctm6eojpfmqas2yzny6nlp4 '@energyweb/origin-backend': 11.0.2-alpha.1634225870.0_swagger-ui-express@4.1.6 '@energyweb/origin-backend-core': 8.0.4-alpha.1634225870.0 - '@energyweb/origin-backend-utils': 1.6.2-alpha.1634225870.0_2a17c88284d8d688902b984a9679d264 + '@energyweb/origin-backend-utils': 1.6.2-alpha.1634225870.0_fil4raue3dlirebltbfjm6osmq '@energyweb/utils-general': 11.0.5-alpha.1634225870.0 '@ethersproject/bignumber': 5.3.0 '@influxdata/influxdb-client': 1.9.0 '@mapbox/timespace': 2.0.4 - '@nestjs-modules/mailer': 1.9.1_ce851543783f0b1ad29d2f4cf992494a - '@nestjs/axios': 0.0.8_3933966b9561a99a78287997461c7d33 - '@nestjs/bull': 0.4.2_9569caea4829e1e6a54e03a46e955ce7 + '@nestjs-modules/mailer': 1.9.1_z2crkq3yh4frvuu5f5gptesjji + '@nestjs/axios': 0.0.8_hezzm24vmguzu6bipglumhd5gm + '@nestjs/bull': 0.4.2_svu4v2sifhq6njkoaosg5fk444 '@nestjs/cli': 7.5.4_uglify-js@2.6.0 - '@nestjs/common': 8.1.1_2740f8938661f2cae724ea514b5f5851 - '@nestjs/config': 1.0.1_3933966b9561a99a78287997461c7d33 - '@nestjs/core': 8.1.1_8d2cb968665aca547518d0a2ac09c447 - '@nestjs/cqrs': 8.0.0_dae37da4bb6dfb5aedde8e4363b0927b + '@nestjs/common': 8.1.1_e5apre4gmhzmvzze5jiuwx2yke + '@nestjs/config': 1.0.1_hezzm24vmguzu6bipglumhd5gm + '@nestjs/core': 8.1.1_ruwls2dgllffi5iy2crkycoei4 + '@nestjs/cqrs': 8.0.0_3lrx3jf3nx5vv3o6rzbwhmespm '@nestjs/jwt': 8.0.0_@nestjs+common@8.1.1 - '@nestjs/passport': 8.0.1_657ee20e3f09dafcc3e7bc216f04f9ef - '@nestjs/platform-express': 8.1.1_9569caea4829e1e6a54e03a46e955ce7 - '@nestjs/schedule': 1.0.1_ca8a8c4fec30006bad441fa41a3f81c3 - '@nestjs/swagger': 5.2.1_b8f974227d6d1a64d7a7c786b02f817e - '@nestjs/testing': 8.1.1_89e103a9c7054b932bde2e86d9ce498a - '@nestjs/typeorm': 8.0.2_85f7579bf0bba64591092ed7ff32bf76 + '@nestjs/passport': 8.0.1_mv7oedr7bhnpzq7hxqqw6bhz54 + '@nestjs/platform-express': 8.1.1_svu4v2sifhq6njkoaosg5fk444 + '@nestjs/schedule': 1.0.1_zkfiyt7mgaagxlked6sbup4bym + '@nestjs/swagger': 5.2.1_xd4xiit5nungjv5hy6dlal4bpy + '@nestjs/testing': 8.1.1_rhqqhkohavfzgk66f2dnttsjri + '@nestjs/typeorm': 8.0.2_qx3vpg7qxoteleijf3l76mv7oy '@types/bcryptjs': 2.4.2 '@types/bull': 3.15.1 '@types/chai': 4.2.18 @@ -15261,8 +15250,8 @@ packages: '@types/passport-strategy': 0.2.35 '@types/supertest': 2.0.10 '@types/uuid': 8.3.0 - '@typescript-eslint/eslint-plugin': 3.10.1_78c90eb01c736ca8fc94478e2e2a5ff9 - '@typescript-eslint/parser': 3.10.1_eslint@7.15.0+typescript@4.1.3 + '@typescript-eslint/eslint-plugin': 3.10.1_pdeq5ma4onwkr7eui6hc4ks77e + '@typescript-eslint/parser': 3.10.1_aumck3adhgdxzbq4vr6p4tbife ansi-regex: 4.1.1 aws-sdk: 2.1469.0 axios: 0.28.0 @@ -15327,7 +15316,7 @@ packages: supertest: 6.0.1 swagger-ui-express: 4.1.6_express@4.19.2 terser: 5.21.0 - ts-jest: 26.5.6_jest@26.6.0+typescript@4.1.3 + ts-jest: 26.5.6_hsuqfnt62iydpitnsoiwlshifm ts-node: 9.1.0_typescript@4.1.3 typeorm: 0.2.41_pg@8.7.1 typescript: 4.1.3 From 6340b0c64c217d01fad29b83c3b39854c6bc9b07 Mon Sep 17 00:00:00 2001 From: Aish1990 Date: Wed, 15 May 2024 20:04:42 +0530 Subject: [PATCH 52/89] ESLINT: Code changes issuerService, organizationService, deviceService --- .../src/pods/device/device.service.ts | 2 +- .../src/pods/issuer/issuer.service.ts | 96 +++++++++---------- .../organization/organization.service.spec.ts | 2 +- 3 files changed, 50 insertions(+), 50 deletions(-) diff --git a/apps/drec-api/src/pods/device/device.service.ts b/apps/drec-api/src/pods/device/device.service.ts index 29484ccc0..448d2e718 100755 --- a/apps/drec-api/src/pods/device/device.service.ts +++ b/apps/drec-api/src/pods/device/device.service.ts @@ -1073,7 +1073,7 @@ export class DeviceService { externalid, latestartDate, lateendDate, - ): Promise { + ): Promise { const isalreadyadded = await this.latedevciecertificaterepository.findOne({ where: { groupId: groupid, diff --git a/apps/drec-api/src/pods/issuer/issuer.service.ts b/apps/drec-api/src/pods/issuer/issuer.service.ts index e6abf419b..b6186ad10 100755 --- a/apps/drec-api/src/pods/issuer/issuer.service.ts +++ b/apps/drec-api/src/pods/issuer/issuer.service.ts @@ -107,7 +107,7 @@ export class IssuerService { ); } - var countryDevicegroup = await this.deviceService.NewfindForGroup( + const countryDevicegroup = await this.deviceService.NewfindForGroup( group.id, ); @@ -123,7 +123,7 @@ export class IssuerService { const endDate = DateTime.fromISO(grouprequest.end_date).toUTC(); //console.log("151", startDate); // console.log("152", endDate); - let start_date = endDate.toString(); + const start_date = endDate.toString(); let hours = 1; const frequency = group.frequency.toLowerCase(); @@ -145,19 +145,19 @@ export class IssuerService { ) { hours = 91 * 24; } - let end_date = new Date( + const end_date = new Date( new Date(new Date(endDate.toString())).getTime() + hours * 3.6e6, ).toISOString(); - let newEndDate: string = ''; - let skipUpdatingNextIssuanceLogTable: boolean = false; + let newEndDate = ''; + let skipUpdatingNextIssuanceLogTable = false; if ( new Date(endDate.toString()).getTime() === group.reservationEndDate.getTime() ) { skipUpdatingNextIssuanceLogTable = true; // console.log("end time reached for buyer reservation", group); - let endDto = new EndReservationdateDTO(); + const endDto = new EndReservationdateDTO(); endDto.endresavationdate = new Date(group.reservationEndDate); await this.groupService.EndReservationGroup( group.id, @@ -175,7 +175,7 @@ export class IssuerService { } else { newEndDate = group.reservationEndDate.toISOString(); } - let allDevicesOfGroup: Device[] = + const allDevicesOfGroup: Device[] = await this.deviceService.findForGroup(group.id); try { @@ -189,7 +189,7 @@ export class IssuerService { ); }); - let deviceOnBoardedWhichIsInBetweenNextIssuance: Device = + const deviceOnBoardedWhichIsInBetweenNextIssuance: Device = allDevicesOfGroup.find((ele) => { //returns first find which is minimum and between next frequency if ( @@ -237,9 +237,9 @@ export class IssuerService { }), ); - for (let key in countryDevicegroup) { + for (const key in countryDevicegroup) { //deep clone to avoid duplicates - let newGroup: DeviceGroup = JSON.parse(JSON.stringify(group)); + const newGroup: DeviceGroup = JSON.parse(JSON.stringify(group)); newGroup.devices = countryDevicegroup[key]; await this.newissueCertificateForGroup( newGroup, @@ -354,7 +354,7 @@ export class IssuerService { historydeviceread.readsvalue; }, ); - let totalReadValueMegaWattHour = + const totalReadValueMegaWattHour = totalhistoryreadforsingledevices / 10 ** 6; if (totalReadValueMegaWattHour != 0) { @@ -442,7 +442,7 @@ export class IssuerService { late_start_date, late_end_date, ) { - let latedevicecertificatelogDto = + const latedevicecertificatelogDto = new DeviceLateongoingIssueCertificateEntity(); (latedevicecertificatelogDto.device_externalid = device_externalid), (latedevicecertificatelogDto.groupId = groupId), @@ -480,10 +480,10 @@ export class IssuerService { ); } const groupReads: number[] = []; - let allDevicesCompleteReadsBetweenTimeRange: Array< + const allDevicesCompleteReadsBetweenTimeRange: Array< Array<{ timestamp: Date; value: number }> > = []; - let filteredDevicesIndexesListIfMeterReadsNotAvailable: Array = []; + const filteredDevicesIndexesListIfMeterReadsNotAvailable: Array = []; /*Get all devices meter reads between time range */ /*https://stackoverflow.com/questions/37576685/using-async-await-with-a-foreach-loop refer to answer why map and async works */ await Promise.all( @@ -539,7 +539,7 @@ export class IssuerService { ) { allReadsForDeviceBetweenTimeRange = allReadsForDeviceBetweenTimeRange.filter((ele) => { - let readingInBetween: boolean = false; + let readingInBetween = false; certifieddevices.forEach((certifieddevicesEle) => { if ( ele.timestamp.getTime() >= @@ -563,7 +563,7 @@ export class IssuerService { } allDevicesCompleteReadsBetweenTimeRange[index] = allReadsForDeviceBetweenTimeRange; - let devciereadvalue = allReadsForDeviceBetweenTimeRange.reduce( + const devciereadvalue = allReadsForDeviceBetweenTimeRange.reduce( (accumulator, currentValue) => accumulator + currentValue.value, 0, ); @@ -624,11 +624,11 @@ export class IssuerService { if (!group.buyerAddress || !group.buyerId) { return; } - let allPreviousReadingsOfDevices: Array<{ + const allPreviousReadingsOfDevices: Array<{ timestamp: Date; value: number; }> = []; - let certificateTransactionUID = uuid(); + const certificateTransactionUID = uuid(); await Promise.all( group.devices.map(async (device: IDevice, index) => { console.log( @@ -637,12 +637,12 @@ export class IssuerService { ); let previousReading: Array<{ timestamp: Date; value: number }> = []; if (allDevicesCompleteReadsBetweenTimeRange[index].length > 0) { - let endTimestampToCheck = new Date( + const endTimestampToCheck = new Date( allDevicesCompleteReadsBetweenTimeRange[ index ][0].timestamp.getTime() - 1000, ); - let startTimeToCheck = device.createdAt; + const startTimeToCheck = device.createdAt; try { previousReading = await this.readservice.findLastReadForMeterWithinRange( @@ -658,7 +658,7 @@ export class IssuerService { ]; } else if (device.meterReadtype === ReadType.ReadMeter) { try { - let aggregateReadings = + const aggregateReadings = await this.readservice.getAggregateMeterReadsFirstEntryOfDevice( device.externalId, ); @@ -683,14 +683,14 @@ export class IssuerService { this.logger.error(`error in getting aggregate read ${e}`); } } - let devciereadvalue = allDevicesCompleteReadsBetweenTimeRange[ + const devciereadvalue = allDevicesCompleteReadsBetweenTimeRange[ index ].reduce( (accumulator, currentValue) => accumulator + currentValue.value, 0, ); - let devicecertificatelogDto = + const devicecertificatelogDto = new CheckCertificateIssueDateLogForDeviceEntity(); (devicecertificatelogDto.externalId = device.externalId), (devicecertificatelogDto.certificate_issuance_startdate = @@ -716,7 +716,7 @@ export class IssuerService { ); //find the minimum of all previous reading dates of devices and use it as start date let minimumStartDate: Date = new Date('1970-04-01T12:51:51.112Z'); - let checkMinimumStartDate: Date = new Date('1970-04-01T12:51:51.112Z'); + const checkMinimumStartDate: Date = new Date('1970-04-01T12:51:51.112Z'); if (allPreviousReadingsOfDevices.length == 1) { minimumStartDate = allPreviousReadingsOfDevices[0].timestamp; } @@ -727,7 +727,7 @@ export class IssuerService { minimumStartDate = allPreviousReadingsOfDevices[0].timestamp; } let maximumEndDate: Date = new Date('1990-04-01T12:51:51.112Z'); - let checkMaximumEndDate: Date = new Date('1990-04-01T12:51:51.112Z'); + const checkMaximumEndDate: Date = new Date('1990-04-01T12:51:51.112Z'); if (allDevicesCompleteReadsBetweenTimeRange.length == 1) { maximumEndDate = @@ -768,7 +768,7 @@ export class IssuerService { this.logger.log( `Issuance: ${JSON.stringify(issuance)}, Group name: ${group.name}`, ); - let totalReadValueMegaWattHour = totalReadValueKw / 10 ** 3; + const totalReadValueMegaWattHour = totalReadValueKw / 10 ** 3; this.groupService.updateTotalReadingRequestedForCertificateIssuance( group.id, group.organizationId, @@ -782,7 +782,7 @@ export class IssuerService { ) { this.groupService.endReservation(group.id, group, grouprequest); } - let devicegroupcertificatelogDto = + const devicegroupcertificatelogDto = new CheckCertificateIssueDateLogForDeviceGroupEntity(); (devicegroupcertificatelogDto.groupid = group.id?.toString()), (devicegroupcertificatelogDto.certificate_issuance_startdate = @@ -802,7 +802,7 @@ export class IssuerService { this.issueCertificate(issuance); return; } - timerForHistoyIssuanceCounter: number = 0; + timerForHistoyIssuanceCounter = 0; private async newHistoryissueCertificateForDevice( group: DeviceGroup, @@ -816,8 +816,8 @@ export class IssuerService { if (devicehistoryrequest.readsvalue < 1000) { return; } - let certificateTransactionUID = uuid(); - let devicecertificatelogDto = + const certificateTransactionUID = uuid(); + const devicecertificatelogDto = new CheckCertificateIssueDateLogForDeviceEntity(); (devicecertificatelogDto.externalId = device.externalId), (devicecertificatelogDto.certificate_issuance_startdate = new Date( @@ -857,7 +857,7 @@ export class IssuerService { this.logger.log( `Issuance: ${JSON.stringify(issuance)}, Group name: ${group.name}`, ); - let devicegroupcertificatelogDto = + const devicegroupcertificatelogDto = new CheckCertificateIssueDateLogForDeviceGroupEntity(); (devicegroupcertificatelogDto.groupid = group.id?.toString()), (devicegroupcertificatelogDto.certificate_issuance_startdate = new Date( @@ -1029,7 +1029,7 @@ export class IssuerService { } getCertificateData(deviceId?: string) { - let request: IGetAllCertificatesOptions = { + const request: IGetAllCertificatesOptions = { // generationEndFrom: new Date(1677671426*1000), // generationEndTo: new Date(1677671426*1000), // generationStartFrom :new Date(1646622684*1000), @@ -1071,7 +1071,7 @@ export class IssuerService { group.leftoverReadsByCountryCode, ); } - var countryDevicegroup = await this.deviceService.NewfindForGroup( + const countryDevicegroup = await this.deviceService.NewfindForGroup( group.id, ); const organization = await this.organizationService.findOne( @@ -1086,9 +1086,9 @@ export class IssuerService { groupId: group.id, }); this.logger.debug(nextissuance); - for (let key in countryDevicegroup) { + for (const key in countryDevicegroup) { //deep clone to avoid duplicates - let newGroup: DeviceGroup = JSON.parse(JSON.stringify(group)); + const newGroup: DeviceGroup = JSON.parse(JSON.stringify(group)); newGroup.devices = countryDevicegroup[key]; await Promise.all( @@ -1100,17 +1100,17 @@ export class IssuerService { ); if (lateongoing) { - let newGroupwithsingledevice: DeviceGroup = JSON.parse( + const newGroupwithsingledevice: DeviceGroup = JSON.parse( JSON.stringify(newGroup), ); newGroupwithsingledevice.devices = [element]; await Promise.all( lateongoing.map(async (element1) => { - let startDate = DateTime.fromISO( + const startDate = DateTime.fromISO( element1.late_start_date, ).toUTC(); - let endDate = DateTime.fromISO( + const endDate = DateTime.fromISO( element1.late_end_date, ).toUTC(); nextissuance.start_date = element1.late_start_date; @@ -1212,7 +1212,7 @@ export class IssuerService { ) { allReadsForDeviceBetweenTimeRange = allReadsForDeviceBetweenTimeRange.filter((ele) => { - let readingInBetween: boolean = false; + let readingInBetween = false; certifieddevices.forEach((certifieddevicesEle) => { if ( ele.timestamp.getTime() >= @@ -1245,14 +1245,14 @@ export class IssuerService { if (!group.buyerAddress || !group.buyerId) { return; } - let certificateTransactionUID = uuid(); + const certificateTransactionUID = uuid(); let previousReading: Array<{ timestamp: Date; value: number }> = []; if (allReadsForDeviceBetweenTimeRange.length > 0) { - let endTimestampToCheck = new Date( + const endTimestampToCheck = new Date( allReadsForDeviceBetweenTimeRange[0].timestamp.getTime() - 1, ); - let startTimeToCheck = group.devices[0].createdAt; + const startTimeToCheck = group.devices[0].createdAt; try { previousReading = @@ -1269,7 +1269,7 @@ export class IssuerService { ]; } else if (group.devices[0].meterReadtype === ReadType.ReadMeter) { try { - let aggregateReadings = + const aggregateReadings = await this.readservice.getAggregateMeterReadsFirstEntryOfDevice( group.devices[0].externalId, ); @@ -1299,7 +1299,7 @@ export class IssuerService { return; } const issueTotalReadValue = totalReadValueKw * 10 ** 3; // Issue certificate in watts - let devicecertificatelogDto = + const devicecertificatelogDto = new CheckCertificateIssueDateLogForDeviceEntity(); (devicecertificatelogDto.externalId = group.devices[0].externalId), (devicecertificatelogDto.certificate_issuance_startdate = @@ -1322,13 +1322,13 @@ export class IssuerService { ); let minimumStartDate: Date = new Date('1970-04-01T12:51:51.112Z'); - let checkMinimumStartDate: Date = new Date('1970-04-01T12:51:51.112Z'); + const checkMinimumStartDate: Date = new Date('1970-04-01T12:51:51.112Z'); minimumStartDate = previousReading.length > 0 ? previousReading[0].timestamp : new Date(startDate.toString()); let maximumEndDate: Date = new Date('1990-04-01T12:51:51.112Z'); - let checkMaximumEndDate: Date = new Date('1990-04-01T12:51:51.112Z'); + const checkMaximumEndDate: Date = new Date('1990-04-01T12:51:51.112Z'); maximumEndDate = allReadsForDeviceBetweenTimeRange[ allReadsForDeviceBetweenTimeRange.length - 1 @@ -1352,7 +1352,7 @@ export class IssuerService { certificateTransactionUID: certificateTransactionUID.toString(), }, }; - let totalReadValueMegaWattHour = totalReadValueKw / 10 ** 3; + const totalReadValueMegaWattHour = totalReadValueKw / 10 ** 3; this.groupService.updateTotalReadingRequestedForCertificateIssuance( group.id, group.organizationId, @@ -1366,7 +1366,7 @@ export class IssuerService { ) { this.groupService.endReservation(group.id, group, grouprequest); } - let devicegroupcertificatelogDto = + const devicegroupcertificatelogDto = new CheckCertificateIssueDateLogForDeviceGroupEntity(); (devicegroupcertificatelogDto.groupid = group.id?.toString()), (devicegroupcertificatelogDto.certificate_issuance_startdate = diff --git a/apps/drec-api/src/pods/organization/organization.service.spec.ts b/apps/drec-api/src/pods/organization/organization.service.spec.ts index 682703894..e641e5c4a 100644 --- a/apps/drec-api/src/pods/organization/organization.service.spec.ts +++ b/apps/drec-api/src/pods/organization/organization.service.spec.ts @@ -345,7 +345,7 @@ describe('OrganizationService', () => { const limit = 20; const role = undefined; - let users = [ + const users = [ { updatedAt: new Date('2024-03-04T07:03:46.336Z'), id: 21, From 349767ba2d116fe7f18706bf7a4691cdabbaf25f Mon Sep 17 00:00:00 2001 From: Aish1990 Date: Wed, 15 May 2024 20:10:29 +0530 Subject: [PATCH 53/89] prettier fix --- apps/drec-api/src/pods/issuer/issuer.service.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/drec-api/src/pods/issuer/issuer.service.ts b/apps/drec-api/src/pods/issuer/issuer.service.ts index b6186ad10..fd21e4dc8 100755 --- a/apps/drec-api/src/pods/issuer/issuer.service.ts +++ b/apps/drec-api/src/pods/issuer/issuer.service.ts @@ -483,7 +483,8 @@ export class IssuerService { const allDevicesCompleteReadsBetweenTimeRange: Array< Array<{ timestamp: Date; value: number }> > = []; - const filteredDevicesIndexesListIfMeterReadsNotAvailable: Array = []; + const filteredDevicesIndexesListIfMeterReadsNotAvailable: Array = + []; /*Get all devices meter reads between time range */ /*https://stackoverflow.com/questions/37576685/using-async-await-with-a-foreach-loop refer to answer why map and async works */ await Promise.all( From 35d7f22b16c2a166304c263c844a6d0fbdca4950 Mon Sep 17 00:00:00 2001 From: Aish1990 Date: Wed, 15 May 2024 20:30:27 +0530 Subject: [PATCH 54/89] ESLINT: Code changes ReadsController --- .../drec-api/src/pods/reads/reads.controller.ts | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/apps/drec-api/src/pods/reads/reads.controller.ts b/apps/drec-api/src/pods/reads/reads.controller.ts index c51e7d999..6b747a1d6 100644 --- a/apps/drec-api/src/pods/reads/reads.controller.ts +++ b/apps/drec-api/src/pods/reads/reads.controller.ts @@ -499,8 +499,7 @@ export class ReadsController extends BaseReadsController { ` please sent valid date, format for dates is YYYY-MM-DD hh:mm:ss example 2020-02-19 19:20:55 or to include milliseconds add dot and upto 3 digits after seconds example 2020-02-19 19:20:55.2 or 2020-02-19 19:20:54.333`, }); } else { - let dateTime; - dateTime = momentTimeZone.tz(dateString, measurements.timezone); + const dateTime = momentTimeZone.tz(dateString, measurements.timezone); if (!dateTime.isValid()) { dateInvalid = true; this.logger.error(`Invalid date sent ${dateString}`); @@ -512,12 +511,12 @@ export class ReadsController extends BaseReadsController { let milliSeondsToAddSentInRequest = ''; if ( dateString.includes('.') && - parseInt( + !isNaN(parseInt( dateString.substring( dateString.indexOf('.'), dateString.length, ), - ) != NaN + )) ) { milliSeondsToAddSentInRequest = dateString.substring( dateString.indexOf('.'), @@ -1065,8 +1064,7 @@ export class ReadsController extends BaseReadsController { ` please sent valid date, format for dates is YYYY-MM-DD hh:mm:ss example 2020-02-19 19:20:55 or to include milliseconds add dot and upto 3 digits after seconds example 2020-02-19 19:20:55.2 or 2020-02-19 19:20:54.333`, }); } else { - let dateTime; - dateTime = momentTimeZone.tz(dateString, measurements.timezone); + const dateTime = momentTimeZone.tz(dateString, measurements.timezone); if (!dateTime.isValid()) { this.logger.error(`Invalid date sent ${dateString}`); dateInvalid = true; @@ -1078,12 +1076,12 @@ export class ReadsController extends BaseReadsController { let milliSeondsToAddSentInRequest = ''; if ( dateString.includes('.') && - parseInt( + !isNaN(parseInt( dateString.substring( dateString.indexOf('.'), dateString.length, ), - ) != NaN + )) ) { milliSeondsToAddSentInRequest = dateString.substring( dateString.indexOf('.'), @@ -1528,11 +1526,10 @@ export class ReadsController extends BaseReadsController { }); } - let deviceExternalId; let latestReadObject; let latestRead; - deviceExternalId = device.externalId; + const deviceExternalId = device.externalId; if (!device.meterReadtype) { this.logger.error(`Read not found`); From dcccaf280bc4df904f26c6eb21bedf80389145d9 Mon Sep 17 00:00:00 2001 From: Aish1990 Date: Wed, 15 May 2024 20:34:23 +0530 Subject: [PATCH 55/89] prettier fix --- .../src/pods/reads/reads.controller.ts | 34 ++++++++++++------- 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/apps/drec-api/src/pods/reads/reads.controller.ts b/apps/drec-api/src/pods/reads/reads.controller.ts index 6b747a1d6..e1ee94038 100644 --- a/apps/drec-api/src/pods/reads/reads.controller.ts +++ b/apps/drec-api/src/pods/reads/reads.controller.ts @@ -499,7 +499,10 @@ export class ReadsController extends BaseReadsController { ` please sent valid date, format for dates is YYYY-MM-DD hh:mm:ss example 2020-02-19 19:20:55 or to include milliseconds add dot and upto 3 digits after seconds example 2020-02-19 19:20:55.2 or 2020-02-19 19:20:54.333`, }); } else { - const dateTime = momentTimeZone.tz(dateString, measurements.timezone); + const dateTime = momentTimeZone.tz( + dateString, + measurements.timezone, + ); if (!dateTime.isValid()) { dateInvalid = true; this.logger.error(`Invalid date sent ${dateString}`); @@ -511,12 +514,14 @@ export class ReadsController extends BaseReadsController { let milliSeondsToAddSentInRequest = ''; if ( dateString.includes('.') && - !isNaN(parseInt( - dateString.substring( - dateString.indexOf('.'), - dateString.length, + !isNaN( + parseInt( + dateString.substring( + dateString.indexOf('.'), + dateString.length, + ), ), - )) + ) ) { milliSeondsToAddSentInRequest = dateString.substring( dateString.indexOf('.'), @@ -1064,7 +1069,10 @@ export class ReadsController extends BaseReadsController { ` please sent valid date, format for dates is YYYY-MM-DD hh:mm:ss example 2020-02-19 19:20:55 or to include milliseconds add dot and upto 3 digits after seconds example 2020-02-19 19:20:55.2 or 2020-02-19 19:20:54.333`, }); } else { - const dateTime = momentTimeZone.tz(dateString, measurements.timezone); + const dateTime = momentTimeZone.tz( + dateString, + measurements.timezone, + ); if (!dateTime.isValid()) { this.logger.error(`Invalid date sent ${dateString}`); dateInvalid = true; @@ -1076,12 +1084,14 @@ export class ReadsController extends BaseReadsController { let milliSeondsToAddSentInRequest = ''; if ( dateString.includes('.') && - !isNaN(parseInt( - dateString.substring( - dateString.indexOf('.'), - dateString.length, + !isNaN( + parseInt( + dateString.substring( + dateString.indexOf('.'), + dateString.length, + ), ), - )) + ) ) { milliSeondsToAddSentInRequest = dateString.substring( dateString.indexOf('.'), From 3ec51c688aab3fdd735fc9d2ec86763827444a0f Mon Sep 17 00:00:00 2001 From: Aish1990 Date: Wed, 15 May 2024 20:39:57 +0530 Subject: [PATCH 56/89] ESLINT: Code changes in permissionService --- apps/drec-api/src/pods/permission/permission.service.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/drec-api/src/pods/permission/permission.service.ts b/apps/drec-api/src/pods/permission/permission.service.ts index c137a7af4..2d18268e4 100755 --- a/apps/drec-api/src/pods/permission/permission.service.ts +++ b/apps/drec-api/src/pods/permission/permission.service.ts @@ -53,7 +53,7 @@ export class PermissionService { Delete: false, Update: false, }; - for (var key in addedPermissionList) { + for (const key in addedPermissionList) { data.permissions.map((myArr, index) => { if (myArr === key) { addedPermissionList[key] = true; @@ -221,7 +221,7 @@ export class PermissionService { Delete: false, Update: false, }; - for (var key in addedPermissionList) { + for (const key in addedPermissionList) { data.permissions.map((myArr, index) => { if (myArr === key) { addedPermissionList[key] = true; From 83cbb808ddff0d48c0c57866ca499167e1cc109e Mon Sep 17 00:00:00 2001 From: Aish1990 Date: Wed, 15 May 2024 20:44:16 +0530 Subject: [PATCH 57/89] ESLINT: Code changes in deviceController --- apps/drec-api/src/pods/device/device.controller.ts | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/apps/drec-api/src/pods/device/device.controller.ts b/apps/drec-api/src/pods/device/device.controller.ts index 2e1512b94..5f5e2f904 100755 --- a/apps/drec-api/src/pods/device/device.controller.ts +++ b/apps/drec-api/src/pods/device/device.controller.ts @@ -950,8 +950,7 @@ export class DeviceController { }); } - let group: DeviceGroup | null; - group = await this.deviceGroupService.findOne({ + const group: DeviceGroup | null = await this.deviceGroupService.findOne({ devicegroup_uid: groupuId, }); if (group === null || group.buyerId != user.id) { @@ -968,9 +967,7 @@ export class DeviceController { }); } if (externalId != null || externalId != undefined) { - let device: DeviceDTO | null; - - device = await this.deviceService.findOne(externalId); + const device: DeviceDTO | null = await this.deviceService.findOne(externalId); if (device === null) { this.logger.error(`device not found, invalid value was sent`); return new Promise((resolve, reject) => { From be2a45d20e10e93cad30ffbee948f2d1d828ee28 Mon Sep 17 00:00:00 2001 From: Aish1990 Date: Wed, 15 May 2024 20:50:44 +0530 Subject: [PATCH 58/89] prettier fix --- apps/drec-api/src/pods/device/device.controller.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/drec-api/src/pods/device/device.controller.ts b/apps/drec-api/src/pods/device/device.controller.ts index 5f5e2f904..80735525c 100755 --- a/apps/drec-api/src/pods/device/device.controller.ts +++ b/apps/drec-api/src/pods/device/device.controller.ts @@ -967,7 +967,8 @@ export class DeviceController { }); } if (externalId != null || externalId != undefined) { - const device: DeviceDTO | null = await this.deviceService.findOne(externalId); + const device: DeviceDTO | null = + await this.deviceService.findOne(externalId); if (device === null) { this.logger.error(`device not found, invalid value was sent`); return new Promise((resolve, reject) => { From 11975ddd49f60a40168dcfaa683ca04f86c9aaeb Mon Sep 17 00:00:00 2001 From: Aish1990 Date: Wed, 15 May 2024 21:01:57 +0530 Subject: [PATCH 59/89] Version upgrade --- version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version b/version index 16b5f2641..9fdfff618 100755 --- a/version +++ b/version @@ -1 +1 @@ -0.0.112 +0.0.113 From fe4a36fdccca8f50de9a2d3e47241a75299019c6 Mon Sep 17 00:00:00 2001 From: Aish1990 Date: Thu, 16 May 2024 15:26:06 +0530 Subject: [PATCH 60/89] ESLINT: code change in deviceGroupService --- .../src/pods/device-group/device-group.service.ts | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/apps/drec-api/src/pods/device-group/device-group.service.ts b/apps/drec-api/src/pods/device-group/device-group.service.ts index 1583c7e90..bb7f6a800 100755 --- a/apps/drec-api/src/pods/device-group/device-group.service.ts +++ b/apps/drec-api/src/pods/device-group/device-group.service.ts @@ -1020,11 +1020,9 @@ export class DeviceGroupService { }); if (nextMinimumCreatedWhichIsLessThanEndDate) { if ( - new Date(startDate).getTime() > - new Date(nextMinimumCreatedAtString).getTime() + !(new Date(startDate).getTime() > + new Date(nextMinimumCreatedAtString).getTime()) ) { - newEndDate = newEndDate; - } else { newEndDate = nextMinimumCreatedAtString; } } @@ -1684,13 +1682,6 @@ export class DeviceGroupService { errorsList: Array; }> = []; let rowsConvertedToCsvCount = 0; - //https://stackoverflow.com/questions/13230487/converting-a-buffer-into-a-readablestream-in-node-js/44091532#44091532 - const readableStream = new Readable(); - readableStream._read = () => {}; - readableStream - .pipe(this.csvParser) - .on('data', async (data) => {}) - .on('end', async () => {}); this.logger.debug('file?.data.toString()', file?.data.toString()); const filedata = file.data.Body.toString('utf-8'); this.csvStringToJSON(filedata); From c79bea67595bd4f714ce53bd12a87ab620ccb331 Mon Sep 17 00:00:00 2001 From: Aish1990 Date: Thu, 16 May 2024 15:29:46 +0530 Subject: [PATCH 61/89] prettier fix --- apps/drec-api/src/pods/device-group/device-group.service.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/apps/drec-api/src/pods/device-group/device-group.service.ts b/apps/drec-api/src/pods/device-group/device-group.service.ts index bb7f6a800..a79142ac3 100755 --- a/apps/drec-api/src/pods/device-group/device-group.service.ts +++ b/apps/drec-api/src/pods/device-group/device-group.service.ts @@ -1020,8 +1020,10 @@ export class DeviceGroupService { }); if (nextMinimumCreatedWhichIsLessThanEndDate) { if ( - !(new Date(startDate).getTime() > - new Date(nextMinimumCreatedAtString).getTime()) + !( + new Date(startDate).getTime() > + new Date(nextMinimumCreatedAtString).getTime() + ) ) { newEndDate = nextMinimumCreatedAtString; } From 8d68b93e4ed68c5a4b8fa8305524e66e5049d7a0 Mon Sep 17 00:00:00 2001 From: Aish1990 Date: Mon, 20 May 2024 08:44:06 +0530 Subject: [PATCH 62/89] permission's request for apiuser fix --- .../src/pods/permission/permission.service.ts | 65 +++++++++++-------- 1 file changed, 37 insertions(+), 28 deletions(-) diff --git a/apps/drec-api/src/pods/permission/permission.service.ts b/apps/drec-api/src/pods/permission/permission.service.ts index c137a7af4..45214f4c5 100755 --- a/apps/drec-api/src/pods/permission/permission.service.ts +++ b/apps/drec-api/src/pods/permission/permission.service.ts @@ -62,12 +62,7 @@ export class PermissionService { } const permissionValue = this.Permissionvalue.computePermissions(addedPermissionList); - const userpermission = await this.findOne({ - aclmodulesId: data.aclmodulesId, - entityType: data.entityType, - entityId: data.entityId, - }); - if (!userpermission) { + const permissionboolean = await this.checkForExistingmodulepermission( data, permissionValue, @@ -101,13 +96,6 @@ export class PermissionService { message: `This Permission not available in this module Name`, }); } - } else { - this.logger.error(`Permission For ModuleId and Role already exist`); - throw new ConflictException({ - success: false, - message: `Permission For ModuleId and Role already exist`, - }); - } } private async checkForExistingmodulepermission( data: any, @@ -303,24 +291,45 @@ export class PermissionService { ) { permissionIds = api_userpermission.permissionIds; } - await Promise.all( - data.map(async (newpermission: NewPermissionDTO) => { - newpermission.entityType = EntityType.User; - newpermission.entityId = loginuser.id; - const perId = await this.create(newpermission, loginuser); - permissionIds.push(perId.id); - }), - ); - await this.userService.apiuser_permission_request( - api_user.api_user_id, - permissionIds, + const userpermissions = await this.repository.find({ + entityType: EntityType.User, + entityId: loginuser.id + }); + + const hasId = data.some(aclmodule => + userpermissions.some( + userpermission => userpermission.aclmodulesId === aclmodule.aclmodulesId + ), ); - return { - statsu: 'success', - message: 'Your permission request send successfully', - }; + if(!hasId) { + await Promise.all( + data.map(async (newpermission: NewPermissionDTO) => { + newpermission.entityType = EntityType.User; + newpermission.entityId = loginuser.id; + const perId = await this.create(newpermission, loginuser); + + permissionIds.push(perId.id); + }), + ); + await this.userService.apiuser_permission_request( + api_user.api_user_id, + permissionIds, + ); + + return { + statsu: 'success', + message: 'Your permission request send successfully', + }; + } + else if(hasId) { + this.logger.error(`Permission For ModuleId and Role already exist`); + throw new ConflictException({ + success: false, + message: `Permission For ModuleId and Role already exist`, + }); + } } async permission_veify(api_user_id, data: any): Promise { From 36b72f271f258d2b3bb52094283e0687ff97615e Mon Sep 17 00:00:00 2001 From: Aish1990 Date: Mon, 20 May 2024 11:46:51 +0530 Subject: [PATCH 63/89] Prettier fix --- .../src/pods/permission/permission.service.ts | 72 +++++++++---------- 1 file changed, 35 insertions(+), 37 deletions(-) diff --git a/apps/drec-api/src/pods/permission/permission.service.ts b/apps/drec-api/src/pods/permission/permission.service.ts index 45214f4c5..d141afd22 100755 --- a/apps/drec-api/src/pods/permission/permission.service.ts +++ b/apps/drec-api/src/pods/permission/permission.service.ts @@ -63,39 +63,37 @@ export class PermissionService { const permissionValue = this.Permissionvalue.computePermissions(addedPermissionList); - const permissionboolean = await this.checkForExistingmodulepermission( - data, - permissionValue, - ); - if (permissionboolean) { - const aclpermission = new ACLModulePermissions({ - ...data, - permissionValue: permissionValue, - }); - if ( - (loginuser.role === Role.OrganizationAdmin && - data.entityType != 'Role') || - loginuser.role === Role.Admin || - loginuser.role === Role.ApiUser - ) { - const modulepermission = await this.repository.save(aclpermission); - return modulepermission; - } else { - this.logger.error( - `You are not authorized to add module for any Role`, - ); - throw new ConflictException({ - success: false, - message: `You are not authorized to add module for any Role`, - }); - } + const permissionboolean = await this.checkForExistingmodulepermission( + data, + permissionValue, + ); + if (permissionboolean) { + const aclpermission = new ACLModulePermissions({ + ...data, + permissionValue: permissionValue, + }); + if ( + (loginuser.role === Role.OrganizationAdmin && + data.entityType != 'Role') || + loginuser.role === Role.Admin || + loginuser.role === Role.ApiUser + ) { + const modulepermission = await this.repository.save(aclpermission); + return modulepermission; } else { - this.logger.error(`This Permission not available in this module Name`); + this.logger.error(`You are not authorized to add module for any Role`); throw new ConflictException({ success: false, - message: `This Permission not available in this module Name`, + message: `You are not authorized to add module for any Role`, }); } + } else { + this.logger.error(`This Permission not available in this module Name`); + throw new ConflictException({ + success: false, + message: `This Permission not available in this module Name`, + }); + } } private async checkForExistingmodulepermission( data: any, @@ -293,23 +291,24 @@ export class PermissionService { } const userpermissions = await this.repository.find({ - entityType: EntityType.User, - entityId: loginuser.id + entityType: EntityType.User, + entityId: loginuser.id, }); - const hasId = data.some(aclmodule => + const hasId = data.some((aclmodule) => userpermissions.some( - userpermission => userpermission.aclmodulesId === aclmodule.aclmodulesId + (userpermission) => + userpermission.aclmodulesId === aclmodule.aclmodulesId, ), ); - if(!hasId) { + if (!hasId) { await Promise.all( data.map(async (newpermission: NewPermissionDTO) => { newpermission.entityType = EntityType.User; newpermission.entityId = loginuser.id; const perId = await this.create(newpermission, loginuser); - + permissionIds.push(perId.id); }), ); @@ -317,13 +316,12 @@ export class PermissionService { api_user.api_user_id, permissionIds, ); - + return { statsu: 'success', message: 'Your permission request send successfully', }; - } - else if(hasId) { + } else if (hasId) { this.logger.error(`Permission For ModuleId and Role already exist`); throw new ConflictException({ success: false, From 1202ee694b6c2afc941f37b253fc233759d21b89 Mon Sep 17 00:00:00 2001 From: Aish1990 Date: Mon, 20 May 2024 14:50:06 +0530 Subject: [PATCH 64/89] Fix: Code changes in deviceGroup Service --- apps/drec-api/src/pods/device-group/device-group.service.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/apps/drec-api/src/pods/device-group/device-group.service.ts b/apps/drec-api/src/pods/device-group/device-group.service.ts index a79142ac3..9b420afa3 100755 --- a/apps/drec-api/src/pods/device-group/device-group.service.ts +++ b/apps/drec-api/src/pods/device-group/device-group.service.ts @@ -2418,8 +2418,7 @@ export class DeviceGroupService { } const skip = (pageNumber - 1) * pageSize; - let queryBuilder: any; - queryBuilder = this.repository + const queryBuilder: any = this.repository .createQueryBuilder('dg') .innerJoin(Device, 'd', 'd.id = ANY(dg.deviceIdsInt)') .innerJoin( @@ -2697,8 +2696,7 @@ export class DeviceGroupService { const skip = (pageNumber - 1) * pageSize; - let queryBuilder: any; - queryBuilder = this.repository + const queryBuilder: any = this.repository .createQueryBuilder('dg') .innerJoin(Device, 'd', 'd.id = ANY(dg.deviceIdsInt)') .innerJoin( From 609a5dc13a8edec2df964ffa414cc593b6776316 Mon Sep 17 00:00:00 2001 From: Aish1990 Date: Mon, 20 May 2024 15:10:10 +0530 Subject: [PATCH 65/89] Fix: Code changes in device Service --- apps/drec-api/src/pods/device/device.service.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/apps/drec-api/src/pods/device/device.service.ts b/apps/drec-api/src/pods/device/device.service.ts index 448d2e718..d37ad2b3b 100755 --- a/apps/drec-api/src/pods/device/device.service.ts +++ b/apps/drec-api/src/pods/device/device.service.ts @@ -1335,9 +1335,8 @@ export class DeviceService { } async getcertifieddevicedaterange(groupId, device?): Promise { this.logger.verbose(`With in getcertifieddevicedaterange`); - let queryBuilder; - queryBuilder = this.checkdevcielogcertificaterepository + const queryBuilder = this.checkdevcielogcertificaterepository .createQueryBuilder('deviceData') .select( 'MIN(deviceData.certificate_issuance_startdate)', @@ -1362,14 +1361,13 @@ export class DeviceService { pageNumber?: number, ): Promise { this.logger.verbose(`With in getcertifieddevicedaterangeBygroupid`); - let queryBuilder; if (pageNumber === undefined || pageNumber === null) { pageNumber = 1; } const pageSize = 10; const skip: number = (pageNumber - 1) * pageSize; - queryBuilder = await this.checkdevcielogcertificaterepository + const queryBuilder = await this.checkdevcielogcertificaterepository .createQueryBuilder('deviceData') .leftJoin('device', 'd', 'deviceData.externalId = d.externalId') .select([ From a1d2ff7541f941f79096654a06930279053ae26b Mon Sep 17 00:00:00 2001 From: Aish1990 Date: Mon, 20 May 2024 15:26:23 +0530 Subject: [PATCH 66/89] Fix: Code changes in checkforISOStringFormat --- apps/drec-api/src/utils/checkForISOStringFormat.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/drec-api/src/utils/checkForISOStringFormat.ts b/apps/drec-api/src/utils/checkForISOStringFormat.ts index dcc5a5dcd..498986c74 100755 --- a/apps/drec-api/src/utils/checkForISOStringFormat.ts +++ b/apps/drec-api/src/utils/checkForISOStringFormat.ts @@ -2,7 +2,7 @@ import moment from 'moment'; export const isValidUTCDateFormat = (dateInput: string) => { const dateFormateToCheck = new RegExp( - /\d\d\d\d\-\d\d\-\d\dT\d\d:\d\d:\d\d\.\d{1,}Z/, + /\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d+Z/ ); const dateFormat = 'YYYY-MM-DDTHH:mm:ssZ'; const momentDateFormatToCheck = moment(dateInput).format(dateFormat); From 78c24bc817881810f3fa33fa1314c86e4be1a66a Mon Sep 17 00:00:00 2001 From: Aish1990 Date: Mon, 20 May 2024 15:55:21 +0530 Subject: [PATCH 67/89] Fix: Code changes in UserController --- apps/drec-api/src/pods/user/user.controller.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/drec-api/src/pods/user/user.controller.ts b/apps/drec-api/src/pods/user/user.controller.ts index bf840177f..3339ca739 100755 --- a/apps/drec-api/src/pods/user/user.controller.ts +++ b/apps/drec-api/src/pods/user/user.controller.ts @@ -250,7 +250,7 @@ export class UserController { @Body() body: UpdateChangePasswordDTO, ): Promise { const emailregex = - /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; + /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z0-9\-]+\.)+[a-zA-Z]{2,}))$/; let emailConfirmation: any; if (emailregex.test(token)) { emailConfirmation = await this.userService.findOne({ email: token }); From 8aa0749f8ca4f6d00e35b1aaedb668be4edc5fa0 Mon Sep 17 00:00:00 2001 From: Aish1990 Date: Mon, 20 May 2024 16:00:38 +0530 Subject: [PATCH 68/89] Fix: Code changes in UserController --- apps/drec-api/src/pods/user/user.controller.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/drec-api/src/pods/user/user.controller.ts b/apps/drec-api/src/pods/user/user.controller.ts index 3339ca739..94e4ca4a3 100755 --- a/apps/drec-api/src/pods/user/user.controller.ts +++ b/apps/drec-api/src/pods/user/user.controller.ts @@ -250,7 +250,7 @@ export class UserController { @Body() body: UpdateChangePasswordDTO, ): Promise { const emailregex = - /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z0-9\-]+\.)+[a-zA-Z]{2,}))$/; + /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z0-9-]+\.)+[a-zA-Z]{2,}))$/; let emailConfirmation: any; if (emailregex.test(token)) { emailConfirmation = await this.userService.findOne({ email: token }); From abae659a29b7523e6c980ef296d81b4960b460a2 Mon Sep 17 00:00:00 2001 From: Aish1990 Date: Mon, 20 May 2024 16:07:38 +0530 Subject: [PATCH 69/89] Fix: Code changes in ApiUserEntity --- apps/drec-api/src/pods/user/api-user.entity.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/apps/drec-api/src/pods/user/api-user.entity.ts b/apps/drec-api/src/pods/user/api-user.entity.ts index 341c5e171..73102d254 100755 --- a/apps/drec-api/src/pods/user/api-user.entity.ts +++ b/apps/drec-api/src/pods/user/api-user.entity.ts @@ -16,8 +16,6 @@ import { Organization } from '../organization/organization.entity'; import { ACLModulePermissions } from '../permission/permission.entity'; @Entity({ name: 'api_user' }) export class ApiUserEntity { - constructor() {} - @PrimaryGeneratedColumn('uuid') api_user_id: string; From f978be82871927141b45223f39ad63c89aad8b52 Mon Sep 17 00:00:00 2001 From: Aish1990 Date: Mon, 20 May 2024 16:12:41 +0530 Subject: [PATCH 70/89] Fix: Code changes in ReadsService --- apps/drec-api/src/pods/reads/reads.service.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/drec-api/src/pods/reads/reads.service.ts b/apps/drec-api/src/pods/reads/reads.service.ts index 1319aa5b1..3b8c088a2 100755 --- a/apps/drec-api/src/pods/reads/reads.service.ts +++ b/apps/drec-api/src/pods/reads/reads.service.ts @@ -1547,7 +1547,6 @@ from(bucket: "${process.env.INFLUXDB_BUCKET}") this.logger.verbose('startDate::::::::::::' + startDate); this.logger.verbose('End DAte:::::::::::::' + endDate); - meter = meter; let tempResults = []; const finalResults: { timestamp?: string; value?: any }[] = []; let response; From ee4a8d7e8a393a7642819befca3ed6044b33de0d Mon Sep 17 00:00:00 2001 From: Aish1990 Date: Mon, 20 May 2024 16:28:47 +0530 Subject: [PATCH 71/89] Fix: Code changes in IssuerService --- apps/drec-api/src/pods/issuer/issuer.service.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/drec-api/src/pods/issuer/issuer.service.ts b/apps/drec-api/src/pods/issuer/issuer.service.ts index fd21e4dc8..8e28da763 100755 --- a/apps/drec-api/src/pods/issuer/issuer.service.ts +++ b/apps/drec-api/src/pods/issuer/issuer.service.ts @@ -63,7 +63,7 @@ export class IssuerService { this.httpService .get(`${process.env.REACT_APP_BACKEND_URL}/api/drec-issuer/ongoing`) - .subscribe((response) => {}); + .subscribe(); } hitTheCronFromIssuerAPIHistory() { @@ -71,7 +71,7 @@ export class IssuerService { this.httpService .get(`${process.env.REACT_APP_BACKEND_URL}/api/drec-issuer/history`) - .subscribe((response) => {}); + .subscribe(); } @Cron(CronExpression.EVERY_30_SECONDS) From b715690ca0489bab95c041cc1ba0e5dda27f23db Mon Sep 17 00:00:00 2001 From: Aish1990 Date: Mon, 20 May 2024 16:33:02 +0530 Subject: [PATCH 72/89] Fix: Code changes in InvitationService --- apps/drec-api/src/pods/invitation/invitation.service.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/apps/drec-api/src/pods/invitation/invitation.service.ts b/apps/drec-api/src/pods/invitation/invitation.service.ts index a9343f2e4..b93084f5e 100644 --- a/apps/drec-api/src/pods/invitation/invitation.service.ts +++ b/apps/drec-api/src/pods/invitation/invitation.service.ts @@ -156,11 +156,10 @@ export class InvitationService { organizationType: organization.organizationType, orgid: organization.id || undefined, }; - let userid: any; this.logger.debug('invitee'); inviteuser.api_user_id = organization.api_user_id; - userid = await this.userService.newcreate( + const userid: any = await this.userService.newcreate( inviteuser, UserStatus.Pending, true, From c9143a2290e8c69616001111a2105fcfd58b24ae Mon Sep 17 00:00:00 2001 From: Aish1990 Date: Mon, 20 May 2024 18:13:39 +0530 Subject: [PATCH 73/89] Fix: Code changes in testfiles --- .../invitation/invitation.service.spec.ts | 4 ++-- .../src/pods/reads/reads.service.spec.ts | 23 ++++++++++++++---- .../src/pods/user/user.service.spec.ts | 24 +++++++++---------- 3 files changed, 33 insertions(+), 18 deletions(-) diff --git a/apps/drec-api/src/pods/invitation/invitation.service.spec.ts b/apps/drec-api/src/pods/invitation/invitation.service.spec.ts index 8dd04fd69..44de8b159 100644 --- a/apps/drec-api/src/pods/invitation/invitation.service.spec.ts +++ b/apps/drec-api/src/pods/invitation/invitation.service.spec.ts @@ -203,7 +203,7 @@ describe('InvitationService', () => { .mockResolvedValue(undefined); const ensureIsNotMemberSpy = jest .spyOn(service, 'ensureIsNotMember') - .mockImplementation(() => {}); + .mockImplementation(); const saveSpy = jest .spyOn(invitationRepository, 'save') .mockResolvedValue(savedinvitedUser as any); @@ -422,7 +422,7 @@ describe('InvitationService', () => { .mockResolvedValue(undefined); const ensureIsNotMemberSpy = jest .spyOn(service, 'ensureIsNotMember') - .mockImplementation(() => {}); + .mockImplementation(); const saveSpy = jest .spyOn(invitationRepository, 'save') .mockResolvedValue(savedinvitedUser as any); diff --git a/apps/drec-api/src/pods/reads/reads.service.spec.ts b/apps/drec-api/src/pods/reads/reads.service.spec.ts index aeaf4b3f7..40303cc21 100644 --- a/apps/drec-api/src/pods/reads/reads.service.spec.ts +++ b/apps/drec-api/src/pods/reads/reads.service.spec.ts @@ -10,19 +10,35 @@ import { DeviceService } from '../device'; import { DeviceGroupService } from '../device-group/device-group.service'; import { OrganizationService } from '../organization/organization.service'; import { EventBus } from '@nestjs/cqrs'; +import { BASE_READ_SERVICE } from './const'; + +jest.mock('@influxdata/influxdb-client', () => { + return { + InfluxDB: jest.fn().mockImplementation(() => { + return { + getQueryApi: jest.fn().mockReturnValue({ + queryRows: jest.fn(), + }), + }; + }), + }; +}); describe('ReadsService', () => { let service: ReadsService; let aggregateRepository: Repository; let historyRepository: Repository; let deltaRepository: Repository; - let baseReadsService: BaseReadService; let deviceService: DeviceService; let deviceGroupService: DeviceGroupService; let organizationService: OrganizationService; let eventBus: EventBus; beforeEach(async () => { + process.env.INFLUXDB_URL = 'http://localhost:8086'; + process.env.INFLUXDB_TOKEN = 'test-token'; + process.env.INFLUXDB_ORG = 'test-org'; + const module: TestingModule = await Test.createTestingModule({ providers: [ ReadsService, @@ -39,9 +55,8 @@ describe('ReadsService', () => { useClass: Repository, }, { - provide: BaseReadService, - useValue: {} as any, - }, + provide: BASE_READ_SERVICE, + useValue: {} as any, }, { provide: DeviceService, useValue: {} as any, diff --git a/apps/drec-api/src/pods/user/user.service.spec.ts b/apps/drec-api/src/pods/user/user.service.spec.ts index caea89ba2..004a715c1 100644 --- a/apps/drec-api/src/pods/user/user.service.spec.ts +++ b/apps/drec-api/src/pods/user/user.service.spec.ts @@ -943,10 +943,10 @@ describe('UserService', () => { const result = await service.findOne({ email: mockuserEntity.email }); expect(result).toBeNull(); - expect(findOneSpy).toHaveBeenCalledWith({ - where: { email: mockuserEntity.email } as FindConditions, - relations: ['organization'], - }); + expect(findOneSpy).toHaveBeenCalledWith( + { email: mockuserEntity.email } as FindConditions, + { relations: ['organization'] }, + ); expect(emailConfirmationService.get).not.toHaveBeenCalled(); }); @@ -963,10 +963,10 @@ describe('UserService', () => { expect(result).toEqual(expect.objectContaining(mockuserEntity)); expect(result.emailConfirmed).toBe(true); - expect(findOneSpy).toHaveBeenCalledWith({ - where: { email: 'test@example.com' } as FindConditions, - relations: ['organization'], - }); + expect(findOneSpy).toHaveBeenCalledWith( + { email: 'test@example.com' } as FindConditions, + { relations: ['organization'] }, + ); expect(emailConfirmationSpy).toHaveBeenCalledWith(1); }); @@ -979,10 +979,10 @@ describe('UserService', () => { expect(result).toEqual(expect.objectContaining(mockuserEntity)); expect(result.emailConfirmed).toBe(false); - expect(repository.findOne).toHaveBeenCalledWith({ - where: { email: 'test@example.com' } as FindConditions, - relations: ['organization'], - }); + expect(repository.findOne).toHaveBeenCalledWith( + { email: 'test@example.com' } as FindConditions, + { relations: ['organization'] }, + ); expect(emailConfirmationService.get).toHaveBeenCalledWith(1); }); }); From a13ee8bbdd8ff89b8909d9a7c51824e58a4521be Mon Sep 17 00:00:00 2001 From: Aish1990 Date: Mon, 20 May 2024 18:37:57 +0530 Subject: [PATCH 74/89] Fix: Code changes in buyerReservationController --- .../src/pods/device-group/buyer-reservation.controller.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/apps/drec-api/src/pods/device-group/buyer-reservation.controller.ts b/apps/drec-api/src/pods/device-group/buyer-reservation.controller.ts index a9c617ab8..036328656 100644 --- a/apps/drec-api/src/pods/device-group/buyer-reservation.controller.ts +++ b/apps/drec-api/src/pods/device-group/buyer-reservation.controller.ts @@ -404,11 +404,10 @@ export class BuyerReservationController { ); }); } - if ( isNaN(deviceGroupToRegister.targetCapacityInMegaWattHour) || deviceGroupToRegister.targetCapacityInMegaWattHour <= 0 || - deviceGroupToRegister.targetCapacityInMegaWattHour === -0 + Object.is(deviceGroupToRegister.targetCapacityInMegaWattHour, -0) ) { this.logger.error( `targetCapacityInMegaWattHour should be valid number can include decimal but should be greater than 0`, From 0b2c4ebb4a5b6a98054c243859f53823ce4dc495 Mon Sep 17 00:00:00 2001 From: Aish1990 Date: Mon, 20 May 2024 19:25:15 +0530 Subject: [PATCH 75/89] Fix: Code changes in certificateLogService --- .../src/pods/certificate-log/certificate-log.service.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/drec-api/src/pods/certificate-log/certificate-log.service.ts b/apps/drec-api/src/pods/certificate-log/certificate-log.service.ts index 052a3846d..9b85b4dc3 100755 --- a/apps/drec-api/src/pods/certificate-log/certificate-log.service.ts +++ b/apps/drec-api/src/pods/certificate-log/certificate-log.service.ts @@ -677,7 +677,7 @@ export class CertificateLogService { const newq = await this.certificaterrepository .createQueryBuilder('issuar') .where( - `issuar.id IN (${JSON.stringify(group.internalCertificateId).replace(/[\[\]]/g, '')})`, + `issuar.id IN (${JSON.stringify(group.internalCertificateId).replace(/[[]]/g, '')})` ); const groupedDatasql = await newq.getQuery(); From 080a5c0c1f4d50f9abe84b60516b959027f9893e Mon Sep 17 00:00:00 2001 From: Aish1990 Date: Mon, 20 May 2024 19:29:28 +0530 Subject: [PATCH 76/89] Fix: Code changes in certificateLogService --- .../src/pods/certificate-log/certificate-log.service.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/drec-api/src/pods/certificate-log/certificate-log.service.ts b/apps/drec-api/src/pods/certificate-log/certificate-log.service.ts index 9b85b4dc3..f5dfde3c1 100755 --- a/apps/drec-api/src/pods/certificate-log/certificate-log.service.ts +++ b/apps/drec-api/src/pods/certificate-log/certificate-log.service.ts @@ -818,7 +818,7 @@ export class CertificateLogService { const newq = await this.cretificatereadmoduleRepository .createQueryBuilder('crm') .where( - `crm.internalCertificateId IN (${JSON.stringify(group.internalCertificateId).replace(/[\[\]]/g, '')})`, + `crm.internalCertificateId IN (${JSON.stringify(group.internalCertificateId).replace(/[[\]]/g, '')})` ); const groupedDatasql = await newq.getQuery(); this.logger.debug(groupedDatasql); From 57c8e1bd9a43ddeed0d1a4bdfda152df609ab504 Mon Sep 17 00:00:00 2001 From: Aish1990 Date: Mon, 20 May 2024 19:35:00 +0530 Subject: [PATCH 77/89] Fix: Code changes in oldissuerlog migration file --- apps/drec-api/migrations/1715146626520-OldIssuerLog.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/apps/drec-api/migrations/1715146626520-OldIssuerLog.ts b/apps/drec-api/migrations/1715146626520-OldIssuerLog.ts index fe60be587..2c4368f75 100644 --- a/apps/drec-api/migrations/1715146626520-OldIssuerLog.ts +++ b/apps/drec-api/migrations/1715146626520-OldIssuerLog.ts @@ -25,5 +25,7 @@ export class OldIssuerLog1715146626520 implements MigrationInterface { )`); } - public async down(queryRunner: QueryRunner): Promise {} + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`DROP TABLE IF EXISTS old_issuer_certificate`); + } } From ba8e47f44f9e13c7d10fd366a9d1459563a0bcd1 Mon Sep 17 00:00:00 2001 From: Aish1990 Date: Mon, 20 May 2024 19:37:43 +0530 Subject: [PATCH 78/89] Fix: Prettier --- .../src/pods/certificate-log/certificate-log.service.ts | 4 ++-- apps/drec-api/src/pods/reads/reads.service.spec.ts | 3 ++- apps/drec-api/src/utils/checkForISOStringFormat.ts | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/apps/drec-api/src/pods/certificate-log/certificate-log.service.ts b/apps/drec-api/src/pods/certificate-log/certificate-log.service.ts index f5dfde3c1..3d9b59b21 100755 --- a/apps/drec-api/src/pods/certificate-log/certificate-log.service.ts +++ b/apps/drec-api/src/pods/certificate-log/certificate-log.service.ts @@ -677,7 +677,7 @@ export class CertificateLogService { const newq = await this.certificaterrepository .createQueryBuilder('issuar') .where( - `issuar.id IN (${JSON.stringify(group.internalCertificateId).replace(/[[]]/g, '')})` + `issuar.id IN (${JSON.stringify(group.internalCertificateId).replace(/[[]]/g, '')})`, ); const groupedDatasql = await newq.getQuery(); @@ -818,7 +818,7 @@ export class CertificateLogService { const newq = await this.cretificatereadmoduleRepository .createQueryBuilder('crm') .where( - `crm.internalCertificateId IN (${JSON.stringify(group.internalCertificateId).replace(/[[\]]/g, '')})` + `crm.internalCertificateId IN (${JSON.stringify(group.internalCertificateId).replace(/[[\]]/g, '')})`, ); const groupedDatasql = await newq.getQuery(); this.logger.debug(groupedDatasql); diff --git a/apps/drec-api/src/pods/reads/reads.service.spec.ts b/apps/drec-api/src/pods/reads/reads.service.spec.ts index 40303cc21..a38788fe6 100644 --- a/apps/drec-api/src/pods/reads/reads.service.spec.ts +++ b/apps/drec-api/src/pods/reads/reads.service.spec.ts @@ -56,7 +56,8 @@ describe('ReadsService', () => { }, { provide: BASE_READ_SERVICE, - useValue: {} as any, }, + useValue: {} as any, + }, { provide: DeviceService, useValue: {} as any, diff --git a/apps/drec-api/src/utils/checkForISOStringFormat.ts b/apps/drec-api/src/utils/checkForISOStringFormat.ts index 498986c74..2ed538726 100755 --- a/apps/drec-api/src/utils/checkForISOStringFormat.ts +++ b/apps/drec-api/src/utils/checkForISOStringFormat.ts @@ -2,7 +2,7 @@ import moment from 'moment'; export const isValidUTCDateFormat = (dateInput: string) => { const dateFormateToCheck = new RegExp( - /\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d+Z/ + /\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d+Z/, ); const dateFormat = 'YYYY-MM-DDTHH:mm:ssZ'; const momentDateFormatToCheck = moment(dateInput).format(dateFormat); From 79ebae387e14eb0eabe21b6537bf91000e310207 Mon Sep 17 00:00:00 2001 From: Aish1990 Date: Mon, 20 May 2024 19:43:09 +0530 Subject: [PATCH 79/89] Fix: code changes in migration updateColumnvaluinNew --- apps/drec-api/migrations/1682659987637-updateColumnvaluinNew.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/drec-api/migrations/1682659987637-updateColumnvaluinNew.ts b/apps/drec-api/migrations/1682659987637-updateColumnvaluinNew.ts index 997a6c435..402480d3b 100755 --- a/apps/drec-api/migrations/1682659987637-updateColumnvaluinNew.ts +++ b/apps/drec-api/migrations/1682659987637-updateColumnvaluinNew.ts @@ -14,6 +14,7 @@ export class updateColumnvaluinNew1682659987637 implements MigrationInterface { ); } + // eslint-disable-next-line @typescript-eslint/no-empty-function public async down(queryRunner: QueryRunner): Promise { // Since updating column values in a down migration can lead to data loss or inconsistency, // and reverting the update operation is complex and risky, leaving the down method empty. From 58ea939f398146b87671adbb4e65f3c44d080d43 Mon Sep 17 00:00:00 2001 From: Aish1990 Date: Mon, 20 May 2024 19:45:39 +0530 Subject: [PATCH 80/89] Fix: Prettier --- apps/drec-api/migrations/1682659987637-updateColumnvaluinNew.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/drec-api/migrations/1682659987637-updateColumnvaluinNew.ts b/apps/drec-api/migrations/1682659987637-updateColumnvaluinNew.ts index 402480d3b..e6762bf1b 100755 --- a/apps/drec-api/migrations/1682659987637-updateColumnvaluinNew.ts +++ b/apps/drec-api/migrations/1682659987637-updateColumnvaluinNew.ts @@ -14,7 +14,7 @@ export class updateColumnvaluinNew1682659987637 implements MigrationInterface { ); } - // eslint-disable-next-line @typescript-eslint/no-empty-function + // eslint-disable-next-line @typescript-eslint/no-empty-function public async down(queryRunner: QueryRunner): Promise { // Since updating column values in a down migration can lead to data loss or inconsistency, // and reverting the update operation is complex and risky, leaving the down method empty. From 925d80f61d7b47d6849217d074afccbe49f3a5c5 Mon Sep 17 00:00:00 2001 From: Aish1990 Date: Tue, 21 May 2024 10:27:18 +0530 Subject: [PATCH 81/89] Fix: Buyer issuer/certificatelogofdevices --- .../src/pods/device-group/device-group.service.ts | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/apps/drec-api/src/pods/device-group/device-group.service.ts b/apps/drec-api/src/pods/device-group/device-group.service.ts index 1583c7e90..7e81b3292 100755 --- a/apps/drec-api/src/pods/device-group/device-group.service.ts +++ b/apps/drec-api/src/pods/device-group/device-group.service.ts @@ -2468,7 +2468,17 @@ export class DeviceGroupService { where_orgnaizationId .andWhere( - "EXISTS(SELECT 1 FROM jsonb_array_elements_text(CAST(crm.metadata AS jsonb)->'deviceIds') AS ids(deviceId) WHERE CAST(ids.deviceId AS INTEGER) = d.id)", + new Brackets((qb) => { + qb.where( + `EXISTS( + SELECT 1 + FROM jsonb_array_elements_text(CAST(crm.metadata AS jsonb)->'deviceIds') AS ids(deviceId) + WHERE + (deviceId ~ '^[0-9]+$' AND CAST(deviceId AS INTEGER) = d.id) + OR (deviceId !~ '^[0-9]+$' AND deviceId = d.id::TEXT) + )` + ); + }) ) .andWhere( new Brackets((qb) => { From 1fdea9affe4198a59ede8e2f93db4c6edc6f886a Mon Sep 17 00:00:00 2001 From: Aish1990 Date: Tue, 21 May 2024 10:32:11 +0530 Subject: [PATCH 82/89] Fix: Prettier --- apps/drec-api/src/pods/device-group/device-group.service.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/drec-api/src/pods/device-group/device-group.service.ts b/apps/drec-api/src/pods/device-group/device-group.service.ts index 7e81b3292..cafccf130 100755 --- a/apps/drec-api/src/pods/device-group/device-group.service.ts +++ b/apps/drec-api/src/pods/device-group/device-group.service.ts @@ -2476,9 +2476,9 @@ export class DeviceGroupService { WHERE (deviceId ~ '^[0-9]+$' AND CAST(deviceId AS INTEGER) = d.id) OR (deviceId !~ '^[0-9]+$' AND deviceId = d.id::TEXT) - )` + )`, ); - }) + }), ) .andWhere( new Brackets((qb) => { From 0eee0a7ba532539d060c428133553b895613488e Mon Sep 17 00:00:00 2001 From: Aish1990 Date: Tue, 21 May 2024 11:00:13 +0530 Subject: [PATCH 83/89] version upgraded --- version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version b/version index 9fdfff618..58ca857c6 100755 --- a/version +++ b/version @@ -1 +1 @@ -0.0.113 +0.0.114 From 94982fa4b1eb4fac055ee523eac66563f4ae2be3 Mon Sep 17 00:00:00 2001 From: Aish1990 Date: Tue, 21 May 2024 17:27:48 +0530 Subject: [PATCH 84/89] excluded the apiuser organization in apiuser's all organization listings api --- .../drec-api/src/pods/organization/organization.service.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/apps/drec-api/src/pods/organization/organization.service.ts b/apps/drec-api/src/pods/organization/organization.service.ts index 9ef1deae9..2e287b69b 100755 --- a/apps/drec-api/src/pods/organization/organization.service.ts +++ b/apps/drec-api/src/pods/organization/organization.service.ts @@ -103,8 +103,11 @@ export class OrganizationService { let query = await this.getFilteredQuery(filterDto); try { if (user != undefined && user?.role === 'ApiUser') { - query = query.andWhere(`organization.api_user_id = :apiuserid`, { - apiuserid: user.api_user_id, + query = query.andWhere((qb) => { + qb.where("organization.api_user_id = :apiuserid", { apiuserid: user.api_user_id }) + .andWhere(`organization.organizationType NOT IN (:...excludedRoles)`, { + excludedRoles: ['ApiUser', 'Admin'] + }); }); } From f7ccc1d18eceac3540565e5a96b098f42d2ad876 Mon Sep 17 00:00:00 2001 From: Aish1990 Date: Tue, 21 May 2024 17:30:24 +0530 Subject: [PATCH 85/89] prettier fix --- .../src/pods/organization/organization.service.ts | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/apps/drec-api/src/pods/organization/organization.service.ts b/apps/drec-api/src/pods/organization/organization.service.ts index 2e287b69b..818136560 100755 --- a/apps/drec-api/src/pods/organization/organization.service.ts +++ b/apps/drec-api/src/pods/organization/organization.service.ts @@ -104,10 +104,14 @@ export class OrganizationService { try { if (user != undefined && user?.role === 'ApiUser') { query = query.andWhere((qb) => { - qb.where("organization.api_user_id = :apiuserid", { apiuserid: user.api_user_id }) - .andWhere(`organization.organizationType NOT IN (:...excludedRoles)`, { - excludedRoles: ['ApiUser', 'Admin'] - }); + qb.where('organization.api_user_id = :apiuserid', { + apiuserid: user.api_user_id, + }).andWhere( + `organization.organizationType NOT IN (:...excludedRoles)`, + { + excludedRoles: ['ApiUser', 'Admin'], + }, + ); }); } From 755c9e3e5f0246bc7285053a74fbdbbf0b1ac29c Mon Sep 17 00:00:00 2001 From: Aish1990 Date: Tue, 21 May 2024 18:27:07 +0530 Subject: [PATCH 86/89] version upgraded --- version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version b/version index 58ca857c6..f64402b51 100755 --- a/version +++ b/version @@ -1 +1 @@ -0.0.114 +0.0.115 From cfe2db2cfd20cd061cb4e6e57fd68165cef08d22 Mon Sep 17 00:00:00 2001 From: Aish1990 Date: Wed, 22 May 2024 17:18:05 +0530 Subject: [PATCH 87/89] version upgrade --- version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version b/version index f64402b51..30f8347b6 100755 --- a/version +++ b/version @@ -1 +1 @@ -0.0.115 +0.0.116 From a7f87e5222a2221b75a71e9caca00c3ffadd8ae4 Mon Sep 17 00:00:00 2001 From: Daniel Mohns Date: Wed, 22 May 2024 14:03:10 +0200 Subject: [PATCH 88/89] Enable ESLint error check CI --- .github/workflows/check.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index 58c5189b6..ea825bb17 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -56,7 +56,6 @@ jobs: - name: Run ESLint (error) working-directory: apps/drec-api run: pnpm run lint:error - continue-on-error: true - name: Run ESLint (all) working-directory: apps/drec-api From 8d59506a15879a4236ec6864e3fb75659ead9491 Mon Sep 17 00:00:00 2001 From: Daniel Mohns Date: Wed, 22 May 2024 14:58:06 +0200 Subject: [PATCH 89/89] Add VitePress temp files to gitignore (#260) --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 58ee6458a..640f218b5 100755 --- a/.gitignore +++ b/.gitignore @@ -90,3 +90,5 @@ apps/drec-api/bin/drec-api # Docs build output apps/drec-api/documentation +docs/.vitepress/cache +docs/.vitepress/dist