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

commonsy

v0.1.2

Published

publcCommon

Readme

commonsy

前后端通用 TypeScript 工具库,包含通用基础、日期时间、金额货币、表单校验、浏览器判断、文件图片、下载链接、加密、WebSocket、服务端、Cesium 地图等工具。源码使用 TypeScript 编写,发布时输出 JavaScript 与 .d.ts 类型声明。

安装

npm install commonsy

引用方式

默认入口

import sysFun from 'commonsy';

sysFun.CommonUtils.isEmpty({});
new sysFun.DateUtils.DateTimeFormatter('2022-10-10 11:11:10', 'yyyy-mm-dd').getFormattedDateTime();
new sysFun.MoneyUtils.ComputeMoney(100).add(50).toDollars();

分类子路径入口

import CommonUtils from 'commonsy/common';
import DateUtils from 'commonsy/date';
import MoneyUtils from 'commonsy/money';
import WebSocketUtils from 'commonsy/websocket';
import ServerUtils from 'commonsy/server';

旧版直达入口

import sysFun from 'commonsy';

new sysFun.DateTimeFormatter('2022-10-10 11:11:10', 'yyyy/mm/dd').getFormattedDateTime();
new sysFun.ComputeMoney(100).add(50).toDollars();

目录结构

commonsy
├── index.ts                    # TypeScript 统一入口
├── dist                        # 构建后的 JavaScript 与类型声明
├── publicFun
│   ├── common                  # 通用基础工具
│   ├── date                    # 日期时间工具
│   ├── money                   # 金额货币工具
│   ├── validate                # 表单校验工具
│   ├── browser                 # 浏览器判断工具
│   ├── file                    # 文件图片工具
│   └── download                # 下载链接工具
├── encryption                  # 加密工具
├── webSocket                   # WebSocket 工具
├── server                      # 项目启动入口、HTTP 服务、SQL、Redis 工具
├── cesium                      # Cesium 地图工具
└── test                        # 测试

子路径导出

| 导入路径 | 对应分类 | | --- | --- | | commonsy | 全量默认入口 | | commonsy/common | 通用基础工具 | | commonsy/date | 日期时间工具 | | commonsy/money | 金额货币工具 | | commonsy/validate | 表单校验工具 | | commonsy/browser | 浏览器判断工具 | | commonsy/file | 文件图片工具 | | commonsy/download | 下载链接工具 | | commonsy/crypto | 加密工具 | | commonsy/websocket | WebSocket 工具 | | commonsy/server | 服务端工具,包含项目启动入口、HTTP 服务、SQL、Redis | | commonsy/map | Cesium 地图工具 |

工具总览

| 分类 | 默认入口名称 | 工具 | | --- | --- | --- | | 通用基础 | CommonUtils | isEmptydeepClonedeepMergedebouncethrottlelistToTreetreeToListsafeJsonParseformatFileSizemaskPhonemaskEmailmaskBankCard | | 类型判断 | TypeUtils | isEmpty | | 对象处理 | ObjectUtils | deepClonedeepMerge | | 函数控制 | FunctionUtils | debouncethrottle | | 树结构 | TreeUtils | listToTreetreeToList | | JSON | JsonUtils | safeJsonParse | | 文件格式 | FileUtils | formatFileSize | | 隐私脱敏 | MaskUtils | maskPhonemaskEmailmaskBankCard | | 日期时间 | DateUtils | DateTimeFormatterCountdownTimer | | 金额货币 | MoneyUtils | BankNumberComputeMoney | | 表单校验 | ValidateUtils | FormValidation | | 浏览器 | BrowserUtils | GetBrowserType | | 文件图片 | FileTools | CompressImageformatFileSize | | 下载链接 | DownloadUtils | XunLeiDownloadUrl | | 加密 | CryptoUtils | Encryption | | WebSocket | WebSocketUtils | WebSocketServerWebSocketClient | | 服务端 | ServerUtils | createServerAppstartServerApploadConfigcreateRoutercomposeMiddlewarescreateErrorHandlercreateLoggersendSuccessgetPaginationvalidateRequestsignJwtsecurityHeadersstaticMiddlewareuploadMiddlewarecreateTaskManagercreateHealthCheckercreateCachecreateUuidgetProcessInfostartHttpServerqueryRowscreateRedisClient | | 地图 | MapUtils | CesiumWrapper |

