@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,76 @@
1
+ import {
2
+ QueryParams,
3
+ BuildQueryResult,
4
+ CreateQueryParams,
5
+ SelectQueryParams,
6
+ InsertQueryParams,
7
+ UpdateQueryParams,
8
+ DeleteQueryParams,
9
+ AlterQueryParams,
10
+ DropTableQueryParams,
11
+ DropIndexQueryParams,
12
+ AddSchema,
13
+ ModifySchema,
14
+ DropSchema,
15
+ Condition,
16
+ isCreateQuery,
17
+ isSelectQuery,
18
+ isInsertQuery,
19
+ isUpdateQuery,
20
+ isDeleteQuery,
21
+ isAlterQuery,
22
+ isDropTableQuery,
23
+ isDropIndexQuery,
24
+ Column,
25
+ } from '../types.js';
26
+
27
+ // ============================================================================
28
+ // Database Dialect Interface
29
+ // ============================================================================
30
+
31
+
32
+ // ============================================================================
33
+ // SQL Builder Base Class
34
+ // ============================================================================
35
+
36
+ export abstract class Dialect<T,Q> {
37
+ public readonly name: string;
38
+ public readonly config: T;
39
+
40
+ protected constructor(name: string, config: T) {
41
+ this.name = name;
42
+ this.config = config;
43
+ }
44
+
45
+ // Abstract methods that must be implemented by concrete dialects
46
+ abstract isConnected(): boolean;
47
+ abstract connect(): Promise<void>;
48
+ abstract disconnect(): Promise<void>;
49
+ abstract healthCheck(): Promise<boolean>;
50
+ abstract query<U = any>(query: Q, params?: any[]): Promise<U>;
51
+ abstract mapColumnType(type: string): string;
52
+ abstract quoteIdentifier(identifier: string): string;
53
+ abstract getParameterPlaceholder(index: number): string;
54
+ abstract getStatementTerminator(): string;
55
+ abstract formatBoolean(value: boolean): string;
56
+ abstract formatDate(value: Date): string;
57
+ abstract formatJson(value: any): string;
58
+ abstract escapeString(value: string): string;
59
+ abstract formatDefaultValue(value: any): string;
60
+ abstract formatLimit(limit: number): string;
61
+ abstract formatOffset(offset: number): string;
62
+ abstract formatLimitOffset(limit: number, offset: number): string;
63
+ abstract formatCreateTable(tableName: string, columns: string[]): string;
64
+ abstract formatAlterTable(tableName: string, alterations: string[]): string;
65
+ abstract formatDropTable(tableName: string, ifExists?: boolean): string;
66
+ abstract formatDropIndex(indexName: string, tableName: string, ifExists?: boolean): string;
67
+ abstract dispose(): Promise<void>;
68
+ }
69
+ export namespace Dialect {
70
+ export type Creator<D,Q> = (config: D) => Dialect<D,Q>;
71
+ export type Constructor<D,Q> = new (config: D) => Dialect<D,Q>;
72
+ export type Factory<D,Q> = Creator<D,Q> | Constructor<D,Q>;
73
+ export function isConstructor<D,Q>(fn: Factory<D,Q>): fn is Constructor<D,Q> {
74
+ return fn.prototype && fn.prototype.constructor === fn;
75
+ }
76
+ }
@@ -0,0 +1,5 @@
1
+ export * from './dialect.js';
2
+ export * from './database.js';
3
+ export * from './model.js';
4
+ export * from './thenable.js';
5
+ export * from './query-classes.js';
@@ -0,0 +1,89 @@
1
+ import type { Database } from './database.js';
2
+ import type { Dialect } from './dialect.js';
3
+ import { AlterSchema, Condition } from '../types.js';
4
+ import * as QueryClasses from './query-classes.js';
5
+
6
+
7
+ /**
8
+ * 基础模型抽象类
9
+ * 定义所有模型类型的通用接口和行为
10
+ */
11
+ export abstract class Model<C=any,O extends object = object,Q = string> {
12
+ constructor(
13
+ public readonly database: Database<C, any, Q>,
14
+ public readonly name: string
15
+ ) {}
16
+
17
+ /**
18
+ * 获取数据库方言
19
+ */
20
+ get dialect(): Dialect<C,Q> {
21
+ return this.database.dialect;
22
+ }
23
+
24
+ /**
25
+ * 获取数据库是否已启动
26
+ */
27
+ get isStarted(): boolean {
28
+ return this.database.isStarted;
29
+ }
30
+
31
+ /**
32
+ * 获取模型名称
33
+ */
34
+ get modelName(): string {
35
+ return this.name;
36
+ }
37
+
38
+ alter(alterations: AlterSchema<O>): QueryClasses.Alteration<O, C, Q> {
39
+ return this.database.alter<O>(this.name, alterations);
40
+ }
41
+ select<K extends keyof O>(...fields: Array<K>): QueryClasses.Selection<Pick<O, K>, K, C, Q> {
42
+ return this.database.select<O, K>(this.name, fields);
43
+ }
44
+
45
+ insert(data: O): QueryClasses.Insertion<O, C, Q> {
46
+ return this.database.insert<O>(this.name, data);
47
+ }
48
+
49
+ update(update: Partial<O>): QueryClasses.Updation<O, C, Q> {
50
+ return this.database.update<O>(this.name, update);
51
+ }
52
+
53
+ delete(condition: Condition<O>): QueryClasses.Deletion<O, C, Q> {
54
+ return this.database.delete<O>(this.name, condition);
55
+ }
56
+ /**
57
+ * 验证查询条件
58
+ */
59
+ protected validateQuery(query: any): boolean {
60
+ return query !== null && query !== undefined;
61
+ }
62
+
63
+ /**
64
+ * 验证数据
65
+ */
66
+ protected validateData(data: any): boolean {
67
+ return data !== null && data !== undefined;
68
+ }
69
+
70
+ /**
71
+ * 处理错误
72
+ */
73
+ protected handleError(error: Error, operation: string): never {
74
+ const message = `Model ${this.name} ${operation} failed: ${error.message}`;
75
+ throw new Error(message);
76
+ }
77
+ }
78
+
79
+ /**
80
+ * 模型信息接口
81
+ */
82
+ export interface ModelInfo {
83
+ name: string;
84
+ databaseName: string;
85
+ dialectName: string;
86
+ isStarted: boolean;
87
+ modelCount: number;
88
+ }
89
+
@@ -0,0 +1,217 @@
1
+ import type { Database } from './database.js';
2
+ import type { Dialect } from './dialect.js';
3
+ import { ThenableQuery } from './thenable.js';
4
+ import { QueryParams, AlterSchema, Condition, Ordering, Schema } from '../types.js';
5
+
6
+ export class Alteration<T extends object, C = any, D = string> extends ThenableQuery<void, C, D> {
7
+ constructor(
8
+ database: Database<C, Record<string, object>, D>,
9
+ private readonly tableName: string,
10
+ private readonly alterations: AlterSchema<T>
11
+ ) {
12
+ super(database, database.dialect as Dialect<C, D>);
13
+ }
14
+
15
+ protected getQueryParams(): QueryParams<T> {
16
+ return {
17
+ type: 'alter',
18
+ tableName: this.tableName,
19
+ alterations: this.alterations
20
+ };
21
+ }
22
+ }
23
+
24
+ export class DroppingTable<T extends object = any, C = any, D = string> extends ThenableQuery<number, C, D> {
25
+ private conditions: Condition<T> = {};
26
+
27
+ constructor(
28
+ database: Database<C, Record<string, object>, any>,
29
+ private readonly tableName: string
30
+ ) {
31
+ super(database, database.dialect as Dialect<C, D>);
32
+ }
33
+
34
+ where(query: Condition<T>): this {
35
+ this.conditions = { ...this.conditions, ...query };
36
+ return this;
37
+ }
38
+
39
+ protected getQueryParams(): QueryParams<T> {
40
+ return {
41
+ type: 'drop_table',
42
+ tableName: this.tableName,
43
+ conditions: this.conditions
44
+ };
45
+ }
46
+ }
47
+
48
+ export class DroppingIndex<C = any, D = string> extends ThenableQuery<number, C, D> {
49
+ private conditions: Condition<any> = {};
50
+
51
+ constructor(
52
+ database: Database<C, Record<string, object>, D>,
53
+ private readonly indexName: string,
54
+ private readonly tableName: string
55
+ ) {
56
+ super(database, database.dialect as Dialect<C, D>);
57
+ }
58
+
59
+ where(query: Condition<any>): this {
60
+ this.conditions = { ...this.conditions, ...query };
61
+ return this;
62
+ }
63
+
64
+ protected getQueryParams(): QueryParams<any> {
65
+ return {
66
+ type: 'drop_index',
67
+ tableName: this.tableName,
68
+ indexName: this.indexName,
69
+ conditions: this.conditions
70
+ };
71
+ }
72
+ }
73
+
74
+ export class Creation<T extends object, C = any, D = string> extends ThenableQuery<void, C, D> {
75
+ constructor(
76
+ database: Database<C, Record<string, object>, D>,
77
+ private readonly tableName: string,
78
+ private readonly schema: Schema<T>
79
+ ) {
80
+ super(database, database.dialect as Dialect<C, D>);
81
+ }
82
+
83
+ protected getQueryParams(): QueryParams<T> {
84
+ return {
85
+ type: 'create',
86
+ tableName: this.tableName,
87
+ schema: this.schema
88
+ };
89
+ }
90
+ }
91
+
92
+ export class Selection<
93
+ T extends object,
94
+ K extends keyof T,
95
+ C = any,
96
+ D = string
97
+ > extends ThenableQuery<Pick<T, K>[], C, D> {
98
+ private conditions: Condition<T> = {};
99
+ private groupings: (keyof T)[] = [];
100
+ private orderings: Ordering<T>[] = [];
101
+ private limitCount?: number;
102
+ private offsetCount?: number;
103
+
104
+ constructor(
105
+ database: Database<C, Record<string, object>, D>,
106
+ private readonly modelName: string,
107
+ private readonly fields: Array<K>
108
+ ) {
109
+ super(database, database.dialect as Dialect<C, D>);
110
+ }
111
+
112
+ where(query: Condition<T>): this {
113
+ this.conditions = { ...this.conditions, ...query };
114
+ return this;
115
+ }
116
+
117
+ groupBy(...fields: (keyof T)[]): this {
118
+ this.groupings.push(...fields);
119
+ return this;
120
+ }
121
+
122
+ orderBy(field: keyof T, direction: "ASC" | "DESC" = "ASC"): this {
123
+ this.orderings.push({ field, direction });
124
+ return this;
125
+ }
126
+
127
+ limit(count: number): this {
128
+ this.limitCount = count;
129
+ return this;
130
+ }
131
+
132
+ offset(count: number): this {
133
+ this.offsetCount = count;
134
+ return this;
135
+ }
136
+
137
+ protected getQueryParams(): QueryParams<T> {
138
+ return {
139
+ type: 'select',
140
+ tableName: this.modelName,
141
+ fields: this.fields,
142
+ conditions: this.conditions,
143
+ groupings: this.groupings,
144
+ orderings: this.orderings,
145
+ limitCount: this.limitCount,
146
+ offsetCount: this.offsetCount
147
+ };
148
+ }
149
+ }
150
+
151
+ export class Insertion<T extends object, C = any, D = string> extends ThenableQuery<T, C, D> {
152
+ constructor(
153
+ database: Database<C, Record<string, object>, D>,
154
+ private readonly modelName: string,
155
+ private readonly data: T
156
+ ) {
157
+ super(database, database.dialect as Dialect<C, D>);
158
+ }
159
+
160
+ protected getQueryParams(): QueryParams<T> {
161
+ return {
162
+ type: 'insert',
163
+ tableName: this.modelName,
164
+ data: this.data
165
+ };
166
+ }
167
+ }
168
+
169
+ export class Updation<T extends object, C = any, D = string> extends ThenableQuery<number, C, D> {
170
+ private conditions: Condition<T> = {};
171
+
172
+ constructor(
173
+ database: Database<C, Record<string, object>, D>,
174
+ private readonly modelName: string,
175
+ private readonly update: Partial<T>
176
+ ) {
177
+ super(database, database.dialect as Dialect<C, D>);
178
+ }
179
+
180
+ where(query: Condition<T>): this {
181
+ this.conditions = { ...this.conditions, ...query };
182
+ return this;
183
+ }
184
+
185
+ protected getQueryParams(): QueryParams<T> {
186
+ return {
187
+ type: 'update',
188
+ tableName: this.modelName,
189
+ update: this.update,
190
+ conditions: this.conditions
191
+ };
192
+ }
193
+ }
194
+
195
+ export class Deletion<T extends object = any, C = any, D = string> extends ThenableQuery<number, C, D> {
196
+ private conditions: Condition<T> = {};
197
+
198
+ constructor(
199
+ database: Database<C, Record<string, object>, D>,
200
+ private readonly modelName: string
201
+ ) {
202
+ super(database, database.dialect as Dialect<C, D>);
203
+ }
204
+
205
+ where(query: Condition<T>): this {
206
+ this.conditions = { ...this.conditions, ...query };
207
+ return this;
208
+ }
209
+
210
+ protected getQueryParams(): QueryParams<T> {
211
+ return {
212
+ type: 'delete',
213
+ tableName: this.modelName,
214
+ conditions: this.conditions
215
+ };
216
+ }
217
+ }
@@ -0,0 +1,54 @@
1
+ import type { Database } from "./database.js";
2
+ import type { Dialect } from "./dialect.js";
3
+ import { QueryParams } from "../types.js";
4
+
5
+
6
+ export abstract class ThenableQuery<T = any,C=any,D=string>
7
+ implements PromiseLike<T>, AsyncIterable<T>
8
+ {
9
+ protected constructor(protected readonly database: Database<C,Record<string, object>,D>,protected readonly dialect: Dialect<C,D>) {}
10
+
11
+ // Abstract method to get query parameters
12
+ protected abstract getQueryParams(): QueryParams;
13
+ [Symbol.toStringTag] = 'ThenableQuery';
14
+ then<TResult1 = T, TResult2 = never>(
15
+ onfulfilled?:
16
+ | ((value: T) => TResult1 | PromiseLike<TResult1>)
17
+ | undefined
18
+ | null,
19
+ onrejected?:
20
+ | ((reason: any) => TResult2 | PromiseLike<TResult2>)
21
+ | undefined
22
+ | null
23
+ ): Promise<TResult1 | TResult2> {
24
+ const params = this.getQueryParams();
25
+ const { query, params: queryParams } = this.database.buildQuery(params);
26
+ return this.dialect.query<T>(query, queryParams).then(onfulfilled, onrejected);
27
+ }
28
+
29
+ catch<TResult = never>(
30
+ onrejected?:
31
+ | ((reason: any) => TResult | PromiseLike<TResult>)
32
+ | undefined
33
+ | null
34
+ ): Promise<any | TResult> {
35
+ const params = this.getQueryParams();
36
+ const { query, params: queryParams } = this.database.buildQuery(params);
37
+ return this.dialect.query(query, queryParams).catch(onrejected);
38
+ }
39
+
40
+ finally(onfinally?: (() => void) | undefined | null): Promise<any> {
41
+ const params = this.getQueryParams();
42
+ const { query, params: queryParams } = this.database.buildQuery(params);
43
+ return this.dialect.query(query, queryParams).finally(onfinally);
44
+ }
45
+
46
+ async *[Symbol.asyncIterator](): AsyncIterator<T, void, unknown> {
47
+ const params = this.getQueryParams();
48
+ const { query, params: queryParams } = this.database.buildQuery(params);
49
+ const rows = await this.dialect.query(query, queryParams);
50
+ for (const row of Array.isArray(rows) ? rows : [rows]) {
51
+ yield row;
52
+ }
53
+ }
54
+ }