hola-server 1.0.11 → 3.0.0

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.
Files changed (204) hide show
  1. package/README.md +382 -1
  2. package/dist/config/index.d.ts +46 -0
  3. package/dist/config/index.d.ts.map +1 -0
  4. package/dist/config/index.js +55 -0
  5. package/dist/config/index.js.map +1 -0
  6. package/dist/core/array.d.ts +27 -0
  7. package/dist/core/array.d.ts.map +1 -0
  8. package/dist/core/array.js +66 -0
  9. package/dist/core/array.js.map +1 -0
  10. package/dist/core/bash.d.ts +51 -0
  11. package/dist/core/bash.d.ts.map +1 -0
  12. package/dist/core/bash.js +161 -0
  13. package/dist/core/bash.js.map +1 -0
  14. package/dist/core/chart.d.ts +11 -0
  15. package/dist/core/chart.d.ts.map +1 -0
  16. package/dist/core/chart.js +35 -0
  17. package/dist/core/chart.js.map +1 -0
  18. package/dist/core/date.d.ts +11 -0
  19. package/dist/core/date.d.ts.map +1 -0
  20. package/dist/core/date.js +18 -0
  21. package/dist/core/date.js.map +1 -0
  22. package/dist/core/encrypt.d.ts +18 -0
  23. package/dist/core/encrypt.d.ts.map +1 -0
  24. package/dist/core/encrypt.js +50 -0
  25. package/dist/core/encrypt.js.map +1 -0
  26. package/dist/core/file.d.ts +22 -0
  27. package/dist/core/file.d.ts.map +1 -0
  28. package/dist/core/file.js +21 -0
  29. package/dist/core/file.js.map +1 -0
  30. package/dist/core/lhs.d.ts +17 -0
  31. package/dist/core/lhs.d.ts.map +1 -0
  32. package/dist/core/lhs.js +30 -0
  33. package/dist/core/lhs.js.map +1 -0
  34. package/dist/core/meta.d.ts +200 -0
  35. package/dist/core/meta.d.ts.map +1 -0
  36. package/dist/core/meta.js +336 -0
  37. package/dist/core/meta.js.map +1 -0
  38. package/dist/core/number.d.ts +37 -0
  39. package/dist/core/number.d.ts.map +1 -0
  40. package/dist/core/number.js +99 -0
  41. package/dist/core/number.js.map +1 -0
  42. package/dist/core/obj.d.ts +9 -0
  43. package/dist/core/obj.d.ts.map +1 -0
  44. package/dist/core/obj.js +15 -0
  45. package/dist/core/obj.js.map +1 -0
  46. package/dist/core/random.d.ts +7 -0
  47. package/dist/core/random.d.ts.map +1 -0
  48. package/dist/core/random.js +7 -0
  49. package/dist/core/random.js.map +1 -0
  50. package/dist/core/role.d.ts +42 -0
  51. package/dist/core/role.d.ts.map +1 -0
  52. package/dist/core/role.js +81 -0
  53. package/dist/core/role.js.map +1 -0
  54. package/dist/core/thread.d.ts +7 -0
  55. package/dist/core/thread.d.ts.map +1 -0
  56. package/dist/core/thread.js +7 -0
  57. package/dist/core/thread.js.map +1 -0
  58. package/dist/core/type.d.ts +46 -0
  59. package/dist/core/type.d.ts.map +1 -0
  60. package/dist/core/type.js +281 -0
  61. package/dist/core/type.js.map +1 -0
  62. package/dist/core/url.d.ts +20 -0
  63. package/dist/core/url.d.ts.map +1 -0
  64. package/dist/core/url.js +24 -0
  65. package/dist/core/url.js.map +1 -0
  66. package/dist/core/validate.d.ts +11 -0
  67. package/dist/core/validate.d.ts.map +1 -0
  68. package/dist/core/validate.js +19 -0
  69. package/dist/core/validate.js.map +1 -0
  70. package/dist/db/db.d.ts +72 -0
  71. package/dist/db/db.d.ts.map +1 -0
  72. package/dist/db/db.js +225 -0
  73. package/dist/db/db.js.map +1 -0
  74. package/dist/db/entity.d.ts +77 -0
  75. package/dist/db/entity.d.ts.map +1 -0
  76. package/dist/db/entity.js +671 -0
  77. package/dist/db/entity.js.map +1 -0
  78. package/dist/db/gridfs.d.ts +29 -0
  79. package/dist/db/gridfs.d.ts.map +1 -0
  80. package/dist/db/gridfs.js +125 -0
  81. package/dist/db/gridfs.js.map +1 -0
  82. package/dist/db/index.d.ts +8 -0
  83. package/dist/db/index.d.ts.map +1 -0
  84. package/dist/db/index.js +8 -0
  85. package/dist/db/index.js.map +1 -0
  86. package/dist/errors/auth.d.ts +15 -0
  87. package/dist/errors/auth.d.ts.map +1 -0
  88. package/dist/errors/auth.js +21 -0
  89. package/dist/errors/auth.js.map +1 -0
  90. package/dist/errors/http.d.ts +15 -0
  91. package/dist/errors/http.d.ts.map +1 -0
  92. package/dist/errors/http.js +21 -0
  93. package/dist/errors/http.js.map +1 -0
  94. package/dist/errors/index.d.ts +18 -0
  95. package/dist/errors/index.d.ts.map +1 -0
  96. package/dist/errors/index.js +18 -0
  97. package/dist/errors/index.js.map +1 -0
  98. package/dist/errors/validation.d.ts +11 -0
  99. package/dist/errors/validation.d.ts.map +1 -0
  100. package/dist/errors/validation.js +15 -0
  101. package/dist/errors/validation.js.map +1 -0
  102. package/dist/http/code.d.ts +21 -0
  103. package/dist/http/code.d.ts.map +1 -0
  104. package/dist/http/code.js +27 -0
  105. package/dist/http/code.js.map +1 -0
  106. package/dist/index.d.ts +57 -0
  107. package/dist/index.d.ts.map +1 -0
  108. package/dist/index.js +61 -0
  109. package/dist/index.js.map +1 -0
  110. package/dist/meta/index.d.ts +9 -0
  111. package/dist/meta/index.d.ts.map +1 -0
  112. package/dist/meta/index.js +11 -0
  113. package/dist/meta/index.js.map +1 -0
  114. package/dist/meta/router.d.ts +26 -0
  115. package/dist/meta/router.d.ts.map +1 -0
  116. package/dist/meta/router.js +258 -0
  117. package/dist/meta/router.js.map +1 -0
  118. package/dist/meta/schema.d.ts +41 -0
  119. package/dist/meta/schema.d.ts.map +1 -0
  120. package/dist/meta/schema.js +69 -0
  121. package/dist/meta/schema.js.map +1 -0
  122. package/dist/plugins/auth.d.ts +248 -0
  123. package/dist/plugins/auth.d.ts.map +1 -0
  124. package/dist/plugins/auth.js +121 -0
  125. package/dist/plugins/auth.js.map +1 -0
  126. package/dist/plugins/body.d.ts +47 -0
  127. package/dist/plugins/body.d.ts.map +1 -0
  128. package/dist/plugins/body.js +36 -0
  129. package/dist/plugins/body.js.map +1 -0
  130. package/dist/plugins/cors.d.ts +62 -0
  131. package/dist/plugins/cors.d.ts.map +1 -0
  132. package/dist/plugins/cors.js +17 -0
  133. package/dist/plugins/cors.js.map +1 -0
  134. package/dist/plugins/error.d.ts +51 -0
  135. package/dist/plugins/error.d.ts.map +1 -0
  136. package/dist/plugins/error.js +51 -0
  137. package/dist/plugins/error.js.map +1 -0
  138. package/dist/plugins/index.d.ts +9 -0
  139. package/dist/plugins/index.d.ts.map +1 -0
  140. package/dist/plugins/index.js +9 -0
  141. package/dist/plugins/index.js.map +1 -0
  142. package/dist/setting.d.ts +66 -0
  143. package/dist/setting.d.ts.map +1 -0
  144. package/dist/setting.js +27 -0
  145. package/dist/setting.js.map +1 -0
  146. package/dist/tool/gen_i18n.d.ts +10 -0
  147. package/dist/tool/gen_i18n.d.ts.map +1 -0
  148. package/dist/tool/gen_i18n.js +51 -0
  149. package/dist/tool/gen_i18n.js.map +1 -0
  150. package/dist/tool/vector_store.d.ts +72 -0
  151. package/dist/tool/vector_store.d.ts.map +1 -0
  152. package/dist/tool/vector_store.js +203 -0
  153. package/dist/tool/vector_store.js.map +1 -0
  154. package/package.json +38 -23
  155. package/core/array.js +0 -187
  156. package/core/bash.js +0 -345
  157. package/core/chart.js +0 -36
  158. package/core/cron.js +0 -10
  159. package/core/date.js +0 -55
  160. package/core/encrypt.js +0 -16
  161. package/core/file.js +0 -38
  162. package/core/lhs.js +0 -27
  163. package/core/meta.js +0 -359
  164. package/core/msg.js +0 -11
  165. package/core/number.js +0 -179
  166. package/core/obj.js +0 -22
  167. package/core/random.js +0 -9
  168. package/core/role.js +0 -116
  169. package/core/thread.js +0 -3
  170. package/core/type.js +0 -329
  171. package/core/url.js +0 -22
  172. package/core/validate.js +0 -32
  173. package/db/db.js +0 -376
  174. package/db/entity.js +0 -1252
  175. package/db/gridfs.js +0 -221
  176. package/http/code.js +0 -18
  177. package/http/context.js +0 -17
  178. package/http/cors.js +0 -15
  179. package/http/error.js +0 -21
  180. package/http/express.js +0 -75
  181. package/http/params.js +0 -57
  182. package/http/router.js +0 -72
  183. package/http/session.js +0 -50
  184. package/index.js +0 -36
  185. package/router/clone.js +0 -73
  186. package/router/create.js +0 -59
  187. package/router/delete.js +0 -53
  188. package/router/read.js +0 -177
  189. package/router/update.js +0 -107
  190. package/setting.js +0 -51
  191. package/test/core/date.js +0 -37
  192. package/test/core/encrypt.js +0 -14
  193. package/test/core/meta.js +0 -594
  194. package/test/core/number.js +0 -17
  195. package/test/crud/router.js +0 -99
  196. package/test/db/db.js +0 -72
  197. package/test/entity/create.js +0 -442
  198. package/test/entity/delete.js +0 -480
  199. package/test/entity/read.js +0 -285
  200. package/test/entity/update.js +0 -252
  201. package/test/router/role.js +0 -15
  202. package/test/router/user.js +0 -17
  203. package/tool/gen_i18n.js +0 -30
  204. package/tool/test.json +0 -25
