@ruiapp/rapid-core 0.2.6 → 0.2.8

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 = {
@@ -2972,7 +2970,7 @@ async function createEntity(server, dataAccessor, options, plugin) {
2972
2970
  const newEntityOneRelationProps = {};
2973
2971
  // save one-relation properties
2974
2972
  for (const property of oneRelationPropertiesToCreate) {
2975
- const targetRow = property.isBaseProperty ? baseRow : row;
2973
+ const rowToBeSaved = property.isBaseProperty ? baseRow : row;
2976
2974
  const fieldValue = entity[property.code];
2977
2975
  const targetDataAccessor = server.getDataAccessor({
2978
2976
  singularCode: property.targetSingularCode,
@@ -2980,13 +2978,15 @@ async function createEntity(server, dataAccessor, options, plugin) {
2980
2978
  if (lodash.isObject(fieldValue)) {
2981
2979
  const targetEntityId = fieldValue["id"];
2982
2980
  if (!targetEntityId) {
2983
- const targetEntity = fieldValue;
2984
- const newTargetEntity = await createEntity(server, targetDataAccessor, {
2985
- routeContext,
2986
- entity: targetEntity,
2987
- });
2988
- newEntityOneRelationProps[property.code] = newTargetEntity;
2989
- targetRow[property.targetIdColumnName] = newTargetEntity["id"];
2981
+ if (!property.selfIdColumnName) {
2982
+ const targetEntity = fieldValue;
2983
+ const newTargetEntity = await createEntity(server, targetDataAccessor, {
2984
+ routeContext,
2985
+ entity: targetEntity,
2986
+ });
2987
+ newEntityOneRelationProps[property.code] = newTargetEntity;
2988
+ rowToBeSaved[property.targetIdColumnName] = newTargetEntity["id"];
2989
+ }
2990
2990
  }
2991
2991
  else {
2992
2992
  const targetEntity = await findById(server, targetDataAccessor, {
@@ -2997,7 +2997,7 @@ async function createEntity(server, dataAccessor, options, plugin) {
2997
2997
  throw newEntityOperationError(`Create ${model.singularCode} entity failed. Property '${property.code}' was invalid. Related ${property.targetSingularCode} entity with id '${targetEntityId}' was not found.`);
2998
2998
  }
2999
2999
  newEntityOneRelationProps[property.code] = targetEntity;
3000
- targetRow[property.targetIdColumnName] = targetEntityId;
3000
+ rowToBeSaved[property.targetIdColumnName] = targetEntityId;
3001
3001
  }
3002
3002
  }
3003
3003
  else if (lodash.isNumber(fieldValue) || lodash.isString(fieldValue)) {
@@ -3011,16 +3011,17 @@ async function createEntity(server, dataAccessor, options, plugin) {
3011
3011
  throw newEntityOperationError(`Create ${model.singularCode} entity failed. Property '${property.code}' was invalid. Related ${property.targetSingularCode} entity with id '${targetEntityId}' was not found.`);
3012
3012
  }
3013
3013
  newEntityOneRelationProps[property.code] = targetEntity;
3014
- targetRow[property.targetIdColumnName] = targetEntityId;
3014
+ rowToBeSaved[property.targetIdColumnName] = targetEntityId;
3015
3015
  }
3016
3016
  else {
3017
3017
  newEntityOneRelationProps[property.code] = null;
3018
- targetRow[property.targetIdColumnName] = null;
3018
+ rowToBeSaved[property.targetIdColumnName] = null;
3019
3019
  }
3020
3020
  }
3021
3021
  let newBaseRow;
3022
+ let baseDataAccessor;
3022
3023
  if (model.base) {
3023
- const baseDataAccessor = server.getDataAccessor({
3024
+ baseDataAccessor = server.getDataAccessor({
3024
3025
  singularCode: model.base,
3025
3026
  });
3026
3027
  newBaseRow = await baseDataAccessor.create(baseRow);
@@ -3028,6 +3029,35 @@ async function createEntity(server, dataAccessor, options, plugin) {
3028
3029
  }
3029
3030
  const newRow = await dataAccessor.create(row);
3030
3031
  const newEntity = mapDbRowToEntity(server, model, Object.assign({}, newBaseRow, newRow, newEntityOneRelationProps), true);
3032
+ // save one-relation properties that has selfIdColumnName
3033
+ for (const property of oneRelationPropertiesToCreate) {
3034
+ const fieldValue = entity[property.code];
3035
+ const targetDataAccessor = server.getDataAccessor({
3036
+ singularCode: property.targetSingularCode,
3037
+ });
3038
+ if (lodash.isObject(fieldValue)) {
3039
+ const targetEntityId = fieldValue["id"];
3040
+ if (!targetEntityId) {
3041
+ if (property.selfIdColumnName) {
3042
+ const targetEntity = fieldValue;
3043
+ targetEntity[property.selfIdColumnName] = newEntity.id;
3044
+ const newTargetEntity = await createEntity(server, targetDataAccessor, {
3045
+ routeContext,
3046
+ entity: targetEntity,
3047
+ });
3048
+ let dataAccessorOfMainEntity = dataAccessor;
3049
+ if (property.isBaseProperty) {
3050
+ dataAccessorOfMainEntity = baseDataAccessor;
3051
+ }
3052
+ const relationFieldChanges = {
3053
+ [property.targetIdColumnName]: newTargetEntity.id,
3054
+ };
3055
+ await dataAccessorOfMainEntity.updateById(newEntity.id, relationFieldChanges);
3056
+ newEntity[property.code] = newTargetEntity;
3057
+ }
3058
+ }
3059
+ }
3060
+ }
3031
3061
  // save many-relation properties
3032
3062
  for (const property of manyRelationPropertiesToCreate) {
3033
3063
  newEntity[property.code] = [];
@@ -3221,7 +3251,7 @@ async function updateEntityById(server, dataAccessor, options, plugin) {
3221
3251
  const { row, baseRow } = mapEntityToDbRow(server, model, changes);
3222
3252
  const updatedEntityOneRelationProps = {};
3223
3253
  for (const property of oneRelationPropertiesToUpdate) {
3224
- const targetRow = property.isBaseProperty ? baseRow : row;
3254
+ const rowToBeSaved = property.isBaseProperty ? baseRow : row;
3225
3255
  const fieldValue = changes[property.code];
3226
3256
  const targetDataAccessor = server.getDataAccessor({
3227
3257
  singularCode: property.targetSingularCode,
@@ -3229,13 +3259,15 @@ async function updateEntityById(server, dataAccessor, options, plugin) {
3229
3259
  if (lodash.isObject(fieldValue)) {
3230
3260
  const targetEntityId = fieldValue["id"];
3231
3261
  if (!targetEntityId) {
3232
- const targetEntity = fieldValue;
3233
- const newTargetEntity = await createEntity(server, targetDataAccessor, {
3234
- routeContext,
3235
- entity: targetEntity,
3236
- });
3237
- updatedEntityOneRelationProps[property.code] = newTargetEntity;
3238
- targetRow[property.targetIdColumnName] = newTargetEntity["id"];
3262
+ if (!property.selfIdColumnName) {
3263
+ const targetEntity = fieldValue;
3264
+ const newTargetEntity = await createEntity(server, targetDataAccessor, {
3265
+ routeContext,
3266
+ entity: targetEntity,
3267
+ });
3268
+ updatedEntityOneRelationProps[property.code] = newTargetEntity;
3269
+ rowToBeSaved[property.targetIdColumnName] = newTargetEntity["id"];
3270
+ }
3239
3271
  }
3240
3272
  else {
3241
3273
  const targetEntity = await findById(server, targetDataAccessor, {
@@ -3246,7 +3278,7 @@ async function updateEntityById(server, dataAccessor, options, plugin) {
3246
3278
  throw newEntityOperationError(`Create ${model.singularCode} entity failed. Property '${property.code}' was invalid. Related ${property.targetSingularCode} entity with id '${targetEntityId}' was not found.`);
3247
3279
  }
3248
3280
  updatedEntityOneRelationProps[property.code] = targetEntity;
3249
- targetRow[property.targetIdColumnName] = targetEntityId;
3281
+ rowToBeSaved[property.targetIdColumnName] = targetEntityId;
3250
3282
  }
3251
3283
  }
3252
3284
  else if (lodash.isNumber(fieldValue) || lodash.isString(fieldValue)) {
@@ -3260,11 +3292,11 @@ async function updateEntityById(server, dataAccessor, options, plugin) {
3260
3292
  throw newEntityOperationError(`Create ${model.singularCode} entity failed. Property '${property.code}' was invalid. Related ${property.targetSingularCode} entity with id '${targetEntityId}' was not found.`);
3261
3293
  }
3262
3294
  updatedEntityOneRelationProps[property.code] = targetEntity;
3263
- targetRow[property.targetIdColumnName] = targetEntityId;
3295
+ rowToBeSaved[property.targetIdColumnName] = targetEntityId;
3264
3296
  }
3265
3297
  else {
3266
3298
  updatedEntityOneRelationProps[property.code] = null;
3267
- targetRow[property.targetIdColumnName] = null;
3299
+ rowToBeSaved[property.targetIdColumnName] = null;
3268
3300
  }
3269
3301
  }
3270
3302
  let updatedRow = row;
@@ -3272,14 +3304,47 @@ async function updateEntityById(server, dataAccessor, options, plugin) {
3272
3304
  updatedRow = await dataAccessor.updateById(id, row);
3273
3305
  }
3274
3306
  let updatedBaseRow = baseRow;
3275
- if (model.base && Object.keys(baseRow).length) {
3276
- const baseDataAccessor = server.getDataAccessor({
3307
+ let baseDataAccessor;
3308
+ if (model.base) {
3309
+ baseDataAccessor = server.getDataAccessor({
3277
3310
  singularCode: model.base,
3278
3311
  });
3279
- updatedBaseRow = await baseDataAccessor.updateById(id, updatedBaseRow);
3312
+ if (Object.keys(baseRow).length) {
3313
+ updatedBaseRow = await baseDataAccessor.updateById(id, updatedBaseRow);
3314
+ }
3280
3315
  }
3281
3316
  let updatedEntity = mapDbRowToEntity(server, model, { ...updatedRow, ...updatedBaseRow, ...updatedEntityOneRelationProps }, true);
3282
3317
  updatedEntity = Object.assign({}, entity, updatedEntity);
3318
+ // save one-relation properties that has selfIdColumnName
3319
+ for (const property of oneRelationPropertiesToUpdate) {
3320
+ const fieldValue = changes[property.code];
3321
+ const targetDataAccessor = server.getDataAccessor({
3322
+ singularCode: property.targetSingularCode,
3323
+ });
3324
+ if (lodash.isObject(fieldValue)) {
3325
+ const targetEntityId = fieldValue["id"];
3326
+ if (!targetEntityId) {
3327
+ if (property.selfIdColumnName) {
3328
+ const targetEntity = fieldValue;
3329
+ targetEntity[property.selfIdColumnName] = updatedEntity.id;
3330
+ const newTargetEntity = await createEntity(server, targetDataAccessor, {
3331
+ routeContext,
3332
+ entity: targetEntity,
3333
+ });
3334
+ let dataAccessorOfMainEntity = dataAccessor;
3335
+ if (property.isBaseProperty) {
3336
+ dataAccessorOfMainEntity = baseDataAccessor;
3337
+ }
3338
+ const relationFieldChanges = {
3339
+ [property.targetIdColumnName]: newTargetEntity.id,
3340
+ };
3341
+ await dataAccessorOfMainEntity.updateById(updatedEntity.id, relationFieldChanges);
3342
+ updatedEntity[property.code] = newTargetEntity;
3343
+ changes[property.code] = newTargetEntity;
3344
+ }
3345
+ }
3346
+ }
3347
+ }
3283
3348
  // save many-relation properties
3284
3349
  for (const property of manyRelationPropertiesToUpdate) {
3285
3350
  const relatedEntities = [];
@@ -4723,8 +4788,8 @@ async function handler$q(plugin, ctx, options) {
4723
4788
  const result = { list: entities };
4724
4789
  if (input.pagination && !input.pagination.withoutTotal) {
4725
4790
  // TOOD: count entities when calling findEntities for performance.
4726
- const countResult = await entityManager.count(input);
4727
- result.total = countResult.count;
4791
+ const total = await entityManager.count(input);
4792
+ result.total = total;
4728
4793
  }
4729
4794
  return result;
4730
4795
  });
@@ -4760,10 +4825,11 @@ var findCollectionEntityById = /*#__PURE__*/Object.freeze({
4760
4825
 
4761
4826
  const code$o = "countCollectionEntities";
4762
4827
  async function handler$o(plugin, ctx, options) {
4763
- await runCollectionEntityActionHandler(ctx, options, code$o, (entityManager, input) => {
4828
+ await runCollectionEntityActionHandler(ctx, options, code$o, async (entityManager, input) => {
4764
4829
  input.filters = removeFiltersWithNullValue(input.filters);
4765
4830
  input.routeContext = ctx.routerContext;
4766
- return entityManager.count(input);
4831
+ const count = await entityManager.count(input);
4832
+ return { count };
4767
4833
  });
4768
4834
  }
4769
4835
 
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";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ruiapp/rapid-core",
3
- "version": "0.2.6",
3
+ "version": "0.2.8",
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,
@@ -796,7 +795,7 @@ async function createEntity(server: IRpdServer, dataAccessor: IRpdDataAccessor,
796
795
  const newEntityOneRelationProps = {};
797
796
  // save one-relation properties
798
797
  for (const property of oneRelationPropertiesToCreate) {
799
- const targetRow = property.isBaseProperty ? baseRow : row;
798
+ const rowToBeSaved = property.isBaseProperty ? baseRow : row;
800
799
  const fieldValue = entity[property.code];
801
800
  const targetDataAccessor = server.getDataAccessor({
802
801
  singularCode: property.targetSingularCode!,
@@ -804,13 +803,15 @@ async function createEntity(server: IRpdServer, dataAccessor: IRpdDataAccessor,
804
803
  if (isObject(fieldValue)) {
805
804
  const targetEntityId = fieldValue["id"];
806
805
  if (!targetEntityId) {
807
- const targetEntity = fieldValue;
808
- const newTargetEntity = await createEntity(server, targetDataAccessor, {
809
- routeContext,
810
- entity: targetEntity,
811
- });
812
- newEntityOneRelationProps[property.code] = newTargetEntity;
813
- targetRow[property.targetIdColumnName!] = newTargetEntity["id"];
806
+ if (!property.selfIdColumnName) {
807
+ const targetEntity = fieldValue;
808
+ const newTargetEntity = await createEntity(server, targetDataAccessor, {
809
+ routeContext,
810
+ entity: targetEntity,
811
+ });
812
+ newEntityOneRelationProps[property.code] = newTargetEntity;
813
+ rowToBeSaved[property.targetIdColumnName!] = newTargetEntity["id"];
814
+ }
814
815
  } else {
815
816
  const targetEntity = await findById(server, targetDataAccessor, {
816
817
  id: targetEntityId,
@@ -822,7 +823,7 @@ async function createEntity(server: IRpdServer, dataAccessor: IRpdDataAccessor,
822
823
  );
823
824
  }
824
825
  newEntityOneRelationProps[property.code] = targetEntity;
825
- targetRow[property.targetIdColumnName!] = targetEntityId;
826
+ rowToBeSaved[property.targetIdColumnName!] = targetEntityId;
826
827
  }
827
828
  } else if (isNumber(fieldValue) || isString(fieldValue)) {
828
829
  // fieldValue is id;
@@ -837,16 +838,17 @@ async function createEntity(server: IRpdServer, dataAccessor: IRpdDataAccessor,
837
838
  );
838
839
  }
839
840
  newEntityOneRelationProps[property.code] = targetEntity;
840
- targetRow[property.targetIdColumnName!] = targetEntityId;
841
+ rowToBeSaved[property.targetIdColumnName!] = targetEntityId;
841
842
  } else {
842
843
  newEntityOneRelationProps[property.code] = null;
843
- targetRow[property.targetIdColumnName!] = null;
844
+ rowToBeSaved[property.targetIdColumnName!] = null;
844
845
  }
845
846
  }
846
847
 
847
848
  let newBaseRow: any;
849
+ let baseDataAccessor: any;
848
850
  if (model.base) {
849
- const baseDataAccessor = server.getDataAccessor({
851
+ baseDataAccessor = server.getDataAccessor({
850
852
  singularCode: model.base,
851
853
  });
852
854
  newBaseRow = await baseDataAccessor.create(baseRow);
@@ -856,6 +858,38 @@ async function createEntity(server: IRpdServer, dataAccessor: IRpdDataAccessor,
856
858
  const newRow = await dataAccessor.create(row);
857
859
  const newEntity = mapDbRowToEntity(server, model, Object.assign({}, newBaseRow, newRow, newEntityOneRelationProps), true);
858
860
 
861
+ // save one-relation properties that has selfIdColumnName
862
+ for (const property of oneRelationPropertiesToCreate) {
863
+ const fieldValue = entity[property.code];
864
+ const targetDataAccessor = server.getDataAccessor({
865
+ singularCode: property.targetSingularCode!,
866
+ });
867
+ if (isObject(fieldValue)) {
868
+ const targetEntityId = fieldValue["id"];
869
+ if (!targetEntityId) {
870
+ if (property.selfIdColumnName) {
871
+ const targetEntity = fieldValue;
872
+ targetEntity[property.selfIdColumnName] = newEntity.id;
873
+ const newTargetEntity = await createEntity(server, targetDataAccessor, {
874
+ routeContext,
875
+ entity: targetEntity,
876
+ });
877
+
878
+ let dataAccessorOfMainEntity = dataAccessor;
879
+ if (property.isBaseProperty) {
880
+ dataAccessorOfMainEntity = baseDataAccessor;
881
+ }
882
+
883
+ const relationFieldChanges = {
884
+ [property.targetIdColumnName]: newTargetEntity.id,
885
+ };
886
+ await dataAccessorOfMainEntity.updateById(newEntity.id, relationFieldChanges);
887
+ newEntity[property.code] = newTargetEntity;
888
+ }
889
+ }
890
+ }
891
+ }
892
+
859
893
  // save many-relation properties
860
894
  for (const property of manyRelationPropertiesToCreate) {
861
895
  newEntity[property.code] = [];
@@ -1068,7 +1102,7 @@ async function updateEntityById(server: IRpdServer, dataAccessor: IRpdDataAccess
1068
1102
 
1069
1103
  const updatedEntityOneRelationProps = {};
1070
1104
  for (const property of oneRelationPropertiesToUpdate) {
1071
- const targetRow = property.isBaseProperty ? baseRow : row;
1105
+ const rowToBeSaved = property.isBaseProperty ? baseRow : row;
1072
1106
  const fieldValue = changes[property.code];
1073
1107
  const targetDataAccessor = server.getDataAccessor({
1074
1108
  singularCode: property.targetSingularCode!,
@@ -1077,13 +1111,15 @@ async function updateEntityById(server: IRpdServer, dataAccessor: IRpdDataAccess
1077
1111
  if (isObject(fieldValue)) {
1078
1112
  const targetEntityId = fieldValue["id"];
1079
1113
  if (!targetEntityId) {
1080
- const targetEntity = fieldValue;
1081
- const newTargetEntity = await createEntity(server, targetDataAccessor, {
1082
- routeContext,
1083
- entity: targetEntity,
1084
- });
1085
- updatedEntityOneRelationProps[property.code] = newTargetEntity;
1086
- targetRow[property.targetIdColumnName!] = newTargetEntity["id"];
1114
+ if (!property.selfIdColumnName) {
1115
+ const targetEntity = fieldValue;
1116
+ const newTargetEntity = await createEntity(server, targetDataAccessor, {
1117
+ routeContext,
1118
+ entity: targetEntity,
1119
+ });
1120
+ updatedEntityOneRelationProps[property.code] = newTargetEntity;
1121
+ rowToBeSaved[property.targetIdColumnName!] = newTargetEntity["id"];
1122
+ }
1087
1123
  } else {
1088
1124
  const targetEntity = await findById(server, targetDataAccessor, {
1089
1125
  id: targetEntityId,
@@ -1095,7 +1131,7 @@ async function updateEntityById(server: IRpdServer, dataAccessor: IRpdDataAccess
1095
1131
  );
1096
1132
  }
1097
1133
  updatedEntityOneRelationProps[property.code] = targetEntity;
1098
- targetRow[property.targetIdColumnName!] = targetEntityId;
1134
+ rowToBeSaved[property.targetIdColumnName!] = targetEntityId;
1099
1135
  }
1100
1136
  } else if (isNumber(fieldValue) || isString(fieldValue)) {
1101
1137
  // fieldValue is id;
@@ -1110,10 +1146,10 @@ async function updateEntityById(server: IRpdServer, dataAccessor: IRpdDataAccess
1110
1146
  );
1111
1147
  }
1112
1148
  updatedEntityOneRelationProps[property.code] = targetEntity;
1113
- targetRow[property.targetIdColumnName!] = targetEntityId;
1149
+ rowToBeSaved[property.targetIdColumnName!] = targetEntityId;
1114
1150
  } else {
1115
1151
  updatedEntityOneRelationProps[property.code] = null;
1116
- targetRow[property.targetIdColumnName!] = null;
1152
+ rowToBeSaved[property.targetIdColumnName!] = null;
1117
1153
  }
1118
1154
  }
1119
1155
 
@@ -1122,16 +1158,52 @@ async function updateEntityById(server: IRpdServer, dataAccessor: IRpdDataAccess
1122
1158
  updatedRow = await dataAccessor.updateById(id, row);
1123
1159
  }
1124
1160
  let updatedBaseRow = baseRow;
1125
- if (model.base && Object.keys(baseRow).length) {
1126
- const baseDataAccessor = server.getDataAccessor({
1161
+ let baseDataAccessor: any;
1162
+ if (model.base) {
1163
+ baseDataAccessor = server.getDataAccessor({
1127
1164
  singularCode: model.base,
1128
1165
  });
1129
- updatedBaseRow = await baseDataAccessor.updateById(id, updatedBaseRow);
1166
+ if (Object.keys(baseRow).length) {
1167
+ updatedBaseRow = await baseDataAccessor.updateById(id, updatedBaseRow);
1168
+ }
1130
1169
  }
1131
1170
 
1132
1171
  let updatedEntity = mapDbRowToEntity(server, model, { ...updatedRow, ...updatedBaseRow, ...updatedEntityOneRelationProps }, true);
1133
1172
  updatedEntity = Object.assign({}, entity, updatedEntity);
1134
1173
 
1174
+ // save one-relation properties that has selfIdColumnName
1175
+ for (const property of oneRelationPropertiesToUpdate) {
1176
+ const fieldValue = changes[property.code];
1177
+ const targetDataAccessor = server.getDataAccessor({
1178
+ singularCode: property.targetSingularCode!,
1179
+ });
1180
+ if (isObject(fieldValue)) {
1181
+ const targetEntityId = fieldValue["id"];
1182
+ if (!targetEntityId) {
1183
+ if (property.selfIdColumnName) {
1184
+ const targetEntity = fieldValue;
1185
+ targetEntity[property.selfIdColumnName] = updatedEntity.id;
1186
+ const newTargetEntity = await createEntity(server, targetDataAccessor, {
1187
+ routeContext,
1188
+ entity: targetEntity,
1189
+ });
1190
+
1191
+ let dataAccessorOfMainEntity = dataAccessor;
1192
+ if (property.isBaseProperty) {
1193
+ dataAccessorOfMainEntity = baseDataAccessor;
1194
+ }
1195
+
1196
+ const relationFieldChanges = {
1197
+ [property.targetIdColumnName]: newTargetEntity.id,
1198
+ };
1199
+ await dataAccessorOfMainEntity.updateById(updatedEntity.id, relationFieldChanges);
1200
+ updatedEntity[property.code] = newTargetEntity;
1201
+ changes[property.code] = newTargetEntity;
1202
+ }
1203
+ }
1204
+ }
1205
+ }
1206
+
1135
1207
  // save many-relation properties
1136
1208
  for (const property of manyRelationPropertiesToUpdate) {
1137
1209
  const relatedEntities: any[] = [];
@@ -1386,7 +1458,7 @@ export default class EntityManager<TEntity = any> {
1386
1458
  return await updateEntityById(this.#server, this.#dataAccessor, options, plugin);
1387
1459
  }
1388
1460
 
1389
- async count(options: CountEntityOptions): Promise<CountEntityResult> {
1461
+ async count(options: CountEntityOptions): Promise<number> {
1390
1462
  const model = this.#dataAccessor.getModel();
1391
1463
  let baseModel: RpdDataModel;
1392
1464
  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
  });
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