@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,14 @@
|
|
|
1
|
+
import { CacheService } from '@carno.js/core';
|
|
2
|
+
import { Statement } from '../driver/driver.interface';
|
|
3
|
+
export declare class QueryCacheManager {
|
|
4
|
+
private cacheService;
|
|
5
|
+
private keyGenerator;
|
|
6
|
+
private namespaceKeys;
|
|
7
|
+
constructor(cacheService: CacheService);
|
|
8
|
+
get<T>(statement: Statement<T>): Promise<any>;
|
|
9
|
+
set<T>(statement: Statement<T>, value: any, ttl?: number): Promise<void>;
|
|
10
|
+
invalidate<T>(statement: Statement<T>): Promise<void>;
|
|
11
|
+
private registerKeyInNamespace;
|
|
12
|
+
private getNamespace;
|
|
13
|
+
private generateKey;
|
|
14
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.QueryCacheManager = void 0;
|
|
4
|
+
const cache_key_generator_1 = require("./cache-key-generator");
|
|
5
|
+
class QueryCacheManager {
|
|
6
|
+
constructor(cacheService) {
|
|
7
|
+
this.cacheService = cacheService;
|
|
8
|
+
this.namespaceKeys = new Map();
|
|
9
|
+
this.keyGenerator = new cache_key_generator_1.CacheKeyGenerator();
|
|
10
|
+
}
|
|
11
|
+
async get(statement) {
|
|
12
|
+
const key = this.generateKey(statement);
|
|
13
|
+
return this.cacheService.get(key);
|
|
14
|
+
}
|
|
15
|
+
async set(statement, value, ttl) {
|
|
16
|
+
const key = this.generateKey(statement);
|
|
17
|
+
const namespace = this.getNamespace(statement);
|
|
18
|
+
this.registerKeyInNamespace(namespace, key);
|
|
19
|
+
await this.cacheService.set(key, value, ttl);
|
|
20
|
+
}
|
|
21
|
+
async invalidate(statement) {
|
|
22
|
+
const namespace = this.getNamespace(statement);
|
|
23
|
+
const keys = this.namespaceKeys.get(namespace);
|
|
24
|
+
if (!keys || keys.size === 0) {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
const deletePromises = Array.from(keys).map(key => this.cacheService.del(key));
|
|
28
|
+
await Promise.all(deletePromises);
|
|
29
|
+
this.namespaceKeys.delete(namespace);
|
|
30
|
+
}
|
|
31
|
+
registerKeyInNamespace(namespace, key) {
|
|
32
|
+
if (!this.namespaceKeys.has(namespace)) {
|
|
33
|
+
this.namespaceKeys.set(namespace, new Set());
|
|
34
|
+
}
|
|
35
|
+
this.namespaceKeys.get(namespace).add(key);
|
|
36
|
+
}
|
|
37
|
+
getNamespace(statement) {
|
|
38
|
+
return statement.table || 'unknown';
|
|
39
|
+
}
|
|
40
|
+
generateKey(statement) {
|
|
41
|
+
return `orm:${this.keyGenerator.generate(statement)}`;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
exports.QueryCacheManager = QueryCacheManager;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Email = void 0;
|
|
4
|
+
const value_object_1 = require("./value-object");
|
|
5
|
+
const REGEX = /^[a-z0-9.]+@[a-z0-9]+\.[a-z]+(\.[a-z]+)?$/i;
|
|
6
|
+
class Email extends value_object_1.ValueObject {
|
|
7
|
+
validate(value) {
|
|
8
|
+
return REGEX.test(value);
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
exports.Email = Email;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Uuid = void 0;
|
|
4
|
+
const value_object_1 = require("./value-object");
|
|
5
|
+
class Uuid extends value_object_1.ValueObject {
|
|
6
|
+
validate(value) {
|
|
7
|
+
return /^[a-f\d]{8}(-[a-f\d]{4}){4}[a-f\d]{8}$/i.test(value);
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
exports.Uuid = Uuid;
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
type VoExtended<T, Vo> = Vo extends ValueObject<T, Vo> ? Vo : ValueObject<T, Vo>;
|
|
2
|
+
type DatabaseValues = {
|
|
3
|
+
max?: number;
|
|
4
|
+
min?: number;
|
|
5
|
+
precision?: number;
|
|
6
|
+
scale?: number;
|
|
7
|
+
};
|
|
8
|
+
export declare abstract class ValueObject<T, Vo> {
|
|
9
|
+
/**
|
|
10
|
+
* Validates the value of the Value Object.
|
|
11
|
+
* It is abstract so that each Value Object can implement its own validation.
|
|
12
|
+
* It is protected from being called directly.
|
|
13
|
+
*
|
|
14
|
+
* @param value
|
|
15
|
+
* @protected
|
|
16
|
+
*/
|
|
17
|
+
protected abstract validate(value: T): boolean;
|
|
18
|
+
/**
|
|
19
|
+
* The maximum length of the Value Object.
|
|
20
|
+
* It value is optional and will be used in database if this Value Object is used as a column.
|
|
21
|
+
* If the value is string, it will be the maximum number of characters.
|
|
22
|
+
* If the value is number, it will be the maximum number.
|
|
23
|
+
*/
|
|
24
|
+
protected max?: number;
|
|
25
|
+
/**
|
|
26
|
+
* The minimum length of the Value Object.
|
|
27
|
+
* It value is optional.
|
|
28
|
+
* If the value is string, it will be the minimum number of characters.
|
|
29
|
+
* If the value is number, it will be the minimum number.
|
|
30
|
+
*/
|
|
31
|
+
protected min?: number;
|
|
32
|
+
/**
|
|
33
|
+
* The precision of the Value Object.
|
|
34
|
+
* It value is optional and will be used in database if this Value Object is used as a column.
|
|
35
|
+
* It is the number of digits in a number.
|
|
36
|
+
*/
|
|
37
|
+
protected precision?: number;
|
|
38
|
+
/**
|
|
39
|
+
* The scale of the Value Object.
|
|
40
|
+
* It value is optional and will be used in database if this Value Object is used as a column.
|
|
41
|
+
* It is the number of digits to the right of the decimal point in a number.
|
|
42
|
+
*/
|
|
43
|
+
protected scale?: number;
|
|
44
|
+
/**
|
|
45
|
+
* Valor do Value Object.
|
|
46
|
+
* É privado para não ser alterado diretamente.
|
|
47
|
+
* O valor também é imutável.
|
|
48
|
+
*
|
|
49
|
+
* @private
|
|
50
|
+
*/
|
|
51
|
+
private value;
|
|
52
|
+
constructor(value: T, skipValidation?: boolean);
|
|
53
|
+
/**
|
|
54
|
+
* Creates a Value Object instance from a value.
|
|
55
|
+
*
|
|
56
|
+
* @example
|
|
57
|
+
* Email.from('test@test.com');
|
|
58
|
+
*
|
|
59
|
+
* @param value
|
|
60
|
+
*/
|
|
61
|
+
static from<T, Vo>(this: new (value: T) => VoExtended<T, Vo>, value: T): VoExtended<T, Vo>;
|
|
62
|
+
/**
|
|
63
|
+
* Returns the scalar value of the Value Object.
|
|
64
|
+
*
|
|
65
|
+
*/
|
|
66
|
+
getValue(): T;
|
|
67
|
+
/**
|
|
68
|
+
* Compares the value of the Value Object with another Value Object.
|
|
69
|
+
*
|
|
70
|
+
* @param vo
|
|
71
|
+
*/
|
|
72
|
+
equals(vo: ValueObject<T, Vo>): boolean;
|
|
73
|
+
/**
|
|
74
|
+
* Returns the database settings of the Value Object.
|
|
75
|
+
*
|
|
76
|
+
* @returns
|
|
77
|
+
*/
|
|
78
|
+
getDatabaseValues(): DatabaseValues;
|
|
79
|
+
/**
|
|
80
|
+
* Sets the value of the Value Object.
|
|
81
|
+
*
|
|
82
|
+
* @param value
|
|
83
|
+
* @private
|
|
84
|
+
*/
|
|
85
|
+
private setValue;
|
|
86
|
+
/**
|
|
87
|
+
* Validates the value of the Value Object.
|
|
88
|
+
* It is private so that it can only be called by the constructor.
|
|
89
|
+
*
|
|
90
|
+
* @param value
|
|
91
|
+
* @returns
|
|
92
|
+
*/
|
|
93
|
+
private validateDatabase;
|
|
94
|
+
}
|
|
95
|
+
export {};
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ValueObject = void 0;
|
|
4
|
+
const core_1 = require("@carno.js/core");
|
|
5
|
+
class ValueObject {
|
|
6
|
+
constructor(value, skipValidation = false) {
|
|
7
|
+
if (!skipValidation && (!this.validate(value) || !this.validateDatabase(value))) {
|
|
8
|
+
throw new core_1.HttpException(`Invalid value for ${this.constructor.name}`, 400);
|
|
9
|
+
}
|
|
10
|
+
this.setValue(value);
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Creates a Value Object instance from a value.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* Email.from('test@test.com');
|
|
17
|
+
*
|
|
18
|
+
* @param value
|
|
19
|
+
*/
|
|
20
|
+
static from(value) {
|
|
21
|
+
return new this(value);
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Returns the scalar value of the Value Object.
|
|
25
|
+
*
|
|
26
|
+
*/
|
|
27
|
+
getValue() {
|
|
28
|
+
return this.value;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Compares the value of the Value Object with another Value Object.
|
|
32
|
+
*
|
|
33
|
+
* @param vo
|
|
34
|
+
*/
|
|
35
|
+
equals(vo) {
|
|
36
|
+
return this.getValue() === vo.getValue();
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Returns the database settings of the Value Object.
|
|
40
|
+
*
|
|
41
|
+
* @returns
|
|
42
|
+
*/
|
|
43
|
+
getDatabaseValues() {
|
|
44
|
+
return {
|
|
45
|
+
max: this.max,
|
|
46
|
+
min: this.min,
|
|
47
|
+
precision: this.precision,
|
|
48
|
+
scale: this.scale,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Sets the value of the Value Object.
|
|
53
|
+
*
|
|
54
|
+
* @param value
|
|
55
|
+
* @private
|
|
56
|
+
*/
|
|
57
|
+
setValue(value) {
|
|
58
|
+
this.value = value;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Validates the value of the Value Object.
|
|
62
|
+
* It is private so that it can only be called by the constructor.
|
|
63
|
+
*
|
|
64
|
+
* @param value
|
|
65
|
+
* @returns
|
|
66
|
+
*/
|
|
67
|
+
validateDatabase(value) {
|
|
68
|
+
if (typeof value === "string") {
|
|
69
|
+
if (this.max !== undefined && value.length > this.max) {
|
|
70
|
+
throw new core_1.HttpException(`Value exceeds maximum length of ${this.max}`, 400);
|
|
71
|
+
}
|
|
72
|
+
if (this.min !== undefined && value.length < this.min) {
|
|
73
|
+
throw new core_1.HttpException(`Value is less than minimum length of ${this.min}`, 400);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
else if (typeof value === "number") {
|
|
77
|
+
if (this.max !== undefined && value > this.max) {
|
|
78
|
+
throw new core_1.HttpException(`Value exceeds maximum value of ${this.max}`, 400);
|
|
79
|
+
}
|
|
80
|
+
if (this.min !== undefined && value < this.min) {
|
|
81
|
+
throw new core_1.HttpException(`Value is less than minimum value of ${this.min}`, 400);
|
|
82
|
+
}
|
|
83
|
+
if (this.precision !== undefined) {
|
|
84
|
+
const totalDigits = value.toString().replace(".", "").length;
|
|
85
|
+
if (totalDigits > this.precision) {
|
|
86
|
+
throw new core_1.HttpException(`Value exceeds precision of ${this.precision}`, 400);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
if (this.scale !== undefined) {
|
|
90
|
+
const decimalDigits = (value.toString().split(".")[1] || "").length;
|
|
91
|
+
if (decimalDigits > this.scale) {
|
|
92
|
+
throw new core_1.HttpException(`Value exceeds scale of ${this.scale}`, 400);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return true;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
exports.ValueObject = ValueObject;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export declare const ENTITIES = "carno:entities";
|
|
2
|
+
export declare const PROPERTIES = "carno:properties";
|
|
3
|
+
export declare const PROPERTIES_METADATA = "carno:properties:metadata";
|
|
4
|
+
export declare const PROPERTIES_RELATIONS = "carno:properties:relations";
|
|
5
|
+
export declare const EVENTS_METADATA = "carno:events:metadata";
|
|
6
|
+
export declare const COMPUTED_PROPERTIES = "carno:computed:properties";
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.COMPUTED_PROPERTIES = exports.EVENTS_METADATA = exports.PROPERTIES_RELATIONS = exports.PROPERTIES_METADATA = exports.PROPERTIES = exports.ENTITIES = void 0;
|
|
4
|
+
exports.ENTITIES = 'carno:entities';
|
|
5
|
+
exports.PROPERTIES = 'carno:properties';
|
|
6
|
+
exports.PROPERTIES_METADATA = 'carno:properties:metadata';
|
|
7
|
+
exports.PROPERTIES_RELATIONS = 'carno:properties:relations';
|
|
8
|
+
exports.EVENTS_METADATA = 'carno:events:metadata';
|
|
9
|
+
exports.COMPUTED_PROPERTIES = 'carno:computed:properties';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function Computed(): PropertyDecorator;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Computed = Computed;
|
|
4
|
+
const core_1 = require("@carno.js/core");
|
|
5
|
+
const constants_1 = require("../constants");
|
|
6
|
+
function Computed() {
|
|
7
|
+
return (target, propertyKey) => {
|
|
8
|
+
const computedProperties = core_1.Metadata.get(constants_1.COMPUTED_PROPERTIES, target.constructor) || [];
|
|
9
|
+
computedProperties.push(propertyKey);
|
|
10
|
+
core_1.Metadata.set(constants_1.COMPUTED_PROPERTIES, computedProperties, target.constructor);
|
|
11
|
+
};
|
|
12
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Entity = Entity;
|
|
4
|
+
const constants_1 = require("../constants");
|
|
5
|
+
const core_1 = require("@carno.js/core");
|
|
6
|
+
function Entity(options) {
|
|
7
|
+
return (target) => {
|
|
8
|
+
const entities = core_1.Metadata.get(constants_1.ENTITIES, Reflect) || [];
|
|
9
|
+
entities.push({ target, options });
|
|
10
|
+
core_1.Metadata.set(constants_1.ENTITIES, entities, Reflect);
|
|
11
|
+
};
|
|
12
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Enum = Enum;
|
|
4
|
+
const property_decorator_1 = require("./property.decorator");
|
|
5
|
+
function Enum(options) {
|
|
6
|
+
const isEnum = true;
|
|
7
|
+
if (!options) {
|
|
8
|
+
return (0, property_decorator_1.Property)({ isEnum, enumItems: '__AUTO_DETECT__', dbType: 'enum' });
|
|
9
|
+
}
|
|
10
|
+
//@ts-ignore
|
|
11
|
+
let enumItems = typeof options === 'function' ? options() : (typeof options.items === 'function' ? options.items() : options.items);
|
|
12
|
+
if (typeof enumItems === 'object') {
|
|
13
|
+
enumItems = Object.keys(enumItems).map(key => enumItems[key]);
|
|
14
|
+
}
|
|
15
|
+
return (0, property_decorator_1.Property)({ ...options, isEnum, enumItems, dbType: 'enum' });
|
|
16
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export declare function BeforeCreate(): (target: any, propertyName: any) => void;
|
|
2
|
+
export declare function AfterCreate(): (target: any, propertyName: any) => void;
|
|
3
|
+
export declare function BeforeUpdate(): (target: any, propertyName: any) => void;
|
|
4
|
+
export declare function AfterUpdate(): (target: any, propertyName: any) => void;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.BeforeCreate = BeforeCreate;
|
|
4
|
+
exports.AfterCreate = AfterCreate;
|
|
5
|
+
exports.BeforeUpdate = BeforeUpdate;
|
|
6
|
+
exports.AfterUpdate = AfterUpdate;
|
|
7
|
+
const constants_1 = require("../constants");
|
|
8
|
+
function BeforeCreate() {
|
|
9
|
+
return function (target, propertyName) {
|
|
10
|
+
const metadata = Reflect.getMetadata(constants_1.EVENTS_METADATA, target.constructor) || [];
|
|
11
|
+
Reflect.defineMetadata(constants_1.EVENTS_METADATA, [...metadata, { type: 'beforeCreate', propertyName }], target.constructor);
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
function AfterCreate() {
|
|
15
|
+
return function (target, propertyName) {
|
|
16
|
+
const metadata = Reflect.getMetadata(constants_1.EVENTS_METADATA, target.constructor) || [];
|
|
17
|
+
Reflect.defineMetadata(constants_1.EVENTS_METADATA, [...metadata, { type: 'afterCreate', propertyName }], target.constructor);
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
function BeforeUpdate() {
|
|
21
|
+
return function (target, propertyName) {
|
|
22
|
+
const metadata = Reflect.getMetadata(constants_1.EVENTS_METADATA, target.constructor) || [];
|
|
23
|
+
Reflect.defineMetadata(constants_1.EVENTS_METADATA, [...metadata, { type: 'beforeUpdate', propertyName }], target.constructor);
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
function AfterUpdate() {
|
|
27
|
+
return function (target, propertyName) {
|
|
28
|
+
const metadata = Reflect.getMetadata(constants_1.EVENTS_METADATA, target.constructor) || [];
|
|
29
|
+
Reflect.defineMetadata(constants_1.EVENTS_METADATA, [...metadata, { type: 'afterUpdate', propertyName }], target.constructor);
|
|
30
|
+
};
|
|
31
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { FilterQuery } from "../driver/driver.interface";
|
|
2
|
+
export type IndexColumnMap<T> = {
|
|
3
|
+
[K in keyof T as K extends symbol ? never : K]: string;
|
|
4
|
+
};
|
|
5
|
+
export type IndexPredicate<T> = string | ((columns: IndexColumnMap<T>) => string);
|
|
6
|
+
export type IndexWhere<T> = IndexPredicate<T> | FilterQuery<T>;
|
|
7
|
+
export type IndexDefinition = {
|
|
8
|
+
name: string;
|
|
9
|
+
properties: string[];
|
|
10
|
+
where?: IndexWhere<any>;
|
|
11
|
+
};
|
|
12
|
+
type IndexOptions<T> = {
|
|
13
|
+
properties: (keyof T)[];
|
|
14
|
+
where?: IndexWhere<T>;
|
|
15
|
+
} | (keyof T)[] | undefined;
|
|
16
|
+
export declare function Index<T>(options?: IndexOptions<T>): ClassDecorator & PropertyDecorator;
|
|
17
|
+
export {};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Index = Index;
|
|
4
|
+
const core_1 = require("@carno.js/core");
|
|
5
|
+
function getCtor(target) {
|
|
6
|
+
return typeof target === "function" ? target : target.constructor;
|
|
7
|
+
}
|
|
8
|
+
function buildFromOptions(options) {
|
|
9
|
+
const props = Array.isArray(options) ? options : options?.properties;
|
|
10
|
+
if (!props || props.length === 0)
|
|
11
|
+
return null;
|
|
12
|
+
const keys = props;
|
|
13
|
+
const where = Array.isArray(options) ? undefined : options?.where;
|
|
14
|
+
return { name: `${keys.join('_')}_index`, properties: keys, where };
|
|
15
|
+
}
|
|
16
|
+
function buildFromProperty(propertyKey) {
|
|
17
|
+
const name = String(propertyKey);
|
|
18
|
+
return { name: `${name}_index`, properties: [name] };
|
|
19
|
+
}
|
|
20
|
+
function resolveIndex(options, propertyKey) {
|
|
21
|
+
const fromOptions = buildFromOptions(options);
|
|
22
|
+
if (fromOptions)
|
|
23
|
+
return fromOptions;
|
|
24
|
+
if (!propertyKey)
|
|
25
|
+
throw new Error("@Index on class requires properties option");
|
|
26
|
+
return buildFromProperty(propertyKey);
|
|
27
|
+
}
|
|
28
|
+
function Index(options) {
|
|
29
|
+
return (target, propertyKey) => {
|
|
30
|
+
const ctor = getCtor(target);
|
|
31
|
+
const indexes = [...(core_1.Metadata.get("indexes", ctor) || [])];
|
|
32
|
+
const index = resolveIndex(options, propertyKey);
|
|
33
|
+
indexes.push(index);
|
|
34
|
+
core_1.Metadata.set("indexes", indexes, ctor);
|
|
35
|
+
};
|
|
36
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { EntityName } from '../driver/driver.interface';
|
|
2
|
+
import { PropertyOptions } from './property.decorator';
|
|
3
|
+
export declare function OneToMany<T>(entity: () => EntityName<T>, fkKey: (string & keyof T) | ((e: T) => any)): PropertyDecorator;
|
|
4
|
+
type ManyToOneOptions = Partial<PropertyOptions>;
|
|
5
|
+
export declare function ManyToOne<T>(entityOrOptions?: (() => EntityName<T>) | ManyToOneOptions, maybeOptions?: ManyToOneOptions): PropertyDecorator;
|
|
6
|
+
export {};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.OneToMany = OneToMany;
|
|
4
|
+
exports.ManyToOne = ManyToOne;
|
|
5
|
+
const constants_1 = require("../constants");
|
|
6
|
+
const core_1 = require("@carno.js/core");
|
|
7
|
+
const utils_1 = require("../utils");
|
|
8
|
+
const index_decorator_1 = require("./index.decorator");
|
|
9
|
+
function OneToMany(entity, fkKey) {
|
|
10
|
+
return (target, propertyKey) => {
|
|
11
|
+
const existing = core_1.Metadata.get(constants_1.PROPERTIES_RELATIONS, target.constructor) || [];
|
|
12
|
+
const options = { relation: 'one-to-many', propertyKey, isRelation: true, entity, fkKey, type: core_1.Metadata.getType(target, propertyKey), originalEntity: target.constructor };
|
|
13
|
+
options['columnName'] = `${(0, utils_1.toSnakeCase)(propertyKey)}_id`;
|
|
14
|
+
// @ts-ignore
|
|
15
|
+
existing.push(options);
|
|
16
|
+
core_1.Metadata.set(constants_1.PROPERTIES_RELATIONS, existing, target.constructor);
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
function ManyToOne(entityOrOptions, maybeOptions) {
|
|
20
|
+
return (target, propertyKey) => {
|
|
21
|
+
const existing = core_1.Metadata.get(constants_1.PROPERTIES_RELATIONS, target.constructor) || [];
|
|
22
|
+
const hasEntity = typeof entityOrOptions === 'function';
|
|
23
|
+
const entity = hasEntity ? entityOrOptions : undefined;
|
|
24
|
+
const options = (!hasEntity ? entityOrOptions : maybeOptions) || {};
|
|
25
|
+
const columnName = options.columnName || `${(0, utils_1.toSnakeCase)(propertyKey)}_id`;
|
|
26
|
+
const relationOptions = {
|
|
27
|
+
relation: 'many-to-one',
|
|
28
|
+
propertyKey,
|
|
29
|
+
isRelation: true,
|
|
30
|
+
entity: entity || '__AUTO_DETECT__',
|
|
31
|
+
type: core_1.Metadata.getType(target, propertyKey),
|
|
32
|
+
originalEntity: target.constructor,
|
|
33
|
+
columnName,
|
|
34
|
+
...options,
|
|
35
|
+
};
|
|
36
|
+
if (options.index) {
|
|
37
|
+
(0, index_decorator_1.Index)({ properties: [propertyKey] })(target, propertyKey);
|
|
38
|
+
}
|
|
39
|
+
existing.push(relationOptions);
|
|
40
|
+
core_1.Metadata.set(constants_1.PROPERTIES_RELATIONS, existing, target.constructor);
|
|
41
|
+
};
|
|
42
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PrimaryKey = PrimaryKey;
|
|
4
|
+
const property_decorator_1 = require("./property.decorator");
|
|
5
|
+
function PrimaryKey(options) {
|
|
6
|
+
const isPrimary = true;
|
|
7
|
+
return (0, property_decorator_1.Property)({ ...options, isPrimary });
|
|
8
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export type PropertyOptions = {
|
|
2
|
+
isPrimary?: boolean;
|
|
3
|
+
nullable?: boolean;
|
|
4
|
+
default?: any;
|
|
5
|
+
length?: number;
|
|
6
|
+
hidden?: boolean;
|
|
7
|
+
unique?: boolean;
|
|
8
|
+
index?: boolean;
|
|
9
|
+
precision?: number;
|
|
10
|
+
scale?: number;
|
|
11
|
+
dbType?: "varchar" | "text" | "int" | "bigint" | "float" | "double" | "decimal" | "date" | "datetime" | "time" | "timestamp" | "boolean" | "json" | "jsonb" | "enum" | "array" | "uuid";
|
|
12
|
+
autoIncrement?: boolean;
|
|
13
|
+
columnName?: string;
|
|
14
|
+
isEnum?: boolean;
|
|
15
|
+
enumItems?: string[] | number[] | '__AUTO_DETECT__';
|
|
16
|
+
array?: boolean;
|
|
17
|
+
onUpdate?: () => any;
|
|
18
|
+
onInsert?: () => any;
|
|
19
|
+
};
|
|
20
|
+
export type Prop = {
|
|
21
|
+
propertyKey: any;
|
|
22
|
+
options: PropertyOptions | undefined;
|
|
23
|
+
};
|
|
24
|
+
export declare function Property(options?: PropertyOptions): PropertyDecorator;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Property = Property;
|
|
4
|
+
const constants_1 = require("../constants");
|
|
5
|
+
const utils_1 = require("../utils");
|
|
6
|
+
const core_1 = require("@carno.js/core");
|
|
7
|
+
const index_decorator_1 = require("./index.decorator");
|
|
8
|
+
const __1 = require("..");
|
|
9
|
+
function Property(options) {
|
|
10
|
+
return (target, propertyKey) => {
|
|
11
|
+
const properties = core_1.Metadata.get(constants_1.PROPERTIES, target.constructor) || [];
|
|
12
|
+
// 1) Resolva o tipo logo no início
|
|
13
|
+
const propType = core_1.Metadata.getType(target, propertyKey);
|
|
14
|
+
const length = (options && options.length) || (0, utils_1.getDefaultLength)(propType?.name);
|
|
15
|
+
if ((0, core_1.isObject)(propType) && options.dbType !== "enum") {
|
|
16
|
+
throw new Error(`Property ${String(propertyKey)} has unknown type`);
|
|
17
|
+
}
|
|
18
|
+
options = { length, ...options };
|
|
19
|
+
options["columnName"] = options?.columnName || (0, utils_1.toSnakeCase)(propertyKey);
|
|
20
|
+
if (propType && (0, utils_1.extendsFrom)(__1.ValueObject, propType.prototype)) {
|
|
21
|
+
let instance = new propType(null, true).getDatabaseValues();
|
|
22
|
+
options["length"] = instance.max;
|
|
23
|
+
options["precision"] = instance.precision;
|
|
24
|
+
options["scale"] = instance.scale;
|
|
25
|
+
instance = null; // Garbage collector
|
|
26
|
+
}
|
|
27
|
+
properties.push({ propertyKey, options });
|
|
28
|
+
core_1.Metadata.set(constants_1.PROPERTIES, properties, target.constructor);
|
|
29
|
+
if (options.isPrimary) {
|
|
30
|
+
const indexes = core_1.Metadata.get("indexes", target.constructor) || [];
|
|
31
|
+
indexes.push({ name: `[TABLE]_pkey`, properties: [propertyKey] });
|
|
32
|
+
core_1.Metadata.set("indexes", indexes, target.constructor);
|
|
33
|
+
}
|
|
34
|
+
if (options.index) {
|
|
35
|
+
(0, index_decorator_1.Index)({ properties: [propertyKey] })(target, propertyKey);
|
|
36
|
+
}
|
|
37
|
+
// 2) Atualize PROPERTIES_METADATA apenas para esta propriedade
|
|
38
|
+
const existingTypes = core_1.Metadata.get(constants_1.PROPERTIES_METADATA, target.constructor) || {};
|
|
39
|
+
// Cria uma cópia para evitar mutação compartilhada entre entidades
|
|
40
|
+
const types = { ...existingTypes };
|
|
41
|
+
types[propertyKey] = { type: propType, options };
|
|
42
|
+
core_1.Metadata.set(constants_1.PROPERTIES_METADATA, types, target.constructor);
|
|
43
|
+
};
|
|
44
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export type UniqueDefinition = {
|
|
2
|
+
name: string;
|
|
3
|
+
properties: string[];
|
|
4
|
+
};
|
|
5
|
+
type UniqueOptions<T> = {
|
|
6
|
+
properties: (keyof T)[];
|
|
7
|
+
} | (keyof T)[] | undefined;
|
|
8
|
+
export declare function Unique<T>(options?: UniqueOptions<T>): ClassDecorator & PropertyDecorator;
|
|
9
|
+
export {};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Unique = Unique;
|
|
4
|
+
const core_1 = require("@carno.js/core");
|
|
5
|
+
function getCtor(target) {
|
|
6
|
+
return typeof target === "function" ? target : target.constructor;
|
|
7
|
+
}
|
|
8
|
+
function buildFromOptions(options) {
|
|
9
|
+
const props = Array.isArray(options) ? options : options?.properties;
|
|
10
|
+
if (!props || props.length === 0) {
|
|
11
|
+
return null;
|
|
12
|
+
}
|
|
13
|
+
const keys = props;
|
|
14
|
+
return {
|
|
15
|
+
name: `${keys.join('_')}_unique`,
|
|
16
|
+
properties: keys,
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
function buildFromProperty(propertyKey) {
|
|
20
|
+
const name = String(propertyKey);
|
|
21
|
+
return {
|
|
22
|
+
name: `${name}_unique`,
|
|
23
|
+
properties: [name],
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
function resolveUnique(options, propertyKey) {
|
|
27
|
+
const fromOptions = buildFromOptions(options);
|
|
28
|
+
if (fromOptions) {
|
|
29
|
+
return fromOptions;
|
|
30
|
+
}
|
|
31
|
+
if (!propertyKey) {
|
|
32
|
+
throw new Error("@Unique on class requires properties option");
|
|
33
|
+
}
|
|
34
|
+
return buildFromProperty(propertyKey);
|
|
35
|
+
}
|
|
36
|
+
function Unique(options) {
|
|
37
|
+
return (target, propertyKey) => {
|
|
38
|
+
const ctor = getCtor(target);
|
|
39
|
+
const uniques = [...(core_1.Metadata.get("uniques", ctor) || [])];
|
|
40
|
+
const unique = resolveUnique(options, propertyKey);
|
|
41
|
+
uniques.push(unique);
|
|
42
|
+
core_1.Metadata.set("uniques", uniques, ctor);
|
|
43
|
+
};
|
|
44
|
+
}
|