/
WrappedEntity.ts
117 lines (90 loc) · 3.51 KB
/
WrappedEntity.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
import { inspect } from 'util';
import { EntityManager } from '../EntityManager';
import { AnyEntity, Dictionary, EntityData, EntityMetadata, Populate, PopulateOptions, Primary } from '../typings';
import { IdentifiedReference, Reference } from './Reference';
import { EntityTransformer, SerializationContext } from './EntityTransformer';
import { AssignOptions, EntityAssigner } from './EntityAssigner';
import { Utils } from '../utils/Utils';
import { LockMode } from '../enums';
import { ValidationError } from '../errors';
export class WrappedEntity<T extends AnyEntity<T>, PK extends keyof T> {
__initialized = true;
__populated?: boolean;
__lazyInitialized?: boolean;
__managed?: boolean;
__em?: EntityManager;
__serializationContext: { root?: SerializationContext<T>; populate?: PopulateOptions<T>[] } = {};
/** holds last entity data snapshot so we can compute changes when persisting managed entities */
__originalEntityData?: EntityData<T>;
/** holds wrapped primary key so we can compute change set without eager commit */
__identifier?: EntityData<T>;
constructor(private readonly entity: T,
private readonly pkGetter: (e: T) => Primary<T>,
private readonly pkSerializer: (e: T) => string) { }
isInitialized(): boolean {
return this.__initialized;
}
populated(populated = true): void {
this.__populated = populated;
this.__lazyInitialized = false;
}
toReference(): IdentifiedReference<T, PK> {
return Reference.create<T, PK>(this.entity);
}
toObject(ignoreFields: string[] = []): EntityData<T> {
return EntityTransformer.toObject(this.entity, ignoreFields) as EntityData<T>;
}
toPOJO(): EntityData<T> {
return EntityTransformer.toObject(this.entity, [], true);
}
toJSON(...args: any[]): EntityData<T> & Dictionary {
// toJSON methods is added to thee prototype during discovery to support automatic serialization via JSON.stringify()
return (this.entity as Dictionary).toJSON(...args);
}
assign(data: EntityData<T>, options?: AssignOptions): T {
if ('assign' in this.entity) {
return (this.entity as Dictionary).assign(data, options);
}
return EntityAssigner.assign(this.entity, data, options);
}
async init<P extends Populate<T> = Populate<T>>(populated = true, populate?: P, lockMode?: LockMode): Promise<T> {
if (!this.__em) {
throw ValidationError.entityNotManaged(this.entity);
}
await this.__em.findOne(this.entity.constructor.name, this.entity, { refresh: true, lockMode, populate });
this.populated(populated);
this.__lazyInitialized = true;
return this.entity;
}
hasPrimaryKey(): boolean {
const pk = this.getPrimaryKey();
return pk !== undefined && pk !== null;
}
getPrimaryKey(): Primary<T> | null {
return this.pkGetter(this.entity);
}
setPrimaryKey(id: Primary<T> | null) {
this.entity[this.entity.__meta!.primaryKeys[0] as string] = id;
}
getSerializedPrimaryKey(): string {
return this.pkSerializer(this.entity);
}
get __meta(): EntityMetadata<T> {
return this.entity.__meta!;
}
get __platform() {
return this.entity.__platform!;
}
get __primaryKeys(): Primary<T>[] {
return Utils.getPrimaryKeyValues(this.entity, this.entity.__meta!.primaryKeys);
}
get __primaryKeyCond(): Primary<T> | Primary<T>[] | null {
if (this.entity.__meta!.compositePK) {
return this.__primaryKeys;
}
return this.getPrimaryKey();
}
[inspect.custom]() {
return `[WrappedEntity<${this.entity.__meta!.className}>]`;
}
}