feat!: 拆分 core / server 入口,peer deps 全部 optional

让只用 Shrimp 核心(RPC + 模块声明 + 内存 CRUD)的项目不必装
express / mongoose / bcrypt / jsonwebtoken,显著降低 install 时间。

- src/core.ts:0 重依赖入口(Shrimp / MemoryShrimpCrud / 类型)
- src/server.ts:在 core 之上再导出 ShrimpServer + MongoShrimpCrud
- package.json:加 exports 字段 + peerDependenciesMeta.optional
- Shrimp.ts:bcrypt 改 lazy import,只有走 Password 字段才触发
- MemoryShrimpCrud.populateItems:接 crudRegistry 参数(对齐 Mongo)
- ShrimpTableModule 构造时自动登记 crudRegistry,业务无需手动 wire
- 新增 test/crudRegistry.test.ts 验证自动登记 + relation 自动 populate

BREAKING: import { ShrimpServer } from 'shrimp-server' 不再可用,
请改为 'shrimp-server/server'。
This commit is contained in:
2026-05-23 16:47:18 +08:00
parent 40f311796b
commit 8e4d5620b7
11 changed files with 207 additions and 99 deletions
+10 -5
View File
@@ -5,9 +5,14 @@
import { ShrimpCode, IShrimpResponse, ITableCrudProto, IModuleInfo, IUser, IRole, WithId, IRoleProto, IPageQuery, IPageResult, IFieldConfig, IFieldRule, IFieldTypeHandler, IShrimpQuery, IShrimpCondition, IShrimpPopulate, ShrimpConfig, IShrimpOperator, IMenuItem, ShrimpError, ShrimpFieldTypes, ILabel } from "./IShrimpType"
import * as bcrypt from "bcrypt"
import { AsyncLocalStorage } from 'async_hooks'
// 懒加载 bcrypt: 只有走到 Password 字段 hash 或 verifyPassword 才 import,
// 让纯核心(MemoryShrimpCrud + 业务模块)的消费方可以不装 bcrypt
async function loadBcrypt(): Promise<typeof import("bcrypt")> {
return await import("bcrypt")
}
export class Shrimp {
root: Shrimp = this
modules: Map<string, ShrimpModule> = new Map()
@@ -253,6 +258,7 @@ export const defaultTypeHandlers: Record<string, IFieldTypeHandler> = {
[ShrimpFieldTypes.Password]: {
reqFilter: async (value) => {
if (typeof value === 'string' && value.length > 0) {
const bcrypt = await loadBcrypt()
return bcrypt.hash(value, 10)
}
return value
@@ -318,10 +324,8 @@ export class ShrimpTableModule<T, P extends ITableCrudProto<T> = ITableCrudProto
if (fields) {
this.fields = fields
}
// 自动注册 CRUD 到 root.crudRegistry,供 MongoShrimpCrud.populateItems 自动解析 relation
if ((dataSource as any).model) {
this.root.crudRegistry.set(moduleKey, dataSource)
}
// 自动注册 CRUD 到 root.crudRegistry,populateItems 据此解析 relation
this.root.crudRegistry.set(moduleKey, dataSource)
}
getFields(): IFieldConfig[] {
@@ -711,6 +715,7 @@ export class UserModule extends ShrimpTableModule<WithId<IUser>> {
/** 校验密码,子类可覆盖 */
protected async verifyPassword(storedPassword: string, plainPassword: string): Promise<boolean> {
const bcrypt = await loadBcrypt()
return bcrypt.compare(plainPassword, storedPassword)
}