@webda/core 1.6.0-beta.3 → 2.0.0-beta.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 (210) hide show
  1. package/lib/application.d.ts +317 -195
  2. package/lib/application.js +171 -679
  3. package/lib/application.js.map +1 -1
  4. package/lib/application.spec.js +97 -289
  5. package/lib/application.spec.js.map +1 -1
  6. package/lib/core.d.ts +102 -214
  7. package/lib/core.js +145 -68
  8. package/lib/core.js.map +1 -1
  9. package/lib/core.spec.js +78 -15
  10. package/lib/core.spec.js.map +1 -1
  11. package/lib/index.d.ts +3 -0
  12. package/lib/index.js +8 -1
  13. package/lib/index.js.map +1 -1
  14. package/lib/models/aclmodel.d.ts +3 -1
  15. package/lib/models/aclmodel.js +3 -1
  16. package/lib/models/aclmodel.js.map +1 -1
  17. package/lib/models/aclmodel.spec.js +4 -1
  18. package/lib/models/aclmodel.spec.js.map +1 -1
  19. package/lib/models/coremodel.d.ts +9 -17
  20. package/lib/models/coremodel.js +36 -36
  21. package/lib/models/coremodel.js.map +1 -1
  22. package/lib/models/ident.d.ts +3 -3
  23. package/lib/models/ident.js +2 -1
  24. package/lib/models/ident.js.map +1 -1
  25. package/lib/models/ownermodel.d.ts +8 -4
  26. package/lib/models/ownermodel.js +9 -4
  27. package/lib/models/ownermodel.js.map +1 -1
  28. package/lib/models/rolemodel.js.map +1 -1
  29. package/lib/models/rolemodel.spec.js +4 -1
  30. package/lib/models/rolemodel.spec.js.map +1 -1
  31. package/lib/models/user.d.ts +4 -3
  32. package/lib/models/user.js +2 -1
  33. package/lib/models/user.js.map +1 -1
  34. package/lib/queues/filequeue.d.ts +2 -7
  35. package/lib/queues/filequeue.js +2 -11
  36. package/lib/queues/filequeue.js.map +1 -1
  37. package/lib/queues/filequeue.spec.js +0 -1
  38. package/lib/queues/filequeue.spec.js.map +1 -1
  39. package/lib/queues/memoryqueue.d.ts +2 -7
  40. package/lib/queues/memoryqueue.js +1 -11
  41. package/lib/queues/memoryqueue.js.map +1 -1
  42. package/lib/queues/queue.spec.d.ts +1 -1
  43. package/lib/queues/queue.spec.js +11 -9
  44. package/lib/queues/queue.spec.js.map +1 -1
  45. package/lib/queues/queueservice.js +1 -1
  46. package/lib/queues/queueservice.js.map +1 -1
  47. package/lib/router.d.ts +46 -1
  48. package/lib/router.js +89 -51
  49. package/lib/router.js.map +1 -1
  50. package/lib/router.spec.js +18 -1
  51. package/lib/router.spec.js.map +1 -1
  52. package/lib/services/asyncevents.d.ts +1 -0
  53. package/lib/services/asyncevents.js +4 -3
  54. package/lib/services/asyncevents.js.map +1 -1
  55. package/lib/services/authentication.d.ts +12 -4
  56. package/lib/services/authentication.js +47 -36
  57. package/lib/services/authentication.js.map +1 -1
  58. package/lib/services/authentication.spec.js +1 -0
  59. package/lib/services/authentication.spec.js.map +1 -1
  60. package/lib/services/binary.d.ts +126 -64
  61. package/lib/services/binary.js +243 -92
  62. package/lib/services/binary.js.map +1 -1
  63. package/lib/services/binary.spec.d.ts +1 -0
  64. package/lib/services/binary.spec.js +96 -25
  65. package/lib/services/binary.spec.js.map +1 -1
  66. package/lib/services/cloudbinary.d.ts +67 -0
  67. package/lib/services/cloudbinary.js +178 -0
  68. package/lib/services/cloudbinary.js.map +1 -0
  69. package/lib/services/cloudbinary.spec.d.ts +13 -0
  70. package/lib/services/cloudbinary.spec.js +205 -0
  71. package/lib/services/cloudbinary.spec.js.map +1 -0
  72. package/lib/services/configuration.d.ts +7 -2
  73. package/lib/services/configuration.js +4 -3
  74. package/lib/services/configuration.js.map +1 -1
  75. package/lib/services/configuration.spec.js +1 -0
  76. package/lib/services/configuration.spec.js.map +1 -1
  77. package/lib/services/cron.d.ts +5 -6
  78. package/lib/services/cron.js +4 -11
  79. package/lib/services/cron.js.map +1 -1
  80. package/lib/services/cron.spec.js +0 -1
  81. package/lib/services/cron.spec.js.map +1 -1
  82. package/lib/services/debugmailer.d.ts +3 -5
  83. package/lib/services/debugmailer.js +3 -11
  84. package/lib/services/debugmailer.js.map +1 -1
  85. package/lib/services/echo.d.ts +2 -6
  86. package/lib/services/echo.js +1 -11
  87. package/lib/services/echo.js.map +1 -1
  88. package/lib/services/echo.spec.js +1 -0
  89. package/lib/services/echo.spec.js.map +1 -1
  90. package/lib/services/filebinary.d.ts +36 -12
  91. package/lib/services/filebinary.js +123 -38
  92. package/lib/services/filebinary.js.map +1 -1
  93. package/lib/services/filebinary.spec.d.ts +4 -2
  94. package/lib/services/filebinary.spec.js +48 -7
  95. package/lib/services/filebinary.spec.js.map +1 -1
  96. package/lib/services/fileconfiguration.d.ts +1 -5
  97. package/lib/services/fileconfiguration.js +1 -10
  98. package/lib/services/fileconfiguration.js.map +1 -1
  99. package/lib/services/invitationservice.d.ts +2 -0
  100. package/lib/services/invitationservice.js +3 -1
  101. package/lib/services/invitationservice.js.map +1 -1
  102. package/lib/services/invitationservice.spec.js +1 -0
  103. package/lib/services/invitationservice.spec.js.map +1 -1
  104. package/lib/services/kubernetesconfiguration.d.ts +3 -5
  105. package/lib/services/kubernetesconfiguration.js +5 -12
  106. package/lib/services/kubernetesconfiguration.js.map +1 -1
  107. package/lib/services/kubernetesconfiguration.spec.js +1 -1
  108. package/lib/services/kubernetesconfiguration.spec.js.map +1 -1
  109. package/lib/services/mailer.d.ts +1 -5
  110. package/lib/services/mailer.js +1 -10
  111. package/lib/services/mailer.js.map +1 -1
  112. package/lib/services/notificationservice.d.ts +2 -0
  113. package/lib/services/notificationservice.js +2 -0
  114. package/lib/services/notificationservice.js.map +1 -1
  115. package/lib/services/oauth.d.ts +6 -4
  116. package/lib/services/oauth.js +28 -11
  117. package/lib/services/oauth.js.map +1 -1
  118. package/lib/services/oauth.spec.js.map +1 -1
  119. package/lib/services/resource.d.ts +1 -5
  120. package/lib/services/resource.js +22 -17
  121. package/lib/services/resource.js.map +1 -1
  122. package/lib/services/resource.spec.js +0 -1
  123. package/lib/services/resource.spec.js.map +1 -1
  124. package/lib/services/service.d.ts +19 -22
  125. package/lib/services/service.js +16 -22
  126. package/lib/services/service.js.map +1 -1
  127. package/lib/services/version.d.ts +2 -5
  128. package/lib/services/version.js +1 -10
  129. package/lib/services/version.js.map +1 -1
  130. package/lib/stores/aggregator.d.ts +3 -5
  131. package/lib/stores/aggregator.js +3 -10
  132. package/lib/stores/aggregator.js.map +1 -1
  133. package/lib/stores/file.d.ts +7 -8
  134. package/lib/stores/file.js +18 -18
  135. package/lib/stores/file.js.map +1 -1
  136. package/lib/stores/file.spec.js +3 -2
  137. package/lib/stores/file.spec.js.map +1 -1
  138. package/lib/stores/mapper.d.ts +1 -5
  139. package/lib/stores/mapper.js +4 -13
  140. package/lib/stores/mapper.js.map +1 -1
  141. package/lib/stores/mapper.spec.js +1 -1
  142. package/lib/stores/mapper.spec.js.map +1 -1
  143. package/lib/stores/memory.d.ts +5 -9
  144. package/lib/stores/memory.js +5 -17
  145. package/lib/stores/memory.js.map +1 -1
  146. package/lib/stores/memory.spec.d.ts +1 -0
  147. package/lib/stores/memory.spec.js +32 -0
  148. package/lib/stores/memory.spec.js.map +1 -1
  149. package/lib/stores/store.d.ts +131 -26
  150. package/lib/stores/store.js +387 -70
  151. package/lib/stores/store.js.map +1 -1
  152. package/lib/stores/store.spec.d.ts +29 -2
  153. package/lib/stores/store.spec.js +204 -31
  154. package/lib/stores/store.spec.js.map +1 -1
  155. package/lib/stores/webdaql/WebdaQLLexer.d.ts +53 -0
  156. package/lib/stores/webdaql/WebdaQLLexer.js +290 -0
  157. package/lib/stores/webdaql/WebdaQLLexer.js.map +1 -0
  158. package/lib/stores/webdaql/WebdaQLParserLexer.d.ts +53 -0
  159. package/lib/stores/webdaql/WebdaQLParserLexer.js +290 -0
  160. package/lib/stores/webdaql/WebdaQLParserLexer.js.map +1 -0
  161. package/lib/stores/webdaql/WebdaQLParserListener.d.ts +308 -0
  162. package/lib/stores/webdaql/WebdaQLParserListener.js +4 -0
  163. package/lib/stores/webdaql/WebdaQLParserListener.js.map +1 -0
  164. package/lib/stores/webdaql/WebdaQLParserParser.d.ts +301 -0
  165. package/lib/stores/webdaql/WebdaQLParserParser.js +1781 -0
  166. package/lib/stores/webdaql/WebdaQLParserParser.js.map +1 -0
  167. package/lib/stores/webdaql/WebdaQLParserVisitor.d.ts +198 -0
  168. package/lib/stores/webdaql/WebdaQLParserVisitor.js +4 -0
  169. package/lib/stores/webdaql/WebdaQLParserVisitor.js.map +1 -0
  170. package/lib/stores/webdaql/query.d.ts +300 -0
  171. package/lib/stores/webdaql/query.js +471 -0
  172. package/lib/stores/webdaql/query.js.map +1 -0
  173. package/lib/stores/webdaql/query.spec.d.ts +1 -0
  174. package/lib/stores/webdaql/query.spec.js +136 -0
  175. package/lib/stores/webdaql/query.spec.js.map +1 -0
  176. package/lib/test.d.ts +48 -1
  177. package/lib/test.js +141 -14
  178. package/lib/test.js.map +1 -1
  179. package/lib/unpackedapplication.d.ts +66 -0
  180. package/lib/unpackedapplication.js +202 -0
  181. package/lib/unpackedapplication.js.map +1 -0
  182. package/lib/utils/context.d.ts +13 -12
  183. package/lib/utils/context.js +7 -6
  184. package/lib/utils/context.js.map +1 -1
  185. package/lib/utils/cookie.d.ts +6 -3
  186. package/lib/utils/cookie.js +5 -1
  187. package/lib/utils/cookie.js.map +1 -1
  188. package/lib/utils/logger.d.ts +16 -3
  189. package/lib/utils/logger.js +16 -3
  190. package/lib/utils/logger.js.map +1 -1
  191. package/lib/utils/logger.spec.js.map +1 -1
  192. package/lib/utils/serializers.js +5 -1
  193. package/lib/utils/serializers.js.map +1 -1
  194. package/lib/utils/waiter.d.ts +1 -1
  195. package/lib/utils/waiter.js.map +1 -1
  196. package/package.json +25 -18
  197. package/test/config-file-no-reload.json +2 -1
  198. package/test/config-file-reload.json +2 -1
  199. package/test/config-kube-reload.json +2 -1
  200. package/test/config-reload.json +1 -1
  201. package/test/config.json +6 -10
  202. package/test/config.old.json +1 -1
  203. package/test/moddas/annotatedservice.js +1 -3
  204. package/test/moddas/debugmailer.js +2 -7
  205. package/test/moddas/fakeservice.js +1 -1
  206. package/test/moddas/voidstore.js +2 -4
  207. package/test/models/ident.js +1 -1
  208. package/test/models/task.js +1 -5
  209. package/webda.module.json +1124 -0
  210. package/test/config.old-default.json +0 -151
