npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

xstao-common-util-server

v1.0.4

Published

公司后端通用库

Readme

xstao-common-util-server

xstao-common-util-server是一个公司后端通用库,包含一些nodejs通用的方法

安装方法

npm install xstao-common-util-server --save

CustomError-自定义异常

  • API

declare module CustomError {
    // 自定义异常格式,符合公司内部http返回值规范 http://aiki.avalongames.com:8090/pages/viewpage.action?pageId=8159346
    interface CustomErrorInterface {
        httpStatusCode: number
        status: number
    }

    // 抛出自定义异常
    function throwCustomError(error: CustomErrorInterface): void

    // 解析自定义异常
    function parseCustomError(e: any): CustomErrorInterface
}
  • Demo

import { CustomError } from 'xstao-common-util-server'

const { parseCustomError,throwCustomError } = CustomError

    try {
        // todo

        // 抛出自定义异常
        throwCustomError({ httpStatusCode: 500, status: xxx })

    } catch (e) {
        // 解析自定义异常
        const { httpStatusCode = 500, status = 1002 } = parseCustomError(e)
        response({ ctx, data: {}, httpStatusCode, status })
    }

CustomLog-自定义日志

  • API

// 对winstonjs/winston进行二次封装
declare class CustomLog {
    constructor(config: {
        // 日志logger名称,对应输出的文件名前缀
        names: Array<string>
        // 日志输出路径
        path: string
        // 日志等级
        level?: string
    })

    // 输出日志
    log(jsonParam: {
        // 日志logger名称
        logger: string
        // 日志等级
        level?: string
        // 输出的消息
        message: string
    }): void
}

  • Demo
// 初始化日志
global.logger = new CustomLog({ names: ['server', 'business'], path: 'log', level: 'info' })
global.logger.log({ logger: 'server',level:'info', message: '服务器初始化完成' })

CustomMysql-自定义mysql

  • API

import { PoolConfig, FieldInfo, Connection } from 'mysql'

// mysq初始化的配置
export interface CustomMysqlConfig extends PoolConfig {
    // 主机名
    host: string
    // 端口
    port: number
    // 用户名
    user: string
    // 密码
    password: string
    // 库名
    database: string
}

// sql命令
export type SqlCommand = string | Array<string>

// 查询函数,可用于事务内执行
export type Query = (jsonParam: {
    connection: Connection
    sqlCommand: SqlCommand
}) => Promise<
    Array<{
        // 执行结果
        rows: Array<any> | any
        // 字段
        fields: Array<FieldInfo>
    }>
>

// 对mysqljs/mysql进行二次封装
declare class CustomMysql {
    // 配置中的字符集默认为utf8mb4
    constructor(config: CustomMysqlConfig)

    // 执行sql
    excute(jsonParam: {
        // sql命令
        sqlCommand: SqlCommand
        // 是否以事务执行
        transaction: boolean
    }): Promise<
        Array<{
            // 执行结果
            rows: Array<any> | any
            // 本次执行的sql命令
            sqlCommand: string
            // 字段
            fields: Array<FieldInfo>
        }>
    >

    // 在事务内部执行sql,返回是否执行成功,不会抛出异常
    relyTransaction(
        execFn: (jsonParam: {
            // 查询函数
            query: Query
            // mysqljs的连接
            connection: Connection
        }) => Promise<void>
    ): Promise<boolean>

    // 加载版本管理工具(注意:该方法不做异常捕获)
    // 对程序自身的mysql数据库进行版本管理,代替运维操作,只适用于数据量较小的库;
    // 原理:创建一个sql更新记录的table,每次启动服务器时对比sql文件和历史记录,如果是新sql则执行更新;如果库里面没有任何表,并且xxx.sql文件存在,则执行xxx.sql对表结构进行初始化
    loadVersionManager(jsonParam: {
        // sql文件目录
        sqlDir: string
        // 数据库的开发名(区分运维部署时的实际名称),作为sql文件名前缀
        databaseDevName: string
    }): Promise<void>

