增加钱包信息相关接口

This commit is contained in:
cebgcontract 2022-10-25 15:27:17 +08:00
parent ed9977cab8
commit 7bebce5b7d
10 changed files with 474 additions and 210 deletions

View File

@ -1,7 +1,8 @@
API_PORT=3006
API_HOST=127.0.0.1
API_PORT=3007
API_HOST=10.0.1.3
API_TOKEN_SECRET=sdf(**&*&xx2213
API_TOKEN_EXPIRESIN=1d
GOOGLE_OAUTH_CLIENT="165555585193-glmtnb94s3kkq906hal72ppiuoqpjjc5.apps.googleusercontent.com"
DB_MAIN=mongodb://localhost/wallet-development

View File

@ -21,8 +21,10 @@
"dotenv": "^16.0.3",
"fastify": "^4.8.1",
"fastify-plugin": "^4.2.1",
"google-auth-library": "^8.5.2",
"mongoose": "^6.6.5",
"mongoose-findorcreate": "^3.0.0",
"nanoid": "^3.1.23",
"tracer": "^1.1.6"
},
"devDependencies": {

View File

@ -1,73 +1,66 @@
import fastify, {
FastifyError,
FastifyInstance,
FastifyReply,
FastifyRequest,
} from "fastify";
import helmet from "@fastify/helmet";
import { IncomingMessage, Server, ServerResponse } from "http";
import { RouterMap } from "decorators/router";
import { mongoose } from "@typegoose/typegoose";
import logger from "logger/logger";
import config from "config/config";
import fastify, { FastifyError, FastifyInstance, FastifyReply, FastifyRequest } from 'fastify'
import helmet from '@fastify/helmet'
import { IncomingMessage, Server, ServerResponse } from 'http'
import { RouterMap } from 'decorators/router'
import { mongoose } from '@typegoose/typegoose'
import logger from 'logger/logger'
import config from 'config/config'
import { ConnectOptions } from 'mongoose'
const zReqParserPlugin = require("plugins/zReqParser");
const zReqParserPlugin = require('plugins/zReqParser')
const zTokenParserPlugin = require("plugins/zTokenParser");
const zTokenParserPlugin = require('plugins/zTokenParser')
const apiAuthPlugin = require("plugins/apiauth");
const apiAuthPlugin = require('plugins/apiauth')
const fs = require("fs");
const join = require("path").join;
const fs = require('fs')
const join = require('path').join
require("./common/Extend");
require('./common/Extend')
export class ApiServer {
server: FastifyInstance<Server, IncomingMessage, ServerResponse>;
server: FastifyInstance<Server, IncomingMessage, ServerResponse>
public constructor() {
this.server = fastify({ logger: true, trustProxy: true });
this.registerPlugins();
this.server = fastify({ logger: true, trustProxy: true })
this.registerPlugins()
}
private registerPlugins() {
this.server.register(require("@fastify/formbody"));
this.server.register(zReqParserPlugin);
this.server.register(helmet, { hidePoweredBy: false });
this.server.register(zTokenParserPlugin);
this.server.register(require('@fastify/formbody'))
this.server.register(zReqParserPlugin)
this.server.register(helmet, { hidePoweredBy: false })
this.server.register(zTokenParserPlugin)
this.server.register(apiAuthPlugin, {
secret: config.api.token_secret,
expiresIn: config.api.token_expiresIn,
});
})
this.server.register(require("@fastify/cors"), {});
this.server.register(require('@fastify/cors'), {})
}
private registerRouter() {
logger.log("register api routers");
let self = this;
logger.log('register api routers')
let self = this
for (let [controller, config] of RouterMap.decoratedRouters) {
for (let data of config.data) {
logger.info(
"add router",
data.method || "all",
'add router',
data.method || 'all',
data.path,
`${data.target.constructor.name}.${controller.name}()`
);
`${data.target.constructor.name}.${controller.name}()`,
)
// @ts-ignore
self.server[data.method || "all"](
self.server[data.method || 'all'](
data.path,
{
preValidation: async function (
request: FastifyRequest,
reply: FastifyReply
) {
request.roles = config.roles;
await this.apiAuth(request, reply);
preValidation: async function (request: FastifyRequest, reply: FastifyReply) {
request.roles = config.roles
await this.apiAuth(request, reply)
},
},
controller
);
controller,
)
}
}
}
@ -75,58 +68,53 @@ export class ApiServer {
* controller
*/
initControllers() {
logger.info("Bootstrap controllers...");
const controllers = join(__dirname, "./controllers");
logger.info('Bootstrap controllers...')
const controllers = join(__dirname, './controllers')
fs.readdirSync(controllers)
.filter((file: string) => ~file.search(/^[^.].*\.(ts|js)$/))
.forEach((file: any) => {
// logger.log(file);
return require(join(controllers, file));
});
return require(join(controllers, file))
})
}
async connectDB() {
const options = {
useNewUrlParser: true,
poolSize: 5,
const options: ConnectOptions = {
minPoolSize: 5,
maxPoolSize: 10,
keepAlive: true,
keepAliveInitialDelay: 300000,
useUnifiedTopology: true,
};
const uri = config.db_main;
logger.info(`connect to ${uri} ...`);
}
const uri = config.db_main
logger.info(`connect to ${uri} ...`)
try {
// await mongoose.createConnection(uri, options)
await mongoose.connect(uri, options);
logger.log("DB Connected");
await mongoose.connect(uri, options)
logger.log('DB Connected')
} catch (err) {
logger.log(`DB Connection Error: ${err.message}`);
logger.log(`DB Connection Error: ${err.message}`)
}
}
private setErrHandler() {
this.server.setNotFoundHandler(function (
request: any,
reply: { send: (arg0: { errcode: number; errmsg: string }) => void }
reply: { send: (arg0: { errcode: number; errmsg: string }) => void },
) {
reply.send({ errcode: 404, errmsg: "page not found" });
});
this.server.setErrorHandler(function (
error: FastifyError,
request: FastifyRequest,
reply: FastifyReply
) {
let statusCode = (error && error.statusCode) || 100;
reply.send({ errcode: 404, errmsg: 'page not found' })
})
this.server.setErrorHandler(function (error: FastifyError, request: FastifyRequest, reply: FastifyReply) {
let statusCode = (error && error.statusCode) || 100
if (statusCode >= 500) {
logger.error(error);
logger.error(error)
} else if (statusCode >= 400) {
logger.info(error);
logger.info(error)
} else {
logger.error(error);
logger.error(error)
}
reply.code(200).send({
errcode: statusCode,
errmsg: error ? error.message : "unknown error",
});
});
errmsg: error ? error.message : 'unknown error',
})
})
}
/**
* ,
@ -138,40 +126,34 @@ export class ApiServer {
* @private
*/
private setFormatSend() {
this.server.addHook(
"preSerialization",
async (request: FastifyRequest, reply: FastifyReply, payload) => {
reply.header("X-Powered-By", "PHP/5.4.16");
// @ts-ignore
if (!payload.errcode) {
payload = {
errcode: 0,
data: payload,
};
this.server.addHook('preSerialization', async (request: FastifyRequest, reply: FastifyReply, payload) => {
reply.header('X-Powered-By', 'PHP/5.4.16')
// @ts-ignore
if (!payload.errcode) {
payload = {
errcode: 0,
data: payload,
}
return payload;
}
);
return payload
})
}
public async start() {
let self = this;
let self = this
return new Promise(async (resolve, reject) => {
await self.connectDB();
self.initControllers();
self.registerRouter();
self.setErrHandler();
self.setFormatSend();
await self.connectDB()
self.initControllers()
self.registerRouter()
self.setErrHandler()
self.setFormatSend()
// new Schedule().start();
this.server.listen(
{ port: config.api.port },
(err: any, address: any) => {
if (err) {
logger.log(err);
process.exit(0);
}
resolve && resolve(address);
this.server.listen({ port: config.api.port, host: config.api.host }, (err: any, address: any) => {
if (err) {
logger.log(err)
process.exit(0)
}
);
});
resolve && resolve(address)
})
})
}
}

