chanjs 2.8.3 → 2.8.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -188,21 +188,26 @@ class Repository extends BaseComponent {
188
188
  return row;
189
189
  }
190
190
 
191
- /** 查询全部,默认上限1000条 */
192
- async all({ query={}, sort={}, fields=[], limit=1000 }={}) {
191
+ /**
192
+ * 查询全部。上限口径统一收口到 config.LIMIT_MAX(this.limit):
193
+ * 未传 limit 时默认取 this.limit;显式传入的 limit 也会被钳制到 [1, this.limit],
194
+ * 避免"all 默认 1000 / 分页上限 300"两套口径并存。
195
+ */
196
+ async all({ query={}, sort={}, fields=[], limit }={}) {
193
197
  const err = this._guard({ query });
194
198
  if (err) return err;
195
- const list = await this._buildBaseQuery({query,sort,fields}).limit(limit);
199
+ const size = Math.min(Math.max(Number(limit) || this.limit, 1), this.limit);
200
+ const list = await this._buildBaseQuery({query,sort,fields}).limit(size);
196
201
  return { success:true, code:CODE_OK, msg:"查询成功", data: list };
197
202
  }
198
203
 
199
- /** 分页偏移查询 */
204
+ /** 分页偏移查询(limit 同 all() 口径,钳制到 config.LIMIT_MAX) */
200
205
  async find({ query={}, sort={}, fields=[], limit, offset }={}) {
201
206
  const err = this._guard({ query });
202
207
  if (err) return err;
203
208
  let q = this._buildBaseQuery({query,sort,fields});
204
209
  typeof offset === 'number' && (q = q.offset(offset));
205
- typeof limit === 'number' && (q = q.limit(limit));
210
+ typeof limit === 'number' && (q = q.limit(Math.min(Math.max(limit, 1), this.limit)));
206
211
  return { success:true, code:CODE_OK, msg:"查询成功", data: await q };
207
212
  }
208
213
 
@@ -4,6 +4,7 @@ import {
4
4
  } from "../../middleware/index.js";
5
5
  import { health } from "../../middleware/health.js";
6
6
  import { BODY_LIMIT } from "../../config/index.js";
7
+ import logger from "../../utils/logger.js";
7
8
 
8
9
  /**
9
10
  * 注册核心中间件(顺序固化:不可随意调整)
@@ -17,6 +18,19 @@ export async function registerCoreMiddleware(chan) {
17
18
  await waf(app, cfg.waf ?? { enabled: false });
18
19
  // 1.5 健康检查端点(默认开启,config.health = {enabled,path} 可调;浅模式零 IO)
19
20
  app.use(health(chan, cfg.health ?? {}));
21
+ // 1.6 宿主全局中间件插槽:config.middleware 数组,按声明顺序注册。
22
+ // 元素支持两种形态:express 中间件本身 (req,res,next);或工厂 () => express 中间件(需闭包 chan/config 时用)。
23
+ // 注册位置在核心链早期、模块路由之前,保证对所有响应(含静态资源)生效。
24
+ // 注意:app/router.js(loadCommonRouter)的执行时机在模块路由之后,app.use 在那里
25
+ // 只罩得住 404 兜底请求,安全响应头等全局策略应经本插槽注册而非写在 router.js。
26
+ for (const mw of cfg.middleware ?? []) {
27
+ const fn = typeof mw === "function" && mw.length <= 1 ? mw(chan) : mw;
28
+ if (typeof fn !== "function") {
29
+ logger.warn(`[Chan] config.middleware 含非法项(须为中间件或中间件工厂),已跳过: ${String(mw)}`);
30
+ continue;
31
+ }
32
+ app.use(fn);
33
+ }
20
34
  // 2. Favicon
21
35
  favicon(app);
22
36
  // 3. 静态资源
@@ -172,7 +172,8 @@ const otherDb = app.dbManager.get("logs");
172
172
  | `REDIS_ENABLED` / `REDIS` | Redis 配置 |
173
173
  | `JWT_SECRET` | JWT 签名密钥 |
174
174
  | `LOCALE` | i18n 默认语言(默认 `zh-CN`)|
175
- | `LIMIT_MAX` | Repository 单页上限(默认 300)|
175
+ | `LIMIT_MAX` | Repository 单页上限(默认 300);`all()`/`find()` 显式 limit 亦被钳制到该值 |
176
+ | `middleware` | 宿主全局中间件插槽:数组,元素为 express 中间件或中间件工厂 `(chan) => mw`,注册于核心链早期(健康检查后、静态资源前),对所有响应生效 |
176
177
  | `SLOW_THRESHOLD` | 数据库慢查询阈值(ms,默认 200),超过记 warn 日志 |
177
178
  | `SHUTDOWN_TIMEOUT` | 优雅停机强制退出超时(ms,默认 5000)|
178
179
  | `BODY_LIMIT` | 请求体上限(默认 `10mb`)|
@@ -1,20 +1,22 @@
1
1
  /**
2
- * 自定义响应头中间件,隐藏原生Express标识,统一输出ChanCMS
3
- * @param {express.Application} app Express实例
4
- * @param {{APP_NAME?: string, APP_VERSION?: string}} [opts] 配置选项
2
+ * 品牌响应头中间件:隐藏原生 Express 标识,统一输出 ChanCMS。
3
+ *
4
+ * 注:安全响应头(X-Content-Type-Options / HSTS / Referrer-Policy /
5
+ * Permissions-Policy / CSP 等)属于宿主业务策略,不在框架层默认设置——
6
+ * 由各项目的 security-headers 中间件统一收敛(本项目见 app/middleware/security-headers.js)。
7
+ * 尤其 CSP frame-ancestors 一旦在框架写死 'self',会与需要被第三方
8
+ * iframe 嵌入的宿主业务直接冲突,故不在此声明。
5
9
  */
6
10
  export const header = (app, opts = {}) => {
7
11
  const appName = opts.APP_NAME || "ChanCMS";
8
12
  const appVer = opts.APP_VERSION || "";
9
13
  const poweredBy = appVer ? `${appName}/${appVer}` : appName;
14
+ // 静态资源在核心链第 3 步即被接住、到不了本中间件,Express 会默认补
15
+ // X-Powered-By: Express 泄露技术栈——先禁用默认注入,品牌头只由下方显式设置
16
+ app.disable("x-powered-by");
10
17
 
11
18
  app.use((_, res, next) => {
12
19
  res.setHeader("X-Powered-By", poweredBy);
13
- // 常驻安全响应头:无论 WAF 是否启用都生效
14
- // 禁止 MIME 嗅探(防 XSS 利用 Content-Type 歧义)
15
- res.setHeader("X-Content-Type-Options", "nosniff");
16
- // 防点击劫持:仅允许同源 iframe 嵌套(如需被第三方嵌入请按需放宽)
17
- res.setHeader("Content-Security-Policy", "frame-ancestors 'self'");
18
20
  next();
19
21
  });
20
- };
22
+ };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "chanjs",
4
- "version": "2.8.3",
4
+ "version": "2.8.4",
5
5
  "description": "chanjs基于 Node.js + Express 5 的标准 HMVC 框架(NHMVC),纯 JavaScript(ESM)开发。",
6
6
  "main": "index.js",
7
7
  "module": "index.js",