@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.
@@ -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<any>;
20
+ count(options: CountRowOptions): Promise<number>;
21
21
  deleteById(id: any): Promise<void>;
22
22
  }
@@ -1,4 +1,4 @@
1
- import { AddEntityRelationsOptions, CountEntityOptions, CountEntityResult, CreateEntityOptions, DeleteEntityByIdOptions, FindEntityByIdOptions, FindEntityOptions, IRpdDataAccessor, RemoveEntityRelationsOptions, RpdDataModel, RpdDataModelIndex, RpdDataModelProperty, UpdateEntityByIdOptions, FindEntityFindOneRelationEntitiesOptions, FindEntityFindManyRelationEntitiesOptions } from "../types";
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<CountEntityResult>;
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 fieldValue = changes[property.code];
3255
+ const relatedEntityToBeSaved = changes[property.code];
3258
3256
  const targetDataAccessor = server.getDataAccessor({
3259
3257
  singularCode: property.targetSingularCode,
3260
3258
  });
3261
- if (lodash.isObject(fieldValue)) {
3262
- const targetEntityId = fieldValue["id"];
3263
- if (!targetEntityId) {
3259
+ if (lodash.isObject(relatedEntityToBeSaved)) {
3260
+ const relatedEntityId = relatedEntityToBeSaved["id"];
3261
+ if (!relatedEntityId) {
3264
3262
  if (!property.selfIdColumnName) {
3265
- const targetEntity = fieldValue;
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
- const targetEntity = await findById(server, targetDataAccessor, {
3276
- id: targetEntityId,
3273
+ let targetEntity = await findById(server, targetDataAccessor, {
3274
+ id: relatedEntityId,
3277
3275
  routeContext,
3278
3276
  });
3279
3277
  if (!targetEntity) {
3280
- throw newEntityOperationError(`Create ${model.singularCode} entity failed. Property '${property.code}' was invalid. Related ${property.targetSingularCode} entity with id '${targetEntityId}' was not found.`);
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] = targetEntityId;
3305
+ rowToBeSaved[property.targetIdColumnName] = relatedEntityId;
3284
3306
  }
3285
3307
  }
3286
- else if (lodash.isNumber(fieldValue) || lodash.isString(fieldValue)) {
3308
+ else if (lodash.isNumber(relatedEntityToBeSaved) || lodash.isString(relatedEntityToBeSaved)) {
3287
3309
  // fieldValue is id;
3288
- const targetEntityId = fieldValue;
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
- const targetEntity = await targetDataAccessor.findById(relatedEntityId);
3444
+ let targetEntity = await targetDataAccessor.findById(relatedEntityId);
3423
3445
  if (!targetEntity) {
3424
- throw new Error(`Entity with id '${relatedEntityId}' in field '${property.code}' is not exists.`);
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 countResult = await entityManager.count(input);
4794
- result.total = countResult.count;
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
- return entityManager.count(input);
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<any>;
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ruiapp/rapid-core",
3
- "version": "0.2.7",
3
+ "version": "0.2.9",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -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<any> {
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 { cloneDeep, filter, find, first, forEach, isArray, isNumber, isObject, isPlainObject, isString, isUndefined, keys, map, reject, uniq } from "lodash";
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 fieldValue = changes[property.code];
1125
+ const relatedEntityToBeSaved = changes[property.code];
1108
1126
  const targetDataAccessor = server.getDataAccessor({
1109
1127
  singularCode: property.targetSingularCode!,
1110
1128
  });
1111
1129
 
1112
- if (isObject(fieldValue)) {
1113
- const targetEntityId = fieldValue["id"];
1114
- if (!targetEntityId) {
1130
+ if (isObject(relatedEntityToBeSaved)) {
1131
+ const relatedEntityId = relatedEntityToBeSaved["id"];
1132
+ if (!relatedEntityId) {
1115
1133
  if (!property.selfIdColumnName) {
1116
- const targetEntity = fieldValue;
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
- const targetEntity = await findById(server, targetDataAccessor, {
1126
- id: targetEntityId,
1143
+ let targetEntity = await findById(server, targetDataAccessor, {
1144
+ id: relatedEntityId,
1127
1145
  routeContext,
1128
1146
  });
1129
1147
  if (!targetEntity) {
1130
1148
  throw newEntityOperationError(
1131
- `Create ${model.singularCode} entity failed. Property '${property.code}' was invalid. Related ${property.targetSingularCode} entity with id '${targetEntityId}' was not found.`,
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!] = targetEntityId;
1178
+ rowToBeSaved[property.targetIdColumnName!] = relatedEntityId;
1136
1179
  }
1137
- } else if (isNumber(fieldValue) || isString(fieldValue)) {
1180
+ } else if (isNumber(relatedEntityToBeSaved) || isString(relatedEntityToBeSaved)) {
1138
1181
  // fieldValue is id;
1139
- const targetEntityId = fieldValue;
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
- const targetEntity = await targetDataAccessor.findById(relatedEntityId);
1336
+ let targetEntity = await targetDataAccessor.findById(relatedEntityId);
1294
1337
  if (!targetEntity) {
1295
- throw new Error(`Entity with id '${relatedEntityId}' in field '${property.code}' is not exists.`);
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<CountEntityResult> {
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
- return entityManager.count(input);
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 countResult = await entityManager.count(input);
22
- result.total = countResult.count;
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<any>;
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[];