View File

@ -1,11 +1,97 @@
import BaseController from "common/base.controller";
import { role, router } from "decorators/router";
import BaseController from 'common/base.controller'
import { ZError } from 'common/ZError'
import { role, router } from 'decorators/router'
import { OAuth2Client } from 'google-auth-library'
import { Account, PlatEnum } from 'modules/Account'
import { Wallet } from 'modules/Wallet'
import { WalletExt } from 'modules/WalletExt'
import { customAlphabet } from 'nanoid'
const nanoid = customAlphabet('1234567890abcdef', 10)
const GOOGLE_OAUTH_ISS = 'https://accounts.google.com'
const GOOGLE_OAUTH_ISS1 = 'accounts.google.com'
class MainController extends BaseController {
@role("anon")
@router("post /client/login")
@role('anon')
@router('post /client/login')
async clientLogin(req, res) {
const { code, token } = req.params;
return {};
const { code, token } = req.params
return {}
}
@role('anon')
@router('post /wallet/login/google')
async checkGoogleJwt(req, res) {
const { token } = req.params
const CLIENT_ID = process.env.GOOGLE_OAUTH_CLIENT
const client = new OAuth2Client(CLIENT_ID)
const ticket = await client.verifyIdToken({
idToken: token,
audience: CLIENT_ID, // Specify the CLIENT_ID of the app that accesses the backend
// Or, if multiple clients access the backend:
//[CLIENT_ID_1, CLIENT_ID_2, CLIENT_ID_3]
})
const payload = ticket.getPayload()
if (!(payload.iss === GOOGLE_OAUTH_ISS || payload.iss === GOOGLE_OAUTH_ISS1)) {
throw new ZError(10, 'id token error')
}
if (payload.aud !== CLIENT_ID) {
throw new ZError(11, 'client id mismatch')
}
const openId = payload.sub
let data: any = {
email: payload.email,
emailVerified: payload.email_verified,
}
if (payload.locale) data.locale = payload.locale
if (payload.name) data.nickname = payload.name
if (payload.picture) data.avatar = payload.picture
let user = await Account.insertOrUpdate({ plat: PlatEnum.GOOGLE, openId }, data)
const ztoken = await res.jwtSign({ id: user.id })
return { token: ztoken }
}
@router('get /wallet/info')
async getWalletInfo(req, res) {
let user = req.user
let record = await Wallet.insertOrUpdate({ account: user.id }, {})
let data: any = { oid: user.id }
if (record.nweRecord) {
record.salt = nanoid()
record.is = nanoid(12)
record.nweRecord = false
await record.save()
}
Object.assign(data, record.toJson())
return data
}
@router('post /wallet/info')
async uploadWalletInfo(req, res) {
let user = req.user
let { key } = req.params
if (!key) {
throw new ZError(10, 'no data to save')
}
let record = await Wallet.insertOrUpdate({ account: user.id }, {})
record.key = key
await record.save()
return {}
}
@router('get /wallet/collection')
async getUserCollection(req, res) {
let user = req.user
let { data } = req.params
await WalletExt.insertOrUpdate({ account: user.id }, { data })
return {}
}
@router('post /wallet/collection')
async uploadUserCollection(req, res) {
let user = req.user
let record = await WalletExt.insertOrUpdate({ account: user.id }, {})
return record.data
}
}

