logging and some cleanup, and mocking database for tests

This commit is contained in:
sneakers-the-rat 2023-08-01 17:15:11 -07:00
parent 3671cbd7ae
commit b377997617
15 changed files with 313 additions and 164 deletions

View file

@ -1,6 +1,7 @@
PORT=8999 PORT=8999
NODE_ENV=development NODE_ENV=development
NODE_CONFIG_DIR = ./server/config NODE_CONFIG_DIR = ./server/config
LOG_DIR=/var/log/chatbridge
POSTGRES_HOST=127.0.0.1 POSTGRES_HOST=127.0.0.1
POSTGRES_PORT=6500 POSTGRES_PORT=6500
@ -13,8 +14,13 @@ SLACK_CLIENT_SECRET=
SLACK_SIGNING_SECRET= SLACK_SIGNING_SECRET=
SLACK_STATE_SECRET= SLACK_STATE_SECRET=
# Used to log in to create and manage groups
ADMIN_TOKEN= ADMIN_TOKEN=
# Keys used to sign cookies used for authentication
COOKIE_KEY_1=
COOKIE_KEY_2=
# Location of the matterbridge binary! # Location of the matterbridge binary!
MATTERBRIDGE_BINARY= MATTERBRIDGE_BINARY=
MATTERBRIDGE_CONFIG_DIR= MATTERBRIDGE_CONFIG_DIR=

View file

@ -21,5 +21,6 @@ export default {
matterbridge: { matterbridge: {
bin: 'MATTERBRIDGE_BINARY', bin: 'MATTERBRIDGE_BINARY',
config: 'MATTERBRIDGE_CONFIG_DIR' config: 'MATTERBRIDGE_CONFIG_DIR'
} },
logDir: 'LOG_DIR'
} }

View file

@ -1,3 +1,4 @@
export default { export default {
port: '8999', port: '8999',
logDir: '/var/chatbridge'
} }

View file

@ -8,7 +8,7 @@
"license": "AGPL-3.0", "license": "AGPL-3.0",
"private": true, "private": true,
"scripts": { "scripts": {
"start": "ts-node-dev --respawn --transpile-only --exit-child src/app.ts", "start": "NODE_ENV=development ts-node-dev --respawn --transpile-only --exit-child src/app.ts",
"build": "../node_modules/.bin/tsc -p .", "build": "../node_modules/.bin/tsc -p .",
"typeorm": "../node_modules/.bin/typeorm-ts-node-commonjs", "typeorm": "../node_modules/.bin/typeorm-ts-node-commonjs",
"migrate": "rm -rf build && yarn build && yarn ../node_modules/.bin/typeorm migration:generate ./src/migrations/added-user-entity -d ./src/utils/data-source.ts", "migrate": "rm -rf build && yarn build && yarn ../node_modules/.bin/typeorm migration:generate ./src/migrations/added-user-entity -d ./src/utils/data-source.ts",
@ -35,6 +35,7 @@
"slugify": "^1.6.6", "slugify": "^1.6.6",
"typeorm": "^0.3.17", "typeorm": "^0.3.17",
"typescript": "^5.1.6", "typescript": "^5.1.6",
"winston": "^3.10.0",
"zod": "^3.21.4" "zod": "^3.21.4"
}, },
"devDependencies": { "devDependencies": {
@ -47,6 +48,7 @@
"@types/jsonwebtoken": "^9.0.2", "@types/jsonwebtoken": "^9.0.2",
"@types/node": "^20.4.2", "@types/node": "^20.4.2",
"@types/pug": "^2.0.6", "@types/pug": "^2.0.6",
"@types/winston": "^2.4.4",
"jest": "^29.6.1", "jest": "^29.6.1",
"ts-jest": "^29.1.1", "ts-jest": "^29.1.1",
"ts-node": "^10.9.1", "ts-node": "^10.9.1",

View file

@ -4,7 +4,7 @@ import config from 'config';
import cors from 'cors'; import cors from 'cors';
import { AppDataSource } from './db/data-source'; import { AppDataSource } from './db/data-source';
import AppError from './errors/appError'; import AppError from './errors/appError';
import {killMatterbridge} from "./matterbridge/process";
import MatterbridgeManager from "./matterbridge/process"; import MatterbridgeManager from "./matterbridge/process";
import {cookieMiddleware} from "./middleware/cookies"; import {cookieMiddleware} from "./middleware/cookies";
@ -14,6 +14,9 @@ import authRoutes from "./routes/auth.routes";
import bridgeRoutes from './routes/bridge.routes'; import bridgeRoutes from './routes/bridge.routes';
import channelRoutes from './routes/channel.routes'; import channelRoutes from './routes/channel.routes';
import logger from "./logging";
AppDataSource.initialize() AppDataSource.initialize()
@ -32,13 +35,7 @@ AppDataSource.initialize()
}) })
app.use('/groups', groupRoutes); app.use('/groups', groupRoutes);
app.use('/auth', authRoutes) app.use('/auth', authRoutes);
// app.use('/slack', async (req:Request, res:Response) => {
// console.log(req)
// let code = req.query.code;
// });
app.use('/slack', slackRoutes); app.use('/slack', slackRoutes);
app.use('/bridge', bridgeRoutes); app.use('/bridge', bridgeRoutes);
app.use('/channel', channelRoutes); app.use('/channel', channelRoutes);
@ -49,12 +46,21 @@ AppDataSource.initialize()
const port = config.get<number>('port'); const port = config.get<number>('port');
app.listen(port); app.listen(port);
logger.info(`Server started on port: ${port}`)
console.log(`Server started on port: ${port}`) await MatterbridgeManager.spawnAll();
let proclist = await MatterbridgeManager.processes;
// await MatterbridgeManager.spawnAll(); logger.info('Spawned group processes: %s', proclist);
// console.log('Spawned group processes:');
// let proclist = await MatterbridgeManager.processes;
// console.log(proclist);
}) })
// Kill matterbridge processes on app exit.
process.on('SIGTERM', () => {
logger.debug('killing matterbridge from SIGTERM')
killMatterbridge()
})
process.on('exit', () => {
logger.debug('killing matterbridge from exit event')
killMatterbridge()
})