服务端工具

服务端工具用于组织 Node 项目的基础设施,适合放在业务项目的 server.jsapp.jsmain.js 中使用。它可以把配置、路由、中间件、统一响应、统一错误、日志、鉴权、安全、静态资源、上传、后台任务、健康检查、缓存、数据库连接、Redis 连接、HTTP 服务启动和退出清理统一管理。

服务端工具默认不强制安装数据库和 Redis 客户端。只有调用 SQL 或 Redis 方法时,才需要在业务项目中安装对应依赖:

npm install mysql2 redis

项目启动入口

最常用的写法是通过 startServerApp 创建项目入口,在 startup 中按顺序初始化资源,在 shutdown 中释放资源。

import ServerUtils from 'commonsy/server';

const app = await ServerUtils.startServerApp({
  name: 'demo-api',
  config: {
    port: 3000,
  },
  startup: [
    {
      name: 'start-http',
      run: async ({ config }) => {
        const httpApp = await ServerUtils.startHttpServer({
          port: config.port,
          routes: [
            {
              method: 'GET',
              path: '/health',
              handler: ({ response, sendJson }) => {
                sendJson(response, { ok: true });
              },
            },
          ],
        });

        return { httpApp };
      },
    },
  ],
  shutdown: [
    {
      name: 'close-http',
      run: async ({ httpApp }) => {
        await ServerUtils.closeHttpServer(httpApp.server);
      },
    },
  ],
});

ServerUtils.bindGracefulShutdown(app);
console.log(app.context.httpApp.url);

完整后端入口示例

下面示例展示一个项目入口如何同时启动 MySQL、Redis 和 HTTP 服务,并组合路由、中间件、日志和统一错误处理:

import ServerUtils from 'commonsy/server';

const logger = ServerUtils.createLogger({
  name: 'demo-api',
  level: 'info',
});
const config = ServerUtils.loadConfig({
  defaults: {
    port: 3000,
  },
  envMap: {
    port: {
      env: 'PORT',
      parse: Number,
      defaultValue: 3000,
    },
    'mysql.host': {
      env: 'MYSQL_HOST',
      defaultValue: 'localhost',
    },
    'mysql.user': {
      env: 'MYSQL_USER',
      defaultValue: 'root',
    },
    'mysql.password': {
      env: 'MYSQL_PASSWORD',
      defaultValue: 'password',
    },
    'mysql.database': {
      env: 'MYSQL_DATABASE',
      defaultValue: 'demo',
    },
    'redis.url': {
      env: 'REDIS_URL',
      defaultValue: 'redis://localhost:6379',
    },
  },
  required: ['mysql.host', 'mysql.database', 'redis.url'],
});
const router = ServerUtils.createRouter();

router.get('/health', ({ response, sendJson }) => {
  sendJson(response, { ok: true });
});

router.get('/users/:id', async ({ params, response, sendJson }) => {
  const users = await ServerUtils.queryRows('select * from users where id = ?', [params.id]);
  sendJson(response, { data: users[0] || null });
});

