npm package: @lotomic/chanjs
Description: Base on chanjs typescript
Author: lanbery
Latest version: 0.1.1

﻿<h1 align="center">@lotomic/chanjs</h1>
<p align="center" >
  <a href="https://github.com/lotocms" target="blank">
    <img src="https://ucarecdn.com/eac2c945-177d-4fc9-8bc1-fa2be48ad3a2/lotolab_golden.svg" width="100" alt="Tsai Logo" />
  </a>
</p>

<p align="center">
  <a href="https://www.npmjs.com/~lotomic" target="_blank"><img src="https://img.shields.io/npm/l/%40tsailab%2Fcli?color=%23FFDEAD&label=License" alt="License" /></a>
  <a href="https://discord.gg/lotolab" target="_blank"><img src="https://img.shields.io/badge/discord-online-brightgreen.svg" alt="Discord"/></a>
  <a href="https://x.com/lamborghini171" target="_blank"><img src="https://img.shields.io/twitter/follow/nestframework.svg?style=social&label=Follow" alt="Follow us on Twitter"></a>
  <a href="https://www.npmjs.com/~lotomic" target="_blank"><img src="https://img.shields.io/npm/v/%40lotomic%2Fchanjs" alt="Tsai cli" /></a>
  <a href="https://www.npmjs.com/~lotomic" target="_blank"><img src="https://img.shields.io/npm/dy/%40lotomic%2Fchanjs?style=flat&logoColor=%23FA0809" alt="Downloads" /></a>
</p>

> 基于 `Express + TypeScript` 的轻量后端基础库，提供配置加载、数据库接入、常用中间件、服务层封装，以及 `helper/common` 扩展能力。

