stabilize-orm 1.3.8 → 2.1.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.
- package/README.md +1097 -546
- package/dist/auto-migrate.d.ts +34 -0
- package/dist/auto-migrate.d.ts.map +1 -0
- package/dist/auto-migrate.js +3003 -0
- package/dist/auto-migrate.js.map +163 -0
- package/dist/cache.d.ts +90 -0
- package/dist/cache.d.ts.map +1 -0
- package/dist/cache.js +166 -0
- package/dist/cache.js.map +64 -0
- package/dist/client.d.ts +73 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +2997 -0
- package/dist/client.js.map +162 -0
- package/dist/hooks.d.ts +31 -0
- package/dist/hooks.d.ts.map +1 -0
- package/dist/hooks.js +4 -0
- package/dist/hooks.js.map +11 -0
- package/dist/index.d.ts +101 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3183 -0
- package/dist/index.js.map +222 -0
- package/dist/logger.d.ts +40 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +8 -0
- package/dist/logger.js.map +11 -0
- package/dist/migrations.d.ts +31 -0
- package/dist/migrations.d.ts.map +1 -0
- package/dist/migrations.js +3009 -0
- package/dist/migrations.js.map +164 -0
- package/{model.ts → dist/model.d.ts} +124 -189
- package/dist/model.d.ts.map +1 -0
- package/dist/model.js +4 -0
- package/dist/model.js.map +10 -0
- package/dist/query-builder.d.ts +91 -0
- package/dist/query-builder.d.ts.map +1 -0
- package/dist/query-builder.js +14 -0
- package/dist/query-builder.js.map +12 -0
- package/dist/repository.d.ts +165 -0
- package/dist/repository.d.ts.map +1 -0
- package/dist/repository.js +176 -0
- package/dist/repository.js.map +69 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/dist/types.d.ts +110 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +4 -0
- package/dist/types.js.map +10 -0
- package/dist/utils/encryption.d.ts +13 -0
- package/dist/utils/encryption.d.ts.map +1 -0
- package/dist/utils/encryption.js +4 -0
- package/dist/utils/encryption.js.map +10 -0
- package/package.json +104 -25
- package/.eslintrc.json +0 -10
- package/.github/ISSUE_TEMPLATE/PULL_REQUEST_TEMPLATE.md +0 -23
- package/.github/ISSUE_TEMPLATE/bug_report.md +0 -25
- package/.github/ISSUE_TEMPLATE/feature_request.md +0 -17
- package/.github/workflows/ci-cd.yml +0 -22
- package/CHANGELOG.md +0 -75
- package/CODE_OF_CONDUCT.md +0 -87
- package/CONTRIBUTING.md +0 -48
- package/FUNDING.md +0 -14
- package/SECURITY.md +0 -35
- package/SUPPORT.md +0 -18
- package/bun.lock +0 -667
- package/cache.ts +0 -181
- package/client.ts +0 -249
- package/docker-compose.yml +0 -22
- package/hooks.ts +0 -76
- package/index.ts +0 -158
- package/logger.ts +0 -127
- package/migrations.ts +0 -318
- package/query-builder.ts +0 -209
- package/repository.ts +0 -1096
- package/tests/migrations.test.ts +0 -141
- package/tsconfig.json +0 -32
- package/types.ts +0 -106
|
@@ -1,189 +1,124 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @file model.ts
|
|
3
|
-
* @description Provides a programmatic API for defining models and a metadata storage system.
|
|
4
|
-
* @author ElectronSz
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import type
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
*
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
*
|
|
69
|
-
* @
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
*
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
*
|
|
87
|
-
* @
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
*
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
/**
|
|
126
|
-
* Finds the soft delete field, if any, for a given model class.
|
|
127
|
-
* @param model - The class constructor for the model.
|
|
128
|
-
* @returns The key of the soft delete field, or null if not found.
|
|
129
|
-
*/
|
|
130
|
-
static getSoftDeleteField(model: Function): string | null {
|
|
131
|
-
const columns = this.getModelMetadata(model)?.columns || {};
|
|
132
|
-
for (const [key, col] of Object.entries(columns)) {
|
|
133
|
-
if (col.softDelete) return key;
|
|
134
|
-
}
|
|
135
|
-
return null;
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
/**
|
|
139
|
-
* Checks if the model is versioned.
|
|
140
|
-
* @param model - The class constructor for the model.
|
|
141
|
-
* @returns True if versioned, false otherwise.
|
|
142
|
-
*/
|
|
143
|
-
static isVersioned(model: Function): boolean {
|
|
144
|
-
return !!this.getModelMetadata(model)?.versioned;
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
/**
|
|
148
|
-
* Gets custom query scopes for a given model class.
|
|
149
|
-
* @param model - The class constructor for the model.
|
|
150
|
-
* @returns Record of scope names to scope functions.
|
|
151
|
-
*/
|
|
152
|
-
static getScopes(model: Function): Record<string, (qb: QueryBuilder<any>, ...args: any[]) => QueryBuilder<any>> {
|
|
153
|
-
return this.getModelMetadata(model)?.scopes || {};
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
static getTimestamps(model: Function): TimestampsConfig {
|
|
157
|
-
return this.getModelMetadata(model)?.timestamps || {};
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
/**
|
|
162
|
-
* Programmatically defines a model and stores its metadata.
|
|
163
|
-
* @param config - The model configuration object.
|
|
164
|
-
* @returns The dynamically created model class.
|
|
165
|
-
*/
|
|
166
|
-
export function defineModel(config: ModelConfig) {
|
|
167
|
-
class Model {
|
|
168
|
-
/**
|
|
169
|
-
* Constructs a model instance from plain data.
|
|
170
|
-
* @param data - The plain object to assign properties from.
|
|
171
|
-
*/
|
|
172
|
-
constructor(data: any) {
|
|
173
|
-
Object.assign(this, data);
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
// Store metadata
|
|
178
|
-
MetadataStorage.setModelMetadata(Model, {
|
|
179
|
-
tableName: config.tableName,
|
|
180
|
-
versioned: config.versioned || false,
|
|
181
|
-
softDelete: config.softDelete || false,
|
|
182
|
-
columns: config.columns,
|
|
183
|
-
relations: config.relations || [],
|
|
184
|
-
scopes: config.scopes || {},
|
|
185
|
-
timestamps: config.timestamps || {},
|
|
186
|
-
});
|
|
187
|
-
|
|
188
|
-
return Model;
|
|
189
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* @file model.ts
|
|
3
|
+
* @description Provides a programmatic API for defining models and a metadata storage system.
|
|
4
|
+
* @author ElectronSz
|
|
5
|
+
*/
|
|
6
|
+
import type { QueryBuilder } from "./query-builder";
|
|
7
|
+
import { DataTypes, RelationType, type DefaultExpression } from "./types";
|
|
8
|
+
export interface ColumnConfig {
|
|
9
|
+
name?: string;
|
|
10
|
+
type: DataTypes;
|
|
11
|
+
length?: number;
|
|
12
|
+
precision?: number;
|
|
13
|
+
scale?: number;
|
|
14
|
+
required?: boolean;
|
|
15
|
+
unique?: boolean;
|
|
16
|
+
defaultValue?: any;
|
|
17
|
+
defaultExpression?: DefaultExpression;
|
|
18
|
+
index?: string;
|
|
19
|
+
softDelete?: boolean;
|
|
20
|
+
minLength?: number;
|
|
21
|
+
maxLength?: number;
|
|
22
|
+
pattern?: RegExp;
|
|
23
|
+
customValidator?: (val: any) => boolean | string;
|
|
24
|
+
encrypted?: boolean;
|
|
25
|
+
optimisticLock?: boolean;
|
|
26
|
+
}
|
|
27
|
+
export interface RelationConfig {
|
|
28
|
+
type: RelationType;
|
|
29
|
+
target: () => any;
|
|
30
|
+
property: string;
|
|
31
|
+
foreignKey?: string;
|
|
32
|
+
inverseKey?: string;
|
|
33
|
+
joinTable?: string;
|
|
34
|
+
}
|
|
35
|
+
export interface TimestampsConfig {
|
|
36
|
+
createdAt?: string;
|
|
37
|
+
updatedAt?: string;
|
|
38
|
+
}
|
|
39
|
+
export interface ModelConfig {
|
|
40
|
+
tableName: string;
|
|
41
|
+
versioned?: boolean;
|
|
42
|
+
softDelete?: boolean;
|
|
43
|
+
columns: Record<string, ColumnConfig>;
|
|
44
|
+
relations?: RelationConfig[];
|
|
45
|
+
scopes?: Record<string, (qb: QueryBuilder<any>, ...args: any[]) => QueryBuilder<any>>;
|
|
46
|
+
timestamps?: TimestampsConfig;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Metadata storage for models.
|
|
50
|
+
* Stores and retrieves model configuration such as columns, relations, scopes, etc.
|
|
51
|
+
*/
|
|
52
|
+
export declare class MetadataStorage {
|
|
53
|
+
private static models;
|
|
54
|
+
/**
|
|
55
|
+
* Associates model metadata with a class constructor.
|
|
56
|
+
* @param model - The class constructor for the model.
|
|
57
|
+
* @param config - The model configuration object.
|
|
58
|
+
*/
|
|
59
|
+
static setModelMetadata(model: Function, config: ModelConfig): void;
|
|
60
|
+
/**
|
|
61
|
+
* Retrieves the model configuration for a given model class.
|
|
62
|
+
* @param model - The class constructor for the model.
|
|
63
|
+
* @returns The model configuration or undefined if not found.
|
|
64
|
+
*/
|
|
65
|
+
static getModelMetadata(model: Function): ModelConfig | undefined;
|
|
66
|
+
/**
|
|
67
|
+
* Gets the table name for a given model class.
|
|
68
|
+
* @param model - The class constructor for the model.
|
|
69
|
+
* @returns The table name or an empty string if not found.
|
|
70
|
+
*/
|
|
71
|
+
static getTableName(model: Function): string;
|
|
72
|
+
/**
|
|
73
|
+
* Gets the column configuration for a given model class.
|
|
74
|
+
* @param model - The class constructor for the model.
|
|
75
|
+
* @returns Record of column names to their configuration.
|
|
76
|
+
*/
|
|
77
|
+
static getColumns(model: Function): Record<string, ColumnConfig>;
|
|
78
|
+
/**
|
|
79
|
+
* Collects validation rules for each column of a given model.
|
|
80
|
+
* @param model - The class constructor for the model.
|
|
81
|
+
* @returns An object mapping column names to an array of validation rule names.
|
|
82
|
+
*/
|
|
83
|
+
static getValidators(model: Function): Record<string, string[]>;
|
|
84
|
+
/**
|
|
85
|
+
* Gets the relationship configuration for a given model class.
|
|
86
|
+
* @param model - The class constructor for the model.
|
|
87
|
+
* @returns Record of property names to their relation configuration.
|
|
88
|
+
*/
|
|
89
|
+
static getRelations(model: Function): Record<string, RelationConfig>;
|
|
90
|
+
/**
|
|
91
|
+
* Finds the soft delete field, if any, for a given model class.
|
|
92
|
+
* @param model - The class constructor for the model.
|
|
93
|
+
* @returns The key of the soft delete field, or null if not found.
|
|
94
|
+
*/
|
|
95
|
+
static getSoftDeleteField(model: Function): string | null;
|
|
96
|
+
/**
|
|
97
|
+
* Checks if the model is versioned.
|
|
98
|
+
* @param model - The class constructor for the model.
|
|
99
|
+
* @returns True if versioned, false otherwise.
|
|
100
|
+
*/
|
|
101
|
+
static isVersioned(model: Function): boolean;
|
|
102
|
+
/**
|
|
103
|
+
* Gets custom query scopes for a given model class.
|
|
104
|
+
* @param model - The class constructor for the model.
|
|
105
|
+
* @returns Record of scope names to scope functions.
|
|
106
|
+
*/
|
|
107
|
+
static getScopes(model: Function): Record<string, (qb: QueryBuilder<any>, ...args: any[]) => QueryBuilder<any>>;
|
|
108
|
+
/**
|
|
109
|
+
* Finds the model constructor by table name.
|
|
110
|
+
* @param tableName - The table name to search for.
|
|
111
|
+
* @returns The model constructor or undefined if not found.
|
|
112
|
+
*/
|
|
113
|
+
static getModelByTableName(tableName: string): Function | undefined;
|
|
114
|
+
static getTimestamps(model: Function): TimestampsConfig;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Programmatically defines a model and stores its metadata.
|
|
118
|
+
* @param config - The model configuration object.
|
|
119
|
+
* @returns The dynamically created model class.
|
|
120
|
+
*/
|
|
121
|
+
export declare function defineModel(config: ModelConfig): {
|
|
122
|
+
new (data: any): {};
|
|
123
|
+
};
|
|
124
|
+
//# sourceMappingURL=model.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../model.ts"],"names":[],"mappings":"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"}
|
package/dist/model.js
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
var F=Object.create;var{getPrototypeOf:G,defineProperty:D,getOwnPropertyNames:H}=Object;var I=Object.prototype.hasOwnProperty;var J=(q,w,x)=>{x=q!=null?F(G(q)):{};let z=w||!q||!q.__esModule?D(x,"default",{value:q,enumerable:!0}):x;for(let A of H(q))if(!I.call(z,A))D(z,A,{get:()=>q[A],enumerable:!0});return z};var K=(q,w)=>()=>(w||q((w={exports:{}}).exports,w),w.exports);var L=import.meta.require;class E{static models=new Map;static setModelMetadata(q,w){this.models.set(q,w)}static getModelMetadata(q){return this.models.get(q)}static getTableName(q){return this.getModelMetadata(q)?.tableName||""}static getColumns(q){return this.getModelMetadata(q)?.columns||{}}static getValidators(q){let w=this.getModelMetadata(q)?.columns||{},x={};for(let[z,A]of Object.entries(w)){let B=[];if(A.required)B.push("required");if(A.unique)B.push("unique");x[z]=B}return x}static getRelations(q){let w=this.getModelMetadata(q)?.relations||[],x={};for(let z of w)x[z.property]=z;return x}static getSoftDeleteField(q){let w=this.getModelMetadata(q)?.columns||{};for(let[x,z]of Object.entries(w))if(z.softDelete)return x;return null}static isVersioned(q){return!!this.getModelMetadata(q)?.versioned}static getScopes(q){return this.getModelMetadata(q)?.scopes||{}}static getModelByTableName(q){for(let[w,x]of this.models)if(x.tableName===q)return w;return}static getTimestamps(q){return this.getModelMetadata(q)?.timestamps||{}}}function P(q){class w{constructor(x){Object.assign(this,x)}}return E.setModelMetadata(w,{tableName:q.tableName,versioned:q.versioned||!1,softDelete:q.softDelete||!1,columns:q.columns,relations:q.relations||[],scopes:q.scopes||{},timestamps:q.timestamps||{}}),w}export{P as defineModel,E as MetadataStorage};
|
|
3
|
+
|
|
4
|
+
//# debugId=37F418164C2C1B3A64756E2164756E21
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["..\\model.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"/**\n * @file model.ts\n * @description Provides a programmatic API for defining models and a metadata storage system.\n * @author ElectronSz\n */\n\nimport type { QueryBuilder } from \"./query-builder\";\nimport { DataTypes, RelationType, type DefaultExpression } from \"./types\";\n\n// Interface for column configuration\nexport interface ColumnConfig {\n name?: string;\n type: DataTypes;\n length?: number;\n precision?: number;\n scale?: number;\n required?: boolean;\n unique?: boolean;\n defaultValue?: any;\n defaultExpression?: DefaultExpression;\n index?: string;\n softDelete?: boolean;\n minLength?: number;\n maxLength?: number;\n pattern?: RegExp;\n customValidator?: (val: any) => boolean | string;\n encrypted?: boolean;\n optimisticLock?: boolean;\n}\n\n// Interface for relationship configuration\nexport interface RelationConfig {\n type: RelationType;\n target: () => any; // Reference to another model\n property: string; // Property name in the model\n foreignKey?: string;\n inverseKey?: string;\n joinTable?: string;\n}\n\nexport interface TimestampsConfig {\n createdAt?: string;\n updatedAt?: string;\n}\n\n// Interface for model configuration\nexport interface ModelConfig {\n tableName: string;\n versioned?: boolean;\n softDelete?: boolean;\n columns: Record<string, ColumnConfig>;\n relations?: RelationConfig[];\n scopes?: Record<\n string,\n (qb: QueryBuilder<any>, ...args: any[]) => QueryBuilder<any>\n >; // Custom query scopes\n timestamps?: TimestampsConfig; // Auto-managed timestamp columns\n}\n\n/**\n * Metadata storage for models.\n * Stores and retrieves model configuration such as columns, relations, scopes, etc.\n */\nexport class MetadataStorage {\n private static models: Map<Function, ModelConfig> = new Map();\n\n /**\n * Associates model metadata with a class constructor.\n * @param model - The class constructor for the model.\n * @param config - The model configuration object.\n */\n static setModelMetadata(model: Function, config: ModelConfig) {\n this.models.set(model, config);\n }\n\n /**\n * Retrieves the model configuration for a given model class.\n * @param model - The class constructor for the model.\n * @returns The model configuration or undefined if not found.\n */\n static getModelMetadata(model: Function): ModelConfig | undefined {\n return this.models.get(model);\n }\n\n /**\n * Gets the table name for a given model class.\n * @param model - The class constructor for the model.\n * @returns The table name or an empty string if not found.\n */\n static getTableName(model: Function): string {\n return this.getModelMetadata(model)?.tableName || \"\";\n }\n\n /**\n * Gets the column configuration for a given model class.\n * @param model - The class constructor for the model.\n * @returns Record of column names to their configuration.\n */\n static getColumns(model: Function): Record<string, ColumnConfig> {\n return this.getModelMetadata(model)?.columns || {};\n }\n\n /**\n * Collects validation rules for each column of a given model.\n * @param model - The class constructor for the model.\n * @returns An object mapping column names to an array of validation rule names.\n */\n static getValidators(model: Function): Record<string, string[]> {\n const columns = this.getModelMetadata(model)?.columns || {};\n const validators: Record<string, string[]> = {};\n for (const [key, col] of Object.entries(columns)) {\n const rules: string[] = [];\n if (col.required) rules.push(\"required\");\n if (col.unique) rules.push(\"unique\");\n validators[key] = rules;\n }\n return validators;\n }\n\n /**\n * Gets the relationship configuration for a given model class.\n * @param model - The class constructor for the model.\n * @returns Record of property names to their relation configuration.\n */\n static getRelations(model: Function): Record<string, RelationConfig> {\n const relations = this.getModelMetadata(model)?.relations || [];\n const result: Record<string, RelationConfig> = {};\n for (const rel of relations) {\n result[rel.property] = rel;\n }\n return result;\n }\n\n /**\n * Finds the soft delete field, if any, for a given model class.\n * @param model - The class constructor for the model.\n * @returns The key of the soft delete field, or null if not found.\n */\n static getSoftDeleteField(model: Function): string | null {\n const columns = this.getModelMetadata(model)?.columns || {};\n for (const [key, col] of Object.entries(columns)) {\n if (col.softDelete) return key;\n }\n return null;\n }\n\n /**\n * Checks if the model is versioned.\n * @param model - The class constructor for the model.\n * @returns True if versioned, false otherwise.\n */\n static isVersioned(model: Function): boolean {\n return !!this.getModelMetadata(model)?.versioned;\n }\n\n /**\n * Gets custom query scopes for a given model class.\n * @param model - The class constructor for the model.\n * @returns Record of scope names to scope functions.\n */\n static getScopes(\n model: Function,\n ): Record<\n string,\n (qb: QueryBuilder<any>, ...args: any[]) => QueryBuilder<any>\n > {\n return this.getModelMetadata(model)?.scopes || {};\n }\n\n /**\n * Finds the model constructor by table name.\n * @param tableName - The table name to search for.\n * @returns The model constructor or undefined if not found.\n */\n static getModelByTableName(tableName: string): Function | undefined {\n for (const [model, config] of this.models) {\n if (config.tableName === tableName) {\n return model;\n }\n }\n return undefined;\n }\n\n static getTimestamps(model: Function): TimestampsConfig {\n return this.getModelMetadata(model)?.timestamps || {};\n }\n}\n\n/**\n * Programmatically defines a model and stores its metadata.\n * @param config - The model configuration object.\n * @returns The dynamically created model class.\n */\nexport function defineModel(config: ModelConfig) {\n class Model {\n /**\n * Constructs a model instance from plain data.\n * @param data - The plain object to assign properties from.\n */\n constructor(data: any) {\n Object.assign(this, data);\n }\n }\n\n // Store metadata\n MetadataStorage.setModelMetadata(Model, {\n tableName: config.tableName,\n versioned: config.versioned || false,\n softDelete: config.softDelete || false,\n columns: config.columns,\n relations: config.relations || [],\n scopes: config.scopes || {},\n timestamps: config.timestamps || {},\n });\n\n return Model;\n}\n"
|
|
6
|
+
],
|
|
7
|
+
"mappings": ";+YA+DO,MAAM,CAAgB,OACZ,QAAqC,IAAI,UAOjD,iBAAgB,CAAC,EAAiB,EAAqB,CAC5D,KAAK,OAAO,IAAI,EAAO,CAAM,QAQxB,iBAAgB,CAAC,EAA0C,CAChE,OAAO,KAAK,OAAO,IAAI,CAAK,QAQvB,aAAY,CAAC,EAAyB,CAC3C,OAAO,KAAK,iBAAiB,CAAK,GAAG,WAAa,SAQ7C,WAAU,CAAC,EAA+C,CAC/D,OAAO,KAAK,iBAAiB,CAAK,GAAG,SAAW,CAAC,QAQ5C,cAAa,CAAC,EAA2C,CAC9D,IAAM,EAAU,KAAK,iBAAiB,CAAK,GAAG,SAAW,CAAC,EACpD,EAAuC,CAAC,EAC9C,QAAY,EAAK,KAAQ,OAAO,QAAQ,CAAO,EAAG,CAChD,IAAM,EAAkB,CAAC,EACzB,GAAI,EAAI,SAAU,EAAM,KAAK,UAAU,EACvC,GAAI,EAAI,OAAQ,EAAM,KAAK,QAAQ,EACnC,EAAW,GAAO,EAEpB,OAAO,QAQF,aAAY,CAAC,EAAiD,CACnE,IAAM,EAAY,KAAK,iBAAiB,CAAK,GAAG,WAAa,CAAC,EACxD,EAAyC,CAAC,EAChD,QAAW,KAAO,EAChB,EAAO,EAAI,UAAY,EAEzB,OAAO,QAQF,mBAAkB,CAAC,EAAgC,CACxD,IAAM,EAAU,KAAK,iBAAiB,CAAK,GAAG,SAAW,CAAC,EAC1D,QAAY,EAAK,KAAQ,OAAO,QAAQ,CAAO,EAC7C,GAAI,EAAI,WAAY,OAAO,EAE7B,OAAO,WAQF,YAAW,CAAC,EAA0B,CAC3C,MAAO,CAAC,CAAC,KAAK,iBAAiB,CAAK,GAAG,gBAQlC,UAAS,CACd,EAIA,CACA,OAAO,KAAK,iBAAiB,CAAK,GAAG,QAAU,CAAC,QAQ3C,oBAAmB,CAAC,EAAyC,CAClE,QAAY,EAAO,KAAW,KAAK,OACjC,GAAI,EAAO,YAAc,EACvB,OAAO,EAGX,aAGK,cAAa,CAAC,EAAmC,CACtD,OAAO,KAAK,iBAAiB,CAAK,GAAG,YAAc,CAAC,EAExD,CAOO,SAAS,CAAW,CAAC,EAAqB,CAC/C,MAAM,CAAM,CAKV,WAAW,CAAC,EAAW,CACrB,OAAO,OAAO,KAAM,CAAI,EAE5B,CAaA,OAVA,EAAgB,iBAAiB,EAAO,CACtC,UAAW,EAAO,UAClB,UAAW,EAAO,WAAa,GAC/B,WAAY,EAAO,YAAc,GACjC,QAAS,EAAO,QAChB,UAAW,EAAO,WAAa,CAAC,EAChC,OAAQ,EAAO,QAAU,CAAC,EAC1B,WAAY,EAAO,YAAc,CAAC,CACpC,CAAC,EAEM",
|
|
8
|
+
"debugId": "37F418164C2C1B3A64756E2164756E21",
|
|
9
|
+
"names": []
|
|
10
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file query-builder.ts
|
|
3
|
+
* @description A feature-rich SQL query builder inspired by Knex.js, TypeORM, Prisma, and Drizzle.
|
|
4
|
+
* @author ElectronSz
|
|
5
|
+
*/
|
|
6
|
+
import { DBClient } from "./client";
|
|
7
|
+
import { Cache } from "./cache";
|
|
8
|
+
type LockMode = "FOR UPDATE" | "FOR SHARE" | "FOR NO KEY UPDATE" | "FOR KEY SHARE";
|
|
9
|
+
export declare class QueryBuilder<T> {
|
|
10
|
+
private table;
|
|
11
|
+
private tableAlias;
|
|
12
|
+
private selectFields;
|
|
13
|
+
private isDistinct;
|
|
14
|
+
private joins;
|
|
15
|
+
private whereConditions;
|
|
16
|
+
private whereParams;
|
|
17
|
+
private orderByClauses;
|
|
18
|
+
private limitValue;
|
|
19
|
+
private offsetValue;
|
|
20
|
+
private groupByClauses;
|
|
21
|
+
private havingConditions;
|
|
22
|
+
private havingParams;
|
|
23
|
+
private lockMode;
|
|
24
|
+
private eagerRelations;
|
|
25
|
+
private unions;
|
|
26
|
+
private ctas;
|
|
27
|
+
constructor(table: string);
|
|
28
|
+
select(...fields: string[]): QueryBuilder<T>;
|
|
29
|
+
selectRaw(expression: string, ...params: any[]): QueryBuilder<T>;
|
|
30
|
+
distinct(): QueryBuilder<T>;
|
|
31
|
+
as(alias: string): QueryBuilder<T>;
|
|
32
|
+
count(column?: string, alias?: string): QueryBuilder<T>;
|
|
33
|
+
sum(column: string, alias?: string): QueryBuilder<T>;
|
|
34
|
+
avg(column: string, alias?: string): QueryBuilder<T>;
|
|
35
|
+
min(column: string, alias?: string): QueryBuilder<T>;
|
|
36
|
+
max(column: string, alias?: string): QueryBuilder<T>;
|
|
37
|
+
where(condition: string, ...params: any[]): QueryBuilder<T>;
|
|
38
|
+
orWhere(condition: string, ...params: any[]): QueryBuilder<T>;
|
|
39
|
+
whereNot(condition: string, ...params: any[]): QueryBuilder<T>;
|
|
40
|
+
whereIn(column: string, values: any[]): QueryBuilder<T>;
|
|
41
|
+
whereNotIn(column: string, values: any[]): QueryBuilder<T>;
|
|
42
|
+
whereNull(column: string): QueryBuilder<T>;
|
|
43
|
+
whereNotNull(column: string): QueryBuilder<T>;
|
|
44
|
+
whereBetween(column: string, start: any, end: any): QueryBuilder<T>;
|
|
45
|
+
whereNotBetween(column: string, start: any, end: any): QueryBuilder<T>;
|
|
46
|
+
whereLike(column: string, pattern: string): QueryBuilder<T>;
|
|
47
|
+
whereILike(column: string, pattern: string): QueryBuilder<T>;
|
|
48
|
+
whereExists(builderOrSql: string | QueryBuilder<any>): QueryBuilder<T>;
|
|
49
|
+
whereNotExists(builderOrSql: string | QueryBuilder<any>): QueryBuilder<T>;
|
|
50
|
+
whereRaw(rawSql: string, ...params: any[]): QueryBuilder<T>;
|
|
51
|
+
/** Knex-style column-to-column comparison: .whereRef('orders.user_id', '=', 'users.id') */
|
|
52
|
+
whereRef(leftCol: string, op: string, rightCol: string): QueryBuilder<T>;
|
|
53
|
+
private addJoin;
|
|
54
|
+
join(table: string, condition: string): QueryBuilder<T>;
|
|
55
|
+
innerJoin(table: string, condition: string): QueryBuilder<T>;
|
|
56
|
+
leftJoin(table: string, condition: string): QueryBuilder<T>;
|
|
57
|
+
rightJoin(table: string, condition: string): QueryBuilder<T>;
|
|
58
|
+
fullJoin(table: string, condition: string): QueryBuilder<T>;
|
|
59
|
+
crossJoin(table: string): QueryBuilder<T>;
|
|
60
|
+
orderBy(column: string, direction?: "ASC" | "DESC"): QueryBuilder<T>;
|
|
61
|
+
groupBy(...columns: string[]): QueryBuilder<T>;
|
|
62
|
+
having(condition: string, ...params: any[]): QueryBuilder<T>;
|
|
63
|
+
limit(limit: number): QueryBuilder<T>;
|
|
64
|
+
offset(offset: number): QueryBuilder<T>;
|
|
65
|
+
take(count: number): QueryBuilder<T>;
|
|
66
|
+
skip(count: number): QueryBuilder<T>;
|
|
67
|
+
first(): QueryBuilder<T>;
|
|
68
|
+
paginate(page: number, pageSize: number): QueryBuilder<T>;
|
|
69
|
+
lock(mode?: LockMode): QueryBuilder<T>;
|
|
70
|
+
forUpdate(): QueryBuilder<T>;
|
|
71
|
+
forShare(): QueryBuilder<T>;
|
|
72
|
+
union(builder: QueryBuilder<any>): QueryBuilder<T>;
|
|
73
|
+
unionAll(builder: QueryBuilder<any>): QueryBuilder<T>;
|
|
74
|
+
with(name: string, builder: QueryBuilder<any>): QueryBuilder<T>;
|
|
75
|
+
withRecursive(name: string, builder: QueryBuilder<any>): QueryBuilder<T>;
|
|
76
|
+
scope(name: string, ...args: any[]): QueryBuilder<T>;
|
|
77
|
+
clone(): QueryBuilder<T>;
|
|
78
|
+
build(): {
|
|
79
|
+
query: string;
|
|
80
|
+
params: any[];
|
|
81
|
+
};
|
|
82
|
+
toSQL(): {
|
|
83
|
+
query: string;
|
|
84
|
+
params: any[];
|
|
85
|
+
};
|
|
86
|
+
execute(client: DBClient, cache?: Cache, cacheKey?: string): Promise<T[]>;
|
|
87
|
+
countExec(client: DBClient): Promise<number>;
|
|
88
|
+
existsExec(client: DBClient): Promise<boolean>;
|
|
89
|
+
}
|
|
90
|
+
export {};
|
|
91
|
+
//# sourceMappingURL=query-builder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"query-builder.d.ts","sourceRoot":"","sources":["../query-builder.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AACpC,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAKhC,KAAK,QAAQ,GACT,YAAY,GACZ,WAAW,GACX,mBAAmB,GACnB,eAAe,CAAC;AAEpB,qBAAa,YAAY,CAAC,CAAC;IACzB,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,UAAU,CAAuB;IACzC,OAAO,CAAC,YAAY,CAAmB;IACvC,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,KAAK,CAAgB;IAC7B,OAAO,CAAC,eAAe,CAAgB;IACvC,OAAO,CAAC,WAAW,CAAa;IAChC,OAAO,CAAC,cAAc,CAAgB;IACtC,OAAO,CAAC,UAAU,CAAuB;IACzC,OAAO,CAAC,WAAW,CAAuB;IAC1C,OAAO,CAAC,cAAc,CAAgB;IACtC,OAAO,CAAC,gBAAgB,CAAgB;IACxC,OAAO,CAAC,YAAY,CAAa;IACjC,OAAO,CAAC,QAAQ,CAAyB;IACzC,OAAO,CAAC,cAAc,CAAgB;IACtC,OAAO,CAAC,MAAM,CAAwD;IACtE,OAAO,CAAC,IAAI,CAKH;gBAEG,KAAK,EAAE,MAAM;IAMzB,MAAM,CAAC,GAAG,MAAM,EAAE,MAAM,EAAE,GAAG,YAAY,CAAC,CAAC,CAAC;IAK5C,SAAS,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,GAAG,EAAE,GAAG,YAAY,CAAC,CAAC,CAAC;IAMhE,QAAQ,IAAI,YAAY,CAAC,CAAC,CAAC;IAK3B,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,YAAY,CAAC,CAAC,CAAC;IAOlC,KAAK,CAAC,MAAM,GAAE,MAAY,EAAE,KAAK,GAAE,MAAgB,GAAG,YAAY,CAAC,CAAC,CAAC;IAKrE,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,GAAE,MAAc,GAAG,YAAY,CAAC,CAAC,CAAC;IAK3D,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,GAAE,MAAc,GAAG,YAAY,CAAC,CAAC,CAAC;IAK3D,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,GAAE,MAAc,GAAG,YAAY,CAAC,CAAC,CAAC;IAK3D,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,GAAE,MAAc,GAAG,YAAY,CAAC,CAAC,CAAC;IAO3D,KAAK,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,GAAG,EAAE,GAAG,YAAY,CAAC,CAAC,CAAC;IAU3D,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,GAAG,EAAE,GAAG,YAAY,CAAC,CAAC,CAAC;IAU7D,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,GAAG,EAAE,GAAG,YAAY,CAAC,CAAC,CAAC;IAU9D,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,YAAY,CAAC,CAAC,CAAC;IAmBvD,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,YAAY,CAAC,CAAC,CAAC;IAY1D,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,YAAY,CAAC,CAAC,CAAC;IAS1C,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,YAAY,CAAC,CAAC,CAAC;IAS7C,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,GAAG,YAAY,CAAC,CAAC,CAAC;IAUnE,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,GAAG,YAAY,CAAC,CAAC,CAAC;IAUtE,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,YAAY,CAAC,CAAC,CAAC;IAU3D,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,YAAY,CAAC,CAAC,CAAC;IAU5D,WAAW,CAAC,YAAY,EAAE,MAAM,GAAG,YAAY,CAAC,GAAG,CAAC,GAAG,YAAY,CAAC,CAAC,CAAC;IAgBtE,cAAc,CAAC,YAAY,EAAE,MAAM,GAAG,YAAY,CAAC,GAAG,CAAC,GAAG,YAAY,CAAC,CAAC,CAAC;IAgBzE,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,GAAG,EAAE,GAAG,YAAY,CAAC,CAAC,CAAC;IAU3D,2FAA2F;IAC3F,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,YAAY,CAAC,CAAC,CAAC;IAOxE,OAAO,CAAC,OAAO;IASf,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,YAAY,CAAC,CAAC,CAAC;IAIvD,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,YAAY,CAAC,CAAC,CAAC;IAI5D,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,YAAY,CAAC,CAAC,CAAC;IAI3D,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,YAAY,CAAC,CAAC,CAAC;IAI5D,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,YAAY,CAAC,CAAC,CAAC;IAI3D,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,YAAY,CAAC,CAAC,CAAC;IAOzC,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,GAAE,KAAK,GAAG,MAAc,GAAG,YAAY,CAAC,CAAC,CAAC;IAO3E,OAAO,CAAC,GAAG,OAAO,EAAE,MAAM,EAAE,GAAG,YAAY,CAAC,CAAC,CAAC;IAK9C,MAAM,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,GAAG,EAAE,GAAG,YAAY,CAAC,CAAC,CAAC;IAQ5D,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,YAAY,CAAC,CAAC,CAAC;IAKrC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,YAAY,CAAC,CAAC,CAAC;IAKvC,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,YAAY,CAAC,CAAC,CAAC;IAIpC,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,YAAY,CAAC,CAAC,CAAC;IAIpC,KAAK,IAAI,YAAY,CAAC,CAAC,CAAC;IAKxB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,YAAY,CAAC,CAAC,CAAC;IAQzD,IAAI,CAAC,IAAI,GAAE,QAAuB,GAAG,YAAY,CAAC,CAAC,CAAC;IAKpD,SAAS,IAAI,YAAY,CAAC,CAAC,CAAC;IAK5B,QAAQ,IAAI,YAAY,CAAC,CAAC,CAAC;IAO3B,KAAK,CAAC,OAAO,EAAE,YAAY,CAAC,GAAG,CAAC,GAAG,YAAY,CAAC,CAAC,CAAC;IASlD,QAAQ,CAAC,OAAO,EAAE,YAAY,CAAC,GAAG,CAAC,GAAG,YAAY,CAAC,CAAC,CAAC;IAWrD,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,CAAC,GAAG,CAAC,GAAG,YAAY,CAAC,CAAC,CAAC;IAU/D,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,CAAC,GAAG,CAAC,GAAG,YAAY,CAAC,CAAC,CAAC;IAYxE,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,YAAY,CAAC,CAAC,CAAC;IAgBpD,KAAK,IAAI,YAAY,CAAC,CAAC,CAAC;IAuBxB,KAAK,IAAI;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,GAAG,EAAE,CAAA;KAAE;IA+DzC,KAAK,IAAI;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,GAAG,EAAE,CAAA;KAAE;IAMnC,OAAO,CACX,MAAM,EAAE,QAAQ,EAChB,KAAK,CAAC,EAAE,KAAK,EACb,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,CAAC,EAAE,CAAC;IAiBT,SAAS,CAAC,MAAM,EAAE,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC;IAa5C,UAAU,CAAC,MAAM,EAAE,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC;CAYrD"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
var X=Object.create;var{getPrototypeOf:k,defineProperty:j,getOwnPropertyNames:F}=Object;var N=Object.prototype.hasOwnProperty;var z=(A,G,H)=>{H=A!=null?X(k(A)):{};let V=G||!A||!A.__esModule?j(H,"default",{value:A,enumerable:!0}):H;for(let I of F(A))if(!N.call(V,I))j(V,I,{get:()=>A[I],enumerable:!0});return V};var B=(A,G)=>()=>(G||A((G={exports:{}}).exports,G),G.exports);var C=import.meta.require;var P;((V)=>{V.Postgres="postgres";V.MySQL="mysql";V.SQLite="sqlite"})(P||={});var Q;((I)=>{I[I.Debug=0]="Debug";I[I.Info=1]="Info";I[I.Warn=2]="Warn";I[I.Error=3]="Error"})(Q||={});var w;((I)=>{I[I.OneToOne=0]="OneToOne";I[I.OneToMany=1]="OneToMany";I[I.ManyToOne=2]="ManyToOne";I[I.ManyToMany=3]="ManyToMany"})(w||={});var E;((J)=>{J[J.STRING=0]="STRING";J[J.TEXT=1]="TEXT";J[J.INTEGER=2]="INTEGER";J[J.BIGINT=3]="BIGINT";J[J.FLOAT=4]="FLOAT";J[J.DOUBLE=5]="DOUBLE";J[J.DECIMAL=6]="DECIMAL";J[J.BOOLEAN=7]="BOOLEAN";J[J.DATE=8]="DATE";J[J.DATETIME=9]="DATETIME";J[J.JSON=10]="JSON";J[J.UUID=11]="UUID";J[J.BLOB=12]="BLOB"})(E||={});class $ extends Error{code;originalError;constructor(A,G,H){super(A);this.code=G;this.originalError=H;this.name="StabilizeError"}}function M(A){return{sql:A}}class x{listeners=new Map;on(A,G){if(!this.listeners.has(A))this.listeners.set(A,[]);this.listeners.get(A).push(G)}off(A,G){let H=this.listeners.get(A);if(H){let V=H.indexOf(G);if(V!==-1)H.splice(V,1)}}emit(A,...G){let H=this.listeners.get(A);if(H)for(let V of H)try{V(...G)}catch{}}}function R(){return crypto.randomUUID()}class Z{static models=new Map;static setModelMetadata(A,G){this.models.set(A,G)}static getModelMetadata(A){return this.models.get(A)}static getTableName(A){return this.getModelMetadata(A)?.tableName||""}static getColumns(A){return this.getModelMetadata(A)?.columns||{}}static getValidators(A){let G=this.getModelMetadata(A)?.columns||{},H={};for(let[V,I]of Object.entries(G)){let W=[];if(I.required)W.push("required");if(I.unique)W.push("unique");H[V]=W}return H}static getRelations(A){let G=this.getModelMetadata(A)?.relations||[],H={};for(let V of G)H[V.property]=V;return H}static getSoftDeleteField(A){let G=this.getModelMetadata(A)?.columns||{};for(let[H,V]of Object.entries(G))if(V.softDelete)return H;return null}static isVersioned(A){return!!this.getModelMetadata(A)?.versioned}static getScopes(A){return this.getModelMetadata(A)?.scopes||{}}static getModelByTableName(A){for(let[G,H]of this.models)if(H.tableName===A)return G;return}static getTimestamps(A){return this.getModelMetadata(A)?.timestamps||{}}}function O(A){class G{constructor(H){Object.assign(this,H)}}return Z.setModelMetadata(G,{tableName:A.tableName,versioned:A.versioned||!1,softDelete:A.softDelete||!1,columns:A.columns,relations:A.relations||[],scopes:A.scopes||{},timestamps:A.timestamps||{}}),G}class U{table;tableAlias=null;selectFields=["*"];isDistinct=!1;joins=[];whereConditions=[];whereParams=[];orderByClauses=[];limitValue=null;offsetValue=null;groupByClauses=[];havingConditions=[];havingParams=[];lockMode=null;eagerRelations=[];unions=[];ctas=[];constructor(A){this.table=A}select(...A){return this.selectFields=A.length>0?A:["*"],this}selectRaw(A,...G){return this.selectFields.push(A),this.whereParams.push(...G),this}distinct(){return this.isDistinct=!0,this}as(A){return this.tableAlias=A,this}count(A="*",G="count"){return this.selectFields=[`COUNT(${A}) AS ${G}`],this}sum(A,G="sum"){return this.selectFields=[`SUM(${A}) AS ${G}`],this}avg(A,G="avg"){return this.selectFields=[`AVG(${A}) AS ${G}`],this}min(A,G="min"){return this.selectFields=[`MIN(${A}) AS ${G}`],this}max(A,G="max"){return this.selectFields=[`MAX(${A}) AS ${G}`],this}where(A,...G){if(this.whereConditions.length>0)this.whereConditions.push(`AND ${A}`);else this.whereConditions.push(A);return this.whereParams.push(...G),this}orWhere(A,...G){if(this.whereConditions.length===0)this.whereConditions.push(A);else this.whereConditions.push(`OR (${A})`);return this.whereParams.push(...G),this}whereNot(A,...G){if(this.whereConditions.length>0)this.whereConditions.push(`AND NOT (${A})`);else this.whereConditions.push(`NOT (${A})`);return this.whereParams.push(...G),this}whereIn(A,G){if(G.length===0){if(this.whereConditions.length>0)this.whereConditions.push("AND 1 = 0");else this.whereConditions.push("1 = 0");return this}let H=G.map(()=>"?").join(", ");if(this.whereConditions.length>0)this.whereConditions.push(`AND ${A} IN (${H})`);else this.whereConditions.push(`${A} IN (${H})`);return this.whereParams.push(...G),this}whereNotIn(A,G){if(G.length===0)return this;let H=G.map(()=>"?").join(", ");if(this.whereConditions.length>0)this.whereConditions.push(`AND ${A} NOT IN (${H})`);else this.whereConditions.push(`${A} NOT IN (${H})`);return this.whereParams.push(...G),this}whereNull(A){if(this.whereConditions.length>0)this.whereConditions.push(`AND ${A} IS NULL`);else this.whereConditions.push(`${A} IS NULL`);return this}whereNotNull(A){if(this.whereConditions.length>0)this.whereConditions.push(`AND ${A} IS NOT NULL`);else this.whereConditions.push(`${A} IS NOT NULL`);return this}whereBetween(A,G,H){if(this.whereConditions.length>0)this.whereConditions.push(`AND ${A} BETWEEN ? AND ?`);else this.whereConditions.push(`${A} BETWEEN ? AND ?`);return this.whereParams.push(G,H),this}whereNotBetween(A,G,H){if(this.whereConditions.length>0)this.whereConditions.push(`AND ${A} NOT BETWEEN ? AND ?`);else this.whereConditions.push(`${A} NOT BETWEEN ? AND ?`);return this.whereParams.push(G,H),this}whereLike(A,G){if(this.whereConditions.length>0)this.whereConditions.push(`AND ${A} LIKE ?`);else this.whereConditions.push(`${A} LIKE ?`);return this.whereParams.push(G),this}whereILike(A,G){if(this.whereConditions.length>0)this.whereConditions.push(`AND ${A} ILIKE ?`);else this.whereConditions.push(`${A} ILIKE ?`);return this.whereParams.push(G),this}whereExists(A){let G=typeof A==="string"?A:A.build().query;if(this.whereConditions.length>0)this.whereConditions.push(`AND EXISTS (${G})`);else this.whereConditions.push(`EXISTS (${G})`);if(typeof A!=="string")this.whereParams.push(...A.build().params);return this}whereNotExists(A){let G=typeof A==="string"?A:A.build().query;if(this.whereConditions.length>0)this.whereConditions.push(`AND NOT EXISTS (${G})`);else this.whereConditions.push(`NOT EXISTS (${G})`);if(typeof A!=="string")this.whereParams.push(...A.build().params);return this}whereRaw(A,...G){if(this.whereConditions.length>0)this.whereConditions.push(`AND ${A}`);else this.whereConditions.push(A);return this.whereParams.push(...G),this}whereRef(A,G,H){return this.whereConditions.push(`${A} ${G} ${H}`),this}addJoin(A,G,H){return this.joins.push(`${A} JOIN ${G} ON ${H}`),this}join(A,G){return this.addJoin("LEFT",A,G)}innerJoin(A,G){return this.addJoin("INNER",A,G)}leftJoin(A,G){return this.addJoin("LEFT",A,G)}rightJoin(A,G){return this.addJoin("RIGHT",A,G)}fullJoin(A,G){return this.addJoin("FULL",A,G)}crossJoin(A){return this.joins.push(`CROSS JOIN ${A}`),this}orderBy(A,G="ASC"){return this.orderByClauses.push(`${A} ${G}`),this}groupBy(...A){return this.groupByClauses.push(...A),this}having(A,...G){return this.havingConditions.push(A),this.havingParams.push(...G),this}limit(A){return this.limitValue=A,this}offset(A){return this.offsetValue=A,this}take(A){return this.limit(A)}skip(A){return this.offset(A)}first(){return this.limitValue=1,this}paginate(A,G){return this.limitValue=G,this.offsetValue=(A-1)*G,this}lock(A="FOR UPDATE"){return this.lockMode=A,this}forUpdate(){return this.lockMode="FOR UPDATE",this}forShare(){return this.lockMode="FOR SHARE",this}union(A){return this.unions.push({query:A.build().query,params:A.build().params,all:!1}),this}unionAll(A){return this.unions.push({query:A.build().query,params:A.build().params,all:!0}),this}with(A,G){return this.ctas.push({name:A,query:G.build().query,params:G.build().params,recursive:!1}),this}withRecursive(A,G){return this.ctas.push({name:A,query:G.build().query,params:G.build().params,recursive:!0}),this}scope(A,...G){let H=Z.getModelByTableName(this.table);if(!H)throw new $(`Model for table ${this.table} not found`,"SCOPE_ERROR");let I=Z.getScopes(H)[A];if(!I)throw new $(`Scope ${A} not found`,"SCOPE_ERROR");return I(this,...G)}clone(){let A=new U(this.table);return A.tableAlias=this.tableAlias,A.selectFields=[...this.selectFields],A.isDistinct=this.isDistinct,A.joins=[...this.joins],A.whereConditions=[...this.whereConditions],A.whereParams=[...this.whereParams],A.orderByClauses=[...this.orderByClauses],A.limitValue=this.limitValue,A.offsetValue=this.offsetValue,A.groupByClauses=[...this.groupByClauses],A.havingConditions=[...this.havingConditions],A.havingParams=[...this.havingParams],A.lockMode=this.lockMode,A.eagerRelations=[...this.eagerRelations],A.unions=[...this.unions],A.ctas=[...this.ctas],A}build(){let A=[],G="";if(this.ctas.length>0){let W=this.ctas.some((Y)=>Y.recursive)?"RECURSIVE ":"",_=this.ctas.map((Y)=>{return A.push(...Y.params),`${Y.name} AS (${Y.query})`}).join(", ");G=`WITH ${W}${_}
|
|
3
|
+
`}let H=this.tableAlias?`${this.table} AS ${this.tableAlias}`:this.table,V=this.isDistinct?" DISTINCT":"",I=`${G}SELECT${V} ${this.selectFields.join(", ")} FROM ${H}`;if(this.joins.length>0)I+=`
|
|
4
|
+
`+this.joins.join(`
|
|
5
|
+
`);if(A.push(...this.whereParams),this.whereConditions.length>0)I+=`
|
|
6
|
+
WHERE `+this.whereConditions.join(" ");if(this.groupByClauses.length>0)I+=`
|
|
7
|
+
GROUP BY `+this.groupByClauses.join(", ");if(A.push(...this.havingParams),this.havingConditions.length>0)I+=`
|
|
8
|
+
HAVING `+this.havingConditions.join(" ");if(this.orderByClauses.length>0)I+=`
|
|
9
|
+
ORDER BY `+this.orderByClauses.join(", ");if(this.limitValue!==null)I+=`
|
|
10
|
+
LIMIT ${this.limitValue}`;if(this.offsetValue!==null)I+=` OFFSET ${this.offsetValue}`;if(this.lockMode)I+=` ${this.lockMode}`;for(let W of this.unions)I+=W.all?`
|
|
11
|
+
UNION ALL (${W.query})`:`
|
|
12
|
+
UNION (${W.query})`,A.push(...W.params);return{query:I,params:A}}toSQL(){return this.build()}async execute(A,G,H){let{query:V,params:I}=this.build();if(G&&H){let _=await G.get(H);if(_)return _}let W=await A.query(V,I);if(G&&H&&W.length>0)await G.set(H,W,60);return W}async countExec(A){let G=this.clone();G.selectFields=["COUNT(*) AS __cnt"],G.orderByClauses=[],G.limitValue=null,G.offsetValue=null;let H=await A.query(G.build().query,G.build().params);return Number(H[0]?.__cnt??0)}async existsExec(A){let G=this.clone();return G.selectFields=["1"],G.orderByClauses=[],G.limitValue=1,G.offsetValue=null,(await A.query(G.build().query,G.build().params)).length>0}}export{U as QueryBuilder};
|
|
13
|
+
|
|
14
|
+
//# debugId=FF5254D917A0605264756E2164756E21
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["..\\types.ts", "..\\model.ts", "..\\query-builder.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"/**\n * @file types.ts\n * @description Contains all shared type definitions and enums for the Stabilize ORM.\n * @author ElectronSz\n */\n\nexport enum DBType {\n Postgres = \"postgres\",\n MySQL = \"mysql\",\n SQLite = \"sqlite\",\n}\n\nexport enum LogLevel {\n Debug,\n Info,\n Warn,\n Error,\n}\n\nexport enum RelationType {\n OneToOne,\n OneToMany,\n ManyToOne,\n ManyToMany,\n}\n\n/**\n * An enumeration of abstract data types that are mapped to database-specific types.\n * This allows models to be defined in a database-agnostic way.\n */\nexport enum DataTypes {\n STRING, // Maps to VARCHAR or TEXT\n TEXT, // Maps to TEXT\n INTEGER, // Maps to INTEGER or INT\n BIGINT, // Maps to BIGINT\n FLOAT, // Maps to REAL or FLOAT\n DOUBLE, // Maps to DOUBLE PRECISION\n DECIMAL, // Maps to DECIMAL or NUMERIC\n BOOLEAN, // Maps to BOOLEAN or TINYINT/INTEGER\n DATE, // Maps to DATE or TEXT\n DATETIME, // Maps to TIMESTAMP, DATETIME, or TEXT\n JSON, // Maps to JSON, JSONB, or TEXT\n UUID, // Maps to UUID or VARCHAR(36)\n BLOB, // Maps to BYTEA or BLOB\n}\n\nexport interface DBConfig {\n type: DBType;\n connectionString: string;\n retryAttempts?: number;\n retryDelay?: number;\n maxJitter?: number;\n}\n\nexport interface CacheConfig {\n enabled: boolean;\n ttl: number;\n redisUrl?: string;\n cachePrefix?: string;\n strategy?: \"cache-aside\" | \"write-through\";\n}\n\n/**\n * Configuration for the logger.\n */\nexport interface LoggerConfig {\n level?: LogLevel;\n filePath?: string;\n maxFileSize?: number;\n maxFiles?: number;\n}\n\nexport interface PoolMetrics {\n activeConnections: number;\n idleConnections: number;\n totalConnections: number;\n}\n\nexport interface QueryHint {\n type: string;\n value: string;\n}\n\nexport interface CacheStats {\n hits: number;\n misses: number;\n keys: number;\n}\n\nexport interface Migration {\n name: string;\n up: string[];\n down: string[];\n}\n\nexport class StabilizeError extends Error {\n constructor(\n message: string,\n public code: string,\n public originalError?: Error,\n ) {\n super(message);\n this.name = \"StabilizeError\";\n }\n}\n\nexport interface DefaultExpression {\n sql: string;\n}\n\nexport function sqlDefault(sql: string): DefaultExpression {\n return { sql };\n}\n\nexport type TransactionIsolationLevel =\n | \"READ UNCOMMITTED\"\n | \"READ COMMITTED\"\n | \"REPEATABLE READ\"\n | \"SERIALIZABLE\";\n\nexport interface QueryLogEntry {\n query: string;\n params: any[];\n durationMs: number;\n timestamp: Date;\n source: string;\n}\n\nexport type StabilizeEvent =\n | \"query\"\n | \"error\"\n | \"migration:start\"\n | \"migration:complete\"\n | \"transaction:start\"\n | \"transaction:complete\"\n | \"transaction:error\"\n | \"connection:open\"\n | \"connection:close\";\n\nexport type StabilizeEventHandler = (...args: any[]) => void;\n\nexport class StabilizeEmitter {\n private listeners: Map<StabilizeEvent, StabilizeEventHandler[]> = new Map();\n\n on(event: StabilizeEvent, handler: StabilizeEventHandler): void {\n if (!this.listeners.has(event)) {\n this.listeners.set(event, []);\n }\n this.listeners.get(event)!.push(handler);\n }\n\n off(event: StabilizeEvent, handler: StabilizeEventHandler): void {\n const handlers = this.listeners.get(event);\n if (handlers) {\n const idx = handlers.indexOf(handler);\n if (idx !== -1) handlers.splice(idx, 1);\n }\n }\n\n emit(event: StabilizeEvent, ...args: any[]): void {\n const handlers = this.listeners.get(event);\n if (handlers) {\n for (const handler of handlers) {\n try {\n handler(...args);\n } catch {}\n }\n }\n }\n}\n\nexport function generateUUID(): string {\n return crypto.randomUUID();\n}\n",
|
|
6
|
+
"/**\n * @file model.ts\n * @description Provides a programmatic API for defining models and a metadata storage system.\n * @author ElectronSz\n */\n\nimport type { QueryBuilder } from \"./query-builder\";\nimport { DataTypes, RelationType, type DefaultExpression } from \"./types\";\n\n// Interface for column configuration\nexport interface ColumnConfig {\n name?: string;\n type: DataTypes;\n length?: number;\n precision?: number;\n scale?: number;\n required?: boolean;\n unique?: boolean;\n defaultValue?: any;\n defaultExpression?: DefaultExpression;\n index?: string;\n softDelete?: boolean;\n minLength?: number;\n maxLength?: number;\n pattern?: RegExp;\n customValidator?: (val: any) => boolean | string;\n encrypted?: boolean;\n optimisticLock?: boolean;\n}\n\n// Interface for relationship configuration\nexport interface RelationConfig {\n type: RelationType;\n target: () => any; // Reference to another model\n property: string; // Property name in the model\n foreignKey?: string;\n inverseKey?: string;\n joinTable?: string;\n}\n\nexport interface TimestampsConfig {\n createdAt?: string;\n updatedAt?: string;\n}\n\n// Interface for model configuration\nexport interface ModelConfig {\n tableName: string;\n versioned?: boolean;\n softDelete?: boolean;\n columns: Record<string, ColumnConfig>;\n relations?: RelationConfig[];\n scopes?: Record<\n string,\n (qb: QueryBuilder<any>, ...args: any[]) => QueryBuilder<any>\n >; // Custom query scopes\n timestamps?: TimestampsConfig; // Auto-managed timestamp columns\n}\n\n/**\n * Metadata storage for models.\n * Stores and retrieves model configuration such as columns, relations, scopes, etc.\n */\nexport class MetadataStorage {\n private static models: Map<Function, ModelConfig> = new Map();\n\n /**\n * Associates model metadata with a class constructor.\n * @param model - The class constructor for the model.\n * @param config - The model configuration object.\n */\n static setModelMetadata(model: Function, config: ModelConfig) {\n this.models.set(model, config);\n }\n\n /**\n * Retrieves the model configuration for a given model class.\n * @param model - The class constructor for the model.\n * @returns The model configuration or undefined if not found.\n */\n static getModelMetadata(model: Function): ModelConfig | undefined {\n return this.models.get(model);\n }\n\n /**\n * Gets the table name for a given model class.\n * @param model - The class constructor for the model.\n * @returns The table name or an empty string if not found.\n */\n static getTableName(model: Function): string {\n return this.getModelMetadata(model)?.tableName || \"\";\n }\n\n /**\n * Gets the column configuration for a given model class.\n * @param model - The class constructor for the model.\n * @returns Record of column names to their configuration.\n */\n static getColumns(model: Function): Record<string, ColumnConfig> {\n return this.getModelMetadata(model)?.columns || {};\n }\n\n /**\n * Collects validation rules for each column of a given model.\n * @param model - The class constructor for the model.\n * @returns An object mapping column names to an array of validation rule names.\n */\n static getValidators(model: Function): Record<string, string[]> {\n const columns = this.getModelMetadata(model)?.columns || {};\n const validators: Record<string, string[]> = {};\n for (const [key, col] of Object.entries(columns)) {\n const rules: string[] = [];\n if (col.required) rules.push(\"required\");\n if (col.unique) rules.push(\"unique\");\n validators[key] = rules;\n }\n return validators;\n }\n\n /**\n * Gets the relationship configuration for a given model class.\n * @param model - The class constructor for the model.\n * @returns Record of property names to their relation configuration.\n */\n static getRelations(model: Function): Record<string, RelationConfig> {\n const relations = this.getModelMetadata(model)?.relations || [];\n const result: Record<string, RelationConfig> = {};\n for (const rel of relations) {\n result[rel.property] = rel;\n }\n return result;\n }\n\n /**\n * Finds the soft delete field, if any, for a given model class.\n * @param model - The class constructor for the model.\n * @returns The key of the soft delete field, or null if not found.\n */\n static getSoftDeleteField(model: Function): string | null {\n const columns = this.getModelMetadata(model)?.columns || {};\n for (const [key, col] of Object.entries(columns)) {\n if (col.softDelete) return key;\n }\n return null;\n }\n\n /**\n * Checks if the model is versioned.\n * @param model - The class constructor for the model.\n * @returns True if versioned, false otherwise.\n */\n static isVersioned(model: Function): boolean {\n return !!this.getModelMetadata(model)?.versioned;\n }\n\n /**\n * Gets custom query scopes for a given model class.\n * @param model - The class constructor for the model.\n * @returns Record of scope names to scope functions.\n */\n static getScopes(\n model: Function,\n ): Record<\n string,\n (qb: QueryBuilder<any>, ...args: any[]) => QueryBuilder<any>\n > {\n return this.getModelMetadata(model)?.scopes || {};\n }\n\n /**\n * Finds the model constructor by table name.\n * @param tableName - The table name to search for.\n * @returns The model constructor or undefined if not found.\n */\n static getModelByTableName(tableName: string): Function | undefined {\n for (const [model, config] of this.models) {\n if (config.tableName === tableName) {\n return model;\n }\n }\n return undefined;\n }\n\n static getTimestamps(model: Function): TimestampsConfig {\n return this.getModelMetadata(model)?.timestamps || {};\n }\n}\n\n/**\n * Programmatically defines a model and stores its metadata.\n * @param config - The model configuration object.\n * @returns The dynamically created model class.\n */\nexport function defineModel(config: ModelConfig) {\n class Model {\n /**\n * Constructs a model instance from plain data.\n * @param data - The plain object to assign properties from.\n */\n constructor(data: any) {\n Object.assign(this, data);\n }\n }\n\n // Store metadata\n MetadataStorage.setModelMetadata(Model, {\n tableName: config.tableName,\n versioned: config.versioned || false,\n softDelete: config.softDelete || false,\n columns: config.columns,\n relations: config.relations || [],\n scopes: config.scopes || {},\n timestamps: config.timestamps || {},\n });\n\n return Model;\n}\n",
|
|
7
|
+
"/**\n * @file query-builder.ts\n * @description A feature-rich SQL query builder inspired by Knex.js, TypeORM, Prisma, and Drizzle.\n * @author ElectronSz\n */\n\nimport { DBClient } from \"./client\";\nimport { Cache } from \"./cache\";\nimport { MetadataStorage } from \"./model\";\nimport { StabilizeError } from \"./types\";\n\ntype JoinType = \"INNER\" | \"LEFT\" | \"RIGHT\" | \"FULL\" | \"CROSS\";\ntype LockMode =\n | \"FOR UPDATE\"\n | \"FOR SHARE\"\n | \"FOR NO KEY UPDATE\"\n | \"FOR KEY SHARE\";\n\nexport class QueryBuilder<T> {\n private table: string;\n private tableAlias: string | null = null;\n private selectFields: string[] = [\"*\"];\n private isDistinct = false;\n private joins: string[] = [];\n private whereConditions: string[] = [];\n private whereParams: any[] = [];\n private orderByClauses: string[] = [];\n private limitValue: number | null = null;\n private offsetValue: number | null = null;\n private groupByClauses: string[] = [];\n private havingConditions: string[] = [];\n private havingParams: any[] = [];\n private lockMode: LockMode | null = null;\n private eagerRelations: string[] = [];\n private unions: { query: string; params: any[]; all: boolean }[] = [];\n private ctas: {\n name: string;\n query: string;\n params: any[];\n recursive: boolean;\n }[] = [];\n\n constructor(table: string) {\n this.table = table;\n }\n\n // ─── SELECT ───────────────────────────────────────────────────────\n\n select(...fields: string[]): QueryBuilder<T> {\n this.selectFields = fields.length > 0 ? fields : [\"*\"];\n return this;\n }\n\n selectRaw(expression: string, ...params: any[]): QueryBuilder<T> {\n this.selectFields.push(expression);\n this.whereParams.push(...params);\n return this;\n }\n\n distinct(): QueryBuilder<T> {\n this.isDistinct = true;\n return this;\n }\n\n as(alias: string): QueryBuilder<T> {\n this.tableAlias = alias;\n return this;\n }\n\n // ─── AGGREGATE SHORTCUTS (Prisma / Sequelize style) ───────────────\n\n count(column: string = \"*\", alias: string = \"count\"): QueryBuilder<T> {\n this.selectFields = [`COUNT(${column}) AS ${alias}`];\n return this;\n }\n\n sum(column: string, alias: string = \"sum\"): QueryBuilder<T> {\n this.selectFields = [`SUM(${column}) AS ${alias}`];\n return this;\n }\n\n avg(column: string, alias: string = \"avg\"): QueryBuilder<T> {\n this.selectFields = [`AVG(${column}) AS ${alias}`];\n return this;\n }\n\n min(column: string, alias: string = \"min\"): QueryBuilder<T> {\n this.selectFields = [`MIN(${column}) AS ${alias}`];\n return this;\n }\n\n max(column: string, alias: string = \"max\"): QueryBuilder<T> {\n this.selectFields = [`MAX(${column}) AS ${alias}`];\n return this;\n }\n\n // ─── WHERE ────────────────────────────────────────────────────────\n\n where(condition: string, ...params: any[]): QueryBuilder<T> {\n if (this.whereConditions.length > 0) {\n this.whereConditions.push(`AND ${condition}`);\n } else {\n this.whereConditions.push(condition);\n }\n this.whereParams.push(...params);\n return this;\n }\n\n orWhere(condition: string, ...params: any[]): QueryBuilder<T> {\n if (this.whereConditions.length === 0) {\n this.whereConditions.push(condition);\n } else {\n this.whereConditions.push(`OR (${condition})`);\n }\n this.whereParams.push(...params);\n return this;\n }\n\n whereNot(condition: string, ...params: any[]): QueryBuilder<T> {\n if (this.whereConditions.length > 0) {\n this.whereConditions.push(`AND NOT (${condition})`);\n } else {\n this.whereConditions.push(`NOT (${condition})`);\n }\n this.whereParams.push(...params);\n return this;\n }\n\n whereIn(column: string, values: any[]): QueryBuilder<T> {\n if (values.length === 0) {\n if (this.whereConditions.length > 0) {\n this.whereConditions.push(\"AND 1 = 0\");\n } else {\n this.whereConditions.push(\"1 = 0\");\n }\n return this;\n }\n const placeholders = values.map(() => \"?\").join(\", \");\n if (this.whereConditions.length > 0) {\n this.whereConditions.push(`AND ${column} IN (${placeholders})`);\n } else {\n this.whereConditions.push(`${column} IN (${placeholders})`);\n }\n this.whereParams.push(...values);\n return this;\n }\n\n whereNotIn(column: string, values: any[]): QueryBuilder<T> {\n if (values.length === 0) return this;\n const placeholders = values.map(() => \"?\").join(\", \");\n if (this.whereConditions.length > 0) {\n this.whereConditions.push(`AND ${column} NOT IN (${placeholders})`);\n } else {\n this.whereConditions.push(`${column} NOT IN (${placeholders})`);\n }\n this.whereParams.push(...values);\n return this;\n }\n\n whereNull(column: string): QueryBuilder<T> {\n if (this.whereConditions.length > 0) {\n this.whereConditions.push(`AND ${column} IS NULL`);\n } else {\n this.whereConditions.push(`${column} IS NULL`);\n }\n return this;\n }\n\n whereNotNull(column: string): QueryBuilder<T> {\n if (this.whereConditions.length > 0) {\n this.whereConditions.push(`AND ${column} IS NOT NULL`);\n } else {\n this.whereConditions.push(`${column} IS NOT NULL`);\n }\n return this;\n }\n\n whereBetween(column: string, start: any, end: any): QueryBuilder<T> {\n if (this.whereConditions.length > 0) {\n this.whereConditions.push(`AND ${column} BETWEEN ? AND ?`);\n } else {\n this.whereConditions.push(`${column} BETWEEN ? AND ?`);\n }\n this.whereParams.push(start, end);\n return this;\n }\n\n whereNotBetween(column: string, start: any, end: any): QueryBuilder<T> {\n if (this.whereConditions.length > 0) {\n this.whereConditions.push(`AND ${column} NOT BETWEEN ? AND ?`);\n } else {\n this.whereConditions.push(`${column} NOT BETWEEN ? AND ?`);\n }\n this.whereParams.push(start, end);\n return this;\n }\n\n whereLike(column: string, pattern: string): QueryBuilder<T> {\n if (this.whereConditions.length > 0) {\n this.whereConditions.push(`AND ${column} LIKE ?`);\n } else {\n this.whereConditions.push(`${column} LIKE ?`);\n }\n this.whereParams.push(pattern);\n return this;\n }\n\n whereILike(column: string, pattern: string): QueryBuilder<T> {\n if (this.whereConditions.length > 0) {\n this.whereConditions.push(`AND ${column} ILIKE ?`);\n } else {\n this.whereConditions.push(`${column} ILIKE ?`);\n }\n this.whereParams.push(pattern);\n return this;\n }\n\n whereExists(builderOrSql: string | QueryBuilder<any>): QueryBuilder<T> {\n const sql =\n typeof builderOrSql === \"string\"\n ? builderOrSql\n : builderOrSql.build().query;\n if (this.whereConditions.length > 0) {\n this.whereConditions.push(`AND EXISTS (${sql})`);\n } else {\n this.whereConditions.push(`EXISTS (${sql})`);\n }\n if (typeof builderOrSql !== \"string\") {\n this.whereParams.push(...builderOrSql.build().params);\n }\n return this;\n }\n\n whereNotExists(builderOrSql: string | QueryBuilder<any>): QueryBuilder<T> {\n const sql =\n typeof builderOrSql === \"string\"\n ? builderOrSql\n : builderOrSql.build().query;\n if (this.whereConditions.length > 0) {\n this.whereConditions.push(`AND NOT EXISTS (${sql})`);\n } else {\n this.whereConditions.push(`NOT EXISTS (${sql})`);\n }\n if (typeof builderOrSql !== \"string\") {\n this.whereParams.push(...builderOrSql.build().params);\n }\n return this;\n }\n\n whereRaw(rawSql: string, ...params: any[]): QueryBuilder<T> {\n if (this.whereConditions.length > 0) {\n this.whereConditions.push(`AND ${rawSql}`);\n } else {\n this.whereConditions.push(rawSql);\n }\n this.whereParams.push(...params);\n return this;\n }\n\n /** Knex-style column-to-column comparison: .whereRef('orders.user_id', '=', 'users.id') */\n whereRef(leftCol: string, op: string, rightCol: string): QueryBuilder<T> {\n this.whereConditions.push(`${leftCol} ${op} ${rightCol}`);\n return this;\n }\n\n // ─── JOIN ─────────────────────────────────────────────────────────\n\n private addJoin(\n type: JoinType,\n table: string,\n condition: string,\n ): QueryBuilder<T> {\n this.joins.push(`${type} JOIN ${table} ON ${condition}`);\n return this;\n }\n\n join(table: string, condition: string): QueryBuilder<T> {\n return this.addJoin(\"LEFT\", table, condition);\n }\n\n innerJoin(table: string, condition: string): QueryBuilder<T> {\n return this.addJoin(\"INNER\", table, condition);\n }\n\n leftJoin(table: string, condition: string): QueryBuilder<T> {\n return this.addJoin(\"LEFT\", table, condition);\n }\n\n rightJoin(table: string, condition: string): QueryBuilder<T> {\n return this.addJoin(\"RIGHT\", table, condition);\n }\n\n fullJoin(table: string, condition: string): QueryBuilder<T> {\n return this.addJoin(\"FULL\", table, condition);\n }\n\n crossJoin(table: string): QueryBuilder<T> {\n this.joins.push(`CROSS JOIN ${table}`);\n return this;\n }\n\n // ─── ORDER BY ─────────────────────────────────────────────────────\n\n orderBy(column: string, direction: \"ASC\" | \"DESC\" = \"ASC\"): QueryBuilder<T> {\n this.orderByClauses.push(`${column} ${direction}`);\n return this;\n }\n\n // ─── GROUP BY / HAVING ────────────────────────────────────────────\n\n groupBy(...columns: string[]): QueryBuilder<T> {\n this.groupByClauses.push(...columns);\n return this;\n }\n\n having(condition: string, ...params: any[]): QueryBuilder<T> {\n this.havingConditions.push(condition);\n this.havingParams.push(...params);\n return this;\n }\n\n // ─── LIMIT / OFFSET (Prisma: take / skip) ─────────────────────────\n\n limit(limit: number): QueryBuilder<T> {\n this.limitValue = limit;\n return this;\n }\n\n offset(offset: number): QueryBuilder<T> {\n this.offsetValue = offset;\n return this;\n }\n\n take(count: number): QueryBuilder<T> {\n return this.limit(count);\n }\n\n skip(count: number): QueryBuilder<T> {\n return this.offset(count);\n }\n\n first(): QueryBuilder<T> {\n this.limitValue = 1;\n return this;\n }\n\n paginate(page: number, pageSize: number): QueryBuilder<T> {\n this.limitValue = pageSize;\n this.offsetValue = (page - 1) * pageSize;\n return this;\n }\n\n // ─── LOCKING ──────────────────────────────────────────────────────\n\n lock(mode: LockMode = \"FOR UPDATE\"): QueryBuilder<T> {\n this.lockMode = mode;\n return this;\n }\n\n forUpdate(): QueryBuilder<T> {\n this.lockMode = \"FOR UPDATE\";\n return this;\n }\n\n forShare(): QueryBuilder<T> {\n this.lockMode = \"FOR SHARE\";\n return this;\n }\n\n // ─── SET OPERATIONS ───────────────────────────────────────────────\n\n union(builder: QueryBuilder<any>): QueryBuilder<T> {\n this.unions.push({\n query: builder.build().query,\n params: builder.build().params,\n all: false,\n });\n return this;\n }\n\n unionAll(builder: QueryBuilder<any>): QueryBuilder<T> {\n this.unions.push({\n query: builder.build().query,\n params: builder.build().params,\n all: true,\n });\n return this;\n }\n\n // ─── COMMON TABLE EXPRESSIONS ─────────────────────────────────────\n\n with(name: string, builder: QueryBuilder<any>): QueryBuilder<T> {\n this.ctas.push({\n name,\n query: builder.build().query,\n params: builder.build().params,\n recursive: false,\n });\n return this;\n }\n\n withRecursive(name: string, builder: QueryBuilder<any>): QueryBuilder<T> {\n this.ctas.push({\n name,\n query: builder.build().query,\n params: builder.build().params,\n recursive: true,\n });\n return this;\n }\n\n // ─── SCOPE ────────────────────────────────────────────────────────\n\n scope(name: string, ...args: any[]): QueryBuilder<T> {\n const model = MetadataStorage.getModelByTableName(this.table);\n if (!model)\n throw new StabilizeError(\n `Model for table ${this.table} not found`,\n \"SCOPE_ERROR\",\n );\n const scopes = MetadataStorage.getScopes(model);\n const scopeFn = scopes[name];\n if (!scopeFn)\n throw new StabilizeError(`Scope ${name} not found`, \"SCOPE_ERROR\");\n return scopeFn(this, ...args);\n }\n\n // ─── CLONE ────────────────────────────────────────────────────────\n\n clone(): QueryBuilder<T> {\n const q = new QueryBuilder<T>(this.table);\n q.tableAlias = this.tableAlias;\n q.selectFields = [...this.selectFields];\n q.isDistinct = this.isDistinct;\n q.joins = [...this.joins];\n q.whereConditions = [...this.whereConditions];\n q.whereParams = [...this.whereParams];\n q.orderByClauses = [...this.orderByClauses];\n q.limitValue = this.limitValue;\n q.offsetValue = this.offsetValue;\n q.groupByClauses = [...this.groupByClauses];\n q.havingConditions = [...this.havingConditions];\n q.havingParams = [...this.havingParams];\n q.lockMode = this.lockMode;\n q.eagerRelations = [...this.eagerRelations];\n q.unions = [...this.unions];\n q.ctas = [...this.ctas];\n return q;\n }\n\n // ─── BUILD ────────────────────────────────────────────────────────\n\n build(): { query: string; params: any[] } {\n const params: any[] = [];\n let ctePrefix = \"\";\n\n if (this.ctas.length > 0) {\n const recursive = this.ctas.some((c) => c.recursive) ? \"RECURSIVE \" : \"\";\n const ctes = this.ctas\n .map((c) => {\n params.push(...c.params);\n return `${c.name} AS (${c.query})`;\n })\n .join(\", \");\n ctePrefix = `WITH ${recursive}${ctes}\\n`;\n }\n\n const table = this.tableAlias\n ? `${this.table} AS ${this.tableAlias}`\n : this.table;\n const distinct = this.isDistinct ? \" DISTINCT\" : \"\";\n\n let query = `${ctePrefix}SELECT${distinct} ${this.selectFields.join(\", \")} FROM ${table}`;\n\n if (this.joins.length > 0) {\n query += \"\\n\" + this.joins.join(\"\\n\");\n }\n\n params.push(...this.whereParams);\n if (this.whereConditions.length > 0) {\n query += \"\\nWHERE \" + this.whereConditions.join(\" \");\n }\n\n if (this.groupByClauses.length > 0) {\n query += \"\\nGROUP BY \" + this.groupByClauses.join(\", \");\n }\n\n params.push(...this.havingParams);\n if (this.havingConditions.length > 0) {\n query += \"\\nHAVING \" + this.havingConditions.join(\" \");\n }\n\n if (this.orderByClauses.length > 0) {\n query += \"\\nORDER BY \" + this.orderByClauses.join(\", \");\n }\n\n if (this.limitValue !== null) {\n query += `\\nLIMIT ${this.limitValue}`;\n }\n if (this.offsetValue !== null) {\n query += ` OFFSET ${this.offsetValue}`;\n }\n\n if (this.lockMode) {\n query += ` ${this.lockMode}`;\n }\n\n for (const u of this.unions) {\n query += u.all ? `\\nUNION ALL (${u.query})` : `\\nUNION (${u.query})`;\n params.push(...u.params);\n }\n\n return { query, params };\n }\n\n toSQL(): { query: string; params: any[] } {\n return this.build();\n }\n\n // ─── EXECUTE ──────────────────────────────────────────────────────\n\n async execute(\n client: DBClient,\n cache?: Cache,\n cacheKey?: string,\n ): Promise<T[]> {\n const { query, params } = this.build();\n\n if (cache && cacheKey) {\n const cached = await cache.get<T[]>(cacheKey);\n if (cached) return cached;\n }\n\n const results = await client.query<T>(query, params);\n\n if (cache && cacheKey && results.length > 0) {\n await cache.set(cacheKey, results, 60);\n }\n\n return results;\n }\n\n async countExec(client: DBClient): Promise<number> {\n const clone = this.clone();\n clone.selectFields = [\"COUNT(*) AS __cnt\"];\n clone.orderByClauses = [];\n clone.limitValue = null;\n clone.offsetValue = null;\n const results = await client.query<any>(\n clone.build().query,\n clone.build().params,\n );\n return Number(results[0]?.__cnt ?? 0);\n }\n\n async existsExec(client: DBClient): Promise<boolean> {\n const clone = this.clone();\n clone.selectFields = [\"1\"];\n clone.orderByClauses = [];\n clone.limitValue = 1;\n clone.offsetValue = null;\n const results = await client.query<any>(\n clone.build().query,\n clone.build().params,\n );\n return results.length > 0;\n }\n}\n"
|
|
8
|
+
],
|
|
9
|
+
"mappings": "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",
|
|
10
|
+
"debugId": "FF5254D917A0605264756E2164756E21",
|
|
11
|
+
"names": []
|
|
12
|
+
}
|