package/db/entity.js DELETED
@@ -1,1252 +0,0 @@
1
- const { SUCCESS, ERROR, NO_PARAMS, INVALID_PARAMS, DUPLICATE_KEY, NOT_FOUND, REF_NOT_FOUND, REF_NOT_UNIQUE, HAS_REF } = require('../http/code');
2
- const { validate_required_fields, has_value } = require('../core/validate');
3
- const { required_params } = require('../http/params');
4
- const { convert_type, convert_update_type, get_type } = require('../core/type');
5
- const { get_entity_meta, DELETE_MODE } = require('../core/meta');
6
- const { unique, map_array_to_obj } = require('../core/array');
7
- const { LOG_ENTITY, get_db, oid_query, oid_queries, is_log_debug, is_log_error, log_debug, log_error, get_session_userid, bulk_update } = require('./db');
8
-
9
- /**
10
- * Convert search value type, if there is error, keep it
11
- * @param {field type} type_name
12
- * @param {search value} search_value
13
- * @returns
14
- */
15
- const convert_search_value_by_type = (type_name, search_value) => {
16
- const type = get_type(type_name);
17
- const { value, err } = type.convert(search_value);
18
- if (err) {
19
- return search_value;
20
- } else {
21
- return value;
22
- }
23
- }
24
-
25
- /**
26
- * Create search object based on the field type and value
27
- * @param {field name} name
28
- * @param {field type name} type_name
29
- * @param {search value} search_value
30
- * @returns
31
- */
32
- const parse_search_value = function (name, type_name, search_value) {
33
- search_value = search_value + "";
34
- if (search_value.startsWith(">=")) {
35
- const value = search_value.substring(2);
36
- return { [name]: { "$gte": convert_search_value_by_type(type_name, value) } };
37
- } else if (search_value.startsWith("<=")) {
38
- const value = search_value.substring(2);
39
- return { [name]: { "$lte": convert_search_value_by_type(type_name, value) } };
40
- } else if (search_value.startsWith(">")) {
41
- const value = search_value.substring(1);
42
- return { [name]: { "$gt": convert_search_value_by_type(type_name, value) } };
43
- } else if (search_value.startsWith("<")) {
44
- const value = search_value.substring(1);
45
- return { [name]: { "$lt": convert_search_value_by_type(type_name, value) } };
46
- } else if (type_name === "array") {
47
- return { [name]: { "$in": [search_value] } };
48
- } else {
49
- let value = convert_search_value_by_type(type_name, search_value);
50
- if (typeof value === "string") {
51
- value = new RegExp(value, 'i');
52
- }
53
- return { [name]: value }
54
- }
55
- };
56
-
57
- class Entity {
58
- /**
59
- * @param {entity meta obj} meta
60
- */
61
- constructor(meta) {
62
- this.meta = (typeof meta === 'string' || meta instanceof String) ? get_entity_meta(meta) : meta;
63
- this.db = get_db();
64
- }
65
-
66
- /**
67
- *
68
- * @returns mongo underlying collection
69
- */
70
- get_col() {
71
- return this.db.get_col(this.meta.collection);
72
- }
73
-
74
- /**
75
- * Execute bulk update using the items
76
- * @param {the items to execute bulk update} items
77
- * @param {the attributes used as search criteria} attrs
78
- * @returns
79
- */
80
- async bulk_update(items, attrs) {
81
- const col = this.get_col();
82
- await bulk_update(col, items, attrs);
83
- }
84
-
85
- /**
86
- * validate the ref value, if success, return code:SUCCESS
87
- * and if the value is ref_label then convert ref_label to objectid
88
- * @param {param object} param_obj
89
- * @returns code and err
90
- */
91
- async validate_ref(param_obj) {
92
- const ref_fields = this.meta.ref_fields;
93
- if (ref_fields) {
94
- for (let i = 0; i < ref_fields.length; i++) {
95
- const field = ref_fields[i];
96
- const value = param_obj[field.name];
97
- const ref_entity = new Entity(get_entity_meta(field.ref));
98
-
99
- if (Array.isArray(value)) {
100
- const array = [];
101
- for (let j = 0; j < value.length; j++) {
102
- const v = value[j];
103
- const ref_entities = await ref_entity.find_by_ref_value(v, { "_id": 1 }, this.meta.collection);
104
-
105
- if (ref_entities.length == 0) {
106
- return { code: REF_NOT_FOUND, err: [field.name] };
107
- } else if (ref_entities.length > 1) {
108
- return { code: REF_NOT_UNIQUE, err: [field.name] };
109
- } else if (ref_entities.length == 1) {
110
- array.push(ref_entities[0]["_id"] + "");
111
- }
112
- }
113
- param_obj[field.name] = array;
114
-
115
- } else if (has_value(value)) {
116
- const ref_entities = await ref_entity.find_by_ref_value(value, { "_id": 1 }, this.meta.collection);
117
-
118
- if (ref_entities.length == 0) {
119
- return { code: REF_NOT_FOUND, err: [field.name] };
120
- } else if (ref_entities.length > 1) {
121
- return { code: REF_NOT_UNIQUE, err: [field.name] };
122
- } else if (ref_entities.length == 1) {
123
- param_obj[field.name] = ref_entities[0]["_id"] + "";
124
- }
125
- }
126
- }
127
- }
128
- return { code: SUCCESS };
129
- }
130
-
131
- /**
132
- * Create search query object using params from client side
133
- * @param {search field value from client side} param_obj
134
- */
135
- async get_search_query(param_obj) {
136
- const search_fields = this.meta.search_fields;
137
- if (search_fields && search_fields.length > 0) {
138
- const refer_field_names = this.meta.ref_fields.map(f => f.name);
139
- const query = {};
140
- const and_array = [];
141
- for (let i = 0; i < search_fields.length; i++) {
142
- const search_field = search_fields[i];
143
- const value = param_obj[search_field.name];
144
- if (has_value(value)) {
145
- if (refer_field_names.includes(search_field.name)) {
146
- //refer field
147
- const refer_entity = new Entity(get_entity_meta(search_field.ref));
148
- const oids = await refer_entity.find_by_ref_value(value, { _id: 1 }, this.meta.collection);
149
- if (oids.length == 1) {
150
- and_array.push({ [search_field.name]: oids.map(o => o._id + "")[0] });
151
- } else if (oids.length > 1) {
152
- and_array.push({ [search_field.name]: { "$in": oids.map(o => o._id + "") } });
153
- }
154
- } else {
155
- and_array.push(parse_search_value(search_field.name, search_field.type, value));
156
- }
157
- }
158
- }
159
-
160
- if (param_obj["_id"] && param_obj["_id"].trim().length > 0) {
161
- const ids = param_obj["_id"].split(",");
162
- if (ids.length == 1) {
163
- and_array.push(oid_query(ids[0]));
164
- } else if (ids.length > 1) {
165
- and_array.push(oid_queries(ids));
166
- }
167
- }
168
-
169
- if (and_array.length > 0) {
170
- query["$and"] = and_array;
171
-
172
- if (is_log_debug()) {
173
- log_debug(LOG_ENTITY, "search query:" + JSON.stringify(query));
174
- }
175
-
176
- return query;
177
- } else {
178
- return {};
179
- }
180
- } else {
181
- return null;
182
- }
183
- }
184
-
185
- /**
186
- * if query is set, it will use this as search query, otherwise create search object from param_obj
187
- * @param {query object to search} query
188
- * @param {search object and all the search attributes object} param_obj
189
- * @returns
190
- */
191
- async list_entity(query_params, query, param_obj, view) {
192
- const error_required_field_names = validate_required_fields(query_params, ["attr_names", "sort_by", "desc"]);
193
- if (error_required_field_names.length > 0) {
194
- if (is_log_error()) {
195
- log_error(LOG_ENTITY, "error required fields:" + JSON.stringify(error_required_field_names));
196
- }
197
-
198
- return { code: NO_PARAMS, err: error_required_field_names };
199
- }
200
-
201
- const { attr_names, page, limit, sort_by, desc } = query_params;
202
- const sort = {};
203
- const sorts = sort_by.split(",");
204
- const descs = desc.split(",");
205
- sorts.forEach(function (value, index) {
206
- sort[value] = descs[index] === "false" ? 1 : -1;
207
- });
208
-
209
- const list_fields = view && view !== "*" ? this.meta.list_fields.filter(field => Array.isArray(field.view) ? this.contain_view(field.view, view) || field.view.includes("*") : view.includes(field.view) || field.view === "*") : this.meta.list_fields;
210
- const list_field_names = list_fields.map(f => f.name);
211
-
212
- const ref_fields = [];
213
- const link_fields = [];
214
-
215
- const attrs = {};
216
- const fields_map = this.meta.fields_map;
217
- attr_names.split(",").forEach((attr) => {
218
- if (list_field_names.includes(attr)) {
219
- attrs[attr] = 1;
220
- const field = fields_map[attr];
221
- if (field.link) {
222
- link_fields.push(field);
223
- attrs[field.link] = 1;
224
- } else if (field.ref) {
225
- ref_fields.push(field);
226
- }
227
- }
228
- });
229
-
230
- let page_int = parseInt(page);
231
- page_int = isNaN(page_int) || page_int <= 0 ? 1 : page_int;
232
- let page_limit = parseInt(limit);
233
- page_limit = isNaN(page_limit) || page_limit <= 0 ? 10 : page_limit;
234
-
235
- const search_query = { ...query, ...await this.get_search_query(param_obj) };
236
- if (!search_query) {
237
- if (is_log_error()) {
238
- log_error(LOG_ENTITY, "no search query is set for param:" + JSON.stringify(param_obj));
239
- }
240
-
241
- return { code: INVALID_PARAMS, err: "no search query is set" };
242
- }
243
-
244
- const total = await this.count(search_query);
245
- const list = await this.find_page(search_query, sort, page_int, page_limit, attrs);
246
- const list_link = await this.read_link_attrs(list, link_fields);
247
- const data = await this.convert_ref_attrs(list_link, ref_fields);
248
-
249
- if (is_log_debug()) {
250
- log_debug(LOG_ENTITY, "total:" + total + ",data:" + JSON.stringify(data));
251
- }
252
-
253
- return { code: SUCCESS, total: total, data: data };
254
- }
255
-
256
- /**
257
- * Validate the param object and invoke the logic to save it to db
258
- * @param {param obj from user input} param_obj
259
- * @param {which view to create the entity} view
260
- * @returns object with code and err
261
- */
262
- async create_entity(param_obj, view) {
263
- const fields = view && view !== "*" ? this.meta.create_fields.filter(field => Array.isArray(field.view) ? field.view.includes(view) || field.view.includes("*") : field.view === view || field.view === "*") : this.meta.create_fields;
264
- const { obj, error_field_names } = convert_type(param_obj, fields);
265
- if (error_field_names.length > 0) {
266
- if (is_log_error()) {
267
- log_error(LOG_ENTITY, "error fields:" + JSON.stringify(error_field_names));
268
- }
269
-
270
- return { code: INVALID_PARAMS, err: error_field_names };
271
- }
272
-
273
- if (this.meta.before_create) {
274
- const { code, err } = await this.meta.before_create(this, obj);
275
- if (err || code != SUCCESS) {
276
- if (is_log_error()) {
277
- log_error(LOG_ENTITY, "before_create error:" + JSON.stringify(err) + ", with code:" + code);
278
- }
279
- return { code: code, err: err };
280
- }
281
- }
282
-
283
- const error_required_field_names = validate_required_fields(obj, this.meta.required_field_names);
284
- if (error_required_field_names.length > 0) {
285
- if (is_log_error()) {
286
- log_error(LOG_ENTITY, "error required fields:" + JSON.stringify(error_required_field_names));
287
- }
288
- return { code: NO_PARAMS, err: error_required_field_names };
289
- }
290
-
291
- const entity_count = await this.count_by_primary_keys(obj);
292
- if (entity_count > 0) {
293
- return { code: DUPLICATE_KEY, err: "entity already exist in db" };
294
- }
295
-
296
- if (this.meta.ref_fields) {
297
- const { code, err } = await this.validate_ref(obj);
298
- if (err || code != SUCCESS) {
299
- if (is_log_error()) {
300
- log_error(LOG_ENTITY, "validate_ref error:" + JSON.stringify(err) + ", with code:" + code);
301
- }
302
- return { code: code, err: err };
303
- }
304
- }
305
-
306
- if (this.meta.create) {
307
- const { code, err } = await this.meta.create(this, obj);
308
- if (err || code != SUCCESS) {
309
- if (is_log_error()) {
310
- log_error(LOG_ENTITY, "create error:" + JSON.stringify(err) + ", with code:" + code);
311
- }
312
- return { code: code, err: err };
313
- }
314
- } else {
315
- const db_obj = await this.create(obj);
316
- if (!db_obj["_id"]) {
317
- if (is_log_error()) {
318
- log_error(LOG_ENTITY, "create error:" + JSON.stringify(err) + ", with code:" + code);
319
- }
320
- return { code: ERROR, err: "creating record is failed" };
321
- }
322
- }
323
-
324
- if (this.meta.after_create) {
325
- const { code, err } = await this.meta.after_create(this, obj);
326
- if (err || code != SUCCESS) {
327
- if (is_log_error()) {
328
- log_error(LOG_ENTITY, "after_create error:" + JSON.stringify(err) + ", with code:" + code);
329
- }
330
- return { code: code, err: err };
331
- }
332
- }
333
-
334
- return { code: SUCCESS };
335
- }
336
-
337
- /**
338
- * Validate the param object and invoke the logic to clone the entity and sae it to db
339
- * @param {param obj from user input} param_obj
340
- * @returns object with code and err
341
- */
342
- async clone_entity(_id, param_obj, view) {
343
- const fields = view && view !== "*" ? this.meta.clone_fields.filter(field => Array.isArray(field.view) ? field.view.includes(view) || field.view.includes("*") : field.view === view || field.view === "*") : this.meta.clone_fields;
344
- const { obj, error_field_names } = convert_type(param_obj, fields);
345
- if (error_field_names.length > 0) {
346
- if (is_log_error()) {
347
- log_error(LOG_ENTITY, "error fields:" + JSON.stringify(error_field_names));
348
- }
349
-
350
- return { code: INVALID_PARAMS, err: error_field_names };
351
- }
352
-
353
- if (this.meta.before_clone) {
354
- const { code, err } = await this.meta.before_clone(_id, this, obj);
355
- if (err || code != SUCCESS) {
356
- if (is_log_error()) {
357
- log_error(LOG_ENTITY, "before_clone error:" + JSON.stringify(err) + ", with code:" + code);
358
- }
359
- return { code: code, err: err };
360
- }
361
- }
362
-
363
- const error_required_field_names = validate_required_fields(obj, this.meta.required_field_names);
364
- if (error_required_field_names.length > 0) {
365
- if (is_log_error()) {
366
- log_error(LOG_ENTITY, "error required fields:" + JSON.stringify(error_required_field_names));
367
- }
368
- return { code: NO_PARAMS, err: error_required_field_names };
369
- }
370
-
371
- const entity_count = await this.count_by_primary_keys(obj);
372
- if (entity_count > 0) {
373
- return { code: DUPLICATE_KEY, err: "entity already exist in db" };
374
- }
375
-
376
- if (this.meta.ref_fields) {
377
- const { code, err } = await this.validate_ref(obj);
378
- if (err || code != SUCCESS) {
379
- if (is_log_error()) {
380
- log_error(LOG_ENTITY, "validate_ref error:" + JSON.stringify(err) + ", with code:" + code);
381
- }
382
- return { code: code, err: err };
383
- }
384
- }
385
-
386
- if (this.meta.clone) {
387
- const { code, err } = await this.meta.clone(_id, this, obj);
388
- if (err || code != SUCCESS) {
389
- if (is_log_error()) {
390
- log_error(LOG_ENTITY, "clone error:" + JSON.stringify(err) + ", with code:" + code);
391
- }
392
- return { code: code, err: err };
393
- }
394
- } else {
395
- const db_obj = await this.create(obj);
396
- if (!db_obj["_id"]) {
397
- if (is_log_error()) {
398
- log_error(LOG_ENTITY, "create error:" + JSON.stringify(err) + ", with code:" + code);
399
- }
400
- return { code: ERROR, err: "creating record is failed" };
401
- }
402
- }
403
-
404
- if (this.meta.after_clone) {
405
- const { code, err } = await this.meta.after_clone(_id, this, obj);
406
- if (err || code != SUCCESS) {
407
- if (is_log_error()) {
408
- log_error(LOG_ENTITY, "after_clone error:" + JSON.stringify(err) + ", with code:" + code);
409
- }
410
- return { code: code, err: err };
411
- }
412
- }
413
-
414
- return { code: SUCCESS };
415
- }
416
-
417
-
418
- /**
419
- * Validate the param object and invoke the logic to update entity
420
- * @param {object id of the entity} _id object id of the entity, if it is null, then use primary key
421
- * @param {param object from user input} param_obj
422
- * @param {which view to update the entity} view
423
- *
424
- */
425
- async update_entity(_id, param_obj, view) {
426
- const fields = view && view !== "*" ? this.meta.update_fields.filter(field => Array.isArray(field.view) ? field.view.includes(view) || field.view.includes("*") : field.view === view || field.view === "*") : this.meta.update_fields;
427
-
428
- const { obj, error_field_names } = convert_update_type(param_obj, fields);
429
- if (error_field_names.length > 0) {
430
- if (is_log_error()) {
431
- log_error(LOG_ENTITY, "update_entity error fields:" + JSON.stringify(error_field_names));
432
- }
433
- return { code: INVALID_PARAMS, err: error_field_names };
434
- }
435
-
436
- if (this.meta.before_update) {
437
- const { code, err } = await this.meta.before_update(_id, this, obj);
438
- if (err || code != SUCCESS) {
439
- if (is_log_error()) {
440
- log_error(LOG_ENTITY, "before_update error:" + JSON.stringify(err) + ", with code:" + code);
441
- }
442
- return { code: code, err: err };
443
- }
444
- }
445
-
446
- const query = _id ? oid_query(_id) : this.primary_key_query(obj);
447
- if (query == null) {
448
- if (is_log_error()) {
449
- log_error(LOG_ENTITY, "error query _id:" + _id + ", with obj:" + JSON.stringify(obj));
450
- }
451
- return { code: INVALID_PARAMS, err: _id ? ["_id"] : this.meta.primary_keys };
452
- }
453
-
454
- const total = await this.count(query);
455
- if (total != 1) {
456
- if (is_log_error()) {
457
- log_error(LOG_ENTITY, "update_entity not found with query:" + JSON.stringify(query) + ", and total:" + total);
458
- }
459
- return { code: NOT_FOUND, err: _id ? ["_id"] : this.meta.primary_keys };
460
- }
461
-
462
- if (this.meta.ref_fields) {
463
- const { code, err } = await this.validate_ref(obj);
464
- if (err || code != SUCCESS) {
465
- if (is_log_error()) {
466
- log_error(LOG_ENTITY, "update_entity validate_ref error:" + JSON.stringify(err) + ", with code:" + code);
467
- }
468
- return { code: code, err: err };
469
- }
470
- }
471
-
472
- if (this.meta.update) {
473
- const { code, err } = await this.meta.update(_id, this, obj);
474
- if (err || code != SUCCESS) {
475
- if (is_log_error()) {
476
- log_error(LOG_ENTITY, "meta update error:" + JSON.stringify(err) + ", with code:" + code + ",_id:" + _id + ",obj:" + JSON.stringify(obj));
477
- }
478
- return { code: code, err: err };
479
- }
480
- } else {
481
- const result = await this.update(query, obj);
482
- if (result.ok != 1) {
483
- if (is_log_error()) {
484
- log_error(LOG_ENTITY, "update record is failed with query:" + JSON.stringify(query) + ",obj:" + JSON.stringify(obj) + ",result:" + JSON.stringify(result));
485
- }
486
- return { code: ERROR, err: "update record is failed" };
487
- }
488
- }
489
-
490
- if (this.meta.after_update) {
491
- const { code, err } = await this.meta.after_update(_id, this, obj);
492
- if (err || code != SUCCESS) {
493
- if (is_log_error()) {
494
- log_error(LOG_ENTITY, "after_update is failed with _id:" + JSON.stringify(_id) + ",obj:" + JSON.stringify(obj) + ",err:" + JSON.stringify(err) + ",code:" + code);
495
- }
496
- return { code: code, err: err };
497
- }
498
- }
499
-
500
- return { code: SUCCESS };
501
- }
502
-
503
- /**
504
- * Validate the param object and invoke the logic to batch update entity
505
- * @param {object id array of the entity} _ids
506
- * @param {param object from user input} param_obj
507
- *
508
- */
509
- async batch_update_entity(_ids, param_obj, view) {
510
- const update_fields = view && view !== "*" ? this.meta.update_fields.filter(field => Array.isArray(field.view) ? this.contain_view(field.view, view) || field.view.includes("*") : view.includes(field.view) || field.view === "*") : this.meta.update_fields;
511
- const { obj, error_field_names } = convert_update_type(param_obj, update_fields);
512
- if (error_field_names.length > 0) {
513
- if (is_log_error()) {
514
- log_error(LOG_ENTITY, "batch_update_entity error fields:" + JSON.stringify(error_field_names));
515
- }
516
- return { code: INVALID_PARAMS, err: error_field_names };
517
- }
518
-
519
- const query = oid_queries(_ids);
520
- if (query == null) {
521
- if (is_log_error()) {
522
- log_error(LOG_ENTITY, "batch_update_entity invalid ids:" + JSON.stringify(_ids));
523
- }
524
- return { code: INVALID_PARAMS, err: ["_ids"] };
525
- }
526
-
527
- if (this.meta.ref_fields) {
528
- const { code, err } = await this.validate_ref(obj);
529
- if (err || code != SUCCESS) {
530
- if (is_log_error()) {
531
- log_error(LOG_ENTITY, "batch_update_entity validate_ref error:" + JSON.stringify(err) + ", with code:" + code);
532
- }
533
- return { code: code, err: err };
534
- }
535
- }
536
-
537
- if (this.meta.batch_update) {
538
- const { code, err } = await this.meta.batch_update(_ids, this, obj);
539
- if (err || code != SUCCESS) {
540
- if (is_log_error()) {
541
- log_error(LOG_ENTITY, "batch_update_entity batch_update error:" + JSON.stringify(err) + ", with code:" + code);
542
- }
543
- return { code: code, err: err };
544
- }
545
- } else {
546
- const result = await this.update(query, obj);
547
- if (result.ok != 1) {
548
- if (is_log_error()) {
549
- log_error(LOG_ENTITY, "batch_update_entity update record is failed with query:" + JSON.stringify(query) + ",obj:" + JSON.stringify(obj) + ",result:" + JSON.stringify(result));
550
- }
551
- return { code: ERROR, err: "batch update record is failed" };
552
- }
553
- }
554
-
555
- if (this.meta.after_batch_update) {
556
- const { code, err } = await this.meta.after_batch_update(_ids, this, obj);
557
- if (err || code != SUCCESS) {
558
- if (is_log_error()) {
559
- log_error(LOG_ENTITY, "after_batch_update error:" + JSON.stringify(err) + ", with code:" + code);
560
- }
561
- return { code: code, err: err };
562
- }
563
- }
564
-
565
- return { code: SUCCESS };
566
- }
567
-
568
- contain_view(array, view) {
569
- for (let i = 0; i < array.length; i++) {
570
- if (view.includes(array[i])) {
571
- return true;
572
- }
573
- }
574
- return false;
575
- }
576
-
577
- /**
578
- * Use objectid to read entity properties. Validate the param object and invoke the logic to read entity properties.
579
- * This method doesn't convert ref property, so all the ref properties are objectid of the ref entity.
580
- * It also donesn't inclue link property. This is used for form view to do create/update the entity.
581
- * @param {object id of the entity} _id object id of the entity
582
- * @param {attr names to retrieve} attr_names
583
- *
584
- */
585
- async read_property(_id, attr_names, view) {
586
- const query = oid_query(_id);
587
- if (query == null) {
588
- if (is_log_error()) {
589
- log_error(LOG_ENTITY, "read_property invalid id:" + _id);
590
- }
591
- return { code: INVALID_PARAMS, err: ["_id"] };
592
- }
593
-
594
- const property_fields = view && view !== "*" ? this.meta.property_fields.filter(field => Array.isArray(field.view) ? this.contain_view(field.view, view) || field.view.includes("*") : view.includes(field.view) || field.view === "*") : this.meta.property_fields;
595
- const field_names = property_fields.map(f => f.name);
596
- const attrs = { _id: 1 };
597
- attr_names.split(",").forEach((attr) => {
598
- if (field_names.includes(attr)) {
599
- attrs[attr] = 1;
600
- }
601
- });
602
-
603
- const results = await this.find(query, attrs);
604
- if (results && results.length == 1) {
605
- if (is_log_debug()) {
606
- log_debug("read_property with query:" + JSON.stringify(query) + ",attrs:" + JSON.stringify(attrs) + ",result:" + JSON.stringify(results));
607
- }
608
- return { code: SUCCESS, data: results[0] };
609
- } else {
610
- return { code: NOT_FOUND, err: ["_id"] };
611
- }
612
- }
613
-
614
- /**
615
- * Use objectid to read entity properties. Validate the param object and invoke the logic to read entity properties.
616
- * It will convert object ref attributes to ref_label property of the ref entity and also read link attributes.
617
- * @param {object id of the entity} _id object id of the entity
618
- * @param {attr names to retrieve} attr_names
619
- *
620
- */
621
- async read_entity(_id, attr_names, view) {
622
- const query = oid_query(_id);
623
- if (query == null) {
624
- if (is_log_error()) {
625
- log_error(LOG_ENTITY, "read_entity invalid id:" + _id);
626
- }
627
- return { code: INVALID_PARAMS, err: ["_id"] };
628
- }
629
-
630
- if (!attr_names) {
631
- if (is_log_error()) {
632
- log_error(LOG_ENTITY, "read_entity invalid attr_names:" + attr_names);
633
- }
634
- return { code: INVALID_PARAMS, err: ["attr_names"] };
635
- }
636
-
637
- const property_fields = view && view !== "*" ? this.meta.property_fields.filter(field => Array.isArray(field.view) ? this.contain_view(field.view, view) || field.view.includes("*") : view.includes(field.view) || field.view === "*") : this.meta.property_fields;
638
- const field_names = property_fields.map(f => f.name);
639
-
640
- const ref_fields = [];
641
- const link_fields = [];
642
- const attrs = { _id: 1 };
643
-
644
- const fields_map = this.meta.fields_map;
645
- attr_names.split(",").forEach((attr) => {
646
- if (field_names.includes(attr)) {
647
- attrs[attr] = 1;
648
- const field = fields_map[attr];
649
- if (field.link) {
650
- link_fields.push(field);
651
- attrs[field.link] = 1;
652
- } else if (field.ref) {
653
- ref_fields.push(field);
654
- }
655
- }
656
- });
657
-
658
- const results = await this.find(query, attrs);
659
- if (results && results.length == 1) {
660
- if (this.meta.after_read) {
661
- const { code, err } = await this.meta.after_read(_id, this, attr_names, results[0]);
662
- if (err || code != SUCCESS) {
663
- if (is_log_error()) {
664
- log_error(LOG_ENTITY, "after_read error:" + JSON.stringify(err) + ", with code:" + code);
665
- }
666
- return { code: code, err: err };
667
- }
668
- }
669
-
670
- const list_link = await this.read_link_attrs(results, link_fields);
671
- const converted = await this.convert_ref_attrs(list_link, ref_fields);
672
-
673
- if (converted && converted.length == 1) {
674
- if (is_log_debug()) {
675
- log_debug("read_entity with query:" + JSON.stringify(query) + ",attrs:" + JSON.stringify(attrs) + ",converted:" + JSON.stringify(converted));
676
- }
677
- return { code: SUCCESS, data: converted[0] };
678
- }
679
- }
680
-
681
- return { code: NOT_FOUND, err: ["_id"] };
682
- }
683
-
684
- /**
685
- * Delete the objects using id array
686
- * @param {array of objectid} id_array
687
- */
688
- async delete_entity(id_array) {
689
- const query = oid_queries(id_array);
690
- if (query == null) {
691
- if (is_log_error()) {
692
- log_error(LOG_ENTITY, "delete_entity invalid id_array:" + JSON.stringify(id_array));
693
- }
694
- return { code: INVALID_PARAMS, err: ["ids"] };
695
- }
696
-
697
- if (this.meta.before_delete) {
698
- const { code, err } = await this.meta.before_delete(this, id_array);
699
- if (err || code != SUCCESS) {
700
- if (is_log_error()) {
701
- log_error(LOG_ENTITY, "before_delete error:" + JSON.stringify(err) + ", with code:" + code);
702
- }
703
- return { code: code, err: err };
704
- }
705
- }
706
-
707
- if (this.meta.delete) {
708
- const { code, err } = await this.meta.delete(this, id_array);
709
- if (err || code != SUCCESS) {
710
- if (is_log_error()) {
711
- log_error(LOG_ENTITY, "delete error:" + JSON.stringify(err) + ", with code:" + code);
712
- }
713
- return { code: code, err: err };
714
- }
715
- } else {
716
- //check all the ref by array first
717
- const has_refer_by_array = await this.check_refer_entity(id_array);
718
- if (has_refer_by_array.length > 0) {
719
- const array = [...new Set(has_refer_by_array)];
720
- if (is_log_error()) {
721
- log_error(LOG_ENTITY, "has_refer_by_array:" + JSON.stringify(array));
722
- }
723
- return { code: HAS_REF, err: array };
724
- }
725
-
726
- const result = await this.delete(query);
727
- if (result.ok != 1) {
728
- if (is_log_error()) {
729
- log_error(LOG_ENTITY, "delete records is failed with query:" + JSON.stringify(query) + ", result:" + JSON.stringify(result));
730
- }
731
- return { code: ERROR, err: "delete record is failed" };
732
- }
733
- //delete other ref_by entity based on delete mode
734
- for (let i = 0; i < this.meta.ref_by_metas.length; i++) {
735
- const ref_by_meta = this.meta.ref_by_metas[i];
736
- const ref_fields = ref_by_meta.ref_fields.filter(field => field.ref == this.meta.collection);
737
- for (let j = 0; j < ref_fields.length; j++) {
738
- const ref_field = ref_fields[j];
739
- if (ref_field.delete == DELETE_MODE.cascade) {
740
- const refer_by_entity = new Entity(ref_by_meta);
741
- await refer_by_entity.delete_refer_entity(ref_field.name, id_array)
742
- }
743
- }
744
- }
745
- }
746
-
747
- if (this.meta.after_delete) {
748
- const { code, err } = await this.meta.after_delete(this, id_array);
749
- if (err || code != SUCCESS) {
750
- if (is_log_error()) {
751
- log_error(LOG_ENTITY, "after_delete error:" + JSON.stringify(err) + ", with code:" + code);
752
- }
753
- return { code: code, err: err };
754
- }
755
- }
756
-
757
- return { code: SUCCESS };
758
- }
759
-
760
- /**
761
- * Construct the primary key query object
762
- * @param {param object} param_obj
763
- * @returns
764
- */
765
- primary_key_query(param_obj) {
766
- const params = required_params(param_obj, this.meta.primary_keys);
767
- if (params === null) {
768
- return null;
769
- }
770
-
771
- const { obj, error_field_names } = convert_type(param_obj, this.meta.primary_key_fields);
772
- if (error_field_names.length > 0) {
773
- return null;
774
- }
775
-
776
- const query = {};
777
- this.meta.primary_keys.forEach(function (key) {
778
- query[key] = obj[key];
779
- });
780
- return query;
781
- }
782
-
783
- /**
784
- * Get the count value by primary key
785
- * @param {object used to create query} obj
786
- * @returns the count value by primary key
787
- */
788
- count_by_primary_keys(obj) {
789
- return this.count(this.primary_key_query(obj));
790
- }
791
-
792
- /**
793
- * Insert Object to db
794
- * @param {inserted object} obj
795
- * @returns
796
- */
797
- create(obj) {
798
- return this.db.create(this.meta.collection, obj);
799
- }
800
-
801
- /**
802
- * Update the object, upsert:true, multi:true
803
- * @param {*} query
804
- * @param {*} obj
805
- * @returns
806
- */
807
- update(query, obj) {
808
- return this.db.update(this.meta.collection, query, obj);
809
- }
810
-
811
- /**
812
- * Remove the records from mongodb
813
- * @param {query to execute delete op} query
814
- * @returns
815
- */
816
- delete(query) {
817
- return this.db.delete(this.meta.collection, query);
818
- }
819
-
820
- /**
821
- * Remove the records from mongodb
822
- * @param {*} id can be array or string
823
- * @returns
824
- */
825
- delete_by_id(id) {
826
- const query = Array.isArray(id) ? oid_queries(id) : oid_query(id);
827
- return this.db.delete(this.meta.collection, query);
828
- }
829
-
830
- /**
831
- * Find the objects that are refered by other entity
832
- * @param {ref value} value
833
- * @param {the attributes to load from db} attr
834
- * @returns array of the objects that are found
835
- */
836
- find_by_ref_value(value, attr, ref_by_entity) {
837
- let query = Array.isArray(value) ? oid_queries(value) : oid_query(value);
838
- if (query == null) {
839
- if (Array.isArray(value)) {
840
- query = { [this.meta.ref_label]: { "$in": value } };
841
- } else {
842
- if (value.includes(",")) {
843
- const values = value.split(",");
844
- query = { [this.meta.ref_label]: { "$in": values } };
845
- } else {
846
- query = { [this.meta.ref_label]: value };
847
- }
848
- }
849
- }
850
-
851
- if (this.meta.ref_filter && ref_by_entity) {
852
- if (this.meta.ref_filter[ref_by_entity]) {
853
- query = { ...query, ...this.meta.ref_filter[ref_by_entity] };
854
- } else if (this.meta.ref_filter["*"]) {
855
- query = { ...query, ...this.meta.ref_filter["*"] };
856
- }
857
- }
858
-
859
- return this.find(query, attr);
860
- }
861
-
862
- /**
863
- * Get the ref entity by the ref value
864
- * @param {field name of the ref} field_name
865
- * @param {the value of the field} value
866
- * @param {which attrs to show} attr
867
- * @returns
868
- */
869
- find_one_ref_entity(field_name, value, attr) {
870
- const fields = this.meta.fields.filter(field => field.name == field_name);
871
- if (fields.length == 1) {
872
- const field = fields[0];
873
- if (field.ref) {
874
- const ref_meta = get_entity_meta(field.ref);
875
- const ref_entity = new Entity(ref_meta);
876
- let query = oid_query(value);
877
- if (query == null) {
878
- query = { [ref_meta.ref_label]: value };
879
- }
880
- return ref_entity.find_one(query, attr);
881
-
882
- } else {
883
- throw new Error("the field:" + field_name + " is not ref field,in entity:" + this.meta.collection);
884
- }
885
- } else {
886
- throw new Error("not found the field by name:" + field_name + ",in entity:" + this.meta.collection);
887
- }
888
- }
889
-
890
- /**
891
- *
892
- * @param {the id array used to check} id_array
893
- * @returns refer by entities
894
- */
895
- async check_refer_entity(id_array) {
896
- const has_refer_by_array = [];
897
- for (let i = 0; i < this.meta.ref_by_metas.length; i++) {
898
- const ref_by_meta = this.meta.ref_by_metas[i];
899
- const refer_by_entity = new Entity(ref_by_meta);
900
- const ref_fields = ref_by_meta.ref_fields.filter(field => field.ref == this.meta.collection);
901
-
902
- for (let j = 0; j < ref_fields.length; j++) {
903
- const ref_field = ref_fields[j];
904
- if (ref_field.delete != DELETE_MODE.keep) {
905
- const attr = {};
906
- if (ref_by_meta.ref_label) {
907
- attr[ref_by_meta.ref_label] = 1;
908
- }
909
-
910
- const entities = await refer_by_entity.get_refer_entities(ref_field.name, id_array, attr);
911
- if (entities && entities.length > 0) {
912
- if (ref_field.delete == DELETE_MODE.cascade) {
913
- const ref_array = await refer_by_entity.check_refer_entity(entities.map(o => o._id + ""));
914
- if (ref_array && ref_array.length > 0) {
915
- has_refer_by_array.push(...ref_array);
916
- }
917
- } else {
918
- if (ref_by_meta.ref_label) {
919
- has_refer_by_array.push(...entities.map(o => this.meta.collection + "<-" + ref_by_meta.collection + ":" + o[ref_by_meta.ref_label]));
920
- } else {
921
- has_refer_by_array.push(...entities.map(o => this.meta.collection + "<-" + ref_by_meta.collection + ":" + o["_id"] + ""));
922
- }
923
- }
924
- }
925
- }
926
- }
927
- }
928
- return has_refer_by_array;
929
- }
930
-
931
- /**
932
- * check whether this entity has refered the entity_id value
933
- * @param {entity in this field name} field_name
934
- * @param {entity object id array} id_array
935
- * @returns true if has refered
936
- */
937
- async get_refer_entities(field_name, id_array, attr) {
938
- const query = { [field_name]: { "$in": id_array } };
939
- return await this.find(query, attr);
940
- }
941
-
942
- /**
943
- * delete refer entities
944
- * @param {entity in this field name} field_name
945
- * @param {entity object id array} id_array
946
- */
947
- async delete_refer_entity(field_name, id_array) {
948
- const entities = await this.get_refer_entities(field_name, id_array, {});
949
- await this.delete_entity(entities.map(o => o._id + ""));
950
- }
951
-
952
- /**
953
- * Convert ref element object id to ref_label
954
- * @param {element of object} elements
955
- * @param {*} passed_ref_fields, if not pass, use all meta ref_fields
956
- * @returns
957
- */
958
- async convert_ref_attrs(elements, passed_ref_fields) {
959
- const ref_fields = passed_ref_fields ? passed_ref_fields : this.meta.ref_fields;
960
- if (elements && ref_fields && ref_fields.length > 0) {
961
- for (let i = 0; i < ref_fields.length; i++) {
962
- const ref_field = ref_fields[i];
963
- let id_array = [];
964
- for (let j = 0; j < elements.length; j++) {
965
- const obj = elements[j];
966
- const value = obj[ref_field.name];
967
- if (Array.isArray(value)) {
968
- id_array = id_array.concat(value);
969
- } else if (value) {
970
- id_array.push(value);
971
- }
972
- }
973
- id_array = unique(id_array);
974
-
975
- const ref_meta = get_entity_meta(ref_field.ref);
976
- const ref_entity = new Entity(ref_meta);
977
- const ref_labels = await ref_entity.get_ref_labels(id_array);
978
- const id_key = "_id";
979
- const label_map_obj = map_array_to_obj(ref_labels, id_key, ref_meta.ref_label);
980
- for (let j = 0; j < elements.length; j++) {
981
- const obj = elements[j];
982
- const value = obj[ref_field.name];
983
- obj[ref_field.name + id_key] = value;
984
-
985
- if (Array.isArray(value)) {
986
- obj[ref_field.name] = value.map(v => label_map_obj[v]);
987
- } else if (value) {
988
- obj[ref_field.name] = label_map_obj[value];
989
- }
990
- }
991
- }
992
- }
993
- return elements;
994
- }
995
-
996
- /**
997
- * read the link attrs
998
- * @param {*} elements
999
- * @returns
1000
- */
1001
- async read_link_attrs(elements, link_fields) {
1002
- if (elements && link_fields && link_fields.length > 0) {
1003
- //key is entity name, value is array of fields
1004
- const entity_attr_map = link_fields.reduce((map, field) => {
1005
- const link_field = this.meta.fields_map[field.link];
1006
- if (map[link_field.ref]) {
1007
- map[link_field.ref].push(field.name);
1008
- } else {
1009
- map[link_field.ref] = [field.name];
1010
- }
1011
- return map;
1012
- }, {});
1013
-
1014
- //key entity, value: attr property used to query
1015
- const entity_filter_map = link_fields.reduce((map, field) => {
1016
- const link_field = this.meta.fields_map[field.link];
1017
- if (map[link_field.ref]) {
1018
- (!map[link_field.ref].includes(link_field.name)) && map[link_field.ref].push(link_field.name);
1019
- } else {
1020
- map[link_field.ref] = [link_field.name];
1021
- }
1022
- return map;
1023
- }, {});
1024
-
1025
- const entities = Object.keys(entity_filter_map);
1026
- for (let i = 0; i < entities.length; i++) {
1027
- const meta = get_entity_meta(entities[i]);
1028
- const entity = new Entity(meta);
1029
- let id_array = [];
1030
- for (let j = 0; j < elements.length; j++) {
1031
- const obj = elements[j];
1032
- const linked_attrs = entity_filter_map[entities[i]];
1033
- for (let k = 0; k < linked_attrs.length; k++) {
1034
- const id = obj[linked_attrs[k]];
1035
- id_array.push(id);
1036
- }
1037
- }
1038
- id_array = unique(id_array);
1039
- const query = oid_queries(id_array);
1040
- const attr_fields = entity_attr_map[entities[i]];
1041
- const attrs = {};
1042
- const ref_fields = [];
1043
- attr_fields.forEach((attr) => {
1044
- attrs[attr] = 1;
1045
- const field = meta.fields_map[attr];
1046
- if (!field.link && field.ref) {
1047
- ref_fields.push(field);
1048
- }
1049
- });
1050
-
1051
- const ref_entity_items = await entity.find(query, attrs);
1052
- if (ref_entity_items && ref_entity_items.length > 0) {
1053
- await entity.convert_ref_attrs(ref_entity_items, ref_fields);
1054
-
1055
- for (let j = 0; j < elements.length; j++) {
1056
- const obj = elements[j];
1057
- const linked_attrs = entity_filter_map[entities[i]];
1058
- for (let k = 0; k < linked_attrs.length; k++) {
1059
- const id = obj[linked_attrs[k]];
1060
- const [link_obj] = ref_entity_items.filter(o => o._id + "" == id);
1061
- if (link_obj) {
1062
- const copy_obj = { ...link_obj };
1063
- delete copy_obj["_id"];
1064
- elements[j] = { ...obj, ...copy_obj };
1065
- }
1066
- }
1067
- }
1068
- }
1069
- }
1070
- }
1071
- return elements;
1072
- }
1073
-
1074
- /**
1075
- * get ref labels of the object, use ref_filter
1076
- * @returns
1077
- */
1078
- get_filtered_ref_labels(ref_by_entity, client_query) {
1079
- let query = {};
1080
- if (this.meta.user_field) {
1081
- query[this.meta.user_field] = get_session_userid();
1082
- }
1083
-
1084
- const search_fields = this.meta.search_fields;
1085
- let search_query = {};
1086
- //client query: key:value, key:value
1087
- if (client_query && client_query.trim().length > 0 && search_fields && search_fields.length > 0) {
1088
- const queries = client_query.split(",");
1089
- for (let i = 0; i < queries.length; i++) {
1090
- const query_values = queries[i].split(":");
1091
- if (query_values && query_values.length == 2) {
1092
- const field_name = query_values[0];
1093
- const [search_field] = search_fields.filter(f => f.name == field_name);
1094
- search_field && (search_query = parse_search_value(field_name, search_field.type, query_values[1]))
1095
- }
1096
- }
1097
- }
1098
-
1099
- if (this.meta.ref_filter && ref_by_entity) {
1100
- if (this.meta.ref_filter[ref_by_entity]) {
1101
- query = { ...query, ...this.meta.ref_filter[ref_by_entity] };
1102
- } else if (this.meta.ref_filter["*"]) {
1103
- query = { ...query, ...this.meta.ref_filter["*"] };
1104
- }
1105
- }
1106
- return this.find_sort({ ...search_query, ...query }, { [this.meta.ref_label]: 1 }, { [this.meta.ref_label]: 1 });
1107
- }
1108
-
1109
- /**
1110
- * get ref labels of the object
1111
- * @param {id array of objectid} id_array
1112
- * @returns
1113
- */
1114
- get_ref_labels(id_array) {
1115
- const query = oid_queries(id_array);
1116
- return this.find(query, { [this.meta.ref_label]: 1 });
1117
- }
1118
-
1119
- /**
1120
- * get entity by object id
1121
- * @param {object id} id
1122
- * @param {the attributes to load from db} attr
1123
- */
1124
- find_by_oid(id, attr) {
1125
- const query = oid_query(id);
1126
- if (query == null) {
1127
- return null;
1128
- }
1129
- return this.find_one(query, attr);
1130
- }
1131
-
1132
- /**
1133
- * Search the db using query
1134
- * @param {search criteria} query
1135
- * @param {the attributes to load from db} attr
1136
- * @returns
1137
- */
1138
- find(query, attr) {
1139
- return this.db.find(this.meta.collection, query, attr);
1140
- }
1141
-
1142
- /**
1143
- * Find one record from db
1144
- * @param {search criteria} query
1145
- * @param {the attributes to load from db} attr
1146
- * @returns
1147
- */
1148
- find_one(query, attr) {
1149
- return this.db.find_one(this.meta.collection, query, attr);
1150
- }
1151
-
1152
- /**
1153
- * Find the records from db using sort to do sorting
1154
- * @param {search criteria} query
1155
- * @param {sort object to sort the result} sort
1156
- * @param {the attributes of the object to load from db} attr
1157
- * @returns
1158
- */
1159
- find_sort(query, sort, attr) {
1160
- return this.db.find_sort(this.meta.collection, query, sort, attr);
1161
- }
1162
-
1163
- /**
1164
- * Find the page records
1165
- * @param {search criteria} query
1166
- * @param {sort object to sort the results} sort
1167
- * @param {the page index to load} page
1168
- * @param {page size } limit
1169
- * @param {the attributes of the object to load from db} attr
1170
- * @returns
1171
- */
1172
- find_page(query, sort, page, limit, attr) {
1173
- return this.db.find_page(this.meta.collection, query, sort, page, limit, attr);
1174
- }
1175
-
1176
- /**
1177
- * The count number of the query
1178
- * @param {search criteria} query
1179
- * @returns
1180
- */
1181
- count(query) {
1182
- return this.db.count(this.meta.collection, query);
1183
- }
1184
-
1185
- /**
1186
- * Calculate the sum value based on the field and query criteria
1187
- * @param {search criteria} query
1188
- * @param {field name to calculate sum} field
1189
- * @returns
1190
- */
1191
- sum(query, field) {
1192
- return this.db.sum(this.meta.collection, query, field);
1193
- }
1194
-
1195
- /**
1196
- * Pull the object from array
1197
- * @param {search criteria} query
1198
- * @param {object pulled from the array} ele
1199
- * @returns
1200
- */
1201
- pull(query, ele) {
1202
- return this.db.pull(this.meta.collection, query, ele);
1203
- }
1204
-
1205
- /**
1206
- * Push the object to array
1207
- * @param {search criteria} query
1208
- * @param {object push to the array} ele
1209
- * @returns
1210
- */
1211
- push(query, ele) {
1212
- return this.db.push(this.meta.collection, query, ele);
1213
- }
1214
-
1215
- /**
1216
- * add the object to set
1217
- * @param {search criteria} query
1218
- * @param {object added to the set} ele
1219
- * @returns
1220
- */
1221
- add_to_set(query, ele) {
1222
- return this.db.add_to_set(this.meta.collection, query, ele);
1223
- };
1224
-
1225
- /**
1226
- * Get the mongodb collection with this entity
1227
- * @returns
1228
- */
1229
- col() {
1230
- return this.db.col(this.meta.collection);
1231
- };
1232
-
1233
- /**
1234
- * Add oid query to entity
1235
- * @param {object id} _id
1236
- * @returns
1237
- */
1238
- oid_query(_id) {
1239
- return oid_query(_id);
1240
- }
1241
-
1242
- /**
1243
- * Object ID array
1244
- * @param {object id array} _ids
1245
- * @returns
1246
- */
1247
- oid_queries(_ids) {
1248
- return oid_queries(_ids);
1249
- }
1250
- }
1251
-
1252
- module.exports = { Entity };