chore: lint with sxzz config

Signed-off-by: Innei <i@innei.in>
This commit is contained in:
Innei
2024-04-29 15:59:43 +08:00
parent c12bd99242
commit e5ac04a650
242 changed files with 1089 additions and 1482 deletions

View File

@@ -1,17 +0,0 @@
assets/types/type.declare.ts
node_modules
dist
out
packages/*/node_modules
packages/*/dist
packages/*/out
packages/*/lib
packages/*/build
packages/*/coverage
packages/*/test
packages/*/tests
packages/*/esm
packages/*/types
test/**/*.db.ts

View File

@@ -1,37 +0,0 @@
module.exports = {
extends: ['@innei/eslint-config-ts'],
root: true,
parserOptions: {
emitDecoratorMetadata: true,
},
plugins: ['unused-imports', '@typescript-eslint'],
rules: {
'no-empty': 'warn',
'no-fallthrough': 'error',
'no-unused-vars': 'off', // or "@typescript-eslint/no-unused-vars": "off",
'@typescript-eslint/no-unused-vars': 'off',
'unused-imports/no-unused-imports': 'error',
'unused-imports/no-unused-vars': [
'warn',
{
vars: 'all',
varsIgnorePattern: '^_',
args: 'after-used',
argsIgnorePattern: '^_',
},
],
},
overrides: [
{
files: [
'apps/core/src/migration/**/*.ts',
'apps/core/src/modules/serverless/pack/**/*.ts',
'apps/core/test/**/*.ts',
],
rules: {
'import/no-default-export': 'off',
},
},
],
}

View File

@@ -3,6 +3,7 @@ import { factory } from '@innei/prettier'
export default {
...factory({
tailwindcss: false,
importSort: false,
}),
importOrderParserPlugins: ['typescript', 'jsx', 'decorators-legacy'],
}

View File

@@ -1,5 +1,3 @@
/* eslint-disable @typescript-eslint/consistent-type-imports */
import type { AxiosRequestConfig } from 'axios'
export const PORT = process.env.PORT || 2333

View File

@@ -1,13 +1,12 @@
/* eslint-disable @typescript-eslint/consistent-type-imports */
import { readFileSync } from 'fs'
import path from 'path'
import { readFileSync } from 'node:fs'
import path from 'node:path'
import { program } from 'commander'
import { load as yamlLoad } from 'js-yaml'
import { machineIdSync } from 'node-machine-id'
import type { AxiosRequestConfig } from 'axios'
import { isDebugMode, isDev } from './global/env.global'
import { parseBooleanishValue } from './utils'
import type { AxiosRequestConfig } from 'axios'
const commander = program
.option('-p, --port <number>', 'server port')
@@ -166,9 +165,7 @@ export const ENCRYPT = {
algorithm: argv.encrypt_algorithm || 'aes-256-ecb',
}
if (ENCRYPT.enable) {
if (!ENCRYPT.key || ENCRYPT.key.length !== 64)
throw new Error(
`你开启了 Key 加密MX_ENCRYPT_KEY or --encrypt_key但是 Key 的长度不为 64当前${ENCRYPT.key.length}`,
)
}
if (ENCRYPT.enable && (!ENCRYPT.key || ENCRYPT.key.length !== 64))
throw new Error(
`你开启了 Key 加密MX_ENCRYPT_KEY or --encrypt_key但是 Key 的长度不为 64当前${ENCRYPT.key.length}`,
)

View File