> 感谢🎉🎉🎉🎉👉👉👉👉 [ChanCMS](https://github.com/chancms) 👍👍👍👍👍

## 安装

```bash
npm install @lotomic/chanjs --save
```

## 快速开始

```ts
import Chan from "@lotomic/chanjs";

const chan = new Chan({
  port: 3000,
  env: "development",
});

await chan.start();

chan.app.get("/health", (_req, res) => {
  res.json({ ok: true });
});

chan.run((port) => {
  console.log(`${Chan.config.APP_NAME} is running on ${port}`);
});
```

## 运行时目录约定

框架会按以下约定加载配置、路由与扩展：

- `config/index.js`：应用配置（端口、数据库、waf、cors、静态目录等）
- `app/modules/*/router.js`：业务模块路由
- `app/router.js`：全局公共路由（可选）
- `app/common/*.js`：挂载到 `Chan.common`
- `app/helper/*.js`：挂载到 `Chan.helper`

```text
|- app
|  |- modules
|  |  |- web
|  |  |  |- controller
|  |  |  |- service
|  |  |  |- view
|  |  |  |- router.js
|  |  |- admin
|  |     |- controller
|  |     |- service
|  |     |- router.js
|  |- common
|  |- helper
|  |- extend
|  |- router.js
|- config
|  |- index.js
|- public
|  |- favicon.ico
```

## 核心能力

- 启动流程统一：`start()` 完成配置、DB、扩展、中间件、路由、错误处理
- 多数据库连接管理（`DatabaseManager` + `knex`）
- 自动加载 `app/common`、`app/helper` 的业务扩展
- 提供 `Controller` / `Service` 基类，封装常见返回与 CRUD
- 内置中间件链（WAF、favicon、static、cookie、body、cors、template、header）

## API 概览

> 通用查询接口

```TS
/**
 * @description 通用Controller page query 参数
 * @param PaginationQuery {Object}
 * @property query.current {number} 当前起始页
 * @property query.pageSize {number} 每页条数
 * @property query.keywords {string} 关键词
 * @property query.params {Object} 查询条件
 * @property query.sort {Object} 排序字段 example {create_time:'asc'}
 */
type PageQueryOptions = {
  current?: number
  pageSize?: number
  keywords?: string
  sort?: {
    [column_name?: string]: 'asc' | 'desc'
  }
  [k: string]: unknown
}
/**
 * @description 通用Service分页查询对象 TO DB
 * @param PaginationQuery {Object}
 * @property query.current {number} 当前起始页
 * @property query.pageSize {number} 每页条数
 * @property query.field {array->string} 返回字段
 * @property query.params {Object} 查询条件
 * @property query.sort {Object} 排序字段 example {create_time:'asc'}
 */
type PaginationQuery = {
  current?: number;
  pageSize?: number;
  params?: SqlBasicData;
  field?: string[];
  sort?: { [field: string]: "asc" | "desc" };
};
```

### `new Chan(options?)`

- `options.port`：优先级高于默认值，默认 `3000`
- `options.env`：运行环境，默认 `production`

### 实例方法

- `start()`：初始化应用（必须先执行）
- `run(cb?)`：启动 HTTP 服务
- `app`：原生 `express.Application`
- `router`：原生 `express.Router`
- `loadRouter()` / `loadCommonRouter()`：手动重载路由（高级用法）

### 静态属性

- `Chan.config`：当前运行配置（来自 `config/index.js`）
- `Chan.db`：默认数据库连接（`db` 数组第一个成功连接）
- `Chan.common`：公共函数集合（内置 + `app/common`）
- `Chan.helper`：工具函数集合（内置 + `app/helper`）
- `Chan.cache`：内置内存缓存实例
- `Chan.paths`：路径工具（`rootPath/appPath/configPath/...`）
- `Chan.Controller` / `Chan.Service`：基类

### `Chan.Controller`

控制器基类，常用方法：

- `success(result, msg?)`
- `fail({ msg?, data?, code? })`
- `error({ err, data?, code? })`
- `paginate(list, total, current, pageSize?)`

### `Chan.Service`

数据库服务基类，常用方法：

- 获取QueryBuilder: createQueryBuilder 返回 knex.QueryBuilder
- 查询：`all`、`find`、`findOne`、`findById`、`query`、`count`、`exists`、`join`
- 写入：`insert`、`insertMany`、`updateById`、`updateByQuery`、`updateMany`
- 删除：`delete`、`deleteById`、`deleteMany`、`softDelete`、`restore`、`forceDelete`
- 统计：`stats`

## helper 与 common

### `Chan.common`

来源：

- 包内置：`src/common/*`
- 业务扩展：`app/common/*.js`

### `Chan.helper`

来源：

- 包内置：`src/helper/*`
- 业务扩展：`app/helper/*.js`

内置常用方法（按当前源码）：

- 时间：`formatTime`、`formatDay`、`formatDateFields`、`transformDate`
- 安全：`setToken`、`getToken`、`verifyToken`、`aesEncrypt`、`aesDecrypt`
- 网络：`request`
- 字符串与内容：`htmlEncode`、`htmlDecode`、`filterBody`
- 其他：`getIp`、`arrToObj`、`buildTree`、`filterFields`

## Config 配置说明

默认从 `config/index.js` 加载配置（`start()` 时读取）。
同时会读取环境变量文件：默认 `.env.prd`，可通过 `ENV_FILE` 覆盖。

```js
// config/index.js
export default {
  APP_NAME: "LotoCMS",
  APP_VERSION: "1.0.0",
  env: "development",
  PROXY: "false",

  AES_SALT: "your_aes_salt",
  JWT_SECRET: "your_jwt_secret",

  cookieKey: "lotocms_token",
  BODY_LIMIT: "2mb",

  modules: ["admin", "web"],

  views: ["app/view"],
  statics: [{ prefix: "/static", dir: "public", maxAge: 0 }],

  cors: {
    origin: "*",
    methods: ["GET", "HEAD", "PUT", "PATCH", "POST", "DELETE"],
    credentials: true,
    maxAge: 86400,
  },

  waf: {
    enabled: true,
    rateLimit: {
      windowMs: "1m",
      max: 120,
      ignorePaths: ["/health"],
    },
  },

  db: [
    {
      key: "default",
      client: "mysql2",
      connection: {
        host: "127.0.0.1",
        port: 3306,
        user: "root",
        password: "123456",
        database: "cms_test",
        charset: "utf8mb4",
      },
      pool: { min: 0, max: 2 },
      isDefault: true,
    },
  ],
};
```

常用字段说明：

- `modules`：模块加载顺序（框架会把 `web` 自动放到最后）
- `db`：数据库配置数组，每项需包含 `client + connection`
- `waf`：WAF 开关与限流配置（`enabled` / `rateLimit`）
- `PROXY`：`trust proxy`（支持字符串 `"true"` / `"false"` 或布尔）
- `views`：模板目录数组（运行时会自动追加 `app/modules/web/view`）
- `statics`：静态目录映射
- `cors`：CORS 配置

## 中间件加载顺序

`start()` 内部注册顺序如下：

1. `waf`
2. `serve-favicon`
3. `express.static`
4. `cookie-parser`
5. `express.raw/json/urlencoded`
6. `cors`
7. `express-art-template`
8. `header`

说明：

- `favicon` 默认读取 `public/favicon.ico`
- `static` 当前实现需要显式提供 `prefix`
- `body` 默认支持 `application/xml`、JSON、表单

## 依赖说明

安装 `@lotomic/chanjs` 后会自动安装框架运行所需核心依赖。

如果业务侧要使用以下能力，请在你的应用中额外安装对应 `peerDependencies`：

```bash
pnpm add multer nodemailer xss zod
```