const app = await ServerUtils.startServerApp({
  name: 'demo-api',
  config,
  logger,
  startup: [
    {
      name: 'connect-mysql',
      run: async ({ config }) => {
        const mysqlPool = await ServerUtils.createMysqlPool(config.mysql);
        return { mysqlPool };
      },
    },
    {
      name: 'connect-redis',
      run: async ({ config }) => {
        const redisClient = await ServerUtils.createRedisClient(config.redis);
        return { redisClient };
      },
    },
    {
      name: 'start-http',
      run: async ({ config }) => {
        const httpApp = await ServerUtils.startHttpServer({
          port: config.port,
          routes: router.routes,
          middlewares: [
            ServerUtils.corsMiddleware(),
            ServerUtils.requestLogger(logger),
          ],
          errorHandler: ServerUtils.createErrorHandler(),
        });

        return { httpApp };
      },
    },
  ],
  shutdown: [
    {
      name: 'close-http',
      run: async ({ httpApp }) => {
        await ServerUtils.closeHttpServer(httpApp.server);
      },
    },
    {
      name: 'close-redis',
      run: async ({ redisClient }) => {
        await ServerUtils.closeRedis(redisClient);
      },
    },
    {
      name: 'close-mysql',
      run: async ({ mysqlPool }) => {
        await ServerUtils.closeMysqlPool(mysqlPool);
      },
    },
  ],
});

ServerUtils.bindGracefulShutdown(app);
console.log(`服务已启动:${app.context.httpApp.url}`);

基础设施工具分类

| 工具对象 | 说明 | | --- | --- | | AppStarter | 项目启动入口、启动步骤、关闭步骤、优雅退出 | | ConfigUtils | 配置合并、环境变量映射、必填配置校验 | | ResponseUtils | 成功响应、失败响应、分页响应和常用响应写出 | | RequestUtils | query、header、客户端 IP、分页参数解析 | | ServerValidateUtils | body、query、params 的服务端参数校验 | | AuthUtils | Bearer Token 解析、HS256 JWT 签发验证、鉴权中间件 | | SecurityUtils | 安全响应头、基础限流、请求体大小限制 | | RouteUtils | 轻量路由、路径参数、请求匹配 | | MiddlewareUtils | 中间件组合、CORS 中间件 | | ErrorUtils | HTTP 错误对象、统一错误响应 | | LoggerUtils | 轻量日志器、请求日志中间件 | | StaticUtils | 静态文件服务、MIME 类型识别、安全路径解析 | | UploadUtils | 文件名清理、轻量 multipart 解析、上传中间件 | | TaskUtils | 后台定时任务注册、启动和停止 | | HealthUtils | 健康检查器和健康检查路由 | | CacheUtils | Redis JSON 缓存、remember 缓存回填 | | IdUtils | UUID、随机 ID、请求 ID 中间件 | | ProcessUtils | 进程信息、sleep、异步超时控制 | | HttpServerUtils | Node 原生 HTTP/HTTPS 服务启动和关闭 | | SqlUtils | MySQL 连接池、查询、事务 | | RedisUtils | Redis 连接、读写、删除 |

分步注册启动入口

如果不想一次性传入 startupshutdown,也可以使用 createServerApp 后再逐步注册:

import ServerUtils from 'commonsy/server';

const app = ServerUtils.createServerApp({
  name: 'demo-api',
  config: {
    port: 3000,
  },
});

app
  .use({
    name: 'start-http',
    run: async ({ config }) => {
      const httpApp = await ServerUtils.startHttpServer({
        port: config.port,
        routes: [],
      });

      return { httpApp };
    },
  })
  .onShutdown({
    name: 'close-http',
    run: async ({ httpApp }) => {
      await ServerUtils.closeHttpServer(httpApp.server);
    },
  });

await app.start();
ServerUtils.bindGracefulShutdown(app);

启动入口 API

| 方法 | 说明 | | --- | --- | | createServerApp(options) | 创建项目启动入口,不会立即执行启动步骤 | | startServerApp(options) | 创建项目启动入口并立即执行 startup | | bindGracefulShutdown(app, options) | 绑定 SIGINTSIGTERM、未捕获异常和未处理 Promise 异常,触发时执行 app.stop() | | app.use(step) | 追加启动步骤 | | app.onShutdown(step) | 追加关闭步骤 | | app.start() | 按注册顺序执行启动步骤 | | app.stop() | 按关闭步骤的反向顺序释放资源 |

