@carno.js/orm 0.2.3
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/LICENSE +674 -0
- package/dist/SqlBuilder.d.ts +103 -0
- package/dist/SqlBuilder.js +618 -0
- package/dist/cache/cache-key-generator.d.ts +13 -0
- package/dist/cache/cache-key-generator.js +66 -0
- package/dist/cache/query-cache-manager.d.ts +14 -0
- package/dist/cache/query-cache-manager.js +44 -0
- package/dist/common/email.vo.d.ts +4 -0
- package/dist/common/email.vo.js +11 -0
- package/dist/common/uuid.d.ts +4 -0
- package/dist/common/uuid.js +10 -0
- package/dist/common/value-object.d.ts +95 -0
- package/dist/common/value-object.js +99 -0
- package/dist/constants.d.ts +6 -0
- package/dist/constants.js +9 -0
- package/dist/decorators/computed.decorator.d.ts +1 -0
- package/dist/decorators/computed.decorator.js +12 -0
- package/dist/decorators/entity.decorator.d.ts +3 -0
- package/dist/decorators/entity.decorator.js +12 -0
- package/dist/decorators/enum.decorator.d.ts +2 -0
- package/dist/decorators/enum.decorator.js +16 -0
- package/dist/decorators/event-hook.decorator.d.ts +4 -0
- package/dist/decorators/event-hook.decorator.js +31 -0
- package/dist/decorators/index.decorator.d.ts +17 -0
- package/dist/decorators/index.decorator.js +36 -0
- package/dist/decorators/one-many.decorator.d.ts +6 -0
- package/dist/decorators/one-many.decorator.js +42 -0
- package/dist/decorators/primary-key.decorator.d.ts +2 -0
- package/dist/decorators/primary-key.decorator.js +8 -0
- package/dist/decorators/property.decorator.d.ts +24 -0
- package/dist/decorators/property.decorator.js +44 -0
- package/dist/decorators/unique.decorator.d.ts +9 -0
- package/dist/decorators/unique.decorator.js +44 -0
- package/dist/domain/base-entity.d.ts +57 -0
- package/dist/domain/base-entity.js +198 -0
- package/dist/domain/collection.d.ts +6 -0
- package/dist/domain/collection.js +15 -0
- package/dist/domain/entities.d.ts +49 -0
- package/dist/domain/entities.js +259 -0
- package/dist/domain/reference.d.ts +86 -0
- package/dist/domain/reference.js +86 -0
- package/dist/driver/bun-driver.base.d.ts +72 -0
- package/dist/driver/bun-driver.base.js +270 -0
- package/dist/driver/bun-mysql.driver.d.ts +53 -0
- package/dist/driver/bun-mysql.driver.js +256 -0
- package/dist/driver/bun-pg.driver.d.ts +52 -0
- package/dist/driver/bun-pg.driver.js +263 -0
- package/dist/driver/driver.interface.d.ts +333 -0
- package/dist/driver/driver.interface.js +2 -0
- package/dist/entry.d.ts +2 -0
- package/dist/entry.js +13 -0
- package/dist/identity-map/entity-key-generator.d.ts +10 -0
- package/dist/identity-map/entity-key-generator.js +45 -0
- package/dist/identity-map/entity-registry.d.ts +11 -0
- package/dist/identity-map/entity-registry.js +41 -0
- package/dist/identity-map/identity-map-context.d.ts +9 -0
- package/dist/identity-map/identity-map-context.js +22 -0
- package/dist/identity-map/identity-map-integration.d.ts +5 -0
- package/dist/identity-map/identity-map-integration.js +37 -0
- package/dist/identity-map/identity-map.d.ts +11 -0
- package/dist/identity-map/identity-map.js +35 -0
- package/dist/identity-map/index.d.ts +5 -0
- package/dist/identity-map/index.js +14 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.js +48 -0
- package/dist/middleware/identity-map.middleware.d.ts +4 -0
- package/dist/middleware/identity-map.middleware.js +22 -0
- package/dist/orm-session-context.d.ts +16 -0
- package/dist/orm-session-context.js +22 -0
- package/dist/orm.d.ts +20 -0
- package/dist/orm.js +69 -0
- package/dist/orm.service.d.ts +13 -0
- package/dist/orm.service.js +361 -0
- package/dist/query/index-condition-builder.d.ts +41 -0
- package/dist/query/index-condition-builder.js +235 -0
- package/dist/query/model-transformer.d.ts +27 -0
- package/dist/query/model-transformer.js +201 -0
- package/dist/query/sql-column-manager.d.ts +28 -0
- package/dist/query/sql-column-manager.js +157 -0
- package/dist/query/sql-condition-builder.d.ts +51 -0
- package/dist/query/sql-condition-builder.js +264 -0
- package/dist/query/sql-join-manager.d.ts +39 -0
- package/dist/query/sql-join-manager.js +242 -0
- package/dist/query/sql-subquery-builder.d.ts +20 -0
- package/dist/query/sql-subquery-builder.js +119 -0
- package/dist/repository/Repository.d.ts +121 -0
- package/dist/repository/Repository.js +174 -0
- package/dist/testing/index.d.ts +1 -0
- package/dist/testing/index.js +17 -0
- package/dist/testing/with-database.d.ts +20 -0
- package/dist/testing/with-database.js +311 -0
- package/dist/transaction/transaction-context.d.ts +10 -0
- package/dist/transaction/transaction-context.js +19 -0
- package/dist/utils/value-processor.d.ts +14 -0
- package/dist/utils/value-processor.js +94 -0
- package/dist/utils.d.ts +3 -0
- package/dist/utils.js +24 -0
- package/package.json +59 -0
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SqlSubqueryBuilder = void 0;
|
|
4
|
+
class SqlSubqueryBuilder {
|
|
5
|
+
constructor(entityStorage, getConditionBuilder) {
|
|
6
|
+
this.entityStorage = entityStorage;
|
|
7
|
+
this.getConditionBuilder = getConditionBuilder;
|
|
8
|
+
this.aliasCounter = 1;
|
|
9
|
+
}
|
|
10
|
+
buildExistsSubquery(relationship, filters, outerAlias, negate, outerModel) {
|
|
11
|
+
const prefix = negate ? 'NOT EXISTS' : 'EXISTS';
|
|
12
|
+
const subquery = this.buildSubquery(relationship, filters, outerAlias, outerModel);
|
|
13
|
+
return `${prefix} (${subquery})`;
|
|
14
|
+
}
|
|
15
|
+
buildSubquery(relationship, filters, outerAlias, outerModel) {
|
|
16
|
+
const subqueryAlias = this.generateAlias();
|
|
17
|
+
const tableName = this.resolveTableName(relationship);
|
|
18
|
+
const whereClause = this.buildWhereClause(relationship, filters, outerAlias, subqueryAlias, outerModel);
|
|
19
|
+
return `SELECT 1 FROM ${tableName} ${subqueryAlias} WHERE ${whereClause}`;
|
|
20
|
+
}
|
|
21
|
+
buildWhereClause(relationship, filters, outerAlias, subqueryAlias, outerModel) {
|
|
22
|
+
const correlation = this.buildCorrelation(relationship, outerAlias, subqueryAlias, outerModel);
|
|
23
|
+
const filterSql = this.buildFilterConditions(filters, subqueryAlias, relationship);
|
|
24
|
+
return this.combineConditions(correlation, filterSql);
|
|
25
|
+
}
|
|
26
|
+
buildCorrelation(relationship, outerAlias, subqueryAlias, outerModel) {
|
|
27
|
+
const fkKey = this.getFkKey(relationship);
|
|
28
|
+
const outerPkKey = this.getOuterPrimaryKey(relationship, outerModel);
|
|
29
|
+
const relatedPkKey = this.getRelatedPrimaryKey(relationship);
|
|
30
|
+
if (relationship.relation === 'one-to-many') {
|
|
31
|
+
return `${subqueryAlias}."${fkKey}" = ${outerAlias}."${outerPkKey}"`;
|
|
32
|
+
}
|
|
33
|
+
const outerFk = relationship.columnName;
|
|
34
|
+
return `${outerAlias}."${outerFk}" = ${subqueryAlias}."${relatedPkKey}"`;
|
|
35
|
+
}
|
|
36
|
+
getOuterPrimaryKey(relationship, outerModel) {
|
|
37
|
+
if (!outerModel) {
|
|
38
|
+
return 'id';
|
|
39
|
+
}
|
|
40
|
+
const entity = this.entityStorage.get(outerModel);
|
|
41
|
+
if (!entity) {
|
|
42
|
+
return 'id';
|
|
43
|
+
}
|
|
44
|
+
for (const prop in entity.properties) {
|
|
45
|
+
if (entity.properties[prop].options.isPrimary) {
|
|
46
|
+
return prop;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return 'id';
|
|
50
|
+
}
|
|
51
|
+
buildFilterConditions(filters, alias, relationship) {
|
|
52
|
+
if (!filters || Object.keys(filters).length === 0) {
|
|
53
|
+
return '';
|
|
54
|
+
}
|
|
55
|
+
const conditionBuilder = this.getConditionBuilder();
|
|
56
|
+
const entity = relationship.entity();
|
|
57
|
+
return conditionBuilder.build(filters, alias, entity);
|
|
58
|
+
}
|
|
59
|
+
combineConditions(correlation, filterSql) {
|
|
60
|
+
if (!filterSql) {
|
|
61
|
+
return correlation;
|
|
62
|
+
}
|
|
63
|
+
return `${correlation} AND ${filterSql}`;
|
|
64
|
+
}
|
|
65
|
+
resolveTableName(relationship) {
|
|
66
|
+
const entity = this.entityStorage.get(relationship.entity());
|
|
67
|
+
if (!entity) {
|
|
68
|
+
const name = relationship.entity().name.toLowerCase();
|
|
69
|
+
return `public.${name}`;
|
|
70
|
+
}
|
|
71
|
+
const schema = entity.schema || 'public';
|
|
72
|
+
const tableName = entity.tableName || relationship.entity().name.toLowerCase();
|
|
73
|
+
return `${schema}."${tableName}"`;
|
|
74
|
+
}
|
|
75
|
+
generateAlias() {
|
|
76
|
+
const alias = `sq${this.aliasCounter}`;
|
|
77
|
+
this.aliasCounter++;
|
|
78
|
+
return alias;
|
|
79
|
+
}
|
|
80
|
+
getFkKey(relationship) {
|
|
81
|
+
if (typeof relationship.fkKey === 'undefined') {
|
|
82
|
+
return 'id';
|
|
83
|
+
}
|
|
84
|
+
if (typeof relationship.fkKey === 'string') {
|
|
85
|
+
return relationship.fkKey;
|
|
86
|
+
}
|
|
87
|
+
const match = /\.(?<propriedade>[\w]+)/.exec(relationship.fkKey.toString());
|
|
88
|
+
const propertyKey = match ? match.groups.propriedade : '';
|
|
89
|
+
const entity = this.entityStorage.get(relationship.entity());
|
|
90
|
+
if (!entity) {
|
|
91
|
+
throw new Error(`Entity not found in storage for relationship. ` +
|
|
92
|
+
`Make sure the entity ${relationship.entity().name} is decorated with @Entity()`);
|
|
93
|
+
}
|
|
94
|
+
const property = Object.entries(entity.properties).find(([key, _value]) => key === propertyKey)?.[1];
|
|
95
|
+
if (property) {
|
|
96
|
+
return property.options.columnName;
|
|
97
|
+
}
|
|
98
|
+
const relation = entity.relations.find((rel) => rel.propertyKey === propertyKey);
|
|
99
|
+
if (relation && relation.columnName) {
|
|
100
|
+
return relation.columnName;
|
|
101
|
+
}
|
|
102
|
+
throw new Error(`Property or relation "${propertyKey}" not found in entity "${entity.tableName}". ` +
|
|
103
|
+
`Available properties: ${Object.keys(entity.properties).join(', ')}. ` +
|
|
104
|
+
`Available relations: ${entity.relations.map((r) => r.propertyKey).join(', ')}`);
|
|
105
|
+
}
|
|
106
|
+
getRelatedPrimaryKey(relationship) {
|
|
107
|
+
const entity = this.entityStorage.get(relationship.entity());
|
|
108
|
+
if (!entity) {
|
|
109
|
+
return 'id';
|
|
110
|
+
}
|
|
111
|
+
for (const prop in entity.properties) {
|
|
112
|
+
if (entity.properties[prop].options.isPrimary) {
|
|
113
|
+
return prop;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
return 'id';
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
exports.SqlSubqueryBuilder = SqlSubqueryBuilder;
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { BaseEntity } from '../domain/base-entity';
|
|
2
|
+
import { SqlBuilder } from '../SqlBuilder';
|
|
3
|
+
import { FilterQuery, FindOptions, 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<Hint extends string = never>(options: RepositoryFindOptions<T, Hint>): Promise<T[]>;
|
|
49
|
+
/**
|
|
50
|
+
* Finds a single entity matching the given criteria.
|
|
51
|
+
* Returns undefined if not found.
|
|
52
|
+
*/
|
|
53
|
+
findOne<Hint extends string = never>(options: RepositoryFindOneOptions<T, Hint>): Promise<T | undefined>;
|
|
54
|
+
/**
|
|
55
|
+
* Finds a single entity matching the given criteria.
|
|
56
|
+
* Throws an error if not found.
|
|
57
|
+
*/
|
|
58
|
+
findOneOrFail<Hint extends string = never>(options: RepositoryFindOneOptions<T, Hint>): Promise<T>;
|
|
59
|
+
/**
|
|
60
|
+
* Finds all entities with optional filtering.
|
|
61
|
+
*/
|
|
62
|
+
findAll<Hint extends string = never>(options?: Omit<RepositoryFindOptions<T>, 'where'>): Promise<T[]>;
|
|
63
|
+
/**
|
|
64
|
+
* Finds an entity by its primary key.
|
|
65
|
+
*/
|
|
66
|
+
findById<Hint extends string = never>(id: number | string, options?: Omit<RepositoryFindOneOptions<T, Hint>, 'where'>): Promise<T | undefined>;
|
|
67
|
+
/**
|
|
68
|
+
* Finds an entity by its primary key.
|
|
69
|
+
* Throws an error if not found.
|
|
70
|
+
*/
|
|
71
|
+
findByIdOrFail<Hint extends string = never>(id: number | string, options?: Omit<RepositoryFindOneOptions<T, Hint>, 'where'>): 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
|
+
* Deletes entities matching the criteria.
|
|
92
|
+
*
|
|
93
|
+
* @example
|
|
94
|
+
* ```typescript
|
|
95
|
+
* await repository.delete({ isActive: false });
|
|
96
|
+
* ```
|
|
97
|
+
*/
|
|
98
|
+
delete(where: FilterQuery<T>): Promise<void>;
|
|
99
|
+
/**
|
|
100
|
+
* Deletes an entity by its primary key.
|
|
101
|
+
*/
|
|
102
|
+
deleteById(id: number | string): Promise<void>;
|
|
103
|
+
/**
|
|
104
|
+
* Counts entities matching the criteria.
|
|
105
|
+
*/
|
|
106
|
+
count(where?: FilterQuery<T>): Promise<number>;
|
|
107
|
+
/**
|
|
108
|
+
* Checks if any entity matches the criteria.
|
|
109
|
+
*/
|
|
110
|
+
exists(where: FilterQuery<T>): Promise<boolean>;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Find options for repository queries.
|
|
114
|
+
*/
|
|
115
|
+
export type RepositoryFindOptions<T, Hint extends string = never> = FindOptions<T, Hint> & {
|
|
116
|
+
where?: FilterQuery<T>;
|
|
117
|
+
};
|
|
118
|
+
/**
|
|
119
|
+
* Find one options for repository queries.
|
|
120
|
+
*/
|
|
121
|
+
export type RepositoryFindOneOptions<T, Hint extends string = never> = Omit<RepositoryFindOptions<T, Hint>, 'limit' | 'offset'>;
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Repository = void 0;
|
|
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
|
+
class Repository {
|
|
26
|
+
constructor(entityClass) {
|
|
27
|
+
this.entityClass = entityClass;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Creates a new query builder for the entity.
|
|
31
|
+
*/
|
|
32
|
+
createQueryBuilder() {
|
|
33
|
+
return this.entityClass.createQueryBuilder();
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Finds entities matching the given criteria.
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* ```TypeScript
|
|
40
|
+
* const lessons = await repository.find({
|
|
41
|
+
* where: { courseId: 1, isPublished: true },
|
|
42
|
+
* order: { orderIndex: 'ASC' },
|
|
43
|
+
* limit: 10
|
|
44
|
+
* });
|
|
45
|
+
* ```
|
|
46
|
+
*/
|
|
47
|
+
async find(options) {
|
|
48
|
+
const { where, orderBy, limit, offset, fields, load, loadStrategy, cache } = options;
|
|
49
|
+
return this.entityClass.find(where || {}, {
|
|
50
|
+
orderBy: orderBy,
|
|
51
|
+
limit,
|
|
52
|
+
offset,
|
|
53
|
+
fields: fields,
|
|
54
|
+
load: load,
|
|
55
|
+
loadStrategy,
|
|
56
|
+
cache,
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Finds a single entity matching the given criteria.
|
|
61
|
+
* Returns undefined if not found.
|
|
62
|
+
*/
|
|
63
|
+
async findOne(options) {
|
|
64
|
+
const { where, orderBy, fields, load, loadStrategy, cache } = options;
|
|
65
|
+
return this.entityClass.findOne(where || {}, {
|
|
66
|
+
orderBy: orderBy,
|
|
67
|
+
fields: fields,
|
|
68
|
+
load: load,
|
|
69
|
+
loadStrategy,
|
|
70
|
+
cache,
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Finds a single entity matching the given criteria.
|
|
75
|
+
* Throws an error if not found.
|
|
76
|
+
*/
|
|
77
|
+
async findOneOrFail(options) {
|
|
78
|
+
const { where, orderBy, fields, load, loadStrategy, cache } = options;
|
|
79
|
+
return this.entityClass.findOneOrFail(where || {}, {
|
|
80
|
+
orderBy: orderBy,
|
|
81
|
+
fields: fields,
|
|
82
|
+
load: load,
|
|
83
|
+
loadStrategy,
|
|
84
|
+
cache,
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Finds all entities with optional filtering.
|
|
89
|
+
*/
|
|
90
|
+
async findAll(options) {
|
|
91
|
+
const { orderBy, limit, offset, fields, load, loadStrategy, cache } = options || {};
|
|
92
|
+
return this.entityClass.findAll({
|
|
93
|
+
orderBy: orderBy,
|
|
94
|
+
limit,
|
|
95
|
+
offset,
|
|
96
|
+
fields: fields,
|
|
97
|
+
load: load,
|
|
98
|
+
loadStrategy,
|
|
99
|
+
cache,
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Finds an entity by its primary key.
|
|
104
|
+
*/
|
|
105
|
+
async findById(id, options) {
|
|
106
|
+
return this.findOne({ where: { id }, ...options });
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Finds an entity by its primary key.
|
|
110
|
+
* Throws an error if not found.
|
|
111
|
+
*/
|
|
112
|
+
async findByIdOrFail(id, options) {
|
|
113
|
+
return this.findOneOrFail({ where: { id }, ...options });
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Creates a new entity.
|
|
117
|
+
*/
|
|
118
|
+
async create(data) {
|
|
119
|
+
return this.entityClass.create(data);
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Updates entities matching the criteria.
|
|
123
|
+
*/
|
|
124
|
+
async update(where, data) {
|
|
125
|
+
await this.createQueryBuilder()
|
|
126
|
+
.update(data)
|
|
127
|
+
.where(where)
|
|
128
|
+
.execute();
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Updates an entity by its primary key.
|
|
132
|
+
*/
|
|
133
|
+
async updateById(id, data) {
|
|
134
|
+
await this.update({ id }, data);
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Deletes entities matching the criteria.
|
|
138
|
+
*
|
|
139
|
+
* @example
|
|
140
|
+
* ```typescript
|
|
141
|
+
* await repository.delete({ isActive: false });
|
|
142
|
+
* ```
|
|
143
|
+
*/
|
|
144
|
+
async delete(where) {
|
|
145
|
+
await this.createQueryBuilder()
|
|
146
|
+
.delete()
|
|
147
|
+
.where(where)
|
|
148
|
+
.execute();
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Deletes an entity by its primary key.
|
|
152
|
+
*/
|
|
153
|
+
async deleteById(id) {
|
|
154
|
+
await this.delete({ id });
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Counts entities matching the criteria.
|
|
158
|
+
*/
|
|
159
|
+
async count(where) {
|
|
160
|
+
return this.createQueryBuilder()
|
|
161
|
+
.count()
|
|
162
|
+
.setStrategy('joined')
|
|
163
|
+
.where(where || {})
|
|
164
|
+
.executeCount();
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Checks if any entity matches the criteria.
|
|
168
|
+
*/
|
|
169
|
+
async exists(where) {
|
|
170
|
+
const count = await this.count(where);
|
|
171
|
+
return count > 0;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
exports.Repository = Repository;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './with-database';
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./with-database"), exports);
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { LoggerService } from '@carno.js/core';
|
|
2
|
+
import { Orm } from '../orm';
|
|
3
|
+
import { BunPgDriver } from '../driver/bun-pg.driver';
|
|
4
|
+
import { ConnectionSettings } from '../driver/driver.interface';
|
|
5
|
+
export type DatabaseTestContext = {
|
|
6
|
+
orm: Orm<BunPgDriver>;
|
|
7
|
+
executeSql: (sql: string) => Promise<{
|
|
8
|
+
rows: unknown[];
|
|
9
|
+
}>;
|
|
10
|
+
};
|
|
11
|
+
export type DatabaseTestOptions = {
|
|
12
|
+
schema?: string;
|
|
13
|
+
entityFile?: string;
|
|
14
|
+
logger?: LoggerService;
|
|
15
|
+
connection?: Partial<ConnectionSettings<BunPgDriver>>;
|
|
16
|
+
};
|
|
17
|
+
type DatabaseTestRoutine = (context: DatabaseTestContext) => Promise<void>;
|
|
18
|
+
export declare function withDatabase(tables: string[], routine: DatabaseTestRoutine, options?: DatabaseTestOptions): Promise<void>;
|
|
19
|
+
export declare function withDatabase(routine: DatabaseTestRoutine, options?: DatabaseTestOptions, tables?: string[]): Promise<void>;
|
|
20
|
+
export {};
|