Add Mattermost bot for stand-up

pull/2325/head
Jérémy Rialland 2022-10-05 12:56:06 +02:00 committed by Jérémy Rialland
parent 81a5c737d0
commit b9db70f590
20 changed files with 1297 additions and 11 deletions

View File

@ -1 +1,2 @@
web: node -v ; yarn -v ; echo "$PORT" ; yarn workspace api run start:prod
bot: node -v ; yarn -v ; echo "$PORT" ; yarn workspace standup-mattermost-bot run start:prod

View File

@ -10,10 +10,13 @@
"modele-social",
"exoneration-covid",
"api",
"site"
"site",
"standup-mattermost-bot"
],
"scripts": {
"scalingo-postbuild": "CI=true ; yarn test:type && yarn workspaces focus api && yarn workspace api run build && yarn workspaces focus --all && yarn test && yarn workspaces focus api --production",
"scalingo-postbuild": "CI=true ; yarn test:type && yarn build:api && yarn build:standup-mattermost-bot && yarn workspaces focus --all && yarn test && yarn workspaces focus standup-mattermost-bot api --production",
"build:api": "yarn workspaces focus api && yarn workspace api run build",
"build:standup-mattermost-bot": "yarn workspaces focus standup-mattermost-bot && yarn workspace standup-mattermost-bot run build",
"lint:eslintrc": "npx eslint-config-prettier .eslintrc.cjs",
"lint:eslint": "NODE_OPTIONS='--max-old-space-size=4096' eslint .",
"lint:eslint:fix": "yarn lint:eslint --fix",

View File

@ -0,0 +1 @@
MONGO_URL=mongodb://root:example@localhost:27017/

View File

@ -0,0 +1,12 @@
# Bot Mattermost pour stand-up asynchrone
Ce bot envoie une notification périodique sur un canal Mattermost dédié afin que chaque membre de l'équipe puisse écrire en réponse où il en est dans ses tâches.
Il désigne également qui sera l'animateur pour chaque jour de la semaine à venir.
Et peut-être plus à venir...
# Détail technique
Le bot peut être installé facilement sur Scalingo, vous pouvez aller dans le `Procfile` à la racine du projet.
Il nécessite une base de données Mongodb pour stocker les token d'authentification et la liste des animateurs de la semaine.

View File

@ -0,0 +1,21 @@
version: '3.7'
services:
mongo:
image: mongo
restart: always
ports:
- 27017:27017
environment:
MONGO_INITDB_ROOT_USERNAME: root
MONGO_INITDB_ROOT_PASSWORD: example
mongo-express:
image: mongo-express
restart: always
ports:
- 8081:8081
environment:
ME_CONFIG_MONGODB_ADMINUSERNAME: root
ME_CONFIG_MONGODB_ADMINPASSWORD: example
ME_CONFIG_MONGODB_URL: mongodb://root:example@mongo:27017/

View File

@ -0,0 +1,39 @@
{
"name": "standup-mattermost-bot",
"license": "MIT",
"version": "2.0.0",
"description": "Code source du standup-mattermost-bot",
"repository": {
"type": "git",
"url": "https://github.com/betagouv/mon-entreprise.git",
"directory": "standup-mattermost-bot"
},
"private": true,
"engines": {
"node": "^16"
},
"type": "module",
"scripts": {
"build": "yarn tsc",
"start": "nodemon -e \"js,ts\" -x 'NODE_OPTIONS=\"--loader ts-node/esm\" node ./source/index.ts'",
"start:prod": "NODE_ENV=production nodemon -d 500ms -w ./dist/index.js -x 'node ./dist/index.js || touch ./dist/index.js'"
},
"dependencies": {
"@breejs/later": "^4.1.0",
"@koa/cors": "^3.4.1",
"@koa/router": "^12.0.0",
"bree": "^9.1.2",
"dotenv": "^16.0.3",
"got": "^12.5.1",
"koa": "^2.13.4",
"mongodb": "^4.10.0",
"nodemon": "^2.0.20"
},
"devDependencies": {
"@types/koa": "^2.13.5",
"@types/koa__cors": "^3.3.0",
"@types/koa__router": "^12.0.0",
"ts-node": "^10.9.1",
"typescript": "^4.8.4"
}
}

View File

@ -0,0 +1,41 @@
import type { MattermostSendMessage } from './mattermost.js'
export const PORT = process.env.PORT || 4000
export const ORIGIN = process.env.ORIGIN || 'http://localhost:4000'
export const MONGO_URL = process.env.MONGO_URL
export const NODE_ENV = process.env.NODE_ENV
export const serverUrl = 'https://mattermost.incubateur.net'
export const clientSecret = 'pgnch7w643yfdkdjnnjcxhpsoe'
export const clientId = 'wbkot91tjbd6byn4fbmrtu8h6o'
export const redirectUri = `${ORIGIN}/oauth`
const days = [
'Lundi',
'Mardi',
'Mercredi',
'Jeudi',
'Vendredi',
'Samedi',
'Dimanche',
]
interface BotConfig {
channelName: string
standupDays: string[]
messageProps: MattermostSendMessage['props']
}
export const botConfig: BotConfig = {
channelName:
NODE_ENV !== 'production'
? 'startup-monentreprise-dev-bot-stand-up'
: 'startup-monentreprise-stand-up',
standupDays: days.slice(0, 4),
messageProps: {
from_webhook: 'true',
override_username: 'LURSSAF est votre amie',
override_icon_url:
'https://mon-entreprise.urssaf.fr/favicon/favicon-32x32.png?v=2.0',
},
}

View File

@ -0,0 +1,2 @@
import './server.js'
import './jobs.js'

View File

@ -0,0 +1,41 @@
import later from '@breejs/later'
import Bree, { BreeOptions } from 'bree'
import { dirname, join } from 'node:path'
import { fileURLToPath } from 'node:url'
import { NODE_ENV } from './config.js'
const __dirname = dirname(fileURLToPath(import.meta.url))
const jobs: BreeOptions['jobs'] = [
{
name: 'refresh-token',
interval: 'at 2:00',
},
{
name: 'daily-stand-up',
interval: 'every weekday at 16:42',
},
{
name: 'weekly-randomizer',
interval: 'on Thursday at 17:42',
},
]
const badJob = jobs.findIndex(
(job) =>
typeof job === 'object' &&
'interval' in job &&
// eslint-disable-next-line
later.parse.text(job.interval).error >= 0
)
if (badJob >= 0) {
throw new Error(`Bad interval in job n°${badJob}`)
}
const bree = new Bree({
root: join(__dirname, 'jobs'),
defaultExtension: NODE_ENV === 'production' ? 'js' : 'ts',
jobs,
})
await bree.start()

View File

@ -0,0 +1,50 @@
import { botConfig, serverUrl } from '../config.js'
import { getUserChannels, sendMessage } from '../mattermost.js'
import { initMongodb } from '../mongodb.js'
const mongo = await initMongodb()
const oauth = await mongo.getOAuth()
if (!oauth) {
throw new Error('No OAuth in database')
}
const { accessToken } = oauth
const standupChannel = (
await getUserChannels({ serverUrl, accessToken, userId: 'me' })
).body.find(({ name }) => name === botConfig.channelName)
if (!standupChannel) {
throw new Error('Standup channel not found')
}
const index = new Date().getDay() - 1
const nextDayMember = (await mongo.getWeeklyTeamOrder())?.memberIds[index]
const nextDayStandup = nextDayMember
? `:arrow_forward: Demain, c'est ${nextDayMember} qui anime le stand-up.`
: ''
const now = new Date()
.toLocaleTimeString('fr', {
hour: '2-digit',
minute: '2-digit',
})
.replace(':', 'h')
await sendMessage({
serverUrl,
accessToken,
channelId: standupChannel.id,
message: `
Coucou tout le monde :wave:
Il est ${now}, l'heure des champion·ne·s, ou plutôt celle d'indiquer nos sujets pour le stand-up de demain.
_(Rappel : Je note ici ce dont je suis fier·e, ce sur quoi je bloque, ce que je veux montrer, ce dont j'ai besoin aide, outillage )_
${nextDayStandup}
`,
props: botConfig.messageProps,
})
await mongo.close()

View File

@ -0,0 +1,26 @@
import { clientId, clientSecret, redirectUri, serverUrl } from '../config.js'
import { initMongodb } from '../mongodb.js'
import { refreshAccessToken } from '../oauth.js'
import { snakeToCamelCaseKeys } from '../utils.js'
const mongo = await initMongodb()
const oauth = await mongo.getOAuth()
if (!oauth) {
throw new Error('No OAuth in database')
}
const { refreshToken } = oauth
const newToken = await refreshAccessToken({
serverUrl,
refreshToken,
redirectUri,
clientId,
clientSecret,
})
await mongo.saveOAuth(snakeToCamelCaseKeys(newToken.body))
await mongo.close()

View File

@ -0,0 +1,76 @@
import { botConfig, serverUrl } from '../config.js'
import {
getChannelMembers,
getUser,
getUserChannels,
sendMessage,
} from '../mattermost.js'
import { initMongodb } from '../mongodb.js'
import { shuffleArray, snakeToCamelCaseKeys } from '../utils.js'
const mongo = await initMongodb()
const oauth = await mongo.getOAuth()
if (!oauth) {
throw new Error('No OAuth in database')
}
const { accessToken } = oauth
const standupChannel = (
await getUserChannels({ serverUrl, accessToken, userId: 'me' })
).body.find(({ name }) => name === botConfig.channelName)
if (!standupChannel) {
throw new Error('Standup channel not found')
}
const standupChannelMembers = (
await getChannelMembers({
serverUrl,
accessToken,
channelId: standupChannel.id,
})
).body.map((x) => snakeToCamelCaseKeys(x))
const standupMembers = await Promise.all(
standupChannelMembers.map(({ userId }) =>
getUser({ serverUrl, accessToken, userId }).then(({ body }) =>
snakeToCamelCaseKeys(body)
)
)
)
const shuffleMembers = shuffleArray(standupMembers)
await mongo.setWeeklyTeamOrder(shuffleMembers.map(({ id }) => id))
const nextStandupOrder = botConfig.standupDays
.map((day, i) =>
shuffleMembers[i] ? `- ${day} : @${shuffleMembers[i].username}` : ''
)
.filter(<T>(x: T | null): x is T => x !== null)
.join('\n')
const now = new Date()
.toLocaleTimeString('fr', {
hour: '2-digit',
minute: '2-digit',
})
.replace(':', 'h')
await sendMessage({
serverUrl,
accessToken,
channelId: standupChannel.id,
message: `
Il est ${now}, c'est déja la fin de semaine (ou presque pour certain :smile:) !
Voici l'ordre des animateurs proposé pour le stand-up de la semaine prochaine :
${nextStandupOrder}
`,
props: botConfig.messageProps,
})
await mongo.close()

View File

@ -0,0 +1,179 @@
import got from 'got'
interface MattermostInput {
serverUrl: string
accessToken: string
}
interface MattermostGetUser extends MattermostInput {
userId: string
}
interface MattermostUser {
id: string
create_at: number
update_at: number
delete_at: number
username: string
email: string
email_verified: boolean
nickname: string
first_name: string
last_name: string
roles: string
}
export const getUser = ({
serverUrl,
accessToken,
userId,
}: MattermostGetUser) =>
got.get<MattermostUser>(`${serverUrl}/api/v4/users/${userId}`, {
responseType: 'json',
headers: { Authorization: `Bearer ${accessToken}` },
})
interface MattermostGetUserChannels extends MattermostInput {
userId: string
}
interface MattermostChannel {
id: string
create_at: number
update_at: number
delete_at: number
team_id: string
type: string
display_name: string
name: string
header: string
purpose: string
last_post_at: number
total_msg_count: number
extra_update_at: number
creator_id: string
total_msg_count_root: number
last_root_post_at: number
}
export const getUserChannels = ({
serverUrl,
accessToken,
userId,
}: MattermostGetUserChannels) =>
got.get<MattermostChannel[]>(`${serverUrl}/api/v4/users/${userId}/channels`, {
responseType: 'json',
headers: { Authorization: `Bearer ${accessToken}` },
})
interface MattermostGetChannelMembers extends MattermostInput {
channelId: string
}
interface MattermostChannelMember {
channel_id: string
user_id: string
roles: string
last_viewed_at: number
msg_count: number
mention_count: number
mention_count_root: number
msg_count_root: number
notify_props: unknown
last_update_at: number
scheme_guest: false
scheme_user: boolean
scheme_admin: boolean
explicit_roles: string
}
export const getChannelMembers = ({
serverUrl,
accessToken,
channelId,
}: MattermostGetChannelMembers) =>
got.get<MattermostChannelMember[]>(
`${serverUrl}/api/v4/channels/${channelId}/members`,
{
responseType: 'json',
headers: { Authorization: `Bearer ${accessToken}` },
}
)
interface MattermostPost {
id: string
create_at: number
update_at: number
delete_at: number
is_pinned: false
user_id: string
channel_id: string
root_id: string
original_id: string
message: string
type: string
props: unknown
hashtags: string
pending_post_id: string
reply_count: number
last_reply_at: number
metadata: unknown
}
/* get posts from a channel
interface MattermostGetChannelPosts extends MattermostInput {
channelId: string
}
interface MattermostChannelPost {
order: string[]
posts: { [id: string]: MattermostPost }
next_post_id: string
prev_post_id: string
}
export const getChannelPosts = ({
serverUrl,
accessToken,
channelId,
}: MattermostGetChannelPosts) =>
got.get<MattermostChannelPost>(
`${serverUrl}/api/v4/channels/${channelId}/posts`,
{
responseType: 'json',
headers: { Authorization: `Bearer ${accessToken}` },
}
)
*/
export interface MattermostSendMessage extends MattermostInput {
channelId: string
message: string
props?: {
from_webhook?: 'true'
override_icon_url?: string
override_username?: string
}
rootId?: string
}
export const sendMessage = ({
serverUrl,
accessToken,
channelId,
message,
props,
rootId,
}: MattermostSendMessage) =>
got.post<MattermostPost>(`${serverUrl}/api/v4/posts`, {
json: {
channel_id: channelId,
message,
props,
root_id: rootId,
},
responseType: 'json',
headers: { Authorization: `Bearer ${accessToken}` },
})

View File

@ -0,0 +1,53 @@
import { MongoClient } from 'mongodb'
import { MONGO_URL } from './config.js'
interface OAuthCollection {
accessToken: string
refreshToken: string
}
interface MemberIds {
memberIds: string[]
}
export const initMongodb = async () => {
if (!MONGO_URL) {
throw new Error('MONGO_URL env var is empty')
}
const client = new MongoClient(MONGO_URL)
await client.connect()
const db = client.db('bot')
return {
saveOAuth: ({ accessToken, refreshToken }: OAuthCollection) => {
const collection = db.collection<OAuthCollection>('oauth')
return collection.findOneAndReplace(
{},
{ accessToken, refreshToken },
{ upsert: true }
)
},
getOAuth: () => {
const collection = db.collection<OAuthCollection>('oauth')
return collection.findOne()
},
setWeeklyTeamOrder: (memberIds: string[]) => {
const collection = db.collection<MemberIds>('weeklyTeamOrder')
return collection.findOneAndReplace({}, { memberIds }, { upsert: true })
},
getWeeklyTeamOrder: () => {
const collection = db.collection<MemberIds>('weeklyTeamOrder')
return collection.findOne()
},
close: () => client.close(),
}
}

View File

@ -0,0 +1,67 @@
import got from 'got'
export interface OAuthResponse {
access_token: string
token_type: string
expires_in: number
scope: string
refresh_token: string
id_token: string
}
interface OAuthParams {
serverUrl: string
clientSecret: string
clientId: string
redirectUri: string
}
interface GetOAuthParams extends OAuthParams {
code: string
}
export const getAccessToken = ({
serverUrl,
clientSecret,
clientId,
redirectUri,
code,
}: GetOAuthParams) =>
got.post<OAuthResponse>(`${serverUrl}/oauth/access_token`, {
form: {
client_secret: clientSecret,
client_id: clientId,
redirect_uri: redirectUri,
grant_type: 'authorization_code',
code,
},
responseType: 'json',
throwHttpErrors: true,
})
interface RefreshOAuthParams extends OAuthParams {
serverUrl: string
clientSecret: string
clientId: string
redirectUri: string
refreshToken: string
}
export const refreshAccessToken = ({
serverUrl,
clientSecret,
clientId,
redirectUri,
refreshToken,
}: RefreshOAuthParams) =>
got.post<OAuthResponse>(`${serverUrl}/oauth/access_token`, {
form: {
client_secret: clientSecret,
client_id: clientId,
redirect_uri: redirectUri,
grant_type: 'refresh_token',
refresh_token: refreshToken,
},
responseType: 'json',
throwHttpErrors: true,
})

View File

@ -0,0 +1,81 @@
import cors from '@koa/cors'
import Router from '@koa/router'
import 'dotenv/config'
import Koa from 'koa'
import {
clientId,
clientSecret,
PORT,
redirectUri,
serverUrl,
} from './config.js'
import { initMongodb } from './mongodb.js'
import { getAccessToken } from './oauth.js'
import { snakeToCamelCaseKeys } from './utils.js'
const mongo = await initMongodb()
type KoaState = Koa.DefaultState
type KoaContext = Koa.DefaultContext
const app = new Koa<KoaState, KoaContext>()
const router = new Router<KoaState, KoaContext>()
app.use(cors())
router.get('/connect', (ctx) => {
const url =
`${serverUrl}/oauth/authorize?` +
[
`client_id=${clientId}`,
`redirect_uri=${redirectUri}`,
`response_type=code`,
`state=`,
].join('&')
ctx.redirect(url)
})
router.get('/oauth', async (ctx) => {
const { code, error } = ctx.query
if (error) {
ctx.status = 400
ctx.body = error
return
}
if (typeof code !== 'string') {
ctx.status = 400
ctx.body = 'Bad code'
return
}
try {
const { body } = await getAccessToken({
serverUrl,
clientSecret,
clientId,
redirectUri,
code,
})
await mongo.saveOAuth(snakeToCamelCaseKeys(body))
ctx.status = 200
} catch (err) {
// eslint-disable-next-line no-console
console.error(err)
ctx.status = 400
}
})
app.use(router.routes())
app.use(router.allowedMethods())
app.listen(PORT, () => {
// eslint-disable-next-line no-console
console.log(`app listening on port ${PORT}`)
})

View File

@ -0,0 +1,35 @@
type CamelCase<S extends string> =
S extends `${infer P1}_${infer P2}${infer P3}`
? `${Lowercase<P1>}${Uppercase<P2>}${CamelCase<P3>}`
: Lowercase<S>
const snakeToCamelCase = <T extends string>(str: T) =>
str
.replace(/_/g, ' ')
.replace(/(?<!\p{L})\p{L}|\s+/gu, (m) => (+m === 0 ? '' : m.toUpperCase()))
.replace(/^./, (m) => m?.toLowerCase()) as CamelCase<T>
export type KeysToCamelCase<T> = {
[K in keyof T as CamelCase<string & K>]: T[K]
}
export const snakeToCamelCaseKeys = <T extends object>(object: T) =>
Object.fromEntries(
Object.entries(object).map(
([key, value]) => [snakeToCamelCase(key), value],
{}
)
) as KeysToCamelCase<T>
export const shuffleArray = <T>(array: T[]) => {
const shuffle = [...array]
for (let i = shuffle.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1))
const [shuffleI, shuffleJ] = [shuffle[i], shuffle[j]]
shuffle[i] = shuffleJ
shuffle[j] = shuffleI
}
return shuffle
}