startup 中每个步骤可以返回对象,返回字段会合并到 app.context,供后续步骤和关闭步骤复用。

路由、中间件和错误处理

import ServerUtils from 'commonsy/server';

const router = ServerUtils.createRouter();

router.get('/users/:id', async (context) => {
  ServerUtils.sendSuccess(context, { id: context.params.id });
}, {
  middlewares: [
    ServerUtils.validateRequest({
      params: {
        id: {
          required: true,
          pattern: /^\d+$/,
        },
      },
    }),
  ],
});

await ServerUtils.startHttpServer({
  port: 3000,
  routes: router.routes,
  middlewares: [
    ServerUtils.requestIdMiddleware(),
    ServerUtils.securityHeaders(),
    ServerUtils.corsMiddleware(),
  ],
  errorHandler: ServerUtils.createErrorHandler(),
});

配置工具

import ServerUtils from 'commonsy/server';

const config = ServerUtils.loadConfig({
  defaults: {
    port: 3000,
  },
  envMap: {
    port: {
      env: 'PORT',
      parse: Number,
      defaultValue: 3000,
    },
    'mysql.host': 'MYSQL_HOST',
  },
  overrides: {
    port: 4000,
  },
  required: ['mysql.host'],
});

console.log(config.port);

鉴权工具

import ServerUtils from 'commonsy/server';

const token = ServerUtils.signJwt(
  {
    userId: 1,
    role: 'admin',
  },
  'secret',
  {
    expiresIn: 3600,
  }
);

const user = ServerUtils.verifyJwt(token, 'secret');
console.log(user.userId);

路由中可以使用鉴权中间件:

router.get('/profile', (context) => {
  ServerUtils.sendSuccess(context, context.user);
}, {
  middlewares: [
    ServerUtils.authMiddleware({
      secret: 'secret',
    }),
  ],
});

健康检查和缓存

import ServerUtils from 'commonsy/server';

const health = ServerUtils.createHealthChecker()
  .add('mysql', async () => {
    await ServerUtils.queryRows('select 1');
    return true;
  })
  .add('redis', async () => {
    return redisClient.isOpen;
  });

const cache = ServerUtils.createCache(redisClient, {
  prefix: 'demo:',
  defaultTtlSeconds: 300,
});

router.get('/health', ServerUtils.healthRoute(health));
router.get('/users/:id', async (context) => {
  const user = await cache.remember(`user:${context.params.id}`, 60, async () => {
    const rows = await ServerUtils.queryRows('select * from users where id = ?', [context.params.id]);
    return rows[0] || null;
  });

  ServerUtils.sendSuccess(context, user);
});

静态文件、上传和任务

import ServerUtils from 'commonsy/server';

const tasks = ServerUtils.createTaskManager();

tasks.interval('clear-cache', async () => {
  console.log('clear cache');
}, 60 * 1000);

tasks.start();

await ServerUtils.startHttpServer({
  port: 3000,
  middlewares: [
    ServerUtils.staticMiddleware({
      rootDir: './public',
      prefix: '/static',
    }),
  ],
  routes: [
    {
      method: 'POST',
      path: '/upload',
      middlewares: [
        ServerUtils.uploadMiddleware({
          maxBytes: 10 * 1024 * 1024,
        }),
      ],
      handler: (context) => {
        ServerUtils.sendSuccess(context, {
          files: context.upload.files.map((file) => ({
            filename: file.filename,
            size: file.size,
          })),
        });
      },
    },
  ],
});

启动 HTTP 服务

import ServerUtils from 'commonsy/server';

const app = await ServerUtils.startHttpServer({
  port: 3000,
  routes: [
    {
      method: 'GET',
      path: '/health',
      handler: ({ response, sendJson }) => {
        sendJson(response, { ok: true });
      },
    },
  ],
});

console.log(app.url); // http://localhost:3000

查询 SQL

