pangea-server 1.0.58 → 1.0.60
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.
|
@@ -4,30 +4,23 @@ type AttributeOp = 'COUNT' | 'SUM';
|
|
|
4
4
|
type AttributeColumn = AttributeField | [AttributeOp, AttributeField];
|
|
5
5
|
type AttributeAlias = string;
|
|
6
6
|
type Attributes = Record<AttributeAlias, AttributeColumn>;
|
|
7
|
-
type IncludeItem = {
|
|
8
|
-
relation?: string;
|
|
9
|
-
active?: boolean;
|
|
10
|
-
include?: IncludeItem[];
|
|
11
|
-
};
|
|
12
7
|
type Filters<BM extends BaseModel> = ModelId | Where<BM> | undefined;
|
|
13
8
|
type Group = string[];
|
|
14
9
|
type Order = Record<string, 'asc' | 'desc'>;
|
|
15
10
|
type FindOneOptions = {
|
|
16
11
|
scopes?: string[];
|
|
17
12
|
attributes?: Attributes;
|
|
18
|
-
include?: IncludeItem[];
|
|
19
13
|
order?: Order;
|
|
20
14
|
paranoid?: boolean;
|
|
21
15
|
};
|
|
22
16
|
type FindManyOptions<BM extends BaseModel> = {
|
|
23
17
|
attributes?: Attributes;
|
|
24
|
-
include?: IncludeItem[];
|
|
25
18
|
where?: Where<BM>;
|
|
26
19
|
searchFields?: string[];
|
|
27
20
|
search?: string | null;
|
|
28
21
|
group?: Group;
|
|
29
22
|
order?: Order;
|
|
30
|
-
paranoid?:
|
|
23
|
+
paranoid?: boolean;
|
|
31
24
|
};
|
|
32
25
|
type FindManyPagedOptions<BM extends BaseModel> = FindManyOptions<BM> & {
|
|
33
26
|
page?: number | null;
|
|
@@ -13,20 +13,20 @@ class Db {
|
|
|
13
13
|
}
|
|
14
14
|
// find methods
|
|
15
15
|
findOneOrNull(model, filters, options = {}) {
|
|
16
|
-
const { scopes
|
|
17
|
-
const scopedModel = scopes
|
|
16
|
+
const { scopes, attributes, order, paranoid = true } = options;
|
|
17
|
+
const scopedModel = scopes?.length ? model.scope(...scopes) : model;
|
|
18
18
|
const baseOptions = {
|
|
19
|
-
attributes: getFinalAttributes(attributes),
|
|
19
|
+
attributes: getFinalAttributes(model, attributes),
|
|
20
20
|
paranoid,
|
|
21
21
|
subQuery: false,
|
|
22
22
|
transaction: this.__tx,
|
|
23
23
|
};
|
|
24
24
|
if (typeof filters === 'number') {
|
|
25
|
-
return scopedModel.findByPk(filters, { ...baseOptions, ...
|
|
25
|
+
return scopedModel.findByPk(filters, { ...baseOptions, ...getInclude(model) });
|
|
26
26
|
}
|
|
27
27
|
return scopedModel.findOne({
|
|
28
28
|
...baseOptions,
|
|
29
|
-
...
|
|
29
|
+
...getInclude(model, { attributes, where: filters }),
|
|
30
30
|
order: getFinalOrder(order),
|
|
31
31
|
});
|
|
32
32
|
}
|
|
@@ -67,7 +67,7 @@ class Db {
|
|
|
67
67
|
return { instances, totalCount: instances.length };
|
|
68
68
|
}
|
|
69
69
|
__getFindManyBaseOptions(model, options = {}) {
|
|
70
|
-
const { attributes,
|
|
70
|
+
const { attributes, where, searchFields, search, group, order, paranoid = true } = options;
|
|
71
71
|
let searchWhere;
|
|
72
72
|
if (searchFields?.length && search) {
|
|
73
73
|
const searchWords = search.split(/\s+/).filter(Boolean);
|
|
@@ -80,13 +80,12 @@ class Db {
|
|
|
80
80
|
})),
|
|
81
81
|
};
|
|
82
82
|
}
|
|
83
|
-
const deletedAtWhere = paranoid === 'deleted' ? { deletedAt: { [_1.Ops.not]: null } } : {};
|
|
84
83
|
return {
|
|
85
|
-
attributes: getFinalAttributes(attributes),
|
|
86
|
-
...
|
|
84
|
+
attributes: getFinalAttributes(model, attributes),
|
|
85
|
+
...getInclude(model, { attributes, where: { ...where, ...searchWhere } }),
|
|
87
86
|
...(group && { group: group.map(pangea_helpers_1.camelToSnake) }),
|
|
88
|
-
order:
|
|
89
|
-
paranoid
|
|
87
|
+
order: getFinalOrder(order),
|
|
88
|
+
paranoid,
|
|
90
89
|
subQuery: false,
|
|
91
90
|
transaction: this.__tx,
|
|
92
91
|
};
|
|
@@ -184,14 +183,17 @@ class Db {
|
|
|
184
183
|
}
|
|
185
184
|
exports.Db = Db;
|
|
186
185
|
// internal functions
|
|
187
|
-
function getFinalAttributes(attributes) {
|
|
186
|
+
function getFinalAttributes(model, attributes) {
|
|
188
187
|
if (!attributes)
|
|
189
188
|
return;
|
|
190
189
|
return Object.entries(attributes).map(([alias, column]) => {
|
|
191
|
-
if (typeof column === 'string')
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
190
|
+
if (typeof column === 'string') {
|
|
191
|
+
const field = column.includes('.') ? column : `${model.name}.${(0, pangea_helpers_1.camelToSnake)(column)}`;
|
|
192
|
+
return [(0, sequelize_1.col)(field), alias];
|
|
193
|
+
}
|
|
194
|
+
const [op, fieldName] = column;
|
|
195
|
+
const field = fieldName.includes('.') ? fieldName : `${model.name}.${(0, pangea_helpers_1.camelToSnake)(fieldName)}`;
|
|
196
|
+
return [(0, sequelize_1.fn)(op, (0, sequelize_1.col)(field)), alias];
|
|
195
197
|
});
|
|
196
198
|
}
|
|
197
199
|
function convertWhereKeys(obj) {
|
|
@@ -223,17 +225,16 @@ function convertWhereKeys(obj) {
|
|
|
223
225
|
}
|
|
224
226
|
return obj;
|
|
225
227
|
}
|
|
226
|
-
function
|
|
228
|
+
function getInclude(model, config = {}, relDepth = new Map()) {
|
|
227
229
|
const includeOptions = [];
|
|
228
|
-
const cleanWhere = { ...where };
|
|
230
|
+
const cleanWhere = { ...config.where };
|
|
229
231
|
for (const [relName, rel] of Object.entries(model.Relations)) {
|
|
230
232
|
const relKey = `${model.name}.${relName}`;
|
|
231
233
|
const currentDepth = relDepth.get(relKey) || 0;
|
|
232
234
|
const maxDepth = rel.joinDepth;
|
|
233
235
|
if (currentDepth >= maxDepth)
|
|
234
236
|
continue;
|
|
235
|
-
|
|
236
|
-
if (!rel.eager || !active)
|
|
237
|
+
if (!rel.eager)
|
|
237
238
|
continue;
|
|
238
239
|
const relWhere = cleanWhere[relName];
|
|
239
240
|
delete cleanWhere[relName];
|
|
@@ -242,11 +243,11 @@ function getIncludeAndWhere(model, includeItems, config = {}, where, relDepth =
|
|
|
242
243
|
const relModel = rel.getModelFn();
|
|
243
244
|
includeOptions.push({
|
|
244
245
|
model: relModel,
|
|
245
|
-
as: rel.
|
|
246
|
-
attributes: !config.
|
|
246
|
+
as: rel.alias,
|
|
247
|
+
attributes: !config.attributes ? undefined : [],
|
|
247
248
|
required: rel.required,
|
|
248
249
|
paranoid: rel.paranoid,
|
|
249
|
-
...
|
|
250
|
+
...getInclude(relModel, { ...config, where: relWhere }, newRelDepth),
|
|
250
251
|
});
|
|
251
252
|
}
|
|
252
253
|
return {
|
|
@@ -254,12 +255,15 @@ function getIncludeAndWhere(model, includeItems, config = {}, where, relDepth =
|
|
|
254
255
|
...(Reflect.ownKeys(cleanWhere).length && { where: convertWhereKeys(cleanWhere) }),
|
|
255
256
|
};
|
|
256
257
|
}
|
|
257
|
-
function getFinalOrder(order) {
|
|
258
|
-
|
|
258
|
+
function getFinalOrder(order, config = {}) {
|
|
259
|
+
if (!order)
|
|
260
|
+
return;
|
|
261
|
+
const finalOrder = Object.entries(order).map(([key, value]) => {
|
|
259
262
|
const parts = key.split('.');
|
|
260
263
|
const direction = value.toUpperCase();
|
|
261
264
|
return [...parts, direction];
|
|
262
265
|
});
|
|
266
|
+
return [...finalOrder, ...(!config.attributes ? [['createdAt', 'DESC']] : [])];
|
|
263
267
|
}
|
|
264
268
|
async function handleDbError(operation) {
|
|
265
269
|
try {
|
|
@@ -35,11 +35,11 @@ function getRelation(relationFn) {
|
|
|
35
35
|
return function (getModelFn, options = {}) {
|
|
36
36
|
return function (target, propertyName) {
|
|
37
37
|
const { foreignKey, ...relOptions } = options;
|
|
38
|
-
const
|
|
39
|
-
relationFn(getModelFn, { as, ...(foreignKey && { foreignKey }) })(target, propertyName);
|
|
38
|
+
const alias = (0, pangea_helpers_1.camelToSnake)(propertyName);
|
|
39
|
+
relationFn(getModelFn, { as: alias, ...(foreignKey && { foreignKey }) })(target, propertyName);
|
|
40
40
|
const model = target.constructor;
|
|
41
41
|
const { eager = relationFn !== seq.HasMany, required = relationFn === seq.BelongsTo ? !model.Columns[`${propertyName}Id`].allowNull : false, paranoid = relationFn !== seq.BelongsTo, joinDepth = 1, ...restOptions } = relOptions;
|
|
42
|
-
model.AddRelation(propertyName, {
|
|
42
|
+
model.AddRelation(propertyName, { alias, getModelFn, eager, required, paranoid, joinDepth, ...restOptions });
|
|
43
43
|
};
|
|
44
44
|
};
|
|
45
45
|
}
|
|
@@ -35,17 +35,13 @@ function Table(tableName, options = {}) {
|
|
|
35
35
|
const allIndexes = [...tableIndexes, ...columnIndexes];
|
|
36
36
|
seq.Table({
|
|
37
37
|
tableName,
|
|
38
|
-
// modelName: camelToSnake(target.name), // 'as' in SQL query
|
|
39
38
|
charset: 'utf8mb4',
|
|
40
39
|
collate: 'utf8mb4_general_ci',
|
|
41
40
|
underscored: true,
|
|
42
41
|
timestamps: true,
|
|
43
42
|
paranoid: true,
|
|
44
43
|
indexes: allIndexes.map(({ field, fields, ...restIndex }) => {
|
|
45
|
-
return {
|
|
46
|
-
...restIndex,
|
|
47
|
-
fields: fields ? fields.map(pangea_helpers_1.camelToSnake) : field ? [(0, pangea_helpers_1.camelToSnake)(field)] : [],
|
|
48
|
-
};
|
|
44
|
+
return { ...restIndex, fields: fields ? fields.map(pangea_helpers_1.camelToSnake) : field ? [(0, pangea_helpers_1.camelToSnake)(field)] : [] };
|
|
49
45
|
}),
|
|
50
46
|
})(target);
|
|
51
47
|
const excludedAttributes = target.ExcludedAttributes;
|