@zhin.js/database 1.0.0

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.
Files changed (109) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +93 -0
  3. package/lib/base/database.d.ts +71 -0
  4. package/lib/base/database.d.ts.map +1 -0
  5. package/lib/base/database.js +101 -0
  6. package/lib/base/database.js.map +1 -0
  7. package/lib/base/dialect.d.ts +34 -0
  8. package/lib/base/dialect.d.ts.map +1 -0
  9. package/lib/base/dialect.js +21 -0
  10. package/lib/base/dialect.js.map +1 -0
  11. package/lib/base/index.d.ts +6 -0
  12. package/lib/base/index.d.ts.map +1 -0
  13. package/lib/base/index.js +6 -0
  14. package/lib/base/index.js.map +1 -0
  15. package/lib/base/model.d.ts +53 -0
  16. package/lib/base/model.d.ts.map +1 -0
  17. package/lib/base/model.js +65 -0
  18. package/lib/base/model.js.map +1 -0
  19. package/lib/base/query-classes.d.ts +68 -0
  20. package/lib/base/query-classes.d.ts.map +1 -0
  21. package/lib/base/query-classes.js +178 -0
  22. package/lib/base/query-classes.js.map +1 -0
  23. package/lib/base/thenable.d.ts +15 -0
  24. package/lib/base/thenable.d.ts.map +1 -0
  25. package/lib/base/thenable.js +33 -0
  26. package/lib/base/thenable.js.map +1 -0
  27. package/lib/dialects/memory.d.ts +52 -0
  28. package/lib/dialects/memory.d.ts.map +1 -0
  29. package/lib/dialects/memory.js +772 -0
  30. package/lib/dialects/memory.js.map +1 -0
  31. package/lib/dialects/mongodb.d.ts +85 -0
  32. package/lib/dialects/mongodb.d.ts.map +1 -0
  33. package/lib/dialects/mongodb.js +461 -0
  34. package/lib/dialects/mongodb.js.map +1 -0
  35. package/lib/dialects/mysql.d.ts +33 -0
  36. package/lib/dialects/mysql.d.ts.map +1 -0
  37. package/lib/dialects/mysql.js +132 -0
  38. package/lib/dialects/mysql.js.map +1 -0
  39. package/lib/dialects/pg.d.ts +33 -0
  40. package/lib/dialects/pg.d.ts.map +1 -0
  41. package/lib/dialects/pg.js +132 -0
  42. package/lib/dialects/pg.js.map +1 -0
  43. package/lib/dialects/redis.d.ts +87 -0
  44. package/lib/dialects/redis.d.ts.map +1 -0
  45. package/lib/dialects/redis.js +500 -0
  46. package/lib/dialects/redis.js.map +1 -0
  47. package/lib/dialects/sqlite.d.ts +46 -0
  48. package/lib/dialects/sqlite.d.ts.map +1 -0
  49. package/lib/dialects/sqlite.js +201 -0
  50. package/lib/dialects/sqlite.js.map +1 -0
  51. package/lib/index.d.ts +18 -0
  52. package/lib/index.d.ts.map +1 -0
  53. package/lib/index.js +18 -0
  54. package/lib/index.js.map +1 -0
  55. package/lib/registry.d.ts +37 -0
  56. package/lib/registry.d.ts.map +1 -0
  57. package/lib/registry.js +21 -0
  58. package/lib/registry.js.map +1 -0
  59. package/lib/type/document/database.d.ts +60 -0
  60. package/lib/type/document/database.d.ts.map +1 -0
  61. package/lib/type/document/database.js +242 -0
  62. package/lib/type/document/database.js.map +1 -0
  63. package/lib/type/document/model.d.ts +42 -0
  64. package/lib/type/document/model.d.ts.map +1 -0
  65. package/lib/type/document/model.js +65 -0
  66. package/lib/type/document/model.js.map +1 -0
  67. package/lib/type/keyvalue/database.d.ts +64 -0
  68. package/lib/type/keyvalue/database.d.ts.map +1 -0
  69. package/lib/type/keyvalue/database.js +214 -0
  70. package/lib/type/keyvalue/database.js.map +1 -0
  71. package/lib/type/keyvalue/model.d.ts +107 -0
  72. package/lib/type/keyvalue/model.d.ts.map +1 -0
  73. package/lib/type/keyvalue/model.js +261 -0
  74. package/lib/type/keyvalue/model.js.map +1 -0
  75. package/lib/type/related/database.d.ts +32 -0
  76. package/lib/type/related/database.d.ts.map +1 -0
  77. package/lib/type/related/database.js +334 -0
  78. package/lib/type/related/database.js.map +1 -0
  79. package/lib/type/related/model.d.ts +43 -0
  80. package/lib/type/related/model.d.ts.map +1 -0
  81. package/lib/type/related/model.js +108 -0
  82. package/lib/type/related/model.js.map +1 -0
  83. package/lib/types.d.ts +251 -0
  84. package/lib/types.d.ts.map +1 -0
  85. package/lib/types.js +28 -0
  86. package/lib/types.js.map +1 -0
  87. package/package.json +54 -0
  88. package/src/base/database.ts +128 -0
  89. package/src/base/dialect.ts +76 -0
  90. package/src/base/index.ts +5 -0
  91. package/src/base/model.ts +89 -0
  92. package/src/base/query-classes.ts +217 -0
  93. package/src/base/thenable.ts +54 -0
  94. package/src/dialects/memory.ts +880 -0
  95. package/src/dialects/mongodb.ts +533 -0
  96. package/src/dialects/mysql.ts +157 -0
  97. package/src/dialects/pg.ts +157 -0
  98. package/src/dialects/redis.ts +598 -0
  99. package/src/dialects/sqlite.ts +233 -0
  100. package/src/index.ts +20 -0
  101. package/src/registry.ts +59 -0
  102. package/src/type/document/database.ts +283 -0
  103. package/src/type/document/model.ts +86 -0
  104. package/src/type/keyvalue/database.ts +261 -0
  105. package/src/type/keyvalue/model.ts +339 -0
  106. package/src/type/related/database.ts +392 -0
  107. package/src/type/related/model.ts +117 -0
  108. package/src/types.ts +403 -0
  109. package/tsconfig.json +24 -0
