@hazejs/orm 0.0.0-stage → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +27 -2
- package/dist/index.d.mts +125 -0
- package/dist/index.mjs +1067 -0
- package/dist/model-CBky_ILK.d.mts +728 -0
- package/dist/mongo/index.d.mts +21 -0
- package/dist/mongo/index.mjs +630 -0
- package/dist/record-DtkUCWRf.mjs +335 -0
- package/package.json +86 -3
|
@@ -0,0 +1,728 @@
|
|
|
1
|
+
import { ConfigInput, Logger } from "@hazejs/core";
|
|
2
|
+
import { Column, InferInsertModel, InferSelectModel, SQL, Table } from "drizzle-orm";
|
|
3
|
+
import { ClientSession, Db, Document, Filter, MongoClient, ObjectId, WithId } from "mongodb";
|
|
4
|
+
type Row$1<T extends Table> = InferSelectModel<T>;
|
|
5
|
+
type Insert<T extends Table> = InferInsertModel<T>;
|
|
6
|
+
/** 表的列名(drizzle 表定义中的属性名) */
|
|
7
|
+
type ColumnKey<T extends Table> = keyof Row$1<T> & string;
|
|
8
|
+
type Operator = '=' | '!=' | '<>' | '>' | '>=' | '<' | '<=' | 'like' | 'not like' | 'in' | 'not in' | 'between' | 'not between';
|
|
9
|
+
type Direction = 'asc' | 'desc';
|
|
10
|
+
/** 分页结果(普通对象,可直接作为响应返回) */
|
|
11
|
+
interface Paginated<T> {
|
|
12
|
+
data: T[];
|
|
13
|
+
total: number;
|
|
14
|
+
page: number;
|
|
15
|
+
perPage: number;
|
|
16
|
+
lastPage: number;
|
|
17
|
+
}
|
|
18
|
+
/** 不同驱动返回的 drizzle 实例类型不同,框架内部以统一接口调用 */
|
|
19
|
+
type AnyDatabase = any;
|
|
20
|
+
/** `{ status: 1, role: ['admin', 'owner'], deletedAt: null }`:数组为 IN,null 为 IS NULL */
|
|
21
|
+
type WhereObject<T extends Table> = { [K in ColumnKey<T>]?: Row$1<T>[K] | Array<Row$1<T>[K]> | null; };
|
|
22
|
+
type WhereCondition<T extends Table> = SQL | WhereObject<T> | ((group: Conditions<T>) => unknown);
|
|
23
|
+
interface Part$1 {
|
|
24
|
+
bool: 'and' | 'or';
|
|
25
|
+
sql: SQL;
|
|
26
|
+
}
|
|
27
|
+
/** 条件构造:多次 where 以 AND 连接,orWhere 以 OR 连接(从左到右),回调参数用于分组 */
|
|
28
|
+
declare class Conditions<T extends Table> {
|
|
29
|
+
readonly table: T;
|
|
30
|
+
protected parts: Part$1[];
|
|
31
|
+
constructor(table: T);
|
|
32
|
+
/**
|
|
33
|
+
* - `where('status', 1)` / `where('age', '>', 18)`
|
|
34
|
+
* - `where({ status: 1, role: ['a', 'b'] })`
|
|
35
|
+
* - `where(eq(users.id, 1))`(drizzle 表达式)
|
|
36
|
+
* - `where(q => q.where('a', 1).orWhere('b', 2))`(括号分组)
|
|
37
|
+
*/
|
|
38
|
+
where(condition: WhereCondition<T>): this;
|
|
39
|
+
where<K extends ColumnKey<T>>(column: K, value: Row$1<T>[K] | Array<Row$1<T>[K]> | null): this;
|
|
40
|
+
where<K extends ColumnKey<T>>(column: K, operator: Operator, value: unknown): this;
|
|
41
|
+
orWhere(condition: WhereCondition<T>): this;
|
|
42
|
+
orWhere<K extends ColumnKey<T>>(column: K, value: Row$1<T>[K] | Array<Row$1<T>[K]> | null): this;
|
|
43
|
+
orWhere<K extends ColumnKey<T>>(column: K, operator: Operator, value: unknown): this;
|
|
44
|
+
whereIn<K extends ColumnKey<T>>(column: K, values: ReadonlyArray<Row$1<T>[K]>): this;
|
|
45
|
+
whereNotIn<K extends ColumnKey<T>>(column: K, values: ReadonlyArray<Row$1<T>[K]>): this;
|
|
46
|
+
whereNull(column: ColumnKey<T>): this;
|
|
47
|
+
whereNotNull(column: ColumnKey<T>): this;
|
|
48
|
+
whereBetween<K extends ColumnKey<T>>(column: K, range: [Row$1<T>[K], Row$1<T>[K]]): this;
|
|
49
|
+
whereNotBetween<K extends ColumnKey<T>>(column: K, range: [Row$1<T>[K], Row$1<T>[K]]): this;
|
|
50
|
+
whereLike(column: ColumnKey<T>, pattern: string): this;
|
|
51
|
+
whereNotLike(column: ColumnKey<T>, pattern: string): this;
|
|
52
|
+
/** 条件成立时才应用:`.when(keyword, q => q.whereLike('name', `%${keyword}%`))` */
|
|
53
|
+
when<V>(value: V, callback: (query: this, value: NonNullable<V>) => unknown): this;
|
|
54
|
+
/** 当前条件组合成的 SQL(无条件时为 undefined) */
|
|
55
|
+
buildWhere(): SQL | undefined;
|
|
56
|
+
get hasConditions(): boolean;
|
|
57
|
+
/** 列名 → drizzle 列对象 */
|
|
58
|
+
columnOf(key: string): Column;
|
|
59
|
+
protected addCondition(bool: Part$1['bool'], args: unknown[]): this;
|
|
60
|
+
protected pushCondition(bool: Part$1['bool'], sql: SQL): this;
|
|
61
|
+
protected parseCondition(args: unknown[]): SQL | undefined;
|
|
62
|
+
protected compare(key: string, operator: Operator, value: unknown): SQL;
|
|
63
|
+
}
|
|
64
|
+
interface TimestampOptions {
|
|
65
|
+
createdAt?: string | false;
|
|
66
|
+
updatedAt?: string | false;
|
|
67
|
+
}
|
|
68
|
+
/** 模型类上的静态配置 */
|
|
69
|
+
interface ModelSettings {
|
|
70
|
+
readonly name: string;
|
|
71
|
+
table: Table;
|
|
72
|
+
connection?: string;
|
|
73
|
+
softDelete: boolean | string;
|
|
74
|
+
timestamps: boolean | TimestampOptions;
|
|
75
|
+
hidden: readonly string[];
|
|
76
|
+
append: readonly string[];
|
|
77
|
+
}
|
|
78
|
+
interface ModelMeta {
|
|
79
|
+
table: Table;
|
|
80
|
+
tableName: string;
|
|
81
|
+
columns: Record<string, Column>;
|
|
82
|
+
primaryKey: string | undefined;
|
|
83
|
+
softDelete: string | undefined;
|
|
84
|
+
createdAt: string | undefined;
|
|
85
|
+
updatedAt: string | undefined;
|
|
86
|
+
}
|
|
87
|
+
interface MongoSession {
|
|
88
|
+
name: string;
|
|
89
|
+
db: Db;
|
|
90
|
+
client: MongoClient;
|
|
91
|
+
/** 处于 Mongo.transaction() 中时的会话 */
|
|
92
|
+
session: ClientSession | undefined;
|
|
93
|
+
}
|
|
94
|
+
declare function resolveMongo(connection?: string): Promise<MongoSession>;
|
|
95
|
+
/**
|
|
96
|
+
* MongoDB 事务(需要副本集或分片集群)。回调内的 Mongo / MongoModel 操作自动加入事务;
|
|
97
|
+
* MongoDB 不支持嵌套事务,嵌套调用直接复用外层事务。
|
|
98
|
+
*/
|
|
99
|
+
declare function mongoTransaction<R>(callback: (session: ClientSession) => Promise<R>, connection?: string): Promise<R>;
|
|
100
|
+
/** Mongo 模型类上的静态配置 */
|
|
101
|
+
interface MongoModelSettings {
|
|
102
|
+
readonly name: string;
|
|
103
|
+
collection: string;
|
|
104
|
+
connection?: string;
|
|
105
|
+
softDelete: boolean | string;
|
|
106
|
+
timestamps: boolean | TimestampOptions;
|
|
107
|
+
}
|
|
108
|
+
/** 泛型约束只检查品牌属性(原因同 SQL 的 ModelLike) */
|
|
109
|
+
interface MongoModelLike {
|
|
110
|
+
readonly '~collection': any;
|
|
111
|
+
}
|
|
112
|
+
type MongoModelClass<M extends MongoModelLike = MongoModel<any>> = (new () => M) & MongoModelSettings;
|
|
113
|
+
/** 文档类型 */
|
|
114
|
+
type DocOf<M> = M extends {
|
|
115
|
+
readonly '~collection': infer D;
|
|
116
|
+
} ? D : never;
|
|
117
|
+
type MongoField<T> = (keyof T & string) | '_id';
|
|
118
|
+
type MongoWhereArgs<T> = [condition: MongoWhere<T>] | [field: MongoField<T>, value: unknown] | [field: MongoField<T>, operator: Operator, value: unknown];
|
|
119
|
+
/** MongoModel.define<Doc>(collection) 返回的基类:实例拥有文档的全部字段 */
|
|
120
|
+
type DefinedMongoModel<T extends Document> = Omit<typeof MongoModel, 'prototype'> & (new () => MongoModel<T> & WithId<T>);
|
|
121
|
+
interface MongoModelMeta {
|
|
122
|
+
softDelete: string | undefined;
|
|
123
|
+
createdAt: string | undefined;
|
|
124
|
+
updatedAt: string | undefined;
|
|
125
|
+
}
|
|
126
|
+
/** 解析软删除与时间戳字段(文档无固定结构,按配置决定) */
|
|
127
|
+
declare function metaOfMongo(model: MongoModelSettings): MongoModelMeta;
|
|
128
|
+
/**
|
|
129
|
+
* MongoDB 模型,API 与 SQL 的 Model 一致:
|
|
130
|
+
*
|
|
131
|
+
* ```ts
|
|
132
|
+
* interface UserDoc { name: string, email: string, status: number }
|
|
133
|
+
*
|
|
134
|
+
* export class User extends MongoModel.define<UserDoc>('users') {
|
|
135
|
+
* static override softDelete = true
|
|
136
|
+
* posts() {
|
|
137
|
+
* return this.hasMany(Post, 'userId')
|
|
138
|
+
* }
|
|
139
|
+
* }
|
|
140
|
+
*
|
|
141
|
+
* const user = await User.findOrFail('6650…') // 字符串 _id 自动转为 ObjectId
|
|
142
|
+
* await User.where('status', 1).with('posts').paginate(1, 20)
|
|
143
|
+
* ```
|
|
144
|
+
*/
|
|
145
|
+
declare class MongoModel<T extends Document = Document> extends ActiveRecord<WithId<T>> {
|
|
146
|
+
/** 仅用于类型推导 */
|
|
147
|
+
readonly '~collection': T;
|
|
148
|
+
static collection: string;
|
|
149
|
+
static connection: string | undefined;
|
|
150
|
+
/** 软删除:true 使用 deletedAt 字段,或指定字段名 */
|
|
151
|
+
static softDelete: boolean | string;
|
|
152
|
+
/** 自动维护 createdAt / updatedAt,可指定字段名或设为 false */
|
|
153
|
+
static timestamps: boolean | TimestampOptions;
|
|
154
|
+
constructor();
|
|
155
|
+
/** 声明模型对应的集合:`class User extends MongoModel.define<UserDoc>('users') {}` */
|
|
156
|
+
static define<T extends Document>(collection: string): DefinedMongoModel<T>;
|
|
157
|
+
static primaryKeyName(): string;
|
|
158
|
+
static query<M extends MongoModelLike>(this: MongoModelClass<M>): MongoModelQuery<M>;
|
|
159
|
+
static where<M extends MongoModelLike>(this: MongoModelClass<M>, ...args: MongoWhereArgs<DocOf<M>>): MongoModelQuery<M>;
|
|
160
|
+
static whereIn<M extends MongoModelLike>(this: MongoModelClass<M>, field: (keyof DocOf<M> & string) | '_id', values: readonly unknown[]): MongoModelQuery<M>;
|
|
161
|
+
static order<M extends MongoModelLike>(this: MongoModelClass<M>, field: (keyof DocOf<M> & string) | '_id', direction?: 'asc' | 'desc'): MongoModelQuery<M>;
|
|
162
|
+
static with<M extends MongoModelLike>(this: MongoModelClass<M>, ...relations: Array<RelationName<M> | `${RelationName<M>}.${string}`>): MongoModelQuery<M>;
|
|
163
|
+
static scope<M extends MongoModelLike>(this: MongoModelClass<M>, name: string, ...args: unknown[]): MongoModelQuery<M>;
|
|
164
|
+
static withTrashed<M extends MongoModelLike>(this: MongoModelClass<M>): MongoModelQuery<M>;
|
|
165
|
+
static onlyTrashed<M extends MongoModelLike>(this: MongoModelClass<M>): MongoModelQuery<M>;
|
|
166
|
+
static find<M extends MongoModelLike>(this: MongoModelClass<M>, id: unknown): Promise<M | undefined>;
|
|
167
|
+
static findOrFail<M extends MongoModelLike>(this: MongoModelClass<M>, id: unknown): Promise<M>;
|
|
168
|
+
static all<M extends MongoModelLike>(this: MongoModelClass<M>): Promise<M[]>;
|
|
169
|
+
static paginate<M extends MongoModelLike>(this: MongoModelClass<M>, page?: number, perPage?: number): Promise<Paginated<M>>;
|
|
170
|
+
static count<M extends MongoModelLike>(this: MongoModelClass<M>): Promise<number>;
|
|
171
|
+
static create<M extends MongoModelLike>(this: MongoModelClass<M>, data: Partial<DocOf<M>>): Promise<M>;
|
|
172
|
+
static destroy<M extends MongoModelLike>(this: MongoModelClass<M>, ids: unknown | unknown[]): Promise<number>;
|
|
173
|
+
save(): Promise<this>;
|
|
174
|
+
delete(): Promise<boolean>;
|
|
175
|
+
forceDelete(): Promise<boolean>;
|
|
176
|
+
restore(): Promise<this>;
|
|
177
|
+
trashed(): boolean;
|
|
178
|
+
refresh(): Promise<this>;
|
|
179
|
+
/** 文档主键(ObjectId) */
|
|
180
|
+
get id(): ObjectId | undefined;
|
|
181
|
+
protected $meta(): MongoModelMeta;
|
|
182
|
+
protected $query(): MongoQuery<Document>;
|
|
183
|
+
protected $whereKey(): MongoQuery<Document>;
|
|
184
|
+
}
|
|
185
|
+
/** 由文档构造模型(供 MongoModelQuery 使用) */
|
|
186
|
+
declare function hydrateMongoModel<M extends MongoModelLike>(model: MongoModelClass<M>, doc: Document): M;
|
|
187
|
+
type Field<T> = (keyof T & string) | '_id';
|
|
188
|
+
type MongoWhere<T> = { [K in Field<T>]?: unknown; } | ((group: MongoQuery<T>) => unknown);
|
|
189
|
+
interface Part {
|
|
190
|
+
bool: 'and' | 'or';
|
|
191
|
+
filter: Document;
|
|
192
|
+
}
|
|
193
|
+
interface MongoQueryOptions {
|
|
194
|
+
connection?: string;
|
|
195
|
+
}
|
|
196
|
+
/** 把字符串形式的 _id 转为 ObjectId(其它字段原样保留) */
|
|
197
|
+
declare function toObjectId(value: unknown): unknown;
|
|
198
|
+
/**
|
|
199
|
+
* MongoDB 查询构造器,方法与 SQL 的 Db.table() 一致:
|
|
200
|
+
*
|
|
201
|
+
* ```ts
|
|
202
|
+
* await Mongo.collection<UserDoc>('users').where('status', 1).order('createdAt', 'desc').paginate(1, 20)
|
|
203
|
+
* ```
|
|
204
|
+
*
|
|
205
|
+
* Mongo 特有能力:`aggregate(pipeline)`、`where({ tags: { $all: ['a'] } })` 直接使用查询运算符。
|
|
206
|
+
*/
|
|
207
|
+
declare class MongoQuery<T = Document, R = WithId<T>> {
|
|
208
|
+
readonly collectionName: string;
|
|
209
|
+
protected connectionName: string | undefined;
|
|
210
|
+
protected parts: Part[];
|
|
211
|
+
protected sorts: Array<[string, 1 | -1]>;
|
|
212
|
+
protected limitValue: number | undefined;
|
|
213
|
+
protected offsetValue: number | undefined;
|
|
214
|
+
protected fields: string[] | undefined;
|
|
215
|
+
constructor(collection: string, options?: MongoQueryOptions);
|
|
216
|
+
connection(name: string): this;
|
|
217
|
+
where(condition: MongoWhere<T>): this;
|
|
218
|
+
where(field: Field<T>, value: unknown): this;
|
|
219
|
+
where(field: Field<T>, operator: Operator, value: unknown): this;
|
|
220
|
+
orWhere(condition: MongoWhere<T>): this;
|
|
221
|
+
orWhere(field: Field<T>, value: unknown): this;
|
|
222
|
+
orWhere(field: Field<T>, operator: Operator, value: unknown): this;
|
|
223
|
+
whereIn(field: Field<T>, values: readonly unknown[]): this;
|
|
224
|
+
whereNotIn(field: Field<T>, values: readonly unknown[]): this;
|
|
225
|
+
/** 字段为 null 或不存在 */
|
|
226
|
+
whereNull(field: Field<T>): this;
|
|
227
|
+
whereNotNull(field: Field<T>): this;
|
|
228
|
+
whereBetween(field: Field<T>, range: [unknown, unknown]): this;
|
|
229
|
+
whereNotBetween(field: Field<T>, range: [unknown, unknown]): this;
|
|
230
|
+
/** SQL 风格的 LIKE 模式(% 与 _),区分大小写 */
|
|
231
|
+
whereLike(field: Field<T>, pattern: string): this;
|
|
232
|
+
whereNotLike(field: Field<T>, pattern: string): this;
|
|
233
|
+
when<V>(value: V, callback: (query: this, value: NonNullable<V>) => unknown): this;
|
|
234
|
+
/** 当前条件组成的过滤器 */
|
|
235
|
+
buildFilter(): Document;
|
|
236
|
+
get hasConditions(): boolean;
|
|
237
|
+
order(field: Field<T>, direction?: Direction): this;
|
|
238
|
+
order(fields: Partial<Record<Field<T>, Direction>>): this;
|
|
239
|
+
limit(value: number): this;
|
|
240
|
+
offset(value: number): this;
|
|
241
|
+
page(page: number, perPage?: number): this;
|
|
242
|
+
field(...fields: Array<Field<T>>): this;
|
|
243
|
+
select(): Promise<R[]>;
|
|
244
|
+
find(): Promise<R | undefined>;
|
|
245
|
+
findOrFail(): Promise<R>;
|
|
246
|
+
value(field: Field<T>): Promise<unknown>;
|
|
247
|
+
column(field: Field<T>): Promise<unknown[]>;
|
|
248
|
+
count(): Promise<number>;
|
|
249
|
+
sum(field: Field<T>): Promise<number>;
|
|
250
|
+
avg(field: Field<T>): Promise<number | null>;
|
|
251
|
+
max(field: Field<T>): Promise<unknown>;
|
|
252
|
+
min(field: Field<T>): Promise<unknown>;
|
|
253
|
+
exists(): Promise<boolean>;
|
|
254
|
+
paginate(page?: number, perPage?: number): Promise<Paginated<R>>;
|
|
255
|
+
chunk(size: number, callback: (docs: R[], page: number) => unknown): Promise<void>;
|
|
256
|
+
/** 聚合管道(自动在开头加上当前条件的 $match) */
|
|
257
|
+
aggregate<O extends Document = Document>(pipeline: Document[]): Promise<O[]>;
|
|
258
|
+
/** 插入一条或多条,返回带 _id 的文档 */
|
|
259
|
+
insert(docs: Partial<T> | Array<Partial<T>>): Promise<Array<WithId<T>>>;
|
|
260
|
+
insertGetId(doc: Partial<T>): Promise<ObjectId>;
|
|
261
|
+
/** 按条件更新(普通字段使用 $set,也可直接传 $inc / $push 等运算符),返回匹配数量 */
|
|
262
|
+
update(values: Partial<T> | Document, options?: {
|
|
263
|
+
all?: boolean;
|
|
264
|
+
}): Promise<number>;
|
|
265
|
+
delete(options?: {
|
|
266
|
+
all?: boolean;
|
|
267
|
+
}): Promise<number>;
|
|
268
|
+
increment(field: Field<T>, step?: number): Promise<number>;
|
|
269
|
+
decrement(field: Field<T>, step?: number): Promise<number>;
|
|
270
|
+
/** 生成的过滤器(调试用) */
|
|
271
|
+
toFilter(): Filter<Document>;
|
|
272
|
+
clone(): this;
|
|
273
|
+
protected scopedFilter(): Document;
|
|
274
|
+
protected transform(docs: Document[]): Promise<R[]>;
|
|
275
|
+
protected label(): string;
|
|
276
|
+
protected session(): Promise<MongoSession>;
|
|
277
|
+
protected pushCondition(bool: Part['bool'], filter: Document): this;
|
|
278
|
+
protected addCondition(bool: Part['bool'], args: unknown[]): this;
|
|
279
|
+
protected parseCondition(args: unknown[]): Document | undefined;
|
|
280
|
+
protected compare(field: string, operator: Operator, raw: unknown): Document;
|
|
281
|
+
protected normalize(field: string, value: unknown): unknown;
|
|
282
|
+
protected normalizeList(field: string, values: readonly unknown[]): unknown[];
|
|
283
|
+
protected write<V>(run: () => Promise<V>): Promise<V>;
|
|
284
|
+
protected writableFilter(action: string, options: {
|
|
285
|
+
all?: boolean;
|
|
286
|
+
}): Document;
|
|
287
|
+
protected group(accumulator: Document): Promise<unknown>;
|
|
288
|
+
}
|
|
289
|
+
type TrashedMode$1 = 'without' | 'with' | 'only';
|
|
290
|
+
/** Mongo 模型查询:结果为模型实例,应用软删除范围,支持预加载与作用域 */
|
|
291
|
+
declare class MongoModelQuery<M extends MongoModelLike> extends MongoQuery<DocOf<M>, M> {
|
|
292
|
+
readonly model: MongoModelClass<M>;
|
|
293
|
+
protected trashed: TrashedMode$1;
|
|
294
|
+
protected eager: string[];
|
|
295
|
+
constructor(model: MongoModelClass<M>);
|
|
296
|
+
withTrashed(): this;
|
|
297
|
+
onlyTrashed(): this;
|
|
298
|
+
with(...relations: Array<RelationName<M> | `${RelationName<M>}.${string}`>): this;
|
|
299
|
+
scope(name: string, ...args: unknown[]): this;
|
|
300
|
+
/** 按 _id 查询(字符串自动转为 ObjectId);不传时取第一条 */
|
|
301
|
+
find(id?: unknown): Promise<M | undefined>;
|
|
302
|
+
findOrFail(id?: unknown): Promise<M>;
|
|
303
|
+
/** 批量删除:启用软删除时只标记删除时间 */
|
|
304
|
+
delete(options?: {
|
|
305
|
+
all?: boolean;
|
|
306
|
+
}): Promise<number>;
|
|
307
|
+
forceDelete(options?: {
|
|
308
|
+
all?: boolean;
|
|
309
|
+
}): Promise<number>;
|
|
310
|
+
restore(options?: {
|
|
311
|
+
all?: boolean;
|
|
312
|
+
}): Promise<number>;
|
|
313
|
+
protected scopedFilter(): Document;
|
|
314
|
+
protected transform(docs: Document[]): Promise<M[]>;
|
|
315
|
+
protected label(): string;
|
|
316
|
+
clone(): this;
|
|
317
|
+
}
|
|
318
|
+
/**
|
|
319
|
+
* - `sqlite`:libsql 驱动(本地文件 `file:./data/app.db`、`:memory:`、Turso `libsql://…`)
|
|
320
|
+
* - `turso`:libsql 的纯 HTTP 客户端(Turso / sqld,`libsql://`、`https://`),不含原生二进制,可运行于 Edge 与 Serverless
|
|
321
|
+
* - `d1`:Cloudflare D1(通过 Workers 绑定访问,`binding` 为绑定名)
|
|
322
|
+
* - `postgres`:postgres-js
|
|
323
|
+
* - `pglite`:嵌入式 PostgreSQL(WASM),适合本地开发与测试,url 为数据目录,省略为内存库
|
|
324
|
+
* - `mysql`:mysql2
|
|
325
|
+
* - `mongodb`:官方 mongodb 驱动(使用 `@hazejs/orm/mongo` 的 Mongo / MongoModel)
|
|
326
|
+
*/
|
|
327
|
+
type Driver = 'sqlite' | 'turso' | 'd1' | 'postgres' | 'pglite' | 'mysql' | 'mongodb';
|
|
328
|
+
type Dialect = 'sqlite' | 'postgres' | 'mysql' | 'mongodb';
|
|
329
|
+
interface ConnectionConfig {
|
|
330
|
+
driver: Driver;
|
|
331
|
+
url?: string;
|
|
332
|
+
/** libsql / Turso 认证令牌 */
|
|
333
|
+
authToken?: string;
|
|
334
|
+
/** D1:Workers 绑定名(默认 `DB`),或直接传入 D1Database 对象 */
|
|
335
|
+
binding?: string | object;
|
|
336
|
+
/** 连接池大小(postgres / mysql / mongodb) */
|
|
337
|
+
pool?: number;
|
|
338
|
+
/** MongoDB 数据库名(默认取 url 中的路径) */
|
|
339
|
+
database?: string;
|
|
340
|
+
/** 以 debug 级别输出 SQL */
|
|
341
|
+
logging?: boolean;
|
|
342
|
+
/** drizzle 表定义目录(相对 srcDir),默认 `database/schema` */
|
|
343
|
+
schema?: string;
|
|
344
|
+
/** 迁移目录(相对 srcDir),默认连接为 `database/migrations`,其它连接为 `database/migrations/<name>` */
|
|
345
|
+
migrations?: string;
|
|
346
|
+
}
|
|
347
|
+
interface DatabaseConfig {
|
|
348
|
+
/** 默认连接名 */
|
|
349
|
+
default: string;
|
|
350
|
+
connections: Record<string, ConnectionConfig>;
|
|
351
|
+
}
|
|
352
|
+
/** `config/database.ts` 的默认导出 */
|
|
353
|
+
declare function defineDatabaseConfig(config: ConfigInput<DatabaseConfig>): ConfigInput<DatabaseConfig>;
|
|
354
|
+
declare function dialectOf(driver: Driver): Dialect;
|
|
355
|
+
interface Connection {
|
|
356
|
+
name: string;
|
|
357
|
+
driver: Driver;
|
|
358
|
+
dialect: Dialect;
|
|
359
|
+
/** SQL 为 drizzle 实例,MongoDB 为 mongodb 的 Db */
|
|
360
|
+
db: AnyDatabase;
|
|
361
|
+
/** 底层客户端(MongoDB 事务需要) */
|
|
362
|
+
client?: unknown;
|
|
363
|
+
close: () => Promise<void>;
|
|
364
|
+
}
|
|
365
|
+
interface DatabaseManagerOptions {
|
|
366
|
+
logger?: Logger;
|
|
367
|
+
/** 解析 sqlite 相对路径的基准目录,默认 process.cwd() */
|
|
368
|
+
rootDir?: string;
|
|
369
|
+
}
|
|
370
|
+
declare class DatabaseManager {
|
|
371
|
+
#private;
|
|
372
|
+
readonly config: DatabaseConfig;
|
|
373
|
+
constructor(config: DatabaseConfig, options?: DatabaseManagerOptions);
|
|
374
|
+
get defaultConnection(): string;
|
|
375
|
+
connectionConfig(name?: string): ConnectionConfig;
|
|
376
|
+
/** 获取连接(首次使用时建立) */
|
|
377
|
+
connection(name?: string): Promise<Connection>;
|
|
378
|
+
/** 关闭连接(默认全部);测试中可用于重建内存数据库 */
|
|
379
|
+
close(name?: string): Promise<void>;
|
|
380
|
+
}
|
|
381
|
+
/** 由 databaseProvider() 在应用启动时设置;脚本 / 测试中可直接调用 */
|
|
382
|
+
declare function setDatabaseManager(value: DatabaseManager | undefined): void;
|
|
383
|
+
declare function useDatabaseManager(): DatabaseManager;
|
|
384
|
+
interface Session {
|
|
385
|
+
name: string;
|
|
386
|
+
driver: Driver;
|
|
387
|
+
dialect: Dialect;
|
|
388
|
+
/** 当前可用的 drizzle 实例(处于事务中时为事务对象) */
|
|
389
|
+
db: AnyDatabase;
|
|
390
|
+
}
|
|
391
|
+
declare function resolveSession(connection?: string): Promise<Session>;
|
|
392
|
+
/**
|
|
393
|
+
* 在事务中执行;回调内通过 Db / Model 发起的查询自动加入该事务(隐式传播),
|
|
394
|
+
* 嵌套调用使用保存点。回调抛错时回滚。
|
|
395
|
+
*/
|
|
396
|
+
declare function transaction<R>(callback: (tx: AnyDatabase) => Promise<R>, connection?: string): Promise<R>;
|
|
397
|
+
interface QueryOptions {
|
|
398
|
+
/** 连接名,默认使用 config/database.ts 的 default */
|
|
399
|
+
connection?: string;
|
|
400
|
+
}
|
|
401
|
+
interface WriteOptions {
|
|
402
|
+
/** 允许无条件更新 / 删除整张表(默认拒绝,防止误操作) */
|
|
403
|
+
all?: boolean;
|
|
404
|
+
}
|
|
405
|
+
/**
|
|
406
|
+
* ThinkPHP 风格的查询构造器,底层使用 drizzle:
|
|
407
|
+
*
|
|
408
|
+
* ```ts
|
|
409
|
+
* await Db.table(users).where('status', 1).order('id', 'desc').paginate(1, 20)
|
|
410
|
+
* ```
|
|
411
|
+
*/
|
|
412
|
+
declare class QueryBuilder<T extends Table, R = Row$1<T>> extends Conditions<T> {
|
|
413
|
+
protected connectionName: string | undefined;
|
|
414
|
+
protected orders: SQL[];
|
|
415
|
+
protected limitValue: number | undefined;
|
|
416
|
+
protected offsetValue: number | undefined;
|
|
417
|
+
protected fields: string[] | undefined;
|
|
418
|
+
constructor(table: T, options?: QueryOptions);
|
|
419
|
+
/** 切换连接 */
|
|
420
|
+
connection(name: string): this;
|
|
421
|
+
/** `order('id', 'desc')`、`order({ status: 'asc', id: 'desc' })` 或 drizzle 表达式 */
|
|
422
|
+
order(column: ColumnKey<T>, direction?: Direction): this;
|
|
423
|
+
order(columns: Partial<Record<ColumnKey<T>, Direction>>): this;
|
|
424
|
+
order(expression: SQL): this;
|
|
425
|
+
limit(value: number): this;
|
|
426
|
+
offset(value: number): this;
|
|
427
|
+
/** 分页:page 从 1 开始 */
|
|
428
|
+
page(page: number, perPage?: number): this;
|
|
429
|
+
/** 只查询指定列 */
|
|
430
|
+
field<K extends ColumnKey<T>>(...keys: K[]): QueryBuilder<T, Pick<Row$1<T>, K>>;
|
|
431
|
+
/** 查询全部结果 */
|
|
432
|
+
select(): Promise<R[]>;
|
|
433
|
+
/** 查询第一条,不存在时为 undefined */
|
|
434
|
+
find(): Promise<R | undefined>;
|
|
435
|
+
findOrFail(): Promise<R>;
|
|
436
|
+
/** 某一列的值(第一条) */
|
|
437
|
+
value<K extends ColumnKey<T>>(column: K): Promise<Row$1<T>[K] | undefined>;
|
|
438
|
+
/** 某一列的全部值 */
|
|
439
|
+
column<K extends ColumnKey<T>>(column: K): Promise<Array<Row$1<T>[K]>>;
|
|
440
|
+
count(): Promise<number>;
|
|
441
|
+
sum(column: ColumnKey<T>): Promise<number>;
|
|
442
|
+
avg(column: ColumnKey<T>): Promise<number | null>;
|
|
443
|
+
max<K extends ColumnKey<T>>(column: K): Promise<Row$1<T>[K] | null>;
|
|
444
|
+
min<K extends ColumnKey<T>>(column: K): Promise<Row$1<T>[K] | null>;
|
|
445
|
+
exists(): Promise<boolean>;
|
|
446
|
+
paginate(page?: number, perPage?: number): Promise<Paginated<R>>;
|
|
447
|
+
/** 分批处理大量数据,回调返回 false 时停止 */
|
|
448
|
+
chunk(size: number, callback: (rows: R[], page: number) => unknown): Promise<void>;
|
|
449
|
+
/** 插入一条或多条,返回插入后的完整记录(MySQL 通过主键回查) */
|
|
450
|
+
insert(values: Insert<T> | Array<Insert<T>>): Promise<Array<Row$1<T>>>;
|
|
451
|
+
/** 插入一条并返回主键值 */
|
|
452
|
+
insertGetId(values: Insert<T>): Promise<unknown>;
|
|
453
|
+
/** 按当前条件更新,返回影响行数 */
|
|
454
|
+
update(values: Partial<Insert<T>> | Record<string, unknown>, options?: WriteOptions): Promise<number>;
|
|
455
|
+
/** 按当前条件删除,返回影响行数 */
|
|
456
|
+
delete(options?: WriteOptions): Promise<number>;
|
|
457
|
+
increment(column: ColumnKey<T>, step?: number): Promise<number>;
|
|
458
|
+
decrement(column: ColumnKey<T>, step?: number): Promise<number>;
|
|
459
|
+
/** 生成的 SQL 与参数(调试用) */
|
|
460
|
+
toSQL(): Promise<{
|
|
461
|
+
sql: string;
|
|
462
|
+
params: unknown[];
|
|
463
|
+
}>;
|
|
464
|
+
clone(): this;
|
|
465
|
+
/** 子类(ModelQuery)追加的全局条件,例如软删除 */
|
|
466
|
+
protected scopedWhere(): SQL | undefined;
|
|
467
|
+
/** 子类(ModelQuery)把行转换为模型 */
|
|
468
|
+
protected transform(rows: Array<Record<string, unknown>>): Promise<R[]>;
|
|
469
|
+
protected label(): string;
|
|
470
|
+
protected session(): Promise<Session>;
|
|
471
|
+
protected aggregate(expression: SQL): Promise<unknown>;
|
|
472
|
+
/** 写操作:把唯一约束等数据库错误转换为框架异常(409) */
|
|
473
|
+
protected write<V>(run: () => Promise<V>): Promise<V>;
|
|
474
|
+
protected writableWhere(action: string, options: WriteOptions): SQL | undefined;
|
|
475
|
+
}
|
|
476
|
+
type TrashedMode = 'without' | 'with' | 'only';
|
|
477
|
+
/** 模型查询:结果为模型实例,自动应用软删除范围,支持预加载关联与作用域 */
|
|
478
|
+
declare class ModelQuery<M extends ModelLike> extends QueryBuilder<TableOf<M> & Table, M> {
|
|
479
|
+
readonly model: ModelClass<M>;
|
|
480
|
+
protected trashed: TrashedMode;
|
|
481
|
+
protected eager: string[];
|
|
482
|
+
constructor(model: ModelClass<M>);
|
|
483
|
+
/** 包含已软删除的数据 */
|
|
484
|
+
withTrashed(): this;
|
|
485
|
+
/** 只查询已软删除的数据 */
|
|
486
|
+
onlyTrashed(): this;
|
|
487
|
+
/** 预加载关联:`with('posts', 'posts.comments', 'profile')` */
|
|
488
|
+
with(...relations: Array<RelationName<M> | `${RelationName<M>}.${string}`>): this;
|
|
489
|
+
/** 调用模型上的 `static scopeXxx(query, ...args)`:`scope('active')` */
|
|
490
|
+
scope(name: string, ...args: unknown[]): this;
|
|
491
|
+
/** 按主键查询;不传主键时取第一条 */
|
|
492
|
+
find(id?: unknown): Promise<M | undefined>;
|
|
493
|
+
findOrFail(id?: unknown): Promise<M>;
|
|
494
|
+
paginate(page?: number, perPage?: number): Promise<Paginated<M>>;
|
|
495
|
+
/** 批量删除:启用软删除时只标记删除时间 */
|
|
496
|
+
delete(options?: {
|
|
497
|
+
all?: boolean;
|
|
498
|
+
}): Promise<number>;
|
|
499
|
+
/** 物理删除(忽略软删除) */
|
|
500
|
+
forceDelete(options?: {
|
|
501
|
+
all?: boolean;
|
|
502
|
+
}): Promise<number>;
|
|
503
|
+
/** 恢复软删除的数据 */
|
|
504
|
+
restore(options?: {
|
|
505
|
+
all?: boolean;
|
|
506
|
+
}): Promise<number>;
|
|
507
|
+
protected scopedWhere(): SQL | undefined;
|
|
508
|
+
protected transform(rows: Array<Record<string, unknown>>): Promise<M[]>;
|
|
509
|
+
protected label(): string;
|
|
510
|
+
clone(): this;
|
|
511
|
+
protected primaryKey(): string;
|
|
512
|
+
}
|
|
513
|
+
/** 关联查询所需的最小接口(SQL 的 ModelQuery 与 Mongo 的 MongoModelQuery 都满足) */
|
|
514
|
+
interface RelationQuery<R> {
|
|
515
|
+
where: (field: never, value: never) => RelationQuery<R>;
|
|
516
|
+
whereIn: (field: never, values: never) => RelationQuery<R>;
|
|
517
|
+
with: (...relations: never[]) => RelationQuery<R>;
|
|
518
|
+
select: () => Promise<R[]>;
|
|
519
|
+
find: () => Promise<R | undefined>;
|
|
520
|
+
}
|
|
521
|
+
/**
|
|
522
|
+
* 记录类的查询类型:SQL 模型为 ModelQuery,Mongo 模型为 MongoModelQuery。
|
|
523
|
+
* 通过品牌属性判断而非结构比较,避免互相引用的模型类型无限展开。
|
|
524
|
+
*/
|
|
525
|
+
type QueryOf<R> = R extends {
|
|
526
|
+
readonly '~table': any;
|
|
527
|
+
} ? ModelQuery<R & {
|
|
528
|
+
readonly '~table': any;
|
|
529
|
+
}> : R extends {
|
|
530
|
+
readonly '~collection': any;
|
|
531
|
+
} ? MongoModelQuery<R & {
|
|
532
|
+
readonly '~collection': any;
|
|
533
|
+
}> : RelationQuery<R>;
|
|
534
|
+
/**
|
|
535
|
+
* 关联关系。可直接 await 获取结果,也可继续构造查询:
|
|
536
|
+
*
|
|
537
|
+
* ```ts
|
|
538
|
+
* const posts = await user.posts()
|
|
539
|
+
* const recent = await user.posts().query().order('id', 'desc').limit(5).select()
|
|
540
|
+
* ```
|
|
541
|
+
*/
|
|
542
|
+
declare abstract class Relation<R extends ActiveRecord, Result> implements PromiseLike<Result> {
|
|
543
|
+
readonly parent: ActiveRecord;
|
|
544
|
+
readonly related: RecordClass<R>;
|
|
545
|
+
constructor(parent: ActiveRecord, related: RecordClass<R>);
|
|
546
|
+
/** 受当前关联约束的查询(返回关联模型自己的查询类型) */
|
|
547
|
+
abstract query(): QueryOf<R>;
|
|
548
|
+
/** 获取关联结果 */
|
|
549
|
+
abstract get(): Promise<Result>;
|
|
550
|
+
/** 批量预加载到一组父记录上 */
|
|
551
|
+
abstract eagerLoad(parents: ActiveRecord[], name: string, nested: string[]): Promise<void>;
|
|
552
|
+
then<A = Result, B = never>(onFulfilled?: ((value: Result) => A | PromiseLike<A>) | null, onRejected?: ((reason: unknown) => B | PromiseLike<B>) | null): Promise<A | B>;
|
|
553
|
+
}
|
|
554
|
+
declare abstract class HasOneOrMany<R extends ActiveRecord, Result> extends Relation<R, Result> {
|
|
555
|
+
readonly foreignKey: string;
|
|
556
|
+
readonly localKey: string;
|
|
557
|
+
constructor(parent: ActiveRecord, related: RecordClass<R>, foreignKey: string, localKey: string);
|
|
558
|
+
query(): QueryOf<R>;
|
|
559
|
+
protected loadFor(parents: ActiveRecord[], nested: string[]): Promise<Map<unknown, R[]>>;
|
|
560
|
+
}
|
|
561
|
+
declare class HasMany<R extends ActiveRecord> extends HasOneOrMany<R, R[]> {
|
|
562
|
+
get(): Promise<R[]>;
|
|
563
|
+
eagerLoad(parents: ActiveRecord[], name: string, nested: string[]): Promise<void>;
|
|
564
|
+
}
|
|
565
|
+
declare class HasOne<R extends ActiveRecord> extends HasOneOrMany<R, R | null> {
|
|
566
|
+
get(): Promise<R | null>;
|
|
567
|
+
eagerLoad(parents: ActiveRecord[], name: string, nested: string[]): Promise<void>;
|
|
568
|
+
}
|
|
569
|
+
declare class BelongsTo<R extends ActiveRecord> extends Relation<R, R | null> {
|
|
570
|
+
readonly foreignKey: string;
|
|
571
|
+
readonly ownerKey: string;
|
|
572
|
+
constructor(parent: ActiveRecord, related: RecordClass<R>, foreignKey: string, ownerKey: string);
|
|
573
|
+
query(): QueryOf<R>;
|
|
574
|
+
get(): Promise<R | null>;
|
|
575
|
+
eagerLoad(parents: ActiveRecord[], name: string, nested: string[]): Promise<void>;
|
|
576
|
+
}
|
|
577
|
+
/** 记录的字段名(SQL 模型为表的列,Mongo 模型为文档字段) */
|
|
578
|
+
type FieldOf<R> = R extends {
|
|
579
|
+
readonly '~row': infer Row;
|
|
580
|
+
} ? keyof Row & string : string;
|
|
581
|
+
/** 记录上返回关联的方法名 */
|
|
582
|
+
type OwnKey<M> = Exclude<keyof M, keyof ActiveRecord | `~${string}`>;
|
|
583
|
+
type RelationName<M> = { [K in OwnKey<M>]: M[K] extends (() => Relation<any, any>) ? K : never; }[OwnKey<M>] & string;
|
|
584
|
+
type RelationResult<F> = F extends (() => Relation<any, infer Result>) ? Result : never;
|
|
585
|
+
/** 关联所需的类信息(构造器 + 查询入口) */
|
|
586
|
+
type RecordClass<R extends ActiveRecord = ActiveRecord> = (new () => R) & {
|
|
587
|
+
readonly name: string;
|
|
588
|
+
};
|
|
589
|
+
type Hook = 'onBeforeWrite' | 'onAfterWrite' | 'onBeforeInsert' | 'onAfterInsert' | 'onBeforeUpdate' | 'onAfterUpdate' | 'onBeforeDelete' | 'onAfterDelete' | 'onBeforeRestore' | 'onAfterRestore';
|
|
590
|
+
/**
|
|
591
|
+
* SQL 模型(Model)与 MongoDB 模型(MongoModel)共用的基类:
|
|
592
|
+
* 属性与脏检查、访问器 / 修改器、关联、序列化与事件。
|
|
593
|
+
*
|
|
594
|
+
* 内部状态使用 `$` 前缀的受保护字段,避免与真实字段名冲突。
|
|
595
|
+
*/
|
|
596
|
+
declare abstract class ActiveRecord<TRow extends object = any> {
|
|
597
|
+
/** 仅用于类型推导 */
|
|
598
|
+
readonly '~row': TRow;
|
|
599
|
+
/** 序列化时隐藏的字段 */
|
|
600
|
+
static hidden: readonly string[];
|
|
601
|
+
/** 序列化时追加的虚拟字段(需定义 getXxxAttr) */
|
|
602
|
+
static append: readonly string[];
|
|
603
|
+
protected $attributes: Record<string, unknown>;
|
|
604
|
+
protected $original: Record<string, unknown>;
|
|
605
|
+
protected $relations: Record<string, unknown>;
|
|
606
|
+
protected $exists: boolean;
|
|
607
|
+
/** 主键字段名(子类实现) */
|
|
608
|
+
static primaryKeyName(): string | undefined;
|
|
609
|
+
/** 由数据库行 / 文档构造已存在的记录 */
|
|
610
|
+
static hydrate<M extends ActiveRecord>(this: new () => M, row: Record<string, unknown>): M;
|
|
611
|
+
get exists(): boolean;
|
|
612
|
+
/** 主键值 */
|
|
613
|
+
getKey(): unknown;
|
|
614
|
+
/** 读取属性(经过 getXxxAttr 访问器) */
|
|
615
|
+
getAttr(key: string): unknown;
|
|
616
|
+
/** 写入属性(经过 setXxxAttr 修改器) */
|
|
617
|
+
setAttr(key: string, value: unknown): this;
|
|
618
|
+
/** 原始属性(不经过访问器) */
|
|
619
|
+
getRaw(key: string): unknown;
|
|
620
|
+
/** 批量赋值(SQL 模型忽略表中不存在的列) */
|
|
621
|
+
fill(data: Record<string, unknown>): this;
|
|
622
|
+
isDirty(key?: string): boolean;
|
|
623
|
+
/** 自上次同步以来修改过的字段 */
|
|
624
|
+
getDirty(): Record<string, unknown>;
|
|
625
|
+
getOriginal(key?: string): unknown;
|
|
626
|
+
/** 加载关联(可嵌套):`await user.load('posts.comments')` */
|
|
627
|
+
load(...relations: Array<RelationName<this> | `${RelationName<this>}.${string}`>): Promise<this>;
|
|
628
|
+
/** 已加载的关联结果 */
|
|
629
|
+
getRelation<K extends RelationName<this>>(name: K): RelationResult<this[K]> | undefined;
|
|
630
|
+
setRelation(name: string, value: unknown): this;
|
|
631
|
+
protected hasMany<R>(related: new () => R, foreignKey: FieldOf<R>, localKey?: keyof TRow & string): HasMany<R & ActiveRecord>;
|
|
632
|
+
protected hasOne<R>(related: new () => R, foreignKey: FieldOf<R>, localKey?: keyof TRow & string): HasOne<R & ActiveRecord>;
|
|
633
|
+
protected belongsTo<R>(related: new () => R, foreignKey: keyof TRow & string, ownerKey?: FieldOf<R>): BelongsTo<R & ActiveRecord>;
|
|
634
|
+
/** 序列化:应用访问器、隐藏字段、追加字段与已加载的关联 */
|
|
635
|
+
toJSON(): Record<string, unknown>;
|
|
636
|
+
/** 是否接受批量赋值的字段 */
|
|
637
|
+
protected acceptsAttribute(_key: string): boolean;
|
|
638
|
+
protected runHook(name: Hook): Promise<void>;
|
|
639
|
+
/** 写入成功后同步原始值 */
|
|
640
|
+
protected syncOriginal(): void;
|
|
641
|
+
}
|
|
642
|
+
/** 通过品牌属性读取模型的表类型(避免结构比较时展开关联类型导致循环) */
|
|
643
|
+
type TableOf<M> = M extends {
|
|
644
|
+
readonly '~table': infer T;
|
|
645
|
+
} ? T : never;
|
|
646
|
+
/**
|
|
647
|
+
* 泛型约束只检查品牌属性:用 `M extends Model` 会做结构比较,
|
|
648
|
+
* 在互相引用的模型之间展开关联类型导致循环
|
|
649
|
+
*/
|
|
650
|
+
interface ModelLike {
|
|
651
|
+
readonly '~table': any;
|
|
652
|
+
}
|
|
653
|
+
/** 模型类(构造器 + 静态配置) */
|
|
654
|
+
type ModelClass<M extends ModelLike = Model<any>> = (new () => M) & ModelSettings;
|
|
655
|
+
type WhereArgs<T extends Table> = [condition: WhereCondition<T>] | [column: ColumnKey<T>, value: unknown] | [column: ColumnKey<T>, operator: Operator, value: unknown];
|
|
656
|
+
/** Model.define(table) 返回的基类:实例拥有表的全部列属性 */
|
|
657
|
+
type DefinedModel<T extends Table> = Omit<typeof Model, 'prototype'> & (new () => Model<T> & Row$1<T>);
|
|
658
|
+
/**
|
|
659
|
+
* ThinkPHP 风格模型,表结构来自 drizzle:
|
|
660
|
+
*
|
|
661
|
+
* ```ts
|
|
662
|
+
* export class User extends Model.define(users) {
|
|
663
|
+
* static override softDelete = true
|
|
664
|
+
* static override hidden = ['password']
|
|
665
|
+
*
|
|
666
|
+
* posts() {
|
|
667
|
+
* return this.hasMany(Post, 'userId')
|
|
668
|
+
* }
|
|
669
|
+
*
|
|
670
|
+
* static scopeActive(query: ModelQuery<User>) {
|
|
671
|
+
* query.where('status', 1)
|
|
672
|
+
* }
|
|
673
|
+
* }
|
|
674
|
+
*
|
|
675
|
+
* const user = await User.findOrFail(1)
|
|
676
|
+
* user.name = 'Ada'
|
|
677
|
+
* await user.save()
|
|
678
|
+
* await User.where('status', 1).with('posts').order('id', 'desc').paginate(1, 20)
|
|
679
|
+
* ```
|
|
680
|
+
*
|
|
681
|
+
* 访问器 / 修改器:定义 `getNameAttr(value, data)` / `setNameAttr(value, data)`;
|
|
682
|
+
* 事件:定义 `onBeforeInsert()`、`onAfterUpdate()` 等方法。
|
|
683
|
+
*/
|
|
684
|
+
declare class Model<T extends Table = Table> extends ActiveRecord<Row$1<T>> {
|
|
685
|
+
#private;
|
|
686
|
+
/** 仅用于类型推导 */
|
|
687
|
+
readonly '~table': T;
|
|
688
|
+
static table: Table;
|
|
689
|
+
/** 使用的连接名,默认使用 config/database.ts 的 default */
|
|
690
|
+
static connection: string | undefined;
|
|
691
|
+
/** 软删除:true 使用 deletedAt 列,或指定列名 */
|
|
692
|
+
static softDelete: boolean | string;
|
|
693
|
+
/** 自动维护 createdAt / updatedAt(列存在时),可指定列名或设为 false */
|
|
694
|
+
static timestamps: boolean | TimestampOptions;
|
|
695
|
+
/** 声明模型对应的表:`class User extends Model.define(users) {}` */
|
|
696
|
+
static define<T extends Table>(table: T): DefinedModel<T>;
|
|
697
|
+
static primaryKeyName(): string | undefined;
|
|
698
|
+
static query<M extends ModelLike>(this: ModelClass<M>): ModelQuery<M>;
|
|
699
|
+
static where<M extends ModelLike>(this: ModelClass<M>, ...args: WhereArgs<TableOf<M> & Table>): ModelQuery<M>;
|
|
700
|
+
static whereIn<M extends ModelLike, K extends ColumnKey<TableOf<M> & Table>>(this: ModelClass<M>, column: K, values: ReadonlyArray<Row$1<TableOf<M> & Table>[K]>): ModelQuery<M>;
|
|
701
|
+
static order<M extends ModelLike>(this: ModelClass<M>, column: ColumnKey<TableOf<M> & Table>, direction?: 'asc' | 'desc'): ModelQuery<M>;
|
|
702
|
+
static with<M extends ModelLike>(this: ModelClass<M>, ...relations: Array<RelationName<M> | `${RelationName<M>}.${string}`>): ModelQuery<M>;
|
|
703
|
+
static scope<M extends ModelLike>(this: ModelClass<M>, name: string, ...args: unknown[]): ModelQuery<M>;
|
|
704
|
+
static withTrashed<M extends ModelLike>(this: ModelClass<M>): ModelQuery<M>;
|
|
705
|
+
static onlyTrashed<M extends ModelLike>(this: ModelClass<M>): ModelQuery<M>;
|
|
706
|
+
static find<M extends ModelLike>(this: ModelClass<M>, id: unknown): Promise<M | undefined>;
|
|
707
|
+
static findOrFail<M extends ModelLike>(this: ModelClass<M>, id: unknown): Promise<M>;
|
|
708
|
+
static all<M extends ModelLike>(this: ModelClass<M>): Promise<M[]>;
|
|
709
|
+
static paginate<M extends ModelLike>(this: ModelClass<M>, page?: number, perPage?: number): Promise<Paginated<M>>;
|
|
710
|
+
static count<M extends ModelLike>(this: ModelClass<M>): Promise<number>;
|
|
711
|
+
/** 创建并保存(会触发事件与时间戳) */
|
|
712
|
+
static create<M extends ModelLike>(this: ModelClass<M>, data: Partial<Insert<TableOf<M> & Table>>): Promise<M>;
|
|
713
|
+
/** 按主键删除(逐个触发事件与软删除),返回删除数量 */
|
|
714
|
+
static destroy<M extends ModelLike>(this: ModelClass<M>, ids: unknown | unknown[]): Promise<number>;
|
|
715
|
+
/** 新模型插入,已存在模型更新修改过的字段 */
|
|
716
|
+
save(): Promise<this>;
|
|
717
|
+
/** 删除:启用软删除时只标记删除时间 */
|
|
718
|
+
delete(): Promise<boolean>;
|
|
719
|
+
/** 物理删除 */
|
|
720
|
+
forceDelete(): Promise<boolean>;
|
|
721
|
+
/** 恢复软删除 */
|
|
722
|
+
restore(): Promise<this>;
|
|
723
|
+
trashed(): boolean;
|
|
724
|
+
/** 从数据库重新读取 */
|
|
725
|
+
refresh(): Promise<this>;
|
|
726
|
+
protected acceptsAttribute(key: string): boolean;
|
|
727
|
+
}
|
|
728
|
+
export { TimestampOptions as $, DatabaseConfig as A, DefinedMongoModel as B, setDatabaseManager as C, DatabaseManager as D, Connection as E, MongoModelQuery as F, MongoModelSettings as G, MongoModel as H, MongoQuery as I, MongoSession as J, hydrateMongoModel as K, MongoQueryOptions as L, Driver as M, defineDatabaseConfig as N, DatabaseManagerOptions as O, dialectOf as P, ModelSettings as Q, MongoWhere as R, resolveSession as S, useDatabaseManager as T, MongoModelClass as U, DocOf as V, MongoModelMeta as W, resolveMongo as X, mongoTransaction as Y, ModelMeta as Z, ModelQuery as _, TableOf as a, Direction as at, WriteOptions as b, RecordClass as c, Paginated as ct, BelongsTo as d, Conditions as et, HasMany as f, RelationQuery as g, Relation as h, ModelLike as i, ColumnKey as it, Dialect as j, ConnectionConfig as k, RelationName as l, Row$1 as lt, QueryOf as m, Model as n, WhereObject as nt, ActiveRecord as o, Insert as ot, HasOne as p, metaOfMongo as q, ModelClass as r, AnyDatabase as rt, FieldOf as s, Operator as st, DefinedModel as t, WhereCondition as tt, RelationResult as u, QueryBuilder as v, transaction as w, Session as x, QueryOptions as y, toObjectId as z };
|