    // 检查乐观锁的版本号
    checkOptimismLockVersion(jsonParam: {
        // 表名
        table: string
        // 该行数据的主键(主键字段必须为id)
        id: string | number
        // 版本号
        version: string
        // 记录乐观锁的字段名,默认为version
        lockColumnKey?: string
    }): Promise<void>

    // 更新乐观锁的版本号
    updateOptimismLockVersion(jsonParam: {
        // 表名
        table: string
        // 该行数据的主键(主键字段必须为id)
        id: string | number
        // 记录乐观锁的字段名,默认为version
        lockColumnKey?: string
    }): Promise<void>
}

export { CustomMysql }

  • Demo
// 普通场景
global.mysql = new CustomMysql({ 
    host: 'xx.xx.xx.xx', 
    port: 3306, user: 'xx', 
    password: 'xx', 
    database: 'xx' 
})
const [{ rows }] = await global.mysql.excute({
    sql: `select * from table`,
    transaction: false,
})

// mysql版本管理器
global.mysql = new CustomMysql({ 
    host: 'xx.xx.xx.xx', 
    port: 3306, 
    user: 'xx', 
    password: 'xx', 
    database: 'xx' ,
    multipleStatements:true 
})
await global.mysql.loadVersionManager({sqlDir:"xxx",databaseDevName:"xxx"})   

// 事务内执行
const isSuccess = await mysql.relyTransaction(
    async ({ query, connection }) => {
        const [{ insertId }] = await query({
            connection,
            sqlCommand: `insert into account set id=10,name='xx'`,
        })
        await query({
            connection,
            sqlCommand: [
                `insert into account set id=11,name='${insertId}'`,
                `insert into account set id=12,name='${insertId}'`,
            ],
        })
    }
)
console.log(isSuccess)

CustomRedis-自定义redis

  • API

import { ClientOpts } from 'redis'

// 对NodeRedis/node_redis进行二次封装
declare class CustomRedis {
    // 配置中的detect_buffers默认为true
    constructor(config: ClientOpts)

    // 执行命令
    excute(jsonParam: {
        // 数据库序号
        index?: number
        // 参数
        params: any
        // 命令
        command: string
    }): Promise<any>

    // 上锁
    lockByRedis(jsonParam: {
        // 数据库序号
        index?: number
        // 锁的key名
        lockKey: string
    }): Promise<void>

    // 解锁
    unlockByRedis(jsonParam: {
        // 数据库序号
        index?: number
        // 锁的key名
        lockKey: string
    }): Promise<void>

    // 使用redis锁保证逻辑的隔离性
    doAtomicFuncByLock(jsonParam: {
        // 数据库序号
        index?: number
        // 锁的key名,支持多个锁
        lockKey: string | Array<string>
        // 锁中间执行的逻辑,常用于并发操作
        atomicFunc: () => any
    }): Promise<any>
}

export { CustomRedis }
  • Demo
// 普通场景
global.redis = new CustomRedis({
    host: 'xx.xx.xx.xx', 
    port: 3306,
    password: 'xx',
    db:xx
})

file-文件操作

  • API

declare module file {
    function download(jsonParam: {
        // 源文件的下载地址
        url: string
        // 文件存放路径
        filePath: string
        // 文件编码,默认为utf8
        encoding?: string
    }): Promise<void>
}

export { file }

  • Demo
// 文件下载
const {file} = require("xstao-common-util-server")

file.download({url:'xxx',path:'temp'})

koaUtil-koa工具

  • API

import { Context, Middleware } from 'koa'
import * as Router from 'koa-router'

declare module koaUtil {
    // 判断服务器是否初始化完成
    function checkInitRouter(
        // 检查函数
        checkFunc: () => boolean
    ): Router

    // 检查md5签名
    function checkMd5SignMiddleware(
        // md5签名的key
        md5Key: string
    ): Middleware

    // 防盗链检测
    function checkRefererMiddleware(
        // 访问来源,支持多个
        referer: string | Array<string>
    ): Middleware