@@ -0,0 +1,392 @@
1
+ import { Database,Dialect } from '../../base';
2
+ import { RelatedModel } from './model.js';
3
+ import {
4
+ QueryParams,
5
+ BuildQueryResult,
6
+ CreateQueryParams,
7
+ SelectQueryParams,
8
+ InsertQueryParams,
9
+ UpdateQueryParams,
10
+ DeleteQueryParams,
11
+ AlterQueryParams,
12
+ DropTableQueryParams,
13
+ DropIndexQueryParams,
14
+ Condition,
15
+ Column,
16
+ AddSchema,
17
+ ModifySchema,
18
+ DropSchema,
19
+ isCreateQuery,
20
+ isSelectQuery,
21
+ isInsertQuery,
22
+ isUpdateQuery,
23
+ isDeleteQuery,
24
+ isAlterQuery,
25
+ isDropTableQuery,
26
+ isDropIndexQuery,
27
+ } from '../../types.js';
28
+
29
+ /**
30
+ * 关系型数据库类
31
+ * 支持表、行、列的关系型数据模型
32
+ */
33
+ export class RelatedDatabase<
34
+ D=any,
35
+ S extends Record<string, object> = Record<string, object>
36
+ > extends Database<D,S,string> {
37
+
38
+ constructor(
39
+ dialect: Dialect<D,string>,
40
+ schemas?: Database.Schemas<S>,
41
+ ) {
42
+ super(dialect,schemas);
43
+ }
44
+
45
+ protected async initialize(): Promise<void> {
46
+ // 自动创建表
47
+ for (const [tableName, schema] of Object.entries(this.schemas || {})) {
48
+ await this.create(tableName, schema);
49
+ }
50
+ }
51
+
52
+ // SQL generation method
53
+ buildQuery<U extends object = any>(params: QueryParams<U>): BuildQueryResult<string> {
54
+ if (isCreateQuery(params)) {
55
+ return this.buildCreateQuery(params);
56
+ } else if (isSelectQuery(params)) {
57
+ return this.buildSelectQuery(params);
58
+ } else if (isInsertQuery(params)) {
59
+ return this.buildInsertQuery(params);
60
+ } else if (isUpdateQuery(params)) {
61
+ return this.buildUpdateQuery(params);
62
+ } else if (isDeleteQuery(params)) {
63
+ return this.buildDeleteQuery(params);
64
+ } else if (isAlterQuery(params)) {
65
+ return this.buildAlterQuery(params);
66
+ } else if (isDropTableQuery(params)) {
67
+ return this.buildDropTableQuery(params);
68
+ } else if (isDropIndexQuery(params)) {
69
+ return this.buildDropIndexQuery(params);
70
+ } else {
71
+ throw new Error(`Unsupported query type: ${(params as any).type}`);
72
+ }
73
+ }
74
+
75
+ // ========================================================================
76
+ // CREATE TABLE Query
77
+ // ========================================================================
78
+
79
+ protected buildCreateQuery<T extends object>(params: CreateQueryParams<T>): BuildQueryResult<string> {
80
+ const columnDefs = Object.entries(params.schema).map(([field, column]) => this.formatColumnDefinition(field,column as Column));
81
+ const query = this.dialect.formatCreateTable(params.tableName, columnDefs);
82
+ return { query, params: [] };
83
+ }
84
+
85
+ // ========================================================================
86
+ // SELECT Query
87
+ // ========================================================================
88
+
89
+ protected buildSelectQuery<T extends object>(params: SelectQueryParams<T>): BuildQueryResult<string> {
90
+ const fields = params.fields && params.fields.length
91
+ ? params.fields.map(f => this.dialect.quoteIdentifier(String(f))).join(', ')
92
+ : '*';
93
+
94
+ let query = `SELECT ${fields} FROM ${this.dialect.quoteIdentifier(params.tableName)}`;
95
+ const queryParams: any[] = [];
96
+
97
+ // WHERE clause
98
+ if (params.conditions) {
99
+ const [condition, conditionParams] = this.parseCondition(params.conditions);
100
+ if (condition) {
101
+ query += ` WHERE ${condition}`;
102
+ queryParams.push(...conditionParams);
103
+ }
104
+ }
105
+
106
+ // GROUP BY clause
107
+ if (params.groupings && params.groupings.length) {
108
+ const groupings = params.groupings.map(f => this.dialect.quoteIdentifier(String(f))).join(', ');
109
+ query += ` GROUP BY ${groupings}`;
110
+ }
111
+
112
+ // ORDER BY clause
113
+ if (params.orderings && params.orderings.length) {
114
+ const orderings = params.orderings
115
+ .map(o => `${this.dialect.quoteIdentifier(String(o.field))} ${o.direction}`)
116
+ .join(', ');
117
+ query += ` ORDER BY ${orderings}`;
118
+ }
119
+
120
+ // LIMIT and OFFSET
121
+ if (params.limitCount !== undefined && params.offsetCount !== undefined) {
122
+ query += ` ${this.dialect.formatLimitOffset(params.limitCount, params.offsetCount)}`;
123
+ } else if (params.limitCount !== undefined) {
124
+ query += ` ${this.dialect.formatLimit(params.limitCount)}`;
125
+ } else if (params.offsetCount !== undefined) {
126
+ query += ` ${this.dialect.formatOffset(params.offsetCount)}`;
127
+ }
128
+
129
+ return { query, params: queryParams };
130
+ }
131
+
132
+ // ========================================================================
133
+ // INSERT Query
134
+ // ========================================================================
135
+
136
+ protected buildInsertQuery<T extends object>(params: InsertQueryParams<T>): BuildQueryResult<string> {
137
+ const keys = Object.keys(params.data);
138
+ const columns = keys.map(k => this.dialect.quoteIdentifier(k)).join(', ');
139
+ const placeholders = keys.map((_, index) => this.dialect.getParameterPlaceholder(index)).join(', ');
140
+
141
+ const query = `INSERT INTO ${this.dialect.quoteIdentifier(params.tableName)} (${columns}) VALUES (${placeholders})`;
142
+ const values = Object.values(params.data).map(v => this.dialect.formatDefaultValue(v));
143
+
144
+ return { query, params: values };
145
+ }
146
+
147
+ // ========================================================================
148
+ // UPDATE Query
149
+ // ========================================================================
150
+
151
+ protected buildUpdateQuery<T extends object>(params: UpdateQueryParams<T>): BuildQueryResult<string> {
152
+ const updateKeys = Object.keys(params.update);
153
+ const setClause = updateKeys
154
+ .map((k, index) => `${this.dialect.quoteIdentifier(k)} = ${this.dialect.getParameterPlaceholder(index)}`)
155
+ .join(', ');
156
+
157
+ let query = `UPDATE ${this.dialect.quoteIdentifier(params.tableName)} SET ${setClause}`;
158
+ const queryParams: any[] = [...Object.values(params.update)];
159
+
160
+ // WHERE clause
161
+ if (params.conditions) {
162
+ const [condition, conditionParams] = this.parseCondition(params.conditions);
163
+ if (condition) {
164
+ query += ` WHERE ${condition}`;
165
+ queryParams.push(...conditionParams);
166
+ }
167
+ }
168
+
169
+ return { query, params: queryParams };
170
+ }
171
+
172
+ // ========================================================================
173
+ // DELETE Query
174
+ // ========================================================================
175
+
176
+ protected buildDeleteQuery<T extends object>(params: DeleteQueryParams<T>): BuildQueryResult<string> {
177
+ let query = `DELETE FROM ${this.dialect.quoteIdentifier(params.tableName)}`;
178
+ const queryParams: any[] = [];
179
+
180
+ // WHERE clause
181
+ if (params.conditions) {
182
+ const [condition, conditionParams] = this.parseCondition(params.conditions);
183
+ if (condition) {
184
+ query += ` WHERE ${condition}`;
185
+ queryParams.push(...conditionParams);
186
+ }
187
+ }
188
+
189
+ return { query, params: queryParams };
190
+ }
191
+
192
+ // ========================================================================
193
+ // ALTER TABLE Query
194
+ // ========================================================================
195
+
196
+ protected buildAlterQuery<T extends object>(params: AlterQueryParams<T>): BuildQueryResult<string> {
197
+ const alterations = Object.entries(params.alterations).map(([field,alteration]) => this.formatAlteration(field, alteration as AddSchema<T> | ModifySchema<T> | DropSchema));
198
+ const query = this.dialect.formatAlterTable(params.tableName, alterations);
199
+ return { query, params: [] };
200
+ }
201
+
202
+ // ========================================================================
203
+ // DROP TABLE Query
204
+ // ========================================================================
205
+
206
+ protected buildDropTableQuery<T extends object>(params: DropTableQueryParams<T>): BuildQueryResult<string> {
207
+ const query = this.dialect.formatDropTable(params.tableName, true);
208
+ return { query, params: [] };
209
+ }
210
+
211
+ // ========================================================================
212
+ // DROP INDEX Query
213
+ // ========================================================================
214
+
215
+ protected buildDropIndexQuery(params: DropIndexQueryParams): BuildQueryResult<string> {
216
+ const query = this.dialect.formatDropIndex(params.indexName, params.tableName, true);
217
+ return { query, params: [] };
218
+ }
219
+
220
+ // ========================================================================
221
+ // Helper Methods
222
+ // ========================================================================
223
+
224
+ protected formatColumnDefinition<T =any>(field: string, column: Column<T>): string {
225
+ const name = this.dialect.quoteIdentifier(String(field));
226
+ const type = this.dialect.mapColumnType(column.type);
227
+ const length = column.length ? `(${column.length})` : '';
228
+ const nullable = column.nullable === false ? ' NOT NULL' : '';
229
+ const primary = column.primary ? ' PRIMARY KEY' : '';
230
+ const unique = column.unique ? ' UNIQUE' : '';
231
+ const defaultVal = column.default !== undefined
232
+ ? ` DEFAULT ${this.dialect.formatDefaultValue(column.default)}`
233
+ : '';
234
+
235
+ return `${name} ${type}${length}${primary}${unique}${nullable}${defaultVal}`;
236
+ }
237
+
238
+ protected formatAlteration<T=any>(field:string,alteration: AddSchema<T> | ModifySchema<T> | DropSchema): string {
239
+ const name = this.dialect.quoteIdentifier(field);
240
+
241
+ switch (alteration.action) {
242
+ case 'add':
243
+ // 将 alteration 转换为 Column 格式
244
+ const addColumn: Column<T> = {
245
+ type: alteration.type,
246
+ nullable: alteration.nullable,
247
+ default: alteration.default,
248
+ primary: alteration.primary,
249
+ length: alteration.length
250
+ };
251
+ return `ADD COLUMN ${this.formatColumnDefinition(field, addColumn)}`;
252
+ case 'modify':
253
+ const type = alteration.type ? this.dialect.mapColumnType(alteration.type) : '';
254
+ const length = alteration.length ? `(${alteration.length})` : '';
255
+ const nullable = alteration.nullable !== undefined
256
+ ? (alteration.nullable ? ' NULL' : ' NOT NULL')
257
+ : '';
258
+ const defaultVal = alteration.default !== undefined
259
+ ? ` DEFAULT ${this.dialect.formatDefaultValue(alteration.default)}`
260
+ : '';
261
+ return `MODIFY COLUMN ${name} ${type}${length}${nullable}${defaultVal}`;
262
+ case 'drop':
263
+ return `DROP COLUMN ${name}`;
264
+ default:
265
+ throw new Error(`Unsupported alteration action`);
266
+ }
267
+ }
268
+
269
+ protected parseCondition<T extends object>(condition: Condition<T>): [string, any[]] {
270
+ const clauses: string[] = [];
271
+ const params: any[] = [];
272
+
273
+ for (const key in condition) {
274
+ if (key === '$and' && Array.isArray((condition as any).$and)) {
275
+ const subClauses: string[] = [];
276
+ for (const subCondition of (condition as any).$and) {
277
+ const [subClause, subParams] = this.parseCondition(subCondition);
278
+ if (subClause) {
279
+ subClauses.push(`(${subClause})`);
280
+ params.push(...subParams);
281
+ }
282
+ }
283
+ if (subClauses.length) {
284
+ clauses.push(subClauses.join(' AND '));
285
+ }
286
+ } else if (key === '$or' && Array.isArray((condition as any).$or)) {
287
+ const subClauses: string[] = [];
288
+ for (const subCondition of (condition as any).$or) {
289
+ const [subClause, subParams] = this.parseCondition(subCondition);
290
+ if (subClause) {
291
+ subClauses.push(`(${subClause})`);
292
+ params.push(...subParams);
293
+ }
294
+ }
295
+ if (subClauses.length) {
296
+ clauses.push(subClauses.join(' OR '));
297
+ }
298
+ } else if (key === '$not' && (condition as any).$not) {
299
+ const [subClause, subParams] = this.parseCondition((condition as any).$not);
300
+ if (subClause) {
301
+ clauses.push(`NOT (${subClause})`);
302
+ params.push(...subParams);
303
+ }
304
+ } else {
305
+ const value = (condition as any)[key];
306
+ if (value && typeof value === 'object' && !Array.isArray(value)) {
307
+ for (const op in value) {
308
+ const quotedKey = this.dialect.quoteIdentifier(key);
309
+ const placeholder = this.dialect.getParameterPlaceholder(params.length);
310
+
311
+ switch (op) {
312
+ case '$eq':
313
+ clauses.push(`${quotedKey} = ${placeholder}`);
314
+ params.push(value[op]);
315
+ break;
316
+ case '$ne':
317
+ clauses.push(`${quotedKey} <> ${placeholder}`);
318
+ params.push(value[op]);
319
+ break;
320
+ case '$gt':
321
+ clauses.push(`${quotedKey} > ${placeholder}`);
322
+ params.push(value[op]);
323
+ break;
324
+ case '$gte':
325
+ clauses.push(`${quotedKey} >= ${placeholder}`);
326
+ params.push(value[op]);
327
+ break;
328
+ case '$lt':
329
+ clauses.push(`${quotedKey} < ${placeholder}`);
330
+ params.push(value[op]);
331
+ break;
332
+ case '$lte':
333
+ clauses.push(`${quotedKey} <= ${placeholder}`);
334
+ params.push(value[op]);
335
+ break;
336
+ case '$in':
337
+ if (Array.isArray(value[op]) && value[op].length) {
338
+ const placeholders = value[op].map(() => this.dialect.getParameterPlaceholder(params.length + value[op].indexOf(value[op])));
339
+ clauses.push(`${quotedKey} IN (${placeholders.join(', ')})`);
340
+ params.push(...value[op]);
341
+ } else {
342
+ clauses.push('1=0'); // Empty IN clause should yield no results
343
+ }
344
+ break;
345
+ case '$nin':
346
+ if (Array.isArray(value[op]) && value[op].length) {
347
+ const placeholders = value[op].map(() => this.dialect.getParameterPlaceholder(params.length + value[op].indexOf(value[op])));
348
+ clauses.push(`${quotedKey} NOT IN (${placeholders.join(', ')})`);
349
+ params.push(...value[op]);
350
+ }
351
+ break;
352
+ case '$like':
353
+ clauses.push(`${quotedKey} LIKE ${placeholder}`);
354
+ params.push(value[op]);
355
+ break;
356
+ case '$nlike':
357
+ clauses.push(`${quotedKey} NOT LIKE ${placeholder}`);
358
+ params.push(value[op]);
359
+ break;
360
+ }
361
+ }
362
+ } else {
363
+ const quotedKey = this.dialect.quoteIdentifier(key);
364
+ const placeholder = this.dialect.getParameterPlaceholder(params.length);
365
+ clauses.push(`${quotedKey} = ${placeholder}`);
366
+ params.push(value);
367
+ }
368
+ }
369
+ }
370
+
371
+ return [clauses.join(' AND '), params];
372
+ }
373
+
374
+ /**
375
+ * 获取模型
376
+ */
377
+ model<T extends keyof S>(name: T): RelatedModel<S[T], Dialect<D,string>> {
378
+ let model = this.models.get(name as string);
379
+ if (!model) {
380
+ model = new RelatedModel(this as unknown as RelatedDatabase<D>, name as string);
381
+ this.models.set(name as string, model);
382
+ }
383
+ return model as unknown as RelatedModel<S[T], Dialect<D,string>>;
384
+ }
385
+
386
+ /**
387
+ * 获取所有模型名称
388
+ */
389
+ getModelNames(): string[] {
390
+ return Object.keys(this.schemas || {});
391
+ }
392
+ }
@@ -0,0 +1,117 @@
1
+ import { Model} from '../../base';
2
+ import { RelatedDatabase } from './database.js';
3
+ import { Condition } from '../../types.js';
4
+
5
+ /**
6
+ * 关系型模型类
7
+ * 继承自 BaseModel,提供关系型数据库特有的操作
8
+ */
9
+ export class RelatedModel<T extends object = object,D=any> extends Model<D,T,string> {
10
+ constructor(
11
+ database: RelatedDatabase<D>,
12
+ name: string
13
+ ) {
14
+ super(database, name);
15
+ }
16
+
17
+ /**
18
+ * 创建数据
19
+ */
20
+ async create(data: Partial<T>): Promise<T> {
21
+ if (!this.validateData(data)) {
22
+ throw new Error('Invalid data provided');
23
+ }
24
+ try {
25
+ const result = await (this.database as RelatedDatabase<D>).insert<T>(this.name, data as T);
26
+ return result as T;
27
+ } catch (error) {
28
+ this.handleError(error as Error, 'create');
29
+ }
30
+ }
31
+
32
+ /**
33
+ * 批量创建数据
34
+ */
35
+ async createMany(data: Partial<T>[]): Promise<T[]> {
36
+ if (!Array.isArray(data) || data.length === 0) {
37
+ throw new Error('Invalid data array provided');
38
+ }
39
+
40
+ try {
41
+ const results = [];
42
+ for (const item of data) {
43
+ const result = await this.create(item);
44
+ results.push(result);
45
+ }
46
+ return results;
47
+ } catch (error) {
48
+ this.handleError(error as Error, 'createMany');
49
+ }
50
+ }
51
+ /**
52
+ * 查找单个数据
53
+ */
54
+ async selectOne(query?: Condition<T>): Promise<T | null> {
55
+ try {
56
+ const selection = this.select();
57
+ if (query) {
58
+ selection.where(query);
59
+ }
60
+ const results = await selection.limit(1);
61
+ return results.length > 0 ? results[0] : null;
62
+ } catch (error) {
63
+ this.handleError(error as Error, 'selectOne');
64
+ }
65
+ }
66
+
67
+ /**
68
+ * 根据ID查找
69
+ */
70
+ async selectById(id: any): Promise<T | null> {
71
+ return this.selectOne({ id } as Condition<T>);
72
+ }
73
+
74
+ /**
75
+ * 更新单个数据
76
+ */
77
+ async updateOne(query: Condition<T>, data: Partial<T>): Promise<boolean> {
78
+ try {
79
+ const result = await this.update(data).where(query);
80
+ return result > 0;
81
+ } catch (error) {
82
+ this.handleError(error as Error, 'updateOne');
83
+ }
84
+ }
85
+
86
+ /**
87
+ * 根据ID更新
88
+ */
89
+ async updateById(id: any, data: Partial<T>): Promise<boolean> {
90
+ return this.updateOne({ id } as Condition<T>, data);
91
+ }
92
+
93
+
94
+ /**
95
+ * 根据ID删除
96
+ */
97
+ async deleteById(id: any): Promise<boolean> {
98
+ const result=await this.delete({ id } as Condition<T>);
99
+ return result>0
100
+ }
101
+
102
+ /**
103
+ * 统计数量
104
+ */
105
+ async count(query?: Condition<T>): Promise<number> {
106
+ try {
107
+ const selection = this.select('*' as keyof T);
108
+ if (query) {
109
+ selection.where(query);
110
+ }
111
+ const results = await selection;
112
+ return results.length;
113
+ } catch (error) {
114
+ this.handleError(error as Error, 'count');
115
+ }
116
+ }
117
+ }