mirror of
https://github.com/linux-odyssey/linux-odyssey.git
synced 2026-11-05 19:20:12 +08:00
24 files changed
+391
-148
No files matched your search
@@ -13,7 +13,8 @@
|
||||
"@linux-odyssey/models": "*",
|
||||
"express": "^4.18.2",
|
||||
"express-basic-auth": "^1.2.1",
|
||||
"express-handlebars": "^7.1.2"
|
||||
"express-handlebars": "^7.1.2",
|
||||
"mongoose": "^8.0.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"nodemon": "^3.0.1"
|
||||
|
||||
Whitespace-only changes.
@@ -1,9 +1,24 @@
|
||||
/* eslint-disable object-shorthand */
|
||||
import Pagination from '../models/pagination.js'
|
||||
import { errorCommands } from '../models/commands.js'
|
||||
|
||||
// eslint-disable-next-line import/prefer-default-export
|
||||
export async function commandListController(req, res) {
|
||||
const payload = {
|
||||
errorCommands: await errorCommands(),
|
||||
const { nextKey, order } = req.query
|
||||
const itemsPerPage = 100
|
||||
|
||||
try {
|
||||
const pagination = new Pagination(order, itemsPerPage, nextKey)
|
||||
const payload = await errorCommands(pagination)
|
||||
const newNextKey = payload[payload.length - 1]?._id
|
||||
|
||||
res.render('commands', {
|
||||
errorCommands: payload,
|
||||
nextKey: newNextKey,
|
||||
order: pagination.getOrder(),
|
||||
})
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
res.status(500).send('Error fetching data')
|
||||
}
|
||||
res.render('commands', payload)
|
||||
}
|
||||
@@ -1,15 +1,24 @@
|
||||
import { userCount } from '../models/users.js'
|
||||
import { sessionCount, sessionCompleted } from '../models/sessions.js'
|
||||
import { questList } from '../models/quests.js'
|
||||
|
||||
// eslint-disable-next-line import/prefer-default-export
|
||||
export async function homeController(req, res) {
|
||||
const quests = await questList()
|
||||
const [totalQuests, totalCompleted] = quests.reduce(
|
||||
([total, completed], quest) => [
|
||||
total + quest.started,
|
||||
completed + quest.completed,
|
||||
],
|
||||
[0, 0]
|
||||
)
|
||||
|
||||
const payload = {
|
||||
title: 'Linux Odyssey Admin',
|
||||
userCount: await userCount(),
|
||||
sessionCount: await sessionCount(),
|
||||
sessionCompleted: await sessionCompleted(),
|
||||
totalQuests,
|
||||
totalCompleted,
|
||||
}
|
||||
payload.completedRate =
|
||||
Math.round((payload.sessionCompleted / payload.sessionCount) * 10000) / 100
|
||||
Math.round((payload.totalCompleted / payload.totalQuests) * 10000) / 100
|
||||
res.render('home', payload)
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
import { questList } from '../models/quests.js'
|
||||
|
||||
// eslint-disable-next-line import/prefer-default-export
|
||||
export async function questListController(req, res) {
|
||||
const quests = await questList()
|
||||
quests.forEach((quest) => {
|
||||
quest.failed = quest.started - quest.completed
|
||||
})
|
||||
res.render('quests', { quests })
|
||||
}
|
||||
@@ -1,8 +1,24 @@
|
||||
import Pagination from '../models/pagination.js'
|
||||
import { sessionList, sessionDetail } from '../models/sessions.js'
|
||||
|
||||
export async function sessionListController(req, res) {
|
||||
const sessions = await sessionList()
|
||||
res.render('sessions', { sessions })
|
||||
const { nextKey, order } = req.query
|
||||
const itemsPerPage = 50
|
||||
|
||||
try {
|
||||
const pagination = new Pagination(order, itemsPerPage, nextKey)
|
||||
const sessions = await sessionList(pagination)
|
||||
const newNextKey = sessions[sessions.length - 1]?._id
|
||||
|
||||
res.render('sessions', {
|
||||
sessions,
|
||||
nextKey: newNextKey,
|
||||
order: pagination.getOrder(),
|
||||
})
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
res.status(500).send('Error fetching session data')
|
||||
}
|
||||
}
|
||||
|
||||
export async function sessionDetailController(req, res) {
|
||||
|
||||
@@ -1,6 +1,22 @@
|
||||
import Pagination from '../models/pagination.js'
|
||||
import { userList } from '../models/users.js'
|
||||
|
||||
// eslint-disable-next-line import/prefer-default-export
|
||||
export async function userListController(req, res) {
|
||||
res.render('users', { users: await userList() })
|
||||
const { nextKey, order } = req.query
|
||||
const itemsPerPage = 50
|
||||
|
||||
try {
|
||||
const pagination = new Pagination(order, itemsPerPage, nextKey)
|
||||
const users = await userList(pagination)
|
||||
const newNextKey = users[users.length - 1]?._id
|
||||
|
||||
res.render('users', {
|
||||
users,
|
||||
nextKey: newNextKey,
|
||||
order: pagination.getOrder(),
|
||||
})
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
res.status(500).send('Error fetching user data')
|
||||
}
|
||||
}
|
||||
@@ -1,22 +1,44 @@
|
||||
import { Command } from '@linux-odyssey/models'
|
||||
|
||||
// eslint-disable-next-line import/prefer-default-export
|
||||
export async function errorCommands() {
|
||||
const commands = await Command.find({
|
||||
$and: [
|
||||
{ error: { $exists: true } },
|
||||
{ error: { $ne: null } },
|
||||
{ error: { $ne: '' } },
|
||||
],
|
||||
})
|
||||
.populate({
|
||||
path: 'session',
|
||||
populate: { path: 'user' },
|
||||
})
|
||||
.exec()
|
||||
return commands.map(({ command, error, createdAt, session }) => {
|
||||
export async function errorCommands(pagination) {
|
||||
const commands = await Command.aggregate([
|
||||
pagination.match('_id'),
|
||||
{
|
||||
$match: {
|
||||
$and: [
|
||||
{ error: { $exists: true } },
|
||||
{ error: { $ne: null } },
|
||||
{ error: { $ne: '' } },
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
$lookup: {
|
||||
from: 'sessions', // 替換成 'session' 對應的集合名稱
|
||||
localField: 'session', // 替換成 'session' 對應的字段名稱
|
||||
foreignField: '_id',
|
||||
as: 'session',
|
||||
},
|
||||
},
|
||||
{ $unwind: '$session' },
|
||||
{
|
||||
$lookup: {
|
||||
from: 'users', // 替換成 'user' 對應的集合名稱
|
||||
localField: 'session.user', // 替換成 'user' 對應的字段名稱
|
||||
foreignField: '_id',
|
||||
as: 'session.user',
|
||||
},
|
||||
},
|
||||
{ $unwind: '$session.user' },
|
||||
pagination.sort('_id'),
|
||||
pagination.limit(),
|
||||
])
|
||||
|
||||
return commands.map(({ _id, command, error, createdAt, session }) => {
|
||||
const { user, quest } = session
|
||||
return {
|
||||
_id,
|
||||
command: command.slice(0, 20),
|
||||
error: error.slice(0, 50),
|
||||
createdAt: createdAt?.toLocaleString(),
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
/* eslint-disable lines-between-class-members */
|
||||
/* eslint-disable class-methods-use-this */
|
||||
// eslint-disable-next-line max-classes-per-file
|
||||
import mongoose from 'mongoose'
|
||||
|
||||
export const DESC = 'desc'
|
||||
export const ASC = 'asc'
|
||||
|
||||
class Asc {
|
||||
getOperator() {
|
||||
return '$gt'
|
||||
}
|
||||
|
||||
getOrder() {
|
||||
return 1
|
||||
}
|
||||
|
||||
getName() {
|
||||
return ASC
|
||||
}
|
||||
}
|
||||
|
||||
class Desc {
|
||||
getOperator() {
|
||||
return '$lt'
|
||||
}
|
||||
|
||||
getOrder() {
|
||||
return -1
|
||||
}
|
||||
|
||||
getName() {
|
||||
return DESC
|
||||
}
|
||||
}
|
||||
|
||||
export default class Pagination {
|
||||
nextKey = null
|
||||
itemsPerPage = 50
|
||||
order = null
|
||||
|
||||
constructor(order, itemsPerPage = 50, nextKey = null) {
|
||||
this.itemsPerPage = itemsPerPage
|
||||
if (!order || order === DESC) {
|
||||
this.order = new Desc()
|
||||
} else if (order === ASC) {
|
||||
this.order = new Asc()
|
||||
} else {
|
||||
throw new Error('order must be asc or desc')
|
||||
}
|
||||
if (nextKey) {
|
||||
this.nextKey = new mongoose.Types.ObjectId(nextKey)
|
||||
}
|
||||
}
|
||||
|
||||
match(field) {
|
||||
const stage = this.nextKey
|
||||
? { [field]: { [this.order.getOperator()]: this.nextKey } }
|
||||
: {}
|
||||
return { $match: stage }
|
||||
}
|
||||
|
||||
sort(field) {
|
||||
return { $sort: { [field]: this.order.getOrder() } }
|
||||
}
|
||||
|
||||
limit() {
|
||||
return { $limit: this.itemsPerPage }
|
||||
}
|
||||
|
||||
getOrder() {
|
||||
return this.order.getName()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/* eslint-disable object-shorthand */
|
||||
/* eslint-disable func-names */
|
||||
import { UserProfile } from '@linux-odyssey/models'
|
||||
|
||||
export function questList() {
|
||||
return UserProfile.aggregate([
|
||||
{
|
||||
$project: {
|
||||
progress: {
|
||||
$objectToArray: '$progress',
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
$unwind: '$progress',
|
||||
},
|
||||
{
|
||||
$group: {
|
||||
_id: '$progress.v.quest',
|
||||
started: {
|
||||
$sum: 1,
|
||||
},
|
||||
completed: {
|
||||
$sum: {
|
||||
$cond: {
|
||||
if: { $eq: ['$progress.v.completed', true] },
|
||||
then: 1,
|
||||
else: 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
$project: {
|
||||
_id: 1,
|
||||
started: 1,
|
||||
completed: 1,
|
||||
completedRate: {
|
||||
$cond: {
|
||||
if: { $eq: ['$started', 0] },
|
||||
then: 0,
|
||||
else: {
|
||||
$round: [
|
||||
{ $multiply: [{ $divide: ['$completed', '$started'] }, 100] },
|
||||
0,
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
$sort: {
|
||||
completed: -1,
|
||||
},
|
||||
},
|
||||
])
|
||||
}
|
||||
@@ -1,28 +1,5 @@
|
||||
import { Command, Session } from '@linux-odyssey/models'
|
||||
|
||||
export function sessionCount() {
|
||||
return Session.find().count()
|
||||
}
|
||||
|
||||
export function sessionCompleted() {
|
||||
return Session.find({ status: 'finished' }).count()
|
||||
}
|
||||
|
||||
export function averageTimeUsage() {
|
||||
return Session.aggregate([
|
||||
{
|
||||
$group: {
|
||||
_id: '$quest',
|
||||
average: {
|
||||
$avg: {
|
||||
$subtract: ['$finishedAt', '$createdAt'],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
])
|
||||
}
|
||||
|
||||
function formatTime(time) {
|
||||
const seconds = Math.floor(time / 1000)
|
||||
const minutes = Math.floor(seconds / 60)
|
||||
@@ -30,8 +7,9 @@ function formatTime(time) {
|
||||
return `${hours}h ${minutes % 60}m ${seconds % 60}s`
|
||||
}
|
||||
|
||||
export async function sessionList() {
|
||||
export async function sessionList(pagination) {
|
||||
const sessions = await Session.aggregate([
|
||||
pagination.match('_id'),
|
||||
{
|
||||
$lookup: {
|
||||
from: 'users',
|
||||
@@ -49,7 +27,10 @@ export async function sessionList() {
|
||||
as: 'commands',
|
||||
},
|
||||
},
|
||||
pagination.sort('_id'),
|
||||
pagination.limit(),
|
||||
])
|
||||
|
||||
return sessions.map(
|
||||
({
|
||||
_id,
|
||||
|
||||
@@ -11,8 +11,9 @@ export function userCount() {
|
||||
return User.find().count()
|
||||
}
|
||||
|
||||
export async function userList() {
|
||||
export async function userList(pagination) {
|
||||
const users = await Session.aggregate([
|
||||
pagination.match('user'),
|
||||
{
|
||||
$group: {
|
||||
_id: '$user',
|
||||
@@ -29,11 +30,14 @@ export async function userList() {
|
||||
},
|
||||
},
|
||||
{ $unwind: '$userData' },
|
||||
{ $sort: { 'userData.createdAt': 1 } },
|
||||
pagination.sort('userData._id'),
|
||||
pagination.limit(),
|
||||
])
|
||||
|
||||
return users.map(({ userData, count, lastActivityAt }) => {
|
||||
const { username, email, createdAt } = userData
|
||||
const { _id, username, email, createdAt } = userData
|
||||
return {
|
||||
_id,
|
||||
username,
|
||||
email,
|
||||
createdAt: createdAt?.toLocaleString(),
|
||||
|
||||
@@ -2,6 +2,7 @@ import { Router } from 'express'
|
||||
|
||||
import { homeController } from './controllers/index.js'
|
||||
import { userListController } from './controllers/users.js'
|
||||
import { questListController } from './controllers/quests.js'
|
||||
import { commandListController } from './controllers/commands.js'
|
||||
import {
|
||||
sessionDetailController,
|
||||
@@ -12,6 +13,7 @@ const router = Router()
|
||||
|
||||
router.get('/', homeController)
|
||||
router.get('/users', userListController)
|
||||
router.get('/quests', questListController)
|
||||
router.get('/commands', commandListController)
|
||||
router.get('/sessions', sessionListController)
|
||||
router.get('/sessions/:id', sessionDetailController)
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
import mongoose from 'mongoose'
|
||||
import Pagination, { ASC, DESC } from '../src/models/pagination.js'
|
||||
|
||||
describe('Pagination', () => {
|
||||
it('should failed when not provide order', () => {
|
||||
expect(new Pagination('').getOrder()).toBe(DESC)
|
||||
expect(() => new Pagination('Hahaha')).toThrow()
|
||||
})
|
||||
it('should return correct limit', () => {
|
||||
const pagination = new Pagination(DESC, 10)
|
||||
|
||||
expect(pagination.limit()).toMatchObject({ $limit: 10 })
|
||||
})
|
||||
|
||||
it('desc should return correct order', async () => {
|
||||
const pagination = new Pagination(DESC, 10)
|
||||
|
||||
expect(pagination.sort('_id')).toMatchObject({ $sort: { _id: -1 } })
|
||||
expect(pagination.sort('time')).toMatchObject({ $sort: { time: -1 } })
|
||||
})
|
||||
|
||||
it('asc should return correct order', async () => {
|
||||
const pagination = new Pagination(ASC, 10)
|
||||
|
||||
expect(pagination.sort('_id')).toMatchObject({ $sort: { _id: 1 } })
|
||||
expect(pagination.sort('time')).toMatchObject({ $sort: { time: 1 } })
|
||||
})
|
||||
|
||||
it('should return correct match stage for empty nextKey', async () => {
|
||||
const pagination = new Pagination(DESC, 10)
|
||||
|
||||
expect(pagination.match('_id')).toMatchObject({ $match: {} })
|
||||
})
|
||||
|
||||
it('should return correct match stage for empty nextKey', async () => {
|
||||
const nextKeyStr = '656c7fea28a4c087bfcefe12'
|
||||
const pagination = new Pagination(DESC, 10, nextKeyStr)
|
||||
const nextKey = new mongoose.Types.ObjectId(nextKeyStr)
|
||||
|
||||
expect(pagination.match('_id')).toMatchObject({
|
||||
$match: {
|
||||
_id: {
|
||||
$lt: nextKey,
|
||||
},
|
||||
},
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -1,6 +1,10 @@
|
||||
<h1>Commands</h1>
|
||||
<div>
|
||||
<h2>Error commands</h2>
|
||||
<div class='pagination'>
|
||||
<a href='/commands?order=asc'>Ascending</a>
|
||||
<a href='/commands?order=desc'>Descending</a>
|
||||
</div>
|
||||
<table>
|
||||
<tr>
|
||||
<th>Command</th>
|
||||
@@ -21,4 +25,7 @@
|
||||
</tr>
|
||||
{{/each}}
|
||||
</table>
|
||||
<div class='pagination'>
|
||||
<a href='/commands?nextKey={{nextKey}}&order={{order}}'>Next</a>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,18 +1,18 @@
|
||||
<h1>Welcome to {{title}}</h1>
|
||||
<div>
|
||||
<h2>Users</h2>
|
||||
<h2>Overview</h2>
|
||||
<table>
|
||||
<tr>
|
||||
<th>Registered Users</th>
|
||||
<td>{{userCount}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Session Count</th>
|
||||
<td>{{sessionCount}}</td>
|
||||
<th>Total Started Quests</th>
|
||||
<td>{{totalQuests}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Completed Session</th>
|
||||
<td>{{sessionCompleted}}</td>
|
||||
<th>Completed Quests</th>
|
||||
<td>{{totalCompleted}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Completed Rate</th>
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
<ul>
|
||||
<li><a href='/'>Home</a></li>
|
||||
<li><a href='/users'>Users</a></li>
|
||||
<li><a href='/quests'>Quests</a></li>
|
||||
<li><a href='/commands'>Commands</a></li>
|
||||
<li><a href='/sessions'>Sessions</a></li>
|
||||
</ul>
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
<h1>Quests</h1>
|
||||
<div>
|
||||
<table>
|
||||
<tr>
|
||||
<th>Id</th>
|
||||
<th>Started</th>
|
||||
<th>Completed</th>
|
||||
<th>Failed</th>
|
||||
<th>Completed Rate</th>
|
||||
</tr>
|
||||
{{#each quests}}
|
||||
<tr>
|
||||
<td>{{_id}}</td>
|
||||
<td>{{started}}</td>
|
||||
<td>{{completed}}</td>
|
||||
<td>{{failed}}</td>
|
||||
<td>{{completedRate}} %</td>
|
||||
</tr>
|
||||
{{/each}}
|
||||
</table>
|
||||
@@ -36,20 +36,20 @@
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<th>Command</th>
|
||||
<th>Stage</th>
|
||||
<th>PWD</th>
|
||||
<th>Input</th>
|
||||
<th>Output</th>
|
||||
<th>Error</th>
|
||||
<th>Stage</th>
|
||||
<th>Created At</th>
|
||||
<th>Input Time</th>
|
||||
</tr>
|
||||
{{#each commands}}
|
||||
<tr>
|
||||
<td>{{command}}</td>
|
||||
<td>{{stage}}</td>
|
||||
<td>{{pwd}}</td>
|
||||
<td>{{command}}</td>
|
||||
<td>{{output}}</td>
|
||||
<td>{{error}}</td>
|
||||
<td>{{stage}}</td>
|
||||
<td>{{createdAt}}</td>
|
||||
</tr>
|
||||
{{/each}}
|
||||
|
||||
@@ -1,27 +1,34 @@
|
||||
<h1>Sessions</h1>
|
||||
<div class='pagination'>
|
||||
<a href='/sessions?order=asc'>Ascending</a>
|
||||
<a href='/sessions?order=desc'>Descending</a>
|
||||
</div>
|
||||
<div>
|
||||
<table>
|
||||
<tr>
|
||||
<th>User</th>
|
||||
<th>Quest</th>
|
||||
<th></th>
|
||||
<th>Status</th>
|
||||
<th>Created At</th>
|
||||
<th>Finished At</th>
|
||||
<th>Used Time</th>
|
||||
<th>Command Count</th>
|
||||
<th>Session</th>
|
||||
</tr>
|
||||
{{#each sessions}}
|
||||
<tr>
|
||||
<td>{{user}}</td>
|
||||
<td>{{quest}}</td>
|
||||
<td><a href='/sessions/{{_id}}'>Detail</a></td>
|
||||
<td>{{status}}</td>
|
||||
<td>{{createdAt}}</td>
|
||||
<td>{{finishedAt}}</td>
|
||||
<td>{{usedTime}}</td>
|
||||
<td>{{commandCount}}</td>
|
||||
<td><a href='/sessions/{{_id}}'>Detail</a></td>
|
||||
</tr>
|
||||
{{/each}}
|
||||
</table>
|
||||
</div>
|
||||
<div class='pagination'>
|
||||
<a href='/sessions?nextKey={{nextKey}}&order={{order}}'>Next</a>
|
||||
</div>
|
||||
@@ -1,23 +1,30 @@
|
||||
<h1>Users List</h1>
|
||||
<div class='pagination'>
|
||||
<a href='/users?order=asc'>Ascending</a>
|
||||
<a href='/users?order=desc'>Descending</a>
|
||||
</div>
|
||||
<div>
|
||||
<table>
|
||||
<tr>
|
||||
<th>Username</th>
|
||||
<th>Email</th>
|
||||
<th>Registration Method</th>
|
||||
<th>Registration Time</th>
|
||||
<th>Sessions Count</th>
|
||||
<th>Last Activity</th>
|
||||
<th>Sessions Count</th>
|
||||
<th>Email</th>
|
||||
<th>Registration Time</th>
|
||||
<th>Registration Method</th>
|
||||
</tr>
|
||||
{{#each users}}
|
||||
<tr>
|
||||
<td>{{username}}</td>
|
||||
<td>{{email}}</td>
|
||||
<td>{{method}}</td>
|
||||
<td>{{createdAt}}</td>
|
||||
<td>{{sessionCount}}</td>
|
||||
<td href='/users/{{_id}}'>{{username}}</td>
|
||||
<td>{{lastActivityAt}}</td>
|
||||
<td>{{sessionCount}}</td>
|
||||
<td>{{email}}</td>
|
||||
<td>{{createdAt}}</td>
|
||||
<td>{{method}}</td>
|
||||
</tr>
|
||||
{{/each}}
|
||||
</table>
|
||||
</div>
|
||||
<div class='pagination'>
|
||||
<a href='/users?nextKey={{nextKey}}&order={{order}}'>Next</a>
|
||||
</div>
|
||||
@@ -6,6 +6,6 @@
|
||||
"license": "GPL",
|
||||
"exports": "./index.js",
|
||||
"dependencies": {
|
||||
"mongoose": "^7.6.0"
|
||||
"mongoose": "^8.0.3"
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -26,7 +26,7 @@
|
||||
"express-validator": "^7.0.1",
|
||||
"jsonwebtoken": "^9.0.1",
|
||||
"minimist": "^1.2.8",
|
||||
"mongoose": "^7.4.0",
|
||||
"mongoose": "^8.0.3",
|
||||
"node-schedule": "^2.1.1",
|
||||
"passport": "^0.6.0",
|
||||
"passport-github2": "^0.1.12",
|
||||
|
||||
@@ -1756,15 +1756,10 @@ bser@2.1.1:
|
||||
dependencies:
|
||||
node-int64 "^0.4.0"
|
||||
|
||||
bson@^5.4.0:
|
||||
version "5.4.0"
|
||||
resolved "https://registry.yarnpkg.com/bson/-/bson-5.4.0.tgz#0eea77276d490953ad8616b483298dbff07384c6"
|
||||
integrity sha512-WRZ5SQI5GfUuKnPTNmAYPiKIof3ORXAF4IRU5UcgmivNIon01rWQlw5RUH954dpu8yGL8T59YShVddIPaU/gFA==
|
||||
|
||||
bson@^5.5.0:
|
||||
version "5.5.0"
|
||||
resolved "https://registry.yarnpkg.com/bson/-/bson-5.5.0.tgz#a419cc69f368d2def3b8b22ea03ed1c9be40e53f"
|
||||
integrity sha512-B+QB4YmDx9RStKv8LLSl/aVIEV3nYJc3cJNNTK2Cd1TL+7P+cNpw9mAPeCgc5K+j01Dv6sxUzcITXDx7ZU3F0w==
|
||||
bson@^6.2.0:
|
||||
version "6.2.0"
|
||||
resolved "https://registry.yarnpkg.com/bson/-/bson-6.2.0.tgz#4b6acafc266ba18eeee111373c2699304a9ba0a3"
|
||||
integrity sha512-ID1cI+7bazPDyL9wYy9GaQ8gEEohWvcUl/Yf0dIdutJxnmInEEyCsb4awy/OiBfall7zBA179Pahi3vCdFze3Q==
|
||||
|
||||
buffer-crc32@~0.2.3:
|
||||
version "0.2.13"
|
||||
@@ -3668,11 +3663,6 @@ internal-slot@^1.0.5:
|
||||
has "^1.0.3"
|
||||
side-channel "^1.0.4"
|
||||
|
||||
ip@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/ip/-/ip-2.0.0.tgz#4cf4ab182fee2314c75ede1276f8c80b479936da"
|
||||
integrity sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==
|
||||
|
||||
ipaddr.js@1.9.1:
|
||||
version "1.9.1"
|
||||
resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3"
|
||||
@@ -4833,49 +4823,23 @@ mongodb-connection-string-url@^2.6.0:
|
||||
"@types/whatwg-url" "^8.2.1"
|
||||
whatwg-url "^11.0.0"
|
||||
|
||||
mongodb@5.7.0:
|
||||
version "5.7.0"
|
||||
resolved "https://registry.yarnpkg.com/mongodb/-/mongodb-5.7.0.tgz#e16d2fcdfd9f8503ec2d88288392dc3235bb3ecc"
|
||||
integrity sha512-zm82Bq33QbqtxDf58fLWBwTjARK3NSvKYjyz997KSy6hpat0prjeX/kxjbPVyZY60XYPDNETaHkHJI2UCzSLuw==
|
||||
mongodb@6.2.0:
|
||||
version "6.2.0"
|
||||
resolved "https://registry.yarnpkg.com/mongodb/-/mongodb-6.2.0.tgz#2c9dcb3eeaf528ed850e94b3df392de6c6b0d7ab"
|
||||
integrity sha512-d7OSuGjGWDZ5usZPqfvb36laQ9CPhnWkAGHT61x5P95p/8nMVeH8asloMwW6GcYFeB0Vj4CB/1wOTDG2RA9BFA==
|
||||
dependencies:
|
||||
bson "^5.4.0"
|
||||
mongodb-connection-string-url "^2.6.0"
|
||||
socks "^2.7.1"
|
||||
optionalDependencies:
|
||||
saslprep "^1.0.3"
|
||||
|
||||
mongodb@5.9.0:
|
||||
version "5.9.0"
|
||||
resolved "https://registry.yarnpkg.com/mongodb/-/mongodb-5.9.0.tgz#5a22065fa8cfaf1d58bf2e3c451cd2c4bfa983a2"
|
||||
integrity sha512-g+GCMHN1CoRUA+wb1Agv0TI4YTSiWr42B5ulkiAfLLHitGK1R+PkSAf3Lr5rPZwi/3F04LiaZEW0Kxro9Fi2TA==
|
||||
dependencies:
|
||||
bson "^5.5.0"
|
||||
mongodb-connection-string-url "^2.6.0"
|
||||
socks "^2.7.1"
|
||||
optionalDependencies:
|
||||
"@mongodb-js/saslprep" "^1.1.0"
|
||||
bson "^6.2.0"
|
||||
mongodb-connection-string-url "^2.6.0"
|
||||
|
||||
mongoose@^7.4.0:
|
||||
version "7.4.0"
|
||||
resolved "https://registry.yarnpkg.com/mongoose/-/mongoose-7.4.0.tgz#3726a8dea0c9e2d54651845cc84c813a6507906a"
|
||||
integrity sha512-oHE1eqodfKzugXRlQxpo+msIea7jPcRoayDuEMr50+bYwM/juA5f+1stjkWlXcg6vo1PdJFVA6DGaKOPLuG5mA==
|
||||
mongoose@^8.0.3:
|
||||
version "8.0.3"
|
||||
resolved "https://registry.yarnpkg.com/mongoose/-/mongoose-8.0.3.tgz#f3708ba0f40b6dec8f5f1a5d40abd69a80207114"
|
||||
integrity sha512-LJRT0yP4TW14HT4r2RkxqyvoTylMSzWpl5QOeVHTnRggCLQSpkoBdgbUtORFq/mSL2o9cLCPJz+6uzFj25qbHw==
|
||||
dependencies:
|
||||
bson "^5.4.0"
|
||||
bson "^6.2.0"
|
||||
kareem "2.5.1"
|
||||
mongodb "5.7.0"
|
||||
mpath "0.9.0"
|
||||
mquery "5.0.0"
|
||||
ms "2.1.3"
|
||||
sift "16.0.1"
|
||||
|
||||
mongoose@^7.6.0:
|
||||
version "7.6.0"
|
||||
resolved "https://registry.yarnpkg.com/mongoose/-/mongoose-7.6.0.tgz#3037b754ccdf168385e52d4bcabeb7f5c3b17a5f"
|
||||
integrity sha512-ztQ12rm0BQN5i7LB6xhWX4l9a9w2aa3jEwa/mM2vAutYJRyAwOzcusvKJBULMzFHyUDBOVW15grisexypgMIWA==
|
||||
dependencies:
|
||||
bson "^5.4.0"
|
||||
kareem "2.5.1"
|
||||
mongodb "5.9.0"
|
||||
mongodb "6.2.0"
|
||||
mpath "0.9.0"
|
||||
mquery "5.0.0"
|
||||
ms "2.1.3"
|
||||
@@ -5758,13 +5722,6 @@ safe-stable-stringify@^2.3.1:
|
||||
resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
|
||||
integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
|
||||
|
||||
saslprep@^1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/saslprep/-/saslprep-1.0.3.tgz#4c02f946b56cf54297e347ba1093e7acac4cf226"
|
||||
integrity sha512-/MY/PEMbk2SuY5sScONwhUDsV2p77Znkb/q3nSVstq/yQzYJOH/Azh29p9oJLsl3LnQwSvZDKagDGBsBwSooag==
|
||||
dependencies:
|
||||
sparse-bitfield "^3.0.3"
|
||||
|
||||
semver@^6.0.0, semver@^6.3.0, semver@^6.3.1:
|
||||
version "6.3.1"
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4"
|
||||
@@ -5913,11 +5870,6 @@ slice-ansi@^4.0.0:
|
||||
astral-regex "^2.0.0"
|
||||
is-fullwidth-code-point "^3.0.0"
|
||||
|
||||
smart-buffer@^4.2.0:
|
||||
version "4.2.0"
|
||||
resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.2.0.tgz#6e1d71fa4f18c05f7d0ff216dd16a481d0e8d9ae"
|
||||
integrity sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==
|
||||
|
||||
socket.io-adapter@~2.5.2:
|
||||
version "2.5.2"
|
||||
resolved "https://registry.yarnpkg.com/socket.io-adapter/-/socket.io-adapter-2.5.2.tgz#5de9477c9182fdc171cd8c8364b9a8894ec75d12"
|
||||
@@ -5956,14 +5908,6 @@ socket.io@^4.7.1:
|
||||
socket.io-adapter "~2.5.2"
|
||||
socket.io-parser "~4.2.4"
|
||||
|
||||
socks@^2.7.1:
|
||||
version "2.7.1"
|
||||
resolved "https://registry.yarnpkg.com/socks/-/socks-2.7.1.tgz#d8e651247178fde79c0663043e07240196857d55"
|
||||
integrity sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==
|
||||
dependencies:
|
||||
ip "^2.0.0"
|
||||
smart-buffer "^4.2.0"
|
||||
|
||||
sorted-array-functions@^1.3.0:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/sorted-array-functions/-/sorted-array-functions-1.3.0.tgz#8605695563294dffb2c9796d602bd8459f7a0dd5"
|
||||
|
||||
Reference in new issue
Block a user