@@ -1,10 +1,4 @@
import { LoggerModule } from 'nestjs-pretty-logger'
import type {
DynamicModule,
MiddlewareConsumer,
NestModule,
Type,
} from '@nestjs/common'
import { Module } from '@nestjs/common'
import { APP_FILTER, APP_GUARD, APP_INTERCEPTOR } from '@nestjs/core'
@@ -66,6 +60,12 @@ import { DatabaseModule } from './processors/database/database.module'
import { GatewayModule } from './processors/gateway/gateway.module'
import { HelperModule } from './processors/helper/helper.module'
import { RedisModule } from './processors/redis/redis.module'
import type {
DynamicModule,
MiddlewareConsumer,
NestModule,
Type,
} from '@nestjs/common'
@Module({
imports: [

View File

@@ -1,9 +1,7 @@
import cluster from 'cluster'
import { performance } from 'perf_hooks'
import cluster from 'node:cluster'
import { performance } from 'node:perf_hooks'
import { Logger } from 'nestjs-pretty-logger'
import wcmatch from 'wildcard-match'
import type { LogLevel } from '@nestjs/common'
import type { NestFastifyApplication } from '@nestjs/platform-fastify'
import { NestFactory } from '@nestjs/core'
@@ -18,6 +16,8 @@ import { logger } from './global/consola.global'
import { isMainProcess, isTest } from './global/env.global'
import { migrateDatabase } from './migration/migrate'
import { checkInit } from './utils/check-init.util'
import type { NestFastifyApplication } from '@nestjs/platform-fastify'
import type { LogLevel } from '@nestjs/common'
const Origin: false | string[] = Array.isArray(CROSS_DOMAIN.allowedOrigins)
? [...CROSS_DOMAIN.allowedOrigins, '*.shizuri.net', '22333322.xyz']

View File

@@ -1,10 +1,10 @@
import cluster from 'cluster'
import os from 'os'
import cluster from 'node:cluster'
import os from 'node:os'
import { logger } from './global/consola.global'
export class Cluster {
static register(workers: number, callback: Function): void {
export const Cluster = {
register(workers: number, callback: Function): void {
if (cluster.isPrimary) {
const cpus = os.cpus().length
@@ -38,7 +38,7 @@ export class Cluster {
cluster.on('online', (worker) => {
logger.info('Worker %s is online', worker.process.pid)
})
cluster.on('exit', (worker, code, signal) => {
cluster.on('exit', (worker, code, _signal) => {
if (code !== 0) {
logger.info(`Worker ${worker.process.pid} died. Restarting`)
cluster.fork()
@@ -47,5 +47,5 @@ export class Cluster {
} else {
callback()
}
}
},
}

View File

@@ -1,11 +1,10 @@
import type { FastifyRequest } from 'fastify'
import fastifyCookie from '@fastify/cookie'
import FastifyMultipart from '@fastify/multipart'
import { Logger } from '@nestjs/common'
import { FastifyAdapter } from '@nestjs/platform-fastify'
import { getIp } from '~/utils'
import type { FastifyRequest } from 'fastify'
const app: FastifyAdapter = new FastifyAdapter({
trustProxy: true,
@@ -39,7 +38,7 @@ app.getInstance().addHook('onRequest', (request, reply, done) => {
logWarn('PHP 是世界上最好的语言!!!!!', request, 'GodPHP')
return reply.code(418).send()
} else if (url.match(/\/(adminer|admin|wp-login|phpMyAdmin|\.env)$/gi)) {
} else if (/\/(adminer|admin|wp-login|phpmyadmin|\.env)$/gi.test(url)) {
const isMxSpaceClient = ua?.match('mx-space')
reply.raw.statusMessage = 'Hey, What the fuck are you doing!'
reply.raw.statusCode = isMxSpaceClient ? 666 : 200
@@ -53,7 +52,7 @@ app.getInstance().addHook('onRequest', (request, reply, done) => {
}
// skip favicon request
if (url.match(/favicon\.ico$/) || url.match(/manifest\.json$/)) {
if (/favicon\.ico$/.test(url) || /manifest\.json$/.test(url)) {
return reply.code(204).send()
}
@@ -64,7 +63,7 @@ app.register(fastifyCookie, {
secret: 'cookie-secret', // 这个 secret 不太重要,不存鉴权相关,无关紧要
})
const logWarn = (desc: string, req: FastifyRequest, context: string) => {
const logWarn = (desc: string, req: FastifyRequest, _context: string) => {
const ua = req.raw.headers['user-agent']
Logger.warn(
// prettier-ignore

View File

@@ -1,9 +1,8 @@
import type { Server } from 'socket.io'
import { IoAdapter } from '@nestjs/platform-socket.io'
import { createAdapter } from '@socket.io/redis-adapter'
import { redisSubPub } from '~/utils/redis-subpub.util'
import type { Server } from 'socket.io'
export const RedisIoAdapterKey = 'mx-core-socket'

View File

@@ -1,9 +1,8 @@
// @reference https://github.com/ever-co/ever-gauzy/blob/d36b4f40b1446f3c33d02e0ba00b53a83109d950/packages/core/src/core/context/request-context.ts
import * as cls from 'cls-hooked'
import type { UserDocument } from '~/modules/user/user.model'
import type { IncomingMessage, ServerResponse } from 'http'
import { UnauthorizedException } from '@nestjs/common'
import type { UserDocument } from '~/modules/user/user.model'
import type { IncomingMessage, ServerResponse } from 'node:http'
type Nullable<T> = T | null
export class RequestContext {
@@ -40,7 +39,7 @@ export class RequestContext {
const requestContext = RequestContext.currentRequestContext()
if (requestContext) {
const user: UserDocument = requestContext.request['user']
const user: UserDocument = requestContext.request.user
if (user) {
return user
@@ -59,8 +58,8 @@ export class RequestContext {
if (requestContext) {
const isAuthenticated =
requestContext.request['isAuthenticated'] ||
requestContext.request['isAuthenticated']
requestContext.request.isAuthenticated ||
requestContext.request.isAuthenticated
return !!isAuthenticated
}

View File

@@ -1,9 +1,8 @@
import type { ControllerOptions } from '@nestjs/common'
import { Controller } from '@nestjs/common'
import { API_VERSION } from '~/app.config'
import { isDev } from '~/global/env.global'
import type { ControllerOptions } from '@nestjs/common'
export const apiRoutePrefix = isDev ? '' : `/api/v${API_VERSION}`
export const ApiController: (

View File

@@ -1,4 +1,4 @@
import { applyDecorators, UseGuards } from '@nestjs/common'
import { UseGuards, applyDecorators } from '@nestjs/common'
import { AuthGuard } from '../guards/auth.guard'

View File

@@ -34,7 +34,7 @@ export function HttpCache(option: ICacheOption): MethodDecorator {
if (key) {
CacheKey(key)(descriptor.value)
}
if (typeof ttl === 'number' && !isNaN(ttl)) {
if (typeof ttl === 'number' && !Number.isNaN(ttl)) {
CacheTTL(ttl)(descriptor.value)
}
return descriptor

View File

@@ -1,8 +1,7 @@
import { createParamDecorator } from '@nestjs/common'
import type { ExecutionContext } from '@nestjs/common'
import type { FastifyRequest } from 'fastify'
import { createParamDecorator } from '@nestjs/common'
export const Cookies = createParamDecorator(
(data: string, ctx: ExecutionContext) => {
const request = ctx.switchToHttp().getRequest<FastifyRequest>()

View File

@@ -1,4 +1,4 @@
import cluster from 'cluster'
import cluster from 'node:cluster'
import { Cron } from '@nestjs/schedule'

View File

@@ -1,8 +1,7 @@
import type { ExecutionContext } from '@nestjs/common'
import { createParamDecorator } from '@nestjs/common'
import { getNestExecutionContextRequest } from '~/transformers/get-req.transformer'
import type { ExecutionContext } from '@nestjs/common'
export const CurrentUser = createParamDecorator(
(data: unknown, ctx: ExecutionContext) => {

View File

@@ -1,10 +1,8 @@
import { UseGuards, applyDecorators } from '@nestjs/common'
import { banInDemo } from '~/utils'
import type { CanActivate } from '@nestjs/common'
import type { Observable } from 'rxjs'
import { applyDecorators, UseGuards } from '@nestjs/common'
import { banInDemo } from '~/utils'
class DemoGuard implements CanActivate {
canActivate(): boolean | Promise<boolean> | Observable<boolean> {
banInDemo()

View File

@@ -1,5 +1,3 @@
import type { IdempotenceOption } from '../interceptors/idempotence.interceptor'
import { SetMetadata } from '@nestjs/common'
import {
@@ -7,6 +5,7 @@ import {
HTTP_RES_TRANSFORM_PAGINATE,
} from '~/constants/meta.constant'
import * as SYSTEM from '~/constants/system.constant'
import type { IdempotenceOption } from '../interceptors/idempotence.interceptor'
/**
* @description 分页转换

View File

@@ -6,13 +6,11 @@
* @FilePath: /mx-server/src/core/decorators/ip.decorator.ts
* @Coding with Love
*/
import { createParamDecorator } from '@nestjs/common'
import { getIp } from '~/utils/ip.util'
import type { ExecutionContext } from '@nestjs/common'
import type { FastifyRequest } from 'fastify'
import { createParamDecorator } from '@nestjs/common'
import { getIp } from '~/utils/ip.util'
export type IpRecord = {
ip: string
agent: string

View File

@@ -1,9 +1,8 @@
import type { ExecutionContext } from '@nestjs/common'
import { createParamDecorator } from '@nestjs/common'
import { isTest } from '~/global/env.global'
import { getNestExecutionContextRequest } from '~/transformers/get-req.transformer'
import type { ExecutionContext } from '@nestjs/common'
export const IsGuest = createParamDecorator(
(data: unknown, ctx: ExecutionContext) => {

View File

@@ -1,7 +1,4 @@
import { resolve } from 'path'
import type { ArgumentsHost, ExceptionFilter } from '@nestjs/common'
import type { FastifyReply, FastifyRequest } from 'fastify'
import type { WriteStream } from 'fs'
import { resolve } from 'node:path'
import {
Catch,
@@ -24,6 +21,9 @@ import { EventManagerService } from '~/processors/helper/helper.event.service'
import { getIp } from '../../utils/ip.util'
import { BizException } from '../exceptions/biz.exception'
import { LoggingInterceptor } from '../interceptors/logging.interceptor'
import type { WriteStream } from 'node:fs'
import type { FastifyReply, FastifyRequest } from 'fastify'
import type { ArgumentsHost, ExceptionFilter } from '@nestjs/common'
type myError = {
readonly status: number
@@ -50,11 +50,11 @@ export class AllExceptionsFilter implements ExceptionFilter {
return
}
process.on('unhandledRejection', (reason: any) => {
console.error('unhandledRejection: ', reason)
console.error('unhandledRejection:', reason)
})
process.on('uncaughtException', (err) => {
console.error('uncaughtException: ', err)
console.error('uncaughtException:', err)
this.eventManager.broadcast(
EventBusEvents.SystemException,
{ message: err?.message ?? err, stack: err?.stack || '' },

View File

@@ -1,7 +1,4 @@
import { isJWT } from 'class-validator'
import type { CanActivate, ExecutionContext } from '@nestjs/common'
import type { UserModel } from '~/modules/user/user.model'
import type { FastifyBizRequest } from '~/transformers/get-req.transformer'
import { Injectable, UnauthorizedException } from '@nestjs/common'
@@ -9,6 +6,9 @@ import { AuthService } from '~/modules/auth/auth.service'
import { ConfigsService } from '~/modules/configs/configs.service'
import { UserService } from '~/modules/user/user.service'
import { getNestExecutionContextRequest } from '~/transformers/get-req.transformer'
import type { FastifyBizRequest } from '~/transformers/get-req.transformer'
import type { UserModel } from '~/modules/user/user.model'
import type { CanActivate, ExecutionContext } from '@nestjs/common'
/**
* JWT auth guard

View File

@@ -1,5 +1,3 @@
import type { CanActivate, ExecutionContext } from '@nestjs/common'
import { Injectable } from '@nestjs/common'
import { AuthService } from '~/modules/auth/auth.service'
@@ -8,6 +6,7 @@ import { UserService } from '~/modules/user/user.service'
import { getNestExecutionContextRequest } from '~/transformers/get-req.transformer'
import { AuthGuard } from './auth.guard'
import type { CanActivate, ExecutionContext } from '@nestjs/common'
/**
* 区分游客和主人的守卫
@@ -29,7 +28,6 @@ export class RolesGuard extends AuthGuard implements CanActivate {
try {
await super.canActivate(context)
isAuthenticated = true
// eslint-disable-next-line no-empty
} catch {}
request.isGuest = !isAuthenticated

View File

@@ -3,13 +3,13 @@
* @description 禁止爬虫的守卫
* @author Innei <https://innei.ren>
*/
import type { CanActivate, ExecutionContext } from '@nestjs/common'
import type { Observable } from 'rxjs'
import { ForbiddenException, Injectable } from '@nestjs/common'
import { isDev } from '~/global/env.global'
import { getNestExecutionContextRequest } from '~/transformers/get-req.transformer'
import type { Observable } from 'rxjs'
import type { CanActivate, ExecutionContext } from '@nestjs/common'
@Injectable()
export class SpiderGuard implements CanActivate {
@@ -24,8 +24,8 @@ export class SpiderGuard implements CanActivate {
const headers = request.headers
const ua: string = headers['user-agent'] || ''
const isSpiderUA =
!!ua.match(/(Scrapy|HttpClient|axios|python|requests)/i) &&
!ua.match(/(mx-space|rss|google|baidu|bing)/gi)
!!/(scrapy|httpclient|axios|python|requests)/i.test(ua) &&
!/(mx-space|rss|google|baidu|bing)/gi.test(ua)
if (ua && !isSpiderUA) {
return true
}

View File

@@ -1,11 +1,10 @@
import type { ExecutionContext } from '@nestjs/common'
import type { FastifyBizRequest } from '~/transformers/get-req.transformer'
import { Injectable } from '@nestjs/common'
import { ThrottlerGuard } from '@nestjs/throttler'
import { getNestExecutionContextRequest } from '~/transformers/get-req.transformer'
import { getIp } from '~/utils'
import type { FastifyBizRequest } from '~/transformers/get-req.transformer'
import type { ExecutionContext } from '@nestjs/common'
@Injectable()
export class ExtendThrottlerGuard extends ThrottlerGuard {

View File

@@ -1,3 +1,4 @@
import { RequestMethod } from '@nestjs/common'
import type {
CallHandler,
ExecutionContext,
@@ -5,8 +6,6 @@ import type {
} from '@nestjs/common'
import type { FastifyReply } from 'fastify'
import { RequestMethod } from '@nestjs/common'
export class AllowAllCorsInterceptor implements NestInterceptor {
intercept(context: ExecutionContext, next: CallHandler<any>) {
const handle = next.handle()

View File

@@ -4,15 +4,9 @@
* @module interceptor/analyze
* @author Innei <https://github.com/Innei>
*/
import { URL } from 'url'
import { URL } from 'node:url'
import { isbot } from 'isbot'
import UAParser from 'ua-parser-js'
import type {
CallHandler,
ExecutionContext,
NestInterceptor,
} from '@nestjs/common'
import type { Observable } from 'rxjs'
import { Inject, Injectable } from '@nestjs/common'
import { Reflector } from '@nestjs/core'
@@ -29,6 +23,12 @@ import { InjectModel } from '~/transformers/model.transformer'
import { scheduleManager } from '~/utils'
import { getIp } from '~/utils/ip.util'
import { getRedisKey } from '~/utils/redis.util'
import type { Observable } from 'rxjs'
import type {
CallHandler,
ExecutionContext,
NestInterceptor,
} from '@nestjs/common'
@Injectable()
export class AnalyzeInterceptor implements NestInterceptor {
@@ -141,8 +141,8 @@ export class AnalyzeInterceptor implements NestInterceptor {
})
}
}
} catch (e) {
console.error(e)
} catch (error) {
console.error(error)
}
})

View File

@@ -6,13 +6,6 @@
* @author Innei <https://innei.ren>
*/
import { of, tap } from 'rxjs'
import type {
CallHandler,
ExecutionContext,
NestInterceptor,
} from '@nestjs/common'
import type { FastifyReply } from 'fastify'
import type { Observable } from 'rxjs'
import { Inject, Injectable, Logger, RequestMethod } from '@nestjs/common'
import { HttpAdapterHost, Reflector } from '@nestjs/core'
@@ -23,6 +16,13 @@ import * as META from '~/constants/meta.constant'
import * as SYSTEM from '~/constants/system.constant'
import { CacheService } from '~/processors/redis/cache.service'
import { getNestExecutionContextRequest } from '~/transformers/get-req.transformer'
import type { Observable } from 'rxjs'
import type { FastifyReply } from 'fastify'
import type {
CallHandler,
ExecutionContext,
NestInterceptor,
} from '@nestjs/common'
/**
* @class HttpCacheInterceptor

View File

@@ -1,4 +1,6 @@
import qs from 'qs'
import { Injectable } from '@nestjs/common'
import { getNestExecutionContextRequest } from '~/transformers/get-req.transformer'
import type {
CallHandler,
ExecutionContext,
@@ -6,10 +8,6 @@ import type {
} from '@nestjs/common'
import type { Observable } from 'rxjs'
import { Injectable } from '@nestjs/common'
import { getNestExecutionContextRequest } from '~/transformers/get-req.transformer'
/** 此拦截器用于转换 req.query.query -> js object用于直接数据库查询需要鉴权 */
@Injectable()
export class DbQueryInterceptor implements NestInterceptor {

View File

@@ -1,10 +1,4 @@
import { catchError, tap } from 'rxjs'
import type {
CallHandler,
ExecutionContext,
NestInterceptor,
} from '@nestjs/common'
import type { FastifyRequest } from 'fastify'
import {
ConflictException,
@@ -21,6 +15,12 @@ import {
import { REFLECTOR } from '~/constants/system.constant'
import { CacheService } from '~/processors/redis/cache.service'
import { getIp, getRedisKey, hashString } from '~/utils'
import type { FastifyRequest } from 'fastify'
import type {
CallHandler,
ExecutionContext,
NestInterceptor,
} from '@nestjs/common'
const IdempotenceHeaderKey = 'x-idempotence'
@@ -89,8 +89,8 @@ export class IdempotenceInterceptor implements NestInterceptor {
const key = disableGenerateKey
? undefined
: options.generateKey
? options.generateKey(request)
: this.generateKey(request)
? options.generateKey(request)
: this.generateKey(request)
const idempotenceKey =
!!(idempotence || key) && getRedisKey(`idempotence:${idempotence || key}`)

View File

@@ -5,17 +5,17 @@
import { isObjectLike } from 'lodash'
import { map } from 'rxjs'
import snakecaseKeys from 'snakecase-keys'
import type {
CallHandler,
ExecutionContext,
NestInterceptor,
} from '@nestjs/common'
import type { Observable } from 'rxjs'
import { Injectable } from '@nestjs/common'
import { Reflector } from '@nestjs/core'
import { RESPONSE_PASSTHROUGH_METADATA } from '~/constants/system.constant'
import type { Observable } from 'rxjs'
import type {
CallHandler,
ExecutionContext,
NestInterceptor,
} from '@nestjs/common'
@Injectable()
export class JSONTransformInterceptor implements NestInterceptor {

View File

@@ -6,17 +6,17 @@
* @author Innei <https://github.com/Innei>
*/
import { tap } from 'rxjs/operators'
import type {
CallHandler,
ExecutionContext,
NestInterceptor,
} from '@nestjs/common'
import type { Observable } from 'rxjs'
import { Injectable, Logger, SetMetadata } from '@nestjs/common'
import { HTTP_REQUEST_TIME } from '~/constants/meta.constant'
import { getNestExecutionContextRequest } from '~/transformers/get-req.transformer'
import type { Observable } from 'rxjs'
import type {
CallHandler,
ExecutionContext,
NestInterceptor,
} from '@nestjs/common'
@Injectable()
export class LoggingInterceptor implements NestInterceptor {

View File

@@ -4,12 +4,6 @@
*/
import { isArrayLike } from 'lodash'
import { map } from 'rxjs/operators'
import type {
CallHandler,
ExecutionContext,
NestInterceptor,
} from '@nestjs/common'
import type { Observable } from 'rxjs'
import { Injectable } from '@nestjs/common'
import { Reflector } from '@nestjs/core'
@@ -17,6 +11,12 @@ import { Reflector } from '@nestjs/core'
import { HTTP_RES_TRANSFORM_PAGINATE } from '~/constants/meta.constant'
import * as SYSTEM from '~/constants/system.constant'
import { transformDataToPaginate } from '~/transformers/paginate.transformer'
import type { Observable } from 'rxjs'
import type {
CallHandler,
ExecutionContext,
NestInterceptor,
} from '@nestjs/common'
export interface Response<T> {
data: T

View File

@@ -1,12 +1,10 @@
// https://github.dev/ever-co/ever-gauzy/packages/core/src/core/context/request-context.middleware.ts
import * as cls from 'cls-hooked'
import type { NestMiddleware } from '@nestjs/common'
import type { IncomingMessage, ServerResponse } from 'http'
import { Injectable } from '@nestjs/common'
import { RequestContext } from '../contexts/request.context'
import type { NestMiddleware } from '@nestjs/common'
import type { IncomingMessage, ServerResponse } from 'node:http'
@Injectable()
export class RequestContextMiddleware implements NestMiddleware {

View File

@@ -1,8 +1,7 @@
import type { ValidationPipeOptions } from '@nestjs/common'
import { Injectable, ValidationPipe } from '@nestjs/common'
import { isDev } from '~/global/env.global'
import type { ValidationPipeOptions } from '@nestjs/common'
@Injectable()
export class ExtendedValidationPipe extends ValidationPipe {

View File

@@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/prefer-literal-enum-member */
export enum BusinessEvents {
GATEWAY_CONNECT = 'GATEWAY_CONNECT',
GATEWAY_DISCONNECT = 'GATEWAY_DISCONNECT',
@@ -57,7 +58,6 @@ export enum BusinessEvents {
ARTICLE_READ_COUNT_UPDATE = 'ARTICLE_READ_COUNT_UPDATE',
}
export enum EventScope {
TO_VISITOR = 1 << 0,
TO_ADMIN = 1 << 1,

View File

@@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/prefer-literal-enum-member */
export enum RedisKeys {
AccessIp = 'access_ip',
Like = 'like',

View File

@@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/prefer-literal-enum-member */
export const MIGRATE_COLLECTION_NAME = 'migrations'
export const CHECKSUM_COLLECTION_NAME = 'checksum'

View File

@@ -1,5 +1,5 @@
import { homedir } from 'os'
import { join } from 'path'
import { homedir } from 'node:os'
import { join } from 'node:path'
import { cwd, isDev } from '~/global/env.global'

View File

@@ -1,7 +1,6 @@
import { isURL } from 'class-validator'
import type { ValidationOptions } from 'class-validator'
import { validatorFactory } from '../simpleValidatorFactory'
import type { ValidationOptions } from 'class-validator'
export const IsAllowedUrl = (validationOptions?: ValidationOptions) => {
return validatorFactory((val) =>

View File

@@ -1,8 +1,7 @@
import { isString } from 'class-validator'
import { isBoolean, merge } from 'lodash'
import type { ValidationOptions } from 'class-validator'
import { validatorFactory } from '../simpleValidatorFactory'
import type { ValidationOptions } from 'class-validator'
export function IsBooleanOrString(validationOptions?: ValidationOptions) {
return validatorFactory((value) => isBoolean(value) || isString(value))(

View File

@@ -1,8 +1,7 @@
import { isInt, isMongoId } from 'class-validator'
import { merge } from 'lodash'
import type { ValidationOptions } from 'class-validator'
import { validatorFactory } from '../simpleValidatorFactory'
import type { ValidationOptions } from 'class-validator'
export function IsBooleanOrString(validationOptions?: ValidationOptions) {
return validatorFactory((value) => isInt(value) || isMongoId(value))(

View File

@@ -1,7 +1,7 @@
import {
ValidatorConstraint,
isString,
registerDecorator,
ValidatorConstraint,
} from 'class-validator'
import { isNil } from 'lodash'
import type {

View File

@@ -6,7 +6,7 @@
* @FilePath: /mx-server/src/common/decorators/simpleValidatorFactory.ts
* @Coding with Love
*/
import { registerDecorator, ValidatorConstraint } from 'class-validator'
import { ValidatorConstraint, registerDecorator } from 'class-validator'
import type {
ValidationArguments,
ValidationOptions,

View File

@@ -1,7 +1,4 @@
/* eslint-disable prefer-rest-params */
/* eslint-disable prefer-rest-params */
import { createLogger, Logger } from 'nestjs-pretty-logger'
import { Logger, createLogger } from 'nestjs-pretty-logger'
import { LOG_DIR } from '~/constants/path.constant'
@@ -18,7 +15,7 @@ Logger.setLoggerInstance(logger)
if (!isTest) {
try {
logger.wrapAll()
} catch (error) {
} catch {
logger.warn('wrap console failed')
}
logger.onData((data) => {

View File

@@ -1,9 +1,10 @@
import cluster from 'cluster'
import cluster from 'node:cluster'
import { parseBooleanishValue } from '~/utils/tool.util'
export const isMainCluster =
process.env.NODE_APP_INSTANCE && parseInt(process.env.NODE_APP_INSTANCE) === 0
process.env.NODE_APP_INSTANCE &&
Number.parseInt(process.env.NODE_APP_INSTANCE) === 0
export const isMainProcess = cluster.isPrimary || isMainCluster
export const isDev = process.env.NODE_ENV == 'development'

View File

@@ -1,6 +1,6 @@
/* eslint-disable import/order */
import cluster from 'cluster'
import { mkdirSync } from 'fs'
import cluster from 'node:cluster'
import { mkdirSync } from 'node:fs'
import { Logger } from '@nestjs/common'
@@ -60,7 +60,7 @@ function registerGlobal() {
function nodeEnvInjection() {
// # https://github.com/kriszyp/cbor-x/blob/master/node-index.js#L16 https://github.com/kriszyp/cbor-x/blob/master/node-index.js#L10
// # ncc not support runtime require so disable ACCELERATION
process.env['CBOR_NATIVE_ACCELERATION_DISABLED'] = 'true'
process.env.CBOR_NATIVE_ACCELERATION_DISABLED = 'true'
}
export function register() {

View File

@@ -12,7 +12,7 @@ export const registerJSONGlobal = () => {
JSON.safeParse = (...rest) => {
try {
return JSON5.parse(...rest)
} catch (error) {
} catch {
return null
}
}

View File

@@ -1,6 +1,6 @@
#!env node
// register global
import cluster from 'cluster'
import cluster from 'node:cluster'
import { logger } from './global/consola.global'
import { isMainCluster } from './global/env.global'
@@ -41,7 +41,10 @@ async function main() {
}
if (CLUSTER.enable) {
Cluster.register(parseInt(CLUSTER.workers) || os.cpus().length, bootstrap)
Cluster.register(
Number.parseInt(CLUSTER.workers) || os.cpus().length,
bootstrap,
)
} else {
bootstrap()
}

View File

@@ -2,8 +2,6 @@ import { plainToInstance } from 'class-transformer'
import 'reflect-metadata'
import type { IConfigKeys } from '~/modules/configs/configs.interface'
import { ENCRYPT } from '~/app.config'
import { register } from '~/global/index.global'
import { generateDefaultConfig } from '~/modules/configs/configs.default'
@@ -11,6 +9,7 @@ import * as optionDtos from '~/modules/configs/configs.dto'
import { encryptObject } from '~/modules/configs/configs.encrypt.util'
import { IConfig } from '~/modules/configs/configs.interface'
import { getDatabaseConnection } from '~/utils/database.util'
import type { IConfigKeys } from '~/modules/configs/configs.interface'
console.log(ENCRYPT)

View File

@@ -26,9 +26,9 @@ export async function migrateDatabase() {
} else {
await migrate.run(db, connection)
}
} catch (err) {
logger.error(`[Database] migrate ${migrate.name} failed`, err)
throw err
} catch (error) {
logger.error(`[Database] migrate ${migrate.name} failed`, error)
throw error
}
await db.collection(MIGRATE_COLLECTION_NAME).insertOne({

View File

@@ -1,9 +1,8 @@
import type { Db } from 'mongodb'
import {
NOTE_COLLECTION_NAME,
POST_COLLECTION_NAME,
} from '~/constants/db.constant'
import type { Db } from 'mongodb'
export default (async function v4_6_0__4(db: Db) {
const countDefault = {

View File

@@ -1,5 +1,4 @@
// patch for version lower than v4.6.0
import type { Db } from 'mongodb'
import {
CATEGORY_COLLECTION_NAME,
@@ -10,6 +9,7 @@ import {
TOPIC_COLLECTION_NAME,
} from '~/constants/db.constant'
import { md5 } from '~/utils'
import type { Db } from 'mongodb'
export default (async function v4_6_0(db: Db) {
await Promise.all([

View File

@@ -8,7 +8,7 @@ import {
import { defineMigration } from '../helper'
export default defineMigration('v4.6.2__0', async (db, connection) => {
export default defineMigration('v4.6.2__0', async (db, _connection) => {
try {
await Promise.all([
db
@@ -66,8 +66,8 @@ export default defineMigration('v4.6.2__0', async (db, connection) => {
},
},
])
} catch (err) {
} catch (error) {
console.error('v4.6.2 migration failed')
throw err
throw error
}
})

View File

@@ -2,7 +2,7 @@ import { NOTE_COLLECTION_NAME } from '~/constants/db.constant'
import { defineMigration } from '../helper'
export default defineMigration('v5.0.0-1', async (db, connection) => {
export default defineMigration('v5.0.0-1', async (db) => {
try {
await Promise.all([
db.collection(NOTE_COLLECTION_NAME).updateMany(
@@ -29,9 +29,9 @@ export default defineMigration('v5.0.0-1', async (db, connection) => {
},
},
)
} catch (err) {
} catch (error) {
console.error('v5.0.0-1 migration failed')
throw err
throw error
}
})

View File

@@ -5,13 +5,11 @@ import {
import { defineMigration } from '../helper'
export default defineMigration('v5.1.1', async (db, connection) => {
await Promise.all([
db
.collection(COMMENT_COLLECTION_NAME)
.updateMany(
{ refType: 'Recently' },
{ $set: { refType: RECENTLY_COLLECTION_NAME } },
),
])
export default defineMigration('v5.1.1', async (db) => {
await db
.collection(COMMENT_COLLECTION_NAME)
.updateMany(
{ refType: 'Recently' },
{ $set: { refType: RECENTLY_COLLECTION_NAME } },
)
})

View File

@@ -1,9 +1,8 @@
import { plainToInstance } from 'class-transformer'
import { validateSync } from 'class-validator'
import { FastifyReply, FastifyRequest } from 'fastify'
import type { CountModel } from '~/shared/model/count.model'
import { FastifyReply } from 'fastify'
import { Body, HttpCode, Inject, Post, Req, Res } from '@nestjs/common'
import { Body, HttpCode, Inject, Post, Res } from '@nestjs/common'
import { ApiController } from '~/common/decorators/api-controller.decorator'
import { Cookies } from '~/common/decorators/cookie.decorator'
@@ -15,6 +14,7 @@ import { CountingService } from '~/processors/helper/helper.counting.service'
import { CacheService } from '~/processors/redis/cache.service'
import { AckDto, AckEventType, AckReadPayloadDto } from './ack.dto'
import type { CountModel } from '~/shared/model/count.model'
@ApiController('ack')
export class AckController {
@@ -33,11 +33,9 @@ export class AckController {
@Body() body: AckDto,
@Cookies() cookies: Record<string, string>,
@Res() res: FastifyReply,
@Req() req: FastifyRequest,
) {
const { type, payload } = body
const uuidReq = req.headers['x-session-uuid']
switch (type) {
case AckEventType.READ: {
const validPayload = plainToInstance(AckReadPayloadDto, payload)
@@ -45,7 +43,7 @@ export class AckController {
validPayload,
ExtendedValidationPipe.options,
)
if (errors.length) {
if (errors.length > 0) {
const error = this.validatePipe.createExceptionFactory()(
errors as any[],
)

View File

@@ -1,4 +1,4 @@
import { forwardRef, Module } from '@nestjs/common'
import { Module, forwardRef } from '@nestjs/common'
import { GatewayModule } from '~/processors/gateway/gateway.module'

View File

@@ -1,25 +1,12 @@
import { omit, pick, uniqBy } from 'lodash'
import { Types } from 'mongoose'
import type { OnModuleDestroy, OnModuleInit } from '@nestjs/common'
import type { Collection } from 'mongodb'
import type { Socket } from 'socket.io'
import type { NoteModel } from '../note/note.model'
import type { PageModel } from '../page/page.model'
import type { PostModel } from '../post/post.model'
import type { RecentlyModel } from '../recently/recently.model'
import type {
ActivityLikePayload,
ActivityLikeSupportType,
ActivityPresence,
} from './activity.interface'
import type { UpdatePresenceDto } from './dtos/presence.dto'
import {
BadRequestException,
forwardRef,
Inject,
Injectable,
Logger,
forwardRef,
} from '@nestjs/common'
import { ArticleTypeEnum } from '~/constants/article.constant'
@@ -50,6 +37,19 @@ import {
isValidRoomName,
parseRoomName,
} from './activity.util'
import type { UpdatePresenceDto } from './dtos/presence.dto'
import type {
ActivityLikePayload,
ActivityLikeSupportType,
ActivityPresence,
} from './activity.interface'
import type { RecentlyModel } from '../recently/recently.model'
import type { PostModel } from '../post/post.model'
import type { PageModel } from '../page/page.model'
import type { NoteModel } from '../note/note.model'
import type { Socket } from 'socket.io'
import type { Collection } from 'mongodb'
import type { OnModuleDestroy, OnModuleInit } from '@nestjs/common'
declare module '~/types/socket-meta' {
interface SocketMetadata {
@@ -285,8 +285,8 @@ export class ActivityService implements OnModuleInit, OnModuleDestroy {
if (!res) {
throw new BadRequestException('你已经支持过啦!')
}
} catch (e: any) {
throw new BadRequestException(e)
} catch (error: any) {
throw new BadRequestException(error)
}
const refModel = await this.databaseService
@@ -389,6 +389,7 @@ export class ActivityService implements OnModuleInit, OnModuleDestroy {
socketMeta
.filter((x) => x?.presence)
.map((x) => {
// eslint-disable-next-line array-callback-return
if (!x.presence) return
return {
@@ -639,7 +640,7 @@ export class ActivityService implements OnModuleInit, OnModuleDestroy {
* 获取过去一年的文章发布
*/
async getLastYearPublication() {
const $gte = new Date(new Date().getTime() - 365 * 24 * 60 * 60 * 1000)
const $gte = new Date(Date.now() - 365 * 24 * 60 * 60 * 1000)
const [posts, notes] = await Promise.all([
this.postService.model
.find({

View File

@@ -2,7 +2,7 @@ import { Transform } from 'class-transformer'
import { IsEnum, IsInt, IsOptional, IsString, Max, Min } from 'class-validator'
export class TopQueryDto {
@Transform(({ value: val }) => parseInt(val))
@Transform(({ value: val }) => Number.parseInt(val))
@Min(1)
@Max(10)
@IsOptional()
@@ -26,7 +26,7 @@ export class TimelineQueryDto {
@IsEnum(TimelineType)
@IsOptional()
@Transform(({ value: v }) => v | 0)
@Transform(({ value: v }) => Math.trunc(v))
type?: TimelineType
}
@@ -45,6 +45,6 @@ export enum ReadAndLikeCountDocumentType {
export class ReadAndLikeCountTypeDto {
@IsEnum(ReadAndLikeCountDocumentType)
@IsOptional()
@Transform(({ value: v }) => v | 0)
@Transform(({ value: v }) => Math.trunc(v))
type?: ReadAndLikeCountDocumentType
}

View File

@@ -1,4 +1,4 @@
import { forwardRef, Module } from '@nestjs/common'
import { Module, forwardRef } from '@nestjs/common'
import { GatewayModule } from '~/processors/gateway/gateway.module'

View File

@@ -1,12 +1,7 @@
import { URL } from 'url'
import { URL } from 'node:url'
import { pick } from 'lodash'
import type { ReturnModelType } from '@typegoose/typegoose'
import type { AnyParamConstructor } from '@typegoose/typegoose/lib/types'
import type { PipelineStage } from 'mongoose'
import type { CategoryModel } from '../category/category.model'
import type { RSSProps } from './aggregate.interface'
import { forwardRef, Inject, Injectable } from '@nestjs/common'
import { Inject, Injectable, forwardRef } from '@nestjs/common'
import { OnEvent } from '@nestjs/event-emitter'
import {
@@ -35,6 +30,11 @@ import { RecentlyService } from '../recently/recently.service'
import { SayService } from '../say/say.service'
import { UserService } from '../user/user.service'
import { ReadAndLikeCountDocumentType, TimelineType } from './aggregate.dto'
import type { RSSProps } from './aggregate.interface'
import type { CategoryModel } from '../category/category.model'
import type { PipelineStage } from 'mongoose'
import type { AnyParamConstructor } from '@typegoose/typegoose/lib/types'
import type { ReturnModelType } from '@typegoose/typegoose'
@Injectable()
export class AggregateService {

View File

@@ -87,10 +87,11 @@ export class AiController {
}
}
if (!dbStored) {
if (!aiConfig.enableSummary || !aiConfig.enableAutoGenerateSummary) {
throw new BizException(ErrorCodeEnum.AINotEnabled)
}
if (
!dbStored &&
(!aiConfig.enableSummary || !aiConfig.enableAutoGenerateSummary)
) {
throw new BizException(ErrorCodeEnum.AINotEnabled)
}
return dbStored

View File

@@ -1,6 +1,5 @@
import OpenAI from 'openai'
import removeMdCodeblock from 'remove-md-codeblock'
import type { PagerDto } from '~/shared/dto/pager.dto'
import { Injectable, Logger } from '@nestjs/common'
import { OnEvent } from '@nestjs/event-emitter'
@@ -17,6 +16,7 @@ import { md5 } from '~/utils'
import { ConfigsService } from '../configs/configs.service'
import { AISummaryModel } from './ai-summary.model'
import type { PagerDto } from '~/shared/dto/pager.dto'
@Injectable()
export class AiService {
@@ -83,7 +83,7 @@ export class AiService {
this.cachedTaskId2AiPromise.set(taskId, taskPromise)
return await taskPromise
// eslint-disable-next-line no-inner-declarations
async function handle(this: AiService, id: string, text: string) {
// 等待 30s
await redis.set(taskId, 'processing', 'EX', 30)
@@ -119,10 +119,12 @@ CONCISE SUMMARY:`,
return doc
}
} catch (er) {
this.logger.error(`OpenAI 在处理文章 ${articleId} 时出错:${er.message}`)
} catch (error) {
this.logger.error(
`OpenAI 在处理文章 ${articleId} 时出错:${error.message}`,
)
throw new BizException(ErrorCodeEnum.AIException, er.message)
throw new BizException(ErrorCodeEnum.AIException, error.message)
} finally {
this.cachedTaskId2AiPromise.delete(taskId)
}

View File

@@ -1,5 +1,4 @@
import dayjs from 'dayjs'
import type { PagerDto } from '~/shared/dto/pager.dto'
import { Delete, Get, HttpCode, Query } from '@nestjs/common'
@@ -13,6 +12,7 @@ import { getTodayEarly, getWeekStart } from '~/utils/time.util'
import { AnalyzeDto } from './analyze.dto'
import { AnalyzeService } from './analyze.service'
import type { PagerDto } from '~/shared/dto/pager.dto'
@ApiController({ path: 'analyze' })
@Auth()
@@ -28,7 +28,7 @@ export class AnalyzeController {
const { from, to = new Date(), page = 1, size = 50 } = query
const data = await this.service.getRangeAnalyzeData(from, to, {
limit: size | 0,
limit: Math.trunc(size),
page,
})
@@ -42,7 +42,7 @@ export class AnalyzeController {
const today = new Date()
const todayEarly = getTodayEarly(today)
return await this.service.getRangeAnalyzeData(todayEarly, today, {
limit: ~~size,
limit: Math.trunc(size),
page,
})
}
@@ -64,7 +64,7 @@ export class AnalyzeController {
const getIpAndPvAggregate = async () => {
const day = await this.service.getIpAndPvAggregate('day', true)
const dayData = Array(24)
const dayData = Array.from({ length: 24 })
.fill(undefined)
.map((v, i) => {
return [

View File

@@ -2,12 +2,12 @@ import { Transform } from 'class-transformer'
import { IsDate, IsOptional } from 'class-validator'
export class AnalyzeDto {
@Transform(({ value: v }) => new Date(parseInt(v)))
@Transform(({ value: v }) => new Date(Number.parseInt(v)))
@IsOptional()
@IsDate()
from?: Date
@Transform(({ value: v }) => new Date(parseInt(v)))
@Transform(({ value: v }) => new Date(Number.parseInt(v)))
@IsOptional()
@IsDate()
to?: Date

View File

@@ -1,7 +1,7 @@
import { SchemaTypes } from 'mongoose'
import { UAParser } from 'ua-parser-js'
import { index, modelOptions, prop, Severity } from '@typegoose/typegoose'
import { Severity, index, modelOptions, prop } from '@typegoose/typegoose'
import { ANALYZE_COLLECTION_NAME } from '~/constants/db.constant'
import { BaseModel } from '~/shared/model/base.model'

View File

@@ -1,6 +1,5 @@
import dayjs from 'dayjs'
import { merge } from 'lodash'
import type { PipelineStage } from 'mongoose'
import { Injectable } from '@nestjs/common'
import { ReturnModelType } from '@typegoose/typegoose'
@@ -12,6 +11,7 @@ import { getRedisKey } from '~/utils/redis.util'
import { OptionModel } from '../configs/configs.model'
import { AnalyzeModel } from './analyze.model'
import type { PipelineStage } from 'mongoose'
@Injectable()
export class AnalyzeService {
@@ -248,7 +248,7 @@ export class AnalyzeService {
}
async getRangeOfTopPathVisitor(from?: Date, to?: Date): Promise<any[]> {
from = from ?? new Date(new Date().getTime() - 1000 * 24 * 3600 * 7)
from = from ?? new Date(Date.now() - 1000 * 24 * 3600 * 7)
to = to ?? new Date()
const pipeline: PipelineStage[] = [

View File

@@ -1,10 +1,10 @@
import { Transform } from 'class-transformer'
import {
IsDate,
isMongoId,
IsNotEmpty,
IsOptional,
IsString,
isMongoId,
} from 'class-validator'
import {

View File

@@ -2,13 +2,10 @@ import dayjs from 'dayjs'
import jwt from 'jsonwebtoken'
import { isDate, omit } from 'lodash'
import { LRUCache } from 'lru-cache'
import type { ClerkClient } from '@clerk/clerk-sdk-node'
import type { TokenModel, UserModel } from '~/modules/user/user.model'
import type { TokenDto } from './auth.controller'
import { createClerkClient } from '@clerk/clerk-sdk-node'
import { nanoid } from '@mx-space/external'
import { forwardRef, Inject, Injectable, Logger } from '@nestjs/common'
import { Inject, Injectable, Logger, forwardRef } from '@nestjs/common'
import { ReturnModelType } from '@typegoose/typegoose'
import { alphabet } from '~/constants/other.constant'
@@ -17,6 +14,9 @@ import { JWTService } from '~/processors/helper/helper.jwt.service'
import { InjectModel } from '~/transformers/model.transformer'
import { ConfigsService } from '../configs/configs.service'
import type { TokenDto } from './auth.controller'
import type { TokenModel, UserModel } from '~/modules/user/user.model'
import type { ClerkClient } from '@clerk/clerk-sdk-node'
const { customAlphabet } = nanoid

View File

@@ -37,8 +37,8 @@ export class AuthnController {
@Post('/authentication')
@HTTPDecorators.Bypass
async newAuthentication(@CurrentUser() user: UserDocument) {
return await this.authnService.generateAuthenticationOptions(user)
async newAuthentication() {
return await this.authnService.generateAuthenticationOptions()
}
@Post('/authentication/verify')

View File

@@ -6,7 +6,7 @@ type CredentialDeviceType = 'singleDevice' | 'multiDevice'
const uint8ArrayGetterSetter = {
get(uint8string: string) {
const base64String = uint8string.replace(/-/g, '+').replace(/_/g, '/') // 将 URL 安全字符转换回标准 Base64 字符
const base64String = uint8string.replaceAll('-', '+').replaceAll('_', '/') // 将 URL 安全字符转换回标准 Base64 字符
const buffer = Buffer.from(base64String, 'base64')
return buffer.buffer.slice(
buffer.byteOffset,
@@ -16,8 +16,8 @@ const uint8ArrayGetterSetter = {
set(value: Uint8Array) {
return Buffer.from(value)
.toString('base64')
.replace(/\+/g, '-')
.replace(/\//g, '_')
.replaceAll('+', '-')
.replaceAll('/', '_')
.replace(/=+$/, '')
},

View File

@@ -1,14 +1,3 @@
import type {
VerifiedAuthenticationResponse,
VerifiedRegistrationResponse,
} from '@simplewebauthn/server'
import type {
AuthenticationResponseJSON,
CredentialDeviceType,
RegistrationResponseJSON,
} from '@simplewebauthn/server/script/deps'
import type { UserDocument } from '../user/user.model'
import { BadRequestException, Injectable } from '@nestjs/common'
import {
generateAuthenticationOptions,
@@ -25,6 +14,16 @@ import { getRedisKey } from '~/utils'
import { ConfigsService } from '../configs/configs.service'
import { AuthnModel } from './authn.model'
import type { UserDocument } from '../user/user.model'
import type {
AuthenticationResponseJSON,
CredentialDeviceType,
RegistrationResponseJSON,
} from '@simplewebauthn/server/script/deps'
import type {
VerifiedAuthenticationResponse,
VerifiedRegistrationResponse,
} from '@simplewebauthn/server'
@Injectable()
export class AuthnService {
@@ -163,7 +162,7 @@ export class AuthnService {
return verification
}
async generateAuthenticationOptions(user: UserDocument) {
async generateAuthenticationOptions() {
const userAuthenticators: Authenticator[] = await this.authnModel
.find()
.lean({ getters: true })

View File

@@ -1,4 +1,4 @@
import { Readable } from 'stream'
import { Readable } from 'node:stream'
import { FastifyRequest } from 'fastify'
import {

View File

@@ -1,6 +1,6 @@
import { existsSync, statSync } from 'fs'
import { readdir, readFile, rm, writeFile } from 'fs/promises'
import { join, resolve } from 'path'
import { existsSync, statSync } from 'node:fs'
import { readFile, readdir, rm, writeFile } from 'node:fs/promises'
import { join, resolve } from 'node:path'
import { flatten } from 'lodash'
import { mkdirp } from 'mkdirp'
@@ -114,26 +114,26 @@ export class BackupService {
// 打包数据目录
const flags = excludeFolders.map((item) => ['--exclude', item]).flat(1)
const flags = excludeFolders.flatMap((item) => ['--exclude', item])
cd(DATA_DIR)
await rm(join(DATA_DIR, 'backup_data'), { recursive: true, force: true })
await rm(join(DATA_DIR, 'temp_copy_need'), {
recursive: true,
force: true,
})
// eslint-disable-next-line no-empty
await $`rsync -a . ./temp_copy_need --exclude temp_copy_need ${flags} && mv temp_copy_need backup_data && zip -r ${join(
backupDirPath,
`backup-${dateDir}`,
)} ./backup_data && rm -rf backup_data`
this.logger.log('--> 备份成功')
} catch (e) {
} catch (error) {
this.logger.error(
`--> 备份失败,请确保已安装 zip 或 mongo-tools, mongo-tools 的版本需要与 mongod 版本一致,${e.message}` ||
e.stderr,
`--> 备份失败,请确保已安装 zip 或 mongo-tools, mongo-tools 的版本需要与 mongod 版本一致,${error.message}` ||
error.stderr,
)
throw e
throw error
}
const path = join(backupDirPath, `backup-${dateDir}.zip`)
@@ -206,9 +206,9 @@ export class BackupService {
await $`mongorestore --uri ${MONGO_DB.customConnectionString || MONGO_DB.uri} -d ${MONGO_DB.dbName} ./mx-space --drop >/dev/null 2>&1`
await migrateDatabase()
} catch (e) {
this.logger.error(e)
throw e
} catch (error) {
this.logger.error(error)
throw error
} finally {
await rm(join(dirPath, 'mx-space'), { recursive: true, force: true })
}
@@ -238,13 +238,13 @@ export class BackupService {
await Promise.all(
Object.entries(pkg.dependencies).map(([name, version]) => {
this.logger.log(`--> 安装依赖 ${name}@${version}`)
return installPKG(`${name}@${version}`, DATA_DIR).catch((er) => {
this.logger.error(`--> 依赖安装失败:${er.message}`)
return installPKG(`${name}@${version}`, DATA_DIR).catch((error) => {
this.logger.error(`--> 依赖安装失败:${error.message}`)
})
}),
)
}
} catch (er) {}
} catch {}
await Promise.all([
this.cacheService.cleanAllRedisKey(),
@@ -316,9 +316,9 @@ export class BackupService {
})
this.logger.log('--> 开始上传到 S3')
await s3.send(command).catch((err) => {
await s3.send(command).catch((error) => {
this.logger.error('--> 上传失败了')
throw err
throw error
})
this.logger.log('--> 上传成功')
})

View File

@@ -4,7 +4,6 @@ import {
BadRequestException,
Body,
Delete,
forwardRef,
Get,
HttpCode,
Inject,
@@ -13,6 +12,7 @@ import {
Post,
Put,
Query,
forwardRef,
} from '@nestjs/common'
import { ApiController } from '~/common/decorators/api-controller.decorator'

View File

@@ -1,11 +1,11 @@
import { IsEnum, IsNotEmpty, IsOptional, IsString } from 'class-validator'
import type { DocumentType } from '@typegoose/typegoose'
import { PartialType } from '@nestjs/mapped-types'
import { index, modelOptions, prop } from '@typegoose/typegoose'
import { CATEGORY_COLLECTION_NAME } from '~/constants/db.constant'
import { BaseModel } from '~/shared/model/base.model'
import type { DocumentType } from '@typegoose/typegoose'
export type CategoryDocument = DocumentType<CategoryModel>

View File

@@ -1,4 +1,4 @@
import { forwardRef, Module } from '@nestjs/common'
import { Module, forwardRef } from '@nestjs/common'
import { PostModule } from '../post/post.module'
import { SlugTrackerModule } from '../slug-tracker/slug-tracker.module'

View File

@@ -1,13 +1,10 @@
import { omit } from 'lodash'
import type { DocumentType } from '@typegoose/typegoose'
import type { FilterQuery } from 'mongoose'
import type { PostModel } from '../post/post.model'
import {
BadRequestException,
forwardRef,
Inject,
Injectable,
forwardRef,
} from '@nestjs/common'
import { ReturnModelType } from '@typegoose/typegoose'
@@ -23,6 +20,9 @@ import { scheduleManager } from '~/utils'
import { PostService } from '../post/post.service'
import { SlugTrackerService } from '../slug-tracker/slug-tracker.service'
import { CategoryModel, CategoryType } from './category.model'
import type { PostModel } from '../post/post.model'
import type { FilterQuery } from 'mongoose'
import type { DocumentType } from '@typegoose/typegoose'
@Injectable()
export class CategoryService {
@@ -58,8 +58,8 @@ export class CategoryService {
}),
)
for (let i = 0; i < data.length; i++) {
Reflect.set(data[i], 'count', counts[i])
for (const [i, datum] of data.entries()) {
Reflect.set(datum, 'count', counts[i])
}
return data
@@ -101,7 +101,7 @@ export class CategoryService {
{ lean: true },
)
.populate('category')
if (!posts.length) {
if (posts.length === 0) {
throw new CannotFindException()
}
return posts.map(({ _id, title, slug, category, created }) => ({
@@ -207,11 +207,9 @@ export class CategoryService {
private clearCache() {
return scheduleManager.batch(() =>
Promise.all([
this.eventManager.emit(EventBusEvents.CleanAggregateCache, null, {
scope: EventScope.TO_SYSTEM,
}),
]),
this.eventManager.emit(EventBusEvents.CleanAggregateCache, null, {
scope: EventScope.TO_SYSTEM,
}),
)
}

View File

@@ -1,7 +1,4 @@
import { isUndefined } from 'lodash'
import type { DocumentType } from '@typegoose/typegoose'
import type { Document, FilterQuery } from 'mongoose'
import type { CommentModel } from './comment.model'
import {
Body,
@@ -45,6 +42,9 @@ import { CommentReplyMailType } from './comment.enum'
import { CommentFilterEmailInterceptor } from './comment.interceptor'
import { CommentState } from './comment.model'
import { CommentService } from './comment.service'
import type { CommentModel } from './comment.model'
import type { Document, FilterQuery } from 'mongoose'
import type { DocumentType } from '@typegoose/typegoose'
const idempotenceMessage = '哦吼,这句话你已经说过啦'
const NESTED_REPLY_MAX = 10

View File

@@ -1,16 +1,16 @@
import { isDefined } from 'class-validator'
import { cloneDeep, isArrayLike, isObjectLike } from 'lodash'
import { map } from 'rxjs'
import type {
CallHandler,
ExecutionContext,
NestInterceptor,
} from '@nestjs/common'
import { Injectable } from '@nestjs/common'
import { getNestExecutionContextRequest } from '~/transformers/get-req.transformer'
import { getAvatar } from '~/utils'
import type {
CallHandler,
ExecutionContext,
NestInterceptor,
} from '@nestjs/common'
@Injectable()
export class CommentFilterEmailInterceptor implements NestInterceptor {
@@ -48,9 +48,9 @@ export class CommentFilterEmailInterceptor implements NestInterceptor {
}
return cloneDeep(data)
} catch (e) {
} catch (error) {
if (isDev) {
console.error(e)
console.error(error)
}
return cloneDeep(data)
}

View File

@@ -1,12 +1,12 @@
import { URL } from 'url'
import { URL } from 'node:url'
import { Types } from 'mongoose'
import autopopulate from 'mongoose-autopopulate'
import { modelOptions, plugin, prop, Ref } from '@typegoose/typegoose'
import { Ref, modelOptions, plugin, prop } from '@typegoose/typegoose'
import {
CollectionRefTypes,
COMMENT_COLLECTION_NAME,
CollectionRefTypes,
} from '~/constants/db.constant'
import { BaseModel } from '~/shared/model/base.model'

View File

@@ -1,4 +1,4 @@
import { forwardRef, Module } from '@nestjs/common'
import { Module, forwardRef } from '@nestjs/common'
import { GatewayModule } from '~/processors/gateway/gateway.module'

View File

@@ -1,23 +1,14 @@
/* eslint-disable @typescript-eslint/no-non-null-assertion */
import { URL } from 'url'
import { URL } from 'node:url'
import { render } from 'ejs'
import { omit, pick } from 'lodash'
import { isObjectIdOrHexString, Types } from 'mongoose'
import type { OnModuleInit } from '@nestjs/common'
import type { ReturnModelType } from '@typegoose/typegoose/lib/types'
import type { WriteBaseModel } from '~/shared/model/write-base.model'
import type { SnippetModel } from '../snippet/snippet.model'
import type {
CommentEmailTemplateRenderProps,
CommentModelRenderProps,
} from './comment.email.default'
import { Types, isObjectIdOrHexString } from 'mongoose'
import {
BadRequestException,
forwardRef,
Inject,
Injectable,
Logger,
forwardRef,
} from '@nestjs/common'
import { OnEvent } from '@nestjs/event-emitter'
@@ -45,6 +36,14 @@ import {
} from './comment.email.default'
import { CommentReplyMailType } from './comment.enum'
import { CommentModel, CommentState } from './comment.model'
import type {
CommentEmailTemplateRenderProps,
CommentModelRenderProps,
} from './comment.email.default'
import type { SnippetModel } from '../snippet/snippet.model'
import type { WriteBaseModel } from '~/shared/model/write-base.model'
import type { OnModuleInit } from '@nestjs/common'
import type { ReturnModelType } from '@typegoose/typegoose/lib/types'
@Injectable()
export class CommentService implements OnModuleInit {

View File

@@ -1,6 +1,5 @@
import type { IConfig } from './configs.interface'
import { DEMO_MODE } from '~/app.config'
import type { IConfig } from './configs.interface'
export const generateDefaultConfig: () => IConfig = () => ({
seo: {

View File

@@ -3,8 +3,8 @@ import {
ArrayUnique,
IsBoolean,
IsEmail,
IsInt,
IsIP,
IsInt,
IsNotEmpty,
IsOptional,
IsString,
@@ -17,7 +17,6 @@ import { IsAllowedUrl } from '~/decorators/dto/isAllowedUrl'
import { Encrypt } from './configs.encrypt.util'
import {
halfFieldOption,
JSONSchemaArrayField,
JSONSchemaHalfGirdPlainField,
JSONSchemaNumberField,
@@ -25,6 +24,7 @@ import {
JSONSchemaPlainField,
JSONSchemaTextAreaField,
JSONSchemaToggleField,
halfFieldOption,
} from './configs.jsonschema.decorator'
const SecretField = (target: Object, propertyKey: string | symbol) => {
@@ -77,7 +77,7 @@ export class UrlDto {
class MailOption {
@IsInt()
@Transform(({ value: val }) => parseInt(val))
@Transform(({ value: val }) => Number.parseInt(val))
@IsOptional()
@JSONSchemaNumberField('发件邮箱端口', halfFieldOption)
port: number

View File

@@ -1,15 +1,9 @@
import { Type } from 'class-transformer'
import { ValidateNested } from 'class-validator'
import { JSONSchema } from 'class-validator-jsonschema'
import type {
ClassConstructor,
TypeHelpOptions,
TypeOptions,
} from 'class-transformer'
import {
AdminExtraDto,
AIDto,
AdminExtraDto,
AlgoliaSearchOptionsDto,
AuthSecurityDto,
BackupOptionsDto,
@@ -25,6 +19,11 @@ import {
ThirdPartyServiceIntegrationDto,
UrlDto,
} from './configs.dto'
import type {
ClassConstructor,
TypeHelpOptions,
TypeOptions,
} from 'class-transformer'
export const configDtoMapping = {} as Record<string, ClassConstructor<any>>
const ConfigField =

View File

@@ -1,6 +1,6 @@
import { Schema } from 'mongoose'
import { modelOptions, prop, Severity } from '@typegoose/typegoose'
import { Severity, modelOptions, prop } from '@typegoose/typegoose'
@modelOptions({
options: { allowMixed: Severity.ALLOW, customName: 'Option' },

View File

@@ -1,8 +1,7 @@
import cluster from 'cluster'
import cluster from 'node:cluster'
import { plainToInstance } from 'class-transformer'
import { validateSync } from 'class-validator'
import { cloneDeep, mergeWith } from 'lodash'
import type { ClassConstructor } from 'class-transformer'
import { createClerkClient } from '@clerk/clerk-sdk-node'
import {
@@ -28,8 +27,9 @@ import { getRedisKey } from '~/utils/redis.util'
import { generateDefaultConfig } from './configs.default'
import { decryptObject, encryptObject } from './configs.encrypt.util'
import { configDtoMapping, IConfig } from './configs.interface'
import { IConfig, configDtoMapping } from './configs.interface'
import { OptionModel } from './configs.model'
import type { ClassConstructor } from 'class-transformer'
const configsKeySet = new Set(Object.keys(configDtoMapping))
@@ -133,13 +133,13 @@ export class ConfigsService {
) as any as IConfig
return decryptObject(instanceConfigsValue)
} catch (err) {
} catch (error) {
await this.configInit()
if (errorRetryCount > 0) {
return await this.getConfig(--errorRetryCount)
}
this.logger.error('获取配置失败')
throw err
throw error
}
} else {
await this.configInit()

View File

@@ -1,4 +1,4 @@
import { resolve } from 'path'
import { resolve } from 'node:path'
import { Module } from '@nestjs/common'
import { CronExpression } from '@nestjs/schedule'

View File

@@ -1,4 +1,4 @@
import { readFile } from 'fs/promises'
import { readFile } from 'node:fs/promises'
import { Observable } from 'rxjs'
import { BadRequestException, Get, Query, Sse } from '@nestjs/common'

View File

@@ -1,6 +1,5 @@
import RemoveMarkdown from 'remove-markdown'
import xss from 'xss'
import type { CategoryModel } from '../category/category.model'
import { CacheKey, CacheTTL } from '@nestjs/cache-manager'
import { Controller, Get, Header } from '@nestjs/common'
@@ -13,6 +12,7 @@ import { AggregateService } from '../aggregate/aggregate.service'
import { ConfigsService } from '../configs/configs.service'
import { MarkdownService } from '../markdown/markdown.service'
import { UserService } from '../user/user.service'
import type { CategoryModel } from '../category/category.model'
@Controller()
export class FeedController {

View File

@@ -1,4 +1,4 @@
import fs from 'fs/promises'
import fs from 'node:fs/promises'
import { FastifyReply, FastifyRequest } from 'fastify'
import { lookup } from 'mime-types'

View File

@@ -1,7 +1,5 @@
import { createWriteStream } from 'fs'
import { resolve } from 'path'
import type { Readable } from 'stream'
import type { FileType } from './file.type'
import { createWriteStream } from 'node:fs'
import { resolve } from 'node:path'
import {
BadRequestException,
@@ -16,6 +14,8 @@ import {
} from '~/constants/path.constant'
import { ConfigsService } from '../configs/configs.service'
import type { FileType } from './file.type'
import type { Readable } from 'node:stream'
@Injectable()
export class FileService {
@@ -80,8 +80,8 @@ export class FileService {
const path = this.resolveFilePath(type, name)
await fs.rename(path, resolve(STATIC_FILE_TRASH_DIR, name))
} catch (e) {
this.logger.error('删除文件失败', e)
} catch (error) {
this.logger.error('删除文件失败', error)
return null
}
}
@@ -102,8 +102,8 @@ export class FileService {
const newPath = this.resolveFilePath(type, newName)
try {
await fs.rename(oldPath, newPath)
} catch (e) {
this.logger.error('重命名文件失败', e.message)
} catch (error) {
this.logger.error('重命名文件失败', error.message)
throw new BadRequestException('重命名文件失败')
}
}

View File

@@ -23,10 +23,10 @@ export class HealthController {
@Get('/email/test')
@Auth()
async testEmail() {
return this.emailService.sendTestEmail().catch((err) => {
return this.emailService.sendTestEmail().catch((error) => {
return {
message: err.message,
trace: err.stack,
message: error.message,
trace: error.stack,
}
})
}

View File

@@ -1,5 +1,3 @@
import type { Readable } from 'form-data'
import {
BadRequestException,
Delete,
@@ -19,6 +17,7 @@ import { formatByteSize } from '~/utils'
import { getTodayLogFilePath } from '~/utils/path.util'
import { LogQueryDto, LogTypeDto } from '../health.dto'
import type { Readable } from 'form-data'
@ApiController('health/log')
@Auth()
@@ -72,7 +71,7 @@ export class HealthLogController {
switch (type) {
case 'pm2':
_type = file.split('-')[2].split('.')[0]
index = parseInt(file.split('-')[3], 10) || 0
index = Number.parseInt(file.split('-')[3], 10) || 0
break
case 'native':
_type = 'log'

View File

@@ -1,6 +1,5 @@
import type { CanActivate } from '@nestjs/common'
import { checkInit } from '~/utils/check-init.util'
import type { CanActivate } from '@nestjs/common'
export class InitGuard implements CanActivate {
async canActivate() {

View File

@@ -1,5 +1,3 @@
import type mongoose from 'mongoose'
import {
Body,
ForbiddenException,
@@ -26,6 +24,7 @@ import { scheduleManager } from '~/utils'
import { AuditReasonDto, LinkDto } from './link.dto'
import { LinkModel, LinkState } from './link.model'
import { LinkService } from './link.service'
import type mongoose from 'mongoose'
const paths = ['links', 'friends']

View File

@@ -1,4 +1,4 @@
import { URL } from 'url'
import { URL } from 'node:url'
import { Transform } from 'class-transformer'
import {
IsEmail,

Some files were not shown because too many files have changed in this diff Show More