View File

@ -8,11 +8,6 @@ export function dbconn(name?: string) {
return target => {
name = name || 'main'
const url = config['db_' + name]
target['db'] = mongoose.createConnection(url, {
useNewUrlParser: true,
useCreateIndex: true,
useFindAndModify: false,
useUnifiedTopology: true,
})
target['db'] = mongoose.createConnection(url, {})
}
}

41
src/modules/Account.ts Normal file
View File

@ -0,0 +1,41 @@
import { getModelForClass, index, modelOptions, prop } from '@typegoose/typegoose'
import { dbconn } from 'decorators/dbconn'
import { Base, TimeStamps } from '@typegoose/typegoose/lib/defaultClasses'
import { BaseModule } from './Base'
export enum PlatEnum {
GOOGLE = 0,
}
interface AccountClass extends Base, TimeStamps {}
@dbconn()
@index({ plat: 1, openId: 1 }, { unique: true })
@modelOptions({ schemaOptions: { collection: 'account', timestamps: true } })
class AccountClass extends BaseModule {
@prop({ enum: PlatEnum, default: PlatEnum.GOOGLE })
public plat!: PlatEnum
@prop({ required: true })
public openId!: string
@prop()
public nickname?: string
@prop()
public avatar?: string
@prop()
public email?: string
@prop({ required: true, default: false })
public emailVerified: boolean
@prop({ default: 0 })
public sex?: string
@prop()
public locale?: string
@prop({ default: false })
public locked: boolean
@prop()
public lockedTime?: Date
@prop()
public comment?: string
@prop()
public lastLogin?: Date
}
export const Account = getModelForClass(AccountClass, { existingConnection: AccountClass.db })

43
src/modules/Wallet.ts Normal file
View File

@ -0,0 +1,43 @@
import { getModelForClass, index, modelOptions, mongoose, prop, Severity } from '@typegoose/typegoose'
import { dbconn } from 'decorators/dbconn'
import { BaseModule } from './Base'
@dbconn()
@index({ account: 1 }, { unique: true })
@modelOptions({
schemaOptions: { collection: 'wallet', timestamps: true },
})
class WalletClass extends BaseModule {
@prop({ required: true })
public account!: string
/**
* master key
*/
@prop()
public key: string
/**
*
*/
@prop()
public is: string
/**
*
*/
@prop()
public salt: string
@prop({ required: true, default: true })
public nweRecord: boolean
public toJson() {
return {
key: this.key,
is: this.is,
salt: this.salt,
}
}
}
export const Wallet = getModelForClass(WalletClass, { existingConnection: WalletClass.db })

22
src/modules/WalletExt.ts Normal file
View File

