diff --git a/app/services/minio.js b/app/services/minio.js
new file mode 100644
index 0000000..d5802c7
--- /dev/null
+++ b/app/services/minio.js
@@ -0,0 +1,70 @@
+// minio.js
+// Copyright (C) 2024 DTP Technologies, LLC
+// All Rights Reserved
+
+'use strict';
+
+
+import * as Minio from 'minio';
+
+import { SiteService } from '../../lib/site-lib.js';
+
+export default class MinioService extends SiteService {
+
+ static get name ( ) { return 'MinioService'; }
+ static get slug ( ) { return 'minio'; }
+
+ constructor (dtp) {
+ super(dtp, MinioService);
+ }
+
+ async start ( ) {
+ await super.start();
+
+ this.minio = new Minio.Client({
+ endPoint: process.env.MINIO_ENDPOINT,
+ port: parseInt(process.env.MINIO_PORT, 10),
+ useSSL: (process.env.MINIO_USE_SSL === 'enabled'),
+ accessKey: process.env.MINIO_ACCESS_KEY,
+ secretKey: process.env.MINIO_SECRET_KEY,
+ });
+ }
+
+ async uploadFile (fileInfo) {
+ const result = await this.minio.fPutObject(
+ fileInfo.bucket,
+ fileInfo.key,
+ fileInfo.filePath,
+ fileInfo.metadata
+ );
+ return result;
+ }
+
+ async downloadFile (fileInfo) {
+ const obj = await this.minio.fGetObject(fileInfo.bucket, fileInfo.key, fileInfo.filePath);
+ return obj;
+ }
+
+ async openDownloadStream (fi) {
+ if (fi.range) {
+ const length = fi.range.end - fi.range.start + 1;
+ const stream = await this.minio.getPartialObject(fi.bucket, fi.key, fi.range.start, length);
+ return stream;
+ }
+ const stream = await this.minio.getObject(fi.bucket, fi.key);
+ return stream;
+ }
+
+ async removeObject (bucket, key) {
+ await this.minio.removeObject(bucket, key);
+ }
+
+ async statObject (bucket, key) {
+ const stat = await this.minio.statObject(bucket, key);
+ return stat;
+ }
+
+ async statFile (file) {
+ return await this.statObject(file.bucket, file.key);
+ }
+}
\ No newline at end of file
diff --git a/dtp-chat.js b/dtp-chat.js
index fdbaad0..5899c5d 100644
--- a/dtp-chat.js
+++ b/dtp-chat.js
@@ -21,16 +21,8 @@ import webpackDevMiddleware from 'webpack-dev-middleware';
import WEBPACK_CONFIG from './webpack.config.js';
-import numeral from 'numeral';
-import dayjs from 'dayjs';
-import * as Marked from 'marked';
-import hljs from 'highlight.js';
-
-import mongoose from 'mongoose';
-import { Redis } from 'ioredis';
-
-import { SiteLog } from './lib/site-lib.js';
import { SiteTripwire } from './lib/site-tripwire.js';
+import { SiteRuntime } from './lib/site-runtime.js';
import http from 'node:http';
@@ -40,174 +32,33 @@ import session from 'express-session';
import RedisStore from 'connect-redis';
import passport from 'passport';
-import { Emitter } from '@socket.io/redis-emitter';
-
-const APP_CONFIG = {
- pkg: require('./package.json'),
-};
+class SiteWebApp extends SiteRuntime {
-class Harness {
-
- static get name ( ) { return 'Harness'; }
- static get slug ( ) { return 'harness'; }
+ static get name ( ) { return 'SiteWebApp'; }
+ static get slug ( ) { return 'webApp'; }
constructor ( ) {
- this.config = { root: __dirname };
- this.models = [ ];
-
- this.log = new SiteLog(this, Harness);
+ super(SiteWebApp, __dirname);
}
async start ( ) {
- await this.loadConfig();
+ await super.start();
this.log.info('loading SiteTripwire (known-malicious request protection)');
this.tripwire = new SiteTripwire(this);
await this.tripwire.start();
- await this.connectMongoDB();
- await this.connectRedis();
-
- await this.loadModels();
- await this.loadServices();
await this.startExpressJS();
}
- async loadConfig ( ) {
- this.config.site = (await import('./config/site.js')).default;
- this.config.limiter = (await import('./config/limiter.js')).default;
- this.config.jobQueues = (await import('./config/job-queues.js')).default;
- }
-
- async connectMongoDB ( ) {
- try {
- this.log.info('starting MongoDB');
-
- /*
- * For some time, strictQuery=true was the Mongoose default. It's being
- * changed. The option has to be set manually now.
- */
- mongoose.set('strictQuery', true);
-
- this.log.info('connecting to MongoDB database', {
- pid: process.pid,
- host: process.env.MONGODB_HOST,
- database: process.env.MONGODB_DATABASE,
- });
- const mongoConnectUri = `mongodb://${process.env.DTP_MONGODB_HOST}/${process.env.DTP_MONGODB_DATABASE}`;
- await mongoose.connect(mongoConnectUri, {
- socketTimeoutMS: 0,
- dbName: process.env.MONGODB_DATABASE,
- });
- this.db = mongoose.connection;
- this.log.info('connected to MongoDB');
- } catch (error) {
- this.log.error('failed to connect to database', { error });
- throw error;
- }
- }
-
- async loadModels ( ) {
- const basePath = path.join(this.config.root, 'app', 'models');
- const entries = await fs.promises.readdir(basePath, { withFileTypes: true });
-
- this.log.info('loading models', { count: entries.length });
- for (const entry of entries) {
- if (!entry.isFile()) {
- continue;
- }
- const filename = path.join(basePath, entry.name);
- const model = (await import(filename)).default;
- if (this.models[model.modelName]) {
- this.log.error('model name collision', { name: model.modelName });
- process.exit(-1);
- }
- this.models.push(model);
- this.log.info('model loaded', { name: model.modelName});
- }
- }
-
- async resetIndexes (target) {
- if (target === 'all') {
- for (const model of this.models) {
- await this.resetIndex(model);
- }
- return;
- }
-
- const model = this.models.find((model) => model.modelName === target);
- if (!model) {
- throw new Error(`requested Mongoose model does not exist: ${target}`);
- }
-
- return this.resetIndex(model);
- }
-
- async resetIndex (model) {
- return new Promise(async (resolve, reject) => {
- this.log.info('dropping model indexes', { model: model.modelName });
- model.collection.dropIndexes((err) => {
- if (err) {
- return reject(err);
- }
- this.log.info('creating model indexes', { model: model.modelName });
- model.ensureIndexes((err) => {
- if (err) {
- return reject(err);
- }
- return resolve(model);
- });
- });
- });
- }
-
- async connectRedis ( ) {
- try {
- const options = {
- host: process.env.DTP_REDIS_HOST,
- port: parseInt(process.env.DTP_REDIS_PORT || '6379', 10),
- password: process.env.DTP_REDIS_PASSWORD,
- keyPrefix: process.env.DTP_REDIS_KEY_PREFIX,
- lazyConnect: false,
- };
- this.log.info('connecting to Redis', {
- host: options.host,
- port: options.port,
- prefix: options.keyPrefix || 'dtp',
- });
-
- this.redis = new Redis(options);
- this.redis.setMaxListeners(64); // prevents warnings/errors with Bull Queue
-
- this.log.info('creating Socket.io Emitter');
- this.emitter = new Emitter(this.redis);
-
- this.log.info('Redis connected');
- } catch (error) {
- this.log.error('failed to connect to Redis', error);
- throw new Error('failed to connect to Redis', { cause: error });
- }
- }
-
- async getRedisKeys (pattern) {
- return new Promise((resolve, reject) => {
- return this.redis.keys(pattern, (err, response) => {
- if (err) {
- return reject(err);
- }
- return resolve(response);
- });
- });
- }
-
async startExpressJS ( ) {
const { session: sessionService } = this.services;
this.app = express();
- this.app.locals.config = APP_CONFIG;
- this.app.locals.pkg = APP_CONFIG.pkg; // convenience
- this.app.locals.site = (await import(path.join(this.config.root, 'config', 'site.js'))).default;
+ this.app.locals.config = this.config;
+ this.app.locals.pkg = this.config.pkg;
+ this.app.locals.site = this.config.site;
this.app.set('view engine', 'pug');
this.app.set('views', path.join(__dirname, 'app', 'views'));
@@ -367,46 +218,12 @@ class Harness {
this.log.error('failed to start application services', { err });
return reject(new Error('failed to start application services', { cause: err }));
}
- this.log.info(`${APP_CONFIG.pkg.name} application services online.`);
+ this.log.info(`${this.config.pkg.name} application services online.`);
return resolve();
});
});
}
- async loadServices ( ) {
- const basePath = path.join(this.config.root, 'app', 'services');
- const entries = await fs.promises.readdir(basePath, { withFileTypes: true });
- const inits = [ ];
-
- this.services = { };
-
- for await (const entry of entries) {
- if (!entry.isFile()) {
- continue;
- }
- try {
- const ServiceClass = (await import(path.join(basePath, entry.name))).default;
- this.log.info('loading service', {
- script: entry.name,
- name: ServiceClass.name,
- slug: ServiceClass.slug,
- });
-
- const service = new ServiceClass(this);
-
- this.services[ServiceClass.slug] = service;
- inits.push(service);
- } catch (error) {
- this.log.error('failed to load service', { error });
- throw new Error('failed to load service', { cause: error });
- }
- }
-
- for await (const service of inits) {
- await service.start();
- }
- }
-
async loadControllers ( ) {
const basePath = path.join(this.config.root, 'app', 'controllers');
const entries = await fs.promises.readdir(basePath, { withFileTypes: true });
@@ -451,67 +268,13 @@ class Harness {
*/
await this.controllers.home.start();
}
-
- async populateViewModel (viewModel) {
- viewModel.DTP_SCRIPT_DEBUG = (process.env.NODE_ENV !== 'production');
- viewModel.dtp = this;
-
- const pkg = await import(path.join(this.config.root, 'package.json'), { assert: { type: 'json' } }); // jshint ignore:line
- viewModel.pkg = pkg.default; // jshint ignore:line
- viewModel.dayjs = dayjs;
- viewModel.numeral = numeral;
- // viewModel.phoneNumberJS = require('libphonenumber-js');
- // viewModel.anchorme = require('anchorme').default;
- // viewModel.hljs = hljs;
- // viewModel.Color = require('color');
- // viewModel.numberToWords = require('number-to-words');
- viewModel.uuidv4 = (await import('uuid')).v4;
-
- /*
- * Set up the protected markdown renderer that will refuse to process links and images
- * for security reasons.
- */
-
- function safeImageRenderer (href, title, text) { return text; }
- function safeLinkRenderer (href, title, text) { return text; }
-
- function confirmedLinkRenderer (href, title, text) {
- return `${text}`;
- }
-
- viewModel.fullMarkedRenderer = new Marked.Renderer();
- viewModel.fullMarkedRenderer.image = safeImageRenderer;
- viewModel.fullMarkedRenderer.link = confirmedLinkRenderer;
-
- viewModel.safeMarkedRenderer = new Marked.Renderer();
- viewModel.safeMarkedRenderer.image = safeImageRenderer;
- viewModel.safeMarkedRenderer.link = safeLinkRenderer;
-
- viewModel.markedConfigChat = {
- renderer: this.safeMarkedRenderer,
- highlight: function(code, lang) {
- const language = hljs.getLanguage(lang) ? lang : 'plaintext';
- return hljs.highlight(code, { language }).value;
- },
- langPrefix: 'hljs language-',
- pedantic: false,
- gfm: true,
- breaks: true,
- sanitize: false,
- smartLists: true,
- smartypants: false,
- xhtml: false,
- };
- Marked.setOptions(viewModel.markedConfigChat);
- viewModel.marked = Marked;
- }
}
(async ( ) => {
try {
- const harness = new Harness();
- await harness.start();
+ const app = new SiteWebApp();
+ await app.start();
} catch (error) {
console.error('failed to start application harness', error);
}
diff --git a/lib/site-runtime.js b/lib/site-runtime.js
new file mode 100644
index 0000000..b599cfe
--- /dev/null
+++ b/lib/site-runtime.js
@@ -0,0 +1,270 @@
+// site-runtime.js
+// Copyright (C) 2024 DTP Technologies, LLC
+// All Rights Reserved
+
+'use strict';
+
+import 'dotenv/config';
+
+import path, { dirname } from 'path';
+import fs from 'fs';
+import { fileURLToPath } from 'url';
+const __dirname = dirname(fileURLToPath(import.meta.url)); // jshint ignore:line
+
+import { createRequire } from 'module';
+const require = createRequire(import.meta.url); // jshint ignore:line
+
+import numeral from 'numeral';
+import dayjs from 'dayjs';
+import * as Marked from 'marked';
+import hljs from 'highlight.js';
+
+import mongoose from 'mongoose';
+import { Redis } from 'ioredis';
+
+import { SiteLog } from './site-lib.js';
+import { SiteTripwire } from './site-tripwire.js';
+
+import { Emitter } from '@socket.io/redis-emitter';
+
+export class SiteRuntime {
+
+ static get name ( ) { return 'SiteRuntime'; }
+ static get slug ( ) { return 'runtime'; }
+
+ constructor (RuntimeClass, rootDir) {
+ this.config = { root: rootDir };
+ this.models = [ ];
+ this.log = new SiteLog(this, RuntimeClass);
+ }
+
+ async start ( ) {
+ await this.loadConfig();
+
+ this.log.info('loading SiteTripwire (known-malicious request protection)');
+ this.tripwire = new SiteTripwire(this);
+ await this.tripwire.start();
+
+ await this.connectMongoDB();
+ await this.connectRedis();
+
+ await this.loadModels();
+ await this.loadServices();
+ }
+
+ async loadConfig ( ) {
+ this.config.pkg = require(path.join(this.config.root, 'package.json'));
+ this.config.site = (await import(path.join(this.config.root, 'config', 'site.js'))).default;
+ this.config.limiter = (await import(path.join(this.config.root, 'config', 'limiter.js'))).default;
+ this.config.jobQueues = (await import(path.join(this.config.root, 'config', 'job-queues.js'))).default;
+ }
+
+ async connectMongoDB ( ) {
+ try {
+ this.log.info('starting MongoDB');
+
+ /*
+ * For some time, strictQuery=true was the Mongoose default. It's being
+ * changed. The option has to be set manually now.
+ */
+ mongoose.set('strictQuery', true);
+
+ this.log.info('connecting to MongoDB database', {
+ pid: process.pid,
+ host: process.env.MONGODB_HOST,
+ database: process.env.MONGODB_DATABASE,
+ });
+ const mongoConnectUri = `mongodb://${process.env.DTP_MONGODB_HOST}/${process.env.DTP_MONGODB_DATABASE}`;
+ await mongoose.connect(mongoConnectUri, {
+ socketTimeoutMS: 0,
+ dbName: process.env.MONGODB_DATABASE,
+ });
+ this.db = mongoose.connection;
+ this.log.info('connected to MongoDB');
+ } catch (error) {
+ this.log.error('failed to connect to database', { error });
+ throw error;
+ }
+ }
+
+ async loadModels ( ) {
+ const basePath = path.join(this.config.root, 'app', 'models');
+ const entries = await fs.promises.readdir(basePath, { withFileTypes: true });
+
+ this.log.info('loading models', { count: entries.length });
+ for (const entry of entries) {
+ if (!entry.isFile()) {
+ continue;
+ }
+ const filename = path.join(basePath, entry.name);
+ const model = (await import(filename)).default;
+ if (this.models[model.modelName]) {
+ this.log.error('model name collision', { name: model.modelName });
+ process.exit(-1);
+ }
+ this.models.push(model);
+ this.log.info('model loaded', { name: model.modelName});
+ }
+ }
+
+ async resetIndexes (target) {
+ if (target === 'all') {
+ for (const model of this.models) {
+ await this.resetIndex(model);
+ }
+ return;
+ }
+
+ const model = this.models.find((model) => model.modelName === target);
+ if (!model) {
+ throw new Error(`requested Mongoose model does not exist: ${target}`);
+ }
+
+ return this.resetIndex(model);
+ }
+
+ async resetIndex (model) {
+ return new Promise(async (resolve, reject) => {
+ this.log.info('dropping model indexes', { model: model.modelName });
+ model.collection.dropIndexes((err) => {
+ if (err) {
+ return reject(err);
+ }
+ this.log.info('creating model indexes', { model: model.modelName });
+ model.ensureIndexes((err) => {
+ if (err) {
+ return reject(err);
+ }
+ return resolve(model);
+ });
+ });
+ });
+ }
+
+ async connectRedis ( ) {
+ try {
+ const options = {
+ host: process.env.DTP_REDIS_HOST,
+ port: parseInt(process.env.DTP_REDIS_PORT || '6379', 10),
+ password: process.env.DTP_REDIS_PASSWORD,
+ keyPrefix: process.env.DTP_REDIS_KEY_PREFIX,
+ lazyConnect: false,
+ };
+ this.log.info('connecting to Redis', {
+ host: options.host,
+ port: options.port,
+ prefix: options.keyPrefix || 'dtp',
+ });
+
+ this.redis = new Redis(options);
+ this.redis.setMaxListeners(64); // prevents warnings/errors with Bull Queue
+
+ this.log.info('creating Socket.io Emitter');
+ this.emitter = new Emitter(this.redis);
+
+ this.log.info('Redis connected');
+ } catch (error) {
+ this.log.error('failed to connect to Redis', error);
+ throw new Error('failed to connect to Redis', { cause: error });
+ }
+ }
+
+ async getRedisKeys (pattern) {
+ return new Promise((resolve, reject) => {
+ return this.redis.keys(pattern, (err, response) => {
+ if (err) {
+ return reject(err);
+ }
+ return resolve(response);
+ });
+ });
+ }
+
+ async loadServices ( ) {
+ const basePath = path.join(this.config.root, 'app', 'services');
+ const entries = await fs.promises.readdir(basePath, { withFileTypes: true });
+ const inits = [ ];
+
+ this.services = { };
+
+ for await (const entry of entries) {
+ if (!entry.isFile()) {
+ continue;
+ }
+ try {
+ const ServiceClass = (await import(path.join(basePath, entry.name))).default;
+ this.log.info('loading service', {
+ script: entry.name,
+ name: ServiceClass.name,
+ slug: ServiceClass.slug,
+ });
+
+ const service = new ServiceClass(this);
+
+ this.services[ServiceClass.slug] = service;
+ inits.push(service);
+ } catch (error) {
+ this.log.error('failed to load service', { error });
+ throw new Error('failed to load service', { cause: error });
+ }
+ }
+
+ for await (const service of inits) {
+ await service.start();
+ }
+ }
+
+ async populateViewModel (viewModel) {
+ viewModel.DTP_SCRIPT_DEBUG = (process.env.NODE_ENV !== 'production');
+ viewModel.dtp = this;
+
+ const pkg = await import(path.join(this.config.root, 'package.json'), { assert: { type: 'json' } }); // jshint ignore:line
+ viewModel.pkg = pkg.default; // jshint ignore:line
+ viewModel.dayjs = dayjs;
+ viewModel.numeral = numeral;
+ // viewModel.phoneNumberJS = require('libphonenumber-js');
+ // viewModel.anchorme = require('anchorme').default;
+ // viewModel.hljs = hljs;
+ // viewModel.Color = require('color');
+ // viewModel.numberToWords = require('number-to-words');
+ viewModel.uuidv4 = (await import('uuid')).v4;
+
+ /*
+ * Set up the protected markdown renderer that will refuse to process links and images
+ * for security reasons.
+ */
+
+ function safeImageRenderer (href, title, text) { return text; }
+ function safeLinkRenderer (href, title, text) { return text; }
+
+ function confirmedLinkRenderer (href, title, text) {
+ return `${text}`;
+ }
+
+ viewModel.fullMarkedRenderer = new Marked.Renderer();
+ viewModel.fullMarkedRenderer.image = safeImageRenderer;
+ viewModel.fullMarkedRenderer.link = confirmedLinkRenderer;
+
+ viewModel.safeMarkedRenderer = new Marked.Renderer();
+ viewModel.safeMarkedRenderer.image = safeImageRenderer;
+ viewModel.safeMarkedRenderer.link = safeLinkRenderer;
+
+ viewModel.markedConfigChat = {
+ renderer: this.safeMarkedRenderer,
+ highlight: function(code, lang) {
+ const language = hljs.getLanguage(lang) ? lang : 'plaintext';
+ return hljs.highlight(code, { language }).value;
+ },
+ langPrefix: 'hljs language-',
+ pedantic: false,
+ gfm: true,
+ breaks: true,
+ sanitize: false,
+ smartLists: true,
+ smartypants: false,
+ xhtml: false,
+ };
+ Marked.setOptions(viewModel.markedConfigChat);
+ viewModel.marked = Marked;
+ }
+}
\ No newline at end of file
diff --git a/package.json b/package.json
index ea696c5..dc69927 100644
--- a/package.json
+++ b/package.json
@@ -39,6 +39,7 @@
"ioredis": "^5.3.2",
"marked": "^12.0.1",
"mediasoup": "^3.13.24",
+ "minio": "^7.1.3",
"mongoose": "^8.3.1",
"morgan": "^1.10.0",
"multer": "^1.4.5-lts.1",
diff --git a/start-local b/start-local
new file mode 100755
index 0000000..6479dc3
--- /dev/null
+++ b/start-local
@@ -0,0 +1,11 @@
+#!/bin/bash
+
+#MINIO_REGION_NAME="us-east-local"
+#MINIO_REGION_COMMENT=""
+#export MINIO_REGION_NAME MINIO_REGION_COMMENT
+
+MINIO_ROOT_USER="dtp-chat"
+MINIO_ROOT_PASSWORD="dd039ca4-1bab-4a6c-809b-0bbb43c46def"
+export MINIO_ROOT_USER MINIO_ROOT_PASSWORD
+
+minio server ./data/minio --address ":9080" --console-address ":9081"
\ No newline at end of file
diff --git a/yarn.lock b/yarn.lock
index c71ffb0..78497b7 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1400,6 +1400,11 @@
resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d"
integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==
+"@zxing/text-encoding@0.9.0":
+ version "0.9.0"
+ resolved "https://registry.yarnpkg.com/@zxing/text-encoding/-/text-encoding-0.9.0.tgz#fb50ffabc6c7c66a0c96b4c03e3d9be74864b70b"
+ integrity sha512-U/4aVJ2mxI0aDNI8Uq0wEhMgY+u4CNtEb0om3+y3+niDAsoTCOB33UF0sxpzqzdqXLqmvc+vZyAt4O8pPdfkwA==
+
abbrev@1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8"
@@ -1587,7 +1592,7 @@ async@^2.6.0:
dependencies:
lodash "^4.17.14"
-async@^3.2.3:
+async@^3.2.3, async@^3.2.4:
version "3.2.5"
resolved "https://registry.yarnpkg.com/async/-/async-3.2.5.tgz#ebd52a8fdaf7a2289a24df399f8d8485c8a46b66"
integrity sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==
@@ -1662,6 +1667,13 @@ binary-extensions@^2.0.0:
resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.3.0.tgz#f6e14a97858d327252200242d4ccfe522c445522"
integrity sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==
+block-stream2@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/block-stream2/-/block-stream2-2.1.0.tgz#ac0c5ef4298b3857796e05be8ebed72196fa054b"
+ integrity sha512-suhjmLI57Ewpmq00qaygS8UgEq2ly2PCItenIyhMqVjo4t4pGzqMvfgJuX8iWTeSDdfSSqS6j38fL4ToNL7Pfg==
+ dependencies:
+ readable-stream "^3.4.0"
+
body-parser@1.20.2:
version "1.20.2"
resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.2.tgz#6feb0e21c4724d06de7ff38da36dad4f57a747fd"
@@ -1702,6 +1714,11 @@ braces@^3.0.2, braces@~3.0.2:
dependencies:
fill-range "^7.0.1"
+browser-or-node@^2.1.1:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/browser-or-node/-/browser-or-node-2.1.1.tgz#738790b3a86a8fc020193fa581273fbe65eaea0f"
+ integrity sha512-8CVjaLJGuSKMVTxJ2DpBl5XnlNDiT4cQFeuCJJrvJmts9YrTZDizTX7PjC2s6W4x+MBGZeEY6dGMrF04/6Hgqg==
+
browser-sync-client@^3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/browser-sync-client/-/browser-sync-client-3.0.2.tgz#6fbe9a7aada25cf14c824683e089ec9ace91cfe1"
@@ -1785,6 +1802,11 @@ bson@^6.4.0, bson@^6.5.0:
resolved "https://registry.yarnpkg.com/bson/-/bson-6.6.0.tgz#f225137eb49fe19bee4d87949a0515c05176e2ad"
integrity sha512-BVINv2SgcMjL4oYbBuCQTpE3/VKOSxrOA8Cj/wQP7izSzlBGVomdm+TcUd0Pzy0ytLSSDweCKQ6X3f5veM5LQA==
+buffer-crc32@^0.2.13:
+ version "0.2.13"
+ resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242"
+ integrity sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==
+
buffer-from@^1.0.0:
version "1.1.2"
resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5"
@@ -2255,6 +2277,11 @@ decamelize@^1.2.0:
resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
integrity sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==
+decode-uri-component@^0.2.2:
+ version "0.2.2"
+ resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.2.tgz#e69dbe25d37941171dd540e024c444cd5188e1e9"
+ integrity sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==
+
deepmerge@^4.2.2:
version "4.3.1"
resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.3.1.tgz#44b5f2147cd3b00d4b56137685966f26fd25dd4a"
@@ -2748,6 +2775,13 @@ fast-json-stable-stringify@^2.0.0, fast-json-stable-stringify@^2.1.0:
resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633"
integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==
+fast-xml-parser@^4.2.2:
+ version "4.3.6"
+ resolved "https://registry.yarnpkg.com/fast-xml-parser/-/fast-xml-parser-4.3.6.tgz#190f9d99097f0c8f2d3a0e681a10404afca052ff"
+ integrity sha512-M2SovcRxD4+vC493Uc2GZVcZaj66CCJhWurC4viynVSTvrpErCShNcDz1lAho6n9REQKvL/ll4A4/fw6Y9z8nw==
+ dependencies:
+ strnum "^1.0.5"
+
fastest-levenshtein@^1.0.12:
version "1.0.16"
resolved "https://registry.yarnpkg.com/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz#210e61b6ff181de91ea9b3d1b84fdedd47e034e5"
@@ -2775,6 +2809,11 @@ fill-range@^7.0.1:
dependencies:
to-regex-range "^5.0.1"
+filter-obj@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/filter-obj/-/filter-obj-1.1.0.tgz#9b311112bc6c6127a16e016c6c5d7f19e0805c5b"
+ integrity sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ==
+
finalhandler@1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.0.tgz#ce0b6855b45853e791b2fcc680046d88253dd7f5"
@@ -3196,6 +3235,19 @@ ipaddr.js@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==
+ipaddr.js@^2.0.1:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-2.1.0.tgz#2119bc447ff8c257753b196fc5f1ce08a4cdf39f"
+ integrity sha512-LlbxQ7xKzfBusov6UMi4MFpEg0m+mAm9xyNGEduwXMEDuf4WfzB/RZwMVYEd7IKGvh4IUkEXYxtAVu9T3OelJQ==
+
+is-arguments@^1.0.4:
+ 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"
@@ -3277,6 +3329,13 @@ is-fullwidth-code-point@^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-generator-function@^1.0.7:
+ version "1.0.10"
+ resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.0.10.tgz#f1558baf1ac17e0deea7c0415c438351ff2b3c72"
+ integrity sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==
+ dependencies:
+ has-tostringtag "^1.0.0"
+
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"
@@ -3369,7 +3428,7 @@ is-symbol@^1.0.2, is-symbol@^1.0.3:
dependencies:
has-symbols "^1.0.2"
-is-typed-array@^1.1.13:
+is-typed-array@^1.1.13, is-typed-array@^1.1.3:
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==
@@ -3504,6 +3563,11 @@ json-schema@^0.4.0:
resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.4.0.tgz#f7de4cf6efab838ebaeb3236474cbba5a1930ab5"
integrity sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==
+json-stream@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/json-stream/-/json-stream-1.0.0.tgz#1a3854e28d2bbeeab31cc7ddf683d2ddc5652708"
+ integrity sha512-H/ZGY0nIAg3QcOwE1QN/rK/Fa7gJn7Ii5obwp6zyPO4xiPNwpIMjqy2gwjBEGqzkF/vSWEIBQCBuN19hYiL6Qg==
+
json5@^2.2.0, json5@^2.2.3:
version "2.2.3"
resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283"
@@ -3738,7 +3802,7 @@ mime-db@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.27, mime-types@^2.1.31, mime-types@~2.1.17, mime-types@~2.1.24, mime-types@~2.1.34:
+mime-types@^2.1.27, mime-types@^2.1.31, mime-types@^2.1.35, mime-types@~2.1.17, 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==
@@ -3789,6 +3853,26 @@ minimist@^1.2.6:
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c"
integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==
+minio@^7.1.3:
+ version "7.1.3"
+ resolved "https://registry.yarnpkg.com/minio/-/minio-7.1.3.tgz#86dc95f3671045d6956920db757bb63f25bf20ee"
+ integrity sha512-xPrLjWkTT5E7H7VnzOjF//xBp9I40jYB4aWhb2xTFopXXfw+Wo82DDWngdUju7Doy3Wk7R8C4LAgwhLHHnf0wA==
+ dependencies:
+ async "^3.2.4"
+ block-stream2 "^2.1.0"
+ browser-or-node "^2.1.1"
+ buffer-crc32 "^0.2.13"
+ fast-xml-parser "^4.2.2"
+ ipaddr.js "^2.0.1"
+ json-stream "^1.0.0"
+ lodash "^4.17.21"
+ mime-types "^2.1.35"
+ query-string "^7.1.3"
+ through2 "^4.0.2"
+ web-encoding "^1.1.5"
+ xml "^1.0.1"
+ xml2js "^0.5.0"
+
minipass@^3.0.0:
version "3.3.6"
resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.3.6.tgz#7bba384db3a1520d18c9c0e5251c3444e95dd94a"
@@ -4445,6 +4529,16 @@ qs@6.11.0:
dependencies:
side-channel "^1.0.4"
+query-string@^7.1.3:
+ version "7.1.3"
+ resolved "https://registry.yarnpkg.com/query-string/-/query-string-7.1.3.tgz#a1cf90e994abb113a325804a972d98276fe02328"
+ integrity sha512-hh2WYhq4fi8+b+/2Kg9CEge4fDPvHS534aOOvOZeQ3+Vf2mCFsaFBYj0i+iXcAq6I9Vzp5fjMFBlONvayDC1qg==
+ dependencies:
+ decode-uri-component "^0.2.2"
+ filter-obj "^1.1.0"
+ split-on-first "^1.0.0"
+ strict-uri-encode "^2.0.0"
+
randexp@^0.5.3:
version "0.5.3"
resolved "https://registry.yarnpkg.com/randexp/-/randexp-0.5.3.tgz#f31c2de3148b30bdeb84b7c3f59b0ebb9fec3738"
@@ -4495,6 +4589,15 @@ readable-stream@1.1:
isarray "0.0.1"
string_decoder "~0.10.x"
+readable-stream@3, readable-stream@^3.4.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"
+
readable-stream@^2.0.1, readable-stream@^2.2.2, readable-stream@^2.3.5:
version "2.3.8"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b"
@@ -4693,7 +4796,7 @@ safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1:
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
-safe-buffer@5.2.1, safe-buffer@^5.1.0:
+safe-buffer@5.2.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==
@@ -4712,7 +4815,7 @@ safe-regex-test@^1.0.3:
resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
-sax@^1.2.4:
+sax@>=0.6.0, sax@^1.2.4:
version "1.3.0"
resolved "https://registry.yarnpkg.com/sax/-/sax-1.3.0.tgz#a5dbe77db3be05c9d1ee7785dbd3ea9de51593d0"
integrity sha512-0s+oAmw9zLl1V1cS9BtZN7JAd0cW5e0QH4W3LWEK6a4LaLEA2OTpGYWDY+6XasBLtz6wkm3u1xRw95mRuJ59WA==
@@ -5014,6 +5117,11 @@ sparse-bitfield@^3.0.3:
dependencies:
memory-pager "^1.0.2"
+split-on-first@^1.0.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/split-on-first/-/split-on-first-1.1.0.tgz#f610afeee3b12bce1d0c30425e76398b78249a5f"
+ integrity sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==
+
standard-as-callback@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/standard-as-callback/-/standard-as-callback-2.1.0.tgz#8953fc05359868a77b5b9739a665c5977bb7df45"
@@ -5059,6 +5167,11 @@ streamsearch@^1.1.0:
resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-1.1.0.tgz#404dd1e2247ca94af554e841a8ef0eaa238da764"
integrity sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==
+strict-uri-encode@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz#b9c7330c7042862f6b142dc274bbcc5866ce3546"
+ integrity sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ==
+
string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
name string-width-cjs
version "4.2.3"
@@ -5115,6 +5228,13 @@ string.prototype.trimstart@^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"
@@ -5159,6 +5279,11 @@ striptags@^3.2.0:
resolved "https://registry.yarnpkg.com/striptags/-/striptags-3.2.0.tgz#cc74a137db2de8b0b9a370006334161f7dd67052"
integrity sha512-g45ZOGzHDMe2bdYMdIvdAfCQkCTDMGBazSw1ypMowwGIee7ZQ5dU0rBJ8Jqgl+jAKIv4dbeE1jscZq9wid1Tkw==
+strnum@^1.0.5:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/strnum/-/strnum-1.0.5.tgz#5c4e829fe15ad4ff0d20c3db5ac97b73c9b072db"
+ integrity sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==
+
style-loader@^3.3.4:
version "3.3.4"
resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-3.3.4.tgz#f30f786c36db03a45cbd55b6a70d930c479090e7"
@@ -5260,6 +5385,13 @@ thirty-two@^1.0.2:
resolved "https://registry.yarnpkg.com/thirty-two/-/thirty-two-1.0.2.tgz#4ca2fffc02a51290d2744b9e3f557693ca6b627a"
integrity sha512-OEI0IWCe+Dw46019YLl6V10Us5bi574EvlJEOcAkB29IzQ/mYD1A6RyNHLjZPiHCmuodxvgF6U+vZO1L15lxVA==
+through2@^4.0.2:
+ version "4.0.2"
+ resolved "https://registry.yarnpkg.com/through2/-/through2-4.0.2.tgz#a7ce3ac2a7a8b0b966c80e7c49f0484c3b239764"
+ integrity sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==
+ dependencies:
+ readable-stream "3"
+
through@^2.3.8:
version "2.3.8"
resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
@@ -5499,11 +5631,22 @@ uri-js@^4.2.2:
dependencies:
punycode "^2.1.0"
-util-deprecate@^1.0.2, util-deprecate@~1.0.1:
+util-deprecate@^1.0.1, util-deprecate@^1.0.2, 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==
+util@^0.12.3:
+ version "0.12.5"
+ resolved "https://registry.yarnpkg.com/util/-/util-0.12.5.tgz#5f17a6059b73db61a875668781a1c2b136bd6fbc"
+ integrity sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==
+ dependencies:
+ inherits "^2.0.3"
+ is-arguments "^1.0.4"
+ is-generator-function "^1.0.7"
+ is-typed-array "^1.1.3"
+ which-typed-array "^1.1.2"
+
utils-merge@1.0.1, utils-merge@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713"
@@ -5549,6 +5692,15 @@ watchpack@^2.4.1:
glob-to-regexp "^0.4.1"
graceful-fs "^4.1.2"
+web-encoding@^1.1.5:
+ version "1.1.5"
+ resolved "https://registry.yarnpkg.com/web-encoding/-/web-encoding-1.1.5.tgz#fc810cf7667364a6335c939913f5051d3e0c4864"
+ integrity sha512-HYLeVCdJ0+lBYV2FvNZmv3HJ2Nt0QYXqZojk3d9FJOLkwnuhzM9tmamh8d7HPM8QqjKH8DeHkFTx+CFlWpZZDA==
+ dependencies:
+ util "^0.12.3"
+ optionalDependencies:
+ "@zxing/text-encoding" "0.9.0"
+
web-streams-polyfill@^3.0.3:
version "3.3.3"
resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz#2073b91a2fdb1fbfbd401e7de0ac9f8214cecb4b"
@@ -5694,7 +5846,7 @@ which-module@^2.0.0:
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:
+which-typed-array@^1.1.14, which-typed-array@^1.1.15, which-typed-array@^1.1.2:
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==
@@ -5925,6 +6077,24 @@ ws@~8.11.0:
resolved "https://registry.yarnpkg.com/ws/-/ws-8.11.0.tgz#6a0d36b8edfd9f96d8b25683db2f8d7de6e8e143"
integrity sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==
+xml2js@^0.5.0:
+ version "0.5.0"
+ resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.5.0.tgz#d9440631fbb2ed800203fad106f2724f62c493b7"
+ integrity sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==
+ dependencies:
+ sax ">=0.6.0"
+ xmlbuilder "~11.0.0"
+
+xml@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/xml/-/xml-1.0.1.tgz#78ba72020029c5bc87b8a81a3cfcd74b4a2fc1e5"
+ integrity sha512-huCv9IH9Tcf95zuYCsQraZtWnJvBtLVE0QHMOs8bWyZAFZNDcYjsPq1nEx8jKA9y+Beo9v+7OBPRisQTjinQMw==
+
+xmlbuilder@~11.0.0:
+ version "11.0.1"
+ resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-11.0.1.tgz#be9bae1c8a046e76b31127726347d0ad7002beb3"
+ integrity sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==
+
xmlhttprequest-ssl@~2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.0.0.tgz#91360c86b914e67f44dce769180027c0da618c67"