@cheetah.js/orm 0.1.46 → 0.1.47
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/dist/SqlBuilder.js +8 -3
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/repository/Repository.d.ts +125 -0
- package/dist/repository/Repository.js +150 -0
- package/package.json +2 -2
package/dist/SqlBuilder.js
CHANGED
|
@@ -202,9 +202,14 @@ export class SqlBuilder {
|
|
|
202
202
|
}
|
|
203
203
|
mapObjectKey(obj, key, parentKey) {
|
|
204
204
|
const fullKey = parentKey ? `${parentKey}.${key}` : key;
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
205
|
+
if (this.isNestedObject(obj[key])) {
|
|
206
|
+
return this.objectToStringMap(obj[key], fullKey);
|
|
207
|
+
}
|
|
208
|
+
if (parentKey) {
|
|
209
|
+
return [`${this.columnManager.discoverAlias(fullKey, true)} ${obj[key]}`];
|
|
210
|
+
}
|
|
211
|
+
const columnName = ValueProcessor.getColumnName(key, this.entity);
|
|
212
|
+
return [`${this.columnManager.discoverAlias(columnName, true)} ${obj[key]}`];
|
|
208
213
|
}
|
|
209
214
|
isNestedObject(value) {
|
|
210
215
|
return typeof value === 'object' && value !== null;
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { BaseEntity } from '../domain/base-entity';
|
|
2
|
+
import { SqlBuilder } from '../SqlBuilder';
|
|
3
|
+
import { FilterQuery, ValueOrInstance } from '../driver/driver.interface';
|
|
4
|
+
/**
|
|
5
|
+
* Generic Repository class for database operations.
|
|
6
|
+
* Provides type-safe methods for CRUD operations.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```typescript
|
|
10
|
+
* @Service()
|
|
11
|
+
* export class LessonRepository extends Repository<Lesson> {
|
|
12
|
+
* constructor() {
|
|
13
|
+
* super(Lesson);
|
|
14
|
+
* }
|
|
15
|
+
*
|
|
16
|
+
* async findByCourse(courseId: number): Promise<Lesson[]> {
|
|
17
|
+
* return this.find({
|
|
18
|
+
* where: { courseId },
|
|
19
|
+
* order: { orderIndex: 'ASC' }
|
|
20
|
+
* });
|
|
21
|
+
* }
|
|
22
|
+
* }
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
export declare abstract class Repository<T extends BaseEntity> {
|
|
26
|
+
protected readonly entityClass: {
|
|
27
|
+
new (): T;
|
|
28
|
+
} & typeof BaseEntity;
|
|
29
|
+
constructor(entityClass: {
|
|
30
|
+
new (): T;
|
|
31
|
+
} & typeof BaseEntity);
|
|
32
|
+
/**
|
|
33
|
+
* Creates a new query builder for the entity.
|
|
34
|
+
*/
|
|
35
|
+
protected createQueryBuilder(): SqlBuilder<T>;
|
|
36
|
+
/**
|
|
37
|
+
* Finds entities matching the given criteria.
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* ```typescript
|
|
41
|
+
* const lessons = await repository.find({
|
|
42
|
+
* where: { courseId: 1, isPublished: true },
|
|
43
|
+
* order: { orderIndex: 'ASC' },
|
|
44
|
+
* limit: 10
|
|
45
|
+
* });
|
|
46
|
+
* ```
|
|
47
|
+
*/
|
|
48
|
+
find(options: RepositoryFindOptions<T>): Promise<T[]>;
|
|
49
|
+
/**
|
|
50
|
+
* Finds a single entity matching the given criteria.
|
|
51
|
+
* Returns undefined if not found.
|
|
52
|
+
*/
|
|
53
|
+
findOne(options: RepositoryFindOneOptions<T>): Promise<T | undefined>;
|
|
54
|
+
/**
|
|
55
|
+
* Finds a single entity matching the given criteria.
|
|
56
|
+
* Throws an error if not found.
|
|
57
|
+
*/
|
|
58
|
+
findOneOrFail(options: RepositoryFindOneOptions<T>): Promise<T>;
|
|
59
|
+
/**
|
|
60
|
+
* Finds all entities with optional filtering.
|
|
61
|
+
*/
|
|
62
|
+
findAll(options?: Omit<RepositoryFindOptions<T>, 'where'>): Promise<T[]>;
|
|
63
|
+
/**
|
|
64
|
+
* Finds an entity by its primary key.
|
|
65
|
+
*/
|
|
66
|
+
findById(id: number | string): Promise<T | undefined>;
|
|
67
|
+
/**
|
|
68
|
+
* Finds an entity by its primary key.
|
|
69
|
+
* Throws an error if not found.
|
|
70
|
+
*/
|
|
71
|
+
findByIdOrFail(id: number | string): Promise<T>;
|
|
72
|
+
/**
|
|
73
|
+
* Creates a new entity.
|
|
74
|
+
*/
|
|
75
|
+
create(data: Partial<{
|
|
76
|
+
[K in keyof T]: ValueOrInstance<T[K]>;
|
|
77
|
+
}>): Promise<T>;
|
|
78
|
+
/**
|
|
79
|
+
* Updates entities matching the criteria.
|
|
80
|
+
*/
|
|
81
|
+
update(where: FilterQuery<T>, data: Partial<{
|
|
82
|
+
[K in keyof T]: ValueOrInstance<T[K]>;
|
|
83
|
+
}>): Promise<void>;
|
|
84
|
+
/**
|
|
85
|
+
* Updates an entity by its primary key.
|
|
86
|
+
*/
|
|
87
|
+
updateById(id: number | string, data: Partial<{
|
|
88
|
+
[K in keyof T]: ValueOrInstance<T[K]>;
|
|
89
|
+
}>): Promise<void>;
|
|
90
|
+
/**
|
|
91
|
+
* Finds entities for deletion (use with caution).
|
|
92
|
+
* To delete, call .remove() on returned entities or use SQL directly.
|
|
93
|
+
*/
|
|
94
|
+
findForDeletion(where: FilterQuery<T>): Promise<T[]>;
|
|
95
|
+
/**
|
|
96
|
+
* Counts entities matching the criteria.
|
|
97
|
+
*/
|
|
98
|
+
count(where?: FilterQuery<T>): Promise<number>;
|
|
99
|
+
/**
|
|
100
|
+
* Checks if any entity matches the criteria.
|
|
101
|
+
*/
|
|
102
|
+
exists(where: FilterQuery<T>): Promise<boolean>;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Order options for repository queries.
|
|
106
|
+
*/
|
|
107
|
+
export type RepositoryOrderOptions<T> = {
|
|
108
|
+
[K in keyof T]?: 'ASC' | 'DESC';
|
|
109
|
+
};
|
|
110
|
+
/**
|
|
111
|
+
* Find options for repository queries.
|
|
112
|
+
*/
|
|
113
|
+
export interface RepositoryFindOptions<T> {
|
|
114
|
+
where?: FilterQuery<T>;
|
|
115
|
+
order?: RepositoryOrderOptions<T>;
|
|
116
|
+
limit?: number;
|
|
117
|
+
offset?: number;
|
|
118
|
+
fields?: readonly (keyof T)[];
|
|
119
|
+
load?: readonly string[];
|
|
120
|
+
loadStrategy?: 'select' | 'joined';
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Find one options for repository queries.
|
|
124
|
+
*/
|
|
125
|
+
export type RepositoryFindOneOptions<T> = Omit<RepositoryFindOptions<T>, 'limit' | 'offset'>;
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generic Repository class for database operations.
|
|
3
|
+
* Provides type-safe methods for CRUD operations.
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* ```typescript
|
|
7
|
+
* @Service()
|
|
8
|
+
* export class LessonRepository extends Repository<Lesson> {
|
|
9
|
+
* constructor() {
|
|
10
|
+
* super(Lesson);
|
|
11
|
+
* }
|
|
12
|
+
*
|
|
13
|
+
* async findByCourse(courseId: number): Promise<Lesson[]> {
|
|
14
|
+
* return this.find({
|
|
15
|
+
* where: { courseId },
|
|
16
|
+
* order: { orderIndex: 'ASC' }
|
|
17
|
+
* });
|
|
18
|
+
* }
|
|
19
|
+
* }
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
export class Repository {
|
|
23
|
+
constructor(entityClass) {
|
|
24
|
+
this.entityClass = entityClass;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Creates a new query builder for the entity.
|
|
28
|
+
*/
|
|
29
|
+
createQueryBuilder() {
|
|
30
|
+
return this.entityClass.createQueryBuilder();
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Finds entities matching the given criteria.
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* ```typescript
|
|
37
|
+
* const lessons = await repository.find({
|
|
38
|
+
* where: { courseId: 1, isPublished: true },
|
|
39
|
+
* order: { orderIndex: 'ASC' },
|
|
40
|
+
* limit: 10
|
|
41
|
+
* });
|
|
42
|
+
* ```
|
|
43
|
+
*/
|
|
44
|
+
async find(options) {
|
|
45
|
+
const { where, order, limit, offset, fields, load, loadStrategy } = options;
|
|
46
|
+
return this.entityClass.find(where || {}, {
|
|
47
|
+
orderBy: order,
|
|
48
|
+
limit,
|
|
49
|
+
offset,
|
|
50
|
+
fields: fields,
|
|
51
|
+
load: load,
|
|
52
|
+
loadStrategy,
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Finds a single entity matching the given criteria.
|
|
57
|
+
* Returns undefined if not found.
|
|
58
|
+
*/
|
|
59
|
+
async findOne(options) {
|
|
60
|
+
const { where, order, fields, load, loadStrategy } = options;
|
|
61
|
+
return this.entityClass.findOne(where || {}, {
|
|
62
|
+
orderBy: order,
|
|
63
|
+
fields: fields,
|
|
64
|
+
load: load,
|
|
65
|
+
loadStrategy,
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Finds a single entity matching the given criteria.
|
|
70
|
+
* Throws an error if not found.
|
|
71
|
+
*/
|
|
72
|
+
async findOneOrFail(options) {
|
|
73
|
+
const { where, order, fields, load, loadStrategy } = options;
|
|
74
|
+
return this.entityClass.findOneOrFail(where || {}, {
|
|
75
|
+
orderBy: order,
|
|
76
|
+
fields: fields,
|
|
77
|
+
load: load,
|
|
78
|
+
loadStrategy,
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Finds all entities with optional filtering.
|
|
83
|
+
*/
|
|
84
|
+
async findAll(options) {
|
|
85
|
+
const { order, limit, offset, fields, load, loadStrategy } = options || {};
|
|
86
|
+
return this.entityClass.findAll({
|
|
87
|
+
orderBy: order,
|
|
88
|
+
limit,
|
|
89
|
+
offset,
|
|
90
|
+
fields: fields,
|
|
91
|
+
load: load,
|
|
92
|
+
loadStrategy,
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Finds an entity by its primary key.
|
|
97
|
+
*/
|
|
98
|
+
async findById(id) {
|
|
99
|
+
return this.findOne({ where: { id } });
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Finds an entity by its primary key.
|
|
103
|
+
* Throws an error if not found.
|
|
104
|
+
*/
|
|
105
|
+
async findByIdOrFail(id) {
|
|
106
|
+
return this.findOneOrFail({ where: { id } });
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Creates a new entity.
|
|
110
|
+
*/
|
|
111
|
+
async create(data) {
|
|
112
|
+
return this.entityClass.create(data);
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Updates entities matching the criteria.
|
|
116
|
+
*/
|
|
117
|
+
async update(where, data) {
|
|
118
|
+
await this.createQueryBuilder()
|
|
119
|
+
.update(data)
|
|
120
|
+
.where(where)
|
|
121
|
+
.execute();
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Updates an entity by its primary key.
|
|
125
|
+
*/
|
|
126
|
+
async updateById(id, data) {
|
|
127
|
+
await this.update({ id }, data);
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Finds entities for deletion (use with caution).
|
|
131
|
+
* To delete, call .remove() on returned entities or use SQL directly.
|
|
132
|
+
*/
|
|
133
|
+
async findForDeletion(where) {
|
|
134
|
+
return this.find({ where });
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Counts entities matching the criteria.
|
|
138
|
+
*/
|
|
139
|
+
async count(where) {
|
|
140
|
+
const results = await this.find({ where: where || {} });
|
|
141
|
+
return results.length;
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Checks if any entity matches the criteria.
|
|
145
|
+
*/
|
|
146
|
+
async exists(where) {
|
|
147
|
+
const count = await this.count(where);
|
|
148
|
+
return count > 0;
|
|
149
|
+
}
|
|
150
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cheetah.js/orm",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.47",
|
|
4
4
|
"description": "A simple ORM for Cheetah.js",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.js",
|
|
@@ -51,5 +51,5 @@
|
|
|
51
51
|
"bun",
|
|
52
52
|
"value-object"
|
|
53
53
|
],
|
|
54
|
-
"gitHead": "
|
|
54
|
+
"gitHead": "5dad3bf3a30252bf126f64cf998d70c4dd9cdd02"
|
|
55
55
|
}
|