import ServerUtils from 'commonsy/server';

await ServerUtils.createMysqlPool({
  host: 'localhost',
  user: 'root',
  password: 'password',
  database: 'demo',
});

const users = await ServerUtils.queryRows('select * from users where status = ?', [1]);
console.log(users);

连接 Redis

import ServerUtils from 'commonsy/server';

await ServerUtils.createRedisClient({
  url: 'redis://localhost:6379',
});

await ServerUtils.redisSet('token:user:1', 'abc', { ttlSeconds: 3600 });
const token = await ServerUtils.redisGet('token:user:1');
console.log(token);

通用基础工具

isEmpty

判断值是否为空。支持 nullundefined、空字符串、空数组、空对象、空 Map、空 Set

import CommonUtils from 'commonsy/common';

CommonUtils.isEmpty(null); // true
CommonUtils.isEmpty('   '); // true
CommonUtils.isEmpty([]); // true
CommonUtils.isEmpty({}); // true
CommonUtils.isEmpty({ name: 'sy' }); // false

deepClone

深拷贝对象、数组、日期、正则,并支持循环引用。

import CommonUtils from 'commonsy/common';

const source = { user: { name: 'sy' }, tags: ['a'] };
const target = CommonUtils.deepClone(source);

target.user.name = 'new name';
console.log(source.user.name); // sy

deepMerge

深度合并对象,后面的对象覆盖前面的同名字段。

import CommonUtils from 'commonsy/common';

const result = CommonUtils.deepMerge(
  { user: { name: 'sy', age: 18 } },
  { user: { age: 20 } }
);

console.log(result); // { user: { name: 'sy', age: 20 } }

debounce

防抖。常用于搜索输入、窗口尺寸变化、按钮防重复触发。

import CommonUtils from 'commonsy/common';

const onSearch = CommonUtils.debounce((keyword) => {
  console.log(keyword);
}, 300);

onSearch('commonsy');

第三个参数为 true 时,首次立即执行。

const submit = CommonUtils.debounce(() => {
  console.log('submit');
}, 500, true);

throttle

节流。常用于滚动、拖拽、鼠标移动等高频事件。

import CommonUtils from 'commonsy/common';

const onScroll = CommonUtils.throttle(() => {
  console.log('scroll');
}, 300);

listToTree

将扁平数组转换为树形结构。

import CommonUtils from 'commonsy/common';

const list = [
  { id: 1, parentId: null, name: '菜单' },
  { id: 2, parentId: 1, name: '子菜单' },
];

const tree = CommonUtils.listToTree(list);
console.log(tree);

支持自定义字段:

CommonUtils.listToTree(list, {
  idKey: 'id',
  parentKey: 'parentId',
  childrenKey: 'children',
  rootValue: null,
});

treeToList

将树形结构拍平成数组。

import CommonUtils from 'commonsy/common';

const list = CommonUtils.treeToList(tree);
console.log(list);

safeJsonParse

安全解析 JSON,失败时返回默认值。

import CommonUtils from 'commonsy/common';

CommonUtils.safeJsonParse('{"name":"sy"}', {}); // { name: 'sy' }
CommonUtils.safeJsonParse('{ bad json }', {}); // {}

formatFileSize

格式化文件大小。

import CommonUtils from 'commonsy/common';

CommonUtils.formatFileSize(1024); // 1 KB
CommonUtils.formatFileSize(1048576); // 1 MB
CommonUtils.formatFileSize(1536, 1); // 1.5 KB

maskPhone

手机号脱敏。

import CommonUtils from 'commonsy/common';

CommonUtils.maskPhone('13812345678'); // 138****5678

maskEmail

邮箱脱敏。

import CommonUtils from 'commonsy/common';

CommonUtils.maskEmail('[email protected]'); // t***[email protected]

maskBankCard

银行卡号脱敏。

import CommonUtils from 'commonsy/common';

