- 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)
168 lines
5.8 KiB
TypeScript
168 lines
5.8 KiB
TypeScript
/**
|
|
* MongoShrimp — Shrimp + Mongoose 装配体(无 HTTP 层)
|
|
*
|
|
* 提供:
|
|
* - 默认 Mongoose Schema(User / Role / OperationLog),子类可覆盖
|
|
* - Mongoose Model 工厂 + 缓存
|
|
* - 默认 CRUD / Module 工厂,绑定 MongoShrimpCrud
|
|
* - mongoose.connect + onDbConnected 钩子
|
|
* - initDefaultData 默认角色/用户播种
|
|
*
|
|
* 不知道:express / jwt / 任何 HTTP 概念。
|
|
* 上层把 HTTP 装到这之上,见 main/expmon.ts 的 ShrimpServer。
|
|
*/
|
|
|
|
import mongoose, { Schema, Model } from "mongoose"
|
|
import { Shrimp } from "../Shrimp/Shrimp"
|
|
import { UserModule, RoleModule } from "../Shrimp/UserRoleModule"
|
|
import { OperationLogModule } from "../Shrimp/OperationLogModule"
|
|
import type { ShrimpCrud } from "../Shrimp/ShrimpCrud"
|
|
import { IUser, IRole, IOperationLog, WithId } from "../IShrimpType"
|
|
import { MongoShrimpCrud } from "./MongoShrimpCrud"
|
|
|
|
export const UserSchema = new Schema({
|
|
username: { type: String, required: true },
|
|
password: { type: String, required: true },
|
|
nickname: { type: String, default: "" },
|
|
roleId: { type: [Schema.Types.ObjectId], ref: "Role", default: [] },
|
|
active: { type: Boolean, default: true },
|
|
}, { timestamps: true })
|
|
|
|
export const RoleSchema = new Schema({
|
|
name: { type: String, required: true },
|
|
description: { type: String, default: "" },
|
|
isSuperAdmin: { type: Boolean, default: false },
|
|
powers: { type: [String], default: [] },
|
|
}, { timestamps: true })
|
|
|
|
export const OperationLogSchema = new Schema({
|
|
operatorId: { type: String, default: null },
|
|
ip: { type: String, default: "" },
|
|
method: { type: String, required: true },
|
|
args: { type: String, default: "" },
|
|
success: { type: Boolean, default: true },
|
|
errorMsg: { type: String, default: "" },
|
|
createdAt: { type: Number, default: () => Date.now() },
|
|
}, { timestamps: false })
|
|
|
|
export class MongoShrimp extends Shrimp {
|
|
userModule: UserModule
|
|
roleModule: RoleModule
|
|
operationLogModule: OperationLogModule
|
|
|
|
protected _userModel?: Model<IUser>
|
|
protected _roleModel?: Model<IRole>
|
|
protected _operationLogModel?: Model<IOperationLog>
|
|
|
|
constructor(mongodbUri: string = "mongodb://localhost:27017/shrimp") {
|
|
super()
|
|
|
|
const userCrud = this.createUserCrud()
|
|
const roleCrud = this.createRoleCrud()
|
|
const operationLogCrud = this.createOperationLogCrud()
|
|
|
|
this.userModule = this.createUserModule(userCrud)
|
|
this.roleModule = this.createRoleModule(roleCrud)
|
|
this.operationLogModule = this.createOperationLogModule(operationLogCrud)
|
|
|
|
mongoose.connect(mongodbUri).then(() => {
|
|
console.log(mongodbUri + " MongoDB connected")
|
|
this.onDbConnected()
|
|
})
|
|
}
|
|
|
|
// ============== 可覆盖的 Schema 工厂 ==============
|
|
|
|
protected createUserSchema(): mongoose.Schema {
|
|
return UserSchema
|
|
}
|
|
|
|
protected createRoleSchema(): mongoose.Schema {
|
|
return RoleSchema
|
|
}
|
|
|
|
protected createOperationLogSchema(): mongoose.Schema {
|
|
return OperationLogSchema
|
|
}
|
|
|
|
protected getUserModel(): Model<IUser> {
|
|
if (!this._userModel) {
|
|
this._userModel = mongoose.model<IUser>("shrimp_users", this.createUserSchema())
|
|
}
|
|
return this._userModel
|
|
}
|
|
|
|
protected getRoleModel(): Model<IRole> {
|
|
if (!this._roleModel) {
|
|
this._roleModel = mongoose.model<IRole>("shrimp_roles", this.createRoleSchema())
|
|
}
|
|
return this._roleModel
|
|
}
|
|
|
|
protected getOperationLogModel(): Model<IOperationLog> {
|
|
if (!this._operationLogModel) {
|
|
this._operationLogModel = mongoose.model<IOperationLog>("shrimp_operation_logs", this.createOperationLogSchema())
|
|
}
|
|
return this._operationLogModel
|
|
}
|
|
|
|
// ============== 可覆盖的 Crud 工厂 ==============
|
|
|
|
protected createUserCrud(): MongoShrimpCrud<WithId<IUser>> {
|
|
return new MongoShrimpCrud<WithId<IUser>>(this.getUserModel())
|
|
}
|
|
|
|
protected createRoleCrud(): MongoShrimpCrud<WithId<IRole>> {
|
|
return new MongoShrimpCrud<WithId<IRole>>(this.getRoleModel())
|
|
}
|
|
|
|
protected createOperationLogCrud(): MongoShrimpCrud<WithId<IOperationLog>> {
|
|
return new MongoShrimpCrud<WithId<IOperationLog>>(this.getOperationLogModel())
|
|
}
|
|
|
|
// ============== 可覆盖的 Module 工厂 ==============
|
|
|
|
protected createUserModule(dataSource: ShrimpCrud<WithId<IUser>>): UserModule {
|
|
return new UserModule(this, dataSource)
|
|
}
|
|
|
|
protected createRoleModule(dataSource: ShrimpCrud<WithId<IRole>>): RoleModule {
|
|
return new RoleModule(this, dataSource)
|
|
}
|
|
|
|
protected createOperationLogModule(dataSource: ShrimpCrud<WithId<IOperationLog>>): OperationLogModule {
|
|
return new OperationLogModule(this.userModule, dataSource)
|
|
}
|
|
|
|
// ============== 启动钩子 ==============
|
|
|
|
protected async onDbConnected(): Promise<void> {
|
|
|
|
}
|
|
|
|
/** 初始化默认数据(如默认角色、用户),子类可覆盖 */
|
|
protected async initDefaultData(name: string = "Administrator", description: string = "System administrator with all permissions"): Promise<void> {
|
|
const result = await this.userModule.dataSource.list({ limit: 1 })
|
|
if (result.total > 0) return
|
|
console.log("初始化默认数据")
|
|
const adminRole = await this.roleModule.dataSource.add({
|
|
name: name,
|
|
description: description,
|
|
isSuperAdmin: true,
|
|
powers: [],
|
|
createdAt: Date.now(),
|
|
updatedAt: Date.now(),
|
|
})
|
|
|
|
await this.userModule.add({
|
|
username: "admin",
|
|
password: "admin",
|
|
nickname: "Administrator",
|
|
roleId: [adminRole._id],
|
|
active: true,
|
|
createdAt: Date.now(),
|
|
updatedAt: Date.now(),
|
|
})
|
|
}
|
|
}
|