diff --git a/configs/chest.json b/configs/chest.json new file mode 100644 index 0000000..d8d5f17 --- /dev/null +++ b/configs/chest.json @@ -0,0 +1,41 @@ +{ + "chests": [ + { + "level": 1, + "name": "Wooden Chest", + "initScoreMin": 10, + "initScoreMax": 50, + "maxBonus": 10, + "minBonus": 5, + "maxBounsCount": 10 + }, + { + "level": 2, + "name": "Iron Chest", + "initScoreMin": 20, + "initScoreMax": 60, + "maxBonus": 20, + "minBonus": 10, + "maxBounsCount": 15 + }, + { + "level": 3, + "name": "Bronze Chest", + "initScoreMin": 30, + "initScoreMax": 80, + "maxBonus": 30, + "minBonus": 15, + "maxBounsCount": 20 + }, + { + "level": 4, + "name": "Sliver Chest", + "initScoreMin": 40, + "initScoreMax": 100, + "maxBonus": 40, + "minBonus": 20, + "maxBounsCount": 50 + } + ] + +} \ No newline at end of file diff --git a/configs/share_cfg.json b/configs/share_cfg.json new file mode 100644 index 0000000..47422ad --- /dev/null +++ b/configs/share_cfg.json @@ -0,0 +1,4 @@ +{ + "inviter": 10, + "invitee": 10 +} \ No newline at end of file diff --git a/initdatas/activity_info.json b/initdatas/activity_info.json index d4da622..7d34f9d 100644 --- a/initdatas/activity_info.json +++ b/initdatas/activity_info.json @@ -1,9 +1,10 @@ [ { - "_id": "first_activity", - "name": "First Activity1", - "description": "This is the first test activity", - "tasks": [{ + "_id": "uaw_activity", + "name": "UAW Activity", + "description": "UAW", + "tasks": [ + { "id": "e2yhq2lj30vwcpedv7p", "task": "TwitterConnect", "title": "", @@ -147,7 +148,7 @@ "task": "TwitterRetweet", "title": "", "type": 2, - "desc": "Showcase your performance in Counter Fire to your friends!", + "desc": "Showcase your performance in Counter Fire to your friends!", "category": "Social Tasks", "score": 300, "autoclaim": false, @@ -170,117 +171,8 @@ "start": "2024-01-01 00:00", "end": "2025-01-01 00:00", "params": {"time": 6, "failRate": 60} - }, { - "id": "e2f7fplj30vwcpe0l97", - "task": "DailyCheckIn", - "title": "", - "type": 1, - "desc": "Check-in for 3 consecutive days.", - "category": "Referral to Earn", - "score": 100, - "autoclaim": false, - "pretasks": [], - "cfg": {}, - "start": "2024-01-01 00:00", - "end": "2025-01-01 00:00", - "params": {"days": 3} - }, { - "id": "e2f7fplj30vwcpe0l98", - "task": "OkxLogin", - "title": "", - "type": 1, - "desc": "Sign in via OKX Wallet.", - "category": "Referral to Earn", - "score": 300, - "autoclaim": false, - "pretasks": [], - "cfg": {"account": "okx", "icon": "okx"}, - "start": "2024-01-01 00:00", - "end": "2025-01-01 00:00", - "params": {"item": {"lottery_ticket": 1}} - }, { - "id": "e2f7fplj30vwcpe0l96", - "task": "DailyCheckIn", - "title": "", - "type": 2, - "desc": "Daily check-in! Score more Flames with 7 days of consecutive check-ins. Ignite it now!", - "category": "Social Tasks", - "score": 20, - "autoclaim": false, - "pretasks": [], - "cfg": {"score": [0, 15, 20, 20, 40, 40, 60]}, - "start": "2024-01-01 00:00", - "end": "2025-01-01 00:00", - "params": {"days": 1, "score": [0, 15, 20, 20, 40, 40, 60]} - }, { - "id": "e2f7t4lj30vwcpe0ldr", - "task": "ShareCode", - "title": "", - "desc": "Click here if your are referred by a friend!", - "type": 1, - "category": "Social Tasks", - "show": true, - "autoclaim": false, - "pretasks": [], - "cfg": {}, - "score": 500, - "params": {"score": [500]} - }, { - "id": "e2f7t4lj31vwcpe0ldr", - "task": "BurnNft", - "type": 1, - "show": true, - "repeat": 2, - "title": "Hero NFT", - "desc": "Click to burn and redeem Flame", - "category": "CF Pal", - "autoclaim": false, - "pretasks": [], - "cfg": {"address": "0xCD4bb3402f1a444a1AF10F31946Ed37DaC0eaC4d"}, - "score": 200, - "params": {"address": "0xCD4bb3402f1a444a1AF10F31946Ed37DaC0eaC4d"} - }, { - "id": "e2f7t4lj32vwcpe0ldr", - "task": "BurnNft", - "type": 1, - "show": true, - "repeat": 2, - "title": "Candy Badge", - "desc": "Click to burn and redeem Flame", - "category": "CF Pal", - "pretasks": [], - "cfg": {"address": "0x6a673D946a976776fd5F163d9d831b2fEB600015"}, - "score": 100, - "params": {"address": "0x6a673D946a976776fd5F163d9d831b2fEB600015"} - }, { - "id": "e2f7t4lj33vwcpe0ldr", - "task": "BurnNft", - "type": 1, - "show": true, - "repeat": 2, - "title": "Explorer Badge", - "desc": "Click to burn and redeem Flame", - "category": "CF Pal", - "autoclaim": false, - "pretasks": [], - "cfg": {"address": "0x7b6399DFbed8Bc46F6A498C6B1040E80c2B5C4bc"}, - "score": 100, - "params": {"address": "0x7b6399DFbed8Bc46F6A498C6B1040E80c2B5C4bc"} - }, { - "id": "e2f7t4lj33vwcpe0ldr", - "task": "BurnNft", - "type": 1, - "show": true, - "repeat": 2, - "title": "Gacha Badge", - "desc": "Click to burn and redeem Flame", - "category": "CF Pal", - "autoclaim": false, - "pretasks": [], - "cfg": {"address": "0xe2E4D5a4045fBFcbCBECAf5b8A94303712d2FA97"}, - "score": 200, - "params": {"address": "0xe2E4D5a4045fBFcbCBECAf5b8A94303712d2FA97"} - }], + } + ], "startTime": 1711086450119, "endTime": 1713678477701 } diff --git a/initdatas/uaw_cfg.json b/initdatas/activity_info.json_bak similarity index 61% rename from initdatas/uaw_cfg.json rename to initdatas/activity_info.json_bak index 3a05d6f..d4da622 100644 --- a/initdatas/uaw_cfg.json +++ b/initdatas/activity_info.json_bak @@ -1,10 +1,9 @@ [ { - "_id": "uaw_activity", - "name": "UAW Activity", - "description": "UAW", - "tasks": [ - { + "_id": "first_activity", + "name": "First Activity1", + "description": "This is the first test activity", + "tasks": [{ "id": "e2yhq2lj30vwcpedv7p", "task": "TwitterConnect", "title": "", @@ -171,8 +170,117 @@ "start": "2024-01-01 00:00", "end": "2025-01-01 00:00", "params": {"time": 6, "failRate": 60} - } - ], + }, { + "id": "e2f7fplj30vwcpe0l97", + "task": "DailyCheckIn", + "title": "", + "type": 1, + "desc": "Check-in for 3 consecutive days.", + "category": "Referral to Earn", + "score": 100, + "autoclaim": false, + "pretasks": [], + "cfg": {}, + "start": "2024-01-01 00:00", + "end": "2025-01-01 00:00", + "params": {"days": 3} + }, { + "id": "e2f7fplj30vwcpe0l98", + "task": "OkxLogin", + "title": "", + "type": 1, + "desc": "Sign in via OKX Wallet.", + "category": "Referral to Earn", + "score": 300, + "autoclaim": false, + "pretasks": [], + "cfg": {"account": "okx", "icon": "okx"}, + "start": "2024-01-01 00:00", + "end": "2025-01-01 00:00", + "params": {"item": {"lottery_ticket": 1}} + }, { + "id": "e2f7fplj30vwcpe0l96", + "task": "DailyCheckIn", + "title": "", + "type": 2, + "desc": "Daily check-in! Score more Flames with 7 days of consecutive check-ins. Ignite it now!", + "category": "Social Tasks", + "score": 20, + "autoclaim": false, + "pretasks": [], + "cfg": {"score": [0, 15, 20, 20, 40, 40, 60]}, + "start": "2024-01-01 00:00", + "end": "2025-01-01 00:00", + "params": {"days": 1, "score": [0, 15, 20, 20, 40, 40, 60]} + }, { + "id": "e2f7t4lj30vwcpe0ldr", + "task": "ShareCode", + "title": "", + "desc": "Click here if your are referred by a friend!", + "type": 1, + "category": "Social Tasks", + "show": true, + "autoclaim": false, + "pretasks": [], + "cfg": {}, + "score": 500, + "params": {"score": [500]} + }, { + "id": "e2f7t4lj31vwcpe0ldr", + "task": "BurnNft", + "type": 1, + "show": true, + "repeat": 2, + "title": "Hero NFT", + "desc": "Click to burn and redeem Flame", + "category": "CF Pal", + "autoclaim": false, + "pretasks": [], + "cfg": {"address": "0xCD4bb3402f1a444a1AF10F31946Ed37DaC0eaC4d"}, + "score": 200, + "params": {"address": "0xCD4bb3402f1a444a1AF10F31946Ed37DaC0eaC4d"} + }, { + "id": "e2f7t4lj32vwcpe0ldr", + "task": "BurnNft", + "type": 1, + "show": true, + "repeat": 2, + "title": "Candy Badge", + "desc": "Click to burn and redeem Flame", + "category": "CF Pal", + "pretasks": [], + "cfg": {"address": "0x6a673D946a976776fd5F163d9d831b2fEB600015"}, + "score": 100, + "params": {"address": "0x6a673D946a976776fd5F163d9d831b2fEB600015"} + }, { + "id": "e2f7t4lj33vwcpe0ldr", + "task": "BurnNft", + "type": 1, + "show": true, + "repeat": 2, + "title": "Explorer Badge", + "desc": "Click to burn and redeem Flame", + "category": "CF Pal", + "autoclaim": false, + "pretasks": [], + "cfg": {"address": "0x7b6399DFbed8Bc46F6A498C6B1040E80c2B5C4bc"}, + "score": 100, + "params": {"address": "0x7b6399DFbed8Bc46F6A498C6B1040E80c2B5C4bc"} + }, { + "id": "e2f7t4lj33vwcpe0ldr", + "task": "BurnNft", + "type": 1, + "show": true, + "repeat": 2, + "title": "Gacha Badge", + "desc": "Click to burn and redeem Flame", + "category": "CF Pal", + "autoclaim": false, + "pretasks": [], + "cfg": {"address": "0xe2E4D5a4045fBFcbCBECAf5b8A94303712d2FA97"}, + "score": 200, + "params": {"address": "0xe2E4D5a4045fBFcbCBECAf5b8A94303712d2FA97"} + }], "startTime": 1711086450119, "endTime": 1713678477701 } diff --git a/package.json b/package.json index de588d1..c336cfd 100644 --- a/package.json +++ b/package.json @@ -18,7 +18,7 @@ "@fastify/formbody": "^7.4.0", "@fastify/helmet": "^10.1.0", "@fastify/jwt": "^6.7.1", - "@typegoose/typegoose": "^12.1.0", + "@typegoose/typegoose": "^12.2.0", "bson": "^4.0.4", "dotenv": "^16.0.3", "ethers": "^5.6.8", @@ -26,7 +26,7 @@ "fastify-plugin": "^3.0.0", "fastify-xml-body-parser": "^2.2.0", "mongodb-extended-json": "^1.11.1", - "mongoose": "8.1.0", + "mongoose": "8.2.3", "node-schedule": "^2.0.0", "siwe": "^2.1.4", "tracer": "^1.1.6", diff --git a/src/common/Constants.ts b/src/common/Constants.ts index a5b214a..b133fa0 100644 --- a/src/common/Constants.ts +++ b/src/common/Constants.ts @@ -14,3 +14,5 @@ export const CONFIRM_MAIL_HTML = `

点击链接进入确认页面, 如果无法跳转, 就复制链接, 电脑上直接用浏览器打开, 手机上使用MetaMask的浏览器打开

{{link2}}

` +// 是否需要手动开启游戏 +export const MANUAL_OPEN_GAME = true diff --git a/src/controllers/activity.controller.ts b/src/controllers/activity.controller.ts index 38ef839..16b742c 100644 --- a/src/controllers/activity.controller.ts +++ b/src/controllers/activity.controller.ts @@ -1,9 +1,11 @@ import { ActivityInfo } from 'models/ActivityInfo' import { ActivityUser } from 'models/ActivityUser' -import { rankKey, rankLevel } from 'services/rank.svr' +import { rankKey, rankLevel, updateRankScore } from 'services/rank.svr' import { BaseController, ROLE_ANON, SyncLocker, ZError, ZRedisClient, role, router } from 'zutils' import { ScoreRecord } from 'models/ScoreRecord' import { formatAddress } from 'zutils/utils/chain.util' +import { formatDate } from 'zutils/utils/date.util' +const shareCfg = require('../../configs/share_cfg.json') const MAX_LIMIT = 100 export default class ActivityController extends BaseController { @@ -38,6 +40,30 @@ export default class ActivityController extends BaseController { if (!inviteUser) { throw new ZError(12, 'invalid invite code') } + // TODO:: 检查自己是否符合条件 + const dateTag = formatDate(new Date()) + // 更新邀请积分-邀请人 + await updateRankScore({ + user: inviteUser.id, + score: shareCfg.inviter, + activity: user.activity, + scoreType: 'invite_user', + scoreParams: { + date: dateTag, + user: user.id, + }, + }) + // 更新邀请积分-被邀请人 + await updateRankScore({ + user: user.id, + score: shareCfg.invitee, + activity: user.activity, + scoreType: 'invite_invitee', + scoreParams: { + date: dateTag, + user: inviteUser.id, + }, + }) user.inviteUser = inviteUser.id await user.save() return {} diff --git a/src/controllers/chest.controller.ts b/src/controllers/chest.controller.ts index acc6979..1fd711e 100644 --- a/src/controllers/chest.controller.ts +++ b/src/controllers/chest.controller.ts @@ -5,6 +5,13 @@ import { mongoose } from '@typegoose/typegoose' import { rankKey, rankLevel, updateRankScore } from 'services/rank.svr' import { formatDate } from 'zutils/utils/date.util' import { ScoreRecord } from 'models/ScoreRecord' +import { ChestRecord } from 'models/chain/ChestRecord' +const chestCfg = require('../../configs/chest.json') +const chestLevelMap = new Map() + +for (let cfg of chestCfg.chests) { + chestLevelMap.set(cfg.level, cfg) +} /** * 宝箱相关接口 */ @@ -67,25 +74,37 @@ class BoxController extends BaseController { const { code } = req.params const user = req.user const uid = user.uid - const score = 10 //TODO:: 根据规则生成助力积分 + const session = await mongoose.startSession() session.startTransaction() try { + // TODO:: 检查用户是否符合助力条件 const chest = await ActivityChest.findOne({ shareCode: code, activity: user.activity }).session(session) if (chest.bonusUsers.includes(uid)) { throw new ZError(10, 'user already enhanced') } - if (chest.bonusUsers.length >= chest.maxBonus) { + if (chest.bonusUsers.length >= chest.maxBounsCount) { throw new ZError(12, 'enhanced times exceed') } + if (chest.status === 9) { + throw new ZError(13, 'chest already opened') + } + if (chest.status === 0) { + throw new ZError(14, 'chest is locked') + } + if (chest.user === uid) { + throw new ZError(15, 'can not enhance self') + } + const score = Math.floor(Math.random() * (chest.bounsCfg[1] - chest.bounsCfg[0] + 1) + chest.bounsCfg[0]) chest.bonusUsers.push(uid) chest.bonusScores.push(score) chest.scoreBonus += score await chest.save({ session }) + // TODO:: 新用户给一个锁住的箱子 await session.commitTransaction() session.endSession() return { - score: 1, // TODO:: 根据规则生成自己获得助力积分 + score: 1, } } catch (error) { session.abortTransaction() @@ -96,6 +115,12 @@ class BoxController extends BaseController { /** * 开启宝箱 + * 流程如下: + * 1. 客户端组装json string: data:,{"p":"cf-20","op":"chest_open","id":"${chestId}"} + * 2. 将字符串转成hex + * 3. 将hex字符串作为data, 发起一笔至特定地址的0ETH交易 + * 4. 服务端监听到交易后, 解析input, 获取chestId + * 5. 服务端调用此接口, 传入chestId, 完成开箱操作 */ @router('post /api/chest/open') async openChest(req) { @@ -105,6 +130,10 @@ class BoxController extends BaseController { if (!chestid) { throw new ZError(11, 'chestid is required') } + const openRecord = await ChestRecord.findOne({ from: user.address, chestId: chestid }) + if (!openRecord) { + throw new ZError(12, 'onchain open record not found') + } const chest = await ActivityChest.findById(chestid) if (!chest) { throw new ZError(12, 'chest not found') diff --git a/src/controllers/game.controller.ts b/src/controllers/game.controller.ts index 62db543..9b6ba06 100644 --- a/src/controllers/game.controller.ts +++ b/src/controllers/game.controller.ts @@ -1,9 +1,11 @@ +import { MANUAL_OPEN_GAME } from 'common/Constants' import { ActivityGame } from 'models/ActivityGame' import { DAILY_SIGN, SIGN_TOTAL, TicketRecord, USE_TICKET } from 'models/TicketRecord' import { queryCheckInList } from 'services/chain.svr' import { checkInToday, seqSignCfg, seqSignScore, totalSignCfg, totalSignScore } from 'services/sign.svr' import { ZError, SyncLocker, ZRedisClient, BaseController, ROLE_ANON, role, router } from 'zutils' import { formatDate } from 'zutils/utils/date.util' +const chestCfg = require('../../configs/chest.json') /** * 探索游戏相关接口 */ @@ -18,7 +20,7 @@ class GameController extends BaseController { const { address } = user const dateTag = formatDate(new Date()) const gameRecord = await ActivityGame.insertOrUpdate({ user: user.id, activity: user.activity }, {}) - if (gameRecord.status === 0) { + if (MANUAL_OPEN_GAME && gameRecord.status === 0) { throw new ZError(11, 'map not open') } if (dateTag === gameRecord.lastSignDay) { @@ -101,17 +103,27 @@ class GameController extends BaseController { score, }) const gameRecord = await ActivityGame.insertOrUpdate({ user: user.id, activity: user.activity }, {}) + if (MANUAL_OPEN_GAME && gameRecord.status === 0) { + throw new ZError(12, 'map not open') + } gameRecord.tickets += score await gameRecord.save() await record.save() return { ticket: score } } /** - * //TODO::开启地图 + * 开启地图 */ @router('get /api/game/open') async openMap(req) { const user = req.user + const gameInfo = await ActivityGame.insertOrUpdate({ user: user.id, activity: user.activity }, {}) + if (gameInfo.status === 1) { + throw new ZError(11, 'already opened') + } + // TODO:: check condition + gameInfo.status = 1 + await gameInfo.save() return {} } /** @@ -121,6 +133,9 @@ class GameController extends BaseController { async gameStat(req, res) { const user = req.user const record = await ActivityGame.insertOrUpdate({ user: user.id, activity: user.activity }, {}) + if (MANUAL_OPEN_GAME && record.status === 0) { + throw new ZError(12, 'map not open') + } const signCfg = seqSignCfg const dateTag = formatDate(new Date()) const checkRecord = await checkInToday(user.address, dateTag) @@ -180,7 +195,7 @@ class GameController extends BaseController { step = parseInt(step) const record = await ActivityGame.insertOrUpdate({ user: user.id, activity: user.activity }, {}) - if (record.status === 0) { + if (MANUAL_OPEN_GAME && record.status === 0) { throw new ZError(12, 'map not open') } if (record.tickets < step) { diff --git a/src/initdata.ts b/src/initdata.ts index 09a3484..96d2a12 100644 --- a/src/initdata.ts +++ b/src/initdata.ts @@ -13,6 +13,9 @@ var ejson = require('mongodb-extended-json') const fs = require('fs') // Used to get all the files in a directory const list = fs.readdirSync(dir) for (var i = 0; i < list.length; i++) { + if (list[i].endsWith('.json') === false) { + continue + } // Remove the file extension const collection_name = list[i].replace('.json', '') const parsedJSON = require(dir + '/' + list[i]) diff --git a/src/models/ActivityChest.ts b/src/models/ActivityChest.ts index 408e8cf..c507fb1 100644 --- a/src/models/ActivityChest.ts +++ b/src/models/ActivityChest.ts @@ -44,7 +44,10 @@ class ActivityChestClass extends BaseModule { public level: number // 最大助力次数 @prop() - public maxBonus: number + public maxBounsCount: number + // 助力积分配置[min, max] + @prop({ type: () => [Number], default: [] }) + public bounsCfg: number[] // 基础积分 @prop({ default: 0 }) public scoreInit: number @@ -64,7 +67,7 @@ class ActivityChestClass extends BaseModule { stat: this.status, shareCode: this.shareCode, level: this.level, - maxBonus: this.maxBonus, + maxBounsCount: this.maxBounsCount, scoreInit: this.scoreInit, scoreBonus: this.scoreBonus, bounsCount: this.bonusUsers.length, diff --git a/src/models/chain/ChestRecord.ts b/src/models/chain/ChestRecord.ts new file mode 100644 index 0000000..9f9a5ce --- /dev/null +++ b/src/models/chain/ChestRecord.ts @@ -0,0 +1,60 @@ +import { getModelForClass, index, modelOptions, prop } from '@typegoose/typegoose' +import { dbconn } from 'decorators/dbconn' +import { BaseModule } from '../Base' +import { hexToUtf8 } from 'zutils/utils/string.util' +import logger from 'logger/logger' + +@dbconn('chain') +@index({ from: 1 }, { unique: false }) +@index({ from: 1, chestId: 1 }, { unique: true }) +@index({ from: 1, blockTime: 1 }, { unique: false }) +@modelOptions({ + schemaOptions: { collection: 'chest_open_record', timestamps: true }, +}) +export class ChestRecordClass extends BaseModule { + @prop({ required: true }) + public from!: string + @prop() + public to: string + @prop({ required: true }) + public hash: string + @prop() + public blockNumber: string + @prop() + public blockHash: string + @prop() + public blockTime: number + @prop() + public dateTag: string + @prop() + public chestId: string + @prop() + public value: string + @prop() + public input: string + + public static async saveEvent(event: any) { + const dataStr = hexToUtf8(event.input) + const regexp = /data:,{\"p\":\"cf-20\",\"op\":\"chest_open\",\"id\":\"(.+?)\"}/ + const match = dataStr.match(regexp) + if (!match) { + logger.log('not a chest open event:', event.hash) + return + } + event.chestId = match[1] + logger.log('open chest with id:', event.chestId) + return ChestRecord.insertOrUpdate({ hash: event.hash }, event) + } + + public toJson() { + return { + address: this.from, + day: this.dateTag, + time: this.blockTime, + } + } +} + +export const ChestRecord = getModelForClass(ChestRecordClass, { + existingConnection: ChestRecordClass['db'], +}) diff --git a/src/services/activity.svr.ts b/src/services/activity.svr.ts new file mode 100644 index 0000000..f3ef5f3 --- /dev/null +++ b/src/services/activity.svr.ts @@ -0,0 +1,3 @@ +export const isActivityReady = (activity: any) => { + return true +} diff --git a/src/services/chain.svr.ts b/src/services/chain.svr.ts index 596422f..0ca5be4 100644 --- a/src/services/chain.svr.ts +++ b/src/services/chain.svr.ts @@ -38,7 +38,7 @@ export const queryCheckInSeq = async (address: string) => { return record.toJson() } -export const queryBurnNftList = async (address: string, user: string, chain: number) => { +export const queryBurnNftList = async (address: string, user: string, chain: string) => { address = address.toLowerCase() user = user.toLowerCase() diff --git a/src/tasks/BurnNft.ts b/src/tasks/BurnNft.ts index c6d2931..0976e0a 100644 --- a/src/tasks/BurnNft.ts +++ b/src/tasks/BurnNft.ts @@ -12,7 +12,7 @@ export default class BurnNft extends ITask { const { task } = data let cfg = this.activity.tasks.find((t: TaskCfg) => t.id === task.id) const address = cfg.params.address.toLowerCase() - const chain = parseInt(process.env.CHAIN) + const chain = process.env.CHAIN const nftList = await queryBurnNftList(address, this.user.address, chain) const localNft = await NftBurnRecord.find({ user: this.user.id, diff --git a/yarn.lock b/yarn.lock index c48552d..0de7e7c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -659,15 +659,15 @@ resolved "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.3.tgz" integrity sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ== -"@typegoose/typegoose@^12.1.0": - version "12.1.0" - resolved "https://registry.yarnpkg.com/@typegoose/typegoose/-/typegoose-12.1.0.tgz#06da94152fef00e69978ecd5de6db83a7ae420b7" - integrity sha512-RhqsFvTCTshtYxuzsHCGwPLJXgX1sc5aguZJ4w3ax6shVHaVQSG4VZddo/BowfP+0CSjp4J8XeCtrunkzkhJOg== +"@typegoose/typegoose@^12.2.0": + version "12.2.0" + resolved "https://registry.yarnpkg.com/@typegoose/typegoose/-/typegoose-12.2.0.tgz#c1aeba14f80ae94069000a9a2db0128c1e35b8fe" + integrity sha512-6gC5aIfccXw4IZOMe3oSef63M6leDyMvuycfwzQdVi8M9C5UnpaV8tO1xzmxiOxUHDST0GdDW/aWCCX6MtOQxg== dependencies: lodash "^4.17.20" - loglevel "^1.8.1" + loglevel "^1.9.1" reflect-metadata "^0.2.1" - semver "^7.5.4" + semver "^7.6.0" tslib "^2.6.2" "@types/bn.js@^4.11.3": @@ -2998,10 +2998,10 @@ lodash@^4.17.20: resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== -loglevel@^1.8.1: - version "1.8.1" - resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.8.1.tgz#5c621f83d5b48c54ae93b6156353f555963377b4" - integrity sha512-tCRIJM51SHjAayKwC+QAg8hT8vg6z7GSgLJKGvzuPb1Wc+hLzqtuVLxp6/HzSPOozuK+8ErAhy7U/sVzw8Dgfg== +loglevel@^1.9.1: + version "1.9.1" + resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.9.1.tgz#d63976ac9bcd03c7c873116d41c2a85bafff1be7" + integrity sha512-hP3I3kCrDIMuRwAwHltphhDM1r8i55H33GgqjXbrisuJhF4kRhW1dNuxsRklp4bXl8DSdLaNLuiL4A/LWRfxvg== long-timeout@0.1.1: version "0.1.1" @@ -3232,10 +3232,10 @@ mongodb@6.3.0: bson "^6.2.0" mongodb-connection-string-url "^3.0.0" -mongoose@8.1.0: - version "8.1.0" - resolved "https://registry.yarnpkg.com/mongoose/-/mongoose-8.1.0.tgz#25be9a39295c0cbffc971fdd4fb6302dceeb2ded" - integrity sha512-kOA4Xnq2goqNpN9EmYElGNWfxA9H80fxcr7UdJKWi3UMflza0R7wpTihCpM67dE/0MNFljoa0sjQtlXVkkySAQ== +mongoose@8.2.3: + version "8.2.3" + resolved "https://registry.yarnpkg.com/mongoose/-/mongoose-8.2.3.tgz#26c2074b0d65fa83fa2fd899d3327a2a820fd4c8" + integrity sha512-ZB8K8AgbVgLCcqjtmZMxaQBEztwEEZCtAIPMx2Q56Uo4WWKmwf5Nu/EEIFo8d/17P946X0z6xzxwIqCxUMKxrA== dependencies: bson "^6.2.0" kareem "2.5.1" @@ -3337,6 +3337,13 @@ node-addon-api@^2.0.0: resolved "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.2.tgz" integrity sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA== +node-fetch@2: + version "2.7.0" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" + integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== + dependencies: + whatwg-url "^5.0.0" + node-fetch@2.6.7: version "2.6.7" resolved "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz" @@ -3937,6 +3944,13 @@ semver@^7.5.4: dependencies: lru-cache "^6.0.0" +semver@^7.6.0: + version "7.6.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.0.tgz#1a46a4db4bffcccd97b743b5005c8325f23d4e2d" + integrity sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg== + dependencies: + lru-cache "^6.0.0" + send@0.18.0: version "0.18.0" resolved "https://registry.npmjs.org/send/-/send-0.18.0.tgz"