发布日期: 2026-01-08
主题: Schema 验证默认启用 + Model 自动加载机制
本次更新专注于提升 Model 层的易用性和开发体验。
变更内容:
- Schema 验证从"需要显式启用"改为"默认启用"
- 提升数据质量,减少脏数据写入
- 符合业界最佳实践(Mongoose、Sequelize 等默认启用)
使用示例:
// ✅ v1.0.5: Schema 验证默认生效
Model.define('users', {
schema: (dsl) => dsl({
username: 'string:3-32!',
email: 'email!'
})
// 无需配置 options.validate,验证自动生效
});
// 插入时自动验证
await User.insertOne({
username: 'ab', // ❌ 验证失败: username 太短
email: 'invalid' // ❌ 验证失败: 邮箱格式错误
});
// 抛出 VALIDATION_ERROR
// ✅ 正确数据通过验证
await User.insertOne({
username: 'john',
email: 'john@example.com'
});禁用验证:
// 全局禁用
Model.define('users', {
schema: ...,
options: { validate: false } // 全局禁用验证
});
// 单次操作跳过
await User.insertOne(doc, { skipValidation: true });影响范围:
- ✅ 现有未定义 schema 的 Model 不受影响
- ✅ 已定义 schema 的 Model 自动启用验证
⚠️ 如需禁用,需显式配置validate: false
迁移指南:
// v1.0.4: 验证需要显式启用
Model.define('users', {
schema: ...,
options: { validate: true } // 需要配置
});
// v1.0.5: 验证默认启用
Model.define('users', {
schema: ...
// 无需配置,自动启用
});
// 如需禁用(兼容旧版本行为)
Model.define('users', {
schema: ...,
options: { validate: false } // 显式禁用
});风险评估: 🟡 低风险
- ✅ 未定义 schema 的 Model 不受影响
- ✅ 验证失败会抛出明确的错误,易于调试
- ✅ 可通过配置或单次操作跳过验证
功能说明:
- 自动扫描指定目录,加载所有 Model 定义文件
- 支持多种文件格式:
js、ts、mjs、cjs - 支持递归扫描子目录
- 支持自定义文件名模式(glob 语法)
使用方式:
const msq = new MonSQLize({
type: 'mongodb',
databaseName: 'mydb',
config: { uri: '...' },
models: './models' // ← 简化配置,自动加载
});
await msq.connect(); // 自动扫描 models/*.model.{js,ts,mjs,cjs}
// 直接使用(无需手动 Model.define)
const User = msq.model('users');const msq = new MonSQLize({
type: 'mongodb',
databaseName: 'mydb',
config: { uri: '...' },
models: {
path: './models', // Model 文件目录
pattern: '*.model.js', // 文件名模式(支持 glob)
recursive: true // 递归扫描子目录
}
});
await msq.connect();Model 文件格式:
// models/user.model.js
module.exports = {
name: 'users', // 集合名称(必需)
schema: (dsl) => dsl({
username: 'string:3-32!',
email: 'email!'
}),
methods: (model) => ({
instance: {
checkPassword(password) {
return this.password === password;
}
},
static: {
async findByUsername(username) {
return await model.findOne({ username });
}
}
}),
hooks: (model) => ({
insert: {
before: async (ctx, doc) => {
doc.createdAt = new Date();
return doc;
}
}
}),
indexes: [
{ key: { username: 1 }, unique: true }
]
};目录结构示例:
models/
├── user.model.js
├── post.model.js
├── comment.model.js
└── admin/
├── role.model.js
└── permission.model.js支持的文件格式:
- ✅
.js- CommonJS - ✅
.mjs- ES Module - ✅
.cjs- CommonJS(显式) - ✅
.ts- TypeScript(需要 ts-node)
配置选项:
| 选项 | 类型 | 默认值 | 说明 |
|---|---|---|---|
path |
string | - | Model 文件目录(必需) |
pattern |
string | *.model.{js,ts,mjs,cjs} |
文件名模式(支持 glob) |
recursive |
boolean | false |
是否递归扫描子目录 |
错误处理:
目录不存在:
[Model] Models directory not found: /path/to/models
文件格式错误:
[Model] ❌ Failed to load models/invalid.model.js: export is null
[Model] ❌ Failed to load models/no-name.model.js: missing 'name' property
重复注册:
[Model] Model 'users' already registered, skipping models/user2.model.js最佳实践:
- 统一命名规范: 使用
{name}.model.js格式 - 按功能分组: 使用子目录组织(如
admin/、public/) - 导出格式: 始终使用
module.exports = { name, ... } - 测试环境: 可以禁用自动加载,手动注册测试 Model
注意事项:
⚠️ 文件必须包含name属性⚠️ 重复的 Model 名称只会注册第一个⚠️ 文件语法错误会导致加载失败(记录日志,不中断)⚠️ TypeScript 文件需要运行时支持(ts-node 或编译后)
与手动注册对比:
| 方式 | 优点 | 缺点 |
|---|---|---|
| 手动注册 | 精确控制、显式依赖 | 重复代码、维护成本高 |
| 自动加载 | 自动发现、代码简洁 | 隐式依赖、加载顺序不确定 |
推荐: 生产环境使用自动加载,测试环境可选择手动注册。
新增类型:
-
✅
BaseOptions.models- Model 自动加载配置interface BaseOptions { models?: string | { path: string; pattern?: string; recursive?: boolean; }; }
-
✅
ModelDefinition.options.validate- Schema 验证配置interface ModelDefinition { options?: { validate?: boolean; // 默认 true }; }
更新类型:
- ✅ 完善
Model.define()类型定义 - ✅ 完善
msq.model()返回类型
Model 自动加载测试 (19个):
- ✅ 简化配置(字符串路径)
- ✅ 默认 pattern 验证
- ✅ 不递归扫描(默认)
- ✅ 自定义 pattern
- ✅ 递归扫描
- ✅ 多种文件格式(js/mjs/cjs)
- ✅ 文件格式验证(缺少 name、空 name、null export)
- ✅ 目录不存在处理
- ✅ 文件加载失败处理
- ✅ 防止重复注册
- ✅ 无效配置处理
- ✅ connect() 后可用
- ✅ Schema 验证集成
- ✅ 自定义方法支持
- ✅ Hooks 支持
- ✅ 日志输出验证
Schema 验证测试 (16个):
- ✅ 默认启用验证
- ✅ insertOne 时验证
- ✅ insertMany 时逐个验证
- ✅ 返回详细错误信息
- ✅ 指示错误字段名
- ✅ 指示错误类型
- ✅ 批量插入错误索引
- ✅ 全局禁用验证
- ✅ 单次操作跳过验证
- ✅ 跳过验证时仍执行 hooks
- ✅ 未定义 schema 的 Model 无影响
- ✅ v1.0.4 风格配置兼容
- ✅ 可选字段正确处理
- ✅ 性能影响测试(验证开销 <30%)
- ✅ 嵌套对象验证
- ✅ 数组验证
| 功能模块 | 测试数量 | 通过率 | 覆盖率 |
|---|---|---|---|
| Model 自动加载 | 19 | 100% ✅ | ~95% |
| Schema 验证 | 16 | 100% ✅ | ~90% |
| 总计 | 35 | 100% ✅ | ~92% |
-
docs/model.md- 更新(新增 1,700 字)- Model 自动加载章节
- Schema 验证章节
- 配置选项详解
- 最佳实践
-
examples/model/auto-load.js- Model 自动加载示例- 简化配置示例
- 完整配置示例
- Schema 验证示例
-
examples/model/schema-validation.js- Schema 验证示例- 基本验证
- 验证错误详情
- 可选字段
- 跳过验证
- 嵌套对象验证
-
examples/model/models/- Model 定义文件示例user.model.js- User Model 定义post.model.js- Post Model 定义admin/role.model.js- Role Model 定义(子目录)
README.md- 更新特性列表和使用示例index.d.ts- 完善 TypeScript 类型定义
- ✅ 编写 Model 自动加载测试用例(19个)
- ✅ 编写 Schema 验证默认启用测试(16个)
- ✅ 验证现有测试兼容性
- ✅ 更新
docs/model.md- 添加 Schema 验证章节 - ✅ 更新
docs/model.md- 添加自动加载章节 - ✅ 添加迁移指南
- 支持跨数据库 Model 操作
- Model 层性能优化
- 更多示例和最佳实践
推荐升级: ✅ 强烈推荐
升级命令:
npm install monsqlize@1.0.5- ✅ 如果你的 Model 已定义 schema,升级后会自动启用验证
- ✅ 如果验证失败,会抛出
VALIDATION_ERROR错误 - ✅ 可通过
validate: false禁用验证(不推荐) - ✅ 可通过
models配置启用自动加载,减少手动注册代码
Schema 验证:
- ✅ 始终定义 schema,保证数据质量
- ✅ 合理使用可选字段,避免过度严格
- ✅ 使用 hooks 添加复杂验证逻辑
- ✅ 捕获
VALIDATION_ERROR返回友好错误
Model 自动加载:
- ✅ 使用统一的文件命名规范(
*.model.js) - ✅ 按功能模块组织目录结构
- ✅ 测试环境可手动注册,保持灵活性
- 📖 完整文档
- 💬 GitHub Issues
- 📧 邮件支持
最后更新: 2026-01-08