View File

@ -0,0 +1,44 @@
{
"compilerOptions": {
/* Basic Options */
"incremental": true,
"target": "ES2020",
"module": "NodeNext",
"outDir": "dist",
"declaration": true,
/* Strict Type-Checking Options */
"strict": true,
"noImplicitAny": true,
"strictNullChecks": true,
"strictFunctionTypes": true,
"strictBindCallApply": true,
"strictPropertyInitialization": true,
"noImplicitThis": true,
"alwaysStrict": true,
/* Additional Checks */
"noUnusedLocals": true,
"noUnusedParameters": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
/* Module Resolution Options */
"moduleResolution": "NodeNext",
"isolatedModules": true,
"esModuleInterop": true,
"resolveJsonModule": true,
/* Advanced Options */
"forceConsistentCasingInFileNames": true,
// temporary disable lib check waiting a fix for https://github.com/sindresorhus/got/issues/2051
"skipLibCheck": true
},
"ts-node": {
"esm": true,
"files": true
},
"include": ["source", "types/**/*.d.ts"],
"exclude": ["**/node_modules", "**/dist", "vitest.config.ts"]
}

View File

@ -0,0 +1 @@
declare module '@breejs/later'

531
yarn.lock
View File

@ -2909,7 +2909,7 @@ __metadata:
languageName: node
linkType: hard
"@babel/runtime@npm:^7.10.2, @babel/runtime@npm:^7.18.9":
"@babel/runtime@npm:^7.10.2, @babel/runtime@npm:^7.10.5, @babel/runtime@npm:^7.18.9":
version: 7.19.0
resolution: "@babel/runtime@npm:7.19.0"
dependencies:
@ -3068,6 +3068,13 @@ __metadata:
languageName: node
linkType: hard
"@breejs/later@npm:^4.1.0":
version: 4.1.0
resolution: "@breejs/later@npm:4.1.0"
checksum: 0d1c2e06b8b20266ec1aaa09ce96f1b24504d6248a62ac3455a0f46fb9189bae0a5960f962c02cd21dbf9794dd11566e970a8204f02af12f6d6815b32b2d2f1e
languageName: node
linkType: hard
"@bugsnag/browser@npm:^7.17.0":
version: 7.17.0
resolution: "@bugsnag/browser@npm:7.17.0"
@ -3752,6 +3759,15 @@ __metadata:
languageName: node
linkType: hard
"@koa/cors@npm:^3.4.1":
version: 3.4.1
resolution: "@koa/cors@npm:3.4.1"
dependencies:
vary: ^1.1.2
checksum: 8359f19e156f36016ae3f174ef374bd377eee271b29b9106d595f53fb8c80b63d6b8db7471a466fdc68f62f06286722c5351b5463ed2d46fe88256a568045af6
languageName: node
linkType: hard
"@koa/router@npm:^10.1.1":
version: 10.1.1
resolution: "@koa/router@npm:10.1.1"
@ -3765,6 +3781,18 @@ __metadata:
languageName: node
linkType: hard
"@koa/router@npm:^12.0.0":
version: 12.0.0
resolution: "@koa/router@npm:12.0.0"
dependencies:
http-errors: ^2.0.0
koa-compose: ^4.1.0
methods: ^1.1.2
path-to-regexp: ^6.2.1
checksum: 5529629f7517dba20319cf70b66c5a6111673019f6d196cd500a7b90e6663c99848c188f1bce17415d46c7b20b06566d432299a53affe0a15d05b9213917b9f6
languageName: node
linkType: hard
"@mapbox/node-pre-gyp@npm:^1.0.5":
version: 1.0.9
resolution: "@mapbox/node-pre-gyp@npm:1.0.9"
@ -8309,7 +8337,7 @@ __metadata:
languageName: node
linkType: hard
"@types/http-cache-semantics@npm:*":
"@types/http-cache-semantics@npm:*, @types/http-cache-semantics@npm:^4.0.1":
version: 4.0.1
resolution: "@types/http-cache-semantics@npm:4.0.1"
checksum: 1048aacf627829f0d5f00184e16548205cd9f964bf0841c29b36bc504509230c40bc57c39778703a1c965a6f5b416ae2cbf4c1d4589c889d2838dd9dbfccf6e9
@ -8455,6 +8483,22 @@ __metadata:
languageName: node
linkType: hard
"@types/koa@npm:^2.13.5":
version: 2.13.5
resolution: "@types/koa@npm:2.13.5"
dependencies:
"@types/accepts": "*"
"@types/content-disposition": "*"
"@types/cookies": "*"
"@types/http-assert": "*"
"@types/http-errors": "*"
"@types/keygrip": "*"
"@types/koa-compose": "*"
"@types/node": "*"
checksum: e3b634d934b79ce8f394bf4130511596081f9c073dbfb4309aa32e4c421c47049a002b65111f8d9687eabec55d5a27b1b9ae0699afa83894cb7032c3536bfa17
languageName: node
linkType: hard
"@types/koa__cors@npm:^3.3.0":
version: 3.3.0
resolution: "@types/koa__cors@npm:3.3.0"
@ -8464,6 +8508,15 @@ __metadata:
languageName: node
linkType: hard
"@types/koa__router@npm:^12.0.0":
version: 12.0.0
resolution: "@types/koa__router@npm:12.0.0"
dependencies:
"@types/koa": "*"
checksum: ebfee772f7a9c5ff5e296a24443eb2c288fa2e5b8c60afbb460b41f0bd0d68c8a722fff5984eef7b7d90d057fe6f556171695ea83e2cdbeef3e2462f73c362b7
languageName: node
linkType: hard
"@types/koa__router@npm:^8.0.11":
version: 8.0.11
resolution: "@types/koa__router@npm:8.0.11"
@ -8473,6 +8526,13 @@ __metadata:
languageName: node
linkType: hard
"@types/lodash@npm:^4.14.165":
version: 4.14.186
resolution: "@types/lodash@npm:4.14.186"
checksum: ee0c1368a8100bb6efb88335107473a41928fc307ff1ef4ff1278868ccddba9c04c68c36d1ffe3a0392ef4a956e1955f7de3203ec09df4f1655dd1b88485c549
languageName: node
linkType: hard
"@types/lodash@npm:^4.14.167":
version: 4.14.181
resolution: "@types/lodash@npm:4.14.181"
@ -8838,6 +8898,13 @@ __metadata:
languageName: node
linkType: hard
"@types/webidl-conversions@npm:*":
version: 7.0.0
resolution: "@types/webidl-conversions@npm:7.0.0"
checksum: 60142c7ddd9eb6f907d232d6b3a81ecf990f73b5a62a004eba8bd0f54809a42ece68ce512e7e3e1d98af8b6393d66cddb96f3622d2fb223c4e9c8937c61bfed7
languageName: node
linkType: hard
"@types/webpack-env@npm:^1.16.0":
version: 1.16.3
resolution: "@types/webpack-env@npm:1.16.3"
@ -8870,6 +8937,16 @@ __metadata:
languageName: node
linkType: hard
"@types/whatwg-url@npm:^8.2.1":
version: 8.2.2
resolution: "@types/whatwg-url@npm:8.2.2"
dependencies:
"@types/node": "*"
"@types/webidl-conversions": "*"
checksum: 5dc5afe078dfa1a8a266745586fa3db9baa8ce7cc904789211d1dca1d34d7f3dd17d0b7423c36bc9beab9d98aa99338f1fc60798c0af6cbb8356f20e20d9f243
languageName: node
linkType: hard
"@types/yargs-parser@npm:*":
version: 21.0.0
resolution: "@types/yargs-parser@npm:21.0.0"
@ -10977,6 +11054,13 @@ __metadata:
languageName: node
linkType: hard
"boolean@npm:^3.2.0":
version: 3.2.0
resolution: "boolean@npm:3.2.0"
checksum: fb29535b8bf710ef45279677a86d14f5185d604557204abd2ca5fa3fb2a5c80e04d695c8dbf13ab269991977a79bb6c04b048220a6b2a3849853faa94f4a7d77
languageName: node
linkType: hard
"boxen@npm:^5.0.0, boxen@npm:^5.1.2":
version: 5.1.2
resolution: "boxen@npm:5.1.2"
@ -11048,6 +11132,24 @@ __metadata:
languageName: node
linkType: hard
"bree@npm:^9.1.2":
version: 9.1.2
resolution: "bree@npm:9.1.2"
dependencies:
"@breejs/later": ^4.1.0
boolean: ^3.2.0
combine-errors: ^3.0.3
cron-validate: ^1.4.3
human-interval: ^2.0.1
is-string-and-not-blank: ^0.0.2
is-valid-path: ^0.1.1
ms: ^2.1.3
p-wait-for: 3
safe-timers: ^1.1.0
checksum: c23c6f1fc3aa27b33c0649668534806140f8fa0d80991d322304d669993ab1188b097c431b633735cd11ca0a49eff2a8b464d8eb781fcaa8e976b2c1098fc4ed
languageName: node
linkType: hard
"broccoli-node-api@npm:^1.7.0":
version: 1.7.0
resolution: "broccoli-node-api@npm:1.7.0"
@ -11220,6 +11322,15 @@ __metadata:
languageName: node
linkType: hard
"bson@npm:^4.7.0":
version: 4.7.0
resolution: "bson@npm:4.7.0"
dependencies:
buffer: ^5.6.0
checksum: 83e7b64afdad5a505073a7e6206e7b345f59e7888fbcb1948fba72b6101a1baf58b7499314f8e24b650567665f7973eda048aabbb1ddcfbadfba7d6c6b0f5e83
languageName: node
linkType: hard
"buffer-alloc-unsafe@npm:^1.1.0":
version: 1.1.0
resolution: "buffer-alloc-unsafe@npm:1.1.0"
@ -11495,6 +11606,28 @@ __metadata:
languageName: node
linkType: hard
"cacheable-lookup@npm:^7.0.0":
version: 7.0.0
resolution: "cacheable-lookup@npm:7.0.0"
checksum: 9e2856763fc0a7347ab34d704c010440b819d4bb5e3593b664381b7433e942dd22e67ee5581f12256f908e79b82d30b86ebbacf40a081bfe10ee93fbfbc2d6a9
languageName: node
linkType: hard
"cacheable-request@npm:^10.2.1":
version: 10.2.1
resolution: "cacheable-request@npm:10.2.1"
dependencies:
"@types/http-cache-semantics": ^4.0.1
get-stream: ^6.0.1
http-cache-semantics: ^4.1.0
keyv: ^4.5.0
mimic-response: ^4.0.0
normalize-url: ^7.1.0
responselike: ^3.0.0
checksum: 11bcee52d676623fbfe4b02b9f30930457796a7320a5db25392238a92a98185ffa7e87619d82a472c411c7f48eada5ec182bab41e6d849a038e84774dcdbba7d
languageName: node
linkType: hard
"cacheable-request@npm:^2.1.1":
version: 2.1.4
resolution: "cacheable-request@npm:2.1.4"
@ -12330,6 +12463,16 @@ __metadata:
languageName: node
linkType: hard
"combine-errors@npm:^3.0.3":
version: 3.0.3
resolution: "combine-errors@npm:3.0.3"
dependencies:
custom-error-instance: 2.1.1
lodash.uniqby: 4.5.0
checksum: bd0b0d2a4020f9976b8fe8eb7d5aa855b43ecacdcb61ee1fc5664d73ff8c1d7d0bbe4dd948bea7ba1870518bfc5688b89941de7a4967659418b4664cdb02884f
languageName: node
linkType: hard
"combined-stream@npm:^1.0.6, combined-stream@npm:^1.0.8, combined-stream@npm:~1.0.6":
version: 1.0.8
resolution: "combined-stream@npm:1.0.8"
@ -12829,6 +12972,15 @@ __metadata:
languageName: node
linkType: hard
"cron-validate@npm:^1.4.3":
version: 1.4.3
resolution: "cron-validate@npm:1.4.3"
dependencies:
yup: 0.32.9
checksum: beb4ef6ee7a0f07ee815866a621fbb01dd27e090da0ec5ac41c2ce845469af4e0e130adde967dd310839ad9e93db6de4c3c00617baa2fb80fdf78c773977f554
languageName: node
linkType: hard
"cross-fetch@npm:^3.1.5":
version: 3.1.5
resolution: "cross-fetch@npm:3.1.5"
@ -13022,6 +13174,13 @@ __metadata:
languageName: node
linkType: hard
"custom-error-instance@npm:2.1.1":
version: 2.1.1
resolution: "custom-error-instance@npm:2.1.1"
checksum: db01483864c9f4356b720b443a1f9b374758745a75199187a0ccc12505cf822bc801a0d8e3f96d727559880024f40e09667d5c08e5de0bff243c6b5ae0bd303c
languageName: node
linkType: hard
"cyclist@npm:^1.0.1":
version: 1.0.1
resolution: "cyclist@npm:1.0.1"
@ -13576,7 +13735,7 @@ __metadata:
languageName: node
linkType: hard
"denque@npm:^2.0.1":
"denque@npm:^2.0.1, denque@npm:^2.1.0":
version: 2.1.0
resolution: "denque@npm:2.1.0"
checksum: 1d4ae1d05e59ac3a3481e7b478293f4b4c813819342273f3d5b826c7ffa9753c520919ba264f377e09108d24ec6cf0ec0ac729a5686cbb8f32d797126c5dae74
@ -13988,6 +14147,13 @@ __metadata:
languageName: node
linkType: hard
"dotenv@npm:^16.0.3":
version: 16.0.3
resolution: "dotenv@npm:16.0.3"
checksum: afcf03f373d7a6d62c7e9afea6328e62851d627a4e73f2e12d0a8deae1cd375892004f3021883f8aec85932cd2834b091f568ced92b4774625b321db83b827f8
languageName: node
linkType: hard
"dotenv@npm:^8.0.0":
version: 8.6.0
resolution: "dotenv@npm:8.6.0"
@ -16408,7 +16574,7 @@ __metadata:
languageName: node
linkType: hard
"form-data-encoder@npm:^2.1.0":
"form-data-encoder@npm:^2.1.0, form-data-encoder@npm:^2.1.2":
version: 2.1.2
resolution: "form-data-encoder@npm:2.1.2"
checksum: 5c6401e3ebd2ba2adfa151c9fbd1df5adae8b1dd7bca5b18ab25ad1f9b83e20ddffb6b9ff77f5006b93d7ec2032e22828c9543c0bd4b2bc5b05335c31a3ba5b9
@ -17212,6 +17378,25 @@ __metadata:
languageName: node
linkType: hard
"got@npm:^12.5.1":
version: 12.5.1
resolution: "got@npm:12.5.1"
dependencies:
"@sindresorhus/is": ^5.2.0
"@szmarczak/http-timer": ^5.0.1
cacheable-lookup: ^7.0.0
cacheable-request: ^10.2.1
decompress-response: ^6.0.0
form-data-encoder: ^2.1.2
get-stream: ^6.0.1
http2-wrapper: ^2.1.10
lowercase-keys: ^3.0.0
p-cancelable: ^3.0.0
responselike: ^3.0.0
checksum: 479a279e8f0ba39270d500e8998dda897c850a9f43eef716c58fcaa7b5049e74ca3fd8ab70be1e2a59a5c8b59a83b9deab16d4e523423bb1e2dfe17401750efa
languageName: node
linkType: hard
"got@npm:^8.3.1":
version: 8.3.2
resolution: "got@npm:8.3.2"
@ -17796,7 +17981,7 @@ __metadata:
languageName: node
linkType: hard
"http-errors@npm:2.0.0":
"http-errors@npm:2.0.0, http-errors@npm:^2.0.0":
version: 2.0.0
resolution: "http-errors@npm:2.0.0"
dependencies:
@ -17912,6 +18097,15 @@ __metadata:
languageName: node
linkType: hard
"human-interval@npm:^2.0.1":
version: 2.0.1
resolution: "human-interval@npm:2.0.1"
dependencies:
numbered: ^1.1.0
checksum: 8f1b37485f554d1f7a3fa2cefdbd9cee2df3ff2cfb86ae1db9f58f2db9d524d44863c2d291f04c810317f2fa7ceeda2188281985c7d65b3774d53c9e835ed55c
languageName: node
linkType: hard
"human-signals@npm:^1.1.1":
version: 1.1.1
resolution: "human-signals@npm:1.1.1"
@ -18319,6 +18513,13 @@ __metadata:
languageName: node
linkType: hard
"ip@npm:^2.0.0":
version: 2.0.0
resolution: "ip@npm:2.0.0"
checksum: cfcfac6b873b701996d71ec82a7dd27ba92450afdb421e356f44044ed688df04567344c36cbacea7d01b1c39a4c732dc012570ebe9bebfb06f27314bca625349
languageName: node
linkType: hard
"ipaddr.js@npm:1.9.1":
version: 1.9.1
resolution: "ipaddr.js@npm:1.9.1"
@ -18976,6 +19177,22 @@ __metadata:
languageName: node
linkType: hard
"is-string-and-not-blank@npm:^0.0.2":
version: 0.0.2
resolution: "is-string-and-not-blank@npm:0.0.2"
dependencies:
is-string-blank: ^1.0.1
checksum: 9b0fff4f0974ffaceb382dcf012587d1ad5d5013d7260a4e85621b67fbcb29ca906bcd607fe71bdd72c642f7b56b5b9e779f9d54224b826da9aa48b2003b6113
languageName: node
linkType: hard
"is-string-blank@npm:^1.0.1":
version: 1.0.1
resolution: "is-string-blank@npm:1.0.1"
checksum: 00a0955c2bac08cc84f9f878d2a3fdba86997ac23c0b661e50f39efba635444d9cec84237337200be9a4e07234069318498592817614525cd959ae0d43df2151
languageName: node
linkType: hard
"is-string@npm:^1.0.5, is-string@npm:^1.0.7":
version: 1.0.7
resolution: "is-string@npm:1.0.7"
@ -19772,6 +19989,15 @@ __metadata:
languageName: node
linkType: hard
"keyv@npm:^4.5.0":
version: 4.5.0
resolution: "keyv@npm:4.5.0"
dependencies:
json-buffer: 3.0.1
checksum: d294873cf88ec8f691e5edeb7b4b884f886c5f021a01902a0e243c362449db2b55419d7fb7187d059add747b7398321e39e44d391b65f94935174ce13452714d
languageName: node
linkType: hard
"kind-of@npm:^3.0.2, kind-of@npm:^3.0.3, kind-of@npm:^3.2.0":
version: 3.2.2
resolution: "kind-of@npm:3.2.2"
@ -20218,6 +20444,62 @@ __metadata:
languageName: node
linkType: hard
"lodash-es@npm:^4.17.15":
version: 4.17.21
resolution: "lodash-es@npm:4.17.21"
checksum: 05cbffad6e2adbb331a4e16fbd826e7faee403a1a04873b82b42c0f22090f280839f85b95393f487c1303c8a3d2a010048bf06151a6cbe03eee4d388fb0a12d2
languageName: node
linkType: hard
"lodash._baseiteratee@npm:~4.7.0":
version: 4.7.0
resolution: "lodash._baseiteratee@npm:4.7.0"
dependencies:
lodash._stringtopath: ~4.8.0
checksum: 814a7125b9e2fa7e436c4402eae842a200189e2839b56bd6cde7cd0a3628b60842f5d39a9f5dceaf8766669b2e4a17a36ce2a213d1d6a891c1bef8a6bda36ea9
languageName: node
linkType: hard
"lodash._basetostring@npm:~4.12.0":
version: 4.12.0
resolution: "lodash._basetostring@npm:4.12.0"
checksum: ccaf83827f86be5c9daeb7b939f761d6a43f0de0781bc3b6772fcb8568fbcbfa1e1082c66e5e12dd23e00ac40a18349c5a793a6a552e3574cbbcb3e1545fcb4c
languageName: node
linkType: hard
"lodash._baseuniq@npm:~4.6.0":
version: 4.6.0
resolution: "lodash._baseuniq@npm:4.6.0"
dependencies:
lodash._createset: ~4.0.0
lodash._root: ~3.0.0
checksum: 8c16fe2e80716b18c2f28bbcc902768141d432b0b98e03b30a2fba6a097377fabdc8753da232568375d2aa9502dc6b3a390200aa1467d2f685a582a46a271936
languageName: node
linkType: hard
"lodash._createset@npm:~4.0.0":
version: 4.0.3
resolution: "lodash._createset@npm:4.0.3"
checksum: fb4450fbf4846aa7b420837ee44400b88664e28499388b7e04b4db38adca1305915f68a245fb2a87e031e7f440b997de4f360de6dea2712952520e97c7898de1
languageName: node
linkType: hard
"lodash._root@npm:~3.0.0":
version: 3.0.1
resolution: "lodash._root@npm:3.0.1"
checksum: 3e12c6f409ae13164a8db358f44a691f1e038dad4e25463802980d0ed641ed118c147b65657501c51778c885422b913264dfbe33ec0c5d676443dd630a7e685a
languageName: node
linkType: hard
"lodash._stringtopath@npm:~4.8.0":
version: 4.8.0
resolution: "lodash._stringtopath@npm:4.8.0"
dependencies:
lodash._basetostring: ~4.12.0
checksum: 00663b317796333e6315ebb4e8b590e68845de10d5d25c7585751fd9d28adf3e60e1ce85a6fbb6a0d440447c841465b91877e761239e358231eed2f52f0a5472
languageName: node
linkType: hard
"lodash.camelcase@npm:^4.3.0":
version: 4.3.0
resolution: "lodash.camelcase@npm:4.3.0"
@ -20372,6 +20654,16 @@ __metadata:
languageName: node
linkType: hard
"lodash.uniqby@npm:4.5.0":
version: 4.5.0
resolution: "lodash.uniqby@npm:4.5.0"
dependencies:
lodash._baseiteratee: ~4.7.0
lodash._baseuniq: ~4.6.0
checksum: 40a4fdd4c31323fcb6db91ec3124020333212ca1f13e75cc9939decdd33e8b176d204fb277be36a51a855c2c90e14d67932b3b130b2f0eedc729e4cb9cdcaed1
languageName: node
linkType: hard
"lodash@npm:^4.17.11, lodash@npm:^4.17.12, lodash@npm:^4.17.13, lodash@npm:^4.17.15, lodash@npm:^4.17.19, lodash@npm:^4.17.20, lodash@npm:^4.17.21":
version: 4.17.21
resolution: "lodash@npm:4.17.21"
@ -20897,6 +21189,13 @@ __metadata:
languageName: node
linkType: hard
"memory-pager@npm:^1.0.2":
version: 1.5.0
resolution: "memory-pager@npm:1.5.0"
checksum: d1a2e684583ef55c61cd3a49101da645b11ad57014dfc565e0b43baa9004b743f7e4ab81493d8fff2ab24e9950987cc3209c94bcc4fc8d7e30a475489a1f15e9
languageName: node
linkType: hard
"meow@npm:^3.1.0":
version: 3.7.0
resolution: "meow@npm:3.7.0"
@ -21092,6 +21391,13 @@ __metadata:
languageName: node
linkType: hard
"mimic-response@npm:^4.0.0":
version: 4.0.0
resolution: "mimic-response@npm:4.0.0"
checksum: 33b804cc961efe206efdb1fca6a22540decdcfce6c14eb5c0c50e5ae9022267ab22ce8f5568b1f7247ba67500fe20d523d81e0e9f009b321ccd9d472e78d1850
languageName: node
linkType: hard
"min-document@npm:^2.19.0":
version: 2.19.0
resolution: "min-document@npm:2.19.0"
@ -21306,6 +21612,32 @@ __metadata:
languageName: node
linkType: hard
"mongodb-connection-string-url@npm:^2.5.3":
version: 2.5.4
resolution: "mongodb-connection-string-url@npm:2.5.4"
dependencies:
"@types/whatwg-url": ^8.2.1
whatwg-url: ^11.0.0
checksum: 9f431826b229488808e4a8a9e6bdde0162be3e6d5cad40867b69b2199ce009f568b67dc1bf587a43367904d8184f1c68689f7ea6574ed40b396726abde9485e1
languageName: node
linkType: hard
"mongodb@npm:^4.10.0":
version: 4.10.0
resolution: "mongodb@npm:4.10.0"
dependencies:
bson: ^4.7.0
denque: ^2.1.0
mongodb-connection-string-url: ^2.5.3
saslprep: ^1.0.3
socks: ^2.7.0
dependenciesMeta:
saslprep:
optional: true
checksum: 4847fe69b6d3baddc440936d306b4d00fa40a1dafabd387f9fb6f3ecd63b27c41f11b2cc46774ac2bf17e9b508d35908ebe21f47badf3449fb7afcbde2733951
languageName: node
linkType: hard
"moo@npm:^0.5.0, moo@npm:^0.5.1":
version: 0.5.1
resolution: "moo@npm:0.5.1"
@ -21357,7 +21689,7 @@ __metadata:
languageName: node
linkType: hard
"ms@npm:2.1.3, ms@npm:^2.0.0, ms@npm:^2.1.1":
"ms@npm:2.1.3, ms@npm:^2.0.0, ms@npm:^2.1.1, ms@npm:^2.1.3":
version: 2.1.3
resolution: "ms@npm:2.1.3"
checksum: aa92de608021b242401676e35cfa5aa42dd70cbdc082b916da7fb925c542173e36bce97ea3e804923fe92c0ad991434e4a38327e15a1b5b5f945d66df615ae6d
@ -21398,6 +21730,13 @@ __metadata:
languageName: node
linkType: hard
"nanoclone@npm:^0.2.1":
version: 0.2.1
resolution: "nanoclone@npm:0.2.1"
checksum: 96b2954e22f70561f41e20d69856266c65583c2a441dae108f1dc71b716785d2c8038dac5f1d5e92b117aed3825f526b53139e2e5d6e6db8a77cfa35b3b8bf40
languageName: node
linkType: hard
"nanoid@npm:^3.3.4":
version: 3.3.4
resolution: "nanoid@npm:3.3.4"
@ -21852,6 +22191,26 @@ __metadata:
languageName: node
linkType: hard
"nodemon@npm:^2.0.20":
version: 2.0.20
resolution: "nodemon@npm:2.0.20"
dependencies:
chokidar: ^3.5.2
debug: ^3.2.7
ignore-by-default: ^1.0.1
minimatch: ^3.1.2
pstree.remy: ^1.1.8
semver: ^5.7.1
simple-update-notifier: ^1.0.7
supports-color: ^5.5.0
touch: ^3.1.0
undefsafe: ^2.0.5
bin:
nodemon: bin/nodemon.js
checksum: 9fe858682414fe703179f4fe36c86e71f40d2693b5345c09803d7b191816a6589c5df8f1f9873bffee92893880183b95a031c86340e46b364ef1b0b7f619edbf
languageName: node
linkType: hard
"noop2@npm:^2.0.0":
version: 2.0.0
resolution: "noop2@npm:2.0.0"
@ -21974,6 +22333,13 @@ __metadata:
languageName: node
linkType: hard
"normalize-url@npm:^7.1.0":
version: 7.2.0
resolution: "normalize-url@npm:7.2.0"
checksum: 7753f081ee997520c9cd855f06975d7ac24b1ef58002e310d5058c831b9a6165ec2ec9fc0c5bc9e886e1257affaffa7c36731ae39073fcf74af07197997d4fb6
languageName: node
linkType: hard
"now-and-later@npm:^2.0.0":
version: 2.0.1
resolution: "now-and-later@npm:2.0.1"
@ -22064,6 +22430,13 @@ __metadata:
languageName: node
linkType: hard
"numbered@npm:^1.1.0":
version: 1.1.0
resolution: "numbered@npm:1.1.0"
checksum: cdc238990fe29818cb603ac8d4050ff82a05b63e10d8848d1ff1e315231e94813c48b405e651b22d32edc8ccf1f323920d1182ea02c081f11d94ea22b1f8c17a
languageName: node
linkType: hard
"object-assign@npm:^4.0.1, object-assign@npm:^4.1.0, object-assign@npm:^4.1.1":
version: 4.1.1
resolution: "object-assign@npm:4.1.1"
@ -22725,7 +23098,7 @@ __metadata:
languageName: node
linkType: hard
"p-wait-for@npm:^3.0.0":
"p-wait-for@npm:3, p-wait-for@npm:^3.0.0":
version: 3.2.0
resolution: "p-wait-for@npm:3.2.0"
dependencies:
@ -23027,7 +23400,7 @@ __metadata:
languageName: node
linkType: hard
"path-to-regexp@npm:^6.1.0":
"path-to-regexp@npm:^6.1.0, path-to-regexp@npm:^6.2.1":
version: 6.2.1
resolution: "path-to-regexp@npm:6.2.1"
checksum: f0227af8284ea13300f4293ba111e3635142f976d4197f14d5ad1f124aebd9118783dd2e5f1fe16f7273743cc3dbeddfb7493f237bb27c10fdae07020cc9b698
@ -23597,6 +23970,13 @@ __metadata:
languageName: node
linkType: hard
"property-expr@npm:^2.0.4":
version: 2.0.5
resolution: "property-expr@npm:2.0.5"
checksum: 4ebe82ce45aaf1527e96e2ab84d75d25217167ec3ff6378cf83a84fb4abc746e7c65768a79d275881602ae82f168f9a6dfaa7f5e331d0fcc83d692770bcce5f1
languageName: node
linkType: hard
"property-information@npm:^5.0.0, property-information@npm:^5.3.0":
version: 5.6.0
resolution: "property-information@npm:5.6.0"
@ -25346,6 +25726,13 @@ __metadata:
languageName: node
linkType: hard
"safe-timers@npm:^1.1.0":
version: 1.1.0
resolution: "safe-timers@npm:1.1.0"
checksum: 6387c1e09fae12c4b96fb62e2575ace9ec6b1f73ad73d937e0ecc79de92cb64e56dbbfa60a8d5d7c54c035960457fa59cffd5d6b396fe0d82ed8042c889a7f1a
languageName: node
linkType: hard
"safer-buffer@npm:>= 2.1.2 < 3, safer-buffer@npm:>= 2.1.2 < 3.0.0, safer-buffer@npm:^2.0.2, safer-buffer@npm:^2.1.0, safer-buffer@npm:~2.1.0":
version: 2.1.2
resolution: "safer-buffer@npm:2.1.2"
@ -25372,6 +25759,15 @@ __metadata:
languageName: node
linkType: hard
"saslprep@npm:^1.0.3":
version: 1.0.3
resolution: "saslprep@npm:1.0.3"
dependencies:
sparse-bitfield: ^3.0.3
checksum: 4fdc0b70fb5e523f977de405e12cca111f1f10dd68a0cfae0ca52c1a7919a94d1556598ba2d35f447655c3b32879846c77f9274c90806f6673248ae3cea6ee43
languageName: node
linkType: hard
"sax@npm:>=0.6.0":
version: 1.2.4
resolution: "sax@npm:1.2.4"
@ -25473,7 +25869,7 @@ __metadata:
languageName: node
linkType: hard
"semver@npm:7.0.0":
"semver@npm:7.0.0, semver@npm:~7.0.0":
version: 7.0.0
resolution: "semver@npm:7.0.0"
bin:
@ -25709,6 +26105,15 @@ __metadata:
languageName: node
linkType: hard
"simple-update-notifier@npm:^1.0.7":
version: 1.0.7
resolution: "simple-update-notifier@npm:1.0.7"
dependencies:
semver: ~7.0.0
checksum: aaadc1f158ad5101b363d1c7aed1f30fc1cac59a760aa31702633e0e6fe423348f07d0e78185aef0aad29130a7b7f0f188c21c7bc7353f897a0ea3682e051a70
languageName: node
linkType: hard
"sisteransi@npm:^1.0.5":
version: 1.0.5
resolution: "sisteransi@npm:1.0.5"
@ -25948,6 +26353,16 @@ __metadata:
languageName: node
linkType: hard
"socks@npm:^2.7.0":
version: 2.7.1
resolution: "socks@npm:2.7.1"
dependencies:
ip: ^2.0.0
smart-buffer: ^4.2.0
checksum: 259d9e3e8e1c9809a7f5c32238c3d4d2a36b39b83851d0f573bfde5f21c4b1288417ce1af06af1452569cd1eb0841169afd4998f0e04ba04656f6b7f0e46d748
languageName: node
linkType: hard
"sort-keys-length@npm:^1.0.0":
version: 1.0.1
resolution: "sort-keys-length@npm:1.0.1"
@ -26081,6 +26496,15 @@ __metadata:
languageName: node
linkType: hard
"sparse-bitfield@npm:^3.0.3":
version: 3.0.3
resolution: "sparse-bitfield@npm:3.0.3"
dependencies:
memory-pager: ^1.0.2
checksum: 174da88dbbcc783d5dbd26921931cc83830280b8055fb05333786ebe6fc015b9601b24972b3d55920dd2d9f5fb120576fbfa2469b08e5222c9cadf3f05210aab
languageName: node
linkType: hard
"spdx-correct@npm:^3.0.0":
version: 3.1.1
resolution: "spdx-correct@npm:3.1.1"
@ -26232,6 +26656,27 @@ __metadata:
languageName: node
linkType: hard
"standup-mattermost-bot@workspace:standup-mattermost-bot":
version: 0.0.0-use.local
resolution: "standup-mattermost-bot@workspace:standup-mattermost-bot"
dependencies:
"@breejs/later": ^4.1.0
"@koa/cors": ^3.4.1
"@koa/router": ^12.0.0
"@types/koa": ^2.13.5
"@types/koa__cors": ^3.3.0
"@types/koa__router": ^12.0.0
bree: ^9.1.2
dotenv: ^16.0.3
got: ^12.5.1
koa: ^2.13.4
mongodb: ^4.10.0
nodemon: ^2.0.20
ts-node: ^10.9.1
typescript: ^4.8.4
languageName: unknown
linkType: soft
"state-toggle@npm:^1.0.0":
version: 1.0.3
resolution: "state-toggle@npm:1.0.3"
@ -27379,6 +27824,13 @@ __metadata:
languageName: node
linkType: hard
"toposort@npm:^2.0.2":
version: 2.0.2
resolution: "toposort@npm:2.0.2"
checksum: d64c74b570391c9432873f48e231b439ee56bc49f7cb9780b505cfdf5cb832f808d0bae072515d93834dd6bceca5bb34448b5b4b408335e4d4716eaf68195dcb
languageName: node
linkType: hard
"tosource@npm:^1.0.0":
version: 1.0.0
resolution: "tosource@npm:1.0.0"
@ -27416,6 +27868,15 @@ __metadata:
languageName: node
linkType: hard
"tr46@npm:^3.0.0":
version: 3.0.0
resolution: "tr46@npm:3.0.0"
dependencies:
punycode: ^2.1.1
checksum: 44c3cc6767fb800490e6e9fd64fd49041aa4e49e1f6a012b34a75de739cc9ed3a6405296072c1df8b6389ae139c5e7c6496f659cfe13a04a4bff3a1422981270
languageName: node
linkType: hard
"tr46@npm:~0.0.3":
version: 0.0.3
resolution: "tr46@npm:0.0.3"
@ -27787,6 +28248,16 @@ __metadata:
languageName: node
linkType: hard
"typescript@npm:^4.8.4":
version: 4.8.4
resolution: "typescript@npm:4.8.4"
bin:
tsc: bin/tsc
tsserver: bin/tsserver
checksum: 3e4f061658e0c8f36c820802fa809e0fd812b85687a9a2f5430bc3d0368e37d1c9605c3ce9b39df9a05af2ece67b1d844f9f6ea8ff42819f13bcb80f85629af0
languageName: node
linkType: hard
"typescript@patch:typescript@^4.2.4#~builtin<compat/typescript>, typescript@patch:typescript@^4.5.4#~builtin<compat/typescript>, typescript@patch:typescript@^4.5.5#~builtin<compat/typescript>":
version: 4.7.4
resolution: "typescript@patch:typescript@npm%3A4.7.4#~builtin<compat/typescript>::version=4.7.4&hash=a1c5e5"
@ -27807,6 +28278,16 @@ __metadata:
languageName: node
linkType: hard
"typescript@patch:typescript@^4.8.4#~builtin<compat/typescript>":
version: 4.8.4
resolution: "typescript@patch:typescript@npm%3A4.8.4#~builtin<compat/typescript>::version=4.8.4&hash=a1c5e5"
bin:
tsc: bin/tsc
tsserver: bin/tsserver
checksum: 563a0ef47abae6df27a9a3ab38f75fc681f633ccf1a3502b1108e252e187787893de689220f4544aaf95a371a4eb3141e4a337deb9895de5ac3c1ca76430e5f0
languageName: node
linkType: hard
"uglify-js@npm:^3.1.4":
version: 3.16.2
resolution: "uglify-js@npm:3.16.2"
@ -28854,6 +29335,13 @@ __metadata:
languageName: node
linkType: hard
"webidl-conversions@npm:^7.0.0":
version: 7.0.0
resolution: "webidl-conversions@npm:7.0.0"
checksum: f05588567a2a76428515333eff87200fae6c83c3948a7482ebb109562971e77ef6dc49749afa58abb993391227c5697b3ecca52018793e0cb4620a48f10bd21b
languageName: node
linkType: hard
"webpack-dev-middleware@npm:^3.7.3":
version: 3.7.3
resolution: "webpack-dev-middleware@npm:3.7.3"
@ -29015,6 +29503,16 @@ __metadata:
languageName: node
linkType: hard
"whatwg-url@npm:^11.0.0":
version: 11.0.0
resolution: "whatwg-url@npm:11.0.0"
dependencies:
tr46: ^3.0.0
webidl-conversions: ^7.0.0
checksum: ed4826aaa57e66bb3488a4b25c9cd476c46ba96052747388b5801f137dd740b73fde91ad207d96baf9f17fbcc80fc1a477ad65181b5eb5fa718d27c69501d7af
languageName: node
linkType: hard
"whatwg-url@npm:^5.0.0":
version: 5.0.0
resolution: "whatwg-url@npm:5.0.0"
@ -29655,6 +30153,21 @@ __metadata:
languageName: node
linkType: hard
"yup@npm:0.32.9":
version: 0.32.9
resolution: "yup@npm:0.32.9"
dependencies:
"@babel/runtime": ^7.10.5
"@types/lodash": ^4.14.165
lodash: ^4.17.20
lodash-es: ^4.17.15
nanoclone: ^0.2.1
property-expr: ^2.0.4
toposort: ^2.0.2
checksum: 3f33850913a237fb7e59b0b5c71d2cc6bdb1d6b2b01fc24c53ec68b35ad2b95cd49f735532117136495cb57f0ec58f0a7e1f1c55fad685555c7114155170f1ea
languageName: node
linkType: hard
"z-schema@npm:^5.0.1, z-schema@npm:~5.0.2":
version: 5.0.3
resolution: "z-schema@npm:5.0.3"