CommonUtils.maskBankCard('6222021234567890'); // 6222 **** **** 7890

日期时间工具

DateTimeFormatter

按指定格式输出日期时间。

import DateUtils from 'commonsy/date';

const formatter = new DateUtils.DateTimeFormatter('2022-10-10 11:11:10', 'yyyy-mm-dd HH:mm:ss');

console.log(formatter.getFormattedDateTime()); // 2022-10-10 11:11:10

支持格式:

| 格式 | 示例 | | --- | --- | | yyyy-mm-dd HH:mm:ss | 2022-10-10 11:11:10 | | yyyy-mm-dd | 2022-10-10 | | yyyy/mm/dd | 2022/10/10 | | yyyy/mm/dd HH:mm:ss | 2022/10/10 11:11:10 |

CountdownTimer

倒计时工具,返回剩余总毫秒数、天、小时、分钟、秒。

import DateUtils from 'commonsy/date';

const countdown = new DateUtils.CountdownTimer('2026-12-31T23:59:59');

const firstRemaining = countdown.start((remaining) => {
  console.log(remaining.days, remaining.hours, remaining.minutes, remaining.seconds);
});

console.log(firstRemaining);

// 主动停止
countdown.stop();

也可以只计算一次:

const remaining = countdown.getTimeRemaining();
console.log(remaining);

返回结构:

{
  total: 1000,
  days: 0,
  hours: 0,
  minutes: 0,
  seconds: 1
}

金额货币工具

BankNumber

使用 Intl.NumberFormat 格式化货币显示。

import MoneyUtils from 'commonsy/money';

const amount = new MoneyUtils.BankNumber(1000.5, 'US', 'USD');

console.log(amount.formatCurrency('US', 'USD')); // $1,000.50

常见参数:

| 地区 | currency | | --- | --- | | US | USD | | CN | CNY | | JP | JPY | | UK | GBP | | EU | EUR |

ComputeMoney

使用分为单位处理金额,减少小数精度误差。

import MoneyUtils from 'commonsy/money';

const money = new MoneyUtils.ComputeMoney(100);

money.add(50);
console.log(money.toDollars()); // 150.00

money.multiply(2);
console.log(money.toDollars()); // 300.00

支持方法:

money.add(10);
money.subtract(5);
money.multiply(2);
money.divide(3);
money.toDollars();

表达式计算:

const result = MoneyUtils.ComputeMoney.calculate('(300 - 50) / 2 + 10');
const finalMoney = new MoneyUtils.ComputeMoney(result);

console.log(finalMoney.toDollars()); // 135.00

表单校验工具

FormValidation

按字段配置执行非空、格式、最大长度、最小长度校验。

import ValidateUtils from 'commonsy/validate';

const formData = [
  {
    val: '13812345678',
    valName: '手机号',
    rule: /^1[3-9]\d{9}$/,
    max: 11,
    min: 11,
    validList: ['isNull', 'isFormattingError', 'isMax', 'isMin'],
  },
];

const validator = new ValidateUtils.FormValidation(formData);

console.log(validator.validationData()); // true

支持规则:

| 规则 | 作用 | 依赖字段 | | --- | --- | --- | | isNull | 判断是否为空 | valNameval | | isFormattingError | 判断正则格式是否匹配 | valNameruleval | | isMax | 判断长度是否超过最大值 | valNamemaxval | | isMin | 判断长度是否小于最小值 | valNameminval |

校验失败时返回错误文案:

const validator = new ValidateUtils.FormValidation([
  { val: '', valName: '姓名', validList: ['isNull'] },
]);

console.log(validator.validationData()); // 姓名不能为空.

浏览器工具

GetBrowserType

判断当前运行容器。

import BrowserUtils from 'commonsy/browser';

const browserType = new BrowserUtils.GetBrowserType();

console.log(browserType.throwType());

返回值:

| 返回值 | 含义 | | --- | --- | | wechat | 微信内置浏览器 | | alipay | 支付宝内置浏览器 | | H5 | 普通 H5 环境或无法识别环境 |