View file

@ -1,8 +1,7 @@
import {NextFunction, Request, Response} from 'express'; import {NextFunction, Request, Response} from 'express';
import {CheckAdminInput} from "../schemas/auth.schema"; import {CheckAdminInput} from "../schemas/auth.schema";
import { hashed_token, tokenHasher} from "../auth"; import { hashed_token, tokenHasher} from "../auth";
import logger from "../logging";
export const checkAdminToken = async( export const checkAdminToken = async(
@ -15,7 +14,7 @@ export const checkAdminToken = async(
req.session?.hashed_token === hashed_token req.session?.hashed_token === hashed_token
){ ){
req.session.hashed_token = hashed_token; req.session.hashed_token = hashed_token;
console.log("Logged in with admin token") logger.info("Logged in with admin token")
res.status(200).json({ res.status(200).json({
status: 'success', status: 'success',
message: "Correct admin token!" message: "Correct admin token!"
@ -23,7 +22,7 @@ export const checkAdminToken = async(
} else { } else {
req.session.logged_in = false; req.session.logged_in = false;
console.log("Login with admin token failed") logger.warning("Login with admin token failed")
return res.status(403).json({ return res.status(403).json({
status:'fail', status:'fail',
message: "Incorrect admin token!" message: "Incorrect admin token!"

View file

@ -17,6 +17,7 @@ const channelRepository = AppDataSource.getRepository(Channel)
import MatterbridgeManager from '../matterbridge/process'; import MatterbridgeManager from '../matterbridge/process';
import logger from "../logging";
export const createChannelHandler = async( export const createChannelHandler = async(
req: Request<{}, {}, CreateChannelInput>, req: Request<{}, {}, CreateChannelInput>,
@ -47,8 +48,6 @@ export const createChannelHandler = async(
group: {id: group.id} group: {id: group.id}
}) })
if (!channel) { if (!channel) {
// create new // create new
channel = new Channel() channel = new Channel()
@ -58,10 +57,6 @@ export const createChannelHandler = async(
channel.bridge = bridge channel.bridge = bridge
channel.group = group channel.group = group
console.log('have channel', channel)
console.log('have group', group)
console.log('have bridge', bridge)
channel = await channelRepository.save(channel) channel = await channelRepository.save(channel)
await groupRepository await groupRepository
@ -76,17 +71,18 @@ export const createChannelHandler = async(
.of(bridge) .of(bridge)
.add(channel) .add(channel)
console.log('newchannel', channel) logger.debug('Created new channel: %s', channel)
console.log('saved group', group)
await MatterbridgeManager.spawnProcess(group.name) await MatterbridgeManager.spawnProcess(group.name)
logger.debug('Spawned process for %s', group.name)
return res.status(200).json({ return res.status(200).json({
status: 'success', status: 'success',
data: channel data: channel
}) })
} catch (err) { } catch (err) {
console.log('failed to create channe', err) logger.error('failed to create channel', err)
return res.status(502).json({ return res.status(502).json({
status: 'failed', status: 'failed',
message: 'failed to create channel' message: 'failed to create channel'

View file

@ -7,32 +7,20 @@ import {randomBytes} from "crypto";
import {AppDataSource} from "../db/data-source"; import {AppDataSource} from "../db/data-source";
import {hashed_token} from "../auth";
const groupRepository = AppDataSource.getRepository(Group) const groupRepository = AppDataSource.getRepository(Group)
import logger from "../logging";
export const createGroupHandler = async( export const createGroupHandler = async(
req: Request<{}, {}, CreateGroupInput>, req: Request<{}, {}, CreateGroupInput>,
res: Response res: Response
) => { ) => {
// console.log(req.body);
// const admin_token = config.get<string>('admin_token');
// if (req.body?.token !== admin_token && req.session.hashed_token !== hashed_token){
// return res.status(403).json({
// status: 'fail',
// message: 'Not authorized to create group without correct admin token'
// })
// }
// Make new invite token as a random UUID
// let invite_token = randomUUID();
// doesn't need to be as long as that...
let invite_token = randomBytes(8).toString('hex'); let invite_token = randomBytes(8).toString('hex');
let group = await groupRepository.create({...req.body, invite_token}) let group = await groupRepository.create({...req.body, invite_token})
let result = await groupRepository.save(group) let result = await groupRepository.save(group)
console.log("Group successfully created") logger.info("Group successfully created: %s", result)
console.log(result)
return res.send({"status": "success", "data": result}) return res.send({"status": "success", "data": result})
} }
@ -51,15 +39,15 @@ export const getGroupHandler = async(
} else { } else {
group = await groupRepository.find() group = await groupRepository.find()
} }
console.log(group);
if (group.length === 0) { if (group.length === 0) {
logger.info("failed to get group with name %s", query)
return res.status(404).json({ return res.status(404).json({
status: 'failed', status: 'failed',
message: `No group with matching name exists. given name: ${query}` message: `No group with matching name exists. given name: ${query}`
}) })
} }
console.log("Groups retrieved", group); logger.info("Groups retrieved %s", group);
return res.status(200).json({ return res.status(200).json({
status: 'success', status: 'success',
@ -69,6 +57,7 @@ export const getGroupHandler = async(
}) })
} catch (err: any) { } catch (err: any) {
logger.debug('Error getting groups', err)
next(err); next(err);
} }
}; };

View file

@ -8,6 +8,7 @@ import {JoinSlackChannelInput} from "../schemas/slack.schema";
import { randomUUID } from "crypto"; import { randomUUID } from "crypto";
import {log} from "util"; import {log} from "util";
import {Join} from "typeorm"; import {Join} from "typeorm";
import logger from "../logging";
const scopes = ['bot', 'channels:write', 'channels:write.invites', 'chat:write:bot', 'chat:write:user', 'users.profile:read']; const scopes = ['bot', 'channels:write', 'channels:write.invites', 'chat:write:bot', 'chat:write:user', 'users.profile:read'];
const bridgeRepository = AppDataSource.getRepository(Bridge) const bridgeRepository = AppDataSource.getRepository(Bridge)
@ -100,9 +101,6 @@ export const SlackInstallLinkHandler = async(
} }
export const SlackCallbackHandler = async( export const SlackCallbackHandler = async(
req: Request, req: Request,
res: Response res: Response
@ -112,7 +110,7 @@ export const SlackCallbackHandler = async(
success: async (installation:any, installOptions:any, req:Request, res:Response) => { success: async (installation:any, installOptions:any, req:Request, res:Response) => {
// console.log(installation, installOptions, req.body, req.content, req.query, req.params) // console.log(installation, installOptions, req.body, req.content, req.query, req.params)
// console.log(installation.team.id, installation.team.name, installation.bot.token); // console.log(installation.team.id, installation.team.name, installation.bot.token);
console.log('istallation info', installation) logger.debug('slack installation info: %s', installation)
let bridge_data = { let bridge_data = {
'Protocol': 'slack', 'Protocol': 'slack',
'Label': installation.team.name, 'Label': installation.team.name,
@ -123,45 +121,30 @@ export const SlackCallbackHandler = async(
'user_token': installation.user.token, 'user_token': installation.user.token,
'bot_id': installation.bot.userId 'bot_id': installation.bot.userId
} }
console.log('bot token', installation.bot.token)
// check if we have an entity // check if we have an entity
let bridge = await bridgeRepository.findOneBy({Token: installation.bot.token}) let bridge = await bridgeRepository.findOneBy({Token: installation.bot.token})
let result
if (!bridge){ if (!bridge){
bridge = await bridgeRepository.create(bridge_data); bridge = await bridgeRepository.create(bridge_data);
await bridgeRepository.save(bridge); await bridgeRepository.save(bridge);
console.log('created bridge') logger.debug('created bridge')
} else { } else {
// await bridgeRepository.update(
// {Token: installation.bot.token}, logger.debug('existing bridge: %s', bridge)
// {
// state_token: req.session.state_token,
// user_token: installation.access_token,
// bot_id: installation.bot.bot_user_id
//
// },
//
// )
console.log('existing bridge', bridge)
// Don't overwrite existing label // Don't overwrite existing label
bridge_data.Label = bridge.Label bridge_data.Label = bridge.Label
bridge_data = {...bridge, ...bridge_data} bridge_data = {...bridge, ...bridge_data}
console.log('updating bridge with', bridge_data)
let newbridge = await bridgeRepository.save(bridge_data) let newbridge = await bridgeRepository.save(bridge_data)
console.log('updated bridge', newbridge)
console.log('updated bridge')
} }
res.send('<html><body><h1>Success! Return to the chatbridge login window.</h1><h3>This tab will close in 3 seconds...</h3><script>window.setTimeout(window.close, 3000)</script></body>') res.send('<html><body><h1>Success! Return to the chatbridge login window.</h1><h3>This tab will close in 3 seconds...</h3><script>window.setTimeout(window.close, 3000)</script></body>')
}, },
failure: (error:any, installOptions:any , req:Request, res:Response) => { failure: (error:any, installOptions:any , req:Request, res:Response) => {
// console.log(error, installOptions, req.body, req.content, req.query, req.params) logger.error('error when logging in with slack', error)
res.send('failure. Something is broken about chatbridge :('); res.send('failure. Something is broken about chatbridge :(');
}, },
} }
await installer.handleCallback(req, res, callbackOptions); await installer.handleCallback(req, res, callbackOptions);
} }
@ -171,7 +154,6 @@ export const getChannelsHandler = async(
res: Response res: Response
) => { ) => {
let bridge = await bridgeRepository.findOneBy({state_token: req.session.state_token}) let bridge = await bridgeRepository.findOneBy({state_token: req.session.state_token})
// console.log('bridge data', bridge)
try { try {
fetch('https://slack.com/api/conversations.list', { fetch('https://slack.com/api/conversations.list', {
@ -182,7 +164,7 @@ export const getChannelsHandler = async(
} }
}).then(result => result.json()) }).then(result => result.json())
.then((result) => { .then((result) => {
console.log('channels',result) logger.debug('got slack channels: %s',result)
let channels = result.channels.map( let channels = result.channels.map(
(chan: slackChannel) => { (chan: slackChannel) => {
return { return {
@ -199,7 +181,8 @@ export const getChannelsHandler = async(
} }
}) })
}) })
} catch { } catch (error:any) {
logger.error('Error getting slack lists', error)
return res.status(502).json({ return res.status(502).json({
status: 'failure', status: 'failure',
message: 'couldnt get lists!' message: 'couldnt get lists!'
@ -214,10 +197,7 @@ export const joinChannelsHandler = async(
) => { ) => {
let bridge = await bridgeRepository.findOneBy({state_token: req.session.state_token}) let bridge = await bridgeRepository.findOneBy({state_token: req.session.state_token})
console.log('joinchannel bridge', bridge)
console.log('joinchannel chanid', req.body.channel_id)
console.log('joinchannel userid', bridge.user_token)
console.log('joinchannel botid', bridge.bot_id)
fetch('https://slack.com/api/conversations.invite', { fetch('https://slack.com/api/conversations.invite', {
method: "POST", method: "POST",
headers: { headers: {
@ -230,7 +210,6 @@ export const joinChannelsHandler = async(
}) })
}).then(result => result.json()) }).then(result => result.json())
.then(result => { .then(result => {
console.log(result);
if (result.ok || result.error === 'already_in_channel'){ if (result.ok || result.error === 'already_in_channel'){
return res.status(200).json({ return res.status(200).json({
status: 'success', status: 'success',
@ -245,80 +224,13 @@ export const joinChannelsHandler = async(
}) })
} }
}) })
// try and invite bot
} }
// export const joinChannelsHandler = async(
// req: Request<{}, {}, JoinSlackChannelInput>,
// res: Response
// ) => {
// let bridge = await bridgeRepository.findOneBy({state_token: req.session.state_token})
// console.log('bridge data', bridge)
//
// try {
// // Get channel ID from channel name
// let channels_res = await fetch('https://slack.com/api/conversations.list', {
// method: "POST",
// headers: {
// "Content-Type": "application/json",
// "Authorization": `Bearer ${bridge.Token}`
// }
// })
// let channels = <{ channels: slackChannel[] }><unknown> await channels_res.json()
// let channel_id = channels.channels.filter(
// (chan) => {
// return (chan.name == req.body.channel)
// }
// ).map(chan => chan.id)[0]
// console.log('channel id', channel_id)
// console.log('bridge token', `Bearer ${bridge.Token}`)
// // Join channel from ID
// fetch('https://slack.com/api/conversations.join', {
// method: "POST",
// headers: {
// "Content-Type": "application/json",
// "Authorization": `Bearer ${bridge.Token}`
// },
// body: JSON.stringify({
// channel: channel_id
// })
// }).then(result => result.json())
// .then((result) => {
// console.log('result', result)
// if (res.ok) {
// res.status(200).json({
// status: 'success',
// data: {
// channels
// }
// })
// } else {
// res.status(502).json({
// status: 'failure',
// message: 'Couldnt join channel'
// })
// }
// })
//
// } catch (error) {
// console.log('channel join error', error)
// return res.status(502).json({
// status: 'failure',
// message: "Couldn't join channel!"
// })
// }
// }
export const getBotInfo = async( export const getBotInfo = async(
req: Request, req: Request,
res: Response res: Response
) => { ) => {
let bridge = await bridgeRepository.findOneBy({state_token: req.session.state_token}) let bridge = await bridgeRepository.findOneBy({state_token: req.session.state_token})
// console.log('bridge data', bridge)
try { try {
fetch('https://slack.com/api/auth.test', { fetch('https://slack.com/api/auth.test', {
@ -340,7 +252,7 @@ export const getBotInfo = async(
} }
}) })
} catch (error) { } catch (error) {
console.log('auth.test error', error) logger.error('auth.test error', error)
return res.status(502).json({ return res.status(502).json({
status:'failure', status:'failure',
message:'Couldnt get bot info' message:'Couldnt get bot info'

View file

@ -0,0 +1,12 @@
import {DataSource} from "typeorm";
export const AppDataSource = new DataSource({
type: 'sqlite',
database: ":memory:",
synchronize: true,
logging: false,
dropSchema: true,
entities: ['src/entities/**/*.entity{.ts,.js}'],
// migrations: ['src/migrations/**/*{.ts,.js}'],
// subscribers: ['server/subscribers/**/*{.ts,.js}'],
});

View file

@ -10,7 +10,6 @@ const postgresConfig = config.get<{
password: string; password: string;
database: string; database: string;
}>('postgresConfig'); }>('postgresConfig');
export const AppDataSource = new DataSource({ export const AppDataSource = new DataSource({
...postgresConfig, ...postgresConfig,
type: 'postgres', type: 'postgres',

56
server/src/logging.ts Normal file
View file

@ -0,0 +1,56 @@
const fs = require('fs')
const path = require('path')
import config from "config";
import { Logger, format, createLogger, transports } from 'winston';
const logDir = config.get<string>('logDir')
const makeLogdir = () => {
fs.mkdir(logDir, (err:Error|undefined) => {
if (err) throw err;
})
}
const makeLogger = (): Logger => {
makeLogdir()
const logger = createLogger({
level: process.env.NODE_ENV === 'development' ? 'debug' : 'info',
format: format.combine(
format.timestamp({
format: 'YYYY-MM-DD HH:mm:ss'
}),
format.errors({ stack: true }),
format.splat(),
format.json()
),
transports: [
new transports.File({
filename: path.join([logDir, 'chatbridge.error.log']),
level: 'error'
}),
new transports.File({
filename: path.join([logDir, 'chatbridge.debug.log']),
level: 'debug'
}),
...(process.env.NODE_ENV === 'development' ? [
new transports.Console({
level: 'debug',
format: format.combine(
format.colorize(),
format.timestamp({
format: 'YYYY-MM-DD HH:mm:ss'
}),
format.simple(),
format.splat()
)
})
]: [])
]
})
return(logger)
}
const logger = makeLogger()
export default logger

View file

@ -8,6 +8,7 @@ import {AppDataSource} from "../db/data-source";
import {Group} from "../entities/group.entity"; import {Group} from "../entities/group.entity";
const slugify = require('slugify'); const slugify = require('slugify');
import * as TOML from '@ltd/j-toml'; import * as TOML from '@ltd/j-toml';
import logger from "../logging";
const fs = require('fs'); const fs = require('fs');
const groupRepository = AppDataSource.getRepository(Group) const groupRepository = AppDataSource.getRepository(Group)
@ -57,7 +58,7 @@ export const getGroupConfig = async (group_name: string, group:object): Promise<
where: {name: group_name}, where: {name: group_name},
relations: {channels: true} relations: {channels: true}
}) })
console.log('config group', group) logger.debug('config group', group)
// Construct config in the gateway style for programmatic use // Construct config in the gateway style for programmatic use
let gateway = <Gateway>{ let gateway = <Gateway>{
name: group.name, name: group.name,
@ -79,7 +80,7 @@ export const getGroupConfig = async (group_name: string, group:object): Promise<
} }
}) })
} }
console.log('config group transformed', gateway) logger.debug('config group transformed', gateway)
return gateway return gateway
} }
@ -154,7 +155,7 @@ export const GatewayToTOML = (gateway: Gateway) => {
protocols[bridge.protocol][bridge.name] = TOML.Section(bridgeEntry) protocols[bridge.protocol][bridge.name] = TOML.Section(bridgeEntry)
}) })
console.log('gateway toml protocols', protocols) logger.debug('gateway toml protocols', protocols)
return { return {
...protocols, ...protocols,
@ -174,10 +175,12 @@ export const writeTOML = (gateway_toml: object, out_file: string) => {
} }
) )
console.log('toml string', toml_string) logger.debug('toml string', toml_string)
fs.writeFileSync(out_file, toml_string) fs.writeFileSync(out_file, toml_string)
logger.info('Wrote group config to %s', out_file)
} }
export const writeGroupConfig = async (group_name: string, out_file: string) => { export const writeGroupConfig = async (group_name: string, out_file: string) => {

View file

@ -12,6 +12,7 @@ import config from "config";
import { writeGroupConfig } from "./config"; import { writeGroupConfig } from "./config";
import {Group} from "../entities/group.entity"; import {Group} from "../entities/group.entity";
import slugify from "slugify"; import slugify from "slugify";
import logger from "../logging";
const groupRepository = AppDataSource.getRepository(Group) const groupRepository = AppDataSource.getRepository(Group)
@ -57,9 +58,8 @@ class MatterbridgeManager {
let group_name_slug = slugify(group_name) let group_name_slug = slugify(group_name)
let group_filename = `${this.matterbridge_config_dir}/matterbridge-${group_name_slug}.toml` let group_filename = `${this.matterbridge_config_dir}/matterbridge-${group_name_slug}.toml`
await writeGroupConfig(group_name, group_filename); await writeGroupConfig(group_name, group_filename);
console.log('matterbridge config written')
if (!this.process_list.includes(group_name_slug)){ if (!this.process_list.includes(group_name_slug)){
console.log('matterbridge new process') logger.info('Spawning new matterbridge process: %s', group_name_slug)
await pm2.start( await pm2.start(
{ {
name: group_name_slug, name: group_name_slug,
@ -68,20 +68,25 @@ class MatterbridgeManager {
interpreter: 'none' interpreter: 'none'
}, },
(err:any, apps:object) => { (err:any, apps:object) => {
console.log('error starting matterbridge process', err, apps) if (err) {
logger.error('error starting matterbridge process', err, apps)
}
} }
) )
this.process_list.push(group_name_slug) this.process_list.push(group_name_slug)
} else { } else {
console.log('matterbridge restarting!') logger.info('Restarting existing matterbridge process: %s', group_name_slug)
await pm2.restart(group_name_slug, (err:any, proc:any) => { await pm2.restart(group_name_slug, (err:any, proc:any) => {
console.log('error restarting matterbridge process', err, apps)} if (err) {
logger.error('error restarting matterbridge process', err)
}}
) )
} }
} }
async refreshConfig(group_name: string) { async refreshConfig(group_name: string) {
let group_filename = `${this.matterbridge_config_dir}/matterbridge-${group_name}.toml` let group_name_slug = slugify(group_name)
let group_filename = `${this.matterbridge_config_dir}/matterbridge-${group_name_slug}.toml`
await writeGroupConfig(group_name, group_filename); await writeGroupConfig(group_name, group_filename);
} }
@ -127,4 +132,19 @@ const manager = new MatterbridgeManager(
matterbridge_config.bin, matterbridge_config.bin,
matterbridge_config.config matterbridge_config.config
) )
export const killMatterbridge = () => {
pm2.connect((err: Error|undefined) => {
if (err){
logger.error('error connecting to pm2', err)
}
pm2.killDaemon((err: Error|undefined) => {
if (err){
logger.error('error killing pm2 daemon', err)
}
pm2.disconnect()
})
})
}
export default manager export default manager

153
yarn.lock
View file

@ -1156,6 +1156,11 @@
resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==
"@colors/colors@1.5.0":
version "1.5.0"
resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9"
integrity sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==
"@cspotcode/source-map-support@^0.8.0": "@cspotcode/source-map-support@^0.8.0":
version "0.8.1" version "0.8.1"
resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1" resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1"
@ -1274,6 +1279,15 @@
resolved "https://registry.yarnpkg.com/@csstools/selector-specificity/-/selector-specificity-2.2.0.tgz#2cbcf822bf3764c9658c4d2e568bd0c0cb748016" resolved "https://registry.yarnpkg.com/@csstools/selector-specificity/-/selector-specificity-2.2.0.tgz#2cbcf822bf3764c9658c4d2e568bd0c0cb748016"
integrity sha512-+OJ9konv95ClSTOJCmMZqpd5+YGsB2S+x6w3E1oaM8UuR5j8nTNHYSz8c9BEPGDOCMQYIEEGlVPj/VY64iTbGw== integrity sha512-+OJ9konv95ClSTOJCmMZqpd5+YGsB2S+x6w3E1oaM8UuR5j8nTNHYSz8c9BEPGDOCMQYIEEGlVPj/VY64iTbGw==
"@dabh/diagnostics@^2.0.2":
version "2.0.3"
resolved "https://registry.yarnpkg.com/@dabh/diagnostics/-/diagnostics-2.0.3.tgz#7f7e97ee9a725dffc7808d93668cc984e1dc477a"
integrity sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA==
dependencies:
colorspace "1.1.x"
enabled "2.0.x"
kuler "^2.0.0"
"@discoveryjs/json-ext@^0.5.0": "@discoveryjs/json-ext@^0.5.0":
version "0.5.7" version "0.5.7"
resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz#1d572bfbbe14b7704e0ba0f39b74815b84870d70" resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz#1d572bfbbe14b7704e0ba0f39b74815b84870d70"
@ -2824,11 +2838,23 @@
resolved "https://registry.yarnpkg.com/@types/strip-json-comments/-/strip-json-comments-0.0.30.tgz#9aa30c04db212a9a0649d6ae6fd50accc40748a1" resolved "https://registry.yarnpkg.com/@types/strip-json-comments/-/strip-json-comments-0.0.30.tgz#9aa30c04db212a9a0649d6ae6fd50accc40748a1"
integrity sha512-7NQmHra/JILCd1QqpSzl8+mJRc8ZHz3uDm8YV1Ks9IhK0epEiTw8aIErbvH9PI+6XbqhyIQy3462nEsn7UVzjQ== integrity sha512-7NQmHra/JILCd1QqpSzl8+mJRc8ZHz3uDm8YV1Ks9IhK0epEiTw8aIErbvH9PI+6XbqhyIQy3462nEsn7UVzjQ==
"@types/triple-beam@^1.3.2":
version "1.3.2"
resolved "https://registry.yarnpkg.com/@types/triple-beam/-/triple-beam-1.3.2.tgz#38ecb64f01aa0d02b7c8f4222d7c38af6316fef8"
integrity sha512-txGIh+0eDFzKGC25zORnswy+br1Ha7hj5cMVwKIU7+s0U2AxxJru/jZSMU6OC9MJWP6+pc/hc6ZjyZShpsyY2g==
"@types/trusted-types@^2.0.2": "@types/trusted-types@^2.0.2":
version "2.0.3" version "2.0.3"
resolved "https://registry.yarnpkg.com/@types/trusted-types/-/trusted-types-2.0.3.tgz#a136f83b0758698df454e328759dbd3d44555311" resolved "https://registry.yarnpkg.com/@types/trusted-types/-/trusted-types-2.0.3.tgz#a136f83b0758698df454e328759dbd3d44555311"
integrity sha512-NfQ4gyz38SL8sDNrSixxU2Os1a5xcdFxipAFxYEuLUlvU2uDwS4NUpsImcf1//SlWItCVMMLiylsxbmNMToV/g== integrity sha512-NfQ4gyz38SL8sDNrSixxU2Os1a5xcdFxipAFxYEuLUlvU2uDwS4NUpsImcf1//SlWItCVMMLiylsxbmNMToV/g==
"@types/winston@^2.4.4":
version "2.4.4"
resolved "https://registry.yarnpkg.com/@types/winston/-/winston-2.4.4.tgz#48cc744b7b42fad74b9a2e8490e0112bd9a3d08d"
integrity sha512-BVGCztsypW8EYwJ+Hq+QNYiT/MUyCif0ouBH+flrY66O5W+KIXAMML6E/0fJpm7VjIzgangahl5S03bJJQGrZw==
dependencies:
winston "*"
"@types/ws@^8.5.5": "@types/ws@^8.5.5":
version "8.5.5" version "8.5.5"
resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.5.5.tgz#af587964aa06682702ee6dcbc7be41a80e4b28eb" resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.5.5.tgz#af587964aa06682702ee6dcbc7be41a80e4b28eb"
@ -4069,7 +4095,7 @@ collect-v8-coverage@^1.0.0:
resolved "https://registry.yarnpkg.com/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz#c0b29bcd33bcd0779a1344c2136051e6afd3d9e9" resolved "https://registry.yarnpkg.com/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz#c0b29bcd33bcd0779a1344c2136051e6afd3d9e9"
integrity sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q== integrity sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==
color-convert@^1.9.0: color-convert@^1.9.0, color-convert@^1.9.3:
version "1.9.3" version "1.9.3"
resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8"
integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==
@ -4088,11 +4114,27 @@ color-name@1.1.3:
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25"
integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==
color-name@~1.1.4: color-name@^1.0.0, color-name@~1.1.4:
version "1.1.4" version "1.1.4"
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
color-string@^1.6.0:
version "1.9.1"
resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.9.1.tgz#4467f9146f036f855b764dfb5bf8582bf342c7a4"
integrity sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==
dependencies:
color-name "^1.0.0"
simple-swizzle "^0.2.2"
color@^3.1.3:
version "3.2.1"
resolved "https://registry.yarnpkg.com/color/-/color-3.2.1.tgz#3544dc198caf4490c3ecc9a790b54fe9ff45e164"
integrity sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==
dependencies:
color-convert "^1.9.3"
color-string "^1.6.0"
colord@^2.9.1: colord@^2.9.1:
version "2.9.3" version "2.9.3"
resolved "https://registry.yarnpkg.com/colord/-/colord-2.9.3.tgz#4f8ce919de456f1d5c1c368c307fe20f3e59fb43" resolved "https://registry.yarnpkg.com/colord/-/colord-2.9.3.tgz#4f8ce919de456f1d5c1c368c307fe20f3e59fb43"
@ -4103,6 +4145,14 @@ colorette@^2.0.10, colorette@^2.0.14:
resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.20.tgz#9eb793e6833067f7235902fcd3b09917a000a95a" resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.20.tgz#9eb793e6833067f7235902fcd3b09917a000a95a"
integrity sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w== integrity sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==
colorspace@1.1.x:
version "1.1.4"
resolved "https://registry.yarnpkg.com/colorspace/-/colorspace-1.1.4.tgz#8d442d1186152f60453bf8070cd66eb364e59243"
integrity sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w==
dependencies:
color "^3.1.3"
text-hex "1.0.x"
combined-stream@^1.0.6, combined-stream@^1.0.8: combined-stream@^1.0.6, combined-stream@^1.0.8:
version "1.0.8" version "1.0.8"
resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f"
@ -4941,6 +4991,11 @@ emojis-list@^3.0.0:
resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78" resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78"
integrity sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q== integrity sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==
enabled@2.0.x:
version "2.0.0"
resolved "https://registry.yarnpkg.com/enabled/-/enabled-2.0.0.tgz#f9dd92ec2d6f4bbc0d5d1e64e21d61cd4665e7c2"
integrity sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==
encodeurl@~1.0.2: encodeurl@~1.0.2:
version "1.0.2" version "1.0.2"
resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59"
@ -5537,6 +5592,11 @@ fclone@1.0.11, fclone@~1.0.11:
resolved "https://registry.yarnpkg.com/fclone/-/fclone-1.0.11.tgz#10e85da38bfea7fc599341c296ee1d77266ee640" resolved "https://registry.yarnpkg.com/fclone/-/fclone-1.0.11.tgz#10e85da38bfea7fc599341c296ee1d77266ee640"
integrity sha512-GDqVQezKzRABdeqflsgMr7ktzgF9CyS+p2oe0jJqUY6izSSbhPIQJDpoU4PtGcD7VPM9xh/dVrTu6z1nwgmEGw== integrity sha512-GDqVQezKzRABdeqflsgMr7ktzgF9CyS+p2oe0jJqUY6izSSbhPIQJDpoU4PtGcD7VPM9xh/dVrTu6z1nwgmEGw==
fecha@^4.2.0:
version "4.2.3"
resolved "https://registry.yarnpkg.com/fecha/-/fecha-4.2.3.tgz#4d9ccdbc61e8629b259fdca67e65891448d569fd"
integrity sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==
file-entry-cache@^6.0.1: file-entry-cache@^6.0.1:
version "6.0.1" version "6.0.1"
resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027"
@ -5634,6 +5694,11 @@ flatted@^3.1.0:
resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.7.tgz#609f39207cb614b89d0765b477cb2d437fbf9787" resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.7.tgz#609f39207cb614b89d0765b477cb2d437fbf9787"
integrity sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ== integrity sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==
fn.name@1.x.x:
version "1.1.0"
resolved "https://registry.yarnpkg.com/fn.name/-/fn.name-1.1.0.tgz#26cad8017967aea8731bc42961d04a3d5988accc"
integrity sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==
follow-redirects@^1.0.0, follow-redirects@^1.14.0, follow-redirects@^1.14.9: follow-redirects@^1.0.0, follow-redirects@^1.14.0, follow-redirects@^1.14.9:
version "1.15.2" version "1.15.2"
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13" resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13"
@ -6344,6 +6409,11 @@ is-arrayish@^0.2.1:
resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d"
integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==
is-arrayish@^0.3.1:
version "0.3.2"
resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.3.2.tgz#4574a2ae56f7ab206896fb431eaeed066fdf8f03"
integrity sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==
is-bigint@^1.0.1: is-bigint@^1.0.1:
version "1.0.4" version "1.0.4"
resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.4.tgz#08147a1875bc2b32005d41ccd8291dffc6691df3" resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.4.tgz#08147a1875bc2b32005d41ccd8291dffc6691df3"
@ -7680,6 +7750,11 @@ klona@^2.0.4, klona@^2.0.5:
resolved "https://registry.yarnpkg.com/klona/-/klona-2.0.6.tgz#85bffbf819c03b2f53270412420a4555ef882e22" resolved "https://registry.yarnpkg.com/klona/-/klona-2.0.6.tgz#85bffbf819c03b2f53270412420a4555ef882e22"
integrity sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA== integrity sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA==
kuler@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/kuler/-/kuler-2.0.0.tgz#e2c570a3800388fb44407e851531c1d670b061b3"
integrity sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==
language-subtag-registry@~0.3.2: language-subtag-registry@~0.3.2:
version "0.3.22" version "0.3.22"
resolved "https://registry.yarnpkg.com/language-subtag-registry/-/language-subtag-registry-0.3.22.tgz#2e1500861b2e457eba7e7ae86877cbd08fa1fd1d" resolved "https://registry.yarnpkg.com/language-subtag-registry/-/language-subtag-registry-0.3.22.tgz#2e1500861b2e457eba7e7ae86877cbd08fa1fd1d"
@ -7819,6 +7894,18 @@ log-driver@^1.2.7:
resolved "https://registry.yarnpkg.com/log-driver/-/log-driver-1.2.7.tgz#63b95021f0702fedfa2c9bb0a24e7797d71871d8" resolved "https://registry.yarnpkg.com/log-driver/-/log-driver-1.2.7.tgz#63b95021f0702fedfa2c9bb0a24e7797d71871d8"
integrity sha512-U7KCmLdqsGHBLeWqYlFA0V0Sl6P08EE1ZrmA9cxjUE0WVqT9qnyVDPz1kzpFEP0jdJuFnasWIfSd7fsaNXkpbg== integrity sha512-U7KCmLdqsGHBLeWqYlFA0V0Sl6P08EE1ZrmA9cxjUE0WVqT9qnyVDPz1kzpFEP0jdJuFnasWIfSd7fsaNXkpbg==
logform@^2.3.2, logform@^2.4.0:
version "2.5.1"
resolved "https://registry.yarnpkg.com/logform/-/logform-2.5.1.tgz#44c77c34becd71b3a42a3970c77929e52c6ed48b"
integrity sha512-9FyqAm9o9NKKfiAKfZoYo9bGXXuwMkxQiQttkT4YjjVtQVIQtK6LmVtlxmCaFswo6N4AfEkHqZTV0taDtPotNg==
dependencies:
"@colors/colors" "1.5.0"
"@types/triple-beam" "^1.3.2"
fecha "^4.2.0"
ms "^2.1.1"
safe-stable-stringify "^2.3.1"
triple-beam "^1.3.0"
loose-envify@^1.1.0, loose-envify@^1.4.0: loose-envify@^1.1.0, loose-envify@^1.4.0:
version "1.4.0" version "1.4.0"
resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
@ -8293,6 +8380,13 @@ once@^1.3.0:
dependencies: dependencies:
wrappy "1" wrappy "1"
one-time@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/one-time/-/one-time-1.0.0.tgz#e06bc174aed214ed58edede573b433bbf827cb45"
integrity sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==
dependencies:
fn.name "1.x.x"
onetime@^5.1.2: onetime@^5.1.2:
version "5.1.2" version "5.1.2"
resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e"
@ -9790,7 +9884,7 @@ readable-stream@^2.0.1:
string_decoder "~1.1.1" string_decoder "~1.1.1"
util-deprecate "~1.0.1" util-deprecate "~1.0.1"
readable-stream@^3.0.6: readable-stream@^3.0.6, readable-stream@^3.4.0, readable-stream@^3.6.0:
version "3.6.2" version "3.6.2"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967"
integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==
@ -10079,6 +10173,11 @@ safe-regex-test@^1.0.0:
get-intrinsic "^1.1.3" get-intrinsic "^1.1.3"
is-regex "^1.1.4" is-regex "^1.1.4"
safe-stable-stringify@^2.3.1:
version "2.4.3"
resolved "https://registry.yarnpkg.com/safe-stable-stringify/-/safe-stable-stringify-2.4.3.tgz#138c84b6f6edb3db5f8ef3ef7115b8f55ccbf886"
integrity sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g==
"safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0": "safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0":
version "2.1.2" version "2.1.2"
resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
@ -10332,6 +10431,13 @@ signal-exit@^3.0.2, signal-exit@^3.0.3, signal-exit@^3.0.7:
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9"
integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==
simple-swizzle@^0.2.2:
version "0.2.2"
resolved "https://registry.yarnpkg.com/simple-swizzle/-/simple-swizzle-0.2.2.tgz#a4da6b635ffcccca33f70d17cb92592de95e557a"
integrity sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==
dependencies:
is-arrayish "^0.3.1"
sisteransi@^1.0.5: sisteransi@^1.0.5:
version "1.0.5" version "1.0.5"
resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed"
@ -10519,6 +10625,11 @@ stable@^0.1.8:
resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf" resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf"
integrity sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w== integrity sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==
stack-trace@0.0.x:
version "0.0.10"
resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.10.tgz#547c70b347e8d32b4e108ea1a2a159e5fdde19c0"
integrity sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==
stack-utils@^2.0.3: stack-utils@^2.0.3:
version "2.0.6" version "2.0.6"
resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.6.tgz#aaf0748169c02fc33c8232abccf933f54a1cc34f" resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.6.tgz#aaf0748169c02fc33c8232abccf933f54a1cc34f"
@ -10891,6 +11002,11 @@ test-exclude@^6.0.0:
glob "^7.1.4" glob "^7.1.4"
minimatch "^3.0.4" minimatch "^3.0.4"
text-hex@1.0.x:
version "1.0.0"
resolved "https://registry.yarnpkg.com/text-hex/-/text-hex-1.0.0.tgz#69dc9c1b17446ee79a92bf5b884bb4b9127506f5"
integrity sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==
text-table@^0.2.0: text-table@^0.2.0:
version "0.2.0" version "0.2.0"
resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4"
@ -10976,6 +11092,11 @@ tree-kill@^1.2.2:
resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.2.tgz#4ca09a9092c88b73a7cdc5e8a01b507b0790a0cc" resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.2.tgz#4ca09a9092c88b73a7cdc5e8a01b507b0790a0cc"
integrity sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A== integrity sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==
triple-beam@^1.3.0:
version "1.4.1"
resolved "https://registry.yarnpkg.com/triple-beam/-/triple-beam-1.4.1.tgz#6fde70271dc6e5d73ca0c3b24e2d92afb7441984"
integrity sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg==
tryer@^1.0.1: tryer@^1.0.1:
version "1.0.1" version "1.0.1"
resolved "https://registry.yarnpkg.com/tryer/-/tryer-1.0.1.tgz#f2c85406800b9b0f74c9f7465b81eaad241252f8" resolved "https://registry.yarnpkg.com/tryer/-/tryer-1.0.1.tgz#f2c85406800b9b0f74c9f7465b81eaad241252f8"
@ -11679,6 +11800,32 @@ wildcard@^2.0.0:
resolved "https://registry.yarnpkg.com/wildcard/-/wildcard-2.0.1.tgz#5ab10d02487198954836b6349f74fff961e10f67" resolved "https://registry.yarnpkg.com/wildcard/-/wildcard-2.0.1.tgz#5ab10d02487198954836b6349f74fff961e10f67"
integrity sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ== integrity sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==
winston-transport@^4.5.0:
version "4.5.0"
resolved "https://registry.yarnpkg.com/winston-transport/-/winston-transport-4.5.0.tgz#6e7b0dd04d393171ed5e4e4905db265f7ab384fa"
integrity sha512-YpZzcUzBedhlTAfJg6vJDlyEai/IFMIVcaEZZyl3UXIl4gmqRpU7AE89AHLkbzLUsv0NVmw7ts+iztqKxxPW1Q==
dependencies:
logform "^2.3.2"
readable-stream "^3.6.0"
triple-beam "^1.3.0"
winston@*, winston@^3.10.0:
version "3.10.0"
resolved "https://registry.yarnpkg.com/winston/-/winston-3.10.0.tgz#d033cb7bd3ced026fed13bf9d92c55b903116803"
integrity sha512-nT6SIDaE9B7ZRO0u3UvdrimG0HkB7dSTAgInQnNR2SOPJ4bvq5q79+pXLftKmP52lJGW15+H5MCK0nM9D3KB/g==
dependencies:
"@colors/colors" "1.5.0"
"@dabh/diagnostics" "^2.0.2"
async "^3.2.3"
is-stream "^2.0.0"
logform "^2.4.0"
one-time "^1.0.0"
readable-stream "^3.4.0"
safe-stable-stringify "^2.3.1"
stack-trace "0.0.x"
triple-beam "^1.3.0"
winston-transport "^4.5.0"
with@^7.0.0: with@^7.0.0:
version "7.0.2" version "7.0.2"
resolved "https://registry.yarnpkg.com/with/-/with-7.0.2.tgz#ccee3ad542d25538a7a7a80aad212b9828495bac" resolved "https://registry.yarnpkg.com/with/-/with-7.0.2.tgz#ccee3ad542d25538a7a7a80aad212b9828495bac"