@@ -13,6 +13,7 @@ exports.Store = exports.StoreParameters = exports.UpdateConditionFailError = exp
13
13
  const core_1 = require("../core");
14
14
  const coremodel_1 = require("../models/coremodel");
15
15
  const service_1 = require("../services/service");
16
+ const query_1 = require("./webdaql/query");
16
17
  class StoreNotFoundError extends core_1.WebdaError {
17
18
  constructor(uuid, storeName) {
18
19
  super("STORE_NOTFOUND", `Item not found ${uuid} Store(${storeName})`);
@@ -30,7 +31,8 @@ exports.UpdateConditionFailError = UpdateConditionFailError;
30
31
  */
31
32
  class StoreParameters extends service_1.ServiceParameters {
32
33
  constructor(params, service) {
33
- var _a, _b;
34
+ var _a, _b, _c, _d;
35
+ var _e;
34
36
  super(params);
35
37
  (_a = this.model) !== null && _a !== void 0 ? _a : (this.model = "Webda/CoreModel");
36
38
  let expose = params.expose;
@@ -49,6 +51,7 @@ class StoreParameters extends service_1.ServiceParameters {
49
51
  if (expose) {
50
52
  expose.restrict = expose.restrict || {};
51
53
  this.expose = expose;
54
+ (_b = (_e = this.expose).queryMethod) !== null && _b !== void 0 ? _b : (_e.queryMethod = "GET");
52
55
  }
53
56
  if (params.map) {
54
57
  throw new Error("Deprecated map usage, use a MapperService");
@@ -56,7 +59,8 @@ class StoreParameters extends service_1.ServiceParameters {
56
59
  if (params.index) {
57
60
  throw new Error("Deprecated index usage, use an AggregatorService");
58
61
  }
59
- (_b = this.strict) !== null && _b !== void 0 ? _b : (this.strict = true);
62
+ (_c = this.strict) !== null && _c !== void 0 ? _c : (this.strict = true);
63
+ (_d = this.slowQueryThreshold) !== null && _d !== void 0 ? _d : (this.slowQueryThreshold = 30000);
60
64
  }
61
65
  }
62
66
  exports.StoreParameters = StoreParameters;
@@ -105,6 +109,23 @@ class Store extends service_1.Service {
105
109
  * Contain the model uuid field
106
110
  */
107
111
  this._uuidField = "uuid";
112
+ /**
113
+ * Add metrics counter
114
+ */
115
+ this.metrics = {
116
+ save: 0,
117
+ update: 0,
118
+ partialUpdate: 0,
119
+ get: 0,
120
+ increment: 0,
121
+ delete: 0,
122
+ collectionUpsert: 0,
123
+ collectionDelete: 0,
124
+ attributeDelete: 0,
125
+ query: 0,
126
+ queryDuration: 0,
127
+ slowQueries: 0
128
+ };
108
129
  }
109
130
  /**
110
131
  * Load the parameters for a service
@@ -118,13 +139,16 @@ class Store extends service_1.Service {
118
139
  * @throws Error if model is not found
119
140
  */
120
141
  computeParameters() {
142
+ var _a;
121
143
  super.computeParameters();
122
144
  const p = this.parameters;
123
145
  this._model = this._webda.getModel(p.model);
124
146
  this._uuidField = this._model.getUuidField();
125
147
  this._lastUpdateField = this._model.getLastUpdateField();
126
148
  this._creationDateField = this._model.getCreationField();
149
+ (_a = this._cacheStore) === null || _a === void 0 ? void 0 : _a.computeParameters();
127
150
  }
151
+ logSlowQuery(query, reason, time) { }
128
152
  /**
129
153
  * Return Store current model
130
154
  * @returns
@@ -135,8 +159,35 @@ class Store extends service_1.Service {
135
159
  getLastUpdateField() {
136
160
  return this._model.getLastUpdateField();
137
161
  }
162
+ /**
163
+ * Get From Cache or main
164
+ * @param uid
165
+ * @param raiseIfNotFound
166
+ * @returns
167
+ */
168
+ _getFromCache(uid, raiseIfNotFound = false) {
169
+ var _a;
170
+ return __awaiter(this, void 0, void 0, function* () {
171
+ let res = yield ((_a = this._cacheStore) === null || _a === void 0 ? void 0 : _a._get(uid));
172
+ if (!res) {
173
+ res = yield this._get(uid, raiseIfNotFound);
174
+ }
175
+ else {
176
+ res.__store = this;
177
+ }
178
+ return res;
179
+ });
180
+ }
181
+ /**
182
+ * Get object from store
183
+ * @param uid
184
+ * @returns
185
+ */
138
186
  getObject(uid) {
139
- return this._get(uid);
187
+ return __awaiter(this, void 0, void 0, function* () {
188
+ this.metrics.get++;
189
+ return this._getFromCache(uid);
190
+ });
140
191
  }
141
192
  /**
142
193
  * @inheritdoc
@@ -153,15 +204,25 @@ class Store extends service_1.Service {
153
204
  post: {
154
205
  description: `The way to create a new ${this._model.name} model`,
155
206
  summary: "Create a new " + this._model.name,
156
- model: this._model.name,
157
207
  operationId: `create${this._model.name}`,
158
208
  responses: {
159
209
  "200": {
160
- model: this._model.name
210
+ description: "Retrieve model",
211
+ content: {
212
+ "application/json": {
213
+ // schema: this._model.name
214
+ }
215
+ }
216
+ },
217
+ "400": {
218
+ description: "Object is invalid"
161
219
  },
162
- "400": "Object is invalid",
163
- "403": "You don't have permissions",
164
- "409": "Object already exists"
220
+ "403": {
221
+ description: "You don't have permissions"
222
+ },
223
+ "409": {
224
+ description: "Object already exists"
225
+ }
165
226
  }
166
227
  }
167
228
  });
@@ -175,6 +236,33 @@ class Store extends service_1.Service {
175
236
  if (!expose.restrict.get) {
176
237
  methods.push("GET");
177
238
  }
239
+ // Query endpoint
240
+ if (!expose.restrict.query) {
241
+ this.addRoute(expose.queryMethod === "GET" ? `${expose.url}{?q}` : expose.url, [expose.queryMethod], this.httpQuery, {
242
+ model: this._model.name,
243
+ [expose.queryMethod.toLowerCase()]: {
244
+ description: `Query on ${this._model.name} model with WebdaQL`,
245
+ summary: "Query " + this._model.name,
246
+ operationId: `create${this._model.name}`,
247
+ responses: {
248
+ "200": {
249
+ description: "Retrieve models",
250
+ content: {
251
+ "application/json": {
252
+ // schema: this._model.name
253
+ }
254
+ }
255
+ },
256
+ "400": {
257
+ description: "Query is invalid"
258
+ },
259
+ "403": {
260
+ description: "You don't have permissions"
261
+ }
262
+ }
263
+ }
264
+ });
265
+ }
178
266
  if (!expose.restrict.delete) {
179
267
  methods.push("DELETE");
180
268
  }
@@ -187,48 +275,71 @@ class Store extends service_1.Service {
187
275
  operationId: `get${this._model.name}`,
188
276
  responses: {
189
277
  "200": {
190
- model: this._model.name
278
+ //model: this._model.name
279
+ },
280
+ "400": {
281
+ description: "Object is invalid"
191
282
  },
192
- "400": "Object is invalid",
193
- "403": "You don't have permissions",
194
- "404": "Unknown object"
283
+ "403": {
284
+ description: "You don't have permissions"
285
+ },
286
+ "404": {
287
+ description: "Unknown object"
288
+ }
195
289
  }
196
290
  },
197
291
  put: {
198
292
  description: `Update a ${this._model.name} if the permissions allow`,
199
293
  summary: "Update a " + this._model.name,
200
- model: this._model.name,
201
294
  operationId: `updatet${this._model.name}`,
202
295
  responses: {
203
296
  "200": {
204
- model: this._model.name
297
+ // model: this._model.name
298
+ },
299
+ "400": {
300
+ description: "Object is invalid"
205
301
  },
206
- "400": "Object is invalid",
207
- "403": "You don't have permissions",
208
- "404": "Unknown object"
302
+ "403": {
303
+ description: "You don't have permissions"
304
+ },
305
+ "404": {
306
+ description: "Unknown object"
307
+ }
209
308
  }
210
309
  },
211
310
  patch: {
212
311
  description: `Patch a ${this._model.name} if the permissions allow`,
213
312
  summary: "Patch a " + this._model.name,
214
- model: this._model.name,
215
313
  operationId: `updatet${this._model.name}`,
216
314
  responses: {
217
- "204": "",
218
- "400": "Object is invalid",
219
- "403": "You don't have permissions",
220
- "404": "Unknown object"
315
+ "204": {
316
+ description: ""
317
+ },
318
+ "400": {
319
+ description: "Object is invalid"
320
+ },
321
+ "403": {
322
+ description: "You don't have permissions"
323
+ },
324
+ "404": {
325
+ description: "Unknown object"
326
+ }
221
327
  }
222
328
  },
223
329
  delete: {
224
330
  operationId: `delete${this._model.name}`,
225
331
  description: `Delete ${this._model.name} if the permissions allow`,
226
332
  summary: "Delete a " + this._model.name,
227
- model: this._model.name,
228
333
  responses: {
229
- "204": "",
230
- "403": "You don't have permissions",
231
- "404": "Unknown object"
334
+ "204": {
335
+ description: ""
336
+ },
337
+ "403": {
338
+ description: "You don't have permissions"
339
+ },
340
+ "404": {
341
+ description: "Unknown object"
342
+ }
232
343
  }
233
344
  }
234
345
  });
@@ -260,6 +371,16 @@ class Store extends service_1.Service {
260
371
  });
261
372
  }
262
373
  }
374
+ /**
375
+ * OVerwrite the model
376
+ * Used mainly in test
377
+ */
378
+ setModel(model) {
379
+ var _a;
380
+ this._model = model;
381
+ (_a = this._cacheStore) === null || _a === void 0 ? void 0 : _a.setModel(model);
382
+ this.parameters.strict = false;
383
+ }
263
384
  /**
264
385
  * Get the url where the store is exposed
265
386
  */
@@ -311,13 +432,16 @@ class Store extends service_1.Service {
311
432
  });
312
433
  }
313
434
  incrementAttribute(uid, prop, value) {
435
+ var _a;
314
436
  return __awaiter(this, void 0, void 0, function* () {
315
437
  // If value === 0 no need to update anything
316
438
  if (value === 0) {
317
439
  return Promise.resolve();
318
440
  }
319
441
  let updateDate = new Date();
442
+ this.metrics.increment++;
320
443
  yield this._incrementAttribute(uid, prop, value, updateDate);
444
+ yield ((_a = this._cacheStore) === null || _a === void 0 ? void 0 : _a._incrementAttribute(uid, prop, value, updateDate));
321
445
  return this.emitSync("Store.PartialUpdated", {
322
446
  object_id: uid,
323
447
  store: this,
@@ -332,12 +456,15 @@ class Store extends service_1.Service {
332
456
  });
333
457
  }
334
458
  upsertItemToCollection(uid, prop, item, index = undefined, itemWriteCondition = undefined, itemWriteConditionField = undefined) {
459
+ var _a;
335
460
  return __awaiter(this, void 0, void 0, function* () {
336
461
  if (itemWriteConditionField === undefined) {
337
462
  itemWriteConditionField = this._uuidField;
338
463
  }
339
464
  let updateDate = new Date();
465
+ this.metrics.collectionUpsert++;
340
466
  yield this._upsertItemToCollection(uid, prop, item, index, itemWriteCondition, itemWriteConditionField, updateDate);
467
+ yield ((_a = this._cacheStore) === null || _a === void 0 ? void 0 : _a._upsertItemToCollection(uid, prop, item, index, itemWriteCondition, itemWriteConditionField, updateDate));
341
468
  yield this.emitSync("Store.PartialUpdated", {
342
469
  object_id: uid,
343
470
  store: this,
@@ -353,9 +480,12 @@ class Store extends service_1.Service {
353
480
  });
354
481
  }
355
482
  deleteItemFromCollection(uid, prop, index, itemWriteCondition, itemWriteConditionField = this._uuidField) {
483
+ var _a;
356
484
  return __awaiter(this, void 0, void 0, function* () {
357
485
  let updateDate = new Date();
486
+ this.metrics.collectionDelete++;
358
487
  yield this._deleteItemFromCollection(uid, prop, index, itemWriteCondition, itemWriteConditionField, updateDate);
488
+ yield ((_a = this._cacheStore) === null || _a === void 0 ? void 0 : _a._deleteItemFromCollection(uid, prop, index, itemWriteCondition, itemWriteConditionField, updateDate));
359
489
  yield this.emitSync("Store.PartialUpdated", {
360
490
  object_id: uid,
361
491
  store: this,
@@ -369,6 +499,125 @@ class Store extends service_1.Service {
369
499
  });
370
500
  });
371
501
  }
502
+ /**
503
+ * Query store with WebdaQL
504
+ * @param query
505
+ * @param context to apply permission
506
+ */
507
+ query(query, context) {
508
+ return __awaiter(this, void 0, void 0, function* () {
509
+ let queryValidator = new query_1.WebdaQL.QueryValidator(query);
510
+ let offset = queryValidator.getOffset();
511
+ const limit = queryValidator.getLimit();
512
+ const parsedQuery = queryValidator.getQuery();
513
+ // Emit the default event
514
+ yield this.emitSync("Store.Query", {
515
+ query,
516
+ parsedQuery,
517
+ store: this
518
+ });
519
+ const result = {
520
+ results: [],
521
+ continuationToken: undefined
522
+ };
523
+ /*
524
+ Offset are split in two with _
525
+
526
+ MainOffset is the database offset, retrieving a page from the database
527
+ SubOffset is the offset within the page
528
+
529
+ As we filter through the page, for additional filters or permissions, the page cut
530
+ by database does not endup being our final page cut, so we need a page offset to
531
+ abstract this completely
532
+ */
533
+ let [mainOffset, subOffset] = offset.split("_");
534
+ let secondOffset = parseInt(subOffset || "0");
535
+ let duration = Date.now();
536
+ this.metrics.query++;
537
+ while (result.results.length < limit) {
538
+ let tmpResults = yield this.find(Object.assign(Object.assign({}, parsedQuery), { continuationToken: mainOffset }));
539
+ // If no filter is returned assume it is by mistake and apply filtering
540
+ if (tmpResults.filter === undefined) {
541
+ tmpResults.filter = queryValidator.getExpression();
542
+ this.log("WARN", `Store '${this.getName()}' postquery full filtering`);
543
+ }
544
+ let subOffsetCount = 0;
545
+ for (let item of tmpResults.results) {
546
+ // Because of dynamic filter and permission we need to suboffset the pagination
547
+ subOffsetCount++;
548
+ if (subOffsetCount <= secondOffset) {
549
+ continue;
550
+ }
551
+ if (tmpResults.filter !== true && !tmpResults.filter.eval(item)) {
552
+ continue;
553
+ }
554
+ if (context) {
555
+ try {
556
+ yield item.canAct(context, "get");
557
+ }
558
+ catch (err) {
559
+ continue;
560
+ }
561
+ }
562
+ result.results.push(item);
563
+ if (result.results.length >= limit) {
564
+ if (subOffsetCount === tmpResults.results.length) {
565
+ result.continuationToken = tmpResults.continuationToken;
566
+ }
567
+ else {
568
+ result.continuationToken = `${mainOffset}_${subOffsetCount}`;
569
+ }
570
+ break;
571
+ }
572
+ }
573
+ // Update both offset
574
+ mainOffset = tmpResults.continuationToken;
575
+ // Fresh new query so we do not need to skip
576
+ secondOffset = 0;
577
+ if (mainOffset === undefined || result.results.length >= limit) {
578
+ break;
579
+ }
580
+ }
581
+ duration = Date.now() - duration;
582
+ this.metrics.queryDuration =
583
+ (this.metrics.queryDuration * (this.metrics.query - 1) + duration) / this.metrics.query;
584
+ if (duration > this.parameters.slowQueryThreshold) {
585
+ this.logSlowQuery(query, "", duration);
586
+ }
587
+ yield this.emitSync("Store.Queried", {
588
+ query,
589
+ parsedQuery: parsedQuery,
590
+ store: this,
591
+ continuationToken: result.continuationToken,
592
+ results: result.results
593
+ });
594
+ return result;
595
+ });
596
+ }
597
+ /**
598
+ * Expose query to http
599
+ */
600
+ httpQuery(ctx) {
601
+ return __awaiter(this, void 0, void 0, function* () {
602
+ let query;
603
+ if (ctx.getHttpContext().getMethod() === "GET") {
604
+ query = ctx.getParameters().q;
605
+ }
606
+ else {
607
+ query = ctx.getRequestBody().q;
608
+ }
609
+ try {
610
+ ctx.write(yield this.query(query, ctx));
611
+ }
612
+ catch (err) {
613
+ if (err instanceof SyntaxError) {
614
+ this.log("INFO", "Query syntax error");
615
+ throw 400;
616
+ }
617
+ throw err;
618
+ }
619
+ });
620
+ }
372
621
  /**
373
622
  * Save an object
374
623
  *
@@ -379,12 +628,12 @@ class Store extends service_1.Service {
379
628
  * Might want to rename to create
380
629
  */
381
630
  save(object, ctx = undefined) {
382
- var _a;
383
- var _b;
631
+ var _a, _b;
632
+ var _c;
384
633
  return __awaiter(this, void 0, void 0, function* () {
385
634
  object = this.initModel(object);
386
635
  // Dates should be store by the Store
387
- (_a = object[_b = this._creationDateField]) !== null && _a !== void 0 ? _a : (object[_b] = new Date());
636
+ (_a = object[_c = this._creationDateField]) !== null && _a !== void 0 ? _a : (object[_c] = new Date());
388
637
  object[this._lastUpdateField] = new Date();
389
638
  if (ctx) {
390
639
  object.setContext(ctx);
@@ -395,7 +644,9 @@ class Store extends service_1.Service {
395
644
  });
396
645
  // Handle object auto listener
397
646
  yield object._onSave();
647
+ this.metrics.save++;
398
648
  let res = yield this._save(object);
649
+ yield ((_b = this._cacheStore) === null || _b === void 0 ? void 0 : _b._save(object));
399
650
  object = this.initModel(res);
400
651
  yield this.emitSync("Store.Saved", {
401
652
  object: object,
@@ -489,6 +740,7 @@ class Store extends service_1.Service {
489
740
  * @return {Promise} with saved object
490
741
  */
491
742
  update(object, reverseMap = true, partial = false) {
743
+ var _a, _b;
492
744
  return __awaiter(this, void 0, void 0, function* () {
493
745
  /** @ignore */
494
746
  var saved;
@@ -501,12 +753,12 @@ class Store extends service_1.Service {
501
753
  }
502
754
  }
503
755
  }
504
- let partialEvent = partial ? "Patch" : "";
505
756
  if (Object.keys(object).length < 2) {
506
757
  return {};
507
758
  }
508
759
  object[this._lastUpdateField] = new Date();
509
- let load = yield this._get(object[this._uuidField], true);
760
+ this.metrics.get++;
761
+ let load = yield this._getFromCache(object[this._uuidField], true);
510
762
  if (load.__type !== this._model.name && this.parameters.strict) {
511
763
  this.log("WARN", `Object '${object[this._uuidField]}' was not created by this store`);
512
764
  throw new StoreNotFoundError(object[this._uuidField], this.getName());
@@ -515,15 +767,26 @@ class Store extends service_1.Service {
515
767
  if (object instanceof coremodel_1.CoreModel) {
516
768
  loaded.setContext(object.getContext());
517
769
  }
518
- yield this.emitSync(`Store.${partialEvent}Update`, {
519
- object: loaded,
520
- store: this,
521
- update: object
522
- });
770
+ if (partial) {
771
+ yield this.emitSync(`Store.PatchUpdate`, {
772
+ object: loaded,
773
+ store: this,
774
+ update: object
775
+ });
776
+ }
777
+ else {
778
+ yield this.emitSync(`Store.Update`, {
779
+ object: loaded,
780
+ store: this,
781
+ update: object
782
+ });
783
+ }
523
784
  yield loaded._onUpdate(object);
524
785
  let res;
525
786
  if (partial) {
787
+ this.metrics.partialUpdate++;
526
788
  yield this._patch(object, object[this._uuidField], load[this._lastUpdateField], this._lastUpdateField);
789
+ yield ((_a = this._cacheStore) === null || _a === void 0 ? void 0 : _a._patch(object, object[this._uuidField], load[this._lastUpdateField], this._lastUpdateField));
527
790
  res = object;
528
791
  }
529
792
  else {
@@ -531,7 +794,9 @@ class Store extends service_1.Service {
531
794
  for (let i in this._reverseMap) {
532
795
  object[this._reverseMap[i].property] = loaded[this._reverseMap[i].property];
533
796
  }
797
+ this.metrics.update++;
534
798
  res = yield this._update(object, object[this._uuidField], load[this._lastUpdateField], this._lastUpdateField);
799
+ yield ((_b = this._cacheStore) === null || _b === void 0 ? void 0 : _b._update(object, object[this._uuidField], load[this._lastUpdateField], this._lastUpdateField));
535
800
  }
536
801
  // Return updated
537
802
  for (let i in res) {
@@ -541,10 +806,18 @@ class Store extends service_1.Service {
541
806
  loaded[i] = object[i];
542
807
  }
543
808
  saved = this.initModel(loaded);
544
- yield this.emitSync(`Store.${partialEvent}Updated`, {
545
- object: saved,
546
- store: this
547
- });
809
+ if (partial) {
810
+ yield this.emitSync(`Store.PatchUpdated`, {
811
+ object: saved,
812
+ store: this
813
+ });
814
+ }
815
+ else {
816
+ yield this.emitSync(`Store.Updated`, {
817
+ object: saved,
818
+ store: this
819
+ });
820
+ }
548
821
  yield saved._onUpdated();
549
822
  return saved;
550
823
  });
@@ -557,8 +830,11 @@ class Store extends service_1.Service {
557
830
  * @returns
558
831
  */
559
832
  removeAttribute(uuid, attribute, itemWriteCondition, itemWriteConditionField) {
833
+ var _a;
560
834
  return __awaiter(this, void 0, void 0, function* () {
835
+ this.metrics.attributeDelete++;
561
836
  yield this._removeAttribute(uuid, attribute, itemWriteCondition, itemWriteConditionField);
837
+ yield ((_a = this._cacheStore) === null || _a === void 0 ? void 0 : _a._removeAttribute(uuid, attribute, itemWriteCondition, itemWriteConditionField));
562
838
  yield this.emitSync("Store.PartialUpdated", {
563
839
  object_id: uuid,
564
840
  partial_update: {
@@ -574,7 +850,7 @@ class Store extends service_1.Service {
574
850
  * @param uuid
575
851
  * @returns
576
852
  */
577
- cascadeDelete(obj, uuid) {
853
+ cascadeDelete(obj, _uuid) {
578
854
  return __awaiter(this, void 0, void 0, function* () {
579
855
  // We dont need uuid but Binary store will need it
580
856
  return this.delete(obj.getUuid());
@@ -598,6 +874,7 @@ class Store extends service_1.Service {
598
874
  * @return {Promise} the deletion promise
599
875
  */
600
876
  delete(uid, writeCondition, writeConditionField, sync = false) {
877
+ var _a, _b;
601
878
  return __awaiter(this, void 0, void 0, function* () {
602
879
  /** @ignore */
603
880
  let to_delete;
@@ -606,7 +883,8 @@ class Store extends service_1.Service {
606
883
  to_delete = uid;
607
884
  }
608
885
  else {
609
- to_delete = yield this._get(uid);
886
+ this.metrics.get++;
887
+ to_delete = yield this._getFromCache(uid);
610
888
  if (to_delete === undefined) {
611
889
  return;
612
890
  }
@@ -630,13 +908,19 @@ class Store extends service_1.Service {
630
908
  yield to_delete._onDelete();
631
909
  // If async we just tag the object as deleted
632
910
  if (this.parameters.asyncDelete && !sync) {
911
+ this.metrics.partialUpdate++;
633
912
  yield this._patch({
634
913
  __deleted: true
635
914
  }, to_delete.getUuid());
915
+ yield ((_a = this._cacheStore) === null || _a === void 0 ? void 0 : _a._patch({
916
+ __deleted: true
917
+ }, to_delete.getUuid()));
636
918
  }
637
919
  else {
920
+ this.metrics.delete++;
638
921
  // Delete from the DB for real
639
922
  yield this._delete(to_delete.getUuid(), writeCondition, writeConditionField);
923
+ yield ((_b = this._cacheStore) === null || _b === void 0 ? void 0 : _b._delete(to_delete.getUuid(), writeCondition, writeConditionField));
640
924
  }
641
925
  // Send post event
642
926
  yield this.emitSync("Store.Deleted", {
@@ -652,7 +936,7 @@ class Store extends service_1.Service {
652
936
  * @param id
653
937
  * @param callback
654
938
  */
655
- canTriggerConfiguration(id, callback) {
939
+ canTriggerConfiguration(_id, _callback) {
656
940
  return false;
657
941
  }
658
942
  /**
@@ -662,7 +946,8 @@ class Store extends service_1.Service {
662
946
  */
663
947
  getConfiguration(id) {
664
948
  return __awaiter(this, void 0, void 0, function* () {
665
- let object = yield this._get(id);
949
+ this.metrics.get++;
950
+ let object = yield this._getFromCache(id);
666
951
  if (!object) {
667
952
  return undefined;
668
953
  }
@@ -688,7 +973,8 @@ class Store extends service_1.Service {
688
973
  if (!uid) {
689
974
  return undefined;
690
975
  }
691
- let object = yield this._get(uid);
976
+ this.metrics.get++;
977
+ let object = yield this._getFromCache(uid);
692
978
  if (!object) {
693
979
  return undefined;
694
980
  }
@@ -725,31 +1011,62 @@ class Store extends service_1.Service {
725
1011
  });
726
1012
  }
727
1013
  /**
728
- * Search inside the store
729
- *
730
- * Still need to define a good abstraction for it
731
- *
732
- * @param request
733
- * @param offset
734
- * @param limit
735
- * @returns
1014
+ * @override
736
1015
  */
737
- find(request = undefined, offset = 0, limit = undefined) {
1016
+ simulateFind(query, uuids) {
738
1017
  return __awaiter(this, void 0, void 0, function* () {
739
- yield this.emitSync("Store.Find", {
740
- request: request,
741
- store: this,
742
- offset: offset,
743
- limit: limit
744
- });
745
- let result = yield this._find(request, offset, limit);
746
- yield this.emitSync("Store.Found", {
747
- request: request,
748
- store: this,
749
- offset: offset,
750
- limit: limit,
751
- results: result
752
- });
1018
+ let result = {
1019
+ results: [],
1020
+ continuationToken: undefined,
1021
+ filter: true
1022
+ };
1023
+ let count = 0;
1024
+ let limit = query.limit;
1025
+ let offset = parseInt(query.continuationToken || "0");
1026
+ let originalOffset = offset;
1027
+ if (query.orderBy && query.orderBy.length) {
1028
+ offset = 0;
1029
+ limit = Number.MAX_SAFE_INTEGER;
1030
+ }
1031
+ // Need to transfert to Array
1032
+ for (let uuid of uuids) {
1033
+ count++;
1034
+ // Offset start
1035
+ if (offset >= count) {
1036
+ continue;
1037
+ }
1038
+ let obj = yield this._getFromCache(uuid);
1039
+ if (obj && query.filter.eval(obj)) {
1040
+ result.results.push(obj);
1041
+ if (result.results.length >= limit) {
1042
+ result.continuationToken = count.toString();
1043
+ return result;
1044
+ }
1045
+ }
1046
+ }
1047
+ if (query.orderBy && query.orderBy.length) {
1048
+ result.results = result.results
1049
+ .sort((a, b) => {
1050
+ let valA, valB;
1051
+ for (let orderBy of query.orderBy) {
1052
+ let invert = orderBy.direction === "ASC" ? 1 : -1;
1053
+ valA = query_1.WebdaQL.ComparisonExpression.getAttributeValue(a, orderBy.field.split("."));
1054
+ valB = query_1.WebdaQL.ComparisonExpression.getAttributeValue(b, orderBy.field.split("."));
1055
+ if (valA === valB) {
1056
+ continue;
1057
+ }
1058
+ if (typeof valA === "string") {
1059
+ return valA.localeCompare(valB) * invert;
1060
+ }
1061
+ return (valA < valB ? -1 : 1) * invert;
1062
+ }
1063
+ return -1;
1064
+ })
1065
+ .slice(originalOffset, query.limit + originalOffset);
1066
+ if (result.results.length >= query.limit) {
1067
+ result.continuationToken = (query.limit + originalOffset).toString();
1068
+ }
1069
+ }
753
1070
  return result;
754
1071
  });
755
1072
  }
@@ -766,7 +1083,7 @@ class Store extends service_1.Service {
766
1083
  object[this._creationDateField] = new Date();
767
1084
  yield object.canAct(ctx, "create");
768
1085
  try {
769
- yield object.validate(ctx);
1086
+ yield object.validate(ctx, body);
770
1087
  }
771
1088
  catch (err) {
772
1089
  this.log("INFO", "Object is not valid", err);
@@ -884,7 +1201,7 @@ class Store extends service_1.Service {
884
1201
  updateObject[i] = object[i];
885
1202
  });
886
1203
  try {
887
- yield updateObject.validate(ctx);
1204
+ yield updateObject.validate(ctx, body);
888
1205
  }
889
1206
  catch (err) {
890
1207
  this.log("INFO", "Object invalid", err);