From 9daaea8878232981910923d181ebd4a7bb9cc673 Mon Sep 17 00:00:00 2001 From: Flatlogic Bot Date: Mon, 14 Apr 2025 16:56:15 +0000 Subject: [PATCH] 1.1 --- .dockerignore | 3 + .gitignore | 7 + app-shell/.eslintrc.cjs | 26 + app-shell/.prettierrc | 11 + app-shell/.sequelizerc | 7 + app-shell/Dockerfile | 23 + app-shell/README.md | 13 + app-shell/package.json | 42 + app-shell/src/_schema.json | 4 + app-shell/src/config.js | 16 + app-shell/src/helpers.js | 23 + app-shell/src/index.js | 54 + .../src/middlewares/check-permissions.js | 17 + app-shell/src/middlewares/modify-path.js | 8 + app-shell/src/routes/executor.js | 312 ++ app-shell/src/routes/vcs.js | 40 + app-shell/src/services/database.js | 88 + app-shell/src/services/executor.js | 1206 +++++++ .../notifications/errors/forbidden.js | 16 + .../notifications/errors/validation.js | 16 + .../src/services/notifications/helpers.js | 30 + app-shell/src/services/notifications/list.js | 100 + app-shell/src/services/project-events.js | 67 + app-shell/src/services/vcs.js | 1205 +++++++ app-shell/yarn.lock | 3044 +++++++++++++++++ cloudbuild.yaml | 14 + frontend/next-env.d.ts | 2 +- pids/backend.pid | 1 + pids/frontend.pid | 1 + 29 files changed, 6395 insertions(+), 1 deletion(-) create mode 100644 .dockerignore create mode 100644 .gitignore create mode 100644 app-shell/.eslintrc.cjs create mode 100644 app-shell/.prettierrc create mode 100644 app-shell/.sequelizerc create mode 100644 app-shell/Dockerfile create mode 100644 app-shell/README.md create mode 100644 app-shell/package.json create mode 100644 app-shell/src/_schema.json create mode 100644 app-shell/src/config.js create mode 100644 app-shell/src/helpers.js create mode 100644 app-shell/src/index.js create mode 100644 app-shell/src/middlewares/check-permissions.js create mode 100644 app-shell/src/middlewares/modify-path.js create mode 100644 app-shell/src/routes/executor.js create mode 100644 app-shell/src/routes/vcs.js create mode 100644 app-shell/src/services/database.js create mode 100644 app-shell/src/services/executor.js create mode 100644 app-shell/src/services/notifications/errors/forbidden.js create mode 100644 app-shell/src/services/notifications/errors/validation.js create mode 100644 app-shell/src/services/notifications/helpers.js create mode 100644 app-shell/src/services/notifications/list.js create mode 100644 app-shell/src/services/project-events.js create mode 100644 app-shell/src/services/vcs.js create mode 100644 app-shell/yarn.lock create mode 100644 cloudbuild.yaml create mode 100644 pids/backend.pid create mode 100644 pids/frontend.pid diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..2c83cc6 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,3 @@ +backend/node_modules +frontend/node_modules +frontend/build diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..339a829 --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +node_modules/ +*/node_modules/ +**/node_modules/ +*/build/ +**/build/ +.DS_Store +.env \ No newline at end of file diff --git a/app-shell/.eslintrc.cjs b/app-shell/.eslintrc.cjs new file mode 100644 index 0000000..563d159 --- /dev/null +++ b/app-shell/.eslintrc.cjs @@ -0,0 +1,26 @@ +const globals = require('globals'); + +module.exports = [ + { + files: ['**/*.js', '**/*.ts', '**/*.tsx'], + languageOptions: { + ecmaVersion: 2021, + sourceType: 'module', + globals: { + ...globals.browser, + ...globals.node, + }, + parser: '@typescript-eslint/parser', + }, + plugins: ['@typescript-eslint'], + rules: { + 'no-unused-vars': 'warn', + 'no-console': 'off', + 'indent': ['error', 2], + 'quotes': ['error', 'single'], + 'semi': ['error', 'always'], + + '@typescript-eslint/no-unused-vars': 'warn', + }, + }, +]; \ No newline at end of file diff --git a/app-shell/.prettierrc b/app-shell/.prettierrc new file mode 100644 index 0000000..bb087f2 --- /dev/null +++ b/app-shell/.prettierrc @@ -0,0 +1,11 @@ +{ + "singleQuote": true, + "tabWidth": 2, + "printWidth": 80, + "trailingComma": "all", + "quoteProps": "as-needed", + "jsxSingleQuote": true, + "bracketSpacing": true, + "bracketSameLine": false, + "arrowParens": "always" +} diff --git a/app-shell/.sequelizerc b/app-shell/.sequelizerc new file mode 100644 index 0000000..fe89188 --- /dev/null +++ b/app-shell/.sequelizerc @@ -0,0 +1,7 @@ +const path = require('path'); +module.exports = { + "config": path.resolve("src", "db", "db.config.js"), + "models-path": path.resolve("src", "db", "models"), + "seeders-path": path.resolve("src", "db", "seeders"), + "migrations-path": path.resolve("src", "db", "migrations") +}; \ No newline at end of file diff --git a/app-shell/Dockerfile b/app-shell/Dockerfile new file mode 100644 index 0000000..eb79c5d --- /dev/null +++ b/app-shell/Dockerfile @@ -0,0 +1,23 @@ +FROM node:20.15.1-alpine + +RUN apk update && apk add bash +# Create app directory +WORKDIR /usr/src/app + +# Install app dependencies +# A wildcard is used to ensure both package.json AND package-lock.json are copied +# where available (npm@5+) +COPY package*.json ./ + +RUN yarn install +# If you are building your code for production +# RUN npm ci --only=production + + +# Bundle app source +COPY . . + + +EXPOSE 4000 + +CMD [ "yarn", "start" ] diff --git a/app-shell/README.md b/app-shell/README.md new file mode 100644 index 0000000..c53191f --- /dev/null +++ b/app-shell/README.md @@ -0,0 +1,13 @@ +#test - template backend, + +#### Run App on local machine: + +##### Install local dependencies: + +- `yarn install` + +--- + +##### Start build: + +- `yarn start` diff --git a/app-shell/package.json b/app-shell/package.json new file mode 100644 index 0000000..e33f634 --- /dev/null +++ b/app-shell/package.json @@ -0,0 +1,42 @@ +{ + "name": "app-shell", + "description": "app-shell", + "scripts": { + "start": "node ./src/index.js" + }, + "dependencies": { + "@babel/parser": "^7.26.7", + "adm-zip": "^0.5.16", + "axios": "^1.6.7", + "bcrypt": "5.1.1", + "cors": "2.8.5", + "eslint": "^9.13.0", + "express": "4.18.2", + "formidable": "1.2.2", + "helmet": "4.1.1", + "json2csv": "^5.0.7", + "jsonwebtoken": "8.5.1", + "lodash": "4.17.21", + "moment": "2.30.1", + "multer": "^1.4.4", + "passport": "^0.7.0", + "passport-google-oauth2": "^0.2.0", + "passport-jwt": "^4.0.1", + "passport-microsoft": "^0.1.0", + "postcss": "^8.5.1", + "sequelize-json-schema": "^2.1.1", + "pg": "^8.13.3" + }, + "engines": { + "node": ">=18" + }, + "private": true, + "devDependencies": { + "@typescript-eslint/eslint-plugin": "^8.12.2", + "@typescript-eslint/parser": "^8.12.2", + "cross-env": "7.0.3", + "mocha": "8.1.3", + "nodemon": "^3.1.7", + "sequelize-cli": "6.6.2" + } +} diff --git a/app-shell/src/_schema.json b/app-shell/src/_schema.json new file mode 100644 index 0000000..6e52f1a --- /dev/null +++ b/app-shell/src/_schema.json @@ -0,0 +1,4 @@ +{ + "Initial version": "{\"iv\":\"cgYtu/qeXkNUlsSf\",\"encryptedData\":\"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\"}", + "1.1": "{\"iv\":\"FvMRPY7l/6tip8ah\",\"encryptedData\":\"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\"}" +} \ No newline at end of file diff --git a/app-shell/src/config.js b/app-shell/src/config.js new file mode 100644 index 0000000..09b0133 --- /dev/null +++ b/app-shell/src/config.js @@ -0,0 +1,16 @@ + + +const config = { + schema_encryption_key: process.env.SCHEMA_ENCRYPTION_KEY || '', + + project_uuid: 'd346520e-34c8-4488-890d-8254d64f8607', + flHost: process.env.NODE_ENV === 'production' ? 'https://flatlogic.com/projects' : 'http://localhost:3000/projects', + + gitea_domain: process.env.GITEA_DOMAIN || 'gitea.flatlogic.app', + gitea_username: process.env.GITEA_USERNAME || 'admin', + gitea_api_token: process.env.GITEA_API_TOKEN || null, + github_repo_url: process.env.GITHUB_REPO_URL || null, + github_token: process.env.GITHUB_TOKEN || null, +}; + +module.exports = config; diff --git a/app-shell/src/helpers.js b/app-shell/src/helpers.js new file mode 100644 index 0000000..1d918b5 --- /dev/null +++ b/app-shell/src/helpers.js @@ -0,0 +1,23 @@ +const jwt = require('jsonwebtoken'); +const config = require('./config'); + +module.exports = class Helpers { + static wrapAsync(fn) { + return function (req, res, next) { + fn(req, res, next).catch(next); + }; + } + + static commonErrorHandler(error, req, res, next) { + if ([400, 403, 404].includes(error.code)) { + return res.status(error.code).send(error.message); + } + + console.error(error); + return res.status(500).send(error.message); + } + + static jwtSign(data) { + return jwt.sign(data, config.secret_key, { expiresIn: '6h' }); + } +}; diff --git a/app-shell/src/index.js b/app-shell/src/index.js new file mode 100644 index 0000000..9672df9 --- /dev/null +++ b/app-shell/src/index.js @@ -0,0 +1,54 @@ +const express = require('express'); +const cors = require('cors'); +const app = express(); +const bodyParser = require('body-parser'); +const checkPermissions = require('./middlewares/check-permissions'); +const modifyPath = require('./middlewares/modify-path'); +const VCS = require('./services/vcs'); + +const executorRoutes = require('./routes/executor'); +const vcsRoutes = require('./routes/vcs'); + +// Function to initialize the Git repository +function initRepo() { + const projectId = '30719'; + return VCS.initRepo(projectId); +} + +// Start the Express app on APP_SHELL_PORT (4000) +function startServer() { + const PORT = 4000; + app.listen(PORT, () => { + console.log(`Listening on port ${PORT}`); + }); +} + +// Run Git check after the server is up +function runGitCheck() { + initRepo() + .then(result => { + console.log(result?.message ? result.message : result); + // Here you can add additional logic if needed + }) + .catch(err => { + console.error('Error during repo initialization:', err); + // Optionally exit the process if Git check is critical: + // process.exit(1); + }); +} + +app.use(cors({ origin: true })); +app.use(bodyParser.json()); +app.use(checkPermissions); +app.use(modifyPath); + +app.use('/executor', executorRoutes); +app.use('/vcs', vcsRoutes); + +// Start the app_shell server +startServer(); + +// Now perform Git check +runGitCheck(); + +module.exports = app; diff --git a/app-shell/src/middlewares/check-permissions.js b/app-shell/src/middlewares/check-permissions.js new file mode 100644 index 0000000..cc9d90a --- /dev/null +++ b/app-shell/src/middlewares/check-permissions.js @@ -0,0 +1,17 @@ +const config = require('../config'); + +function checkPermissions(req, res, next) { + const project_uuid = config.project_uuid; + const requiredHeader = 'X-Project-UUID'; + const headerValue = req.headers[requiredHeader.toLowerCase()]; + // Logging whatever request we're getting + console.log('Request:', req.url, req.method, req.body, req.headers); + + if (headerValue && headerValue === project_uuid) { + next(); + } else { + res.status(403).send({ error: 'Stop right there, criminal scum! Your project UUID is invalid or missing.' }); + } +} + +module.exports = checkPermissions; \ No newline at end of file diff --git a/app-shell/src/middlewares/modify-path.js b/app-shell/src/middlewares/modify-path.js new file mode 100644 index 0000000..0154280 --- /dev/null +++ b/app-shell/src/middlewares/modify-path.js @@ -0,0 +1,8 @@ +function modifyPath(req, res, next) { + if (req.body && req.body.path) { + req.body.path = '../../../' + req.body.path; + } + next(); + } + +module.exports = modifyPath; \ No newline at end of file diff --git a/app-shell/src/routes/executor.js b/app-shell/src/routes/executor.js new file mode 100644 index 0000000..588cfff --- /dev/null +++ b/app-shell/src/routes/executor.js @@ -0,0 +1,312 @@ +const express = require('express'); +const multer = require('multer'); +const upload = multer({ dest: 'uploads/' }); +const fs = require('fs'); + +const ExecutorService = require('../services/executor'); + +const wrapAsync = require('../helpers').wrapAsync; + +const router = express.Router(); + +router.post( + '/read_project_tree', + wrapAsync(async (req, res) => { + const { path } = req.body; + const tree = await ExecutorService.readProjectTree(path); + res.status(200).send(tree); + }), +); + +router.post( + '/read_file', + wrapAsync(async (req, res) => { + const { path, showLines } = req.body; + const content = await ExecutorService.readFileContents(path, showLines); + res.status(200).send(content); + }), +); + +router.post( + '/count_file_lines', + wrapAsync(async (req, res) => { + const { path } = req.body; + const content = await ExecutorService.countFileLines(path); + res.status(200).send(content); + }), +); + +// router.post( +// '/read_file_header', +// wrapAsync(async (req, res) => { +// const { path, N } = req.body; +// try { +// const header = await ExecutorService.readFileHeader(path, N); +// res.status(200).send(header); +// } catch (error) { +// res.status(500).send({ +// error: true, +// message: error.message, +// details: error.details || error.stack, +// validation: error.validation +// }); +// } +// }), +// ); + +router.post( + '/read_file_line_context', + wrapAsync(async (req, res) => { + const { path, lineNumber, windowSize, showLines } = req.body; + try { + const context = await ExecutorService.readFileLineContext(path, lineNumber, windowSize, showLines); + res.status(200).send(context); + } catch (error) { + res.status(500).send({ + error: true, + message: error.message, + details: error.details || error.stack, + validation: error.validation + }); + } + }), +); + +router.post( + '/write_file', + wrapAsync(async (req, res) => { + const { path, fileContents, comment } = req.body; + try { + await ExecutorService.writeFile(path, fileContents, comment); + res.status(200).send({ message: 'File written successfully' }); + } catch (error) { + res.status(500).send({ + error: true, + message: error.message, + details: error.details || error.stack, + validation: error.validation + }); + } + }), +); + +router.post( + '/insert_file_content', + wrapAsync(async (req, res) => { + const { path, lineNumber, newContent, message } = req.body; + try { + await ExecutorService.insertFileContent(path, lineNumber, newContent, message); + res.status(200).send({ message: 'File written successfully' }); + } catch (error) { + res.status(500).send({ + error: true, + message: error.message, + details: error.details || error.stack, + validation: error.validation + }); + } + }), +); + +router.post( + '/replace_file_line', + wrapAsync(async (req, res) => { + const { path, lineNumber, newText } = req.body; + try { + const result = await ExecutorService.replaceFileLine(path, lineNumber, newText); + res.status(200).send(result); + } catch (error) { + res.status(500).send({ + error: true, + message: error.message, + details: error.details || error.stack, + validation: error.validation + }); + } + }), +); +router.post( + '/replace_file_chunk', + wrapAsync(async (req, res) => { + const { path, startLine, endLine, newCode } = req.body; + try { + const result = await ExecutorService.replaceFileChunk(path, startLine, endLine, newCode); + res.status(200).send(result); + } catch (error) { + res.status(500).send({ + error: true, + message: error.message, + details: error.details || error.stack, + validation: error.validation + }); + } + }), +); + +router.post( + '/delete_file_lines', + wrapAsync(async (req, res) => { + const { path, startLine, endLine, message } = req.body; + try { + const result = await ExecutorService.deleteFileLines(path, startLine, endLine, message); + res.status(200).send(result); + } catch (error) { + res.status(500).send({ + error: true, + message: error.message, + details: error.details || error.stack, + validation: error.validation + }); + } + }), +); + +router.post( + '/validate_file', + wrapAsync(async (req, res) => { + const { path } = req.body; + try { + const validationResult = await ExecutorService.validateFile(path); + res.status(200).send({ validationResult }); + } catch (error) { + res.status(500).send({ + error: true, + message: error.message, + details: error.details || error.stack, + validation: error.validation + }); + } + }), +); + + +router.post( + '/check_frontend_runtime_error', + wrapAsync(async (req, res) => { + try { + const result = await ExecutorService.checkFrontendRuntimeLogs(); + res.status(200).send(result); + } catch (error) { + res.status(500).send({ error: error }); + } + }), +); + + +router.post( + '/replace_code_block', + wrapAsync(async (req, res) => { + const {path, oldCode, newCode, message} = req.body; + try { + const response = await ExecutorService.replaceCodeBlock(path, oldCode, newCode, message); + res.status(200).send(response); + } catch (error) { + res.status(500).send({ + error: true, + message: error.message, + details: error.details || error.stack, + validation: error.validation + }) + } + }) +) + +router.post('/update_project_files_from_scheme', + upload.single('file'), // 'file' - name of the field in the form + async (req, res) => { + console.log('Request received'); + console.log('Headers:', req.headers); + if (!req.file) { + return res.status(400).json({ error: 'No file uploaded' }); + } + + console.log('File info:', { + originalname: req.file.originalname, + path: req.file.path, + size: req.file.size, + mimetype: req.file.mimetype + }); + + try { + console.log('Starting update process...'); + const result = await ExecutorService.updateProjectFilesFromScheme(req.file.path); + console.log('Update completed, result:', result); + + console.log('Removing temp file...'); + fs.unlinkSync(req.file.path); + console.log('Temp file removed'); + + console.log('Sending response...'); + return res.json(result); + } catch (error) { + console.error('Error in route handler:', error); + if (req.file) { + try { + fs.unlinkSync(req.file.path); + console.log('Temp file removed after error'); + } catch (unlinkError) { + console.error('Error removing temp file:', unlinkError); + } + } + console.error('Update project files error:', error); + return res.status(500).json({ + error: error.message, + stack: process.env.NODE_ENV === 'development' ? error.stack : undefined + }); + } + } +); + +router.post( + '/get_db_schema', + wrapAsync(async (req, res) => { + try { + + const jsonSchema = await ExecutorService.getDBSchema(); + res.status(200).send({ jsonSchema }); + } catch (error) { + res.status(500).send({ error: error }); + } + }), +); + +router.post( + '/execute_sql', + wrapAsync(async (req, res) => { + try { + const { query } = req.body; + const result = await ExecutorService.executeSQL(query); + res.status(200).send(result); + } catch (error) { + res.status(500).send({ error: error }); + } + }), +); + +router.post( + '/search_files', + wrapAsync(async (req, res) => { + try { + const { searchStrings } = req.body; + + if ( + typeof searchStrings !== 'string' && + !( + Array.isArray(searchStrings) && + searchStrings.every(item => typeof item === 'string') + ) + ) { + return res.status(400).send({ error: 'searchStrings must be a string or an array of strings' }); + } + + const result = await ExecutorService.searchFiles(searchStrings); + res.status(200).send(result); + } catch (error) { + res.status(500).send({ error: error.message }); + } + }), +); + +router.use('/', require('../helpers').commonErrorHandler); + +module.exports = router; diff --git a/app-shell/src/routes/vcs.js b/app-shell/src/routes/vcs.js new file mode 100644 index 0000000..926498d --- /dev/null +++ b/app-shell/src/routes/vcs.js @@ -0,0 +1,40 @@ +const express = require('express'); +const wrapAsync = require('../helpers').wrapAsync; // Ваша обёртка для обработки асинхронных маршрутов +const VSC = require('../services/vcs'); +const router = express.Router(); + +router.post('/init', wrapAsync(async (req, res) => { + const result = await VSC.initRepo(); + res.status(200).send(result); +})); + +router.post('/commit', wrapAsync(async (req, res) => { + const { message, files, dev_schema } = req.body; + const result = await VSC.commitChanges(message, files, dev_schema); + res.status(200).send(result); +})); + +router.post('/log', wrapAsync(async (req, res) => { + const result = await VSC.getLog(); + res.status(200).send(result); +})); + +router.post('/rollback', wrapAsync(async (req, res) => { + const { ref } = req.body; + // const result = await VSC.checkout(ref); + const result = await VSC.revert(ref); + res.status(200).send(result); +})); + +router.post('/sync-to-stable', wrapAsync(async (req, res) => { + const result = await VSC.mergeDevIntoMaster(); + res.status(200).send(result); +})); + +router.post('/reset-dev', wrapAsync(async (req, res) => { + const result = await VSC.resetDevBranch(); + res.status(200).send(result); +})); + +router.use('/', require('../helpers').commonErrorHandler); +module.exports = router; \ No newline at end of file diff --git a/app-shell/src/services/database.js b/app-shell/src/services/database.js new file mode 100644 index 0000000..bf8f3a9 --- /dev/null +++ b/app-shell/src/services/database.js @@ -0,0 +1,88 @@ +// Database.js +const { Client } = require('pg'); +const config = require('../../../backend/src/db/db.config'); + +const env = process.env.NODE_ENV || 'development'; +const dbConfig = config[env]; + +class Database { + constructor() { + this.client = new Client({ + user: dbConfig.username, + password: dbConfig.password, + database: dbConfig.database, + host: dbConfig.host, + port: dbConfig.port + }); + + // Connect once, reuse the client + this.client.connect().catch(err => { + console.error('Error connecting to the database:', err); + throw err; + }); + } + + async executeSQL(query) { + try { + const result = await this.client.query(query); + return { + success: true, + rows: result.rows + }; + } catch (error) { + console.error('Error executing query:', error); + throw error; + } + } + + // Method to fetch simple table/column info from 'information_schema' + // (You can expand this to handle constraints, indexes, etc.) + async getDBSchema(schemaName = 'public') { + try { + const tableQuery = ` + SELECT table_name + FROM information_schema.tables + WHERE table_schema = $1 + AND table_type = 'BASE TABLE' + ORDER BY table_name + `; + + const columnQuery = ` + SELECT table_name, column_name, data_type, is_nullable + FROM information_schema.columns + WHERE table_schema = $1 + ORDER BY table_name, ordinal_position + `; + + const [tablesResult, columnsResult] = await Promise.all([ + this.client.query(tableQuery, [schemaName]), + this.client.query(columnQuery, [schemaName]), + ]); + + // Build a simple schema object: + const tables = tablesResult.rows.map(row => row.table_name); + const columnsByTable = {}; + + columnsResult.rows.forEach(row => { + const { table_name, column_name, data_type, is_nullable } = row; + if (!columnsByTable[table_name]) columnsByTable[table_name] = []; + columnsByTable[table_name].push({ column_name, data_type, is_nullable }); + }); + + // Combine tables with their columns + return tables.map(table => ({ + table, + columns: columnsByTable[table] || [], + })); + } catch (error) { + console.error('Error fetching schema:', error); + throw error; + } + } + + async close() { + await this.client.end(); + } +} + +module.exports = new Database(); diff --git a/app-shell/src/services/executor.js b/app-shell/src/services/executor.js new file mode 100644 index 0000000..eecb869 --- /dev/null +++ b/app-shell/src/services/executor.js @@ -0,0 +1,1206 @@ +const fs = require('fs').promises; +const os = require('os'); +const path = require('path'); +const AdmZip = require('adm-zip'); +const { exec } = require('child_process'); +const util = require('util'); +const ProjectEventsService = require('./project-events'); +const config = require('../config.js'); +// Babel Parser for JS/TS/TSX +const babelParser = require('@babel/parser'); +const babelParse = babelParser.parse; + +// Local App DB Connection +const database = require('./database'); + +// PostCSS for CSS +const postcss = require('postcss'); + +const execAsync = util.promisify(exec); + +module.exports = class ExecutorService { + static async readProjectTree(directoryPath) { + const paths = { + frontend: '../../../frontend', + backend: '../../../backend', + default: '../../../' + }; + + try { + const publicDir = path.join(__dirname, paths[directoryPath] || directoryPath || paths.default); + + return await getDirectoryTree(publicDir); + } catch (error) { + console.error('Error reading directory:', error); + + throw error; + } + } + + static async readFileContents(filePath, showLines) { + try { + const fullPath = path.join(__dirname, filePath); + const content = await fs.readFile(fullPath, 'utf8'); + + if (showLines) { + const lines = content.split('\n'); + + const lineObject = {}; + lines.forEach((line, index) => { + lineObject[index + 1] = line; + }); + + return lineObject; + } else { + return content; + } + } catch (error) { + console.error('Error reading file:', error); + throw error; + } + } + + static async countFileLines(filePath) { + try { + const fullPath = path.join(__dirname, filePath); + + // Check file exists + await fs.access(fullPath); + + // Read file content + const content = await fs.readFile(fullPath, 'utf8'); + + // Split by newline and count + const lines = content.split('\n'); + + return { + success: true, + lineCount: lines.length + }; + } catch (error) { + console.error('Error counting file lines:', error); + return { + success: false, + message: error.message + }; + } + } + + // static async readFileHeader(filePath, N = 30) { + // try { + // const fullPath = path.join(__dirname, filePath); + // const content = await fs.readFile(fullPath, 'utf8'); + // const lines = content.split('\n'); + // + // if (lines.length < N) { + // return { error: `File has less than ${N} lines` }; + // } + // + // const headerLines = lines.slice(0, Math.min(50, lines.length)); + // + // const lineObject = {}; + // headerLines.forEach((line, index) => { + // lineObject[index + 1] = line; + // }); + // + // return lineObject; + // } catch (error) { + // console.error('Error reading file header:', error); + // throw error; + // } + // } + + static async readFileLineContext(filePath, lineNumber, windowSize, showLines) { + try { + const fullPath = path.join(__dirname, filePath); + const content = await fs.readFile(fullPath, 'utf8'); + const lines = content.split('\n'); + + const start = Math.max(0, lineNumber - windowSize); + const end = Math.min(lines.length, lineNumber + windowSize + 1); + + const contextLines = lines.slice(start, end); + + if (showLines) { + const lineObject = {}; + contextLines.forEach((line, index) => { + lineObject[start + index + 1] = line; + }); + + return lineObject; + } else { + return contextLines.join('\n'); + } + } catch (error) { + console.error('Error reading file line context:', error); + throw error; + } + } + + static async validateFile(filePath) { + console.log('Validating file:', filePath); + + // Read file content + let content; + try { + content = await fs.readFile(filePath, 'utf8'); + } catch (err) { + throw new Error(`Could not read file: ${filePath}\n${err.message}`); + } + + // Determine file extension + let ext = path.extname(filePath).toLowerCase(); + if (ext === '.temp') { + ext = path.extname(filePath.slice(0, -5)).toLowerCase(); + } + + try { + switch (ext) { + case '.js': + case '.ts': + case '.tsx': { + // Parse JS/TS/TSX with Babel + babelParse(content, { + sourceType: 'module', + // plugins array covers JS, TS, TSX, and optional JS flavors + plugins: ['jsx', 'typescript'] + }); + break; + } + + case '.css': { + // Parse CSS with PostCSS + postcss.parse(content); + break; + } + + default: { + // If the extension isn't recognized, assume it's "valid" + // or you could throw an error to force a known extension + console.warn(`No validation implemented for extension "${ext}". Skipping syntax check.`); + } + } + + // If parsing succeeded, return true + return true; + + } catch (parseError) { + // Rethrow parse errors with a friendlier message + throw parseError; + } + } + + static async checkFrontendRuntimeLogs() { + const frontendLogPath = '../frontend/json/runtimeError.json'; + + try { + // Check if file exists + try { + console.log('Accessing frontend logs:', frontendLogPath); + await fs.access(frontendLogPath); + } catch (error) { + console.log('Frontend logs not found:', error); + // File doesn't exist - return empty object + return {runtime_error: {}}; + } + + // File exists, try to read it + try { + // Read the entire file instead of using tail + const fileContent = await fs.readFile(frontendLogPath, 'utf8'); + console.log('Reading frontend logs:', fileContent); + + // Handle empty file + if (!fileContent || fileContent.trim() === '') { + return {runtime_error: {}}; + } + + // Parse JSON content + const runtime_error = JSON.parse(fileContent); + + console.log('Parsed frontend logs:', runtime_error); + return {runtime_error}; + } catch (error) { + // Error reading or parsing file + console.error('Error reading frontend runtime logs:', error); + return {runtime_error: {}}; + } + } catch (error) { + // Unexpected error + console.log('Error checking frontend logs:', error); + return {runtime_error: {}}; + } + } + + static async writeFile(filePath, fileContents, comment) { + try { + console.log(comment) + const fullPath = path.join(__dirname, filePath); + + // Write to a temp file first + const tempPath = `${fullPath}.temp`; + await fs.writeFile(tempPath, fileContents, 'utf8'); + + // Validate the temp file + await this.validateFile(tempPath); + + // Rename temp file to original path + await fs.rename(tempPath, fullPath); + + return true; + } catch (error) { + console.error('Error writing file:', error); + throw error; + } + } + + static async insertFileContent(filePath, lineNumber, newContent, message) { + try { + const fullPath = path.join(__dirname, filePath); + + // Check file exists + await fs.access(fullPath); + + // Read and split by line + const content = await fs.readFile(fullPath, 'utf8'); + const lines = content.split('\n'); + + // Ensure lineNumber is within [1 ... lines.length + 1] + // 1 means "insert at the very first line" + // lines.length + 1 means "append at the end" + if (lineNumber < 1) { + lineNumber = 1; + } + if (lineNumber > lines.length + 1) { + lineNumber = lines.length + 1; + } + + // Convert to 0-based index + const insertIndex = lineNumber - 1; + + // Prepare preview + const preview = { + insertionLine: lineNumber, + insertedLines: newContent.split('\n') + }; + + // Insert newContent lines at the specified index + lines.splice(insertIndex, 0, ...newContent.split('\n')); + + // Write changes to a temp file first + const updatedContent = lines.join('\n'); + const tempPath = `${fullPath}.temp`; + await fs.writeFile(tempPath, updatedContent, 'utf8'); + + await this.validateFile(tempPath); + + // Rename temp file to original path + await fs.rename(tempPath, fullPath); + + return { + success: true + }; + + } catch (error) { + console.error('Error inserting file content:', error); + throw error; + } + } + + static async replaceFileLine(filePath, lineNumber, newText, message = null) { + const fullPath = path.join(__dirname, filePath); + try { + + try { + await fs.access(fullPath); + } catch (error) { + throw new Error(`File not found: ${filePath}`); + } + + const content = await fs.readFile(fullPath, 'utf8'); + const lines = content.split('\n'); + + if (lineNumber < 1 || lineNumber > lines.length) { + throw new Error(`Invalid line number: ${lineNumber}. File has ${lines.length} lines`); + } + + if (typeof newText !== 'string') { + throw new Error('New text must be a string'); + } + + const preview = { + oldLine: lines[lineNumber - 1], + newLine: newText, + lineNumber: lineNumber + }; + + lines[lineNumber - 1] = newText; + const newContent = lines.join('\n'); + const tempPath = `${fullPath}.temp`; + await fs.writeFile(tempPath, newContent, 'utf8'); + + await this.validateFile(tempPath); + + await fs.rename(tempPath, fullPath); + + return { + success: true + }; + + } catch (error) { + console.error('Error updating file line:', error); + + try { + await fs.unlink(`${fullPath}.temp`); + } catch { + } + + throw { + error: error, + message: error.message, + details: error.stack + }; + } + } + + static async replaceFileChunk(filePath, startLine, endLine, newCode) { + try { + // Check if this is a single-line change + const newCodeLines = newCode.split('\n'); + if (newCodeLines.length === 1 && endLine === startLine) { + // Redirect to replace_file_line + return await this.replaceFileLine(filePath, startLine, newCode); + } + + const fullPath = path.join(__dirname, filePath); + + // Check if file exists + try { + await fs.access(fullPath); + } catch (error) { + throw new Error(`File not found: ${filePath}`); + } + + const content = await fs.readFile(fullPath, 'utf8'); + const lines = content.split('\n'); + + // Adjust line numbers to array indices (subtract 1) + const startIndex = startLine - 1; + const endIndex = endLine - 1; + + // Validate input parameters + if (startIndex < 0 || endIndex >= lines.length || startIndex > endIndex) { + throw new Error(`Invalid line range: ${startLine}-${endLine}. File has ${lines.length} lines`); + } + + // Check type of new code + if (typeof newCode !== 'string') { + throw new Error('New code must be a string'); + } + + // Create changes preview + const preview = { + oldLines: lines.slice(startIndex, endIndex + 1), + newLines: newCode.split('\n'), + startLine, + endLine + }; + + // Apply changes to temp file first + lines.splice(startIndex, endIndex - startIndex + 1, ...newCode.split('\n')); + const newContent = lines.join(os.EOL); + const tempPath = `${fullPath}.temp`; + await fs.writeFile(tempPath, newContent, 'utf8'); + await this.validateFile(tempPath); + // Apply changes if all validations passed + await fs.rename(tempPath, fullPath); + + return { + success: true + }; + + } catch (error) { + console.error('Error updating file slice:', error); + + // Clean up temp file if exists + try { + await fs.unlink(`${fullPath}.temp`); + } catch { + } + + throw { + error: error, + message: error.message, + details: error.details || error.stack + }; + } + } + + static async replaceCodeBlock(filePath, oldCode, newCode, message) { + try { + console.log(message); + const fullPath = path.join(__dirname, filePath); + + // Check file exists + await fs.access(fullPath); + + // Read file content + let content = await fs.readFile(fullPath, 'utf8'); + + // A small helper to unify line breaks to just `\n` + const unifyLineBreaks = (str) => str.replace(/\r\n/g, '\n'); + + // Normalize line breaks in file content, oldCode, and newCode + content = unifyLineBreaks(content); + oldCode = unifyLineBreaks(oldCode); + newCode = unifyLineBreaks(newCode); + + // Optional: Trim trailing spaces or handle other whitespace normalization if needed + // oldCode = oldCode.trim(); + // newCode = newCode.trim(); + + // Check if oldCode actually exists in the content + const index = content.indexOf(oldCode); + if (index === -1) { + return { + success: false, + message: 'Old code not found in file.' + }; + } + + // Create a preview before replacing + const preview = { + oldCodeSnippet: oldCode, + newCodeSnippet: newCode + }; + + // Perform replacement (single occurrence). For multiple, use replaceAll or a loop. + // If you want a global replacement, consider: + // content = content.split(oldCode).join(newCode); + content = content.replace(oldCode, newCode); + + // Write to a temp file first + const tempPath = `${fullPath}.temp`; + await fs.writeFile(tempPath, content, 'utf8'); + + await this.validateFile(tempPath); + // Rename temp file to original + await fs.rename(tempPath, fullPath); + + return { + success: true + }; + + } catch (error) { + console.error('Error replacing code:', error); + return { + error: error, + message: error.message, + details: error.details || error.stack + }; + } + } + + //todo add validation + static async deleteFileLines(filePath, startLine, endLine, veryShortDescription) { + try { + const fullPath = path.join(__dirname, filePath); + + // Check if file exists + await fs.access(fullPath); + + // Read file content + const content = await fs.readFile(fullPath, 'utf8'); + const lines = content.split('\n'); + + // Convert to zero-based indices + const startIndex = startLine - 1; + const endIndex = endLine - 1; + + // Validate range + if (startIndex < 0 || endIndex >= lines.length || startIndex > endIndex) { + throw new Error( + `Invalid line range: ${startLine}-${endLine}. File has ${lines.length} lines` + ); + } + + // Prepare a preview of the lines being deleted + const preview = { + deletedLines: lines.slice(startIndex, endIndex + 1), + startLine, + endLine + }; + + // Remove lines + lines.splice(startIndex, endIndex - startIndex + 1); + + // Join remaining lines and write to a temporary file + const newContent = lines.join('\n'); + const tempPath = `${fullPath}.temp`; + await fs.writeFile(tempPath, newContent, 'utf8'); + + await this.validateFile(tempPath); + // Rename temp file to original + await fs.rename(tempPath, fullPath); + + return { + success: true + }; + + } catch (error) { + console.error('Error deleting file lines:', error); + return { + error: error, + message: error.message, + details: error.details || error.stack + }; + } + } + + static async validateTypeScript(filePath, content = null) { + try { + // Basic validation of JSX syntax + const jsxErrors = []; + + if (content !== null) { + // Check for matching braces + if ((content.match(/{/g) || []).length !== (content.match(/}/g) || []).length) { + jsxErrors.push("Unmatched curly braces"); + } + + // Check for invalid syntax in JSX attributes + if (content.includes('label={')) { + if (!content.match(/label={[^}]+}/)) { + jsxErrors.push("Invalid label attribute syntax"); + } + } + + if (jsxErrors.length > 0) { + return { + valid: false, + errors: jsxErrors.map(error => ({ + code: 'JSX_SYNTAX_ERROR', + severity: 'error', + location: '', + message: error + })) + }; + } + } + + return { + valid: true, + errors: [], + errorCount: 0, + warningCount: 0 + }; + + } catch (error) { + console.error('TypeScript validation error:', error); + return { + valid: false, + errors: [{ + code: 'VALIDATION_FAILED', + severity: 'error', + location: '', + message: `TypeScript validation error: ${error.message}` + }], + errorCount: 1, + warningCount: 0 + }; + } + } + + static async validateBackendFiles(backendPath) { + try { + // Check for syntax errors + await execAsync(`node --check ${backendPath}/src/index.js`); + + // Try to run the code in a test environment + const testProcess = exec( + 'NODE_ENV=test node -e "try { require(\'./src/index.js\') } catch(e) { console.error(e); process.exit(1) }"', + {cwd: backendPath} + ); + + return new Promise((resolve) => { + let output = ''; + let error = ''; + + testProcess.stdout.on('data', (data) => { + output += data; + }); + + testProcess.stderr.on('data', (data) => { + error += data; + }); + + testProcess.on('close', (code) => { + if (code === 0) { + resolve({valid: true}); + } else { + resolve({ + valid: false, + error: error || output + }); + } + }); + + // Timeout on validation + setTimeout(() => { + testProcess.kill(); + resolve({ + valid: true, + warning: 'Validation timeout, but no immediate errors found' + }); + }, 5000); + }); + } catch (error) { + return { + valid: false, + error: error.message + }; + } + } + + static async createBackup(ROOT_PATH) { + const timestamp = new Date().toISOString().replace(/[:.]/g, '-'); + const backupDir = path.join(ROOT_PATH, 'backups', timestamp); + + try { + await fs.mkdir(path.join(ROOT_PATH, 'backups'), {recursive: true}); + + const dirsToBackup = ['frontend', 'backend']; + + for (const dir of dirsToBackup) { + const sourceDir = path.join(ROOT_PATH, dir); + const targetDir = path.join(backupDir, dir); + + await fs.mkdir(targetDir, {recursive: true}); + + await execAsync( + `cd "${sourceDir}" && ` + + `find . -type f -not -path "*/node_modules/*" -not -path "*/\\.*" | ` + + `while read file; do ` + + `mkdir -p "${targetDir}/$(dirname "$file")" && ` + + `cp "$file" "${targetDir}/$file"; ` + + `done` + ); + } + + console.log('Backup created at:', backupDir); + return backupDir; + } catch (error) { + console.error('Error creating backup:', error); + throw error; + } + } + + static async restoreFromBackup(backupDir, ROOT_PATH) { + try { + console.log('Restoring from backup:', backupDir); + await execAsync(`rm -rf ${ROOT_PATH}/backend/*`); + await execAsync(`cp -r ${backupDir}/* ${ROOT_PATH}/backend/`); + return true; + } catch (error) { + console.error('Error restoring from backup:', error); + throw error; + } + } + + static async updateProjectFilesFromScheme(zipFilePath) { + const MAX_FILE_SIZE = 10 * 1024 * 1024; + const ROOT_PATH = path.join(__dirname, '../../../'); + + try { + console.log('Checking file access...'); + await fs.access(zipFilePath); + + console.log('Getting file stats...'); + const stats = await fs.stat(zipFilePath); + console.log('File size:', stats.size); + + if (stats.size > MAX_FILE_SIZE) { + console.log('File size exceeds limit'); + return {success: false, error: 'File size exceeds limit'}; + } + + // Copying zip file to /tmp + const tempZipPath = path.join('/tmp', path.basename(zipFilePath)); + await fs.copyFile(zipFilePath, tempZipPath); + + // Launching background update process + const servicesUpdate = (async () => { + try { + console.log('Stopping services...'); + + // await ProjectEventsService.sendEvent('SERVICE_STOP_STARTED', { + // message: 'Stopping services', + // timestamp: new Date().toISOString() + // }); + + await stopServices(); + + // await ProjectEventsService.sendEvent('SERVICE_STOP_COMPLETED', { + // message: 'Services stopped successfully', + // timestamp: new Date().toISOString() + // }); + + console.log('Creating zip instance...'); + const zip = new AdmZip(tempZipPath); + + console.log('Extracting files to:', ROOT_PATH); + zip.extractAllTo(ROOT_PATH, true); + console.log('Files extracted'); + + const removedFilesPath = path.join(ROOT_PATH, 'removed_files.json'); + try { + await fs.access(removedFilesPath); + const removedFilesContent = await fs.readFile(removedFilesPath, 'utf8'); + const filesToRemove = JSON.parse(removedFilesContent); + await removeFiles(filesToRemove, ROOT_PATH); + + await fs.unlink(removedFilesPath); + } catch (error) { + console.log('No removed files to process or error accessing removed_files.json:', error); + } + + // Remove temp zip file + await fs.unlink(tempZipPath); + + // await ProjectEventsService.sendEvent('SERVICE_START_STARTED', { + // message: 'Starting services', + // timestamp: new Date().toISOString() + // }); + + // Start services after a delay + setTimeout(async () => { + try { + await startServices(); + console.log('Services started successfully'); + + await ProjectEventsService.sendEvent('SERVICE_START_COMPLETED', { + message: 'All files have been successfully retrieved and applied.', + timestamp: new Date().toISOString() + }); + } catch (e) { + console.error('Failed to start services:', e); + } + }, 3000); + + } catch (error) { + console.error('Error in service update process:', error); + } + })(); + + servicesUpdate.catch(error => { + console.error('Background update process failed:', error); + }); + + console.log('Returning immediate response'); + + return { + success: true, + message: 'Update process initiated' + }; + + } catch (error) { + console.error('Critical error in updateProjectFilesFromScheme:', error); + return { + success: false, + error: error.message + }; + } + } + + static async getDBSchema() { + try { + return await database.getDBSchema(); + } catch (error) { + console.error('Error reading schema:', error); + throw { + error: error, + message: error.message, + details: error.details || error.stack + }; + } + } + + static async executeSQL(query) { + try { + return await database.executeSQL(query); + } catch (error) { + console.error('Error executing query:', error); + throw { + error: error, + message: error.message, + details: error.details || error.stack + }; + } + } + + static async stopServices() { + return await stopServices(); + } + + static async startServices() { + return await startServices(); + } + + static async checkServicesStatus() { + return await checkStatus(); + } + + static async searchFiles(searchStrings) { + const results = {}; + const ROOT_PATH = path.join(__dirname, '../../../'); + const directories = [`${ROOT_PATH}backend/`, `${ROOT_PATH}frontend/`]; + const excludeDirs = ['node_modules', 'build', 'app_shell']; + + if (!Array.isArray(searchStrings)) { + searchStrings = [searchStrings]; + } + + for (const searchString of searchStrings) { + try { + for (const directoryPath of directories) { + const findCommand = `find '${directoryPath}' -type f ${excludeDirs.map(dir => `-not -path "*/${dir}/*"`).join(' ')} -print | xargs grep -nH -C 1 -e '${searchString}'`; + + try { + const { stdout } = await execAsync(findCommand); + + const lines = stdout.trim().split('\n').filter(line => line !== ''); + const searchResults = {}; + // searchResults['__raw_lines__'] = lines; + + for (let i = 0; i < lines.length; i++) { + const line = lines[i]; + const parts = line.split(':'); + let filePath = ''; + let lineNumberStr = ''; + let content = ''; + let relativeFilePath = ''; + let lineNum = null; + + if (parts.length >= 3 && !parts[0].includes('-')) { + filePath = parts.shift(); + lineNumberStr = parts.shift(); + content = parts.join(':').trim(); + relativeFilePath = filePath.replace(`${ROOT_PATH}`, ''); + lineNum = parseInt(lineNumberStr, 10) + 1; + } else { + content = line.trim(); + } + + const context = []; + if (i > 0 && lines[i - 1].includes(':')) { + const prevLineParts = lines[i - 1].split(':'); + if (prevLineParts.length >= 3 && !prevLineParts[0].includes('-')) { + prevLineParts.shift(); + prevLineParts.shift(); + context.push(prevLineParts.join(':').trim()); + } else { + context.push(lines[i - 1].trim()); + } + } + context.push(content); + if (i < lines.length - 1 && lines[i + 1].includes(':')) { + const nextLineParts = lines[i + 1].split(':'); + if (nextLineParts.length >= 3 && !nextLineParts[0].includes('-')) { + nextLineParts.shift(); + nextLineParts.shift(); + context.push(nextLineParts.join(':').trim()); + } else { + context.push(lines[i + 1].trim()); + } + } + + if (relativeFilePath && !searchResults[relativeFilePath]) { + searchResults[relativeFilePath] = []; + } + if (relativeFilePath) { + searchResults[relativeFilePath].push({ + lineNumber: lineNum, + context: context.join('\n'), + // __filePathAndLine__: filePath + ':' + lineNumberStr + ':' + content, + }); + } + } + + if (!results[searchString]) { + results[searchString] = {}; + } + Object.assign(results[searchString], searchResults); + } catch (err) { + if (!err.message.includes('No such file or directory') && !err.stderr.includes('No such file or directory')) { + console.error(`Error using find/grep for "${searchString}" in ${directoryPath}:`, err); + } + } + } + } catch (error) { + console.error(`Error searching for "${searchString}":`, error); + results[searchString] = { error: error.message }; + } + } + + return results; + } + +} + +async function getDirectoryTree(dirPath) { + const entries = await fs.readdir(dirPath, { withFileTypes: true }); + const result = {}; + + for (const entry of entries) { + const fullPath = path.join(dirPath, entry.name); + + if (entry.isDirectory() && ( + entry.name === 'node_modules' || + entry.name === 'app-shell' || + entry.name === '.git' || + entry.name === '.idea' + )) { + continue; + } + + const relativePath = fullPath.replace('/app', ''); + + if (entry.isDirectory()) { + const subTree = await getDirectoryTree(fullPath); + Object.keys(subTree).forEach(key => { + result[key.replace('/app', '')] = subTree[key]; + }); + } else { + const fileContent = await fs.readFile(fullPath, 'utf8'); + const lineCount = fileContent.split('\n').length; + result[relativePath] = lineCount; + } + } + + return result; +} + +async function stopServices() { + try { + console.log('Finding service processes...'); + // await ProjectEventsService.sendEvent('SERVICE_STOP_INITIATED', { + // message: 'Initiating service stop', + // timestamp: new Date().toISOString() + // }); + // Frontend stopping + const { stdout: frontendProcess } = await execAsync("ps -o pid,cmd | grep '[n]ext-server' | awk '{print $1}'"); + if (frontendProcess.trim()) { + console.log('Stopping frontend, pid:', frontendProcess.trim()); + + // await ProjectEventsService.sendEvent('FRONTEND_STOP_STARTED', { + // message: `Stopping frontend, pid: ${frontendProcess.trim()}`, + // timestamp: new Date().toISOString() + // }); + + // await execAsync(`kill -15 ${frontendProcess.trim()}`); + + // await ProjectEventsService.sendEvent('FRONTEND_STOP_COMPLETED', { + // message: 'Frontend stopped successfully', + // timestamp: new Date().toISOString() + // }); + } + + // Backend stopping + const { stdout: backendProcess } = await execAsync("ps -o pid,cmd | grep '[n]ode ./src/index.js' | grep -v app-shell | awk '{print $1}'"); + if (backendProcess.trim()) { + console.log('Stopping backend, pid:', backendProcess.trim()); + + // await ProjectEventsService.sendEvent('BACKEND_STOP_STARTED', { + // message: `Stopping backend, pid: ${backendProcess.trim()}`, + // timestamp: new Date().toISOString() + // }); + + // await execAsync(`kill -15 ${backendProcess.trim()}`); + + // await ProjectEventsService.sendEvent('BACKEND_STOP_COMPLETED', { + // message: 'Backend stopped successfully', + // timestamp: new Date().toISOString() + // }); + } + + await new Promise(resolve => setTimeout(resolve, 4000)); + + + // await ProjectEventsService.sendEvent('SERVICE_STOP_COMPLETED', { + // message: 'All services stopped successfully', + // timestamp: new Date().toISOString() + // }); + + return { success: true }; + } catch (error) { + console.error('Error stopping services:', error); + + await ProjectEventsService.sendEvent('SERVICE_STOP_FAILED', { + message: 'Error stopping services', + error: error.message, + timestamp: new Date().toISOString() + }); + + return { success: false, error: error.message }; + } +} + +async function startServices() { + try { + console.log('Starting services...'); + // await ProjectEventsService.sendEvent('SERVICE_START_INITIATED', { + // message: 'Initiating service start', + // timestamp: new Date().toISOString() + // }); + + // await ProjectEventsService.sendEvent('FRONTEND_START_STARTED', { + // message: 'Starting frontend service', + // timestamp: new Date().toISOString() + // }); + // await execAsync('yarn --cwd /app/frontend dev &'); + // await ProjectEventsService.sendEvent('FRONTEND_START_COMPLETED', { + // message: 'Frontend service started successfully', + // timestamp: new Date().toISOString() + // }); + + // await ProjectEventsService.sendEvent('BACKEND_START_STARTED', { + // message: 'Starting backend service', + // timestamp: new Date().toISOString() + // }); + // await execAsync('yarn --cwd /app/backend start &'); + // await ProjectEventsService.sendEvent('BACKEND_START_COMPLETED', { + // message: 'Backend service started successfully', + // timestamp: new Date().toISOString() + // }); + + // await ProjectEventsService.sendEvent('SERVICE_START_COMPLETED', { + // message: 'All services started successfully', + // timestamp: new Date().toISOString() + // }); + + return { success: true }; + } catch (error) { + console.error('Error starting services:', error); + await ProjectEventsService.sendEvent('SERVICE_START_FAILED', { + message: 'Error starting services', + error: error.message, + timestamp: new Date().toISOString() + }); + return { success: false, error: error.message }; + } +} + +async function checkStatus() { + try { + const { stdout } = await execAsync('ps aux'); + return { + success: true, + frontendRunning: stdout.includes('next-server'), + backendRunning: stdout.includes('nodemon') && stdout.includes('/app/backend'), + nginxRunning: stdout.includes('nginx: master process') + }; + } catch (error) { + return { + success: false, + error: error.message + }; + } +} + +async function validateJSXSyntax(code) { + // Define validation rules for JSX + const rules = [ + { + // JSX attribute with expression + pattern: /^[a-zA-Z][a-zA-Z0-9]*={.*}$/, + message: 'Invalid JSX attribute syntax' + }, + { + // Invalid sequences + pattern: /,{2,}/, + message: 'Invalid character sequence detected', + shouldNotMatch: true + }, + { + // Ternary expressions + pattern: /^[a-zA-Z][a-zA-Z0-9]*={[\w\s]+\?[^}]+:[^}]+}$/, + message: 'Invalid ternary expression in JSX' + } + ]; + + // Validate each line + const lines = code.split('\n'); + for (const line of lines) { + const trimmedLine = line.trim(); + + // Skip empty lines + if (!trimmedLine) continue; + + // Check each rule + for (const rule of rules) { + if (rule.shouldNotMatch) { + // For patterns that should not be present + if (rule.pattern.test(trimmedLine)) { + return { + valid: false, + errors: [{ + code: 'JSX_SYNTAX_ERROR', + severity: 'error', + location: '', + message: rule.message + }] + }; + } + } else { + // For patterns that should match + if (trimmedLine.includes('=') && !rule.pattern.test(trimmedLine)) { + return { + valid: false, + errors: [{ + code: 'JSX_SYNTAX_ERROR', + severity: 'error', + location: '', + message: rule.message + }] + }; + } + } + } + + // Additional JSX-specific checks + if ((trimmedLine.match(/{/g) || []).length !== (trimmedLine.match(/}/g) || []).length) { + return { + valid: false, + errors: [{ + code: 'JSX_SYNTAX_ERROR', + severity: 'error', + location: '', + message: 'Unmatched curly braces in JSX' + }] + }; + } + } + + // If all checks pass + return { + valid: true, + errors: [] + }; +} + +async function removeFiles(files, rootPath) { + try { + for (const file of files) { + const fullPath = path.join(rootPath, file); + try { + await fs.unlink(fullPath); + console.log(`File removed: ${fullPath}`); + } catch (error) { + console.error(`Error when trying to delete a file ${fullPath}:`, error); + } + } + } catch (error) { + console.error('Error removing files:', error); + throw error; + } +} \ No newline at end of file diff --git a/app-shell/src/services/notifications/errors/forbidden.js b/app-shell/src/services/notifications/errors/forbidden.js new file mode 100644 index 0000000..192fa10 --- /dev/null +++ b/app-shell/src/services/notifications/errors/forbidden.js @@ -0,0 +1,16 @@ +const { getNotification, isNotification } = require('../helpers'); + +module.exports = class ForbiddenError extends Error { + constructor(messageCode) { + let message; + + if (messageCode && isNotification(messageCode)) { + message = getNotification(messageCode); + } + + message = message || getNotification('errors.forbidden.message'); + + super(message); + this.code = 403; + } +}; diff --git a/app-shell/src/services/notifications/errors/validation.js b/app-shell/src/services/notifications/errors/validation.js new file mode 100644 index 0000000..464550c --- /dev/null +++ b/app-shell/src/services/notifications/errors/validation.js @@ -0,0 +1,16 @@ +const { getNotification, isNotification } = require('../helpers'); + +module.exports = class ValidationError extends Error { + constructor(messageCode) { + let message; + + if (messageCode && isNotification(messageCode)) { + message = getNotification(messageCode); + } + + message = message || getNotification('errors.validation.message'); + + super(message); + this.code = 400; + } +}; diff --git a/app-shell/src/services/notifications/helpers.js b/app-shell/src/services/notifications/helpers.js new file mode 100644 index 0000000..1c3a60f --- /dev/null +++ b/app-shell/src/services/notifications/helpers.js @@ -0,0 +1,30 @@ +const _get = require('lodash/get'); +const errors = require('./list'); + +function format(message, args) { + if (!message) { + return null; + } + + return message.replace(/{(\d+)}/g, function (match, number) { + return typeof args[number] != 'undefined' ? args[number] : match; + }); +} + +const isNotification = (key) => { + const message = _get(errors, key); + return !!message; +}; + +const getNotification = (key, ...args) => { + const message = _get(errors, key); + + if (!message) { + return key; + } + + return format(message, args); +}; + +exports.getNotification = getNotification; +exports.isNotification = isNotification; diff --git a/app-shell/src/services/notifications/list.js b/app-shell/src/services/notifications/list.js new file mode 100644 index 0000000..a0a1613 --- /dev/null +++ b/app-shell/src/services/notifications/list.js @@ -0,0 +1,100 @@ +const errors = { + app: { + title: 'test', + }, + + auth: { + userDisabled: 'Your account is disabled', + forbidden: 'Forbidden', + unauthorized: 'Unauthorized', + userNotFound: `Sorry, we don't recognize your credentials`, + wrongPassword: `Sorry, we don't recognize your credentials`, + weakPassword: 'This password is too weak', + emailAlreadyInUse: 'Email is already in use', + invalidEmail: 'Please provide a valid email', + passwordReset: { + invalidToken: 'Password reset link is invalid or has expired', + error: `Email not recognized`, + }, + passwordUpdate: { + samePassword: `You can't use the same password. Please create new password`, + }, + userNotVerified: `Sorry, your email has not been verified yet`, + emailAddressVerificationEmail: { + invalidToken: 'Email verification link is invalid or has expired', + error: `Email not recognized`, + }, + }, + + iam: { + errors: { + userAlreadyExists: 'User with this email already exists', + userNotFound: 'User not found', + disablingHimself: `You can't disable yourself`, + revokingOwnPermission: `You can't revoke your own owner permission`, + deletingHimself: `You can't delete yourself`, + emailRequired: 'Email is required', + }, + }, + + importer: { + errors: { + invalidFileEmpty: 'The file is empty', + invalidFileExcel: 'Only excel (.xlsx) files are allowed', + invalidFileUpload: + 'Invalid file. Make sure you are using the last version of the template.', + importHashRequired: 'Import hash is required', + importHashExistent: 'Data has already been imported', + userEmailMissing: 'Some items in the CSV do not have an email', + }, + }, + + errors: { + forbidden: { + message: 'Forbidden', + }, + validation: { + message: 'An error occurred', + }, + searchQueryRequired: { + message: 'Search query is required', + }, + }, + + emails: { + invitation: { + subject: `You've been invited to {0}`, + body: ` +

