@cheetah.js/orm 0.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.
Files changed (93) hide show
  1. package/README.md +228 -0
  2. package/build.ts +14 -0
  3. package/cheetah.config.ts +14 -0
  4. package/dist/SqlBuilder.d.ts +57 -0
  5. package/dist/SqlBuilder.js +436 -0
  6. package/dist/SqlBuilder.js.map +1 -0
  7. package/dist/bun/index.d.ts +13 -0
  8. package/dist/bun/index.js +224319 -0
  9. package/dist/bun/index.js.map +306 -0
  10. package/dist/cheetah.d.ts +1 -0
  11. package/dist/cheetah.js +24 -0
  12. package/dist/cheetah.js.map +1 -0
  13. package/dist/constants.d.ts +4 -0
  14. package/dist/constants.js +5 -0
  15. package/dist/constants.js.map +1 -0
  16. package/dist/decorators/entity.decorator.d.ts +3 -0
  17. package/dist/decorators/entity.decorator.js +10 -0
  18. package/dist/decorators/entity.decorator.js.map +1 -0
  19. package/dist/decorators/index.decorator.d.ts +3 -0
  20. package/dist/decorators/index.decorator.js +17 -0
  21. package/dist/decorators/index.decorator.js.map +1 -0
  22. package/dist/decorators/one-many.decorator.d.ts +3 -0
  23. package/dist/decorators/one-many.decorator.js +17 -0
  24. package/dist/decorators/one-many.decorator.js.map +1 -0
  25. package/dist/decorators/primary-key.decorator.d.ts +2 -0
  26. package/dist/decorators/primary-key.decorator.js +6 -0
  27. package/dist/decorators/primary-key.decorator.js.map +1 -0
  28. package/dist/decorators/property.decorator.d.ts +15 -0
  29. package/dist/decorators/property.decorator.js +25 -0
  30. package/dist/decorators/property.decorator.js.map +1 -0
  31. package/dist/domain/base-entity.d.ts +42 -0
  32. package/dist/domain/base-entity.js +106 -0
  33. package/dist/domain/base-entity.js.map +1 -0
  34. package/dist/domain/collection.d.ts +6 -0
  35. package/dist/domain/collection.js +11 -0
  36. package/dist/domain/collection.js.map +1 -0
  37. package/dist/domain/entities.d.ts +40 -0
  38. package/dist/domain/entities.js +137 -0
  39. package/dist/domain/entities.js.map +1 -0
  40. package/dist/domain/reference.d.ts +4 -0
  41. package/dist/domain/reference.js +7 -0
  42. package/dist/domain/reference.js.map +1 -0
  43. package/dist/driver/driver.interface.d.ts +270 -0
  44. package/dist/driver/driver.interface.js +2 -0
  45. package/dist/driver/driver.interface.js.map +1 -0
  46. package/dist/driver/pg-driver.d.ts +43 -0
  47. package/dist/driver/pg-driver.js +255 -0
  48. package/dist/driver/pg-driver.js.map +1 -0
  49. package/dist/index.d.ts +13 -0
  50. package/dist/index.js +16 -0
  51. package/dist/index.js.map +1 -0
  52. package/dist/migration/diff-calculator.d.ts +17 -0
  53. package/dist/migration/diff-calculator.js +230 -0
  54. package/dist/migration/diff-calculator.js.map +1 -0
  55. package/dist/migration/migrator.d.ts +18 -0
  56. package/dist/migration/migrator.js +233 -0
  57. package/dist/migration/migrator.js.map +1 -0
  58. package/dist/orm.d.ts +14 -0
  59. package/dist/orm.js +23 -0
  60. package/dist/orm.js.map +1 -0
  61. package/dist/orm.service.d.ts +8 -0
  62. package/dist/orm.service.js +115 -0
  63. package/dist/orm.service.js.map +1 -0
  64. package/dist/utils.d.ts +1 -0
  65. package/dist/utils.js +16 -0
  66. package/dist/utils.js.map +1 -0
  67. package/package.json +50 -0
  68. package/src/SqlBuilder.ts +542 -0
  69. package/src/cheetah.ts +28 -0
  70. package/src/constants.ts +4 -0
  71. package/src/decorators/entity.decorator.ts +10 -0
  72. package/src/decorators/index.decorator.ts +18 -0
  73. package/src/decorators/one-many.decorator.ts +19 -0
  74. package/src/decorators/primary-key.decorator.ts +6 -0
  75. package/src/decorators/property.decorator.ts +41 -0
  76. package/src/domain/base-entity.ts +149 -0
  77. package/src/domain/collection.ts +10 -0
  78. package/src/domain/entities.ts +159 -0
  79. package/src/domain/reference.ts +5 -0
  80. package/src/driver/driver.interface.ts +331 -0
  81. package/src/driver/pg-driver.ts +308 -0
  82. package/src/index.ts +17 -0
  83. package/src/migration/diff-calculator.ts +258 -0
  84. package/src/migration/migrator.ts +278 -0
  85. package/src/orm.service.ts +115 -0
  86. package/src/orm.ts +30 -0
  87. package/src/utils.ts +18 -0
  88. package/test/domain/base-entity.spec.ts +463 -0
  89. package/test/migration/.sql +5 -0
  90. package/test/migration/cheetah.config.ts +13 -0
  91. package/test/migration/migator.spec.ts +251 -0
  92. package/test/migration/test.sql +5 -0
  93. package/test/node-database.ts +32 -0
