@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.
Files changed (98) hide show
  1. package/LICENSE +674 -0
  2. package/dist/SqlBuilder.d.ts +103 -0
  3. package/dist/SqlBuilder.js +618 -0
  4. package/dist/cache/cache-key-generator.d.ts +13 -0
  5. package/dist/cache/cache-key-generator.js +66 -0
  6. package/dist/cache/query-cache-manager.d.ts +14 -0
  7. package/dist/cache/query-cache-manager.js +44 -0
  8. package/dist/common/email.vo.d.ts +4 -0
  9. package/dist/common/email.vo.js +11 -0
  10. package/dist/common/uuid.d.ts +4 -0
  11. package/dist/common/uuid.js +10 -0
  12. package/dist/common/value-object.d.ts +95 -0
  13. package/dist/common/value-object.js +99 -0
  14. package/dist/constants.d.ts +6 -0
  15. package/dist/constants.js +9 -0
  16. package/dist/decorators/computed.decorator.d.ts +1 -0
  17. package/dist/decorators/computed.decorator.js +12 -0
  18. package/dist/decorators/entity.decorator.d.ts +3 -0
  19. package/dist/decorators/entity.decorator.js +12 -0
  20. package/dist/decorators/enum.decorator.d.ts +2 -0
  21. package/dist/decorators/enum.decorator.js +16 -0
  22. package/dist/decorators/event-hook.decorator.d.ts +4 -0
  23. package/dist/decorators/event-hook.decorator.js +31 -0
  24. package/dist/decorators/index.decorator.d.ts +17 -0
  25. package/dist/decorators/index.decorator.js +36 -0
  26. package/dist/decorators/one-many.decorator.d.ts +6 -0
  27. package/dist/decorators/one-many.decorator.js +42 -0
  28. package/dist/decorators/primary-key.decorator.d.ts +2 -0
  29. package/dist/decorators/primary-key.decorator.js +8 -0
  30. package/dist/decorators/property.decorator.d.ts +24 -0
  31. package/dist/decorators/property.decorator.js +44 -0
  32. package/dist/decorators/unique.decorator.d.ts +9 -0
  33. package/dist/decorators/unique.decorator.js +44 -0
  34. package/dist/domain/base-entity.d.ts +57 -0
  35. package/dist/domain/base-entity.js +198 -0
  36. package/dist/domain/collection.d.ts +6 -0
  37. package/dist/domain/collection.js +15 -0
  38. package/dist/domain/entities.d.ts +49 -0
  39. package/dist/domain/entities.js +259 -0
  40. package/dist/domain/reference.d.ts +86 -0
  41. package/dist/domain/reference.js +86 -0
  42. package/dist/driver/bun-driver.base.d.ts +72 -0
  43. package/dist/driver/bun-driver.base.js +270 -0
  44. package/dist/driver/bun-mysql.driver.d.ts +53 -0
  45. package/dist/driver/bun-mysql.driver.js +256 -0
  46. package/dist/driver/bun-pg.driver.d.ts +52 -0
  47. package/dist/driver/bun-pg.driver.js +263 -0
  48. package/dist/driver/driver.interface.d.ts +333 -0
  49. package/dist/driver/driver.interface.js +2 -0
  50. package/dist/entry.d.ts +2 -0
  51. package/dist/entry.js +13 -0
  52. package/dist/identity-map/entity-key-generator.d.ts +10 -0
  53. package/dist/identity-map/entity-key-generator.js +45 -0
  54. package/dist/identity-map/entity-registry.d.ts +11 -0
  55. package/dist/identity-map/entity-registry.js +41 -0
  56. package/dist/identity-map/identity-map-context.d.ts +9 -0
  57. package/dist/identity-map/identity-map-context.js +22 -0
  58. package/dist/identity-map/identity-map-integration.d.ts +5 -0
  59. package/dist/identity-map/identity-map-integration.js +37 -0
  60. package/dist/identity-map/identity-map.d.ts +11 -0
  61. package/dist/identity-map/identity-map.js +35 -0
  62. package/dist/identity-map/index.d.ts +5 -0
  63. package/dist/identity-map/index.js +14 -0
  64. package/dist/index.d.ts +28 -0
  65. package/dist/index.js +48 -0
  66. package/dist/middleware/identity-map.middleware.d.ts +4 -0
  67. package/dist/middleware/identity-map.middleware.js +22 -0
  68. package/dist/orm-session-context.d.ts +16 -0
  69. package/dist/orm-session-context.js +22 -0
  70. package/dist/orm.d.ts +20 -0
  71. package/dist/orm.js +69 -0
  72. package/dist/orm.service.d.ts +13 -0
  73. package/dist/orm.service.js +361 -0
  74. package/dist/query/index-condition-builder.d.ts +41 -0
  75. package/dist/query/index-condition-builder.js +235 -0
  76. package/dist/query/model-transformer.d.ts +27 -0
  77. package/dist/query/model-transformer.js +201 -0
  78. package/dist/query/sql-column-manager.d.ts +28 -0
  79. package/dist/query/sql-column-manager.js +157 -0
  80. package/dist/query/sql-condition-builder.d.ts +51 -0
  81. package/dist/query/sql-condition-builder.js +264 -0
  82. package/dist/query/sql-join-manager.d.ts +39 -0
  83. package/dist/query/sql-join-manager.js +242 -0
  84. package/dist/query/sql-subquery-builder.d.ts +20 -0
  85. package/dist/query/sql-subquery-builder.js +119 -0
  86. package/dist/repository/Repository.d.ts +121 -0
  87. package/dist/repository/Repository.js +174 -0
  88. package/dist/testing/index.d.ts +1 -0
  89. package/dist/testing/index.js +17 -0
  90. package/dist/testing/with-database.d.ts +20 -0
  91. package/dist/testing/with-database.js +311 -0
  92. package/dist/transaction/transaction-context.d.ts +10 -0
  93. package/dist/transaction/transaction-context.js +19 -0
  94. package/dist/utils/value-processor.d.ts +14 -0
  95. package/dist/utils/value-processor.js +94 -0
  96. package/dist/utils.d.ts +3 -0
  97. package/dist/utils.js +24 -0
  98. package/package.json +59 -0
