/** * 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 globalOptions: Record = {} forcedOptionAccess = new Map() constructor(jwtSecret: string, config: Record = {}, 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): Record { return { _id: user._id, roleId: user.roleId } } isUserActive(user: WithId): boolean { return user.active === true } getUserRoleIds(user: WithId): string[] { return Array.isArray(user.roleId) ? user.roleId.map(String) : user.roleId ? [String(user.roleId)] : [] } isRoleSuperAdmin(role: WithId | null): boolean { return !!role?.isSuperAdmin } getRolePowers(role: WithId | null): string[] { return role?.powers || [] } getUserDisplayName(user: WithId): string { return user.nickname || "" } }