@@ -0,0 +1,149 @@
1
+ import { SqlBuilder } from '../SqlBuilder';
2
+ import { FilterQuery, FindOneOption, FindOptions, InstanceOf } from '../driver/driver.interface';
3
+
4
+ export abstract class BaseEntity {
5
+ private _oldValues: any = {};
6
+ private _changedValues: any = {};
7
+ private $_isPersisted: boolean = false;
8
+
9
+ constructor() {
10
+ return new Proxy(this, {
11
+ set(target: any, p: string, newValue: any): boolean {
12
+
13
+ if (p.startsWith('$')) {
14
+ target[p] = newValue;
15
+ return true;
16
+ }
17
+
18
+ // se oldvalue não existir, é porque é a primeira vez que o atributo está sendo setado
19
+ if (!target._oldValues[p]) {
20
+ target._oldValues[p] = newValue;
21
+ }
22
+
23
+ // se o valor for diferente do valor antigo, é porque o valor foi alterado
24
+ if (target._oldValues[p] !== newValue) {
25
+ target._changedValues[p] = newValue;
26
+ }
27
+
28
+ target[p] = newValue;
29
+
30
+ return true;
31
+ },
32
+ })
33
+ }
34
+
35
+ /**
36
+ * Gets current entity's Repository.
37
+ */
38
+ static createQueryBuilder<T>(
39
+ this: { new(): T } & typeof BaseEntity,
40
+ ): SqlBuilder<T> {
41
+ return new SqlBuilder<T>(this);
42
+ }
43
+
44
+ /**
45
+ * Gets current entity's Repository.
46
+ */
47
+ private createQueryBuilder<T>(): SqlBuilder<T> {
48
+ // @ts-ignore
49
+ return new SqlBuilder<T>(this.constructor);
50
+ }
51
+
52
+ static async find<T, Hint extends string = never>(
53
+ this: { new(): T } & typeof BaseEntity,
54
+ where: FilterQuery<T>,
55
+ options?: FindOptions<T, Hint>
56
+ ): Promise<T[]> {
57
+ return this.createQueryBuilder<T>()
58
+ .select(options?.fields as any)
59
+ .where(where)
60
+ .limit(options?.limit)
61
+ .offset(options?.offset)
62
+ .orderBy(options?.orderBy as string[])
63
+ .executeAndReturnAll();
64
+ }
65
+
66
+ static async findOne<T, Hint extends string = never>(
67
+ this: { new(): T } & typeof BaseEntity,
68
+ where: FilterQuery<T>,
69
+ options?: FindOneOption<T, Hint>
70
+ ): Promise<T | undefined> {
71
+ return this.createQueryBuilder<T>()
72
+ .select(options?.fields as any)
73
+ .where(where)
74
+ .executeAndReturnFirst();
75
+ }
76
+
77
+ /**
78
+ * Find a record in the database based on the provided query where and return it, or throw an error if not found.
79
+ *
80
+ * @param {FilterQuery<T>} where - The query where used to search for the record.
81
+ * @param options
82
+ * @return {Promise<T>} - A promise that resolves with the found record.
83
+ */
84
+ static async findOneOrFail<T, Hint extends string = never>(
85
+ this: { new(): T } & typeof BaseEntity,
86
+ where: FilterQuery<T>,
87
+ options?: FindOneOption<T, Hint>
88
+ ): Promise<T> {
89
+ return this.createQueryBuilder<T>()
90
+ // @ts-ignore
91
+ .select(options?.fields)
92
+ .where(where)
93
+ .orderBy(options?.orderBy as string[])
94
+ .executeAndReturnFirstOrFail();
95
+ }
96
+
97
+ static async findAll<
98
+ T extends object,
99
+ Hint extends string = never
100
+ >(
101
+ this: { new(): T } & typeof BaseEntity,
102
+ options: FindOptions<T, Hint>
103
+ ): Promise<T[]> {
104
+ const builder = this.createQueryBuilder<T>()
105
+ .select(options.fields as any)
106
+ .offset(options?.offset)
107
+ .limit(options.limit)
108
+ .orderBy(options?.orderBy as string[]);
109
+
110
+ return builder.executeAndReturnAll();
111
+ }
112
+
113
+ static async create<T extends BaseEntity>(
114
+ this: { new(): T } & typeof BaseEntity,
115
+ where: Partial<InstanceOf<T>>,
116
+ ): Promise<T> {
117
+ return this.createQueryBuilder<T>()
118
+ .insert(where)
119
+ .executeAndReturnFirstOrFail();
120
+ }
121
+
122
+ static getTableName(): string {
123
+ if ('tableName' in this) {
124
+ return (this as any).tableName;
125
+ }
126
+
127
+ return this.name.toLowerCase();
128
+ }
129
+
130
+ public async save() {
131
+ const qb = this.createQueryBuilder()
132
+
133
+ if (this.$_isPersisted) {
134
+ qb.update(this._changedValues)
135
+ // @ts-ignore
136
+ .where({id: this._oldValues.id})
137
+ } else {
138
+ qb.insert(this._oldValues)
139
+ }
140
+
141
+ await qb.execute()
142
+
143
+ this._oldValues = {
144
+ ...this._oldValues,
145
+ ...this._changedValues,
146
+ }
147
+ this._changedValues = {}
148
+ }
149
+ }
@@ -0,0 +1,10 @@
1
+ export class ArrayCollection<T extends object, O extends object> {
2
+ getItems(): T[] {
3
+ return [];
4
+ }
5
+ }
6
+ export class Collection<T extends object, O extends object = object> extends ArrayCollection<T, O> {
7
+ constructor(owner: O, items?: T[], initialized = true) {
8
+ super();
9
+ }
10
+ }
@@ -0,0 +1,159 @@
1
+ import { Metadata, Service } from '@cheetah.js/core';
2
+ import { PropertyOptions } from '../decorators/property.decorator';
3
+ import { ColumnsInfo, Relationship, SnapshotIndexInfo, SnapshotTable } from '../driver/driver.interface';
4
+ import { getDefaultLength } from '../utils';
5
+
6
+ export type Property = {
7
+ options: PropertyOptions;
8
+ type: Function;
9
+ }
10
+
11
+ export type Options = {
12
+ showProperties: { [key: string]: Property };
13
+ hideProperties: string[];
14
+ indexes?: SnapshotIndexInfo[];
15
+ relations: Relationship<any>[];
16
+ tableName: string;
17
+ schema?: string;
18
+ }
19
+
20
+ @Service()
21
+ export class EntityStorage {
22
+ static instance: EntityStorage;
23
+
24
+ private entities: Map<Function, Options> = new Map();
25
+
26
+ constructor() {
27
+ EntityStorage.instance = this;
28
+ }
29
+
30
+ add(entity: { target: Function, options: any }, properties: {[key: string]: Property}, relations: Relationship<any>[]) {
31
+ const entityName = entity.options?.tableName || entity.target.name.toLowerCase();
32
+ const indexes = Metadata.get('indexes', entity.target) || [];
33
+ this.entities.set(entity.target, {
34
+ showProperties: properties,
35
+ hideProperties: [],
36
+ relations,
37
+ indexes: indexes.map((index: {name: string, properties: string[]}) => {
38
+ return {
39
+ table: entityName,
40
+ indexName: index.name.replace('[TABLE]', entityName),
41
+ columnName: index.properties.join(','),
42
+ }
43
+ }),
44
+ tableName: entityName,
45
+ ...entity.options
46
+ })
47
+ }
48
+
49
+ get(entity: Function) {
50
+ return this.entities.get(entity);
51
+ }
52
+
53
+ entries() {
54
+ return this.entities.entries();
55
+ }
56
+
57
+ static getInstance() {
58
+ return EntityStorage.instance;
59
+ }
60
+
61
+ async snapshot(values: Options): Promise<SnapshotTable> {
62
+ return {
63
+ tableName: values.tableName,
64
+ schema: values.schema || 'public',
65
+ indexes: values.indexes || [],
66
+ columns: this.snapshotColumns(values),
67
+ }
68
+ }
69
+
70
+ private snapshotColumns(values: Options): ColumnsInfo[] {
71
+
72
+ let properties: ColumnsInfo[] = Object.entries(values.showProperties).map(([key, value]) => {
73
+ return {
74
+ name: key,
75
+ type: value.type.name,
76
+ nullable: value.options?.nullable,
77
+ default: value.options?.default,
78
+ primary: value.options?.isPrimary,
79
+ unique: value.options?.unique,
80
+ length: value.options?.length,
81
+ }
82
+ })
83
+ // @ts-ignore
84
+ let relations: ColumnsInfo[] = values.relations && values.relations.map((relation) => {
85
+ const type = this.getFkType(relation)
86
+
87
+ return {
88
+ name: relation.propertyKey as string,
89
+ type,
90
+ nullable: relation.nullable,
91
+ unique: relation.unique,
92
+ length: relation.length || getDefaultLength(type),
93
+ default: relation.default,
94
+ primary: relation.isPrimary,
95
+ foreignKeys: [
96
+ {
97
+ referencedColumnName: this.getFkKey(relation),
98
+ referencedTableName: this.get(relation.entity() as any)!.tableName,
99
+ }
100
+ ]
101
+ }
102
+ })
103
+
104
+ if (!relations) {
105
+ relations = []
106
+ }
107
+ if (!properties) {
108
+ properties = []
109
+ }
110
+
111
+ return [...properties, ...relations]
112
+ }
113
+
114
+ private snapshotIndexes(values: Options): SnapshotIndexInfo[] {
115
+ return Object.entries(values.showProperties).map(([key, value]) => {
116
+ return {
117
+ indexName: key,
118
+ columnName: key,
119
+ table: values.tableName,
120
+ }
121
+ })
122
+ }
123
+
124
+ private getFkType(relation: Relationship<any>): any {
125
+ const entity = this.get(relation.entity() as any)
126
+ if (!entity) {
127
+ return 'unknown'
128
+ }
129
+
130
+ return entity.showProperties[this.getFkKey(relation)].type.name
131
+ }
132
+
133
+ /**
134
+ * If fkKey is null, return the primary key of the entity
135
+ * @private
136
+ * @param relationShip
137
+ */
138
+ private getFkKey(relationShip: Relationship<any>): string | number {
139
+ // se for nullable, deverá retornar o primary key da entidade target
140
+ if (typeof relationShip.fkKey === 'undefined') {
141
+ const entity = this.entities.get(relationShip.entity() as any);
142
+ const property = Object.entries(entity!.showProperties).find(([key, value]) => value.options.isPrimary === true);
143
+ if (!property) {
144
+ throw new Error(`Entity ${entity!.tableName} does not have a primary key`);
145
+ }
146
+
147
+ return property[0];
148
+ }
149
+
150
+ // se o fkKey é uma função, ele retornará a propriedade da entidade que é a chave estrangeira
151
+ // precisamos pegar o nome dessa propriedade
152
+ if (typeof relationShip.fkKey === 'string') {
153
+ return relationShip.fkKey;
154
+ }
155
+
156
+ const match = /\.(?<propriedade>[\w]+)/.exec(relationShip.fkKey.toString());
157
+ return match ? match.groups!.propriedade : '';
158
+ }
159
+ }
@@ -0,0 +1,5 @@
1
+ export class Reference<T> {
2
+ constructor(private entity: T) {
3
+ console.log('Reference constructor')
4
+ }
5
+ }
@@ -0,0 +1,331 @@
1
+ import { PropertyOptions } from '../decorators/property.decorator';
2
+ import { Collection } from '../domain/collection';
3
+ import { Reference } from '../domain/reference';
4
+
5
+ export interface DriverInterface {
6
+ connectionString: string;
7
+ executeStatement(statement: Statement<any>): Promise<{ query: any, startTime: number, sql: string }>;
8
+ connect(): Promise<void>;
9
+ disconnect(): Promise<void>;
10
+ executeSql(s: string): Promise<any>;
11
+ snapshot(tableName: string, options: any): Promise<SnapshotTable | undefined>;
12
+
13
+ getCreateTableInstruction(schema: string | undefined, tableName: string, creates: ColDiff[]): string;
14
+ getAlterTableFkInstruction(schema: string | undefined, tableName: string, colDiff: ColDiff, fk: ForeignKeyInfo) : string;
15
+ getCreateIndex(index: { name: string; properties?: string[] }, schema: string | undefined, tableName: string): string;
16
+ getAddColumn(schema: string | undefined, tableName: string, colName: string, colDiff: ColDiff, colDiffInstructions: string[]): void;
17
+ getDropColumn(colDiffInstructions: string[], schema: string | undefined, tableName: string, colName: string): void;
18
+
19
+ getDropIndex(index: {name: string; properties?: string[]}, schema: string | undefined, tableName: string): string;
20
+
21
+ getAlterTableType(schema: string | undefined, tableName: string, colName: string, colDiff: ColDiff): string;
22
+
23
+ getAlterTableDefaultInstruction(schema: string | undefined, tableName: string, colName: string, colDiff: ColDiff): string;
24
+
25
+ getAlterTablePrimaryKeyInstruction(schema: string | undefined, tableName: string, colName: string, colDiff: ColDiff): string;
26
+
27
+ getDropConstraint(param: {name: string}, schema: string | undefined, tableName: string): string;
28
+
29
+ getAddUniqueConstraint(schema: string | undefined, tableName: string, colName: string): string;
30
+
31
+ getAlterTableDropNullInstruction(schema: string | undefined, tableName: string, colName: string, colDiff: ColDiff): string;
32
+
33
+ getAlterTableDropNotNullInstruction(schema: string | undefined, tableName: string, colName: string, colDiff: ColDiff): string;
34
+
35
+ startTransaction(): Promise<void>;
36
+ commitTransaction(): Promise<void>;
37
+ rollbackTransaction(): Promise<void>;
38
+ }
39
+
40
+ export type SnapshotConstraintInfo = {
41
+ indexName: string;
42
+ consDef: string;
43
+ type: string;
44
+ }
45
+
46
+ export interface ConnectionSettings<T extends DriverInterface = DriverInterface> {
47
+ host?: string;
48
+ port?: number;
49
+ username?: string;
50
+ password?: string;
51
+ database?: string;
52
+ connectionString?: string;
53
+ ssl?: boolean;
54
+ driver: T;
55
+ entities?: Function[] | string;
56
+ migrationPath?: string;
57
+ }
58
+
59
+ export type ConditionOperators<T, C> = {
60
+ $ne?: T;
61
+ $in?: T[];
62
+ $nin?: T[];
63
+ $like?: string;
64
+ $gt?: T;
65
+ $gte?: T;
66
+ $lt?: T;
67
+ $lte?: T;
68
+
69
+ $and?: Condition<C>[];
70
+ $or?: Condition<C>[];
71
+ // adicione aqui os demais operadores que precisar
72
+ };
73
+
74
+ export type Condition<T> = {
75
+ [P in keyof T]?: T[P] | ConditionOperators<T[P], T>;
76
+ };
77
+
78
+ export type InstanceOf<T> = {
79
+ [key in keyof T]: T[key]
80
+ };
81
+
82
+ export type JoinStatement<T> = {
83
+ type: 'INNER' | 'LEFT' | 'RIGHT';
84
+ originalEntity?: Function;
85
+ originTable: string;
86
+ originSchema: string;
87
+ originAlias: string;
88
+ joinTable: string;
89
+ joinSchema: string;
90
+ joinAlias: string;
91
+ joinEntity?: Function;
92
+ joinWhere?: string;
93
+ joinProperty: string;
94
+ on: string;
95
+ propertyKey: string | symbol;
96
+ };
97
+
98
+ export type Statement<T> = {
99
+ statement?: 'select' | 'insert' | 'update' | 'delete';
100
+ table?: string;
101
+ alias?: string;
102
+ columns?: Array<keyof T>;
103
+ join?: JoinStatement<T>[];
104
+ where?: string;
105
+ values?: any;
106
+ groupBy?: string[];
107
+ orderBy?: string[];
108
+ limit?: number;
109
+ offset?: number;
110
+ }
111
+
112
+ interface SnapshotColumnInfo {
113
+ table_catalog: string;
114
+ table_schema: string;
115
+ table_name: string;
116
+ column_name: string;
117
+ ordinal_position: number;
118
+ column_default: string | null;
119
+ is_nullable: string;
120
+ data_type: string;
121
+ character_maximum_length: number | null;
122
+ character_octet_length: number | null;
123
+ numeric_precision: number | null;
124
+ numeric_scale: number | null;
125
+ datetime_precision: number | null;
126
+ character_set_name: string | null;
127
+ collation_name: string | null;
128
+ column_type: string;
129
+ column_key: string;
130
+ extra: string;
131
+ privileges: string;
132
+ column_comment: string;
133
+ }
134
+
135
+ export type SnapshotTable = {
136
+ tableName: string;
137
+ schema?: string;
138
+ columns: ColumnsInfo[];
139
+ indexes: SnapshotIndexInfo[];
140
+ foreignKeys?: ForeignKeyInfo[];
141
+ }
142
+
143
+ export type SnapshotIndexInfo = {
144
+ table: string;
145
+ indexName: string;
146
+ columnName: string;
147
+ }
148
+
149
+ export type ForeignKeyInfo = {
150
+ referencedTableName: string;
151
+ referencedColumnName: string;
152
+ }
153
+
154
+ export type ColumnsInfo = {
155
+ name: string;
156
+ type: string;
157
+ nullable?: boolean;
158
+ default?: string | null;
159
+ primary?: boolean;
160
+ unique?: boolean;
161
+ length?: number;
162
+ foreignKeys?: ForeignKeyInfo[];
163
+ }
164
+
165
+ export type SqlActionType = 'CREATE' | 'DELETE' | 'ALTER' | 'INDEX';
166
+
167
+ export type ColDiff = {
168
+ actionType: SqlActionType;
169
+ colName: string;
170
+ colType?: string;
171
+ colLength?: number;
172
+ indexTables?: { name: string, properties?: string[] }[];
173
+ colChanges?: {
174
+ default?: string | null;
175
+ primary?: boolean;
176
+ unique?: boolean;
177
+ nullable?: boolean;
178
+ foreignKeys?: ForeignKeyInfo[];
179
+ };
180
+ }
181
+
182
+ export type TableDiff = {
183
+ tableName: string;
184
+ schema?: string;
185
+ newTable?: boolean;
186
+ colDiffs: ColDiff[];
187
+ }
188
+
189
+ export declare const PrimaryKeyType: unique symbol;
190
+ export declare const PrimaryKeyProp: unique symbol;
191
+ type ReadonlyPrimary<T> = T extends any[] ? Readonly<T> : T;
192
+ export type Primary<T> = T extends {
193
+ [PrimaryKeyType]?: infer PK;
194
+ } ? ReadonlyPrimary<PK> : T extends {
195
+ _id?: infer PK;
196
+ } ? ReadonlyPrimary<PK> | string : T extends {
197
+ uuid?: infer PK;
198
+ } ? ReadonlyPrimary<PK> : T extends {
199
+ id?: infer PK;
200
+ } ? ReadonlyPrimary<PK> : never;
201
+ export type PrimaryProperty<T> = T extends {
202
+ [PrimaryKeyProp]?: infer PK;
203
+ } ? PK : T extends {
204
+ _id?: any;
205
+ } ? '_id' | string : T extends {
206
+ uuid?: any;
207
+ } ? 'uuid' : T extends {
208
+ id?: any;
209
+ } ? 'id' : never;
210
+ export type IPrimaryKeyValue = number | string | bigint | Date | {
211
+ toHexString(): string;
212
+ };
213
+ export type IPrimaryKey<T extends IPrimaryKeyValue = IPrimaryKeyValue> = T;
214
+ export type OperatorMap<T> = {
215
+ $and?: Query<T>[];
216
+ $or?: Query<T>[];
217
+ $eq?: ExpandScalar<T> | ExpandScalar<T>[];
218
+ $ne?: ExpandScalar<T>;
219
+ $in?: ExpandScalar<T>[];
220
+ $nin?: ExpandScalar<T>[];
221
+ $not?: Query<T>;
222
+ $gt?: ExpandScalar<T>;
223
+ $gte?: ExpandScalar<T>;
224
+ $lt?: ExpandScalar<T>;
225
+ $lte?: ExpandScalar<T>;
226
+ $like?: string;
227
+
228
+ };
229
+ export type ExcludeFunctions<T, K extends keyof T> = T[K] extends Function ? never : (K extends symbol ? never : K);
230
+ export type Scalar = boolean | number | string | bigint | symbol | Date | RegExp | Uint8Array | {
231
+ toHexString(): string;
232
+ };
233
+ //TODO: editar
234
+ export type ExpandProperty<T> = T extends (infer U)[] ? NonNullable<U> : NonNullable<T> ;
235
+ export type ExpandScalar<T> = null | (T extends string ? T | RegExp : T extends Date ? Date | string : T);
236
+ type ExpandObject<T> = T extends object ? T extends Scalar ? never : {
237
+ -readonly [K in keyof T as ExcludeFunctions<T, K>]?: Query<ExpandProperty<T[K]>> | FilterValue<ExpandProperty<T[K]>> | null;
238
+ } : never;
239
+ export type EntityProps<T> = {
240
+ -readonly [K in keyof T as ExcludeFunctions<T, K>]?: T[K];
241
+ };
242
+ export type Query<T> = T extends object ? T extends Scalar ? never : FilterQuery<T> : FilterValue<T>;
243
+ export type FilterValue2<T> = T | ExpandScalar<T> | Primary<T>;
244
+ export type FilterValue<T> = OperatorMap<FilterValue2<T>> | FilterValue2<T> | FilterValue2<T>[] | null;
245
+ export type EntityClass<T> = Function & { prototype: T };
246
+ export type EntityName<T> = string | EntityClass<T> | { name: string };
247
+ export type ObjectQuery<T> = ExpandObject<T> & OperatorMap<T>;
248
+ export type FilterQuery<T> = ObjectQuery<T> | NonNullable<ExpandScalar<Primary<T>>> | NonNullable<EntityProps<T> & OperatorMap<T>> | FilterQuery<T>[];
249
+
250
+ export type Relationship<T> = {
251
+ isRelation?: boolean;
252
+ relation: 'one-to-many' | 'many-to-one';
253
+ type: Function;
254
+ fkKey?: (string & keyof T) | ((e: T) => any);
255
+ entity: () => EntityName<T>;
256
+ originalEntity?: EntityName<T>;
257
+ propertyKey: string | symbol;
258
+ } & Partial<PropertyOptions>;
259
+
260
+ export type Cast<T, R> = T extends R ? T : R;
261
+ export type IsUnknown<T> = T extends unknown ? unknown extends T ? true : never : never;
262
+ export type IdentifiedReference<T, PK extends keyof T | unknown = PrimaryProperty<T>> = true extends IsUnknown<PK> ? Reference<T> : ({
263
+ [K in Cast<PK, keyof T>]: T[K];
264
+ } & Reference<T>);
265
+ export type Ref<T, PK extends keyof T | unknown = PrimaryProperty<T>> = IdentifiedReference<T, PK>;
266
+ type Loadable<T extends object> = Collection<T, any> | Reference<T> | readonly T[];
267
+ type ExtractType<T> = T extends Loadable<infer U> ? U : T;
268
+ type StringKeys<T, E extends string = never> = T extends Collection<any, any> ? `${Exclude<keyof ExtractType<T> | E, symbol>}` : T extends Ref<any> ? `${Exclude<keyof ExtractType<T> | E, symbol>}` : T extends object ? `${Exclude<keyof ExtractType<T> | E, symbol>}` : never;
269
+ type Defined<T> = Exclude<T, null | undefined>;
270
+ type GetStringKey<T, K extends StringKeys<T, string>, E extends string> = K extends keyof T ? ExtractType<T[K]> : (K extends E ? keyof T : never);
271
+ type Prev = [never, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
272
+ export type AutoPath<
273
+ O,
274
+ P extends string,
275
+ E extends string = never,
276
+ D extends Prev[number] = 5
277
+ > = [D] extends [never]
278
+ ? string
279
+ : P extends any
280
+ ? (P & `${string}.` extends never
281
+ ? P
282
+ : P & `${string}.`) extends infer Q
283
+ ? Q extends `${infer A}.${infer B}`
284
+ ? A extends StringKeys<O, E>
285
+ ? `${A}.${AutoPath<Defined<GetStringKey<O, A, E>>, B, E, Prev[D]>}`
286
+ : never
287
+ : Q extends StringKeys<O, E>
288
+ ? (Defined<GetStringKey<O, Q, E>> extends unknown
289
+ ? Exclude<P, `${string}.`>
290
+ : never) | (StringKeys<Defined<GetStringKey<O, Q, E>>, E> extends never
291
+ ? never
292
+ : `${Q}.`)
293
+ : keyof ExtractType<O>
294
+ : never
295
+ : never;
296
+
297
+ export declare enum QueryOrder {
298
+ ASC = "ASC",
299
+ ASC_NULLS_LAST = "ASC NULLS LAST",
300
+ ASC_NULLS_FIRST = "ASC NULLS FIRST",
301
+ DESC = "DESC",
302
+ DESC_NULLS_LAST = "DESC NULLS LAST",
303
+ DESC_NULLS_FIRST = "DESC NULLS FIRST",
304
+ asc = "asc",
305
+ asc_nulls_last = "asc nulls last",
306
+ asc_nulls_first = "asc nulls first",
307
+ desc = "desc",
308
+ desc_nulls_last = "desc nulls last",
309
+ desc_nulls_first = "desc nulls first"
310
+ }
311
+ export declare enum QueryOrderNumeric {
312
+ ASC = 1,
313
+ DESC = -1
314
+ }
315
+ export type QueryOrderKeysFlat = QueryOrder | QueryOrderNumeric | keyof typeof QueryOrder;
316
+ export type QueryOrderKeys<T> = QueryOrderKeysFlat | QueryOrderMap<T>;
317
+ export type QueryOrderMap<T> = {
318
+ [K in keyof T as ExcludeFunctions<T, K>]?: QueryOrderKeys<ExpandProperty<T[K]>>;
319
+ };
320
+ export type EntityField<T, P extends string = never> = AutoPath<T, P, '*'>;
321
+ export interface FindOptions<T, P extends string = never> {
322
+ // populate?: readonly AutoPath<T, P>[] | boolean;
323
+ orderBy?: (QueryOrderMap<T> & {
324
+ 0?: never;
325
+ }) | QueryOrderMap<T>[];
326
+ // cache?: boolean | number | [string, number];
327
+ limit?: number;
328
+ offset?: number;
329
+ fields?: readonly EntityField<T, P>[];
330
+ }
331
+ export type FindOneOption<T, P extends string = never> = Omit<FindOptions<T, P>, 'limit'|'offset'>