hola-server 0.3.7 → 0.3.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.
package/core/meta.js CHANGED
@@ -7,16 +7,23 @@ const meta_manager = {};
7
7
  * list: this field can be shown in table list
8
8
  * search: this field can be shown in search form
9
9
  * update: if is false, in update form, it will be readonly status
10
+ * delete: delete is only used for ref field, it decide when the ref entity will be deleted, how to handle this entity,no value, will not let the refered entity be deleted, keep: keep this entity(no data consistency), cascade: also delete this entity also,
10
11
  * sys: this field is used to control the user can set the value or not. sys field can only be set in the server side(before callback is good place to do this)
11
12
  * create is false, this attribute can be shown in property list but sys property can't be shown in property list
12
13
  *
13
14
  * routes: configure customer defined routes
14
15
  */
15
- const field_attrs = ["name", "type", "required", "ref", "create", "list", "search", "update", "clone", "sys"];
16
+ const field_attrs = ["name", "type", "required", "ref", "delete", "create", "list", "search", "update", "clone", "sys"];
16
17
  const meta_attrs = ["collection", "primary_keys", "fields", "creatable", "readable", "updatable", "deleteable", "cloneable", "after_read",
17
- "before_create", "after_create", "before_update", "after_update", "before_delete", "after_delete", "create", "update", "batch_update", "after_batch_update", "delete",
18
+ "before_create", "after_create", "before_clone", "after_clone", "before_update", "after_update", "before_delete", "after_delete", "create", "clone", "update", "batch_update", "after_batch_update", "delete",
18
19
  "ref_label", "ref_filter", "route", "user_field"];
19
20
 
21
+ const DELETE_MODE = Object.freeze({
22
+ all: ["keep", "cascade"],
23
+ keep: "keep",
24
+ cascade: "cascade"
25
+ });
26
+
20
27
  /**
21
28
  * Validate the field attributes and keep them correct(also set default value)
22
29
  * @param {entity meta} meta
@@ -44,7 +51,7 @@ const validate_field = (meta, field) => {
44
51
  }
45
52
 
46
53
  if (!ref_meta.ref_label) {
47
- throw new Error("meta:" + meta.collection + ",field:" + field.name + " refers an meta:" + field.ref + " without ref_label]");
54
+ throw new Error("meta:" + meta.collection + ",field:" + field.name + " refers an meta:" + field.ref + " without ref_label");
48
55
  }
49
56
 
50
57
  const ref_by_collections = ref_meta.ref_by_metas.map(m => m.collection);
@@ -53,6 +60,17 @@ const validate_field = (meta, field) => {
53
60
  }
54
61
  }
55
62
 
63
+ if (field.delete) {
64
+ if (!field.ref) {
65
+ throw new Error("meta:" + meta.collection + ",field:" + field.name + " doesn't let define delete in none ref field.");
66
+ }
67
+
68
+ const all_modes = DELETE_MODE.all;
69
+ if (!all_modes.includes(field.delete)) {
70
+ throw new Error("meta:" + meta.collection + ",field:" + field.name + " has invalid delete:" + field.delete + ", valid values:" + JSON.stringify(all_modes));
71
+ }
72
+ }
73
+
56
74
  const keys = Object.keys(field);
57
75
  keys.forEach(key => {
58
76
  if (!field_attrs.includes(key)) {
@@ -168,12 +186,15 @@ class EntityMeta {
168
186
 
169
187
  set_callback(this, "after_read", meta.after_read);
170
188
  set_callback(this, "before_create", meta.before_create);
189
+ set_callback(this, "before_clone", meta.before_clone);
171
190
  set_callback(this, "before_update", meta.before_update);
172
191
  set_callback(this, "before_delete", meta.before_delete);
173
192
  set_callback(this, "after_create", meta.after_create);
193
+ set_callback(this, "after_clone", meta.after_clone);
174
194
  set_callback(this, "after_update", meta.after_update);
175
195
  set_callback(this, "after_delete", meta.after_delete);
176
196
  set_callback(this, "create", meta.create);
197
+ set_callback(this, "clone", meta.clone);
177
198
  set_callback(this, "update", meta.update);
178
199
  set_callback(this, "batch_update", meta.batch_update);
179
200
  set_callback(this, "after_batch_update", meta.after_batch_update);
@@ -226,4 +247,4 @@ class EntityMeta {
226
247
  }
227
248
  }
228
249
 
229
- module.exports = { EntityMeta, validate_all_metas, get_entity_meta, get_all_metas }
250
+ module.exports = { EntityMeta, validate_all_metas, get_entity_meta, get_all_metas, DELETE_MODE }
package/db/entity.js CHANGED
@@ -2,7 +2,7 @@ const { SUCCESS, ERROR, NO_PARAMS, INVALID_PARAMS, DUPLICATE_KEY, NOT_FOUND, REF
2
2
  const { validate_required_fields, has_value } = require('../core/validate');
3
3
  const { required_params } = require('../http/params');
4
4
  const { convert_type, convert_update_type, get_type } = require('../core/type');
5
- const { get_entity_meta } = require('../core/meta');
5
+ const { get_entity_meta, DELETE_MODE } = require('../core/meta');
6
6
  const { unique, map_array_to_obj } = require('../core/array');
7
7
  const { LOG_ENTITY, get_db, oid_query, oid_queries, is_log_debug, is_log_error, log_debug, log_error, get_session_userid } = require('./db');
8
8
 
@@ -218,25 +218,7 @@ class Entity {
218
218
  * @returns object with code and err
219
219
  */