Hello,

+

You've been invited to {0} set password for your {1} account.

+

{2}

+

Thanks,

+

Your {0} team

+ `, + }, + emailAddressVerification: { + subject: `Verify your email for {0}`, + body: ` +

Hello,

+

Follow this link to verify your email address.

+

{0}

+

If you didn't ask to verify this address, you can ignore this email.

+

Thanks,

+

Your {1} team

+ `, + }, + passwordReset: { + subject: `Reset your password for {0}`, + body: ` +

Hello,

+

Follow this link to reset your {0} password for your {1} account.

+

{2}

+

If you didn't ask to reset your password, you can ignore this email.

+

Thanks,

+

Your {0} team

+ `, + }, + }, +}; + +module.exports = errors; diff --git a/app-shell/src/services/project-events.js b/app-shell/src/services/project-events.js new file mode 100644 index 0000000..dabc32d --- /dev/null +++ b/app-shell/src/services/project-events.js @@ -0,0 +1,67 @@ +const axios = require('axios'); +const config = require('../config.js'); + +class ProjectEventsService { + /** + * Sends a project event to the Rails backend + * + * @param {string} eventType - Type of the event + * @param {object} payload - Event payload data + * @param {object} options - Additional options + * @param {string} [options.conversationId] - Optional conversation ID + * @param {boolean} [options.isError=false] - Whether this is an error event + * @returns {Promise} - Response from the webhook + */ + static async sendEvent(eventType, payload = {}, options = {}) { + try { + console.log(`[DEBUG] Sending project event: ${eventType}`); + + const webhookUrl = `https://flatlogic.com/projects/events_webhook`; + + // Prepare the event data + const eventData = { + project_uuid: config.project_uuid, + event_type: eventType, + payload: { + ...payload, + message: `[APP] ${payload.message}`, + is_error: options.isError || false, + system_message: true, + is_command_info: true + } + }; + + // Add conversation ID if provided + if (options.conversationId) { + eventData.conversation_id = options.conversationId; + } + + const headers = { + 'Content-Type': 'application/json', + 'x-project-uuid': config.project_uuid + }; + + console.log(`[DEBUG] Event data: ${JSON.stringify(eventData)}`); + + const response = await axios.post(webhookUrl, eventData, { headers }); + + console.log(`[DEBUG] Event sent successfully, status: ${response.status}`); + return response.data; + } catch (error) { + console.error(`[ERROR] Failed to send project event: ${error.message}`); + if (error.response) { + console.error(`[ERROR] Response status: ${error.response.status}`); + console.error(`[ERROR] Response data: ${JSON.stringify(error.response.data)}`); + } + + // Don't throw the error, just return a failed status + // This prevents errors in the event service from breaking app functionality + return { + success: false, + error: error.message + }; + } + } +} + +module.exports = ProjectEventsService; \ No newline at end of file diff --git a/app-shell/src/services/vcs.js b/app-shell/src/services/vcs.js new file mode 100644 index 0000000..6235c57 --- /dev/null +++ b/app-shell/src/services/vcs.js @@ -0,0 +1,1205 @@ +const util = require('util'); +const exec = util.promisify(require('child_process').exec); +const path = require('path'); +const { promises: fs } = require("fs"); +const axios = require('axios'); +const config = require('../config.js'); + +const ROOT_PATH = '/app'; +const MAX_BUFFER = 1024 * 1024 * 50; +const GITEA_DOMAIN = config.gitea_domain; +const USERNAME = config.gitea_username; +const API_TOKEN = config.gitea_api_token; +const GITHUB_REPO_URL = config.github_repo_url; +const GITHUB_TOKEN = config.github_token; + +const devSchemaFilePath = path.join(ROOT_PATH, '/app-shell/src/_schema.json'); + +class VCS { + static isInitRepoRunning = false; + // Main method – controller of the repository initialization process + static async initRepo(projectId = 'test') { + if (VCS.isInitRepoRunning) { + console.warn('[WARNING] initRepo is already running. Skipping.'); + return; + } + VCS.isInitRepoRunning = true; + try { + console.log(`[DEBUG] Starting repository initialization for project "${projectId}"...`); + + await this._waitForGitLockRelease(path.join(ROOT_PATH, '.git')); + // await this._removeGitLockIfExists(path.join(ROOT_PATH, '.git')); + console.log('[DEBUG] Git lock released, proceeding with initialization...'); + + if (GITHUB_REPO_URL) { + console.log(`[DEBUG] GitHub repository URL provided: ${GITHUB_REPO_URL}`); + console.log(`[DEBUG] Setting up local GitHub repository...`); + await this.setupLocalGitHubRepo(); + console.log(`[DEBUG] GitHub repository setup completed.`); + } else { + console.log(`[DEBUG] No GitHub repository URL provided. Skipping GitHub setup.`); + } + + console.log(`[DEBUG] Setting up Gitea remote repository for project "${projectId}"...`); + const giteaRemoteUrl = await this.setupGiteaRemote(projectId); + console.log(`[DEBUG] Gitea remote URL: ${giteaRemoteUrl.replace(/\/\/.*?@/, '//***@')}`); + + if (!GITHUB_REPO_URL) { + console.log(`[DEBUG] Setting up local repository with Gitea remote...`); + await this.setupLocalRepo(giteaRemoteUrl); + console.log(`[DEBUG] Local repository setup with Gitea remote completed.`); + } else { + console.log(`[DEBUG] Adding Gitea as additional remote to existing GitHub repository...`); + await this._addGiteaRemote(giteaRemoteUrl); + console.log(`[DEBUG] Gitea remote added to GitHub repository.`); + } + + console.log(`[DEBUG] Repository initialization for project "${projectId}" completed successfully.`); + console.log(`[DEBUG] Repository configuration: GitHub: ${GITHUB_REPO_URL ? 'Yes' : 'No'}, Gitea: Yes`); + + return { message: `Repository ${projectId} is ready.` }; + } catch (error) { + console.error(`[ERROR] Repository initialization for project "${projectId}" failed: ${error?.message}`); + + throw new Error(`Error during repo initialization: ${error.message}`); + } finally { + VCS.isInitRepoRunning = false; + console.log(`[DEBUG] Repository initialization process for "${projectId}" finished.`); + } + } + + // Checks for the existence of the remote repo and creates it if it doesn't exist + static async setupGiteaRemote(projectId) { + console.log(`[DEBUG] Checking Gitea remote repository "${projectId}"...`); + let repoData = await this.checkRepoExists(projectId); + if (!repoData) { + console.log(`[DEBUG] Gitea remote repository "${projectId}" does not exist. Creating...`); + repoData = await this.createRemoteRepo(projectId); + console.log(`[DEBUG] Gitea remote repository created: ${JSON.stringify(repoData)}`); + } else { + console.log(`[DEBUG] Gitea remote repository "${projectId}" already exists.`); + } + // Return the URL with token authentication + return `https://${USERNAME}:${API_TOKEN}@${GITEA_DOMAIN}/${USERNAME}/${projectId}.git`; + } + + // Sets up the local repository: either fetches/reset if .git exists, + // initializes git in a non-empty directory, or clones the repository if empty. + static async setupLocalRepo(remoteUrl) { + const gitDir = path.join(ROOT_PATH, '.git'); + const localRepoExists = await this.exists(gitDir); + if (localRepoExists) { + await this.fetchAndResetRepo(); + } else { + const files = await fs.readdir(ROOT_PATH); + if (files.length > 0) { + await this.initializeGitRepo(remoteUrl); + } else { + console.log('[DEBUG] Local directory is empty. Cloning remote repository...'); + await exec(`git clone ${remoteUrl} .`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + } + } + } + + static async setupLocalGitHubRepo() { + try { + if (!GITHUB_REPO_URL) { + console.log('[DEBUG] GITHUB_REPO_URL is not set. Skipping GitHub repo setup.'); + return; + } + + const gitDir = path.join(ROOT_PATH, '.git'); + const repoExists = await this.exists(gitDir); + + if (repoExists) { + console.log('[DEBUG] Git repository already initialized. Fetching and resetting...'); + + await this._addGithubRemote(); + + console.log('[DEBUG] Fetching GitHub remote...'); + await exec(`git fetch github`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + + try { + console.log('[DEBUG] Checking for remote branch "github/ai-dev"...'); + await exec(`git rev-parse --verify github/ai-dev`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + console.log('[DEBUG] Remote branch "github/ai-dev" exists. Resetting local repository to github/ai-dev...'); + await exec(`git reset --hard github/ai-dev`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + console.log('[DEBUG] Switching to branch "ai-dev"...'); + await exec(`git checkout -B ai-dev`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + } catch (e) { + console.log('[DEBUG] Remote branch "github/ai-dev" does NOT exist. Creating initial commit...'); + await this.commitInitialChanges(); + } + return; + } + + console.log('[DEBUG] Initializing git in existing directory...'); + // const gitignorePath = path.join(ROOT_PATH, '.gitignore'); + // const ignoreContent = `node_modules/\n*/node_modules/\n*/build/\n`; + // await fs.writeFile(gitignorePath, ignoreContent, 'utf8'); + + await exec(`git init`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + console.log('[DEBUG] Configuring git user...'); + await exec(`git config user.email "support@flatlogic.com"`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + await exec(`git config user.name "Flatlogic Bot"`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + + await this._addGithubRemote(); + + console.log('[DEBUG] Fetching GitHub remote...'); + await exec(`git fetch github`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + try { + console.log('[DEBUG] Checking for remote branch "github/ai-dev"...'); + await exec(`git rev-parse --verify github/ai-dev`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + console.log('[DEBUG] Remote branch "github/ai-dev" exists. Resetting local repository to github/ai-dev...'); + await exec(`git reset --hard github/ai-dev`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + console.log('[DEBUG] Switching to branch "ai-dev"...'); + await exec(`git checkout -B ai-dev`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + } catch (e) { + console.log('[DEBUG] Remote branch "github/ai-dev" does NOT exist. Creating initial commit...'); + await this.commitInitialChanges(); + } + } catch (error) { + console.error(`[ERROR] Failed to setup local GitHub repo: ${error?.message}`); + throw error; + } + } + + // Check if a file/directory exists + static async exists(pathToCheck) { + try { + await fs.access(pathToCheck); + return true; + } catch { + return false; + } + } + + // If the local repository exists, fetches remote data and resets the repository state + static async fetchAndResetRepo() { + console.log('[DEBUG] Local repository exists. Fetching remotes...'); + + if (GITHUB_REPO_URL) { + await exec(`git fetch github`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + const branchReset = await this.tryResetToBranch('ai-dev', 'github'); + + if (branchReset) { + return; + } + } + + await exec(`git fetch gitea`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + const branchReset = await this.tryResetToBranch('ai-dev', 'gitea'); + + if (!branchReset) { + const masterReset = await this.tryResetToBranch('master', 'gitea'); + if (masterReset) { + console.log('[DEBUG] Creating and switching to branch "ai-dev"...'); + await exec(`git branch ai-dev`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + await exec(`git checkout ai-dev`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + console.log('[DEBUG] Pushing ai-dev branch to remotes...'); + await exec(`git push -u gitea ai-dev --force`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + if (GITHUB_REPO_URL) { + await exec(`git push -u github ai-dev --force`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + } + } else { + console.log('[DEBUG] Neither "gitea/ai-dev" nor "gitea/master" exist. Creating initial commit...'); + await this.commitInitialChanges(); + } + } + } + + // Tries to check out and reset to the specified branch + static async tryResetToBranch(branchName, remote) { + try { + console.log(`[DEBUG] Checking for remote branch "${remote}/${branchName}"...`); + await exec(`git rev-parse --verify ${remote}/${branchName}`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + console.log(`[DEBUG] Remote branch "${remote}/${branchName}" found. Resetting local repository to "${remote}/${branchName}"...`); + await exec(`git reset --hard ${remote}/${branchName}`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + await exec(`git checkout ${branchName === 'ai-dev' ? 'ai-dev' : branchName}`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + + return true; + } catch (e) { + console.log(`[DEBUG] Remote branch "${remote}/${branchName}" does NOT exist.`); + + return false; + } + } + + // If remote branch doesn't exist, make the initial commit and set up branches + static async commitInitialChanges() { + console.log('[DEBUG] Adding all files for initial commit...'); + await exec(`git add .`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + const { stdout: status } = await exec(`git status --porcelain`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + if (status.trim()) { + await exec(`git commit -m "Initial version"`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + + if (GITHUB_REPO_URL) { + await exec(`git push -u github master --force`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + } + await exec(`git push -u gitea master --force`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + + console.log('[DEBUG] Creating and switching to branch "ai-dev"...'); + await exec(`git branch ai-dev`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + await exec(`git checkout ai-dev`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + console.log('[DEBUG] Making ai-dev branch identical to master...'); + + if (GITHUB_REPO_URL) { + await exec(`git reset --hard github/master`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + } else { + await exec(`git reset --hard gitea/master`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + } + + console.log('[DEBUG] Pushing ai-dev branch to remotes...'); + if (GITHUB_REPO_URL) { + await exec(`git push -u github ai-dev --force`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + } + await exec(`git push -u gitea ai-dev --force`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + } else { + console.log('[DEBUG] No local changes to commit.'); + } + } + + // If the local directory is not empty but .git doesn't exist, initialize git, + // add .gitignore, configure the user, and add the remote origin. + static async initializeGitRepo(giteaRemoteUrl) { + console.log('[DEBUG] Local directory is not empty. Initializing git...'); + const gitignorePath = path.join(ROOT_PATH, '.gitignore'); + const ignoreContent = `node_modules/\n*/node_modules/\n*/build/\n`; + await fs.writeFile(gitignorePath, ignoreContent, 'utf8'); + + await exec(`git init`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + console.log('[DEBUG] Configuring git user...'); + await exec(`git config user.email "support@flatlogic.com"`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + await exec(`git config user.name "Flatlogic Bot"`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + + console.log(`[DEBUG] Adding Gitea remote ${giteaRemoteUrl}...`); + await exec(`git remote add gitea ${giteaRemoteUrl}`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + + if (GITHUB_REPO_URL) { + await this._addGithubRemote(); + } + + console.log('[DEBUG] Fetching Gitea remote...'); + await exec(`git fetch gitea`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + try { + console.log('[DEBUG] Checking for remote branch "gitea/ai-dev"...'); + await exec(`git rev-parse --verify gitea/ai-dev`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + console.log('[DEBUG] Remote branch "gitea/ai-dev" exists. Resetting local repository to gitea/ai-dev...'); + await exec(`git reset --hard gitea/ai-dev`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + console.log('[DEBUG] Switching to branch "ai-dev"...'); + await exec(`git checkout -B ai-dev`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + } catch (e) { + console.log('[DEBUG] Remote branch "gitea/ai-dev" does NOT exist. Creating initial commit...'); + await this.commitInitialChanges(); + } + } + + // Method to check if the repository exists on remote server + static async checkRepoExists(repoName) { + const url = `https://${GITEA_DOMAIN}/api/v1/repos/${USERNAME}/${repoName}`; + try { + const response = await axios.get(url, { + headers: { Authorization: `token ${API_TOKEN}` } + }); + return response.data; + } catch (err) { + if (err.response && err.response.status === 404) { + return null; + } + throw new Error('Error checking repository existence: ' + err?.message); + } + } + + // Method to create a remote repository via API + static async createRemoteRepo(repoName) { + const createUrl = `https://${GITEA_DOMAIN}/api/v1/user/repos`; + console.log("[DEBUG] createUrl", createUrl); + + try { + const response = await axios.post(createUrl, { + name: repoName, + description: `Repository for project ${repoName}`, + private: false + }, { + headers: { Authorization: `token ${API_TOKEN}` } + }); + + return response.data; + } catch (err) { + console.log('Error creating repository via API: ' + err?.message) + // throw new Error('Error creating repository via API: ' + err.message); + } + } + + static async commitChanges(message = "", files = '.', dev_schema) { + try { + console.log(`[DEBUG] Starting commit process...`); + await this._ensureDevBranch(); + + console.log(`[DEBUG] Ensuring .gitignore is properly configured...`); + await this._ensureGitignore(); + + // Save dev_schema + await this._saveDevSchema(message, dev_schema); + + console.log(`[DEBUG] Adding files to git index: ${files}`); + if (files === '.') { + await exec(`git add .`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + } else { + await exec(`git add ${files}`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + } + + const { stdout: status } = await exec('git status --porcelain', { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + console.log(`[DEBUG] Git status before commit: ${status}`); + + if (!status.trim()) { + console.log(`[DEBUG] No changes to commit`); + return { message: "No changes to commit" }; + } + + const now = new Date(); + const commitMessage = message || `Auto commit: ${now.toISOString()}`; + console.log(`[DEBUG] Committing changes with message: "${commitMessage}"`); + + const { stdout: commitOutput, stderr: commitError } = await exec(`git commit -m "${commitMessage}"`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + console.log(`[DEBUG] Commit output: ${commitOutput}`); + if (commitError) { + console.log(`[DEBUG] Commit stderr: ${commitError}`); + } + + const { stdout: currentBranch } = await exec(`git rev-parse --abbrev-ref HEAD`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + const branchName = currentBranch.trim(); + console.log(`[DEBUG] Current branch: ${branchName}`); + + console.log(`[DEBUG] Pushing changes to Gitea...`); + try { + const { stdout: giteaPushOutput, stderr: giteaPushError } = await exec(`git push gitea ${branchName}`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + console.log(`[DEBUG] Gitea push output: ${giteaPushOutput}`); + if (giteaPushError) { + console.log(`[DEBUG] Gitea push stderr: ${giteaPushError}`); + } + } catch (giteaError) { + console.error(`[ERROR] Failed to push to Gitea: ${giteaError?.message}`); + + if (giteaError.stderr && giteaError.stderr.includes('rejected')) { + console.log(`[DEBUG] Push rejected, trying with --force...`); + try { + const { stdout, stderr } = await exec(`git push gitea ${branchName} --force`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + console.log(`[DEBUG] Force push to Gitea output: ${stdout}`); + if (stderr) { + console.log(`[DEBUG] Force push to Gitea stderr: ${stderr}`); + } + } catch (forceError) { + console.error(`[ERROR] Force push to Gitea failed: ${forceError?.message}`); + } + } + } + + if (GITHUB_REPO_URL) { + console.log(`[DEBUG] Pushing changes to GitHub...`); + try { + const { stdout: githubPushOutput, stderr: githubPushError } = await exec(`git push github ${branchName}`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + console.log(`[DEBUG] GitHub push output: ${githubPushOutput}`); + if (githubPushError) { + console.log(`[DEBUG] GitHub push stderr: ${githubPushError}`); + } + } catch (githubError) { + console.error(`[ERROR] Failed to push to GitHub: ${githubError?.message}`); + + if (githubError.stderr && githubError.stderr.includes('rejected')) { + console.log(`[DEBUG] Push rejected, trying with --force...`); + try { + const { stdout, stderr } = await exec(`git push github ${branchName} --force`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + console.log(`[DEBUG] Force push to GitHub output: ${stdout}`); + if (stderr) { + console.log(`[DEBUG] Force push to GitHub stderr: ${stderr}`); + } + } catch (forceError) { + console.error(`[ERROR] Force push to GitHub failed: ${forceError?.message}`); + } + } + } + } + + console.log(`[DEBUG] Commit process completed`); + return { message: "Changes committed" }; + } catch (error) { + console.error(`[ERROR] Error during commit process: ${error?.message}`); + } + } + + static async getLog() { + try { + const remote = GITHUB_REPO_URL ? 'github' : 'gitea'; + + const { stdout: remotes } = await exec(`git remote -v`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + console.log(`[DEBUG] Remotes: ${remotes}`); + + const { stdout: branches } = await exec(`git branch -a`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + console.log(`[DEBUG] Branches: ${branches}`); + + const { stdout } = await exec(`git log ${remote}/ai-dev --oneline`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + const lines = stdout.split(/\r?\n/).filter(line => line.trim() !== ''); + const result = {}; + lines.forEach((line) => { + const firstSpaceIndex = line.indexOf(' '); + if (firstSpaceIndex > 0) { + const hash = line.substring(0, firstSpaceIndex); + const message = line.substring(firstSpaceIndex + 1).trim(); + result[hash] = message; + } + }); + return result; + } catch (error) { + console.error(`[ERROR] Error during get log: ${error?.message}`); + throw error; + } + } + + static async checkout(ref) { + try { + await exec(`git checkout ${ref}`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + return { message: `Checked out to ${ref}` }; + } catch (error) { + throw new Error(`Error during checkout: ${error?.message}`); + } + } + + static async revert(commitHash) { + try { + const { stdout: currentBranch } = await exec(`git rev-parse --abbrev-ref HEAD`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + const branchName = currentBranch.trim(); + + await exec(`git reset --hard`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + + await exec( + `git revert --no-edit ${commitHash}..HEAD --no-commit`, + { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER } + ); + + await exec( + `git commit -m "Revert to version ${commitHash}"`, + { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER } + ); + + await exec(`git push gitea ${branchName}`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + if (GITHUB_REPO_URL) { + await exec(`git push github ${branchName}`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + } + + const commitMessage = await this._getCommitMessageByHash(commitHash); + const devSchema = await this._getDevSchemaByCommitMessage(commitMessage); + + return { message: `Reverted to commit ${commitHash}`, devSchema }; + } catch (error) { + console.error("Error during revert:", error?.message); + if (error.stdout) { + console.error("Revert stdout:", error.stdout); + } + if (error.stderr) { + console.error("Revert stderr:", error.stderr); + } + throw new Error(`Error during revert: ${error?.message}`); + } + } + + static async mergeDevIntoMaster() { + try { + // First, make sure we have the latest changes from both branches + console.log('[DEBUG] Fetching latest changes from remote repositories...'); + await exec(`git fetch gitea`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + if (GITHUB_REPO_URL) { + await exec(`git fetch github`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + } + + // Switch to branch 'master' + console.log('[DEBUG] Switching to branch "master"...'); + await exec(`git checkout master`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + + // Pull latest changes from master + console.log('[DEBUG] Pulling latest changes from master branch...'); + try { + await exec(`git pull gitea master`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + console.log('[DEBUG] Successfully pulled from Gitea master'); + } catch (pullError) { + console.warn(`[WARN] Failed to pull from Gitea master: ${pullError?.message}`); + // Try to continue anyway + } + + // Switch to ai-dev and make sure it's up to date + console.log('[DEBUG] Switching to branch "ai-dev"...'); + await exec(`git checkout ai-dev`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + + // Pull latest changes from ai-dev + console.log('[DEBUG] Pulling latest changes from ai-dev branch...'); + try { + await exec(`git pull gitea ai-dev`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + console.log('[DEBUG] Successfully pulled from Gitea ai-dev'); + } catch (pullError) { + console.warn(`[WARN] Failed to pull from Gitea ai-dev: ${pullError?.message}`); + // Try to continue anyway + } + + // Switch back to master for the merge + console.log('[DEBUG] Switching back to branch "master"...'); + await exec(`git checkout master`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + + // Merge branch 'ai-dev' into 'master' with a forced merge. + // Parameter -X theirs is used to resolve conflicts by keeping the changes from the branch being merged in case of conflicts. + console.log('[DEBUG] Merging branch "ai-dev" into "master" (force merge with -X theirs)...'); + try { + const { stdout: mergeOutput, stderr: mergeError } = await exec( + `git merge ai-dev --no-ff -X theirs -m "Forced merge: merge ai-dev into master"`, + { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER } + ); + console.log(`[DEBUG] Merge output: ${mergeOutput}`); + if (mergeError) { + console.log(`[DEBUG] Merge stderr: ${mergeError}`); + } + } catch (mergeError) { + console.error(`[ERROR] Merge failed: ${mergeError?.message}`); + if (mergeError.stdout) { + console.error(`[ERROR] Merge stdout: ${mergeError.stdout}`); + } + if (mergeError.stderr) { + console.error(`[ERROR] Merge stderr: ${mergeError.stderr}`); + } + + // Abort the merge if it failed + console.log('[DEBUG] Aborting failed merge...'); + await exec(`git merge --abort`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + throw new Error(`Failed to merge ai-dev into master: ${mergeError?.message}`); + } + + // Push the merged 'master' branch to both remotes + console.log('[DEBUG] Pushing merged master branch to Gitea remote...'); + try { + const { stdout: giteaPushOutput, stderr: giteaPushError } = await exec(`git push gitea master`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + console.log(`[DEBUG] Gitea push output: ${giteaPushOutput}`); + if (giteaPushError) { + console.log(`[DEBUG] Gitea push stderr: ${giteaPushError}`); + } + } catch (pushError) { + console.error(`[ERROR] Failed to push to Gitea: ${pushError?.message}`); + + // If push is rejected, try with --force + if (pushError.stderr && pushError.stderr.includes('rejected')) { + console.log('[DEBUG] Push rejected, trying with --force...'); + try { + const { stdout, stderr } = await exec(`git push gitea master --force`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + console.log(`[DEBUG] Force push to Gitea output: ${stdout}`); + if (stderr) { + console.log(`[DEBUG] Force push to Gitea stderr: ${stderr}`); + } + } catch (forceError) { + console.error(`[ERROR] Force push to Gitea also failed: ${forceError?.message}`); + throw forceError; + } + } else { + throw pushError; + } + } + + if (GITHUB_REPO_URL) { + console.log('[DEBUG] Pushing merged master branch to GitHub remote...'); + try { + const { stdout: githubPushOutput, stderr: githubPushError } = await exec(`git push github master`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + console.log(`[DEBUG] GitHub push output: ${githubPushOutput}`); + if (githubPushError) { + console.log(`[DEBUG] GitHub push stderr: ${githubPushError}`); + } + } catch (pushError) { + console.error(`[ERROR] Failed to push to GitHub: ${pushError?.message}`); + + // If push is rejected, try with --force + if (pushError.stderr && pushError.stderr.includes('rejected')) { + console.log('[DEBUG] Push rejected, trying with --force...'); + try { + const { stdout, stderr } = await exec(`git push github master --force`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + console.log(`[DEBUG] Force push to GitHub output: ${stdout}`); + if (stderr) { + console.log(`[DEBUG] Force push to GitHub stderr: ${stderr}`); + } + } catch (forceError) { + console.error(`[ERROR] Force push to GitHub also failed: ${forceError?.message}`); + throw forceError; + } + } else { + throw pushError; + } + } + } + + return { message: "Branch ai-dev merged into master and pushed to all remotes" }; + } catch (error) { + console.error(`[ERROR] Error during mergeDevIntoMaster: ${error?.message}`); + throw new Error(`Error during merge of ai-dev into master: ${error?.message}`); + } + } + + static async _mergeDevIntoMasterGitHub() { + try { + // Switch to branch 'master' + console.log('Switching to branch "master" (GitHub)...'); + await exec(`git checkout master`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + + // Merge branch 'ai-dev' into 'master' with a forced merge. + console.log('Merging branch "ai-dev" into "master" (GitHub, force merge with -X theirs)...'); + await exec( + `git merge ai-dev --no-ff -X theirs -m "Forced merge: merge ai-dev into master"`, + { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER } + ); + + // Push the merged 'master' branch to remote (GitHub) + console.log('Pushing merged master branch to remote (GitHub)...'); + const { stdout, stderr } = await exec(`git push -f github master`, { + cwd: ROOT_PATH, + maxBuffer: MAX_BUFFER + }); + if (stdout) { + console.log("Git push GitHub stdout:", stdout); + } + if (stderr) { + console.error("Git push GitHub stderr:", stderr); + } + return { message: "Branch ai-dev merged into master and pushed to GitHub remote" }; + } catch (error) { + console.error("Error during mergeDevIntoMasterGitHub:", error?.message); + if (error.stdout) { + console.error("Merge GitHub stdout:", error.stdout); + } + if (error.stderr) { + console.error("Merge GitHub stderr:", error.stderr); + } + throw error; + } + } + + static async resetDevBranch() { + try { + console.log(`[DEBUG] Starting reset of ai-dev branch to match master...`); + + // First, fetch all remote branches to ensure we have the latest information + console.log(`[DEBUG] Fetching latest changes from remotes...`); + await exec(`git fetch --all`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + + // Check current branch state + const { stdout: initialBranches } = await exec(`git branch -a`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + console.log(`[DEBUG] Initial branches: ${initialBranches}`); + + // Check if master branch exists + const { stdout: masterExists } = await exec(`git branch --list master`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + if (!masterExists.trim()) { + console.log(`[DEBUG] Master branch does not exist. Creating it...`); + await exec(`git checkout -b master`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + } + + // Switch to master branch + console.log(`[DEBUG] Switching to branch "master"...`); + await exec(`git checkout master`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + + // Pull latest changes from master + console.log(`[DEBUG] Pulling latest changes from master...`); + try { + await exec(`git pull gitea master`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + } catch (error) { + console.log(`[DEBUG] Error pulling from master: ${error?.message}`); + } + + // Verify we are on master branch + const { stdout: currentBranch } = await exec(`git rev-parse --abbrev-ref HEAD`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + console.log(`[DEBUG] Current branch after checkout: ${currentBranch.trim()}`); + + // Get master branch commit hash + const { stdout: masterCommit } = await exec(`git rev-parse master`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + console.log(`[DEBUG] Master branch commit hash: ${masterCommit.trim()}`); + + // Delete local ai-dev branch if it exists + try { + await exec(`git branch -D ai-dev`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + console.log(`[DEBUG] Local branch ai-dev deleted successfully`); + } catch (error) { + console.log(`[DEBUG] Local branch ai-dev does not exist or could not be deleted: ${error?.message}`); + } + + // Create new ai-dev branch from master using the exact commit hash + await exec(`git branch ai-dev ${masterCommit.trim()}`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + console.log(`[DEBUG] Created new ai-dev branch from master commit ${masterCommit.trim()}`); + + // Switch to the new ai-dev branch + await exec(`git checkout ai-dev`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + console.log(`[DEBUG] Switched to new ai-dev branch`); + + // Verify we are on ai-dev branch + const { stdout: newCurrentBranch } = await exec(`git rev-parse --abbrev-ref HEAD`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + console.log(`[DEBUG] Current branch after creating ai-dev: ${newCurrentBranch.trim()}`); + + // Verify that ai-dev points to the same commit as master + const { stdout: aiDevCommit } = await exec(`git rev-parse ai-dev`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + console.log(`[DEBUG] ai-dev branch commit hash: ${aiDevCommit.trim()}`); + + if (aiDevCommit.trim() !== masterCommit.trim()) { + console.error(`[ERROR] ai-dev branch does not point to the same commit as master!`); + console.error(`[ERROR] master: ${masterCommit.trim()}, ai-dev: ${aiDevCommit.trim()}`); + throw new Error(`Failed to create ai-dev branch from master`); + } + + console.log(`[DEBUG] Verified: ai-dev branch points to the same commit as master`); + + // Delete remote ai-dev branches if they exist + console.log(`[DEBUG] Deleting remote ai-dev branches if they exist...`); + + // For Gitea + try { + // First check if the remote branch exists + const { stdout: giteaBranches } = await exec(`git ls-remote --heads gitea ai-dev`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + + if (giteaBranches.trim()) { + console.log(`[DEBUG] Remote branch ai-dev exists on Gitea, deleting it...`); + await exec(`git push gitea --delete ai-dev`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + console.log(`[DEBUG] Remote branch ai-dev on Gitea deleted successfully`); + + // Verify deletion + const { stdout: verifyGiteaDeletion } = await exec(`git ls-remote --heads gitea ai-dev`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + if (verifyGiteaDeletion.trim()) { + console.log(`[WARN] Remote branch ai-dev on Gitea still exists after deletion attempt`); + } else { + console.log(`[DEBUG] Verified: Remote branch ai-dev on Gitea is deleted`); + } + } else { + console.log(`[DEBUG] Remote branch ai-dev does not exist on Gitea`); + } + } catch (error) { + console.log(`[DEBUG] Error checking/deleting remote branch on Gitea: ${error?.message}`); + } + + // For GitHub + if (GITHUB_REPO_URL) { + try { + // First check if the remote branch exists + const { stdout: githubBranches } = await exec(`git ls-remote --heads github ai-dev`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + + if (githubBranches.trim()) { + console.log(`[DEBUG] Remote branch ai-dev exists on GitHub, deleting it...`); + await exec(`git push github --delete ai-dev`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + console.log(`[DEBUG] Remote branch ai-dev on GitHub deleted successfully`); + + // Verify deletion + const { stdout: verifyGithubDeletion } = await exec(`git ls-remote --heads github ai-dev`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + if (verifyGithubDeletion.trim()) { + console.log(`[WARN] Remote branch ai-dev on GitHub still exists after deletion attempt`); + } else { + console.log(`[DEBUG] Verified: Remote branch ai-dev on GitHub is deleted`); + } + } else { + console.log(`[DEBUG] Remote branch ai-dev does not exist on GitHub`); + } + } catch (error) { + console.log(`[DEBUG] Error checking/deleting remote branch on GitHub: ${error?.message}`); + } + } + + // Wait a moment to ensure deletion is processed + console.log(`[DEBUG] Waiting for remote branch deletion to be processed...`); + await new Promise(resolve => setTimeout(resolve, 2000)); + + // Push new ai-dev branch to remote repositories with force + console.log(`[DEBUG] Pushing new ai-dev branch to Gitea (force push)...`); + try { + const { stdout, stderr } = await exec(`git push -u gitea ai-dev --force`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + console.log(`[DEBUG] Gitea force push output: ${stdout}`); + if (stderr) { + console.log(`[DEBUG] Gitea force push stderr: ${stderr}`); + } + + // Verify the push + const { stdout: verifyGiteaPush } = await exec(`git ls-remote --heads gitea ai-dev`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + console.log(`[DEBUG] Gitea ai-dev branch after push: ${verifyGiteaPush}`); + + // Extract the hash from the output + const giteaAiDevHash = verifyGiteaPush.split(/\s+/)[0]; + + if (giteaAiDevHash === masterCommit.trim()) { + console.log(`[DEBUG] Verified: Gitea ai-dev branch matches master branch`); + } else { + console.log(`[WARN] Gitea ai-dev branch does not match master branch!`); + console.log(`[WARN] master: ${masterCommit.trim()}, Gitea ai-dev: ${giteaAiDevHash}`); + } + } catch (error) { + console.error(`[ERROR] Force push to Gitea failed: ${error?.message}`); + throw error; + } + + if (GITHUB_REPO_URL) { + console.log(`[DEBUG] Pushing new ai-dev branch to GitHub (force push)...`); + try { + const { stdout, stderr } = await exec(`git push -u github ai-dev --force`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + console.log(`[DEBUG] GitHub force push output: ${stdout}`); + if (stderr) { + console.log(`[DEBUG] GitHub force push stderr: ${stderr}`); + } + + // Verify the push + const { stdout: verifyGithubPush } = await exec(`git ls-remote --heads github ai-dev`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + console.log(`[DEBUG] GitHub ai-dev branch after push: ${verifyGithubPush}`); + + // Extract the hash from the output + const githubAiDevHash = verifyGithubPush.split(/\s+/)[0]; + + if (githubAiDevHash === masterCommit.trim()) { + console.log(`[DEBUG] Verified: GitHub ai-dev branch matches master branch`); + } else { + console.log(`[WARN] GitHub ai-dev branch does not match master branch!`); + console.log(`[WARN] master: ${masterCommit.trim()}, GitHub ai-dev: ${githubAiDevHash}`); + } + } catch (error) { + console.error(`[ERROR] Force push to GitHub failed: ${error?.message}`); + throw error; + } + } + + // Final verification + console.log(`[DEBUG] Performing final verification...`); + + // Get master commit hash again to ensure it hasn't changed + const { stdout: finalMasterCommit } = await exec(`git rev-parse master`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + console.log(`[DEBUG] Final master branch commit hash: ${finalMasterCommit.trim()}`); + + // Get ai-dev commit hash + const { stdout: finalAiDevCommit } = await exec(`git rev-parse ai-dev`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + console.log(`[DEBUG] Final ai-dev branch commit hash: ${finalAiDevCommit.trim()}`); + + // Get remote branches + const { stdout: finalRemoteBranches } = await exec(`git ls-remote --heads`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + console.log(`[DEBUG] Final remote branches: ${finalRemoteBranches}`); + + if (finalAiDevCommit.trim() !== finalMasterCommit.trim()) { + console.error(`[ERROR] Final verification failed: ai-dev and master branches point to different commits!`); + console.error(`[ERROR] master: ${finalMasterCommit.trim()}, ai-dev: ${finalAiDevCommit.trim()}`); + } else { + console.log(`[DEBUG] Final verification passed: ai-dev and master branches point to the same commit`); + } + + console.log(`[DEBUG] Reset of ai-dev branch completed successfully`); + return { message: "Branch ai-dev has been reset to be an exact copy of master" }; + } catch (error) { + console.error(`[ERROR] Error during reset of dev branch: ${error?.message}`); + throw new Error(`Error during reset of dev branch: ${error?.message}`); + } + } + + static async _resetDevBranchGitHub() { + try { + console.log('[DEBUG] Switching to branch "master" (GitHub)...'); + await exec(`git checkout master`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + + console.log('[DEBUG] Resetting branch "ai-dev" to be identical to "master" (GitHub)...'); + await exec(`git checkout -B ai-dev master`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + + console.log('[DEBUG] Pushing updated branch "ai-dev" to remote (GitHub, force push)...'); + await exec(`git push -f github ai-dev`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + + return { message: 'ai-dev branch successfully reset to master (GitHub).' }; + } catch (error) { + console.error("Error during resetting ai-dev branch (GitHub):", error?.message); + if (error.stdout) { + console.error("Reset GitHub stdout:", error.stdout); + } + if (error.stderr) { + console.error("Reset GitHub stderr:", error.stderr); + } + throw new Error(`Error during resetting ai-dev branch (GitHub): ${error?.message}`); + } + } + + static async _pushChangesToGitea() { + try { + const { stdout, stderr } = await exec(`git push gitea ai-dev`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + if (stdout) { + console.log("Git push Gitea stdout:", stdout); + } + if (stderr) { + console.error("Git push Gitea stderr:", stderr); + } + return { message: "Changes pushed to Gitea remote repository (ai-dev branch)" }; + } catch (error) { + console.error("Git push Gitea error:", error?.message); + if (error.stdout) { + console.error("Git push Gitea stdout:", error.stdout); + } + if (error.stderr) { + console.error("Git push Gitea stderr:", error.stderr); + } + throw error; + } + } + + static async _pushChangesToGithub() { + try { + const { stdout, stderr } = await exec(`git push github ai-dev`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + if (stdout) { + console.log("Git push GitHub stdout:", stdout); + } + if (stderr) { + console.error("Git push GitHub stderr:", stderr); + } + return { message: "Changes pushed to GitHub repository (ai-dev branch)" }; + } catch (error) { + console.error("Git push GitHub error:", error?.message); + if (error.stdout) { + console.error("Git push GitHub stdout:", error.stdout); + } + if (error.stderr) { + console.error("Git push GitHub stderr:", error.stderr); + } + throw error; + } + } + + static async _addGithubRemote() { + if (GITHUB_REPO_URL) { + try { + const { stdout: remotes } = await exec(`git remote -v`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + if (!remotes.includes('github')) { + console.log(`[DEBUG] Adding GitHub remote: git remote add github ${GITHUB_REPO_URL}`); + await exec(`git remote add github ${GITHUB_REPO_URL}`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + console.log(`[DEBUG] GitHub remote added: ${GITHUB_REPO_URL}`); + } else { + console.log(`[DEBUG] GitHub remote already exists.`); + } + } catch (error) { + console.error(`[ERROR] Failed to add GitHub remote: ${error?.message}`); + if (error.stdout) { + console.error(`[ERROR] git remote add stdout: ${error.stdout}`); + } + if (error.stderr) { + console.error(`[ERROR] git remote add stderr: ${error.stderr}`); + } + throw error; + } + } + } + + static async _addGiteaRemote(giteaRemoteUrl) { + try { + const { stdout: remotes } = await exec(`git remote -v`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + if (!remotes.includes('gitea')) { + console.log(`[DEBUG] Adding Gitea remote: git remote add gitea ${giteaRemoteUrl}`); + await exec(`git remote add gitea ${giteaRemoteUrl}`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + console.log(`[DEBUG] Gitea remote added: ${giteaRemoteUrl}`); + } else { + console.log(`[DEBUG] Gitea remote already exists.`); + } + } catch (error) { + console.error(`[ERROR] Failed to add Gitea remote: ${error?.message}`); + if (error.stdout) { + console.error(`[ERROR] git remote add stdout: ${error.stdout}`); + } + if (error.stderr) { + console.error(`[ERROR] git remote add stderr: ${error.stderr}`); + } + throw error; + } + } + + static async _revertGitHubChanges(branchName) { + try { + await exec(`git push -f github ${branchName}`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + } catch (error) { + console.error("Error during revertGitHubChanges:", error?.message); + if (error.stdout) { + console.error("revertGitHubChanges stdout:", error.stdout); + } + if (error.stderr) { + console.error("revertGitHubChanges stderr:", error.stderr); + } + throw new Error(`Error during revertGitHubChanges: ${error?.message}`); + } + } + + static async _ensureDevBranch() { + try { + console.log(`[DEBUG] Ensuring we are on 'ai-dev' branch...`); + + const { stdout: branchList } = await exec(`git branch --list ai-dev`, { + cwd: ROOT_PATH, + maxBuffer: MAX_BUFFER, + }); + + if (!branchList || branchList.trim() === '') { + console.log(`[DEBUG] Branch 'ai-dev' not found. Creating branch 'ai-dev'.`); + await exec(`git checkout -b ai-dev`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + } else { + const { stdout: currentBranchStdout } = await exec(`git rev-parse --abbrev-ref HEAD`, { + cwd: ROOT_PATH, + maxBuffer: MAX_BUFFER, + }); + const currentBranch = currentBranchStdout.trim(); + + if (currentBranch !== 'ai-dev') { + console.log(`[DEBUG] Switching from branch '${currentBranch}' to 'ai-dev'.`); + await exec(`git checkout ai-dev`, { cwd: ROOT_PATH, maxBuffer: MAX_BUFFER }); + } else { + console.log(`[DEBUG] Already on branch 'ai-dev'.`); + } + } + + console.log(`[DEBUG] Successfully ensured we are on 'ai-dev' branch.`); + } catch (error) { + console.error(`[ERROR] Error ensuring branch 'ai-dev': ${error?.message}`); + if (error.stdout) { + console.error(`[ERROR] stdout: ${error.stdout}`); + } + if (error.stderr) { + console.error(`[ERROR] stderr: ${error.stderr}`); + } + throw new Error(`Error ensuring branch 'ai-dev': ${error?.message}`); + } + } + + static async _ensureGitignore() { + try { + console.log(`[DEBUG] Checking .gitignore file...`); + const gitignorePath = path.join(ROOT_PATH, '.gitignore'); + + let gitignoreContent = ''; + try { + gitignoreContent = await fs.readFile(gitignorePath, 'utf8'); + console.log(`[DEBUG] Existing .gitignore found.`); + } catch (error) { + console.log(`[DEBUG] .gitignore file not found, creating new one.`); + } + + + const requiredPatterns = [ + 'node_modules/', + '*/node_modules/', + '**/node_modules/', + '*/build/', + '**/build/', + '.DS_Store', + '.env' + ]; + + let needsUpdate = false; + for (const pattern of requiredPatterns) { + if (!gitignoreContent.includes(pattern)) { + gitignoreContent += `\n${pattern}`; + needsUpdate = true; + } + } + + if (needsUpdate) { + console.log(`[DEBUG] Updating .gitignore file with missing patterns.`); + await fs.writeFile(gitignorePath, gitignoreContent.trim(), 'utf8'); + console.log(`[DEBUG] .gitignore file updated successfully.`); + } else { + console.log(`[DEBUG] .gitignore file is up to date.`); + } + + return true; + } catch (error) { + console.error(`[ERROR] Error ensuring .gitignore: ${error?.message}`); + return false; + } + } + + static async _waitForGitLockRelease(gitDir, timeout = 10000, interval = 500) { + const lockFilePath = path.join(gitDir, 'index.lock'); + const startTime = Date.now(); + + while (Date.now() - startTime < timeout) { + try { + await fs.access(lockFilePath); + console.log('[DEBUG] index.lock file exists. Waiting...'); + await new Promise(resolve => setTimeout(resolve, interval)); + } catch (err) { + console.log('[DEBUG] index.lock file no longer exists. Proceeding...'); + return; + } + } + + throw new Error('Timeout waiting for index.lock to be released'); + } + + static async _removeGitLockIfExists(gitDir) { + const lockFilePath = path.join(gitDir, 'index.lock'); + try { + await fs.access(lockFilePath); + console.log('[DEBUG] index.lock file exists. Removing...'); + await fs.unlink(lockFilePath); + console.log('[DEBUG] index.lock file removed.'); + } catch (err) { + console.log('[DEBUG] index.lock file does not exist. No action needed.'); + } + } + + static async _saveDevSchema(commitMessage, dev_schema) { + try { + let devSchemaData = {}; + try { + const fileContent = await fs.readFile(devSchemaFilePath, 'utf8'); + devSchemaData = JSON.parse(fileContent); + } catch (readError) { + console.log(`[DEBUG] _dev_schema.json not found or empty, creating new.`); + devSchemaData = {}; + } + + const schema = JSON.parse(dev_schema); + + devSchemaData[commitMessage] = JSON.stringify(schema); + + await fs.writeFile(devSchemaFilePath, JSON.stringify(devSchemaData, null, 2), 'utf8'); + console.log(`[DEBUG] _dev_schema.json updated with new schema for commit '${commitMessage}'`); + } catch (error) { + console.error(`[ERROR] Error saving dev schema: ${error?.message}`); + throw new Error(`Error saving dev schema: ${error?.message}`); + } + } + + static async _getDevSchemaByHash(hash) { + try { + const fileContent = await fs.readFile(devSchemaFilePath, 'utf8'); + const devSchemaData = JSON.parse(fileContent); + + if (devSchemaData[hash]) { + return devSchemaData[hash]; + } else { + throw new Error(`Schema not found for commit hash: ${hash}`); + } + } catch (error) { + console.error(`[ERROR] Error reading dev schema: ${error?.message}`); + console.error(`Error reading dev schema: ${error?.message}`); + } + } + + static async _getDevSchemaByCommitMessage(commitMessage) { + try { + const fileContent = await fs.readFile(devSchemaFilePath, 'utf8'); + const devSchemaData = JSON.parse(fileContent); + + if (devSchemaData[commitMessage]) { + return devSchemaData[commitMessage]; + } else { + throw new Error(`Schema not found for commit message: ${commitMessage}`); + } + } catch (error) { + console.error(`[ERROR] Error retrieving dev schema: ${error.message}`); + throw new Error(`Error retrieving dev schema: ${error.message}`); + } + } + + static async _getCommitMessageByHash(commitHash) { + return new Promise((resolve, reject) => { + exec(`git log -1 --format=%B ${commitHash}`, (error, stdout, stderr) => { + if (error) { + reject(`Error getting commit message: ${stderr}`); + } else { + resolve(stdout.trim()); + } + }); + }); + } +} + +module.exports = VCS; \ No newline at end of file diff --git a/app-shell/yarn.lock b/app-shell/yarn.lock new file mode 100644 index 0000000..63ccb71 --- /dev/null +++ b/app-shell/yarn.lock @@ -0,0 +1,3044 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@isaacs/cliui@^8.0.2": + version "8.0.2" + resolved "https://registry.yarnpkg.com/@isaacs/cliui/-/cliui-8.0.2.tgz#b37667b7bc181c168782259bab42474fbf52b550" + integrity sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA== + dependencies: + string-width "^5.1.2" + string-width-cjs "npm:string-width@^4.2.0" + strip-ansi "^7.0.1" + strip-ansi-cjs "npm:strip-ansi@^6.0.1" + wrap-ansi "^8.1.0" + wrap-ansi-cjs "npm:wrap-ansi@^7.0.0" + +"@mapbox/node-pre-gyp@^1.0.11": + version "1.0.11" + resolved "https://registry.yarnpkg.com/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz#417db42b7f5323d79e93b34a6d7a2a12c0df43fa" + integrity sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ== + dependencies: + detect-libc "^2.0.0" + https-proxy-agent "^5.0.0" + make-dir "^3.1.0" + node-fetch "^2.6.7" + nopt "^5.0.0" + npmlog "^5.0.1" + rimraf "^3.0.2" + semver "^7.3.5" + tar "^6.1.11" + +"@one-ini/wasm@0.1.1": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@one-ini/wasm/-/wasm-0.1.1.tgz#6013659736c9dbfccc96e8a9c2b3de317df39323" + integrity sha512-XuySG1E38YScSJoMlqovLru4KTUNSjgVTIjyh7qMX6aNN5HY5Ct5LhRJdxO79JtTzKfzV/bnWpz+zquYrISsvw== + +"@pkgjs/parseargs@^0.11.0": + version "0.11.0" + resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33" + integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg== + +abbrev@1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" + integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== + +abbrev@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-2.0.0.tgz#cf59829b8b4f03f89dda2771cb7f3653828c89bf" + integrity sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ== + +accepts@^1.3.7, accepts@~1.3.8: + version "1.3.8" + resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" + integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== + dependencies: + mime-types "~2.1.34" + negotiator "0.6.3" + +agent-base@6: + version "6.0.2" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" + integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ== + dependencies: + debug "4" + +ansi-colors@4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" + integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== + +ansi-regex@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.1.tgz#123d6479e92ad45ad897d4054e3c7ca7db4944e1" + integrity sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw== + +ansi-regex@^4.1.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.1.tgz#164daac87ab2d6f6db3a29875e2d1766582dabed" + integrity sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g== + +ansi-regex@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" + integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== + +ansi-regex@^6.0.1: + version "6.1.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.1.0.tgz#95ec409c69619d6cb1b8b34f14b660ef28ebd654" + integrity sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA== + +ansi-styles@^3.2.0: + version "3.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== + dependencies: + color-convert "^1.9.0" + +ansi-styles@^4.0.0, ansi-styles@^4.1.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" + +ansi-styles@^6.1.0: + version "6.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5" + integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug== + +anymatch@~3.1.1, anymatch@~3.1.2: + version "3.1.3" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" + integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + +append-field@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/append-field/-/append-field-1.0.0.tgz#1e3440e915f0b1203d23748e78edd7b9b5b43e56" + integrity sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw== + +"aproba@^1.0.3 || ^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/aproba/-/aproba-2.0.0.tgz#52520b8ae5b569215b354efc0caa3fe1e45a8adc" + integrity sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ== + +are-we-there-yet@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz#372e0e7bd279d8e94c653aaa1f67200884bf3e1c" + integrity sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw== + dependencies: + delegates "^1.0.0" + readable-stream "^3.6.0" + +argparse@^1.0.7: + version "1.0.10" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" + integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== + dependencies: + sprintf-js "~1.0.2" + +array-buffer-byte-length@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz#1e5583ec16763540a27ae52eed99ff899223568f" + integrity sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg== + dependencies: + call-bind "^1.0.5" + is-array-buffer "^3.0.4" + +array-flatten@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" + integrity sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg== + +array.prototype.map@^1.0.1: + version "1.0.7" + resolved "https://registry.yarnpkg.com/array.prototype.map/-/array.prototype.map-1.0.7.tgz#82fa4d6027272d1fca28a63bbda424d0185d78a7" + integrity sha512-XpcFfLoBEAhezrrNw1V+yLXkE7M6uR7xJEsxbG6c/V9v043qurwVJB9r9UTnoSioFDoz1i1VOydpWGmJpfVZbg== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + es-abstract "^1.23.2" + es-array-method-boxes-properly "^1.0.0" + es-object-atoms "^1.0.0" + is-string "^1.0.7" + +arraybuffer.prototype.slice@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz#097972f4255e41bc3425e37dc3f6421cf9aefde6" + integrity sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A== + dependencies: + array-buffer-byte-length "^1.0.1" + call-bind "^1.0.5" + define-properties "^1.2.1" + es-abstract "^1.22.3" + es-errors "^1.2.1" + get-intrinsic "^1.2.3" + is-array-buffer "^3.0.4" + is-shared-array-buffer "^1.0.2" + +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== + +at-least-node@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2" + integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg== + +available-typed-arrays@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz#a5cc375d6a03c2efc87a553f3e0b1522def14846" + integrity sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ== + dependencies: + possible-typed-array-names "^1.0.0" + +axios@^1.6.7: + version "1.7.7" + resolved "https://registry.yarnpkg.com/axios/-/axios-1.7.7.tgz#2f554296f9892a72ac8d8e4c5b79c14a91d0a47f" + integrity sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q== + dependencies: + follow-redirects "^1.15.6" + form-data "^4.0.0" + proxy-from-env "^1.1.0" + +balanced-match@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== + +base64url@3.x.x: + version "3.0.1" + resolved "https://registry.yarnpkg.com/base64url/-/base64url-3.0.1.tgz#6399d572e2bc3f90a9a8b22d5dbb0a32d33f788d" + integrity sha512-ir1UPr3dkwexU7FdV8qBBbNDRUhMmIekYMFZfi+C/sLNnRESKPl23nB9b2pltqfOQNnGzsDdId90AEtG5tCx4A== + +bcrypt@5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/bcrypt/-/bcrypt-5.1.1.tgz#0f732c6dcb4e12e5b70a25e326a72965879ba6e2" + integrity sha512-AGBHOG5hPYZ5Xl9KXzU5iKq9516yEmvCKDg3ecP5kX2aB6UqTeXZxk2ELnDgDm6BQSMlLt9rDB4LoSMx0rYwww== + dependencies: + "@mapbox/node-pre-gyp" "^1.0.11" + node-addon-api "^5.0.0" + +binary-extensions@^2.0.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.3.0.tgz#f6e14a97858d327252200242d4ccfe522c445522" + integrity sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw== + +bluebird@^3.7.2: + version "3.7.2" + resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" + integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== + +body-parser@1.20.1: + version "1.20.1" + resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.1.tgz#b1812a8912c195cd371a3ee5e66faa2338a5c668" + integrity sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw== + dependencies: + bytes "3.1.2" + content-type "~1.0.4" + debug "2.6.9" + depd "2.0.0" + destroy "1.2.0" + http-errors "2.0.0" + iconv-lite "0.4.24" + on-finished "2.4.1" + qs "6.11.0" + raw-body "2.5.1" + type-is "~1.6.18" + unpipe "1.0.0" + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +brace-expansion@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" + integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== + dependencies: + balanced-match "^1.0.0" + +braces@~3.0.2: + version "3.0.3" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789" + integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== + dependencies: + fill-range "^7.1.1" + +browser-stdout@1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" + integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== + +buffer-equal-constant-time@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819" + integrity sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA== + +buffer-from@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" + integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== + +busboy@^0.2.11: + version "0.2.14" + resolved "https://registry.yarnpkg.com/busboy/-/busboy-0.2.14.tgz#6c2a622efcf47c57bbbe1e2a9c37ad36c7925453" + integrity sha512-InWFDomvlkEj+xWLBfU3AvnbVYqeTWmQopiW0tWWEy5yehYm2YkGEc59sUmw/4ty5Zj/b0WHGs1LgecuBSBGrg== + dependencies: + dicer "0.2.5" + readable-stream "1.1.x" + +bytes@3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" + integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== + +call-bind@^1.0.2, call-bind@^1.0.5, call-bind@^1.0.6, call-bind@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.7.tgz#06016599c40c56498c18769d2730be242b6fa3b9" + integrity sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w== + dependencies: + es-define-property "^1.0.0" + es-errors "^1.3.0" + function-bind "^1.1.2" + get-intrinsic "^1.2.4" + set-function-length "^1.2.1" + +camelcase@^5.0.0, camelcase@^5.3.1: + version "5.3.1" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" + integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== + +chalk@^4.0.0: + version "4.1.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +chokidar@3.4.2: + version "3.4.2" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.4.2.tgz#38dc8e658dec3809741eb3ef7bb0a47fe424232d" + integrity sha512-IZHaDeBeI+sZJRX7lGcXsdzgvZqKv6sECqsbErJA4mHWfpRrD8B97kSFN4cQz6nGBGiuFia1MKR4d6c1o8Cv7A== + dependencies: + anymatch "~3.1.1" + braces "~3.0.2" + glob-parent "~5.1.0" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.4.0" + optionalDependencies: + fsevents "~2.1.2" + +chokidar@^3.5.2: + version "3.6.0" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b" + integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw== + dependencies: + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" + optionalDependencies: + fsevents "~2.3.2" + +chownr@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece" + integrity sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ== + +cli-color@^2.0.3: + version "2.0.4" + resolved "https://registry.yarnpkg.com/cli-color/-/cli-color-2.0.4.tgz#d658080290968816b322248b7306fad2346fb2c8" + integrity sha512-zlnpg0jNcibNrO7GG9IeHH7maWFeCz+Ja1wx/7tZNU5ASSSSZ+/qZciM0/LHCYxSdqv5h2sdbQ/PXYdOuetXvA== + dependencies: + d "^1.0.1" + es5-ext "^0.10.64" + es6-iterator "^2.0.3" + memoizee "^0.4.15" + timers-ext "^0.1.7" + +cliui@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-5.0.0.tgz#deefcfdb2e800784aa34f46fa08e06851c7bbbc5" + integrity sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA== + dependencies: + string-width "^3.1.0" + strip-ansi "^5.2.0" + wrap-ansi "^5.1.0" + +cliui@^7.0.2: + version "7.0.4" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" + integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.0" + wrap-ansi "^7.0.0" + +color-convert@^1.9.0: + version "1.9.3" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== + dependencies: + color-name "1.1.3" + +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + +color-name@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== + +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +color-support@^1.1.2: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-support/-/color-support-1.1.3.tgz#93834379a1cc9a0c61f82f52f0d04322251bd5a2" + integrity sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg== + +combined-stream@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" + integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== + dependencies: + delayed-stream "~1.0.0" + +commander@^10.0.0: + version "10.0.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-10.0.1.tgz#881ee46b4f77d1c1dccc5823433aa39b022cbe06" + integrity sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug== + +commander@^6.1.0: + version "6.2.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-6.2.1.tgz#0792eb682dfbc325999bb2b84fddddba110ac73c" + integrity sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA== + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== + +concat-stream@^1.5.2: + version "1.6.2" + resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" + integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== + dependencies: + buffer-from "^1.0.0" + inherits "^2.0.3" + readable-stream "^2.2.2" + typedarray "^0.0.6" + +config-chain@^1.1.13: + version "1.1.13" + resolved "https://registry.yarnpkg.com/config-chain/-/config-chain-1.1.13.tgz#fad0795aa6a6cdaff9ed1b68e9dff94372c232f4" + integrity sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ== + dependencies: + ini "^1.3.4" + proto-list "~1.2.1" + +console-control-strings@^1.0.0, console-control-strings@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" + integrity sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ== + +content-disposition@0.5.4: + version "0.5.4" + resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.4.tgz#8b82b4efac82512a02bb0b1dcec9d2c5e8eb5bfe" + integrity sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ== + dependencies: + safe-buffer "5.2.1" + +content-type@~1.0.4: + version "1.0.5" + resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.5.tgz#8b773162656d1d1086784c8f23a54ce6d73d7918" + integrity sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA== + +cookie-signature@1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" + integrity sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ== + +cookie@0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.5.0.tgz#d1f5d71adec6558c58f389987c366aa47e994f8b" + integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw== + +core-util-is@~1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" + integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== + +cors@2.8.5: + version "2.8.5" + resolved "https://registry.yarnpkg.com/cors/-/cors-2.8.5.tgz#eac11da51592dd86b9f06f6e7ac293b3df875d29" + integrity sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g== + dependencies: + object-assign "^4" + vary "^1" + +cross-env@7.0.3: + version "7.0.3" + resolved "https://registry.yarnpkg.com/cross-env/-/cross-env-7.0.3.tgz#865264b29677dc015ba8418918965dd232fc54cf" + integrity sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw== + dependencies: + cross-spawn "^7.0.1" + +cross-spawn@^7.0.0, cross-spawn@^7.0.1: + version "7.0.3" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" + integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + +csv-parser@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/csv-parser/-/csv-parser-3.0.0.tgz#b88a6256d79e090a97a1b56451f9327b01d710e7" + integrity sha512-s6OYSXAK3IdKqYO33y09jhypG/bSDHPuyCme/IdEHfWpLf/jKcpitVFyOC6UemgGk8v7Q5u2XE0vvwmanxhGlQ== + dependencies: + minimist "^1.2.0" + +d@1, d@^1.0.1, d@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/d/-/d-1.0.2.tgz#2aefd554b81981e7dccf72d6842ae725cb17e5de" + integrity sha512-MOqHvMWF9/9MX6nza0KgvFH4HpMU0EF5uUDXqX/BtxtU8NfB0QzRtJ8Oe/6SuS4kbhyzVJwjd97EA4PKrzJ8bw== + dependencies: + es5-ext "^0.10.64" + type "^2.7.2" + +data-view-buffer@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/data-view-buffer/-/data-view-buffer-1.0.1.tgz#8ea6326efec17a2e42620696e671d7d5a8bc66b2" + integrity sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA== + dependencies: + call-bind "^1.0.6" + es-errors "^1.3.0" + is-data-view "^1.0.1" + +data-view-byte-length@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz#90721ca95ff280677eb793749fce1011347669e2" + integrity sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ== + dependencies: + call-bind "^1.0.7" + es-errors "^1.3.0" + is-data-view "^1.0.1" + +data-view-byte-offset@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz#5e0bbfb4828ed2d1b9b400cd8a7d119bca0ff18a" + integrity sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA== + dependencies: + call-bind "^1.0.6" + es-errors "^1.3.0" + is-data-view "^1.0.1" + +debug@2.6.9: + version "2.6.9" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== + dependencies: + ms "2.0.0" + +debug@4, debug@^4: + version "4.3.7" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.7.tgz#87945b4151a011d76d95a198d7111c865c360a52" + integrity sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ== + dependencies: + ms "^2.1.3" + +debug@4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" + integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw== + dependencies: + ms "^2.1.1" + +decamelize@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" + integrity sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA== + +define-data-property@^1.0.1, define-data-property@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.4.tgz#894dc141bb7d3060ae4366f6a0107e68fbe48c5e" + integrity sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A== + dependencies: + es-define-property "^1.0.0" + es-errors "^1.3.0" + gopd "^1.0.1" + +define-properties@^1.1.2, define-properties@^1.1.3, define-properties@^1.2.0, define-properties@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.1.tgz#10781cc616eb951a80a034bafcaa7377f6af2b6c" + integrity sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg== + dependencies: + define-data-property "^1.0.1" + has-property-descriptors "^1.0.0" + object-keys "^1.1.1" + +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== + +delegates@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" + integrity sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ== + +depd@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" + integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== + +depd@^1.1.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" + integrity sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ== + +destroy@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" + integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== + +detect-libc@^2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-2.0.3.tgz#f0cd503b40f9939b894697d19ad50895e30cf700" + integrity sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw== + +dicer@0.2.5: + version "0.2.5" + resolved "https://registry.yarnpkg.com/dicer/-/dicer-0.2.5.tgz#5996c086bb33218c812c090bddc09cd12facb70f" + integrity sha512-FDvbtnq7dzlPz0wyYlOExifDEZcu8h+rErEXgfxqmLfRfC/kJidEFh4+effJRO3P0xmfqyPbSMG0LveNRfTKVg== + dependencies: + readable-stream "1.1.x" + streamsearch "0.1.2" + +diff@4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" + integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== + +eastasianwidth@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" + integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA== + +ecdsa-sig-formatter@1.0.11: + version "1.0.11" + resolved "https://registry.yarnpkg.com/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz#ae0f0fa2d85045ef14a817daa3ce9acd0489e5bf" + integrity sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ== + dependencies: + safe-buffer "^5.0.1" + +editorconfig@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/editorconfig/-/editorconfig-1.0.4.tgz#040c9a8e9a6c5288388b87c2db07028aa89f53a3" + integrity sha512-L9Qe08KWTlqYMVvMcTIvMAdl1cDUubzRNYL+WfA4bLDMHe4nemKkpmYzkznE1FwLKu0EEmy6obgQKzMJrg4x9Q== + dependencies: + "@one-ini/wasm" "0.1.1" + commander "^10.0.0" + minimatch "9.0.1" + semver "^7.5.3" + +ee-first@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" + integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== + +emoji-regex@^7.0.1: + version "7.0.3" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" + integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== + +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + +emoji-regex@^9.2.2: + version "9.2.2" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" + integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== + +encodeurl@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" + integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== + +es-abstract@^1.17.0-next.1, es-abstract@^1.22.1, es-abstract@^1.22.3, es-abstract@^1.23.0, es-abstract@^1.23.2: + version "1.23.3" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.23.3.tgz#8f0c5a35cd215312573c5a27c87dfd6c881a0aa0" + integrity sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A== + dependencies: + array-buffer-byte-length "^1.0.1" + arraybuffer.prototype.slice "^1.0.3" + available-typed-arrays "^1.0.7" + call-bind "^1.0.7" + data-view-buffer "^1.0.1" + data-view-byte-length "^1.0.1" + data-view-byte-offset "^1.0.0" + es-define-property "^1.0.0" + es-errors "^1.3.0" + es-object-atoms "^1.0.0" + es-set-tostringtag "^2.0.3" + es-to-primitive "^1.2.1" + function.prototype.name "^1.1.6" + get-intrinsic "^1.2.4" + get-symbol-description "^1.0.2" + globalthis "^1.0.3" + gopd "^1.0.1" + has-property-descriptors "^1.0.2" + has-proto "^1.0.3" + has-symbols "^1.0.3" + hasown "^2.0.2" + internal-slot "^1.0.7" + is-array-buffer "^3.0.4" + is-callable "^1.2.7" + is-data-view "^1.0.1" + is-negative-zero "^2.0.3" + is-regex "^1.1.4" + is-shared-array-buffer "^1.0.3" + is-string "^1.0.7" + is-typed-array "^1.1.13" + is-weakref "^1.0.2" + object-inspect "^1.13.1" + object-keys "^1.1.1" + object.assign "^4.1.5" + regexp.prototype.flags "^1.5.2" + safe-array-concat "^1.1.2" + safe-regex-test "^1.0.3" + string.prototype.trim "^1.2.9" + string.prototype.trimend "^1.0.8" + string.prototype.trimstart "^1.0.8" + typed-array-buffer "^1.0.2" + typed-array-byte-length "^1.0.1" + typed-array-byte-offset "^1.0.2" + typed-array-length "^1.0.6" + unbox-primitive "^1.0.2" + which-typed-array "^1.1.15" + +es-array-method-boxes-properly@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz#873f3e84418de4ee19c5be752990b2e44718d09e" + integrity sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA== + +es-define-property@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.0.tgz#c7faefbdff8b2696cf5f46921edfb77cc4ba3845" + integrity sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ== + dependencies: + get-intrinsic "^1.2.4" + +es-errors@^1.2.1, es-errors@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f" + integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== + +es-get-iterator@^1.0.2: + version "1.1.3" + resolved "https://registry.yarnpkg.com/es-get-iterator/-/es-get-iterator-1.1.3.tgz#3ef87523c5d464d41084b2c3c9c214f1199763d6" + integrity sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.1.3" + has-symbols "^1.0.3" + is-arguments "^1.1.1" + is-map "^2.0.2" + is-set "^2.0.2" + is-string "^1.0.7" + isarray "^2.0.5" + stop-iteration-iterator "^1.0.0" + +es-object-atoms@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/es-object-atoms/-/es-object-atoms-1.0.0.tgz#ddb55cd47ac2e240701260bc2a8e31ecb643d941" + integrity sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw== + dependencies: + es-errors "^1.3.0" + +es-set-tostringtag@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz#8bb60f0a440c2e4281962428438d58545af39777" + integrity sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ== + dependencies: + get-intrinsic "^1.2.4" + has-tostringtag "^1.0.2" + hasown "^2.0.1" + +es-to-primitive@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" + integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA== + dependencies: + is-callable "^1.1.4" + is-date-object "^1.0.1" + is-symbol "^1.0.2" + +es5-ext@^0.10.35, es5-ext@^0.10.46, es5-ext@^0.10.62, es5-ext@^0.10.64, es5-ext@~0.10.14, es5-ext@~0.10.2: + version "0.10.64" + resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.64.tgz#12e4ffb48f1ba2ea777f1fcdd1918ef73ea21714" + integrity sha512-p2snDhiLaXe6dahss1LddxqEm+SkuDvV8dnIQG0MWjyHpcMNfXKPE+/Cc0y+PhxJX3A4xGNeFCj5oc0BUh6deg== + dependencies: + es6-iterator "^2.0.3" + es6-symbol "^3.1.3" + esniff "^2.0.1" + next-tick "^1.1.0" + +es6-iterator@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7" + integrity sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g== + dependencies: + d "1" + es5-ext "^0.10.35" + es6-symbol "^3.1.1" + +es6-symbol@^3.1.1, es6-symbol@^3.1.3: + version "3.1.4" + resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.4.tgz#f4e7d28013770b4208ecbf3e0bf14d3bcb557b8c" + integrity sha512-U9bFFjX8tFiATgtkJ1zg25+KviIXpgRvRHS8sau3GfhVzThRQrOeksPeT0BWW2MNZs1OEWJ1DPXOQMn0KKRkvg== + dependencies: + d "^1.0.2" + ext "^1.7.0" + +es6-weak-map@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/es6-weak-map/-/es6-weak-map-2.0.3.tgz#b6da1f16cc2cc0d9be43e6bdbfc5e7dfcdf31d53" + integrity sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA== + dependencies: + d "1" + es5-ext "^0.10.46" + es6-iterator "^2.0.3" + es6-symbol "^3.1.1" + +escalade@^3.1.1: + version "3.2.0" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.2.0.tgz#011a3f69856ba189dffa7dc8fcce99d2a87903e5" + integrity sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA== + +escape-html@~1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" + integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== + +escape-string-regexp@4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" + integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== + +esniff@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/esniff/-/esniff-2.0.1.tgz#a4d4b43a5c71c7ec51c51098c1d8a29081f9b308" + integrity sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg== + dependencies: + d "^1.0.1" + es5-ext "^0.10.62" + event-emitter "^0.3.5" + type "^2.7.2" + +esprima@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" + integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== + +etag@~1.8.1: + version "1.8.1" + resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" + integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== + +event-emitter@^0.3.5: + version "0.3.5" + resolved "https://registry.yarnpkg.com/event-emitter/-/event-emitter-0.3.5.tgz#df8c69eef1647923c7157b9ce83840610b02cc39" + integrity sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA== + dependencies: + d "1" + es5-ext "~0.10.14" + +express@4.18.2: + version "4.18.2" + resolved "https://registry.yarnpkg.com/express/-/express-4.18.2.tgz#3fabe08296e930c796c19e3c516979386ba9fd59" + integrity sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ== + dependencies: + accepts "~1.3.8" + array-flatten "1.1.1" + body-parser "1.20.1" + content-disposition "0.5.4" + content-type "~1.0.4" + cookie "0.5.0" + cookie-signature "1.0.6" + debug "2.6.9" + depd "2.0.0" + encodeurl "~1.0.2" + escape-html "~1.0.3" + etag "~1.8.1" + finalhandler "1.2.0" + fresh "0.5.2" + http-errors "2.0.0" + merge-descriptors "1.0.1" + methods "~1.1.2" + on-finished "2.4.1" + parseurl "~1.3.3" + path-to-regexp "0.1.7" + proxy-addr "~2.0.7" + qs "6.11.0" + range-parser "~1.2.1" + safe-buffer "5.2.1" + send "0.18.0" + serve-static "1.15.0" + setprototypeof "1.2.0" + statuses "2.0.1" + type-is "~1.6.18" + utils-merge "1.0.1" + vary "~1.1.2" + +ext@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/ext/-/ext-1.7.0.tgz#0ea4383c0103d60e70be99e9a7f11027a33c4f5f" + integrity sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw== + dependencies: + type "^2.7.2" + +fill-range@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" + integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg== + dependencies: + to-regex-range "^5.0.1" + +finalhandler@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.2.0.tgz#7d23fe5731b207b4640e4fcd00aec1f9207a7b32" + integrity sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg== + dependencies: + debug "2.6.9" + encodeurl "~1.0.2" + escape-html "~1.0.3" + on-finished "2.4.1" + parseurl "~1.3.3" + statuses "2.0.1" + unpipe "~1.0.0" + +find-up@5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" + integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== + dependencies: + locate-path "^6.0.0" + path-exists "^4.0.0" + +find-up@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" + integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg== + dependencies: + locate-path "^3.0.0" + +flat@^4.1.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/flat/-/flat-4.1.1.tgz#a392059cc382881ff98642f5da4dde0a959f309b" + integrity sha512-FmTtBsHskrU6FJ2VxCnsDb84wu9zhmO3cUX2kGFb5tuwhfXxGciiT0oRY+cck35QmG+NmGh5eLz6lLCpWTqwpA== + dependencies: + is-buffer "~2.0.3" + +follow-redirects@^1.15.6: + version "1.15.9" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.9.tgz#a604fa10e443bf98ca94228d9eebcc2e8a2c8ee1" + integrity sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ== + +for-each@^0.3.3: + version "0.3.3" + resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e" + integrity sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw== + dependencies: + is-callable "^1.1.3" + +foreground-child@^3.1.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-3.3.0.tgz#0ac8644c06e431439f8561db8ecf29a7b5519c77" + integrity sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg== + dependencies: + cross-spawn "^7.0.0" + signal-exit "^4.0.1" + +form-data@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.1.tgz#ba1076daaaa5bfd7e99c1a6cb02aa0a5cff90d48" + integrity sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + mime-types "^2.1.12" + +formidable@1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/formidable/-/formidable-1.2.2.tgz#bf69aea2972982675f00865342b982986f6b8dd9" + integrity sha512-V8gLm+41I/8kguQ4/o1D3RIHRmhYFG4pnNyonvua+40rqcEmT4+V71yaZ3B457xbbgCsCfjSPi65u/W6vK1U5Q== + +forwarded@0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" + integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow== + +fresh@0.5.2, fresh@^0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" + integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q== + +fs-extra@^9.1.0: + version "9.1.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.1.0.tgz#5954460c764a8da2094ba3554bf839e6b9a7c86d" + integrity sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ== + dependencies: + at-least-node "^1.0.0" + graceful-fs "^4.2.0" + jsonfile "^6.0.1" + universalify "^2.0.0" + +fs-minipass@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb" + integrity sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg== + dependencies: + minipass "^3.0.0" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== + +fsevents@~2.1.2: + version "2.1.3" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.1.3.tgz#fb738703ae8d2f9fe900c33836ddebee8b97f23e" + integrity sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ== + +fsevents@~2.3.2: + version "2.3.3" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" + integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== + +function-bind@^1.1.1, function-bind@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" + integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== + +function.prototype.name@^1.1.6: + version "1.1.6" + resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.6.tgz#cdf315b7d90ee77a4c6ee216c3c3362da07533fd" + integrity sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + functions-have-names "^1.2.3" + +functions-have-names@^1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834" + integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ== + +gauge@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/gauge/-/gauge-3.0.2.tgz#03bf4441c044383908bcfa0656ad91803259b395" + integrity sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q== + dependencies: + aproba "^1.0.3 || ^2.0.0" + color-support "^1.1.2" + console-control-strings "^1.0.0" + has-unicode "^2.0.1" + object-assign "^4.1.1" + signal-exit "^3.0.0" + string-width "^4.2.3" + strip-ansi "^6.0.1" + wide-align "^1.1.2" + +get-caller-file@^2.0.1, get-caller-file@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== + +get-intrinsic@^1.1.3, get-intrinsic@^1.2.1, get-intrinsic@^1.2.3, get-intrinsic@^1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.4.tgz#e385f5a4b5227d449c3eabbad05494ef0abbeadd" + integrity sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ== + dependencies: + es-errors "^1.3.0" + function-bind "^1.1.2" + has-proto "^1.0.1" + has-symbols "^1.0.3" + hasown "^2.0.0" + +get-symbol-description@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.0.2.tgz#533744d5aa20aca4e079c8e5daf7fd44202821f5" + integrity sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg== + dependencies: + call-bind "^1.0.5" + es-errors "^1.3.0" + get-intrinsic "^1.2.4" + +glob-parent@~5.1.0, glob-parent@~5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== + dependencies: + is-glob "^4.0.1" + +glob@7.1.6: + version "7.1.6" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" + integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +glob@^10.3.3: + version "10.4.5" + resolved "https://registry.yarnpkg.com/glob/-/glob-10.4.5.tgz#f4d9f0b90ffdbab09c9d77f5f29b4262517b0956" + integrity sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg== + dependencies: + foreground-child "^3.1.0" + jackspeak "^3.1.2" + minimatch "^9.0.4" + minipass "^7.1.2" + package-json-from-dist "^1.0.0" + path-scurry "^1.11.1" + +glob@^7.1.3: + version "7.2.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" + integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.1.1" + once "^1.3.0" + path-is-absolute "^1.0.0" + +globalthis@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.4.tgz#7430ed3a975d97bfb59bcce41f5cabbafa651236" + integrity sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ== + dependencies: + define-properties "^1.2.1" + gopd "^1.0.1" + +gopd@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c" + integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA== + dependencies: + get-intrinsic "^1.1.3" + +graceful-fs@^4.1.6, graceful-fs@^4.2.0: + version "4.2.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" + integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== + +growl@1.10.5: + version "1.10.5" + resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e" + integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA== + +has-bigints@^1.0.1, has-bigints@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa" + integrity sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ== + +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== + +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + +has-property-descriptors@^1.0.0, has-property-descriptors@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz#963ed7d071dc7bf5f084c5bfbe0d1b6222586854" + integrity sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg== + dependencies: + es-define-property "^1.0.0" + +has-proto@^1.0.1, has-proto@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.3.tgz#b31ddfe9b0e6e9914536a6ab286426d0214f77fd" + integrity sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q== + +has-symbols@^1.0.0, has-symbols@^1.0.2, has-symbols@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" + integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== + +has-tostringtag@^1.0.0, has-tostringtag@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.2.tgz#2cdc42d40bef2e5b4eeab7c01a73c54ce7ab5abc" + integrity sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw== + dependencies: + has-symbols "^1.0.3" + +has-unicode@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" + integrity sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ== + +hasown@^2.0.0, hasown@^2.0.1, hasown@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" + integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== + dependencies: + function-bind "^1.1.2" + +he@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" + integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== + +helmet@4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/helmet/-/helmet-4.1.1.tgz#751f0e273d809ace9c172073e0003bed27d27a4a" + integrity sha512-Avg4XxSBrehD94mkRwEljnO+6RZx7AGfk8Wa6K1nxaU+hbXlFOhlOIMgPfFqOYQB/dBCsTpootTGuiOG+CHiQA== + +http-errors@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3" + integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ== + dependencies: + depd "2.0.0" + inherits "2.0.4" + setprototypeof "1.2.0" + statuses "2.0.1" + toidentifier "1.0.1" + +https-proxy-agent@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6" + integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA== + dependencies: + agent-base "6" + debug "4" + +iconv-lite@0.4.24: + version "0.4.24" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" + integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== + dependencies: + safer-buffer ">= 2.1.2 < 3" + +ignore-by-default@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/ignore-by-default/-/ignore-by-default-1.0.1.tgz#48ca6d72f6c6a3af00a9ad4ae6876be3889e2b09" + integrity sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA== + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@2.0.4, inherits@^2.0.3, inherits@~2.0.1, inherits@~2.0.3: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +ini@^1.3.4: + version "1.3.8" + resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" + integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== + +internal-slot@^1.0.4, internal-slot@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.7.tgz#c06dcca3ed874249881007b0a5523b172a190802" + integrity sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g== + dependencies: + es-errors "^1.3.0" + hasown "^2.0.0" + side-channel "^1.0.4" + +ipaddr.js@1.9.1: + version "1.9.1" + resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" + integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== + +is-arguments@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.1.tgz#15b3f88fda01f2a97fec84ca761a560f123efa9b" + integrity sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA== + dependencies: + call-bind "^1.0.2" + has-tostringtag "^1.0.0" + +is-array-buffer@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/is-array-buffer/-/is-array-buffer-3.0.4.tgz#7a1f92b3d61edd2bc65d24f130530ea93d7fae98" + integrity sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.2.1" + +is-bigint@^1.0.1: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.4.tgz#08147a1875bc2b32005d41ccd8291dffc6691df3" + integrity sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg== + dependencies: + has-bigints "^1.0.1" + +is-binary-path@~2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" + integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== + dependencies: + binary-extensions "^2.0.0" + +is-boolean-object@^1.1.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.1.2.tgz#5c6dc200246dd9321ae4b885a114bb1f75f63719" + integrity sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA== + dependencies: + call-bind "^1.0.2" + has-tostringtag "^1.0.0" + +is-buffer@~2.0.3: + version "2.0.5" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.5.tgz#ebc252e400d22ff8d77fa09888821a24a658c191" + integrity sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ== + +is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.2.7: + version "1.2.7" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" + integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== + +is-core-module@^2.13.0: + version "2.15.1" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.15.1.tgz#a7363a25bee942fefab0de13bf6aa372c82dcc37" + integrity sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ== + dependencies: + hasown "^2.0.2" + +is-data-view@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-data-view/-/is-data-view-1.0.1.tgz#4b4d3a511b70f3dc26d42c03ca9ca515d847759f" + integrity sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w== + dependencies: + is-typed-array "^1.1.13" + +is-date-object@^1.0.1: + version "1.0.5" + resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.5.tgz#0841d5536e724c25597bf6ea62e1bd38298df31f" + integrity sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ== + dependencies: + has-tostringtag "^1.0.0" + +is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== + +is-fullwidth-code-point@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" + integrity sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w== + +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + +is-glob@^4.0.1, is-glob@~4.0.1: + version "4.0.3" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" + integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== + dependencies: + is-extglob "^2.1.1" + +is-map@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/is-map/-/is-map-2.0.3.tgz#ede96b7fe1e270b3c4465e3a465658764926d62e" + integrity sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw== + +is-negative-zero@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.3.tgz#ced903a027aca6381b777a5743069d7376a49747" + integrity sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw== + +is-number-object@^1.0.4: + version "1.0.7" + resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.7.tgz#59d50ada4c45251784e9904f5246c742f07a42fc" + integrity sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ== + dependencies: + has-tostringtag "^1.0.0" + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +is-plain-obj@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" + integrity sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg== + +is-promise@^2.2.2: + version "2.2.2" + resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.2.2.tgz#39ab959ccbf9a774cf079f7b40c7a26f763135f1" + integrity sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ== + +is-regex@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" + integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg== + dependencies: + call-bind "^1.0.2" + has-tostringtag "^1.0.0" + +is-set@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/is-set/-/is-set-2.0.3.tgz#8ab209ea424608141372ded6e0cb200ef1d9d01d" + integrity sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg== + +is-shared-array-buffer@^1.0.2, is-shared-array-buffer@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz#1237f1cba059cdb62431d378dcc37d9680181688" + integrity sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg== + dependencies: + call-bind "^1.0.7" + +is-string@^1.0.5, is-string@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd" + integrity sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg== + dependencies: + has-tostringtag "^1.0.0" + +is-symbol@^1.0.2, is-symbol@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.4.tgz#a6dac93b635b063ca6872236de88910a57af139c" + integrity sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg== + dependencies: + has-symbols "^1.0.2" + +is-typed-array@^1.1.13: + version "1.1.13" + resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.13.tgz#d6c5ca56df62334959322d7d7dd1cca50debe229" + integrity sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw== + dependencies: + which-typed-array "^1.1.14" + +is-weakref@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.2.tgz#9529f383a9338205e89765e0392efc2f100f06f2" + integrity sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ== + dependencies: + call-bind "^1.0.2" + +isarray@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" + integrity sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ== + +isarray@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723" + integrity sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw== + +isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== + +iterate-iterator@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/iterate-iterator/-/iterate-iterator-1.0.2.tgz#551b804c9eaa15b847ea6a7cdc2f5bf1ec150f91" + integrity sha512-t91HubM4ZDQ70M9wqp+pcNpu8OyJ9UAtXntT/Bcsvp5tZMnz9vRa+IunKXeI8AnfZMTv0jNuVEmGeLSMjVvfPw== + +iterate-value@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/iterate-value/-/iterate-value-1.0.2.tgz#935115bd37d006a52046535ebc8d07e9c9337f57" + integrity sha512-A6fMAio4D2ot2r/TYzr4yUWrmwNdsN5xL7+HUiyACE4DXm+q8HtPcnFTp+NnW3k4N05tZ7FVYFFb2CR13NxyHQ== + dependencies: + es-get-iterator "^1.0.2" + iterate-iterator "^1.0.1" + +jackspeak@^3.1.2: + version "3.4.3" + resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-3.4.3.tgz#8833a9d89ab4acde6188942bd1c53b6390ed5a8a" + integrity sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw== + dependencies: + "@isaacs/cliui" "^8.0.2" + optionalDependencies: + "@pkgjs/parseargs" "^0.11.0" + +js-beautify@^1.14.5: + version "1.15.1" + resolved "https://registry.yarnpkg.com/js-beautify/-/js-beautify-1.15.1.tgz#4695afb508c324e1084ee0b952a102023fc65b64" + integrity sha512-ESjNzSlt/sWE8sciZH8kBF8BPlwXPwhR6pWKAw8bw4Bwj+iZcnKW6ONWUutJ7eObuBZQpiIb8S7OYspWrKt7rA== + dependencies: + config-chain "^1.1.13" + editorconfig "^1.0.4" + glob "^10.3.3" + js-cookie "^3.0.5" + nopt "^7.2.0" + +js-cookie@^3.0.5: + version "3.0.5" + resolved "https://registry.yarnpkg.com/js-cookie/-/js-cookie-3.0.5.tgz#0b7e2fd0c01552c58ba86e0841f94dc2557dcdbc" + integrity sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw== + +js-yaml@3.14.0: + version "3.14.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.0.tgz#a7a34170f26a21bb162424d8adacb4113a69e482" + integrity sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + +json2csv@^5.0.7: + version "5.0.7" + resolved "https://registry.yarnpkg.com/json2csv/-/json2csv-5.0.7.tgz#f3a583c25abd9804be873e495d1e65ad8d1b54ae" + integrity sha512-YRZbUnyaJZLZUJSRi2G/MqahCyRv9n/ds+4oIetjDF3jWQA7AG7iSeKTiZiCNqtMZM7HDyt0e/W6lEnoGEmMGA== + dependencies: + commander "^6.1.0" + jsonparse "^1.3.1" + lodash.get "^4.4.2" + +jsonfile@^6.0.1: + version "6.1.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae" + integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ== + dependencies: + universalify "^2.0.0" + optionalDependencies: + graceful-fs "^4.1.6" + +jsonparse@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280" + integrity sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg== + +jsonwebtoken@8.5.1: + version "8.5.1" + resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz#00e71e0b8df54c2121a1f26137df2280673bcc0d" + integrity sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w== + dependencies: + jws "^3.2.2" + lodash.includes "^4.3.0" + lodash.isboolean "^3.0.3" + lodash.isinteger "^4.0.4" + lodash.isnumber "^3.0.3" + lodash.isplainobject "^4.0.6" + lodash.isstring "^4.0.1" + lodash.once "^4.0.0" + ms "^2.1.1" + semver "^5.6.0" + +jsonwebtoken@^9.0.0: + version "9.0.2" + resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz#65ff91f4abef1784697d40952bb1998c504caaf3" + integrity sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ== + dependencies: + jws "^3.2.2" + lodash.includes "^4.3.0" + lodash.isboolean "^3.0.3" + lodash.isinteger "^4.0.4" + lodash.isnumber "^3.0.3" + lodash.isplainobject "^4.0.6" + lodash.isstring "^4.0.1" + lodash.once "^4.0.0" + ms "^2.1.1" + semver "^7.5.4" + +jwa@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/jwa/-/jwa-1.4.1.tgz#743c32985cb9e98655530d53641b66c8645b039a" + integrity sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA== + dependencies: + buffer-equal-constant-time "1.0.1" + ecdsa-sig-formatter "1.0.11" + safe-buffer "^5.0.1" + +jws@^3.2.2: + version "3.2.2" + resolved "https://registry.yarnpkg.com/jws/-/jws-3.2.2.tgz#001099f3639468c9414000e99995fa52fb478304" + integrity sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA== + dependencies: + jwa "^1.4.1" + safe-buffer "^5.0.1" + +locate-path@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" + integrity sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A== + dependencies: + p-locate "^3.0.0" + path-exists "^3.0.0" + +locate-path@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" + integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== + dependencies: + p-locate "^5.0.0" + +lodash.get@^4.4.2: + version "4.4.2" + resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99" + integrity sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ== + +lodash.includes@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/lodash.includes/-/lodash.includes-4.3.0.tgz#60bb98a87cb923c68ca1e51325483314849f553f" + integrity sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w== + +lodash.isboolean@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz#6c2e171db2a257cd96802fd43b01b20d5f5870f6" + integrity sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg== + +lodash.isinteger@^4.0.4: + version "4.0.4" + resolved "https://registry.yarnpkg.com/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz#619c0af3d03f8b04c31f5882840b77b11cd68343" + integrity sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA== + +lodash.isnumber@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz#3ce76810c5928d03352301ac287317f11c0b1ffc" + integrity sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw== + +lodash.isplainobject@^4.0.6: + version "4.0.6" + resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb" + integrity sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA== + +lodash.isstring@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/lodash.isstring/-/lodash.isstring-4.0.1.tgz#d527dfb5456eca7cc9bb95d5daeaf88ba54a5451" + integrity sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw== + +lodash.once@^4.0.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac" + integrity sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg== + +lodash@4.17.21, lodash@^4.17.21: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== + +log-symbols@4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.0.0.tgz#69b3cc46d20f448eccdb75ea1fa733d9e821c920" + integrity sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA== + dependencies: + chalk "^4.0.0" + +lru-cache@^10.2.0: + version "10.4.3" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.4.3.tgz#410fc8a17b70e598013df257c2446b7f3383f119" + integrity sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ== + +lru-queue@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/lru-queue/-/lru-queue-0.1.0.tgz#2738bd9f0d3cf4f84490c5736c48699ac632cda3" + integrity sha512-BpdYkt9EvGl8OfWHDQPISVpcl5xZthb+XPsbELj5AQXxIC8IriDZIQYjBJPEm5rS420sjZ0TLEzRcq5KdBhYrQ== + dependencies: + es5-ext "~0.10.2" + +make-dir@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" + integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== + dependencies: + semver "^6.0.0" + +media-typer@0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" + integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ== + +memoizee@^0.4.15: + version "0.4.17" + resolved "https://registry.yarnpkg.com/memoizee/-/memoizee-0.4.17.tgz#942a5f8acee281fa6fb9c620bddc57e3b7382949" + integrity sha512-DGqD7Hjpi/1or4F/aYAspXKNm5Yili0QDAFAY4QYvpqpgiY6+1jOfqpmByzjxbWd/T9mChbCArXAbDAsTm5oXA== + dependencies: + d "^1.0.2" + es5-ext "^0.10.64" + es6-weak-map "^2.0.3" + event-emitter "^0.3.5" + is-promise "^2.2.2" + lru-queue "^0.1.0" + next-tick "^1.1.0" + timers-ext "^0.1.7" + +merge-descriptors@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" + integrity sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w== + +merge-descriptors@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.3.tgz#d80319a65f3c7935351e5cfdac8f9318504dbed5" + integrity sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ== + +methods@^1.1.2, methods@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" + integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w== + +mime-db@1.52.0: + version "1.52.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== + +mime-types@^2.1.12, mime-types@~2.1.24, mime-types@~2.1.34: + version "2.1.35" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" + integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== + dependencies: + mime-db "1.52.0" + +mime@1.6.0, mime@^1.3.4: + version "1.6.0" + resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" + integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== + +minimatch@3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" + integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== + dependencies: + brace-expansion "^1.1.7" + +minimatch@9.0.1: + version "9.0.1" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.1.tgz#8a555f541cf976c622daf078bb28f29fb927c253" + integrity sha512-0jWhJpD/MdhPXwPuiRkCbfYfSKp2qnn2eOc279qI7f+osl/l+prKSrvhg157zSYvx/1nmgn2NqdT6k2Z7zSH9w== + dependencies: + brace-expansion "^2.0.1" + +minimatch@^3.0.4, minimatch@^3.1.1, minimatch@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" + integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== + dependencies: + brace-expansion "^1.1.7" + +minimatch@^9.0.4: + version "9.0.5" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.5.tgz#d74f9dd6b57d83d8e98cfb82133b03978bc929e5" + integrity sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow== + dependencies: + brace-expansion "^2.0.1" + +minimist@^1.2.0, minimist@^1.2.6: + version "1.2.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" + integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== + +minipass@^3.0.0: + version "3.3.6" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.3.6.tgz#7bba384db3a1520d18c9c0e5251c3444e95dd94a" + integrity sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw== + dependencies: + yallist "^4.0.0" + +minipass@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-5.0.0.tgz#3e9788ffb90b694a5d0ec94479a45b5d8738133d" + integrity sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ== + +"minipass@^5.0.0 || ^6.0.2 || ^7.0.0", minipass@^7.1.2: + version "7.1.2" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.1.2.tgz#93a9626ce5e5e66bd4db86849e7515e92340a707" + integrity sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw== + +minizlib@^2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.2.tgz#e90d3466ba209b932451508a11ce3d3632145931" + integrity sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg== + dependencies: + minipass "^3.0.0" + yallist "^4.0.0" + +mkdirp@^0.5.4: + version "0.5.6" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6" + integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw== + dependencies: + minimist "^1.2.6" + +mkdirp@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" + integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== + +mocha@8.1.3: + version "8.1.3" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-8.1.3.tgz#5e93f873e35dfdd69617ea75f9c68c2ca61c2ac5" + integrity sha512-ZbaYib4hT4PpF4bdSO2DohooKXIn4lDeiYqB+vTmCdr6l2woW0b6H3pf5x4sM5nwQMru9RvjjHYWVGltR50ZBw== + dependencies: + ansi-colors "4.1.1" + browser-stdout "1.3.1" + chokidar "3.4.2" + debug "4.1.1" + diff "4.0.2" + escape-string-regexp "4.0.0" + find-up "5.0.0" + glob "7.1.6" + growl "1.10.5" + he "1.2.0" + js-yaml "3.14.0" + log-symbols "4.0.0" + minimatch "3.0.4" + ms "2.1.2" + object.assign "4.1.0" + promise.allsettled "1.0.2" + serialize-javascript "4.0.0" + strip-json-comments "3.0.1" + supports-color "7.1.0" + which "2.0.2" + wide-align "1.1.3" + workerpool "6.0.0" + yargs "13.3.2" + yargs-parser "13.1.2" + yargs-unparser "1.6.1" + +moment@2.30.1: + version "2.30.1" + resolved "https://registry.yarnpkg.com/moment/-/moment-2.30.1.tgz#f8c91c07b7a786e30c59926df530b4eac96974ae" + integrity sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how== + +ms@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== + +ms@2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +ms@2.1.3, ms@^2.1.1, ms@^2.1.3: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + +multer@^1.4.4: + version "1.4.4" + resolved "https://registry.yarnpkg.com/multer/-/multer-1.4.4.tgz#e2bc6cac0df57a8832b858d7418ccaa8ebaf7d8c" + integrity sha512-2wY2+xD4udX612aMqMcB8Ws2Voq6NIUPEtD1be6m411T4uDH/VtL9i//xvcyFlTVfRdaBsk7hV5tgrGQqhuBiw== + dependencies: + append-field "^1.0.0" + busboy "^0.2.11" + concat-stream "^1.5.2" + mkdirp "^0.5.4" + object-assign "^4.1.1" + on-finished "^2.3.0" + type-is "^1.6.4" + xtend "^4.0.0" + +negotiator@0.6.3: + version "0.6.3" + resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" + integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== + +next-tick@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.1.0.tgz#1836ee30ad56d67ef281b22bd199f709449b35eb" + integrity sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ== + +node-addon-api@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-5.1.0.tgz#49da1ca055e109a23d537e9de43c09cca21eb762" + integrity sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA== + +node-fetch@^2.6.7: + version "2.7.0" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" + integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== + dependencies: + whatwg-url "^5.0.0" + +node-mocks-http@1.9.0: + version "1.9.0" + resolved "https://registry.yarnpkg.com/node-mocks-http/-/node-mocks-http-1.9.0.tgz#6000c570fc4b809603782309be81c73a71d85b71" + integrity sha512-ILf7Ws8xyX9Rl2fLZ7xhZBovrRwgaP84M13esndP6V17M/8j25TpwNzb7Im8U9XCo6fRhdwqiQajWXpsas/E6w== + dependencies: + accepts "^1.3.7" + depd "^1.1.0" + fresh "^0.5.2" + merge-descriptors "^1.0.1" + methods "^1.1.2" + mime "^1.3.4" + parseurl "^1.3.3" + range-parser "^1.2.0" + type-is "^1.6.18" + +nodemon@^3.1.7: + version "3.1.7" + resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-3.1.7.tgz#07cb1f455f8bece6a499e0d72b5e029485521a54" + integrity sha512-hLj7fuMow6f0lbB0cD14Lz2xNjwsyruH251Pk4t/yIitCFJbmY1myuLlHm/q06aST4jg6EgAh74PIBBrRqpVAQ== + dependencies: + chokidar "^3.5.2" + debug "^4" + ignore-by-default "^1.0.1" + minimatch "^3.1.2" + pstree.remy "^1.1.8" + semver "^7.5.3" + simple-update-notifier "^2.0.0" + supports-color "^5.5.0" + touch "^3.1.0" + undefsafe "^2.0.5" + +nopt@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-5.0.0.tgz#530942bb58a512fccafe53fe210f13a25355dc88" + integrity sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ== + dependencies: + abbrev "1" + +nopt@^7.2.0: + version "7.2.1" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-7.2.1.tgz#1cac0eab9b8e97c9093338446eddd40b2c8ca1e7" + integrity sha512-taM24ViiimT/XntxbPyJQzCG+p4EKOpgD3mxFwW38mGjVUrfERQOeY4EDHjdnptttfHuHQXFx+lTP08Q+mLa/w== + dependencies: + abbrev "^2.0.0" + +normalize-path@^3.0.0, normalize-path@~3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + +npmlog@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-5.0.1.tgz#f06678e80e29419ad67ab964e0fa69959c1eb8b0" + integrity sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw== + dependencies: + are-we-there-yet "^2.0.0" + console-control-strings "^1.1.0" + gauge "^3.0.0" + set-blocking "^2.0.0" + +oauth@0.10.x: + version "0.10.0" + resolved "https://registry.yarnpkg.com/oauth/-/oauth-0.10.0.tgz#3551c4c9b95c53ea437e1e21e46b649482339c58" + integrity sha512-1orQ9MT1vHFGQxhuy7E/0gECD3fd2fCC+PIX+/jgmU/gI3EpRocXtmtvxCO5x3WZ443FLTLFWNDjl5MPJf9u+Q== + +oauth@0.9.x: + version "0.9.15" + resolved "https://registry.yarnpkg.com/oauth/-/oauth-0.9.15.tgz#bd1fefaf686c96b75475aed5196412ff60cfb9c1" + integrity sha512-a5ERWK1kh38ExDEfoO6qUHJb32rd7aYmPHuyCu3Fta/cnICvYmgd2uhuKXvPD+PXB+gCEYYEaQdIRAjCOwAKNA== + +object-assign@^4, object-assign@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== + +object-inspect@^1.13.1: + version "1.13.2" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.2.tgz#dea0088467fb991e67af4058147a24824a3043ff" + integrity sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g== + +object-keys@^1.0.11, object-keys@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" + integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== + +object.assign@4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.0.tgz#968bf1100d7956bb3ca086f006f846b3bc4008da" + integrity sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w== + dependencies: + define-properties "^1.1.2" + function-bind "^1.1.1" + has-symbols "^1.0.0" + object-keys "^1.0.11" + +object.assign@^4.1.5: + version "4.1.5" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.5.tgz#3a833f9ab7fdb80fc9e8d2300c803d216d8fdbb0" + integrity sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ== + dependencies: + call-bind "^1.0.5" + define-properties "^1.2.1" + has-symbols "^1.0.3" + object-keys "^1.1.1" + +on-finished@2.4.1, on-finished@^2.3.0: + version "2.4.1" + resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" + integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg== + dependencies: + ee-first "1.1.1" + +once@^1.3.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== + dependencies: + wrappy "1" + +p-limit@^2.0.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" + integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== + dependencies: + p-try "^2.0.0" + +p-limit@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" + integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== + dependencies: + yocto-queue "^0.1.0" + +p-locate@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" + integrity sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ== + dependencies: + p-limit "^2.0.0" + +p-locate@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" + integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== + dependencies: + p-limit "^3.0.2" + +p-try@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" + integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== + +package-json-from-dist@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz#4f1471a010827a86f94cfd9b0727e36d267de505" + integrity sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw== + +parseurl@^1.3.3, parseurl@~1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" + integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== + +passport-google-oauth2@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/passport-google-oauth2/-/passport-google-oauth2-0.2.0.tgz#fc9ea59e7091f02e24fd16d6be9257ea982ebbc3" + integrity sha512-62EdPtbfVdc55nIXi0p1WOa/fFMM8v/M8uQGnbcXA4OexZWCnfsEi3wo2buag+Is5oqpuHzOtI64JpHk0Xi5RQ== + dependencies: + passport-oauth2 "^1.1.2" + +passport-jwt@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/passport-jwt/-/passport-jwt-4.0.1.tgz#c443795eff322c38d173faa0a3c481479646ec3d" + integrity sha512-UCKMDYhNuGOBE9/9Ycuoyh7vP6jpeTp/+sfMJl7nLff/t6dps+iaeE0hhNkKN8/HZHcJ7lCdOyDxHdDoxoSvdQ== + dependencies: + jsonwebtoken "^9.0.0" + passport-strategy "^1.0.0" + +passport-microsoft@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/passport-microsoft/-/passport-microsoft-0.1.0.tgz#dc72c1a38b294d74f4dc55fe93f52e25cb9aa5b4" + integrity sha512-0giBDgE1fnR5X84zJZkQ11hnKVrzEgViwRO6RGsormK9zTxFQmN/UHMTDbIpvhk989VqALewB6Pk1R5vNr3GHw== + dependencies: + passport-oauth2 "1.2.0" + pkginfo "0.2.x" + +passport-oauth2@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/passport-oauth2/-/passport-oauth2-1.2.0.tgz#49613a3eca85c7a1e65bf1019e2b6b80a10c8ac2" + integrity sha512-6128N+n/MOrJdXxdC2q/PVKXtqgihGFIeup+9bsPybAvMPOUKqdGhh9ZIzZF8rFKJOlxUP9fgP3H0JQe18n0rg== + dependencies: + oauth "0.9.x" + passport-strategy "1.x.x" + uid2 "0.0.x" + +passport-oauth2@^1.1.2: + version "1.8.0" + resolved "https://registry.yarnpkg.com/passport-oauth2/-/passport-oauth2-1.8.0.tgz#55725771d160f09bbb191828d5e3d559eee079c8" + integrity sha512-cjsQbOrXIDE4P8nNb3FQRCCmJJ/utnFKEz2NX209f7KOHPoX18gF7gBzBbLLsj2/je4KrgiwLLGjf0lm9rtTBA== + dependencies: + base64url "3.x.x" + oauth "0.10.x" + passport-strategy "1.x.x" + uid2 "0.0.x" + utils-merge "1.x.x" + +passport-strategy@1.x.x, passport-strategy@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/passport-strategy/-/passport-strategy-1.0.0.tgz#b5539aa8fc225a3d1ad179476ddf236b440f52e4" + integrity sha512-CB97UUvDKJde2V0KDWWB3lyf6PC3FaZP7YxZ2G8OAtn9p4HI9j9JLP9qjOGZFvyl8uwNT8qM+hGnz/n16NI7oA== + +passport@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/passport/-/passport-0.7.0.tgz#3688415a59a48cf8068417a8a8092d4492ca3a05" + integrity sha512-cPLl+qZpSc+ireUvt+IzqbED1cHHkDoVYMo30jbJIdOOjQ1MQYZBPiNvmi8UM6lJuOpTPXJGZQk0DtC4y61MYQ== + dependencies: + passport-strategy "1.x.x" + pause "0.0.1" + utils-merge "^1.0.1" + +path-exists@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" + integrity sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ== + +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== + +path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + +path-parse@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" + integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== + +path-scurry@^1.11.1: + version "1.11.1" + resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.11.1.tgz#7960a668888594a0720b12a911d1a742ab9f11d2" + integrity sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA== + dependencies: + lru-cache "^10.2.0" + minipass "^5.0.0 || ^6.0.2 || ^7.0.0" + +path-to-regexp@0.1.7: + version "0.1.7" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" + integrity sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ== + +pause@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/pause/-/pause-0.0.1.tgz#1d408b3fdb76923b9543d96fb4c9dfd535d9cb5d" + integrity sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg== + +picomatch@^2.0.4, picomatch@^2.2.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== + +pkginfo@0.2.x: + version "0.2.3" + resolved "https://registry.yarnpkg.com/pkginfo/-/pkginfo-0.2.3.tgz#7239c42a5ef6c30b8f328439d9b9ff71042490f8" + integrity sha512-7W7wTrE/NsY8xv/DTGjwNIyNah81EQH0MWcTzrHL6pOpMocOGZc0Mbdz9aXxSrp+U0mSmkU8jrNCDCfUs3sOBg== + +possible-typed-array-names@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz#89bb63c6fada2c3e90adc4a647beeeb39cc7bf8f" + integrity sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q== + +process-nextick-args@~2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" + integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== + +promise.allsettled@1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/promise.allsettled/-/promise.allsettled-1.0.2.tgz#d66f78fbb600e83e863d893e98b3d4376a9c47c9" + integrity sha512-UpcYW5S1RaNKT6pd+s9jp9K9rlQge1UXKskec0j6Mmuq7UJCvlS2J2/s/yuPN8ehftf9HXMxWlKiPbGGUzpoRg== + dependencies: + array.prototype.map "^1.0.1" + define-properties "^1.1.3" + es-abstract "^1.17.0-next.1" + function-bind "^1.1.1" + iterate-value "^1.0.0" + +proto-list@~1.2.1: + version "1.2.4" + resolved "https://registry.yarnpkg.com/proto-list/-/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849" + integrity sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA== + +proxy-addr@~2.0.7: + version "2.0.7" + resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025" + integrity sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg== + dependencies: + forwarded "0.2.0" + ipaddr.js "1.9.1" + +proxy-from-env@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" + integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== + +pstree.remy@^1.1.8: + version "1.1.8" + resolved "https://registry.yarnpkg.com/pstree.remy/-/pstree.remy-1.1.8.tgz#c242224f4a67c21f686839bbdb4ac282b8373d3a" + integrity sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w== + +qs@6.11.0: + version "6.11.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a" + integrity sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q== + dependencies: + side-channel "^1.0.4" + +randombytes@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" + integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== + dependencies: + safe-buffer "^5.1.0" + +range-parser@^1.2.0, range-parser@~1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" + integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== + +raw-body@2.5.1: + version "2.5.1" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.1.tgz#fe1b1628b181b700215e5fd42389f98b71392857" + integrity sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig== + dependencies: + bytes "3.1.2" + http-errors "2.0.0" + iconv-lite "0.4.24" + unpipe "1.0.0" + +readable-stream@1.1.x: + version "1.1.14" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9" + integrity sha512-+MeVjFf4L44XUkhM1eYbD8fyEsxcV81pqMSR5gblfcLCHfZvbrqy4/qYHE+/R5HoBUT11WV5O08Cr1n3YXkWVQ== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "0.0.1" + string_decoder "~0.10.x" + +readable-stream@^2.2.2: + version "2.3.8" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b" + integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.1.1" + util-deprecate "~1.0.1" + +readable-stream@^3.6.0: + version "3.6.2" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" + integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + +readdirp@~3.4.0: + version "3.4.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.4.0.tgz#9fdccdf9e9155805449221ac645e8303ab5b9ada" + integrity sha512-0xe001vZBnJEK+uKcj8qOhyAKPzIT+gStxWr3LCB0DwcXR5NZJ3IaC+yGnHCYzB/S7ov3m3EEbZI2zeNvX+hGQ== + dependencies: + picomatch "^2.2.1" + +readdirp@~3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" + integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== + dependencies: + picomatch "^2.2.1" + +regexp.prototype.flags@^1.5.2: + version "1.5.3" + resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.5.3.tgz#b3ae40b1d2499b8350ab2c3fe6ef3845d3a96f42" + integrity sha512-vqlC04+RQoFalODCbCumG2xIOvapzVMHwsyIGM/SIE8fRhFFsXeH8/QQ+s0T0kDAhKc4k30s73/0ydkHQz6HlQ== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + es-errors "^1.3.0" + set-function-name "^2.0.2" + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== + +require-main-filename@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" + integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== + +resolve@^1.22.1: + version "1.22.8" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d" + integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== + dependencies: + is-core-module "^2.13.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + +rimraf@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" + integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== + dependencies: + glob "^7.1.3" + +safe-array-concat@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/safe-array-concat/-/safe-array-concat-1.1.2.tgz#81d77ee0c4e8b863635227c721278dd524c20edb" + integrity sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q== + dependencies: + call-bind "^1.0.7" + get-intrinsic "^1.2.4" + has-symbols "^1.0.3" + isarray "^2.0.5" + +safe-buffer@5.2.1, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@~5.2.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + +safe-buffer@~5.1.0, safe-buffer@~5.1.1: + version "5.1.2" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== + +safe-regex-test@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/safe-regex-test/-/safe-regex-test-1.0.3.tgz#a5b4c0f06e0ab50ea2c395c14d8371232924c377" + integrity sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw== + dependencies: + call-bind "^1.0.6" + es-errors "^1.3.0" + is-regex "^1.1.4" + +"safer-buffer@>= 2.1.2 < 3": + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + +semver@^5.6.0: + version "5.7.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" + integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== + +semver@^6.0.0: + version "6.3.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" + integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== + +semver@^7.3.5, semver@^7.5.3, semver@^7.5.4: + version "7.6.3" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.3.tgz#980f7b5550bc175fb4dc09403085627f9eb33143" + integrity sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A== + +send@0.18.0: + version "0.18.0" + resolved "https://registry.yarnpkg.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be" + integrity sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg== + dependencies: + debug "2.6.9" + depd "2.0.0" + destroy "1.2.0" + encodeurl "~1.0.2" + escape-html "~1.0.3" + etag "~1.8.1" + fresh "0.5.2" + http-errors "2.0.0" + mime "1.6.0" + ms "2.1.3" + on-finished "2.4.1" + range-parser "~1.2.1" + statuses "2.0.1" + +sequelize-cli@6.6.2: + version "6.6.2" + resolved "https://registry.yarnpkg.com/sequelize-cli/-/sequelize-cli-6.6.2.tgz#8d838b25c988cf136914cdc3843e19d88c3dcb67" + integrity sha512-V8Oh+XMz2+uquLZltZES6MVAD+yEnmMfwfn+gpXcDiwE3jyQygLt4xoI0zG8gKt6cRcs84hsKnXAKDQjG/JAgg== + dependencies: + cli-color "^2.0.3" + fs-extra "^9.1.0" + js-beautify "^1.14.5" + lodash "^4.17.21" + resolve "^1.22.1" + umzug "^2.3.0" + yargs "^16.2.0" + +sequelize-json-schema@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/sequelize-json-schema/-/sequelize-json-schema-2.1.1.tgz#a82d3813925e81485d76ce291f4ff5c8cb2ae492" + integrity sha512-yCGaHnmQQeL6MQ/fOxhkR5C2aOGZyTD6OrgjP4yw1rbuujuIUVdzWN3AsC6r6AvlGZ3EUBBbCJHKl8OIFFES4Q== + +serialize-javascript@4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-4.0.0.tgz#b525e1238489a5ecfc42afacc3fe99e666f4b1aa" + integrity sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw== + dependencies: + randombytes "^2.1.0" + +serve-static@1.15.0: + version "1.15.0" + resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.15.0.tgz#faaef08cffe0a1a62f60cad0c4e513cff0ac9540" + integrity sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g== + dependencies: + encodeurl "~1.0.2" + escape-html "~1.0.3" + parseurl "~1.3.3" + send "0.18.0" + +set-blocking@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw== + +set-function-length@^1.2.1: + version "1.2.2" + resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.2.tgz#aac72314198eaed975cf77b2c3b6b880695e5449" + integrity sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg== + dependencies: + define-data-property "^1.1.4" + es-errors "^1.3.0" + function-bind "^1.1.2" + get-intrinsic "^1.2.4" + gopd "^1.0.1" + has-property-descriptors "^1.0.2" + +set-function-name@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/set-function-name/-/set-function-name-2.0.2.tgz#16a705c5a0dc2f5e638ca96d8a8cd4e1c2b90985" + integrity sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ== + dependencies: + define-data-property "^1.1.4" + es-errors "^1.3.0" + functions-have-names "^1.2.3" + has-property-descriptors "^1.0.2" + +setprototypeof@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" + integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== + +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + +side-channel@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.6.tgz#abd25fb7cd24baf45466406b1096b7831c9215f2" + integrity sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA== + dependencies: + call-bind "^1.0.7" + es-errors "^1.3.0" + get-intrinsic "^1.2.4" + object-inspect "^1.13.1" + +signal-exit@^3.0.0: + version "3.0.7" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" + integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== + +signal-exit@^4.0.1: + version "4.1.0" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04" + integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== + +simple-update-notifier@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz#d70b92bdab7d6d90dfd73931195a30b6e3d7cebb" + integrity sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w== + dependencies: + semver "^7.5.3" + +sprintf-js@~1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== + +statuses@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" + integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== + +stop-iteration-iterator@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz#6a60be0b4ee757d1ed5254858ec66b10c49285e4" + integrity sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ== + dependencies: + internal-slot "^1.0.4" + +streamsearch@0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-0.1.2.tgz#808b9d0e56fc273d809ba57338e929919a1a9f1a" + integrity sha512-jos8u++JKm0ARcSUTAZXOVC0mSox7Bhn6sBgty73P1f3JGf7yG2clTbBNHUdde/kdvP2FESam+vM6l8jBrNxHA== + +"string-width-cjs@npm:string-width@^4.2.0": + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +"string-width@^1.0.2 || 2": + version "2.1.1" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" + integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== + dependencies: + is-fullwidth-code-point "^2.0.0" + strip-ansi "^4.0.0" + +"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string-width@^3.0.0, string-width@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" + integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w== + dependencies: + emoji-regex "^7.0.1" + is-fullwidth-code-point "^2.0.0" + strip-ansi "^5.1.0" + +string-width@^5.0.1, string-width@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" + integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA== + dependencies: + eastasianwidth "^0.2.0" + emoji-regex "^9.2.2" + strip-ansi "^7.0.1" + +string.prototype.trim@^1.2.9: + version "1.2.9" + resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz#b6fa326d72d2c78b6df02f7759c73f8f6274faa4" + integrity sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + es-abstract "^1.23.0" + es-object-atoms "^1.0.0" + +string.prototype.trimend@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz#3651b8513719e8a9f48de7f2f77640b26652b229" + integrity sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + es-object-atoms "^1.0.0" + +string.prototype.trimstart@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz#7ee834dda8c7c17eff3118472bb35bfedaa34dde" + integrity sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + es-object-atoms "^1.0.0" + +string_decoder@^1.1.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" + integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== + dependencies: + safe-buffer "~5.2.0" + +string_decoder@~0.10.x: + version "0.10.31" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" + integrity sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ== + +string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== + dependencies: + safe-buffer "~5.1.0" + +"strip-ansi-cjs@npm:strip-ansi@^6.0.1": + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" + integrity sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow== + dependencies: + ansi-regex "^3.0.0" + +strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" + integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== + dependencies: + ansi-regex "^4.1.0" + +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-ansi@^7.0.1: + version "7.1.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" + integrity sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ== + dependencies: + ansi-regex "^6.0.1" + +strip-json-comments@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.0.1.tgz#85713975a91fb87bf1b305cca77395e40d2a64a7" + integrity sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw== + +supports-color@7.1.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.1.0.tgz#68e32591df73e25ad1c4b49108a2ec507962bfd1" + integrity sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g== + dependencies: + has-flag "^4.0.0" + +supports-color@^5.5.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== + dependencies: + has-flag "^3.0.0" + +supports-color@^7.1.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + dependencies: + has-flag "^4.0.0" + +supports-preserve-symlinks-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" + integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== + +tar@^6.1.11: + version "6.2.1" + resolved "https://registry.yarnpkg.com/tar/-/tar-6.2.1.tgz#717549c541bc3c2af15751bea94b1dd068d4b03a" + integrity sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A== + dependencies: + chownr "^2.0.0" + fs-minipass "^2.0.0" + minipass "^5.0.0" + minizlib "^2.1.1" + mkdirp "^1.0.3" + yallist "^4.0.0" + +timers-ext@^0.1.7: + version "0.1.8" + resolved "https://registry.yarnpkg.com/timers-ext/-/timers-ext-0.1.8.tgz#b4e442f10b7624a29dd2aa42c295e257150cf16c" + integrity sha512-wFH7+SEAcKfJpfLPkrgMPvvwnEtj8W4IurvEyrKsDleXnKLCDw71w8jltvfLa8Rm4qQxxT4jmDBYbJG/z7qoww== + dependencies: + es5-ext "^0.10.64" + next-tick "^1.1.0" + +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + +toidentifier@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" + integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== + +touch@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/touch/-/touch-3.1.1.tgz#097a23d7b161476435e5c1344a95c0f75b4a5694" + integrity sha512-r0eojU4bI8MnHr8c5bNo7lJDdI2qXlWWJk6a9EAFG7vbhTjElYhBVS3/miuE0uOuoLdb8Mc/rVfsmm6eo5o9GA== + +tr46@~0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" + integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== + +type-is@^1.6.18, type-is@^1.6.4, type-is@~1.6.18: + version "1.6.18" + resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" + integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== + dependencies: + media-typer "0.3.0" + mime-types "~2.1.24" + +type@^2.7.2: + version "2.7.3" + resolved "https://registry.yarnpkg.com/type/-/type-2.7.3.tgz#436981652129285cc3ba94f392886c2637ea0486" + integrity sha512-8j+1QmAbPvLZow5Qpi6NCaN8FB60p/6x8/vfNqOk/hC+HuvFZhL4+WfekuhQLiqFZXOgQdrs3B+XxEmCc6b3FQ== + +typed-array-buffer@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz#1867c5d83b20fcb5ccf32649e5e2fc7424474ff3" + integrity sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ== + dependencies: + call-bind "^1.0.7" + es-errors "^1.3.0" + is-typed-array "^1.1.13" + +typed-array-byte-length@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz#d92972d3cff99a3fa2e765a28fcdc0f1d89dec67" + integrity sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw== + dependencies: + call-bind "^1.0.7" + for-each "^0.3.3" + gopd "^1.0.1" + has-proto "^1.0.3" + is-typed-array "^1.1.13" + +typed-array-byte-offset@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz#f9ec1acb9259f395093e4567eb3c28a580d02063" + integrity sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA== + dependencies: + available-typed-arrays "^1.0.7" + call-bind "^1.0.7" + for-each "^0.3.3" + gopd "^1.0.1" + has-proto "^1.0.3" + is-typed-array "^1.1.13" + +typed-array-length@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/typed-array-length/-/typed-array-length-1.0.6.tgz#57155207c76e64a3457482dfdc1c9d1d3c4c73a3" + integrity sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g== + dependencies: + call-bind "^1.0.7" + for-each "^0.3.3" + gopd "^1.0.1" + has-proto "^1.0.3" + is-typed-array "^1.1.13" + possible-typed-array-names "^1.0.0" + +typedarray@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" + integrity sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA== + +uid2@0.0.x: + version "0.0.4" + resolved "https://registry.yarnpkg.com/uid2/-/uid2-0.0.4.tgz#033f3b1d5d32505f5ce5f888b9f3b667123c0a44" + integrity sha512-IevTus0SbGwQzYh3+fRsAMTVVPOoIVufzacXcHPmdlle1jUpq7BRL+mw3dgeLanvGZdwwbWhRV6XrcFNdBmjWA== + +umzug@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/umzug/-/umzug-2.3.0.tgz#0ef42b62df54e216b05dcaf627830a6a8b84a184" + integrity sha512-Z274K+e8goZK8QJxmbRPhl89HPO1K+ORFtm6rySPhFKfKc5GHhqdzD0SGhSWHkzoXasqJuItdhorSvY7/Cgflw== + dependencies: + bluebird "^3.7.2" + +unbox-primitive@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.2.tgz#29032021057d5e6cdbd08c5129c226dff8ed6f9e" + integrity sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw== + dependencies: + call-bind "^1.0.2" + has-bigints "^1.0.2" + has-symbols "^1.0.3" + which-boxed-primitive "^1.0.2" + +undefsafe@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/undefsafe/-/undefsafe-2.0.5.tgz#38733b9327bdcd226db889fb723a6efd162e6e2c" + integrity sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA== + +universalify@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.1.tgz#168efc2180964e6386d061e094df61afe239b18d" + integrity sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw== + +unpipe@1.0.0, unpipe@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" + integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== + +util-deprecate@^1.0.1, util-deprecate@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== + +utils-merge@1.0.1, utils-merge@1.x.x, utils-merge@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" + integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA== + +vary@^1, vary@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" + integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== + +webidl-conversions@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" + integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== + +whatwg-url@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" + integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== + dependencies: + tr46 "~0.0.3" + webidl-conversions "^3.0.0" + +which-boxed-primitive@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6" + integrity sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg== + dependencies: + is-bigint "^1.0.1" + is-boolean-object "^1.1.0" + is-number-object "^1.0.4" + is-string "^1.0.5" + is-symbol "^1.0.3" + +which-module@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.1.tgz#776b1fe35d90aebe99e8ac15eb24093389a4a409" + integrity sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ== + +which-typed-array@^1.1.14, which-typed-array@^1.1.15: + version "1.1.15" + resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.15.tgz#264859e9b11a649b388bfaaf4f767df1f779b38d" + integrity sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA== + dependencies: + available-typed-arrays "^1.0.7" + call-bind "^1.0.7" + for-each "^0.3.3" + gopd "^1.0.1" + has-tostringtag "^1.0.2" + +which@2.0.2, which@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + +wide-align@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" + integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== + dependencies: + string-width "^1.0.2 || 2" + +wide-align@^1.1.2: + version "1.1.5" + resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.5.tgz#df1d4c206854369ecf3c9a4898f1b23fbd9d15d3" + integrity sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg== + dependencies: + string-width "^1.0.2 || 2 || 3 || 4" + +workerpool@6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.0.0.tgz#85aad67fa1a2c8ef9386a1b43539900f61d03d58" + integrity sha512-fU2OcNA/GVAJLLyKUoHkAgIhKb0JoCpSjLC/G2vYKxUjVmQwGbRVeoPJ1a8U4pnVofz4AQV5Y/NEw8oKqxEBtA== + +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrap-ansi@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-5.1.0.tgz#1fd1f67235d5b6d0fee781056001bfb694c03b09" + integrity sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q== + dependencies: + ansi-styles "^3.2.0" + string-width "^3.0.0" + strip-ansi "^5.0.0" + +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrap-ansi@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" + integrity sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ== + dependencies: + ansi-styles "^6.1.0" + string-width "^5.0.1" + strip-ansi "^7.0.1" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== + +xtend@^4.0.0: + version "4.0.2" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" + integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== + +y18n@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.3.tgz#b5f259c82cd6e336921efd7bfd8bf560de9eeedf" + integrity sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ== + +y18n@^5.0.5: + version "5.0.8" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" + integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== + +yallist@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== + +yargs-parser@13.1.2, yargs-parser@^13.1.2: + version "13.1.2" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.2.tgz#130f09702ebaeef2650d54ce6e3e5706f7a4fb38" + integrity sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg== + dependencies: + camelcase "^5.0.0" + decamelize "^1.2.0" + +yargs-parser@^15.0.1: + version "15.0.3" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-15.0.3.tgz#316e263d5febe8b38eef61ac092b33dfcc9b1115" + integrity sha512-/MVEVjTXy/cGAjdtQf8dW3V9b97bPN7rNn8ETj6BmAQL7ibC7O1Q9SPJbGjgh3SlwoBNXMzj/ZGIj8mBgl12YA== + dependencies: + camelcase "^5.0.0" + decamelize "^1.2.0" + +yargs-parser@^20.2.2: + version "20.2.9" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" + integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== + +yargs-unparser@1.6.1: + version "1.6.1" + resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-1.6.1.tgz#bd4b0ee05b4c94d058929c32cb09e3fce71d3c5f" + integrity sha512-qZV14lK9MWsGCmcr7u5oXGH0dbGqZAIxTDrWXZDo5zUr6b6iUmelNKO6x6R1dQT24AH3LgRxJpr8meWy2unolA== + dependencies: + camelcase "^5.3.1" + decamelize "^1.2.0" + flat "^4.1.0" + is-plain-obj "^1.1.0" + yargs "^14.2.3" + +yargs@13.3.2: + version "13.3.2" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.2.tgz#ad7ffefec1aa59565ac915f82dccb38a9c31a2dd" + integrity sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw== + dependencies: + cliui "^5.0.0" + find-up "^3.0.0" + get-caller-file "^2.0.1" + require-directory "^2.1.1" + require-main-filename "^2.0.0" + set-blocking "^2.0.0" + string-width "^3.0.0" + which-module "^2.0.0" + y18n "^4.0.0" + yargs-parser "^13.1.2" + +yargs@^14.2.3: + version "14.2.3" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-14.2.3.tgz#1a1c3edced1afb2a2fea33604bc6d1d8d688a414" + integrity sha512-ZbotRWhF+lkjijC/VhmOT9wSgyBQ7+zr13+YLkhfsSiTriYsMzkTUFP18pFhWwBeMa5gUc1MzbhrO6/VB7c9Xg== + dependencies: + cliui "^5.0.0" + decamelize "^1.2.0" + find-up "^3.0.0" + get-caller-file "^2.0.1" + require-directory "^2.1.1" + require-main-filename "^2.0.0" + set-blocking "^2.0.0" + string-width "^3.0.0" + which-module "^2.0.0" + y18n "^4.0.0" + yargs-parser "^15.0.1" + +yargs@^16.2.0: + version "16.2.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" + integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== + dependencies: + cliui "^7.0.2" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.0" + y18n "^5.0.5" + yargs-parser "^20.2.2" + +yocto-queue@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" + integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== diff --git a/cloudbuild.yaml b/cloudbuild.yaml new file mode 100644 index 0000000..74a47d0 --- /dev/null +++ b/cloudbuild.yaml @@ -0,0 +1,14 @@ +steps: + - name: 'gcr.io/cloud-builders/docker' + entrypoint: 'bash' + args: ['-c', 'docker pull gcr.io/fldemo-315215/test555-30719-dev:latest || exit 0'] + - name: 'gcr.io/cloud-builders/docker' + args: [ + 'build', + '-t', 'gcr.io/fldemo-315215/test555-30719-dev:latest', + '--file', 'Dockerfile.dev', + '--cache-from', 'gcr.io/fldemo-315215/test555-30719-dev:latest', + '.' + ] +images: ['gcr.io/fldemo-315215/test555-30719-dev:latest'] +logsBucket: 'gs://fldemo-315215-cloudbuild-logs' \ No newline at end of file diff --git a/frontend/next-env.d.ts b/frontend/next-env.d.ts index 4f11a03..a4a7b3f 100644 --- a/frontend/next-env.d.ts +++ b/frontend/next-env.d.ts @@ -2,4 +2,4 @@ /// // NOTE: This file should not be edited -// see https://nextjs.org/docs/basic-features/typescript for more information. +// see https://nextjs.org/docs/pages/building-your-application/configuring/typescript for more information. diff --git a/pids/backend.pid b/pids/backend.pid new file mode 100644 index 0000000..b8626c4 --- /dev/null +++ b/pids/backend.pid @@ -0,0 +1 @@ +4 diff --git a/pids/frontend.pid b/pids/frontend.pid new file mode 100644 index 0000000..00750ed --- /dev/null +++ b/pids/frontend.pid @@ -0,0 +1 @@ +3