@ -0,0 +1,22 @@
import { getModelForClass, index, modelOptions, mongoose, prop, Severity } from '@typegoose/typegoose'
import { dbconn } from 'decorators/dbconn'
import { BaseModule } from './Base'
@dbconn()
@index({ account: 1 }, { unique: true })
@modelOptions({
schemaOptions: { collection: 'wallet_ext', timestamps: true },
options: { allowMixed: Severity.ALLOW },
})
class WalletExtClass extends BaseModule {
@prop({ required: true })
public account!: string
@prop({ type: mongoose.Schema.Types.Mixed })
public data: any
@prop({ required: true, default: true })
public nweRecord: boolean
}
export const WalletExt = getModelForClass(WalletExtClass, { existingConnection: WalletExtClass.db })

View File

@ -1,55 +1,50 @@
import { FastifyPluginAsync, FastifyReply, FastifyRequest } from "fastify";
import fastifyPlugin from "fastify-plugin";
import { FastifyPluginAsync, FastifyReply, FastifyRequest } from 'fastify'
import fastifyPlugin from 'fastify-plugin'
import { Account } from 'modules/Account'
declare module "fastify" {
declare module 'fastify' {
interface FastifyRequest {
roles?: string[];
user?: any;
token?: string;
roles?: string[]
user?: any
token?: string
}
interface FastifyInstance {
apiAuth: (request: FastifyRequest, reply: FastifyReply) => {};
apiAuth: (request: FastifyRequest, reply: FastifyReply) => {}
}
}
export interface ApiAuthOptions {
secret: string;
expiresIn: string;
secret: string
expiresIn: string
}
const apiAuthPlugin: FastifyPluginAsync<ApiAuthOptions> = async function (
fastify,
opts
) {
fastify.register(require("@fastify/jwt"), {
const apiAuthPlugin: FastifyPluginAsync<ApiAuthOptions> = async function (fastify, opts) {
fastify.register(require('@fastify/jwt'), {
secret: opts.secret,
sign: { expiresIn: opts.expiresIn },
});
})
// 只有路由配置的role为anon才不需要过滤
fastify.decorate(
"apiAuth",
async function (request: FastifyRequest, reply: FastifyReply) {
if (!request.roles || request.roles.indexOf("anon") == -1) {
try {
if (!request.token) {
return reply.send({ code: 11, msg: "need login" });
}
//@ts-ignore
const data = this.jwt.verify(request.token);
if (!data || !data.id) {
return reply.send({ code: 10, msg: "need login" });
}
// let account = await Account.findById(data.id)
// if (!account) {
// return reply.send({ code: 10, msg: 'need login' })
// }
// request.user = account
} catch (err) {
return reply.send({ code: 401, msg: "need auth" });
fastify.decorate('apiAuth', async function (request: FastifyRequest, reply: FastifyReply) {
if (!request.roles || request.roles.indexOf('anon') == -1) {
try {
if (!request.token) {
return reply.send({ code: 11, msg: 'need login' })
}
//@ts-ignore
const data = this.jwt.verify(request.token)
if (!data || !data.id) {
return reply.send({ code: 10, msg: 'need login' })
}
let account = await Account.findById(data.id)
if (!account) {
return reply.send({ code: 10, msg: 'need login' })
}
request.user = account
} catch (err) {
return reply.send({ code: 401, msg: 'need auth' })
}
}
);
};
})
}
export default fastifyPlugin(apiAuthPlugin, "4.x");
export default fastifyPlugin(apiAuthPlugin, '4.x')

215
yarn.lock
View File

@ -148,40 +148,6 @@
"@nodelib/fs.scandir" "2.1.5"
fastq "^1.6.0"
"@redis/bloom@1.0.2":
version "1.0.2"
resolved "https://registry.npmmirror.com/@redis/bloom/-/bloom-1.0.2.tgz#42b82ec399a92db05e29fffcdfd9235a5fc15cdf"
integrity sha512-EBw7Ag1hPgFzdznK2PBblc1kdlj5B5Cw3XwI9/oG7tSn85/HKy3X9xHy/8tm/eNXJYHLXHJL/pkwBpFMVVefkw==
"@redis/client@1.3.0":
version "1.3.0"
resolved "https://registry.npmmirror.com/@redis/client/-/client-1.3.0.tgz#c62ccd707f16370a2dc2f9e158a28b7da049fa77"
integrity sha512-XCFV60nloXAefDsPnYMjHGtvbtHR8fV5Om8cQ0JYqTNbWcQo/4AryzJ2luRj4blveWazRK/j40gES8M7Cp6cfQ==
dependencies:
cluster-key-slot "1.1.0"
generic-pool "3.8.2"
yallist "4.0.0"
"@redis/graph@1.0.1":
version "1.0.1"
resolved "https://registry.npmmirror.com/@redis/graph/-/graph-1.0.1.tgz#eabc58ba99cd70d0c907169c02b55497e4ec8a99"
integrity sha512-oDE4myMCJOCVKYMygEMWuriBgqlS5FqdWerikMoJxzmmTUErnTRRgmIDa2VcgytACZMFqpAOWDzops4DOlnkfQ==
"@redis/json@1.0.4":
version "1.0.4"
resolved "https://registry.npmmirror.com/@redis/json/-/json-1.0.4.tgz#f372b5f93324e6ffb7f16aadcbcb4e5c3d39bda1"
integrity sha512-LUZE2Gdrhg0Rx7AN+cZkb1e6HjoSKaeeW8rYnt89Tly13GBI5eP4CwDVr+MY8BAYfCg4/N15OUrtLoona9uSgw==
"@redis/search@1.1.0":
version "1.1.0"
resolved "https://registry.npmmirror.com/@redis/search/-/search-1.1.0.tgz#7abb18d431f27ceafe6bcb4dd83a3fa67e9ab4df"
integrity sha512-NyFZEVnxIJEybpy+YskjgOJRNsfTYqaPbK/Buv6W2kmFNaRk85JiqjJZA5QkRmWvGbyQYwoO5QfDi2wHskKrQQ==
"@redis/time-series@1.0.3":
version "1.0.3"
resolved "https://registry.npmmirror.com/@redis/time-series/-/time-series-1.0.3.tgz#4cfca8e564228c0bddcdf4418cba60c20b224ac4"
integrity sha512-OFp0q4SGrTH0Mruf6oFsHGea58u8vS/iI5+NpYdicaM+7BgqBZH8FFvNZ8rYYLrUO/QRqMq72NpXmxLVNcdmjA==
"@tsconfig/node10@^1.0.7":
version "1.0.9"
resolved "https://registry.npmmirror.com/@tsconfig/node10/-/node10-1.0.9.tgz#df4907fc07a886922637b15e02d4cebc4c0021b2"
@ -367,6 +333,13 @@ acorn@^8.4.1, acorn@^8.8.0:
resolved "https://registry.npmmirror.com/acorn/-/acorn-8.8.0.tgz#88c0187620435c7f6015803f5539dae05a9dbea8"
integrity sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==
agent-base@6:
version "6.0.2"
resolved "https://registry.npmmirror.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77"
integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==
dependencies:
debug "4"
ajv-formats@^2.1.1:
version "2.1.1"
resolved "https://registry.npmmirror.com/ajv-formats/-/ajv-formats-2.1.1.tgz#6e669400659eb74973bbf2e33327180a0996b520"
@ -434,6 +407,11 @@ array-union@^2.1.0:
resolved "https://registry.npmmirror.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d"
integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==
arrify@^2.0.0:
version "2.0.1"
resolved "https://registry.npmmirror.com/arrify/-/arrify-2.0.1.tgz#c9655e9331e0abcd588d2a7cad7e9956f66701fa"
integrity sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==
asn1.js@^5.3.0:
version "5.4.1"
resolved "https://registry.npmmirror.com/asn1.js/-/asn1.js-5.4.1.tgz#11a980b84ebb91781ce35b0fdc2ee294e3783f07"
@ -477,11 +455,16 @@ balanced-match@^1.0.0:
resolved "https://registry.npmmirror.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==
base64-js@^1.3.1:
base64-js@^1.3.0, base64-js@^1.3.1:
version "1.5.1"
resolved "https://registry.npmmirror.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a"
integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==
bignumber.js@^9.0.0:
version "9.1.0"
resolved "https://registry.npmmirror.com/bignumber.js/-/bignumber.js-9.1.0.tgz#8d340146107fe3a6cb8d40699643c302e8773b62"
integrity sha512-4LwHK4nfDOraBCtst+wOWIHbu1vhvAPJK8g8nROd4iuc3PSEjWif/qwbkh8jwCJz6yDBvtU4KPynETgrfh7y3A==
binary-extensions@^2.0.0:
version "2.2.0"
resolved "https://registry.npmmirror.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d"
@ -514,6 +497,11 @@ bson@^4.6.5, bson@^4.7.0:
dependencies:
buffer "^5.6.0"
buffer-equal-constant-time@1.0.1:
version "1.0.1"
resolved "https://registry.npmmirror.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819"
integrity sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==
buffer-from@^1.0.0:
version "1.1.2"
resolved "https://registry.npmmirror.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5"
@ -563,11 +551,6 @@ chokidar@^3.5.1:
optionalDependencies:
fsevents "~2.3.2"
cluster-key-slot@1.1.0:
version "1.1.0"
resolved "https://registry.npmmirror.com/cluster-key-slot/-/cluster-key-slot-1.1.0.tgz#30474b2a981fb12172695833052bc0d01336d10d"
integrity sha512-2Nii8p3RwAPiFwsnZvukotvow2rIHM+yQ6ZcBXGHdniadkYGZYiGmkHJIbZPIV9nfv7m/U1IPMVVcAhoWFeklw==
color-convert@^2.0.1:
version "2.0.1"
resolved "https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3"
@ -621,7 +604,7 @@ dateformat@4.5.1:
resolved "https://registry.npmmirror.com/dateformat/-/dateformat-4.5.1.tgz#c20e7a9ca77d147906b6dc2261a8be0a5bd2173c"
integrity sha512-OD0TZ+B7yP7ZgpJf5K2DIbj3FZvFvxgFUuaqA/V5zTjAtAAXZ1E8bktHxmAGs4x5b7PflqA9LeQ84Og7wYtF7Q==
debug@4.x, debug@^4.0.0, debug@^4.1.1, debug@^4.3.2, debug@^4.3.4:
debug@4, debug@4.x, debug@^4.0.0, debug@^4.1.1, debug@^4.3.2, debug@^4.3.4:
version "4.3.4"
resolved "https://registry.npmmirror.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865"
integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==
@ -674,7 +657,7 @@ dynamic-dedupe@^0.3.0:
dependencies:
xtend "^4.0.0"
ecdsa-sig-formatter@^1.0.11:
ecdsa-sig-formatter@1.0.11, ecdsa-sig-formatter@^1.0.11:
version "1.0.11"
resolved "https://registry.npmmirror.com/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz#ae0f0fa2d85045ef14a817daa3ce9acd0489e5bf"
integrity sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==
@ -823,6 +806,11 @@ events@^3.3.0:
resolved "https://registry.npmmirror.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400"
integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==
extend@^3.0.2:
version "3.0.2"
resolved "https://registry.npmmirror.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa"
integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==
fast-decode-uri-component@^1.0.1:
version "1.0.1"
resolved "https://registry.npmmirror.com/fast-decode-uri-component/-/fast-decode-uri-component-1.0.1.tgz#46f8b6c22b30ff7a81357d4f59abfae938202543"
@ -892,6 +880,11 @@ fast-redact@^3.1.1:
resolved "https://registry.npmmirror.com/fast-redact/-/fast-redact-3.1.2.tgz#d58e69e9084ce9fa4c1a6fa98a3e1ecf5d7839aa"
integrity sha512-+0em+Iya9fKGfEQGcd62Yv6onjBmmhV1uh86XVfOU8VwAe6kaFdQCWI9s0/Nnugx5Vd9tdbZ7e6gE2tR9dzXdw==
fast-text-encoding@^1.0.0:
version "1.0.6"
resolved "https://registry.npmmirror.com/fast-text-encoding/-/fast-text-encoding-1.0.6.tgz#0aa25f7f638222e3396d72bf936afcf1d42d6867"
integrity sha512-VhXlQgj9ioXCqGstD37E/HBeqEGV/qOD/kmbVG8h5xKBYvM1L3lR1Zn4555cQ8GkYbJa8aJSipLPndE1k6zK2w==
fast-uri@^2.0.0, fast-uri@^2.1.0:
version "2.1.0"
resolved "https://registry.npmmirror.com/fast-uri/-/fast-uri-2.1.0.tgz#9279432d6b53675c90116b947ed2bbba582d6fb5"
@ -1030,10 +1023,23 @@ function-bind@^1.1.1:
resolved "https://registry.npmmirror.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==
generic-pool@3.8.2:
version "3.8.2"
resolved "https://registry.npmmirror.com/generic-pool/-/generic-pool-3.8.2.tgz#aab4f280adb522fdfbdc5e5b64d718d3683f04e9"
integrity sha512-nGToKy6p3PAbYQ7p1UlWl6vSPwfwU6TMSWK7TTu+WUY4ZjyZQGniGGt2oNVvyNSpyZYSB43zMXVLcBm08MTMkg==
gaxios@^5.0.0, gaxios@^5.0.1:
version "5.0.2"
resolved "https://registry.npmmirror.com/gaxios/-/gaxios-5.0.2.tgz#ca3a40e851c728d31d7001c2357062d46bf966d1"
integrity sha512-TjtV2AJOZoMQqRYoy5eM8cCQogYwazWNYLQ72QB0kwa6vHHruYkGmhhyrlzbmgNHK1dNnuP2WSH81urfzyN2Og==
dependencies:
extend "^3.0.2"
https-proxy-agent "^5.0.0"
is-stream "^2.0.0"
node-fetch "^2.6.7"
gcp-metadata@^5.0.0:
version "5.0.1"
resolved "https://registry.npmmirror.com/gcp-metadata/-/gcp-metadata-5.0.1.tgz#8d1e785ee7fad554bc2a80c1f930c9a9518d2b00"
integrity sha512-jiRJ+Fk7e8FH68Z6TLaqwea307OktJpDjmYnU7/li6ziwvVvU2RlrCyQo5vkdeP94chm0kcSCOOszvmuaioq3g==
dependencies:
gaxios "^5.0.0"
json-bigint "^1.0.0"
glob-parent@^5.1.2, glob-parent@~5.1.2:
version "5.1.2"
@ -1080,11 +1086,42 @@ globby@^11.1.0:
merge2 "^1.4.1"
slash "^3.0.0"
google-auth-library@^8.5.2:
version "8.5.2"
resolved "https://registry.npmmirror.com/google-auth-library/-/google-auth-library-8.5.2.tgz#bcdced8f7b475b80bf0e9c109c7c7e930866947b"
integrity sha512-FPfOSaI8n2TVXFHTP8/vAVFCXhyALj7w9/Rgefux3oeKZ/nQDNmfNTJ+lIKcoYT1cKkvMllp1Eood7Y5L+TP+A==
dependencies:
arrify "^2.0.0"
base64-js "^1.3.0"
ecdsa-sig-formatter "^1.0.11"
fast-text-encoding "^1.0.0"
gaxios "^5.0.0"
gcp-metadata "^5.0.0"
gtoken "^6.1.0"
jws "^4.0.0"
lru-cache "^6.0.0"
google-p12-pem@^4.0.0:
version "4.0.1"
resolved "https://registry.npmmirror.com/google-p12-pem/-/google-p12-pem-4.0.1.tgz#82841798253c65b7dc2a4e5fe9df141db670172a"
integrity sha512-WPkN4yGtz05WZ5EhtlxNDWPhC4JIic6G8ePitwUWy4l+XPVYec+a0j0Ts47PDtW59y3RwAhUd9/h9ZZ63px6RQ==
dependencies:
node-forge "^1.3.1"
grapheme-splitter@^1.0.4:
version "1.0.4"
resolved "https://registry.npmmirror.com/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz#9cf3a665c6247479896834af35cf1dbb4400767e"
integrity sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==
gtoken@^6.1.0:
version "6.1.2"
resolved "https://registry.npmmirror.com/gtoken/-/gtoken-6.1.2.tgz#aeb7bdb019ff4c3ba3ac100bbe7b6e74dce0e8bc"
integrity sha512-4ccGpzz7YAr7lxrT2neugmXQ3hP9ho2gcaityLVkiUecAiwiy60Ii8gRbZeOsXV19fYaRjgBSshs8kXw+NKCPQ==
dependencies:
gaxios "^5.0.1"
google-p12-pem "^4.0.0"
jws "^4.0.0"
has-flag@^4.0.0:
version "4.0.0"
resolved "https://registry.npmmirror.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b"
@ -1102,6 +1139,14 @@ helmet@^6.0.0:
resolved "https://registry.npmmirror.com/helmet/-/helmet-6.0.0.tgz#8e183820ddccd7729a206ad73c577b264f495595"
integrity sha512-FO9RpR1wNJepH/GbLPQVtkE2eESglXL641p7SdyoT4LngHFJcZheHMoyUcjCZF4qpuMMO1u5q6RK0l9Ux8JBcg==
https-proxy-agent@^5.0.0:
version "5.0.1"
resolved "https://registry.npmmirror.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6"
integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==
dependencies:
agent-base "6"
debug "4"
ieee754@^1.1.13, ieee754@^1.2.1:
version "1.2.1"
resolved "https://registry.npmmirror.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352"
@ -1179,6 +1224,11 @@ is-number@^7.0.0:
resolved "https://registry.npmmirror.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b"
integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==
is-stream@^2.0.0:
version "2.0.1"
resolved "https://registry.npmmirror.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077"
integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==
isexe@^2.0.0:
version "2.0.0"
resolved "https://registry.npmmirror.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
@ -1196,6 +1246,13 @@ js-yaml@^4.1.0:
dependencies:
argparse "^2.0.1"
json-bigint@^1.0.0:
version "1.0.0"
resolved "https://registry.npmmirror.com/json-bigint/-/json-bigint-1.0.0.tgz#ae547823ac0cad8398667f8cd9ef4730f5b01ff1"
integrity sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==
dependencies:
bignumber.js "^9.0.0"
json-schema-traverse@^0.4.1:
version "0.4.1"
resolved "https://registry.npmmirror.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660"
@ -1216,6 +1273,23 @@ json5@^2.2.1:
resolved "https://registry.npmmirror.com/json5/-/json5-2.2.1.tgz#655d50ed1e6f95ad1a3caababd2b0efda10b395c"
integrity sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==
jwa@^2.0.0:
version "2.0.0"
resolved "https://registry.npmmirror.com/jwa/-/jwa-2.0.0.tgz#a7e9c3f29dae94027ebcaf49975c9345593410fc"
integrity sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA==
dependencies:
buffer-equal-constant-time "1.0.1"
ecdsa-sig-formatter "1.0.11"
safe-buffer "^5.0.1"
jws@^4.0.0:
version "4.0.0"
resolved "https://registry.npmmirror.com/jws/-/jws-4.0.0.tgz#2d4e8cf6a318ffaa12615e9dec7e86e6c97310f4"
integrity sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==
dependencies:
jwa "^2.0.0"
safe-buffer "^5.0.1"
kareem@2.4.1:
version "2.4.1"
resolved "https://registry.npmmirror.com/kareem/-/kareem-2.4.1.tgz#7d81ec518204a48c1cb16554af126806c3cd82b0"
@ -1398,11 +1472,28 @@ ms@2.1.3:
resolved "https://registry.npmmirror.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
nanoid@^3.1.23:
version "3.3.4"
resolved "https://registry.npmmirror.com/nanoid/-/nanoid-3.3.4.tgz#730b67e3cd09e2deacf03c027c81c9d9dbc5e8ab"
integrity sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==
natural-compare@^1.4.0:
version "1.4.0"
resolved "https://registry.npmmirror.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==
node-fetch@^2.6.7:
version "2.6.7"
resolved "https://registry.npmmirror.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad"
integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==
dependencies:
whatwg-url "^5.0.0"
node-forge@^1.3.1:
version "1.3.1"
resolved "https://registry.npmmirror.com/node-forge/-/node-forge-1.3.1.tgz#be8da2af243b2417d5f646a770663a92b7e9ded3"
integrity sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==
normalize-path@^3.0.0, normalize-path@~3.0.0:
version "3.0.0"
resolved "https://registry.npmmirror.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65"
@ -1595,18 +1686,6 @@ real-require@^0.2.0:
resolved "https://registry.npmmirror.com/real-require/-/real-require-0.2.0.tgz#209632dea1810be2ae063a6ac084fee7e33fba78"
integrity sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==
redis@^4.3.1:
version "4.3.1"
resolved "https://registry.npmmirror.com/redis/-/redis-4.3.1.tgz#290532a0c22221e05e991162ac4dca1e1b2ff6da"
integrity sha512-cM7yFU5CA6zyCF7N/+SSTcSJQSRMEKN0k0Whhu6J7n9mmXRoXugfWDBo5iOzGwABmsWKSwGPTU5J4Bxbl+0mrA==
dependencies:
"@redis/bloom" "1.0.2"
"@redis/client" "1.3.0"
"@redis/graph" "1.0.1"
"@redis/json" "1.0.4"
"@redis/search" "1.1.0"
"@redis/time-series" "1.0.3"
reflect-metadata@^0.1.13:
version "0.1.13"
resolved "https://registry.npmmirror.com/reflect-metadata/-/reflect-metadata-0.1.13.tgz#67ae3ca57c972a2aa1642b10fe363fe32d49dc08"
@ -1866,6 +1945,11 @@ tr46@^3.0.0:
dependencies:
punycode "^2.1.1"
tr46@~0.0.3:
version "0.0.3"
resolved "https://registry.npmmirror.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a"
integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==
tracer@^1.1.6:
version "1.1.6"
resolved "https://registry.npmmirror.com/tracer/-/tracer-1.1.6.tgz#5afc5ea0d7c6026dbafb36bed86e88cafe9bebad"
@ -1981,6 +2065,11 @@ v8-compile-cache-lib@^3.0.1:
resolved "https://registry.npmmirror.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf"
integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==
webidl-conversions@^3.0.0:
version "3.0.1"
resolved "https://registry.npmmirror.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871"
integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==
webidl-conversions@^7.0.0:
version "7.0.0"
resolved "https://registry.npmmirror.com/webidl-conversions/-/webidl-conversions-7.0.0.tgz#256b4e1882be7debbf01d05f0aa2039778ea080a"
@ -1994,6 +2083,14 @@ whatwg-url@^11.0.0:
tr46 "^3.0.0"
webidl-conversions "^7.0.0"
whatwg-url@^5.0.0:
version "5.0.0"
resolved "https://registry.npmmirror.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d"
integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==
dependencies:
tr46 "~0.0.3"
webidl-conversions "^3.0.0"
which@^2.0.1:
version "2.0.2"
resolved "https://registry.npmmirror.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1"
@ -2016,7 +2113,7 @@ xtend@^4.0.0, xtend@^4.0.2:
resolved "https://registry.npmmirror.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54"
integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==
yallist@4.0.0, yallist@^4.0.0:
yallist@^4.0.0:
version "4.0.0"
resolved "https://registry.npmmirror.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"
integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==