    // iam权限认证,返回一个中间件
    function iamMiddleware(jsonParam: {
        // iam服务地址
        iamServiceUrl: string
        // opweb应用令牌
        projectToken: string
        // 路由匹配类型,默认为matchedRoute
        type?:
            | 'matchedRoute' // 匹配的路由,包含通配符,即上下文中的_matchedRoute
            | 'path' // 实际请求路径,即上下文中的path
            | 'custom' // 自定义路由,值由customRouteFunction参数决定
        // 自定义路由,仅type='custom'生效
        customRouteFunction?: (
            ctx: Context // 上下文
        ) => string
        // 动作
        action: string
        // 通用信息限制,默认自动从请求中获取所有参数,get从query string获取,其他从body中获取
        objectAttr?:
            | Array<string> // 手动指定通用信息限制的key
            | ((ctx: Context) => { [propName: string]: any }) // 从上下文中自定义
    }): Middleware

    // iam工具
    const iamUtil: {
        // 从iam服务获取用户授权
        getUserAuthorization: (jsonParam: {
            // iam服务地址
            iamServiceUrl: string
            // 上下文
            ctx: Context
        }) => Promise<{
            // 用户id
            id: number
        }>
    }

    // 参数类型检查支持的类型
    type paramTypeString =
        | 'number'
        | 'string'
        | 'object'
        | 'any'
        | 'Array<number>'
        | 'Array<string>'
        | 'Array<object>'
        | 'Array<any>'

    // 参数类型实例
    const paramType: paramTypeString

    // 参数格式化
    const paramFormat: {
        // 参数类型检查
        checkType: (jsonParam: {
            // 值
            value: any
            // 类型
            type: paramTypeString
        }) => void
        // 参数检查并格式化,返回一个中间件
        paramFormatMiddleware: (
            // 格式
            formats: Array<{
                // 参数key
                id: string
                // 正则
                regex?: RegExp
                // 类型
                type: paramTypeString
                // 是否可选,默认为必传
                optional?: boolean
            }>
        ) => Middleware
    }

    // 格式化所有get请求中的参数,url解码
    const queryFormatRouter: Router

    // 按公司内部返回值规范返回
    function response(jsonParam: {
        // 上下文
        ctx: Context
        // http状态码
        httpStatusCode: number
        // 业务状态码
        status: number
        // 业务数据
        data?: any
    }): void
}

export { koaUtil }

  • Demo
// checkInitRouter 应用初始化检测路由,可在服务器未初始化完成前不提供业务接口访问
app.use(checkInitRouter(global.hasInitialized).routes())
   .use(checkInitRouter(global.hasInitialized).allowedMethods())

// checkMd5SignMiddleware md5签名检测中间件
const v1 = new Router({
    prefix: '/xx',
})
v1.get('/xx-xx-xx', checkMd5SignMiddleware(global.md5Key))

// checkRefererMiddleware 防盗链检测中间件
const v1 = new Router({
    prefix: '/xx',
})
v1.get('/xx-xx-xx', checkRefererMiddleware(global.referer))

// iamMiddleware IAM权限认证中间件
const v1 = new Router({
    prefix: '/xx',
})
v1.post('/xx-xx-xx',iamMiddleware({ iamServiceUrl: 'xx', projectToken: 'xx', type: 'path', action: 'xx' }))

// iamUtil
const { id } = await getUserAuthorization({ iamServiceUrl: 'xx', ctx:ctx })

// paramFormatMiddleware 参数格式化中间件
const v1 = new Router({
    prefix: '/xx',
})
v1.get('/xx-xx-xx', paramFormatMiddleware([{id:"id",regex:/^\d+$/,type:'Array<number>',optional:true}]))

// queryFormatRouter get请求参数格式化路由,将所有get参数的值进行url解码
app.use(queryFormatRouter.routes()).use(queryFormatRouter.allowedMethods())

// response 返回客户端消息
response({ ctx, httpStatusCode: 500, status: 50001, data })

system-系统层面的工具

  • API

declare module system {
    // 不使用缓存重新加载模块
    function requireUncached(module: string)
}

export { system }

  • Demo
const {system: {requireUncached}} = require("xstao-common-util-server")
const path = require("path")

const doSomeThing = ()=>{
    //此处只能使用相对路径
    const m = requireUncached(path.resolve(__dirname, "../xxx/xxx"))
    
}