@ruiapp/rapid-core 0.2.7 → 0.2.9
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/dist/dataAccess/dataAccessor.d.ts +1 -1
- package/dist/dataAccess/entityManager.d.ts +2 -2
- package/dist/index.js +73 -21
- package/dist/types.d.ts +12 -1
- package/package.json +1 -1
- package/src/dataAccess/dataAccessor.ts +3 -5
- package/src/dataAccess/entityManager.ts +83 -16
- package/src/plugins/dataManage/actionHandlers/countCollectionEntities.ts +4 -3
- package/src/plugins/dataManage/actionHandlers/findCollectionEntities.ts +2 -2
- package/src/plugins/dataManage/actionHandlers/updateCollectionEntityById.ts +6 -0
- package/src/types.ts +15 -1
|
@@ -17,6 +17,6 @@ export default class DataAccessor<T = any> implements IRpdDataAccessor<T> {
|
|
|
17
17
|
find(options: FindRowOptions): Promise<T[]>;
|
|
18
18
|
findOne(options: FindRowOptions): Promise<T>;
|
|
19
19
|
findById(id: any): Promise<T | null>;
|
|
20
|
-
count(options: CountRowOptions): Promise<
|
|
20
|
+
count(options: CountRowOptions): Promise<number>;
|
|
21
21
|
deleteById(id: any): Promise<void>;
|
|
22
22
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AddEntityRelationsOptions, CountEntityOptions,
|
|
1
|
+
import { AddEntityRelationsOptions, CountEntityOptions, CreateEntityOptions, DeleteEntityByIdOptions, FindEntityByIdOptions, FindEntityOptions, IRpdDataAccessor, RemoveEntityRelationsOptions, RpdDataModel, RpdDataModelIndex, RpdDataModelProperty, UpdateEntityByIdOptions, FindEntityFindOneRelationEntitiesOptions, FindEntityFindManyRelationEntitiesOptions } from "../types";
|
|
2
2
|
import { IRpdServer, RapidPlugin } from "../core/server";
|
|
3
3
|
import { RouteContext } from "../core/routeContext";
|
|
4
4
|
export type FindOneRelationEntitiesOptions = {
|
|
@@ -30,7 +30,7 @@ export default class EntityManager<TEntity = any> {
|
|
|
30
30
|
findById(options: FindEntityByIdOptions | string | number): Promise<TEntity | null>;
|
|
31
31
|
createEntity(options: CreateEntityOptions, plugin?: RapidPlugin): Promise<TEntity>;
|
|
32
32
|
updateEntityById(options: UpdateEntityByIdOptions, plugin?: RapidPlugin): Promise<TEntity>;
|
|
33
|
-
count(options: CountEntityOptions): Promise<
|
|
33
|
+
count(options: CountEntityOptions): Promise<number>;
|
|
34
34
|
deleteById(options: DeleteEntityByIdOptions | string | number, plugin?: RapidPlugin): Promise<void>;
|
|
35
35
|
addRelations(options: AddEntityRelationsOptions, plugin?: RapidPlugin): Promise<void>;
|
|
36
36
|
removeRelations(options: RemoveEntityRelationsOptions, plugin?: RapidPlugin): Promise<void>;
|
package/dist/index.js
CHANGED
|
@@ -159,11 +159,9 @@ class DataAccessor {
|
|
|
159
159
|
const result = await this.#databaseAccessor.queryDatabaseObject(query.command, query.params);
|
|
160
160
|
const row = lodash.first(result);
|
|
161
161
|
if (row) {
|
|
162
|
-
return row;
|
|
162
|
+
return row.count;
|
|
163
163
|
}
|
|
164
|
-
return
|
|
165
|
-
count: 0,
|
|
166
|
-
};
|
|
164
|
+
return 0;
|
|
167
165
|
}
|
|
168
166
|
async deleteById(id) {
|
|
169
167
|
const options = {
|
|
@@ -3254,15 +3252,15 @@ async function updateEntityById(server, dataAccessor, options, plugin) {
|
|
|
3254
3252
|
const updatedEntityOneRelationProps = {};
|
|
3255
3253
|
for (const property of oneRelationPropertiesToUpdate) {
|
|
3256
3254
|
const rowToBeSaved = property.isBaseProperty ? baseRow : row;
|
|
3257
|
-
const
|
|
3255
|
+
const relatedEntityToBeSaved = changes[property.code];
|
|
3258
3256
|
const targetDataAccessor = server.getDataAccessor({
|
|
3259
3257
|
singularCode: property.targetSingularCode,
|
|
3260
3258
|
});
|
|
3261
|
-
if (lodash.isObject(
|
|
3262
|
-
const
|
|
3263
|
-
if (!
|
|
3259
|
+
if (lodash.isObject(relatedEntityToBeSaved)) {
|
|
3260
|
+
const relatedEntityId = relatedEntityToBeSaved["id"];
|
|
3261
|
+
if (!relatedEntityId) {
|
|
3264
3262
|
if (!property.selfIdColumnName) {
|
|
3265
|
-
const targetEntity =
|
|
3263
|
+
const targetEntity = relatedEntityToBeSaved;
|
|
3266
3264
|
const newTargetEntity = await createEntity(server, targetDataAccessor, {
|
|
3267
3265
|
routeContext,
|
|
3268
3266
|
entity: targetEntity,
|
|
@@ -3272,20 +3270,44 @@ async function updateEntityById(server, dataAccessor, options, plugin) {
|
|
|
3272
3270
|
}
|
|
3273
3271
|
}
|
|
3274
3272
|
else {
|
|
3275
|
-
|
|
3276
|
-
id:
|
|
3273
|
+
let targetEntity = await findById(server, targetDataAccessor, {
|
|
3274
|
+
id: relatedEntityId,
|
|
3277
3275
|
routeContext,
|
|
3278
3276
|
});
|
|
3279
3277
|
if (!targetEntity) {
|
|
3280
|
-
throw newEntityOperationError(`
|
|
3278
|
+
throw newEntityOperationError(`Update ${model.singularCode} entity failed. Property '${property.code}' was invalid. Related ${property.targetSingularCode} entity with id '${relatedEntityId}' was not found.`);
|
|
3279
|
+
}
|
|
3280
|
+
// update relation entity if options.relationPropertiesToUpdate is specified.
|
|
3281
|
+
const updateRelationPropertiesOptions = lodash.get(options.relationPropertiesToUpdate, property.code);
|
|
3282
|
+
let subRelationPropertiesToUpdate = undefined;
|
|
3283
|
+
let relationEntityToUpdate = null;
|
|
3284
|
+
if (updateRelationPropertiesOptions === true) {
|
|
3285
|
+
relationEntityToUpdate = targetEntity;
|
|
3286
|
+
}
|
|
3287
|
+
else if (updateRelationPropertiesOptions) {
|
|
3288
|
+
let propertiesToUpdate = lodash.uniq([
|
|
3289
|
+
"id",
|
|
3290
|
+
...(updateRelationPropertiesOptions.propertiesToUpdate || []),
|
|
3291
|
+
...Object.keys(updateRelationPropertiesOptions.relationPropertiesToUpdate || []),
|
|
3292
|
+
]);
|
|
3293
|
+
relationEntityToUpdate = lodash.pick(relatedEntityToBeSaved, propertiesToUpdate);
|
|
3294
|
+
subRelationPropertiesToUpdate = updateRelationPropertiesOptions.relationPropertiesToUpdate;
|
|
3295
|
+
}
|
|
3296
|
+
if (relationEntityToUpdate) {
|
|
3297
|
+
targetEntity = await updateEntityById(server, targetDataAccessor, {
|
|
3298
|
+
routeContext: routeContext,
|
|
3299
|
+
id: relatedEntityId,
|
|
3300
|
+
entityToSave: relationEntityToUpdate,
|
|
3301
|
+
relationPropertiesToUpdate: subRelationPropertiesToUpdate,
|
|
3302
|
+
});
|
|
3281
3303
|
}
|
|
3282
3304
|
updatedEntityOneRelationProps[property.code] = targetEntity;
|
|
3283
|
-
rowToBeSaved[property.targetIdColumnName] =
|
|
3305
|
+
rowToBeSaved[property.targetIdColumnName] = relatedEntityId;
|
|
3284
3306
|
}
|
|
3285
3307
|
}
|
|
3286
|
-
else if (lodash.isNumber(
|
|
3308
|
+
else if (lodash.isNumber(relatedEntityToBeSaved) || lodash.isString(relatedEntityToBeSaved)) {
|
|
3287
3309
|
// fieldValue is id;
|
|
3288
|
-
const targetEntityId =
|
|
3310
|
+
const targetEntityId = relatedEntityToBeSaved;
|
|
3289
3311
|
const targetEntity = await findById(server, targetDataAccessor, {
|
|
3290
3312
|
id: targetEntityId,
|
|
3291
3313
|
routeContext,
|
|
@@ -3419,9 +3441,33 @@ async function updateEntityById(server, dataAccessor, options, plugin) {
|
|
|
3419
3441
|
}
|
|
3420
3442
|
else {
|
|
3421
3443
|
// related entity is existed
|
|
3422
|
-
|
|
3444
|
+
let targetEntity = await targetDataAccessor.findById(relatedEntityId);
|
|
3423
3445
|
if (!targetEntity) {
|
|
3424
|
-
throw new Error(`Entity with id '${relatedEntityId}' in field '${property.code}'
|
|
3446
|
+
throw new Error(`Entity with id '${relatedEntityId}' in field '${property.code}' does not exist.`);
|
|
3447
|
+
}
|
|
3448
|
+
// update relation entity if options.relationPropertiesToUpdate is specified.
|
|
3449
|
+
const updateRelationPropertiesOptions = lodash.get(options.relationPropertiesToUpdate, property.code);
|
|
3450
|
+
let subRelationPropertiesToUpdate = undefined;
|
|
3451
|
+
let relationEntityToUpdate = null;
|
|
3452
|
+
if (updateRelationPropertiesOptions === true) {
|
|
3453
|
+
relationEntityToUpdate = targetEntity;
|
|
3454
|
+
}
|
|
3455
|
+
else if (updateRelationPropertiesOptions) {
|
|
3456
|
+
let propertiesToUpdate = lodash.uniq([
|
|
3457
|
+
"id",
|
|
3458
|
+
...(updateRelationPropertiesOptions.propertiesToUpdate || []),
|
|
3459
|
+
...Object.keys(updateRelationPropertiesOptions.relationPropertiesToUpdate || []),
|
|
3460
|
+
]);
|
|
3461
|
+
relationEntityToUpdate = lodash.pick(relatedEntityToBeSaved, propertiesToUpdate);
|
|
3462
|
+
subRelationPropertiesToUpdate = updateRelationPropertiesOptions.relationPropertiesToUpdate;
|
|
3463
|
+
}
|
|
3464
|
+
if (relationEntityToUpdate) {
|
|
3465
|
+
targetEntity = await updateEntityById(server, targetDataAccessor, {
|
|
3466
|
+
routeContext: routeContext,
|
|
3467
|
+
id: relatedEntityId,
|
|
3468
|
+
entityToSave: relationEntityToUpdate,
|
|
3469
|
+
relationPropertiesToUpdate: subRelationPropertiesToUpdate,
|
|
3470
|
+
});
|
|
3425
3471
|
}
|
|
3426
3472
|
if (!currentTargetIds.includes(relatedEntityId)) {
|
|
3427
3473
|
if (property.linkTableName) {
|
|
@@ -4790,8 +4836,8 @@ async function handler$q(plugin, ctx, options) {
|
|
|
4790
4836
|
const result = { list: entities };
|
|
4791
4837
|
if (input.pagination && !input.pagination.withoutTotal) {
|
|
4792
4838
|
// TOOD: count entities when calling findEntities for performance.
|
|
4793
|
-
const
|
|
4794
|
-
result.total =
|
|
4839
|
+
const total = await entityManager.count(input);
|
|
4840
|
+
result.total = total;
|
|
4795
4841
|
}
|
|
4796
4842
|
return result;
|
|
4797
4843
|
});
|
|
@@ -4827,10 +4873,11 @@ var findCollectionEntityById = /*#__PURE__*/Object.freeze({
|
|
|
4827
4873
|
|
|
4828
4874
|
const code$o = "countCollectionEntities";
|
|
4829
4875
|
async function handler$o(plugin, ctx, options) {
|
|
4830
|
-
await runCollectionEntityActionHandler(ctx, options, code$o, (entityManager, input) => {
|
|
4876
|
+
await runCollectionEntityActionHandler(ctx, options, code$o, async (entityManager, input) => {
|
|
4831
4877
|
input.filters = removeFiltersWithNullValue(input.filters);
|
|
4832
4878
|
input.routeContext = ctx.routerContext;
|
|
4833
|
-
|
|
4879
|
+
const count = await entityManager.count(input);
|
|
4880
|
+
return { count };
|
|
4834
4881
|
});
|
|
4835
4882
|
}
|
|
4836
4883
|
|
|
@@ -4906,11 +4953,16 @@ async function handler$l(plugin, ctx, options) {
|
|
|
4906
4953
|
if (stateProperties) {
|
|
4907
4954
|
delete mergedInput.$stateProperties;
|
|
4908
4955
|
}
|
|
4956
|
+
const relationPropertiesToUpdate = mergedInput.$relationPropertiesToUpdate;
|
|
4957
|
+
if (relationPropertiesToUpdate) {
|
|
4958
|
+
delete mergedInput.$relationPropertiesToUpdate;
|
|
4959
|
+
}
|
|
4909
4960
|
const updateEntityByIdOptions = {
|
|
4910
4961
|
id: mergedInput.id,
|
|
4911
4962
|
entityToSave: mergedInput,
|
|
4912
4963
|
operation,
|
|
4913
4964
|
stateProperties,
|
|
4965
|
+
relationPropertiesToUpdate,
|
|
4914
4966
|
routeContext: ctx.routerContext,
|
|
4915
4967
|
};
|
|
4916
4968
|
const entityManager = server.getEntityManager(options.singularCode);
|
package/dist/types.d.ts
CHANGED
|
@@ -377,7 +377,7 @@ export interface IRpdDataAccessor<T = any> {
|
|
|
377
377
|
find(options: FindRowOptions): Promise<T[]>;
|
|
378
378
|
findOne(options: FindRowOptions): Promise<T | null>;
|
|
379
379
|
findById(id: any): Promise<T | null>;
|
|
380
|
-
count(options: CountRowOptions): Promise<
|
|
380
|
+
count(options: CountRowOptions): Promise<number>;
|
|
381
381
|
deleteById(id: any): Promise<void>;
|
|
382
382
|
}
|
|
383
383
|
export type EntityFilterRelationalOperators = "eq" | "ne" | "lt" | "lte" | "gt" | "gte" | "contains" | "notContains" | "containsCS" | "notContainsCS" | "startsWith" | "notStartsWith" | "endsWith" | "notEndsWith";
|
|
@@ -487,9 +487,20 @@ export interface UpdateEntityByIdOptions {
|
|
|
487
487
|
operation?: {
|
|
488
488
|
type: string;
|
|
489
489
|
};
|
|
490
|
+
/**
|
|
491
|
+
* 指定需要更新那几个状态属性(配置了`config.stateMachine`的属性)。当不指定时默认更新全部状态属性。
|
|
492
|
+
*/
|
|
490
493
|
stateProperties?: string[];
|
|
491
494
|
postponeUniquenessCheck?: boolean;
|
|
495
|
+
/**
|
|
496
|
+
* 指定需要更新关联对象的哪些属性。更新实体时,会创建关联对象,但是默认不更新关联对象的属性。
|
|
497
|
+
*/
|
|
498
|
+
relationPropertiesToUpdate?: Record<string, UpdateRelationPropertiesOptions>;
|
|
492
499
|
}
|
|
500
|
+
export type UpdateRelationPropertiesOptions = true | {
|
|
501
|
+
propertiesToUpdate?: string[];
|
|
502
|
+
relationPropertiesToUpdate?: Record<string, UpdateRelationPropertiesOptions>;
|
|
503
|
+
};
|
|
493
504
|
export interface DeleteEntityOptions {
|
|
494
505
|
routeContext?: RouteContext;
|
|
495
506
|
filters?: EntityFilterOptions[];
|
package/package.json
CHANGED
|
@@ -98,7 +98,7 @@ export default class DataAccessor<T = any> implements IRpdDataAccessor<T> {
|
|
|
98
98
|
return result;
|
|
99
99
|
}
|
|
100
100
|
|
|
101
|
-
async count(options: CountRowOptions): Promise<
|
|
101
|
+
async count(options: CountRowOptions): Promise<number> {
|
|
102
102
|
let query: DatabaseQuery;
|
|
103
103
|
if (this.#model.base) {
|
|
104
104
|
const baseModel = this.#server.getModel({
|
|
@@ -112,11 +112,9 @@ export default class DataAccessor<T = any> implements IRpdDataAccessor<T> {
|
|
|
112
112
|
|
|
113
113
|
const row = first(result);
|
|
114
114
|
if (row) {
|
|
115
|
-
return row;
|
|
115
|
+
return row.count;
|
|
116
116
|
}
|
|
117
|
-
return
|
|
118
|
-
count: 0,
|
|
119
|
-
};
|
|
117
|
+
return 0;
|
|
120
118
|
}
|
|
121
119
|
|
|
122
120
|
async deleteById(id: any) {
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
AddEntityRelationsOptions,
|
|
3
3
|
CountEntityOptions,
|
|
4
|
-
CountEntityResult,
|
|
5
4
|
CreateEntityOptions,
|
|
6
5
|
DeleteEntityByIdOptions,
|
|
7
6
|
EntityFilterOperators,
|
|
@@ -25,7 +24,26 @@ import { mapDbRowToEntity, mapEntityToDbRow } from "./entityMapper";
|
|
|
25
24
|
import { mapPropertyNameToColumnName } from "./propertyMapper";
|
|
26
25
|
import { IRpdServer, RapidPlugin } from "~/core/server";
|
|
27
26
|
import { getEntityPartChanges } from "~/helpers/entityHelpers";
|
|
28
|
-
import {
|
|
27
|
+
import {
|
|
28
|
+
cloneDeep,
|
|
29
|
+
concat,
|
|
30
|
+
filter,
|
|
31
|
+
find,
|
|
32
|
+
first,
|
|
33
|
+
forEach,
|
|
34
|
+
get,
|
|
35
|
+
isArray,
|
|
36
|
+
isNumber,
|
|
37
|
+
isObject,
|
|
38
|
+
isPlainObject,
|
|
39
|
+
isString,
|
|
40
|
+
isUndefined,
|
|
41
|
+
keys,
|
|
42
|
+
map,
|
|
43
|
+
pick,
|
|
44
|
+
reject,
|
|
45
|
+
uniq,
|
|
46
|
+
} from "lodash";
|
|
29
47
|
import {
|
|
30
48
|
getEntityPropertiesIncludingBase,
|
|
31
49
|
getEntityProperty,
|
|
@@ -1104,16 +1122,16 @@ async function updateEntityById(server: IRpdServer, dataAccessor: IRpdDataAccess
|
|
|
1104
1122
|
const updatedEntityOneRelationProps = {};
|
|
1105
1123
|
for (const property of oneRelationPropertiesToUpdate) {
|
|
1106
1124
|
const rowToBeSaved = property.isBaseProperty ? baseRow : row;
|
|
1107
|
-
const
|
|
1125
|
+
const relatedEntityToBeSaved = changes[property.code];
|
|
1108
1126
|
const targetDataAccessor = server.getDataAccessor({
|
|
1109
1127
|
singularCode: property.targetSingularCode!,
|
|
1110
1128
|
});
|
|
1111
1129
|
|
|
1112
|
-
if (isObject(
|
|
1113
|
-
const
|
|
1114
|
-
if (!
|
|
1130
|
+
if (isObject(relatedEntityToBeSaved)) {
|
|
1131
|
+
const relatedEntityId = relatedEntityToBeSaved["id"];
|
|
1132
|
+
if (!relatedEntityId) {
|
|
1115
1133
|
if (!property.selfIdColumnName) {
|
|
1116
|
-
const targetEntity =
|
|
1134
|
+
const targetEntity = relatedEntityToBeSaved;
|
|
1117
1135
|
const newTargetEntity = await createEntity(server, targetDataAccessor, {
|
|
1118
1136
|
routeContext,
|
|
1119
1137
|
entity: targetEntity,
|
|
@@ -1122,21 +1140,46 @@ async function updateEntityById(server: IRpdServer, dataAccessor: IRpdDataAccess
|
|
|
1122
1140
|
rowToBeSaved[property.targetIdColumnName!] = newTargetEntity["id"];
|
|
1123
1141
|
}
|
|
1124
1142
|
} else {
|
|
1125
|
-
|
|
1126
|
-
id:
|
|
1143
|
+
let targetEntity = await findById(server, targetDataAccessor, {
|
|
1144
|
+
id: relatedEntityId,
|
|
1127
1145
|
routeContext,
|
|
1128
1146
|
});
|
|
1129
1147
|
if (!targetEntity) {
|
|
1130
1148
|
throw newEntityOperationError(
|
|
1131
|
-
`
|
|
1149
|
+
`Update ${model.singularCode} entity failed. Property '${property.code}' was invalid. Related ${property.targetSingularCode} entity with id '${relatedEntityId}' was not found.`,
|
|
1132
1150
|
);
|
|
1133
1151
|
}
|
|
1152
|
+
|
|
1153
|
+
// update relation entity if options.relationPropertiesToUpdate is specified.
|
|
1154
|
+
const updateRelationPropertiesOptions = get(options.relationPropertiesToUpdate, property.code);
|
|
1155
|
+
let subRelationPropertiesToUpdate = undefined;
|
|
1156
|
+
let relationEntityToUpdate = null;
|
|
1157
|
+
if (updateRelationPropertiesOptions === true) {
|
|
1158
|
+
relationEntityToUpdate = targetEntity;
|
|
1159
|
+
} else if (updateRelationPropertiesOptions) {
|
|
1160
|
+
let propertiesToUpdate = uniq([
|
|
1161
|
+
"id",
|
|
1162
|
+
...(updateRelationPropertiesOptions.propertiesToUpdate || []),
|
|
1163
|
+
...Object.keys(updateRelationPropertiesOptions.relationPropertiesToUpdate || []),
|
|
1164
|
+
]);
|
|
1165
|
+
relationEntityToUpdate = pick(relatedEntityToBeSaved, propertiesToUpdate);
|
|
1166
|
+
subRelationPropertiesToUpdate = updateRelationPropertiesOptions.relationPropertiesToUpdate;
|
|
1167
|
+
}
|
|
1168
|
+
if (relationEntityToUpdate) {
|
|
1169
|
+
targetEntity = await updateEntityById(server, targetDataAccessor, {
|
|
1170
|
+
routeContext: routeContext,
|
|
1171
|
+
id: relatedEntityId,
|
|
1172
|
+
entityToSave: relationEntityToUpdate,
|
|
1173
|
+
relationPropertiesToUpdate: subRelationPropertiesToUpdate,
|
|
1174
|
+
});
|
|
1175
|
+
}
|
|
1176
|
+
|
|
1134
1177
|
updatedEntityOneRelationProps[property.code] = targetEntity;
|
|
1135
|
-
rowToBeSaved[property.targetIdColumnName!] =
|
|
1178
|
+
rowToBeSaved[property.targetIdColumnName!] = relatedEntityId;
|
|
1136
1179
|
}
|
|
1137
|
-
} else if (isNumber(
|
|
1180
|
+
} else if (isNumber(relatedEntityToBeSaved) || isString(relatedEntityToBeSaved)) {
|
|
1138
1181
|
// fieldValue is id;
|
|
1139
|
-
const targetEntityId =
|
|
1182
|
+
const targetEntityId = relatedEntityToBeSaved;
|
|
1140
1183
|
const targetEntity = await findById(server, targetDataAccessor, {
|
|
1141
1184
|
id: targetEntityId,
|
|
1142
1185
|
routeContext,
|
|
@@ -1290,9 +1333,33 @@ async function updateEntityById(server: IRpdServer, dataAccessor: IRpdDataAccess
|
|
|
1290
1333
|
relatedEntities.push(newTargetEntity);
|
|
1291
1334
|
} else {
|
|
1292
1335
|
// related entity is existed
|
|
1293
|
-
|
|
1336
|
+
let targetEntity = await targetDataAccessor.findById(relatedEntityId);
|
|
1294
1337
|
if (!targetEntity) {
|
|
1295
|
-
throw new Error(`Entity with id '${relatedEntityId}' in field '${property.code}'
|
|
1338
|
+
throw new Error(`Entity with id '${relatedEntityId}' in field '${property.code}' does not exist.`);
|
|
1339
|
+
}
|
|
1340
|
+
|
|
1341
|
+
// update relation entity if options.relationPropertiesToUpdate is specified.
|
|
1342
|
+
const updateRelationPropertiesOptions = get(options.relationPropertiesToUpdate, property.code);
|
|
1343
|
+
let subRelationPropertiesToUpdate = undefined;
|
|
1344
|
+
let relationEntityToUpdate = null;
|
|
1345
|
+
if (updateRelationPropertiesOptions === true) {
|
|
1346
|
+
relationEntityToUpdate = targetEntity;
|
|
1347
|
+
} else if (updateRelationPropertiesOptions) {
|
|
1348
|
+
let propertiesToUpdate = uniq([
|
|
1349
|
+
"id",
|
|
1350
|
+
...(updateRelationPropertiesOptions.propertiesToUpdate || []),
|
|
1351
|
+
...Object.keys(updateRelationPropertiesOptions.relationPropertiesToUpdate || []),
|
|
1352
|
+
]);
|
|
1353
|
+
relationEntityToUpdate = pick(relatedEntityToBeSaved, propertiesToUpdate);
|
|
1354
|
+
subRelationPropertiesToUpdate = updateRelationPropertiesOptions.relationPropertiesToUpdate;
|
|
1355
|
+
}
|
|
1356
|
+
if (relationEntityToUpdate) {
|
|
1357
|
+
targetEntity = await updateEntityById(server, targetDataAccessor, {
|
|
1358
|
+
routeContext: routeContext,
|
|
1359
|
+
id: relatedEntityId,
|
|
1360
|
+
entityToSave: relationEntityToUpdate,
|
|
1361
|
+
relationPropertiesToUpdate: subRelationPropertiesToUpdate,
|
|
1362
|
+
});
|
|
1296
1363
|
}
|
|
1297
1364
|
|
|
1298
1365
|
if (!currentTargetIds.includes(relatedEntityId)) {
|
|
@@ -1459,7 +1526,7 @@ export default class EntityManager<TEntity = any> {
|
|
|
1459
1526
|
return await updateEntityById(this.#server, this.#dataAccessor, options, plugin);
|
|
1460
1527
|
}
|
|
1461
1528
|
|
|
1462
|
-
async count(options: CountEntityOptions): Promise<
|
|
1529
|
+
async count(options: CountEntityOptions): Promise<number> {
|
|
1463
1530
|
const model = this.#dataAccessor.getModel();
|
|
1464
1531
|
let baseModel: RpdDataModel;
|
|
1465
1532
|
if (model.base) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CountEntityOptions, RunEntityActionHandlerOptions } from "~/types";
|
|
1
|
+
import { CountEntityOptions, CountEntityResult, RunEntityActionHandlerOptions } from "~/types";
|
|
2
2
|
import runCollectionEntityActionHandler from "~/helpers/runCollectionEntityActionHandler";
|
|
3
3
|
import { removeFiltersWithNullValue } from "~/helpers/filterHelper";
|
|
4
4
|
import { ActionHandlerContext } from "~/core/actionHandler";
|
|
@@ -7,9 +7,10 @@ import { RapidPlugin } from "~/core/server";
|
|
|
7
7
|
export const code = "countCollectionEntities";
|
|
8
8
|
|
|
9
9
|
export async function handler(plugin: RapidPlugin, ctx: ActionHandlerContext, options: RunEntityActionHandlerOptions) {
|
|
10
|
-
await runCollectionEntityActionHandler(ctx, options, code, (entityManager, input: CountEntityOptions) => {
|
|
10
|
+
await runCollectionEntityActionHandler(ctx, options, code, async (entityManager, input: CountEntityOptions): Promise<CountEntityResult> => {
|
|
11
11
|
input.filters = removeFiltersWithNullValue(input.filters);
|
|
12
12
|
input.routeContext = ctx.routerContext;
|
|
13
|
-
|
|
13
|
+
const count = await entityManager.count(input);
|
|
14
|
+
return { count };
|
|
14
15
|
});
|
|
15
16
|
}
|
|
@@ -18,8 +18,8 @@ export async function handler(plugin: RapidPlugin, ctx: ActionHandlerContext, op
|
|
|
18
18
|
|
|
19
19
|
if (input.pagination && !input.pagination.withoutTotal) {
|
|
20
20
|
// TOOD: count entities when calling findEntities for performance.
|
|
21
|
-
const
|
|
22
|
-
result.total =
|
|
21
|
+
const total = await entityManager.count(input);
|
|
22
|
+
result.total = total;
|
|
23
23
|
}
|
|
24
24
|
return result;
|
|
25
25
|
});
|
|
@@ -22,11 +22,17 @@ export async function handler(plugin: RapidPlugin, ctx: ActionHandlerContext, op
|
|
|
22
22
|
delete mergedInput.$stateProperties;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
+
const relationPropertiesToUpdate = mergedInput.$relationPropertiesToUpdate;
|
|
26
|
+
if (relationPropertiesToUpdate) {
|
|
27
|
+
delete mergedInput.$relationPropertiesToUpdate;
|
|
28
|
+
}
|
|
29
|
+
|
|
25
30
|
const updateEntityByIdOptions: UpdateEntityByIdOptions = {
|
|
26
31
|
id: mergedInput.id,
|
|
27
32
|
entityToSave: mergedInput,
|
|
28
33
|
operation,
|
|
29
34
|
stateProperties,
|
|
35
|
+
relationPropertiesToUpdate,
|
|
30
36
|
routeContext: ctx.routerContext,
|
|
31
37
|
};
|
|
32
38
|
const entityManager = server.getEntityManager(options.singularCode);
|
package/src/types.ts
CHANGED
|
@@ -456,7 +456,7 @@ export interface IRpdDataAccessor<T = any> {
|
|
|
456
456
|
find(options: FindRowOptions): Promise<T[]>;
|
|
457
457
|
findOne(options: FindRowOptions): Promise<T | null>;
|
|
458
458
|
findById(id: any): Promise<T | null>;
|
|
459
|
-
count(options: CountRowOptions): Promise<
|
|
459
|
+
count(options: CountRowOptions): Promise<number>;
|
|
460
460
|
deleteById(id: any): Promise<void>;
|
|
461
461
|
}
|
|
462
462
|
|
|
@@ -628,10 +628,24 @@ export interface UpdateEntityByIdOptions {
|
|
|
628
628
|
operation?: {
|
|
629
629
|
type: string;
|
|
630
630
|
};
|
|
631
|
+
/**
|
|
632
|
+
* 指定需要更新那几个状态属性(配置了`config.stateMachine`的属性)。当不指定时默认更新全部状态属性。
|
|
633
|
+
*/
|
|
631
634
|
stateProperties?: string[];
|
|
632
635
|
postponeUniquenessCheck?: boolean;
|
|
636
|
+
/**
|
|
637
|
+
* 指定需要更新关联对象的哪些属性。更新实体时,会创建关联对象,但是默认不更新关联对象的属性。
|
|
638
|
+
*/
|
|
639
|
+
relationPropertiesToUpdate?: Record<string, UpdateRelationPropertiesOptions>;
|
|
633
640
|
}
|
|
634
641
|
|
|
642
|
+
export type UpdateRelationPropertiesOptions =
|
|
643
|
+
| true
|
|
644
|
+
| {
|
|
645
|
+
propertiesToUpdate?: string[];
|
|
646
|
+
relationPropertiesToUpdate?: Record<string, UpdateRelationPropertiesOptions>;
|
|
647
|
+
};
|
|
648
|
+
|
|
635
649
|
export interface DeleteEntityOptions {
|
|
636
650
|
routeContext?: RouteContext;
|
|
637
651
|
filters?: EntityFilterOptions[];
|