@@ -0,0 +1,57 @@
1
+ import { SqlBuilder } from '../SqlBuilder';
2
+ import { FilterQuery, FindOneOption, FindOptions, ValueOrInstance } from '../driver/driver.interface';
3
+ export declare abstract class BaseEntity {
4
+ private _oldValues;
5
+ private _changedValues;
6
+ private $_isPersisted;
7
+ constructor();
8
+ /**
9
+ * Gets current entity's Repository.
10
+ */
11
+ static createQueryBuilder<T>(this: {
12
+ new (): T;
13
+ } & typeof BaseEntity): SqlBuilder<T>;
14
+ /**
15
+ * Gets current entity's Repository.
16
+ */
17
+ private createQueryBuilder;
18
+ static find<T, Hint extends string = never>(this: {
19
+ new (): T;
20
+ } & typeof BaseEntity, where: FilterQuery<T>, options?: FindOptions<T, Hint>): Promise<T[]>;
21
+ static findOne<T, Hint extends string = never>(this: {
22
+ new (): T;
23
+ } & typeof BaseEntity, where: FilterQuery<T>, options?: FindOneOption<T, Hint>): Promise<T | undefined>;
24
+ /**
25
+ * Find a record in the database based on the provided query where and return it, or throw an error if not found.
26
+ *
27
+ * @param {FilterQuery<T>} where - The query where used to search for the record.
28
+ * @param options
29
+ * @return {Promise<T>} - A promise that resolves with the found record.
30
+ */
31
+ static findOneOrFail<T, Hint extends string = never>(this: {
32
+ new (): T;
33
+ } & typeof BaseEntity, where: FilterQuery<T>, options?: FindOneOption<T, Hint>): Promise<T>;
34
+ static findAll<T extends object, Hint extends string = never>(this: {
35
+ new (): T;
36
+ } & typeof BaseEntity, options: FindOptions<T, Hint>): Promise<T[]>;
37
+ static create<T extends BaseEntity>(this: {
38
+ new (): T;
39
+ } & typeof BaseEntity, where: Partial<{
40
+ [K in keyof T]: ValueOrInstance<T[K]>;
41
+ }>): Promise<T>;
42
+ save(): Promise<void>;
43
+ /**
44
+ * Determines whether the current object has been persisted after the last modification.
45
+ *
46
+ * @return {boolean} Returns true if the object has been persisted, otherwise false.
47
+ */
48
+ isPersisted(): boolean;
49
+ toJSON(): Record<string, any>;
50
+ private serializeWithEntity;
51
+ private serializeWithMetadata;
52
+ private shouldSkipProperty;
53
+ private shouldSkipPropertyBasic;
54
+ private isInternalProperty;
55
+ private getHiddenPropertiesFromMetadata;
56
+ private addComputedProperties;
57
+ }
@@ -0,0 +1,198 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.BaseEntity = void 0;
4
+ const SqlBuilder_1 = require("../SqlBuilder");
5
+ const entities_1 = require("./entities");
6
+ const core_1 = require("@carno.js/core");
7
+ const constants_1 = require("../constants");
8
+ class BaseEntity {
9
+ constructor() {
10
+ this._oldValues = {};
11
+ this._changedValues = {};
12
+ this.$_isPersisted = false;
13
+ return new Proxy(this, {
14
+ set(target, p, newValue) {
15
+ if (p.startsWith('$') || p.startsWith('_')) {
16
+ target[p] = newValue;
17
+ return true;
18
+ }
19
+ // se oldvalue não existir, é porque é a primeira vez que o atributo está sendo setado
20
+ if (!(p in target._oldValues)) {
21
+ target._oldValues[p] = newValue;
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
+ this.$_isPersisted = false;
27
+ }
28
+ target[p] = newValue;
29
+ return true;
30
+ },
31
+ });
32
+ }
33
+ /**
34
+ * Gets current entity's Repository.
35
+ */
36
+ static createQueryBuilder() {
37
+ return new SqlBuilder_1.SqlBuilder(this);
38
+ }
39
+ /**
40
+ * Gets current entity's Repository.
41
+ */
42
+ createQueryBuilder() {
43
+ // @ts-ignore
44
+ return new SqlBuilder_1.SqlBuilder(this.constructor);
45
+ }
46
+ static async find(where, options) {
47
+ return this.createQueryBuilder()
48
+ .select(options?.fields)
49
+ .setStrategy(options?.loadStrategy)
50
+ .load(options?.load)
51
+ .where(where)
52
+ .limit(options?.limit)
53
+ .offset(options?.offset)
54
+ .orderBy(options?.orderBy)
55
+ .cache(options?.cache)
56
+ .executeAndReturnAll();
57
+ }
58
+ static async findOne(where, options) {
59
+ return this.createQueryBuilder()
60
+ .select(options?.fields)
61
+ .setStrategy(options?.loadStrategy)
62
+ .load(options?.load)
63
+ .where(where)
64
+ .cache(options?.cache)
65
+ .executeAndReturnFirst();
66
+ }
67
+ /**
68
+ * Find a record in the database based on the provided query where and return it, or throw an error if not found.
69
+ *
70
+ * @param {FilterQuery<T>} where - The query where used to search for the record.
71
+ * @param options
72
+ * @return {Promise<T>} - A promise that resolves with the found record.
73
+ */
74
+ static async findOneOrFail(where, options) {
75
+ return this.createQueryBuilder()
76
+ // @ts-ignore
77
+ .select(options?.fields)
78
+ .setStrategy(options?.loadStrategy)
79
+ .load(options?.load)
80
+ .where(where)
81
+ .orderBy(options?.orderBy)
82
+ .cache(options?.cache)
83
+ .executeAndReturnFirstOrFail();
84
+ }
85
+ static async findAll(options) {
86
+ const builder = this.createQueryBuilder()
87
+ .select(options.fields)
88
+ .setStrategy(options?.loadStrategy)
89
+ .load(options?.load)
90
+ .offset(options?.offset)
91
+ .limit(options.limit)
92
+ .orderBy(options?.orderBy)
93
+ .cache(options?.cache);
94
+ return builder.executeAndReturnAll();
95
+ }
96
+ static async create(where) {
97
+ return this.createQueryBuilder()
98
+ .insert(where)
99
+ .executeAndReturnFirstOrFail();
100
+ }
101
+ async save() {
102
+ const qb = this.createQueryBuilder();
103
+ if (this.$_isPersisted) {
104
+ qb.update(this._changedValues);
105
+ qb.setInstance(this);
106
+ // @ts-ignore
107
+ qb.where({ id: this._oldValues.id });
108
+ }
109
+ else {
110
+ qb.insert(this._oldValues);
111
+ }
112
+ await qb.execute();
113
+ qb.callHook('afterCreate', this);
114
+ qb.callHook('afterUpdate', this);
115
+ this._oldValues = {
116
+ ...this._oldValues,
117
+ ...this._changedValues,
118
+ };
119
+ this._changedValues = {};
120
+ }
121
+ /**
122
+ * Determines whether the current object has been persisted after the last modification.
123
+ *
124
+ * @return {boolean} Returns true if the object has been persisted, otherwise false.
125
+ */
126
+ isPersisted() {
127
+ return this.$_isPersisted;
128
+ }
129
+ toJSON() {
130
+ const storage = entities_1.EntityStorage.getInstance();
131
+ const entity = storage.get(this.constructor);
132
+ const data = entity
133
+ ? this.serializeWithEntity(entity)
134
+ : this.serializeWithMetadata();
135
+ this.addComputedProperties(data);
136
+ return data;
137
+ }
138
+ serializeWithEntity(entity) {
139
+ const data = {};
140
+ const allProperties = new Set(Object.keys(entity.properties));
141
+ const allRelations = new Set((entity.relations || []).map((relation) => relation.propertyKey));
142
+ const hidePropertiesSet = new Set(entity.hideProperties);
143
+ for (const key in this) {
144
+ if (this.shouldSkipProperty(key, allProperties, allRelations, hidePropertiesSet)) {
145
+ continue;
146
+ }
147
+ data[key] = this[key];
148
+ }
149
+ return data;
150
+ }
151
+ serializeWithMetadata() {
152
+ const data = {};
153
+ const hideProperties = this.getHiddenPropertiesFromMetadata();
154
+ const hidePropertiesSet = new Set(hideProperties);
155
+ for (const key in this) {
156
+ if (this.shouldSkipPropertyBasic(key, hidePropertiesSet)) {
157
+ continue;
158
+ }
159
+ data[key] = this[key];
160
+ }
161
+ return data;
162
+ }
163
+ shouldSkipProperty(key, allProperties, allRelations, hideProperties) {
164
+ if (this.isInternalProperty(key)) {
165
+ return true;
166
+ }
167
+ if (!allProperties.has(key) && !allRelations.has(key)) {
168
+ return true;
169
+ }
170
+ return hideProperties.has(key);
171
+ }
172
+ shouldSkipPropertyBasic(key, hideProperties) {
173
+ if (this.isInternalProperty(key)) {
174
+ return true;
175
+ }
176
+ return hideProperties.has(key);
177
+ }
178
+ isInternalProperty(key) {
179
+ return key.startsWith('$') || key.startsWith('_');
180
+ }
181
+ getHiddenPropertiesFromMetadata() {
182
+ const properties = core_1.Metadata.get(constants_1.PROPERTIES_METADATA, this.constructor) || {};
183
+ const hideProperties = [];
184
+ for (const [key, prop] of Object.entries(properties)) {
185
+ if (prop.options?.hidden) {
186
+ hideProperties.push(key);
187
+ }
188
+ }
189
+ return hideProperties;
190
+ }
191
+ addComputedProperties(data) {
192
+ const computedProperties = core_1.Metadata.get(constants_1.COMPUTED_PROPERTIES, this.constructor) || [];
193
+ for (const key of computedProperties) {
194
+ data[key] = this[key];
195
+ }
196
+ }
197
+ }
198
+ exports.BaseEntity = BaseEntity;
@@ -0,0 +1,6 @@
1
+ export declare class ArrayCollection<T extends object, O extends object> {
2
+ getItems(): T[];
3
+ }
4
+ export declare class Collection<T extends object, O extends object = object> extends ArrayCollection<T, O> {
5
+ constructor(owner: O, items?: T[], initialized?: boolean);
6
+ }
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Collection = exports.ArrayCollection = void 0;
4
+ class ArrayCollection {
5
+ getItems() {
6
+ return [];
7
+ }
8
+ }
9
+ exports.ArrayCollection = ArrayCollection;
10
+ class Collection extends ArrayCollection {
11
+ constructor(owner, items, initialized = true) {
12
+ super();
13
+ }
14
+ }
15
+ exports.Collection = Collection;
@@ -0,0 +1,49 @@
1
+ import { PropertyOptions } from "../decorators/property.decorator";
2
+ import { Relationship, SnapshotIndexInfo, SnapshotTable, SnapshotUniqueInfo } from "../driver/driver.interface";
3
+ export type Property = {
4
+ options: PropertyOptions;
5
+ type: Function;
6
+ };
7
+ export type Options = {
8
+ properties: {
9
+ [key: string]: Property;
10
+ };
11
+ hideProperties: string[];
12
+ indexes?: SnapshotIndexInfo[];
13
+ uniques?: SnapshotUniqueInfo[];
14
+ relations: Relationship<any>[];
15
+ tableName: string;
16
+ hooks?: {
17
+ type: string;
18
+ propertyName: string;
19
+ }[];
20
+ schema?: string;
21
+ };
22
+ export declare class EntityStorage {
23
+ static instance: EntityStorage;
24
+ private entities;
25
+ constructor();
26
+ add(entity: {
27
+ target: Function;
28
+ options: any;
29
+ }, properties: {
30
+ [key: string]: Property;
31
+ }, relations: Relationship<any>[], hooks: {
32
+ type: string;
33
+ propertyName: string;
34
+ }[]): void;
35
+ get(entity: Function): Options;
36
+ entries(): MapIterator<[Function, Options]>;
37
+ static getInstance(): EntityStorage;
38
+ snapshot(values: Options): Promise<SnapshotTable>;
39
+ private snapshotColumns;
40
+ private snapshotIndexes;
41
+ private getFkType;
42
+ private getFkIncrement;
43
+ /**
44
+ * If fkKey is null, return the primary key of the entity
45
+ * @private
46
+ * @param relationShip
47
+ */
48
+ private getFkKey;
49
+ }
@@ -0,0 +1,259 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ var EntityStorage_1;
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.EntityStorage = void 0;
14
+ const core_1 = require("@carno.js/core");
15
+ const orm_session_context_1 = require("../orm-session-context");
16
+ const utils_1 = require("../utils");
17
+ const index_condition_builder_1 = require("../query/index-condition-builder");
18
+ function buildIndexColumnMap(properties, relations) {
19
+ const map = mapPropertyColumns(properties);
20
+ addRelationColumns(map, relations);
21
+ return map;
22
+ }
23
+ function mapPropertyColumns(properties) {
24
+ const map = {};
25
+ Object.entries(properties).forEach(([key, value]) => {
26
+ map[key] = value.options.columnName;
27
+ });
28
+ return map;
29
+ }
30
+ function addRelationColumns(map, relations) {
31
+ relations.forEach((relation) => {
32
+ map[String(relation.propertyKey)] = relation.columnName;
33
+ });
34
+ }
35
+ function mapIndexDefinitions(indexes, entityName, columnMap) {
36
+ return indexes.map((index) => toSnapshotIndex(index, entityName, columnMap));
37
+ }
38
+ function toSnapshotIndex(index, entityName, columnMap) {
39
+ const columns = resolveIndexColumns(index, columnMap);
40
+ const indexName = resolveIndexName(index.name, entityName, columns);
41
+ return {
42
+ table: entityName,
43
+ indexName,
44
+ columnName: columns.join(","),
45
+ where: resolveIndexWhere(index.where, columnMap),
46
+ };
47
+ }
48
+ function resolveIndexColumns(index, columnMap) {
49
+ return index.properties.map((propName) => resolveIndexColumn(propName, columnMap));
50
+ }
51
+ function resolveIndexColumn(propName, columnMap) {
52
+ const mapped = columnMap[propName];
53
+ if (mapped) {
54
+ return mapped;
55
+ }
56
+ return (0, utils_1.toSnakeCase)(propName);
57
+ }
58
+ function resolveIndexName(name, entityName, columns) {
59
+ if (name.includes('_pkey') || name.includes('[TABLE]')) {
60
+ return name.replace("[TABLE]", entityName);
61
+ }
62
+ return `${columns.join("_")}_index`;
63
+ }
64
+ function resolveIndexWhere(where, columnMap) {
65
+ if (!where) {
66
+ return undefined;
67
+ }
68
+ if (typeof where === "string") {
69
+ return where;
70
+ }
71
+ if (typeof where === "function") {
72
+ return where(columnMap);
73
+ }
74
+ return buildIndexWhere(where, columnMap);
75
+ }
76
+ function buildIndexWhere(where, columnMap) {
77
+ const builder = new index_condition_builder_1.IndexConditionBuilder(columnMap);
78
+ return builder.build(where);
79
+ }
80
+ function mapUniqueDefinitions(uniques, entityName, columnMap) {
81
+ return uniques.map((unique) => toSnapshotUnique(unique, entityName, columnMap));
82
+ }
83
+ function toSnapshotUnique(unique, entityName, columnMap) {
84
+ const columns = resolveUniqueColumns(unique, columnMap);
85
+ const uniqueName = resolveUniqueName(unique.name, entityName, columns);
86
+ return {
87
+ table: entityName,
88
+ uniqueName,
89
+ columnName: columns.join(","),
90
+ };
91
+ }
92
+ function resolveUniqueColumns(unique, columnMap) {
93
+ return unique.properties.map((propName) => resolveUniqueColumn(propName, columnMap));
94
+ }
95
+ function resolveUniqueColumn(propName, columnMap) {
96
+ const mapped = columnMap[propName];
97
+ if (mapped) {
98
+ return mapped;
99
+ }
100
+ return (0, utils_1.toSnakeCase)(propName);
101
+ }
102
+ function resolveUniqueName(name, entityName, columns) {
103
+ return `${columns.join("_")}_unique`;
104
+ }
105
+ let EntityStorage = EntityStorage_1 = class EntityStorage {
106
+ constructor() {
107
+ this.entities = new Map();
108
+ EntityStorage_1.instance = this;
109
+ }
110
+ add(entity, properties, relations, hooks) {
111
+ const entityName = entity.options?.tableName || (0, utils_1.toSnakeCase)(entity.target.name);
112
+ const indexes = core_1.Metadata.get("indexes", entity.target) || [];
113
+ const uniques = core_1.Metadata.get("uniques", entity.target) || [];
114
+ const columnMap = buildIndexColumnMap(properties, relations);
115
+ this.entities.set(entity.target, {
116
+ properties: properties,
117
+ hideProperties: Object.entries(properties)
118
+ .filter(([_key, value]) => value.options.hidden)
119
+ .map(([key]) => key),
120
+ relations,
121
+ indexes: mapIndexDefinitions(indexes, entityName, columnMap),
122
+ uniques: mapUniqueDefinitions(uniques, entityName, columnMap),
123
+ hooks,
124
+ tableName: entityName,
125
+ ...entity.options,
126
+ });
127
+ }
128
+ get(entity) {
129
+ return this.entities.get(entity);
130
+ }
131
+ entries() {
132
+ return this.entities.entries();
133
+ }
134
+ static getInstance() {
135
+ const scoped = orm_session_context_1.ormSessionContext.getStorage();
136
+ if (scoped) {
137
+ return scoped;
138
+ }
139
+ return EntityStorage_1.instance;
140
+ }
141
+ async snapshot(values) {
142
+ return {
143
+ tableName: values.tableName,
144
+ schema: values.schema || "public",
145
+ indexes: values.indexes || [],
146
+ uniques: values.uniques || [],
147
+ columns: this.snapshotColumns(values),
148
+ };
149
+ }
150
+ snapshotColumns(values) {
151
+ let properties = Object.entries(values.properties).map(([_key, value]) => {
152
+ return {
153
+ name: value.options.columnName,
154
+ type: value.options.dbType ?? value.type.name,
155
+ nullable: value.options?.nullable,
156
+ default: value.options?.default,
157
+ autoIncrement: value.options?.autoIncrement,
158
+ primary: value.options?.isPrimary,
159
+ unique: value.options?.unique,
160
+ length: value.options?.length,
161
+ isEnum: value.options?.isEnum,
162
+ precision: value.options?.precision,
163
+ scale: value.options?.scale,
164
+ enumItems: value.options?.enumItems,
165
+ };
166
+ });
167
+ // @ts-ignore
168
+ let relations = values.relations &&
169
+ values.relations
170
+ .filter((relation) => relation.relation === 'many-to-one')
171
+ .map((relation) => {
172
+ const type = this.getFkType(relation);
173
+ return {
174
+ name: relation.columnName,
175
+ type,
176
+ nullable: relation.nullable,
177
+ unique: relation.unique,
178
+ length: relation.length || (0, utils_1.getDefaultLength)(type),
179
+ default: relation.default,
180
+ autoIncrement: relation.autoIncrement,
181
+ primary: relation.isPrimary,
182
+ precision: relation.precision,
183
+ scale: relation.scale,
184
+ foreignKeys: [
185
+ {
186
+ referencedColumnName: this.getFkKey(relation),
187
+ referencedTableName: this.get(relation.entity()).tableName,
188
+ },
189
+ ],
190
+ };
191
+ });
192
+ if (!relations) {
193
+ relations = [];
194
+ }
195
+ if (!properties) {
196
+ properties = [];
197
+ }
198
+ return [...properties, ...relations];
199
+ }
200
+ snapshotIndexes(values) {
201
+ return Object.entries(values.properties).map(([key, _value]) => {
202
+ return {
203
+ indexName: key,
204
+ columnName: key,
205
+ table: values.tableName,
206
+ };
207
+ });
208
+ }
209
+ getFkType(relation) {
210
+ const entity = this.get(relation.entity());
211
+ if (!entity) {
212
+ return "unknown";
213
+ }
214
+ const foreignKey = this.getFkKey(relation);
215
+ const property = entity.properties[foreignKey];
216
+ if (!property) {
217
+ return "unknown";
218
+ }
219
+ if (property.options?.dbType) {
220
+ return property.options.dbType;
221
+ }
222
+ return property.type?.name ?? "unknown";
223
+ }
224
+ getFkIncrement(relation) {
225
+ const entity = this.get(relation.entity());
226
+ if (!entity) {
227
+ return "unknown";
228
+ }
229
+ return entity.properties[this.getFkKey(relation)].options.autoIncrement;
230
+ }
231
+ /**
232
+ * If fkKey is null, return the primary key of the entity
233
+ * @private
234
+ * @param relationShip
235
+ */
236
+ getFkKey(relationShip) {
237
+ // se for nullable, deverá retornar o primary key da entidade target
238
+ if (typeof relationShip.fkKey === "undefined") {
239
+ const entity = this.entities.get(relationShip.entity());
240
+ const property = Object.entries(entity.properties).find(([_key, value]) => value.options.isPrimary === true);
241
+ if (!property) {
242
+ throw new Error(`Entity ${entity.tableName} does not have a primary key`);
243
+ }
244
+ return property[0];
245
+ }
246
+ // se o fkKey é uma função, ele retornará a propriedade da entidade que é a chave estrangeira
247
+ // precisamos pegar o nome dessa propriedade
248
+ if (typeof relationShip.fkKey === "string") {
249
+ return relationShip.fkKey;
250
+ }
251
+ const match = /\.(?<propriedade>[\w]+)/.exec(relationShip.fkKey.toString());
252
+ return match ? match.groups.propriedade : "";
253
+ }
254
+ };
255
+ exports.EntityStorage = EntityStorage;
256
+ exports.EntityStorage = EntityStorage = EntityStorage_1 = __decorate([
257
+ (0, core_1.Service)(),
258
+ __metadata("design:paramtypes", [])
259
+ ], EntityStorage);
@@ -0,0 +1,86 @@
1
+ /**
2
+ * Transparent wrapper type to prevent circular dependencies in TypeScript.
3
+ *
4
+ * @example
5
+ * ```typescript
6
+ * // Instead of direct import causing circular dependency:
7
+ * import { User } from './User';
8
+ * class Post {
9
+ * @ManyToOne()
10
+ * author: User; // Circular dependency!
11
+ * }
12
+ *
13
+ * // Use Ref to break the cycle:
14
+ * import type { User } from './User';
15
+ * class Post {
16
+ * @ManyToOne()
17
+ * author: Ref<User>; // No circular dependency!
18
+ * }
19
+ * ```
20
+ */
21
+ export type Ref<T> = T;
22
+ /**
23
+ * Creates a reference to an entity.
24
+ * This is an identity function - it returns the input unchanged.
25
+ * Useful for explicit ref creation when needed.
26
+ *
27
+ * @param entity - The entity to wrap in a reference
28
+ * @returns The same entity (identity function)
29
+ *
30
+ * @example
31
+ * ```typescript
32
+ * const user = new User();
33
+ * const userRef = ref(user); // userRef === user (same reference)
34
+ * ```
35
+ */
36
+ export declare function ref<T>(entity: T): Ref<T>;
37
+ /**
38
+ * Unwraps a reference to get the underlying entity.
39
+ * This is an identity function - it returns the input unchanged.
40
+ * Provided for API consistency and explicitness.
41
+ *
42
+ * @param reference - The reference to unwrap
43
+ * @returns The underlying entity (same as input)
44
+ *
45
+ * @example
46
+ * ```typescript
47
+ * const post = await Post.findOne({ id: 1 });
48
+ * const author = unwrap(post.author); // author === post.author
49
+ * ```
50
+ */
51
+ export declare function unwrap<T>(reference: Ref<T>): T;
52
+ /**
53
+ * Type guard to check if a value is not null or undefined.
54
+ * Useful when working with optional references.
55
+ *
56
+ * @param value - The value to check
57
+ * @returns True if value is not null/undefined
58
+ *
59
+ * @example
60
+ * ```typescript
61
+ * const post = await Post.findOne({ id: 1 });
62
+ * if (isLoaded(post.author)) {
63
+ * console.log(post.author.name); // TypeScript knows author is defined
64
+ * }
65
+ * ```
66
+ */
67
+ export declare function isLoaded<T>(value: Ref<T> | null | undefined): value is Ref<T>;
68
+ /**
69
+ * @deprecated Use `Ref<T>` type instead. This class is kept for backward compatibility.
70
+ */
71
+ export declare class Reference<T> {
72
+ private entity;
73
+ constructor(entity: T);
74
+ get(): T;
75
+ }
76
+ /**
77
+ * Creates a lightweight entity reference by class and id without hitting the DB.
78
+ * Useful to assign many-to-one relations when only the id is known.
79
+ *
80
+ * Example:
81
+ * const library = await UserLibrary.create({
82
+ * user: refById(User, userId),
83
+ * course: refById(Course, courseId),
84
+ * });
85
+ */
86
+ export declare function refById<C extends new () => any, T = InstanceType<C>, PK = any>(Cls: C, id: PK): T;