文件图片工具

CompressImage

浏览器端图片压缩。传入 File,返回压缩后的 Blob

import FileTools from 'commonsy/file';

const image = new FileTools.CompressImage(file, 1024, 1024, 0.8);
const blob = await image.compressImg();

console.log(blob);

参数:

| 参数 | 说明 | | --- | --- | | file | 浏览器文件对象 | | maxWidth | 最大宽度 | | maxHeight | 最大高度 | | quality | 图片质量,通常为 01 |

dataURLtoBlob

将 DataURL 转换为 Blob。

import FileTools from 'commonsy/file';

const blob = FileTools.CompressImage.dataURLtoBlob(dataUrl);

formatFileSize

FileTools 中也包含 formatFileSize

import FileTools from 'commonsy/file';

FileTools.formatFileSize(1024); // 1 KB

下载链接工具

XunLeiDownloadUrl

将普通下载地址转换为迅雷 thunder:// 协议地址。

import DownloadUtils from 'commonsy/download';

const thunderUrl = new DownloadUtils.XunLeiDownloadUrl('http://localhost/file.zip').changeUrl();

console.log(thunderUrl);

加密工具

Encryption

提供 MD5、AES、RSA 工具。

import CryptoUtils from 'commonsy/crypto';

const encryption = new CryptoUtils.Encryption();

console.log(encryption.md5('abc')); // 900150983cd24fb0d6963f7d28e17f72

AES 加密和解密

import CryptoUtils from 'commonsy/crypto';

const encryption = new CryptoUtils.Encryption();
const result = encryption.aesEncrypt('hello');

console.log(result.encryptedData);
console.log(result.key);
console.log(result.iv);

const text = encryption.aesDecrypt(result.encryptedData, result.key, result.iv);
console.log(text); // hello

RSA 加密

import CryptoUtils from 'commonsy/crypto';

const encryption = new CryptoUtils.Encryption();
const encrypted = encryption.rsaEncrypt('hello');

console.log(encrypted);

preEncrypt

type 自动分发加密方法。

import CryptoUtils from 'commonsy/crypto';

const encryption = new CryptoUtils.Encryption();

encryption.preEncrypt({ type: 'MD5', value: 'abc' });
encryption.preEncrypt({ type: 'AES', value: 'hello' });
encryption.preEncrypt({ type: 'RSA', value: 'hello' });

WebSocket 工具

WebSocketServer

Node 服务端 WebSocket 封装。

import WebSocketUtils from 'commonsy/websocket';

const server = new WebSocketUtils.WebSocketServer({ port: 8080 });

server.on('connection', (client) => {
  client.on('message', (message) => {
    console.log('收到消息:', message);
    client.send(`服务器已收到消息: ${message}`);
  });

  client.on('close', () => {
    console.log('客户端已断开连接');
  });
});

内置 JSON 消息类型:

| type | 行为 | | --- | --- | | auth | 调用 handleAuth(userId) | | greeting | 返回欢迎信息 | | question | 返回问题回复 | | ping | 返回 pong | | broadcast | 广播 content 给其他客户端 |

可用方法:

server.on('connection', callback);
server.broadcast('hello', senderSocket);
server.close();

WebSocketClient

浏览器或 Node 客户端 WebSocket 封装,支持心跳和自动重连。

import WebSocketUtils from 'commonsy/websocket';

const client = new WebSocketUtils.WebSocketClient('ws://localhost:8080', {
  heartbeatInterval: 30000,
  reconnectDelay: 5000,
});

client.connect('user-001');
client.sendMessage(JSON.stringify({ type: 'greeting' }));

// 主动关闭
client.close();

Cesium 地图工具

CesiumWrapper

按需加载 Cesium,封装 Viewer 初始化、相机控制、点线面绘制、标注、GeoJSON 加载和资源清理。

import MapUtils from 'commonsy/map';