220
220
  async create_entity(param_obj) {
221
- return this._create_entity(param_obj, this.meta.create_fields);
222
- }
223
-
224
- /**
225
- * Validate the param object and invoke the logic to clone the entity and sae it to db
226
- * @param {param obj from user input} param_obj
227
- * @returns object with code and err
228
- */
229
- async clone_entity(param_obj) {
230
- return this._create_entity(param_obj, this.meta.clone_fields);
231
- }
232
-
233
- /**
234
- * Validate the param object and invoke the logic to save it to db
235
- * @param {param obj from user input} param_obj
236
- * @param {fields used to convert value} fields
237
- * @returns object with code and err
238
- */
239
- async _create_entity(param_obj, fields) {
221
+ const fields = this.meta.create_fields
240
222
  const { obj, error_field_names } = convert_type(param_obj, fields);
241
223
  if (error_field_names.length > 0) {
242
224
  if (is_log_error()) {
@@ -310,6 +292,87 @@ class Entity {
310
292
  return { code: SUCCESS };
311
293
  }
312
294
 
295
+ /**
296
+ * Validate the param object and invoke the logic to clone the entity and sae it to db
297
+ * @param {param obj from user input} param_obj
298
+ * @returns object with code and err
299
+ */
300
+ async clone_entity(param_obj) {
301
+ const fields = this.meta.clone_fields
302
+ const { obj, error_field_names } = convert_type(param_obj, fields);
303
+ if (error_field_names.length > 0) {
304
+ if (is_log_error()) {
305
+ log_error(LOG_ENTITY, "error fields:" + JSON.stringify(error_field_names));
306
+ }
307
+
308
+ return { code: INVALID_PARAMS, err: error_field_names };
309
+ }
310
+
311
+ if (this.meta.before_clone) {
312
+ const { code, err } = await this.meta.before_clone(this, obj);
313
+ if (err || code != SUCCESS) {
314
+ if (is_log_error()) {
315
+ log_error(LOG_ENTITY, "before_clone error:" + JSON.stringify(err) + ", with code:" + code);
316
+ }
317
+ return { code: code, err: err };
318
+ }
319
+ }
320
+
321
+ const error_required_field_names = validate_required_fields(obj, this.meta.required_field_names);
322
+ if (error_required_field_names.length > 0) {
323
+ if (is_log_error()) {
324
+ log_error(LOG_ENTITY, "error required fields:" + JSON.stringify(error_required_field_names));
325
+ }
326
+ return { code: NO_PARAMS, err: error_required_field_names };
327
+ }
328
+
329
+ const entity_count = await this.count_by_primary_keys(obj);
330
+ if (entity_count > 0) {
331
+ return { code: DUPLICATE_KEY, err: "entity already exist in db" };
332
+ }
333
+
334
+ if (this.meta.ref_fields) {
335
+ const { code, err } = await this.validate_ref(obj);
336
+ if (err || code != SUCCESS) {
337
+ if (is_log_error()) {
338
+ log_error(LOG_ENTITY, "validate_ref error:" + JSON.stringify(err) + ", with code:" + code);
339
+ }
340
+ return { code: code, err: err };
341
+ }
342
+ }
343
+
344
+ if (this.meta.clone) {
345
+ const { code, err } = await this.meta.clone(this, obj);
346
+ if (err || code != SUCCESS) {
347
+ if (is_log_error()) {
348
+ log_error(LOG_ENTITY, "clone error:" + JSON.stringify(err) + ", with code:" + code);
349
+ }
350
+ return { code: code, err: err };
351
+ }
352
+ } else {
353
+ const db_obj = await this.create(obj);
354
+ if (!db_obj["_id"]) {
355
+ if (is_log_error()) {
356
+ log_error(LOG_ENTITY, "create error:" + JSON.stringify(err) + ", with code:" + code);
357
+ }
358
+ return { code: ERROR, err: "creating record is failed" };
359
+ }
360
+ }
361
+
362
+ if (this.meta.after_clone) {
363
+ const { code, err } = await this.meta.after_clone(this, obj);
364
+ if (err || code != SUCCESS) {
365
+ if (is_log_error()) {
366
+ log_error(LOG_ENTITY, "after_clone error:" + JSON.stringify(err) + ", with code:" + code);
367
+ }
368
+ return { code: code, err: err };
369
+ }
370
+ }
371
+
372
+ return { code: SUCCESS };
373
+ }
374
+
375
+
313
376
  /**
314
377
  * Validate the param object and invoke the logic to update entity
315
378
  * @param {object id of the entity} _id object id of the entity, if it is null, then use primary key
@@ -569,18 +632,8 @@ class Entity {
569
632
  }
570
633
  }
571
634
 
572
- const has_refer_by_array = [];
573
- for (let i = 0; i < this.meta.ref_by_metas.length; i++) {
574
- const ref_by_meta = this.meta.ref_by_metas[i];
575
- const refer_by_entity = new Entity(ref_by_meta);
576
- for (let j = 0; j < id_array.length; j++) {
577
- const has_refer_by = await refer_by_entity.has_refer_entity(this.meta.collection, id_array[j]);
578
- if (has_refer_by) {
579
- has_refer_by_array.push(id_array[j]);
580
- }
581
- }
582
- }
583
-
635
+ //check all the ref by array first
636
+ const has_refer_by_array = await this.check_refer_entity(id_array);
584
637
  if (has_refer_by_array.length > 0) {
585
638
  if (is_log_error()) {
586
639
  log_error(LOG_ENTITY, "has_refer_by_array:" + JSON.stringify(has_refer_by_array));
@@ -606,6 +659,21 @@ class Entity {
606
659
  }
607
660
  }
608
661
 
662
+ //delete other ref_by entity based on delete mode
663
+ for (let i = 0; i < this.meta.ref_by_metas.length; i++) {
664
+ const ref_by_meta = this.meta.ref_by_metas[i];
665
+ const ref_fields = ref_by_meta.ref_fields.filter(field => field.ref == this.meta.collection);
666
+ for (let j = 0; j < ref_fields.length; j++) {
667
+ const ref_field = ref_fields[j];
668
+ if (ref_field.delete == DELETE_MODE.cascade) {
669
+ const refer_by_entity = new Entity(ref_by_meta);
670
+ for (let j = 0; j < id_array.length; j++) {
671
+ await refer_by_entity.delete_refer_entity(this.meta.collection, id_array[j])
672
+ }
673
+ }
674
+ }
675
+ }
676
+
609
677
  if (this.meta.after_delete) {
610
678
  const { code, err } = await this.meta.after_delete(this, id_array);
611
679
  if (err || code != SUCCESS) {
@@ -734,27 +802,72 @@ class Entity {
734
802
  }
735
803
  }
736
804
 
805
+ /**
806
+ * check whether this entity has refered the entity_id value
807
+ * @param {entity collection} entity_name
808
+ * @param {entity object id} entity_id
809
+ * @returns true if has refered
810
+ */
811
+ async check_refer_entity(id_array) {
812
+ const has_refer_by_array = [];
813
+ for (let i = 0; i < this.meta.ref_by_metas.length; i++) {
814
+ const ref_by_meta = this.meta.ref_by_metas[i];
815
+ const refer_by_entity = new Entity(ref_by_meta);
816
+ const ref_fields = ref_by_meta.ref_fields.filter(field => field.ref == this.meta.collection);
817
+
818
+ for (let j = 0; j < ref_fields.length; j++) {
819
+ const ref_field = ref_fields[j];
820
+ if (ref_field.delete != DELETE_MODE.keep) {
821
+ for (let j = 0; j < id_array.length; j++) {
822
+ const entities = await refer_by_entity.get_refer_entities(this.meta.collection, id_array[j], {});
823
+ if (entities && entities.length > 0) {
824
+ if (ref_field.delete == DELETE_MODE.cascade) {
825
+ const ref_id_array = await refer_by_entity.check_refer_entity(entities.map(o => o._id + ""));
826
+ if (ref_id_array && ref_id_array.length > 0) {
827
+ has_refer_by_array.push(id_array[j]);
828
+ }
829
+ } else {
830
+ has_refer_by_array.push(id_array[j]);
831
+ }
832
+ }
833
+ }
834
+ }
835
+ }
836
+ }
837
+ return has_refer_by_array;
838
+ }
839
+
737
840
  /**
738
841
  * check whether this entity has refered the entity_id value
739
842
  * @param {entity collection} entity_name
740
843
  * @param {entity object id} entity_id
741
844
  * @returns true if has refered
742
845
  */
743
- async has_refer_entity(entity_name, entity_id) {
846
+ async get_refer_entities(entity_name, entity_id, attr) {
847
+ const array = [];
744
848
  if (this.meta.ref_fields) {
745
849
  const fields = this.meta.ref_fields.filter(f => f.ref === entity_name);
746
850
  if (fields.length > 0) {
747
851
  for (let i = 0; i < fields.length; i++) {
748
852
  const field = fields[i];
749
853
  const query = { [field.name]: entity_id + "" };
750
- const count = await this.count(query);
751
- if (count > 0) {
752
- return true;
753
- }
854
+ const founed = await this.find(query, attr);
855
+ array.push(...founed);
754
856
  }
755
857
  }
756
858
  }
757
- return false;
859
+ return array;
860
+ }
861
+
862
+ /**
863
+ * delete the ref entity
864
+ * @param {entity collection} entity_name
865
+ * @param {entity object id} entity_id
866
+ * @returns
867
+ */
868
+ async delete_refer_entity(entity_name, entity_id) {
869
+ const entities = await this.get_refer_entities(entity_name, entity_id, {});
870
+ await this.delete_entity(entities.map(o => o._id + ""));
758
871
  }
759
872
 
760
873
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hola-server",
3
- "version": "0.3.7",
3
+ "version": "0.3.8",
4
4
  "description": "a meta programming framework used to build nodejs restful api",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -23,7 +23,7 @@
23
23
  "devDependencies": {
24
24
  "chai": "^4.3.6",
25
25
  "chai-http": "^4.3.0",
26
- "mocha": "^10.0.0"
26
+ "mocha": "^10.1.0"
27
27
  },
28
28
  "repository": {
29
29
  "type": "git",
package/setting.js CHANGED
@@ -5,7 +5,7 @@ let settings = {
5
5
  key: "AhBWt15WFj8PrMnnZhX8AF1IM4V2x0A3"
6
6
  },
7
7
  mongo: {
8
- url: 'mongodb://localhost/hola',
8
+ url: 'mongodb://127.0.0.1/hola',
9
9
  pool: 10
10
10
  },
11
11
  log: {
package/test/core/meta.js CHANGED
@@ -164,6 +164,102 @@ describe('EntityMeta', function () {
164
164
  strictEqual(entity_meta2.validate_meta_info(), true);
165
165
  });
166
166
 
167
+ it('should success for valid meta info for cascade delete', function () {
168
+ const entity_meta1 = new EntityMeta({
169
+ collection: "user11",
170
+ primary_keys: ["name"],
171
+ fields: [
172
+ { name: "name", type: "string", required: true },
173
+ { name: "role", type: "string", ref: "role_meta1", delete: "cascade", required: true },
174
+ ]
175
+ });
176
+
177
+ const entity_meta2 = new EntityMeta({
178
+ collection: "role_meta1",
179
+ primary_keys: ["name"],
180
+ ref_label: "name",
181
+ fields: [
182
+ { name: "name", type: "string", required: true },
183
+ ]
184
+ });
185
+
186
+ strictEqual(entity_meta1.validate_meta_info(), true);
187
+ strictEqual(entity_meta2.validate_meta_info(), true);
188
+ });
189
+
190
+ it('should success for valid meta info for keep delete', function () {
191
+ const entity_meta1 = new EntityMeta({
192
+ collection: "user12",
193
+ primary_keys: ["name"],
194
+ fields: [
195
+ { name: "name", type: "string", required: true },
196
+ { name: "role", type: "string", ref: "role_meta2", delete: "keep", required: true },
197
+ ]
198
+ });
199
+
200
+ const entity_meta2 = new EntityMeta({
201
+ collection: "role_meta2",
202
+ primary_keys: ["name"],
203
+ ref_label: "name",
204
+ fields: [
205
+ { name: "name", type: "string", required: true },
206
+ ]
207
+ });
208
+
209
+ strictEqual(entity_meta1.validate_meta_info(), true);
210
+ strictEqual(entity_meta2.validate_meta_info(), true);
211
+ });
212
+
213
+ it('should fails wrong delete value for ref', function () {
214
+ throws(() => {
215
+ const entity_meta1 = new EntityMeta({
216
+ collection: "user13",
217
+ primary_keys: ["name"],
218
+ fields: [
219
+ { name: "name", type: "string", required: true },
220
+ { name: "role", type: "string", ref: "role_meta3", delete: "other", required: true },
221
+ ]
222
+ });
223
+
224
+ const entity_meta2 = new EntityMeta({
225
+ collection: "role_meta3",
226
+ primary_keys: ["name"],
227
+ ref_label: "name",
228
+ fields: [
229
+ { name: "name", type: "string", required: true },
230
+ ]
231
+ });
232
+ entity_meta1.validate_meta_info();
233
+ entity_meta2.validate_meta_info();
234
+ });
235
+ });
236
+
237
+
238
+ it('should fails delete defined for non-ref field', function () {
239
+ throws(() => {
240
+ const entity_meta1 = new EntityMeta({
241
+ collection: "user14",
242
+ primary_keys: ["name"],
243
+ fields: [
244
+ { name: "name", type: "string", required: true, delete: "keep" },
245
+ { name: "role", type: "string", ref: "role_meta4", required: true },
246
+ ]
247
+ });
248
+
249
+ const entity_meta2 = new EntityMeta({
250
+ collection: "role_meta4",
251
+ primary_keys: ["name"],
252
+ ref_label: "name",
253
+ fields: [
254
+ { name: "name", type: "string", required: true },
255
+ ]
256
+ });
257
+ entity_meta1.validate_meta_info();
258
+ entity_meta2.validate_meta_info();
259
+ });
260
+ });
261
+
262
+
167
263
  it('should fails for wrong ref ', function () {
168
264
  throws(() => {
169
265
  const entity_meta1 = new EntityMeta({
@@ -208,7 +304,7 @@ describe('EntityMeta', function () {
208
304
 
209
305
  it('should collection and fields properties set successfully', function () {
210
306
  const entity_meta = new EntityMeta({
211
- collection: "user11",
307
+ collection: "user111",
212
308
  primary_keys: ["name"],
213
309
  fields: [
214
310
  { name: "email", type: "string", required: true },
@@ -216,7 +312,7 @@ describe('EntityMeta', function () {
216
312
  { name: "status", type: "string", required: true }
217
313
  ]
218
314
  });
219
- strictEqual(entity_meta.collection, "user11");
315
+ strictEqual(entity_meta.collection, "user111");
220
316
  strictEqual(entity_meta.fields.length, 3);
221
317
  strictEqual(entity_meta.field_names.join(""), ["email", "pwd", "status"].join(""));
222
318
  });
@@ -270,6 +270,210 @@ describe('Entity Delete', function () {
270
270
  });
271
271
  });
272
272
 
273
+ describe('delete entity with ref and keep delete fields', function () {
274
+ const user_meta = new EntityMeta({
275
+ creatable: true,
276
+ readable: true,
277
+ updatable: true,
278
+ deleteable: true,
279
+ collection: "user_entity_delete_eight",
280
+ primary_keys: ["name"],
281
+ ref_label: "name",
282
+ fields: [
283
+ { name: "name", required: true },
284
+ { name: "age", type: "uint" },
285
+ { name: "role", type: "string", ref: "role_delete_eight", delete: "keep", required: true },
286
+ ]
287
+ });
288
+
289
+ const role_meta = new EntityMeta({
290
+ creatable: true,
291
+ readable: true,
292
+ updatable: true,
293
+ deleteable: true,
294
+ collection: "role_delete_eight",
295
+ primary_keys: ["name"],
296
+ ref_label: "name",
297
+ fields: [
298
+ { name: "name", required: true },
299
+ { name: "desc", type: "string" }
300
+ ]
301
+ });
302
+
303
+ const log_meta = new EntityMeta({
304
+ creatable: true,
305
+ readable: true,
306
+ updatable: true,
307
+ deleteable: true,
308
+ collection: "log_one",
309
+ primary_keys: ["name"],
310
+ ref_label: "name",
311
+ fields: [
312
+ { name: "name", required: true },
313
+ { name: "user", type: "string", ref: "user_entity_delete_eight", delete: "cascade", required: true },
314
+ ]
315
+ });
316
+
317
+ user_meta.validate_meta_info();
318
+ role_meta.validate_meta_info();
319
+ log_meta.validate_meta_info();
320
+
321
+ const user_entity = new Entity(user_meta);
322
+ const role_entity = new Entity(role_meta);
323
+ const log_entity = new Entity(log_meta);
324
+
325
+ it('should delete user successfully with role', async function () {
326
+ await user_entity.delete({});
327
+ await role_entity.delete({});
328
+ await log_entity.delete({});
329
+ await role_entity.create({ "name": "role1" });
330
+ await role_entity.create({ "name": "role2", desc: "role 2" });
331
+ const db_role = await role_entity.find_one(user_entity.primary_key_query({ "name": "role1" }));
332
+
333
+ const user = { "name": "user1", age: "10", role: "role1" };
334
+ const { code, err } = await user_entity.create_entity(user);
335
+ const query = user_entity.primary_key_query(user);
336
+ const db_user = await user_entity.find_one(query);
337
+ strictEqual(code, SUCCESS);
338
+ strictEqual(err, undefined);
339
+ strictEqual(db_user.role, db_role["_id"] + "");
340
+
341
+ const user2 = { "name": "user2", age: "20", role: db_role["_id"] + "" };
342
+ const result = await user_entity.create_entity(user2);
343
+ const query2 = user_entity.primary_key_query(user2);
344
+ const db_user2 = await user_entity.find_one(query2);
345
+ strictEqual(result.code, SUCCESS);
346
+ strictEqual(result.err, undefined);
347
+ strictEqual(db_user2.role, db_role["_id"] + "");
348
+
349
+ const log1 = { "name": "log1", user: db_user2["_id"] + "" };
350
+ const resultlog = await log_entity.create_entity(log1);
351
+ const db_log = await log_entity.find_one(log_entity.primary_key_query(log1));
352
+ strictEqual(resultlog.code, SUCCESS);
353
+ strictEqual(resultlog.err, undefined);
354
+ strictEqual(db_log.user, db_user2["_id"] + "");
355
+
356
+ const delete_ids = [db_role["_id"] + ""];
357
+ const result3 = await role_entity.delete_entity(delete_ids);
358
+ strictEqual(result3.code, SUCCESS);
359
+ deepStrictEqual(result3.err, undefined);
360
+
361
+ strictEqual(await user_entity.count({}), 2);
362
+ strictEqual(await role_entity.count({}), 1);
363
+ strictEqual(await log_entity.count({}), 1);
364
+
365
+ const result4 = await user_entity.delete_entity([db_user2["_id"] + ""]);
366
+ strictEqual(result4.code, SUCCESS);
367
+ deepStrictEqual(result4.err, undefined);
368
+
369
+ strictEqual(await user_entity.count({}), 1);
370
+ strictEqual(await role_entity.count({}), 1);
371
+ strictEqual(await log_entity.count({}), 0);
372
+
373
+ await user_entity.delete({});
374
+ await role_entity.delete({});
375
+ await log_entity.delete({});
376
+ });
377
+ });
378
+
379
+
380
+ describe('delete entity with ref and cascade delete fields', function () {
381
+ const user_meta = new EntityMeta({
382
+ creatable: true,
383
+ readable: true,
384
+ updatable: true,
385
+ deleteable: true,
386
+ collection: "user_entity_delete_nine",
387
+ primary_keys: ["name"],
388
+ ref_label: "name",
389
+ fields: [
390
+ { name: "name", required: true },
391
+ { name: "age", type: "uint" },
392
+ { name: "role", type: "string", ref: "role_delete_nine", delete: "cascade", required: true },
393
+ ]
394
+ });
395
+
396
+ const role_meta = new EntityMeta({
397
+ creatable: true,
398
+ readable: true,
399
+ updatable: true,
400
+ deleteable: true,
401
+ collection: "role_delete_nine",
402
+ primary_keys: ["name"],
403
+ ref_label: "name",
404
+ fields: [
405
+ { name: "name", required: true },
406
+ { name: "desc", type: "string" }
407
+ ]
408
+ });
409
+
410
+ const log_meta = new EntityMeta({
411
+ creatable: true,
412
+ readable: true,
413
+ updatable: true,
414
+ deleteable: true,
415
+ collection: "log_nine",
416
+ primary_keys: ["name"],
417
+ ref_label: "name",
418
+ fields: [
419
+ { name: "name", required: true },
420
+ { name: "user", type: "string", ref: "user_entity_delete_nine", delete: "cascade", required: true },
421
+ ]
422
+ });
423
+
424
+ user_meta.validate_meta_info();
425
+ role_meta.validate_meta_info();
426
+ log_meta.validate_meta_info();
427
+
428
+ const user_entity = new Entity(user_meta);
429
+ const role_entity = new Entity(role_meta);
430
+ const log_entity = new Entity(log_meta);
431
+
432
+ it('should delete user successfully with role', async function () {
433
+ await user_entity.delete({});
434
+ await role_entity.delete({});
435
+ await log_entity.delete({});
436
+ await role_entity.create({ "name": "role1" });
437
+ await role_entity.create({ "name": "role2", desc: "role 2" });
438
+ const db_role = await role_entity.find_one(user_entity.primary_key_query({ "name": "role1" }));
439
+
440
+ const user = { "name": "user1", age: "10", role: "role1" };
441
+ const { code, err } = await user_entity.create_entity(user);
442
+ const query = user_entity.primary_key_query(user);
443
+ const db_user = await user_entity.find_one(query);
444
+ strictEqual(code, SUCCESS);
445
+ strictEqual(err, undefined);
446
+ strictEqual(db_user.role, db_role["_id"] + "");
447
+
448
+ const user2 = { "name": "user2", age: "20", role: db_role["_id"] + "" };
449
+ const result = await user_entity.create_entity(user2);
450
+ const query2 = user_entity.primary_key_query(user2);
451
+ const db_user2 = await user_entity.find_one(query2);
452
+ strictEqual(result.code, SUCCESS);
453
+ strictEqual(result.err, undefined);
454
+ strictEqual(db_user2.role, db_role["_id"] + "");
455
+
456
+ const log1 = { "name": "log1", user: db_user2["_id"] + "" };
457
+ const resultlog = await log_entity.create_entity(log1);
458
+ const db_log = await log_entity.find_one(log_entity.primary_key_query(log1));
459
+ strictEqual(resultlog.code, SUCCESS);
460
+ strictEqual(resultlog.err, undefined);
461
+ strictEqual(db_log.user, db_user2["_id"] + "");
462
+
463
+ const delete_ids = [db_role["_id"] + ""];
464
+ const result3 = await role_entity.delete_entity(delete_ids);
465
+ strictEqual(result3.code, SUCCESS);
466
+ deepStrictEqual(result3.err, undefined);
467
+
468
+ strictEqual(await user_entity.count({}), 0);
469
+ strictEqual(await role_entity.count({}), 1);
470
+ strictEqual(await log_entity.count({}), 0);
471
+
472
+ await user_entity.delete({});
473
+ await role_entity.delete({});
474
+ await log_entity.delete({});
475
+ });
476
+ });
273
477
  });
274
478
  }
275
479
  );