- Shrimp.ts (875 行) 按类拆分到 Shrimp/(7 文件: Shrimp, ShrimpModule, ShrimpTableModule, ShrimpPower, ShrimpCrud, UserRoleModule, OperationLogModule) - forMongo/: MongoShrimpCrud + MongoShrimp(原 ShrimpServer 的 mongo 装配部分,无 express) - forExpress/: buildShrimpRouter + jwtAuth + types - main/: index(0 依赖核心) + expmon(express+mongo 整合,导出 ShrimpServer) + types(纯协议) - 入口子路径 server → expmon(express+mongo 整合方案命名更准确) - 删除冗余的 index.ts / core.ts(合并为 main/index.ts)
100 lines
3.7 KiB
TypeScript
100 lines
3.7 KiB
TypeScript
/**
|
|
* Shrimp expmon 入口 — Express + Mongoose 整合方案
|
|
*
|
|
* 在 core 之上把 forMongo(MongoShrimp + 数据源)和 forExpress(buildShrimpRouter
|
|
* + JWT)拼起来,导出开箱即用的 ShrimpServer 装配体。
|
|
*
|
|
* 这一入口需要消费方安装 peer:express / mongoose / jsonwebtoken / bcrypt。
|
|
* 不需要时改从 'shrimp-server' 导入,不会触发任何 peer。
|
|
*
|
|
* 想换掉其中一块的高级用法:
|
|
* - 自己造 ITokenAuth(看 createJwtTokenAuth 实现)
|
|
* - 自己造 dataSource(实现 ShrimpCrud 接口)
|
|
* - 直接 buildShrimpRouter(deps) 拼自己的 Express app,绕开本类
|
|
*/
|
|
|
|
import { Router } from "express"
|
|
import { MongoShrimp, UserSchema, RoleSchema, OperationLogSchema } from "../forMongo/MongoShrimp"
|
|
import { buildShrimpRouter } from "../forExpress/buildShrimpRouter"
|
|
import { createJwtTokenAuth } from "../forExpress/jwtAuth"
|
|
import type { ITokenAuth, IUserAccessor } from "../forExpress/types"
|
|
import type { RootShrimpPower } from "../Shrimp/ShrimpPower"
|
|
import type { IUser, IRole, WithId } from "../IShrimpType"
|
|
|
|
// 再导出所有 core 的符号,'shrimp-server/expmon' 单一入口就够用
|
|
export * from "./index"
|
|
|
|
// ===== forMongo / forExpress 公开符号 =====
|
|
export { MongoShrimp, UserSchema, RoleSchema, OperationLogSchema } from "../forMongo/MongoShrimp"
|
|
export { MongoShrimpCrud } from "../forMongo/MongoShrimpCrud"
|
|
export { buildShrimpRouter } from "../forExpress/buildShrimpRouter"
|
|
export { createJwtTokenAuth } from "../forExpress/jwtAuth"
|
|
export type { IJwtTokenAuthOptions } from "../forExpress/jwtAuth"
|
|
export type { ITokenAuth, IUserAccessor, IShrimpRouterDeps } from "../forExpress/types"
|
|
|
|
// ============== ShrimpServer ==============
|
|
|
|
export class ShrimpServer extends MongoShrimp implements IUserAccessor {
|
|
router: Router
|
|
jwtSecret: string
|
|
config: Record<string, any>
|
|
globalOptions: Record<string, any> = {}
|
|
forcedOptionAccess = new Map<string, RootShrimpPower>()
|
|
|
|
constructor(jwtSecret: string, config: Record<string, any> = {}, mongodbUri: string = "mongodb://localhost:27017/shrimp") {
|
|
super(mongodbUri)
|
|
this.jwtSecret = jwtSecret
|
|
this.config = config
|
|
|
|
this.router = buildShrimpRouter({
|
|
shrimp: this,
|
|
userModule: this.userModule,
|
|
roleModule: this.roleModule,
|
|
operationLogModule: this.operationLogModule,
|
|
tokenAuth: this.createTokenAuth(),
|
|
config: this.config,
|
|
globalOptions: this.globalOptions,
|
|
forcedOptionAccess: this.forcedOptionAccess,
|
|
userAccessor: this,
|
|
})
|
|
}
|
|
|
|
registerOptions(key: string, options: any, access?: RootShrimpPower) {
|
|
this.globalOptions[key] = options
|
|
if (access) {
|
|
this.forcedOptionAccess.set(key, access)
|
|
}
|
|
}
|
|
|
|
/** 创建 Token 鉴权,默认 JWT。子类可覆盖换成 session 之类。 */
|
|
protected createTokenAuth(): ITokenAuth {
|
|
return createJwtTokenAuth(this.jwtSecret)
|
|
}
|
|
|
|
// ============== 可覆盖的用户/角色字段访问钩子(实现 IUserAccessor) ==============
|
|
|
|
getJwtPayload(user: WithId<IUser>): Record<string, any> {
|
|
return { _id: user._id, roleId: user.roleId }
|
|
}
|
|
|
|
isUserActive(user: WithId<IUser>): boolean {
|
|
return user.active === true
|
|
}
|
|
|
|
getUserRoleIds(user: WithId<IUser>): string[] {
|
|
return Array.isArray(user.roleId) ? user.roleId.map(String) : user.roleId ? [String(user.roleId)] : []
|
|
}
|
|
|
|
isRoleSuperAdmin(role: WithId<IRole> | null): boolean {
|
|
return !!role?.isSuperAdmin
|
|
}
|
|
|
|
getRolePowers(role: WithId<IRole> | null): string[] {
|
|
return role?.powers || []
|
|
}
|
|
|
|
getUserDisplayName(user: WithId<IUser>): string {
|
|
return user.nickname || ""
|
|
}
|
|
}
|