-
Notifications
You must be signed in to change notification settings - Fork 286
/
Copy pathmodel-service.ts
110 lines (93 loc) · 3 KB
/
model-service.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
import { DataTypeAbstract, ModelOptions } from 'sequelize';
import { Model } from '../model/model';
import { inferDataType } from '../../sequelize/data-type/data-type-service';
const MODEL_NAME_KEY = 'sequelize:modelName';
const OPTIONS_KEY = 'sequelize:options';
/**
* Sets model name from class by storing this
* information through reflect metadata
*/
export function setModelName(target: any, modelName: string): void {
Reflect.defineMetadata(MODEL_NAME_KEY, modelName, target);
}
/**
* Returns model name from class by restoring this
* information from reflect metadata
*/
export function getModelName(target: any): string {
return Reflect.getMetadata(MODEL_NAME_KEY, target);
}
/**
* Returns sequelize define options from class prototype
* by restoring this information from reflect metadata
*/
export function getOptions(target: any): ModelOptions | undefined {
const options = Reflect.getMetadata(OPTIONS_KEY, target);
if (options) {
return { ...options };
}
}
/**
* Sets seuqlize define options to class prototype
*/
export function setOptions(target: any, options: ModelOptions<any>): void {
Reflect.defineMetadata(OPTIONS_KEY, { ...options }, target);
}
/**
* Adds options be assigning new options to old one
*/
export function addOptions(target: any, options: ModelOptions<any>): void {
let _options = getOptions(target);
if (!_options) {
_options = {};
}
setOptions(target, {
..._options,
...options,
validate: {
...(_options.validate || {}),
...(options.validate || {}),
},
});
}
/**
* Maps design types to sequelize data types;
* @throws if design type cannot be automatically mapped to
* a sequelize data type
*/
export function getSequelizeTypeByDesignType(target: any, propertyName: string): DataTypeAbstract {
const type = Reflect.getMetadata('design:type', target, propertyName);
const dataType = inferDataType(type);
if (dataType) {
return dataType;
}
throw new Error(`Specified type of property '${propertyName}'
cannot be automatically resolved to a sequelize data type. Please
define the data type manually`);
}
/**
* Resolves all model getters of specified options object
* recursively.
* So that {model: () => Person} will be converted to
* {model: Person}
*/
export function resolveModelGetter(options: any): any {
const maybeModelGetter = (value) => typeof value === 'function' && value.length === 0;
const isModel = (value) => value && value.prototype && value.prototype instanceof Model;
const isOptionObjectOrArray = (value) => value && typeof value === 'object';
return Object.keys(options).reduce(
(acc, key) => {
const value = options[key];
if (maybeModelGetter(value)) {
const maybeModel = value();
if (isModel(maybeModel)) {
acc[key] = maybeModel;
}
} else if (isOptionObjectOrArray(value)) {
acc[key] = resolveModelGetter(value);
}
return acc;
},
Array.isArray(options) ? [...options] : { ...options }
);
}