const map = new MapUtils.CesiumWrapper('container');
const viewer = await map.init({
  animation: false,
  timeline: false,
});

console.log(viewer);

相机控制

map.setCameraView({
  longitude: 116.391,
  latitude: 39.907,
  height: 3000,
  heading: 0,
  pitch: -45,
  roll: 0,
});

map.flyTo({
  longitude: 116.391,
  latitude: 39.907,
  height: 3000,
  duration: 2,
});

添加点

const point = map.addPoint({
  id: 'point-1',
  name: '位置点',
  longitude: 116.391,
  latitude: 39.907,
  height: 0,
});

添加图片标注

const marker = map.addBillboard({
  id: 'marker-1',
  name: '图标标注',
  longitude: 116.391,
  latitude: 39.907,
  altitude: 0,
  image: '/marker.png',
  width: 32,
  billboardHeight: 32,
});

添加文字标签

const label = map.addLabel({
  id: 'label-1',
  text: '北京',
  longitude: 116.391,
  latitude: 39.907,
});

添加线

const line = map.addPolyline({
  id: 'line-1',
  positions: [
    [116.391, 39.907, 0],
    [121.473, 31.23, 0],
  ],
  width: 4,
});

添加面

const polygon = map.addPolygon({
  id: 'polygon-1',
  positions: [
    [116.38, 39.9, 0],
    [116.4, 39.9, 0],
    [116.4, 39.92, 0],
    [116.38, 39.92, 0],
  ],
});

加载 GeoJSON

const dataSource = await map.addGeoJson('/data/area.geojson', {
  flyTo: true,
  clampToGround: true,
});

删除和清理

map.removeEntity('point-1');
map.clearEntities();
map.clearDataSources();
map.destroy();

常用方法:

| 方法 | 作用 | | --- | --- | | init(options) | 初始化 Viewer | | loadCesium() | 按需加载 Cesium 模块 | | getViewer() | 获取 Viewer 实例 | | toCartesian(longitude, latitude, height) | 经纬度转 Cartesian3 | | toCartesianArray(positions) | 经纬度数组转 Cartesian3 数组 | | setCameraView(options) | 立即设置相机视角 | | flyTo(options) | 飞行到指定位置 | | addPoint(options) | 添加点实体 | | addBillboard(options) | 添加图片标注 | | addLabel(options) | 添加文字标签 | | addPolyline(options) | 添加线实体 | | addPolygon(options) | 添加面实体 | | addGeoJson(data, options) | 加载 GeoJSON 数据源 | | removeEntity(entityOrId) | 删除实体 | | clearEntities() | 清空实体 | | clearDataSources(destroy) | 清空数据源 | | destroy() | 销毁 Viewer |

注意:Cesium 体积较大,业务项目需要自行安装并处理 Cesium 资源和样式。

默认入口完整示例

import sysFun from 'commonsy';

sysFun.CommonUtils.maskPhone('13812345678');
new sysFun.DateUtils.DateTimeFormatter('2022-10-10 11:11:10', 'yyyy-mm-dd').getFormattedDateTime();
new sysFun.MoneyUtils.ComputeMoney(100).add(50).toDollars();
new sysFun.ValidateUtils.FormValidation([{ val: '', valName: '姓名', validList: ['isNull'] }]).validationData();
new sysFun.BrowserUtils.GetBrowserType().throwType();
new sysFun.DownloadUtils.XunLeiDownloadUrl('http://localhost').changeUrl();
new sysFun.CryptoUtils.Encryption().md5('abc');
new sysFun.MapUtils.CesiumWrapper('container');

测试

npm test

环境说明

  • 包格式为 ES Module。
  • CompressImage 依赖浏览器 FileReaderImagedocumentcanvasBlob
  • WebSocketServer 依赖 Node 环境和 ws
  • CesiumWrapper 需要业务项目安装并配置 cesium
  • 加密工具依赖 crypto-jsnode-rsa