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 +25 -4
- package/db/entity.js +151 -38
- package/package.json +2 -2
- package/setting.js +1 -1
- package/test/core/meta.js +98 -2
- package/test/entity/delete.js +204 -0
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
|
-
|
|
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
|
-
|
|
573
|
-
|
|
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
|
|
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
|
|
751
|
-
|
|
752
|
-
return true;
|
|
753
|
-
}
|
|
854
|
+
const founed = await this.find(query, attr);
|
|
855
|
+
array.push(...founed);
|
|
754
856
|
}
|
|
755
857
|
}
|
|
756
858
|
}
|
|
757
|
-
return
|
|
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.
|
|
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.
|
|
26
|
+
"mocha": "^10.1.0"
|
|
27
27
|
},
|
|
28
28
|
"repository": {
|
|
29
29
|
"type": "git",
|
package/setting.js
CHANGED
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: "
|
|
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, "
|
|
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
|
});
|
package/test/entity/delete.js
CHANGED
|
@@ -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
|
);
|