@webda/core 2.0.0-beta.3 → 2.1.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 (276) hide show
  1. package/lib/application.d.ts +5 -5
  2. package/lib/application.js +71 -84
  3. package/lib/application.js.map +1 -1
  4. package/lib/application.spec.js +121 -140
  5. package/lib/application.spec.js.map +1 -1
  6. package/lib/core.d.ts +21 -25
  7. package/lib/core.js +233 -320
  8. package/lib/core.js.map +1 -1
  9. package/lib/core.spec.js +334 -406
  10. package/lib/core.spec.js.map +1 -1
  11. package/lib/index.d.ts +49 -48
  12. package/lib/index.js +53 -70
  13. package/lib/index.js.map +1 -1
  14. package/lib/models/aclmodel.d.ts +2 -2
  15. package/lib/models/aclmodel.js +63 -90
  16. package/lib/models/aclmodel.js.map +1 -1
  17. package/lib/models/aclmodel.spec.js +128 -152
  18. package/lib/models/aclmodel.spec.js.map +1 -1
  19. package/lib/models/coremodel.d.ts +33 -14
  20. package/lib/models/coremodel.js +160 -117
  21. package/lib/models/coremodel.js.map +1 -1
  22. package/lib/models/coremodel.spec.js +143 -107
  23. package/lib/models/coremodel.spec.js.map +1 -1
  24. package/lib/models/deployment.js +1 -2
  25. package/lib/models/ident.d.ts +3 -3
  26. package/lib/models/ident.js +4 -9
  27. package/lib/models/ident.js.map +1 -1
  28. package/lib/models/ident.spec.js +9 -11
  29. package/lib/models/ident.spec.js.map +1 -1
  30. package/lib/models/ownermodel.d.ts +2 -2
  31. package/lib/models/ownermodel.js +39 -62
  32. package/lib/models/ownermodel.js.map +1 -1
  33. package/lib/models/ownermodel.spec.js +126 -168
  34. package/lib/models/ownermodel.spec.js.map +1 -1
  35. package/lib/models/rolemodel.d.ts +1 -1
  36. package/lib/models/rolemodel.js +24 -40
  37. package/lib/models/rolemodel.js.map +1 -1
  38. package/lib/models/rolemodel.spec.js +44 -63
  39. package/lib/models/rolemodel.spec.js.map +1 -1
  40. package/lib/models/user.d.ts +9 -9
  41. package/lib/models/user.js +3 -8
  42. package/lib/models/user.js.map +1 -1
  43. package/lib/models/user.spec.js +14 -16
  44. package/lib/models/user.spec.js.map +1 -1
  45. package/lib/queues/filequeue.d.ts +2 -2
  46. package/lib/queues/filequeue.js +72 -93
  47. package/lib/queues/filequeue.js.map +1 -1
  48. package/lib/queues/filequeue.spec.js +53 -70
  49. package/lib/queues/filequeue.spec.js.map +1 -1
  50. package/lib/queues/memoryqueue.d.ts +2 -2
  51. package/lib/queues/memoryqueue.js +37 -61
  52. package/lib/queues/memoryqueue.js.map +1 -1
  53. package/lib/queues/memoryqueue.spec.js +142 -165
  54. package/lib/queues/memoryqueue.spec.js.map +1 -1
  55. package/lib/queues/pubsubservice.d.ts +2 -2
  56. package/lib/queues/pubsubservice.js +3 -7
  57. package/lib/queues/pubsubservice.js.map +1 -1
  58. package/lib/queues/queue.spec.d.ts +1 -1
  59. package/lib/queues/queue.spec.js +42 -56
  60. package/lib/queues/queue.spec.js.map +1 -1
  61. package/lib/queues/queueservice.d.ts +3 -3
  62. package/lib/queues/queueservice.js +51 -67
  63. package/lib/queues/queueservice.js.map +1 -1
  64. package/lib/router.d.ts +3 -3
  65. package/lib/router.js +46 -47
  66. package/lib/router.js.map +1 -1
  67. package/lib/router.spec.js +64 -61
  68. package/lib/router.spec.js.map +1 -1
  69. package/lib/services/asyncevents.d.ts +2 -2
  70. package/lib/services/asyncevents.js +44 -64
  71. package/lib/services/asyncevents.js.map +1 -1
  72. package/lib/services/asyncevents.spec.js +81 -98
  73. package/lib/services/asyncevents.spec.js.map +1 -1
  74. package/lib/services/authentication.d.ts +23 -13
  75. package/lib/services/authentication.js +540 -566
  76. package/lib/services/authentication.js.map +1 -1
  77. package/lib/services/authentication.spec.js +411 -447
  78. package/lib/services/authentication.spec.js.map +1 -1
  79. package/lib/services/binary.d.ts +8 -6
  80. package/lib/services/binary.js +212 -245
  81. package/lib/services/binary.js.map +1 -1
  82. package/lib/services/binary.spec.d.ts +3 -3
  83. package/lib/services/binary.spec.js +390 -443
  84. package/lib/services/binary.spec.js.map +1 -1
  85. package/lib/services/cloudbinary.d.ts +3 -3
  86. package/lib/services/cloudbinary.js +45 -70
  87. package/lib/services/cloudbinary.js.map +1 -1
  88. package/lib/services/cloudbinary.spec.d.ts +3 -3
  89. package/lib/services/cloudbinary.spec.js +133 -162
  90. package/lib/services/cloudbinary.spec.js.map +1 -1
  91. package/lib/services/configuration.d.ts +1 -1
  92. package/lib/services/configuration.js +78 -105
  93. package/lib/services/configuration.js.map +1 -1
  94. package/lib/services/configuration.spec.js +63 -83
  95. package/lib/services/configuration.spec.js.map +1 -1
  96. package/lib/services/cron.d.ts +3 -2
  97. package/lib/services/cron.js +9 -13
  98. package/lib/services/cron.js.map +1 -1
  99. package/lib/services/cron.spec.js +18 -21
  100. package/lib/services/cron.spec.js.map +1 -1
  101. package/lib/services/cryptoservice.d.ts +9 -4
  102. package/lib/services/cryptoservice.js +187 -221
  103. package/lib/services/cryptoservice.js.map +1 -1
  104. package/lib/services/cryptoservice.spec.js +88 -115
  105. package/lib/services/cryptoservice.spec.js.map +1 -1
  106. package/lib/services/debugmailer.d.ts +1 -1
  107. package/lib/services/debugmailer.js +13 -34
  108. package/lib/services/debugmailer.js.map +1 -1
  109. package/lib/services/debugmailer.spec.js +16 -29
  110. package/lib/services/debugmailer.spec.js.map +1 -1
  111. package/lib/services/echo.d.ts +2 -2
  112. package/lib/services/echo.js +15 -31
  113. package/lib/services/echo.js.map +1 -1
  114. package/lib/services/echo.spec.js +27 -40
  115. package/lib/services/echo.spec.js.map +1 -1
  116. package/lib/services/filebinary.d.ts +5 -5
  117. package/lib/services/filebinary.js +165 -210
  118. package/lib/services/filebinary.js.map +1 -1
  119. package/lib/services/filebinary.spec.d.ts +2 -1
  120. package/lib/services/filebinary.spec.js +106 -116
  121. package/lib/services/filebinary.spec.js.map +1 -1
  122. package/lib/services/fileconfiguration.d.ts +1 -1
  123. package/lib/services/fileconfiguration.js +25 -44
  124. package/lib/services/fileconfiguration.js.map +1 -1
  125. package/lib/services/fileconfiguration.spec.js +79 -109
  126. package/lib/services/fileconfiguration.spec.js.map +1 -1
  127. package/lib/services/invitationservice.d.ts +8 -8
  128. package/lib/services/invitationservice.js +274 -314
  129. package/lib/services/invitationservice.js.map +1 -1
  130. package/lib/services/invitationservice.spec.js +443 -449
  131. package/lib/services/invitationservice.spec.js.map +1 -1
  132. package/lib/services/kubernetesconfiguration.d.ts +1 -1
  133. package/lib/services/kubernetesconfiguration.js +41 -60
  134. package/lib/services/kubernetesconfiguration.js.map +1 -1
  135. package/lib/services/kubernetesconfiguration.spec.js +80 -98
  136. package/lib/services/kubernetesconfiguration.spec.js.map +1 -1
  137. package/lib/services/mailer.d.ts +4 -4
  138. package/lib/services/mailer.js +62 -86
  139. package/lib/services/mailer.js.map +1 -1
  140. package/lib/services/mailer.spec.js +86 -127
  141. package/lib/services/mailer.spec.js.map +1 -1
  142. package/lib/services/notificationservice.d.ts +3 -3
  143. package/lib/services/notificationservice.js +21 -42
  144. package/lib/services/notificationservice.js.map +1 -1
  145. package/lib/services/notificationservice.spec.js +47 -73
  146. package/lib/services/notificationservice.spec.js.map +1 -1
  147. package/lib/services/oauth.d.ts +4 -4
  148. package/lib/services/oauth.js +68 -83
  149. package/lib/services/oauth.js.map +1 -1
  150. package/lib/services/oauth.spec.js +130 -156
  151. package/lib/services/oauth.spec.js.map +1 -1
  152. package/lib/services/proxy.d.ts +2 -6
  153. package/lib/services/proxy.js +45 -58
  154. package/lib/services/proxy.js.map +1 -1
  155. package/lib/services/proxy.spec.js +34 -53
  156. package/lib/services/proxy.spec.js.map +1 -1
  157. package/lib/services/resource.d.ts +2 -2
  158. package/lib/services/resource.js +12 -18
  159. package/lib/services/resource.js.map +1 -1
  160. package/lib/services/resource.spec.js +67 -99
  161. package/lib/services/resource.spec.js.map +1 -1
  162. package/lib/services/service.d.ts +26 -3
  163. package/lib/services/service.js +68 -40
  164. package/lib/services/service.js.map +1 -1
  165. package/lib/services/service.spec.js +62 -67
  166. package/lib/services/service.spec.js.map +1 -1
  167. package/lib/services/version.d.ts +1 -1
  168. package/lib/services/version.js +3 -8
  169. package/lib/services/version.js.map +1 -1
  170. package/lib/services/version.spec.js +11 -24
  171. package/lib/services/version.spec.js.map +1 -1
  172. package/lib/stores/aggregator.d.ts +2 -2
  173. package/lib/stores/aggregator.js +37 -58
  174. package/lib/stores/aggregator.js.map +1 -1
  175. package/lib/stores/file.d.ts +3 -3
  176. package/lib/stores/file.js +93 -131
  177. package/lib/stores/file.js.map +1 -1
  178. package/lib/stores/file.spec.d.ts +2 -2
  179. package/lib/stores/file.spec.js +262 -289
  180. package/lib/stores/file.spec.js.map +1 -1
  181. package/lib/stores/mapper.d.ts +3 -3
  182. package/lib/stores/mapper.js +110 -137
  183. package/lib/stores/mapper.js.map +1 -1
  184. package/lib/stores/mapper.spec.js +133 -150
  185. package/lib/stores/mapper.spec.js.map +1 -1
  186. package/lib/stores/memory.d.ts +3 -3
  187. package/lib/stores/memory.js +98 -144
  188. package/lib/stores/memory.js.map +1 -1
  189. package/lib/stores/memory.spec.d.ts +2 -2
  190. package/lib/stores/memory.spec.js +124 -145
  191. package/lib/stores/memory.spec.js.map +1 -1
  192. package/lib/stores/store.d.ts +27 -17
  193. package/lib/stores/store.js +833 -849
  194. package/lib/stores/store.js.map +1 -1
  195. package/lib/stores/store.spec.d.ts +5 -4
  196. package/lib/stores/store.spec.js +625 -669
  197. package/lib/stores/store.spec.js.map +1 -1
  198. package/lib/stores/webdaql/WebdaQLLexer.d.ts +4 -4
  199. package/lib/stores/webdaql/WebdaQLLexer.js +9 -13
  200. package/lib/stores/webdaql/WebdaQLLexer.js.map +1 -1
  201. package/lib/stores/webdaql/WebdaQLParserLexer.d.ts +4 -4
  202. package/lib/stores/webdaql/WebdaQLParserLexer.js +9 -13
  203. package/lib/stores/webdaql/WebdaQLParserLexer.js.map +1 -1
  204. package/lib/stores/webdaql/WebdaQLParserListener.d.ts +2 -2
  205. package/lib/stores/webdaql/WebdaQLParserListener.js +1 -2
  206. package/lib/stores/webdaql/WebdaQLParserListener.js.map +1 -1
  207. package/lib/stores/webdaql/WebdaQLParserParser.d.ts +10 -10
  208. package/lib/stores/webdaql/WebdaQLParserParser.js +62 -91
  209. package/lib/stores/webdaql/WebdaQLParserParser.js.map +1 -1
  210. package/lib/stores/webdaql/WebdaQLParserVisitor.d.ts +2 -2
  211. package/lib/stores/webdaql/WebdaQLParserVisitor.js +1 -2
  212. package/lib/stores/webdaql/WebdaQLParserVisitor.js.map +1 -1
  213. package/lib/stores/webdaql/query.d.ts +4 -5
  214. package/lib/stores/webdaql/query.js +16 -19
  215. package/lib/stores/webdaql/query.js.map +1 -1
  216. package/lib/stores/webdaql/query.spec.js +30 -32
  217. package/lib/stores/webdaql/query.spec.js.map +1 -1
  218. package/lib/test.d.ts +3 -3
  219. package/lib/test.js +73 -100
  220. package/lib/test.js.map +1 -1
  221. package/lib/unpackedapplication.d.ts +1 -1
  222. package/lib/unpackedapplication.js +49 -39
  223. package/lib/unpackedapplication.js.map +1 -1
  224. package/lib/utils/abstractdeployer.js +1 -5
  225. package/lib/utils/abstractdeployer.js.map +1 -1
  226. package/lib/utils/abstractdeployer.spec.js +6 -8
  227. package/lib/utils/abstractdeployer.spec.js.map +1 -1
  228. package/lib/utils/context.d.ts +7 -5
  229. package/lib/utils/context.js +95 -103
  230. package/lib/utils/context.js.map +1 -1
  231. package/lib/utils/context.spec.js +139 -163
  232. package/lib/utils/context.spec.js.map +1 -1
  233. package/lib/utils/cookie.d.ts +3 -3
  234. package/lib/utils/cookie.js +42 -61
  235. package/lib/utils/cookie.js.map +1 -1
  236. package/lib/utils/cookie.spec.js +42 -64
  237. package/lib/utils/cookie.spec.js.map +1 -1
  238. package/lib/utils/esm.d.ts +4 -0
  239. package/lib/utils/esm.js +10 -0
  240. package/lib/utils/esm.js.map +1 -0
  241. package/lib/utils/httpcontext.d.ts +3 -0
  242. package/lib/utils/httpcontext.js +48 -65
  243. package/lib/utils/httpcontext.js.map +1 -1
  244. package/lib/utils/httpcontext.spec.js +37 -56
  245. package/lib/utils/httpcontext.spec.js.map +1 -1
  246. package/lib/utils/logger.d.ts +2 -2
  247. package/lib/utils/logger.js +15 -28
  248. package/lib/utils/logger.js.map +1 -1
  249. package/lib/utils/logger.spec.js +9 -11
  250. package/lib/utils/logger.spec.js.map +1 -1
  251. package/lib/utils/serializers.js +17 -20
  252. package/lib/utils/serializers.js.map +1 -1
  253. package/lib/utils/serializers.spec.js +43 -44
  254. package/lib/utils/serializers.spec.js.map +1 -1
  255. package/lib/utils/session.d.ts +6 -6
  256. package/lib/utils/session.js +37 -59
  257. package/lib/utils/session.js.map +1 -1
  258. package/lib/utils/session.spec.js +38 -51
  259. package/lib/utils/session.spec.js.map +1 -1
  260. package/lib/utils/waiter.d.ts +1 -1
  261. package/lib/utils/waiter.js +32 -52
  262. package/lib/utils/waiter.js.map +1 -1
  263. package/lib/utils/waiter.spec.js +75 -92
  264. package/lib/utils/waiter.spec.js.map +1 -1
  265. package/package.json +18 -13
  266. package/test/config-invitation.json +1 -3
  267. package/test/config.json +1 -2
  268. package/test/config.old.json +1 -2
  269. package/test/moddas/annotatedservice.js +5 -5
  270. package/test/moddas/debugmailer.js +2 -3
  271. package/test/moddas/fakeservice.js +2 -3
  272. package/test/moddas/voidstore.js +6 -4
  273. package/test/models/ident.js +2 -6
  274. package/test/models/task.js +3 -7
  275. package/test/package.json +2 -1
  276. package/webda.module.json +895 -190
@@ -1,40 +1,31 @@
1
- "use strict";
2
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
- return new (P || (P = Promise))(function (resolve, reject) {
5
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
- step((generator = generator.apply(thisArg, _arguments || [])).next());
9
- });
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
10
6
  };
11
- Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.Store = exports.StoreParameters = exports.UpdateConditionFailError = exports.StoreNotFoundError = void 0;
13
- const core_1 = require("../core");
14
- const coremodel_1 = require("../models/coremodel");
15
- const service_1 = require("../services/service");
16
- const query_1 = require("./webdaql/query");
17
- class StoreNotFoundError extends core_1.WebdaError {
7
+ import { WebdaError } from "../core.js";
8
+ import { CoreModel } from "../models/coremodel.js";
9
+ import { Route, Service, ServiceParameters } from "../services/service.js";
10
+ import { WebdaQL } from "./webdaql/query.js";
11
+ export class StoreNotFoundError extends WebdaError {
18
12
  constructor(uuid, storeName) {
19
13
  super("STORE_NOTFOUND", `Item not found ${uuid} Store(${storeName})`);
20
14
  }
21
15
  }
22
- exports.StoreNotFoundError = StoreNotFoundError;
23
- class UpdateConditionFailError extends core_1.WebdaError {
16
+ export class UpdateConditionFailError extends WebdaError {
24
17
  constructor(uuid, conditionField, condition) {
25
18
  super("STORE_UPDATE_CONDITION_FAILED", `UpdateCondition not met on ${uuid}.${conditionField} === ${condition instanceof Date ? condition.toISOString() : condition}`);
26
19
  }
27
20
  }
28
- exports.UpdateConditionFailError = UpdateConditionFailError;
29
21
  /**
30
22
  * Store parameter
31
23
  */
32
- class StoreParameters extends service_1.ServiceParameters {
24
+ export class StoreParameters extends ServiceParameters {
33
25
  constructor(params, service) {
34
- var _a, _b, _c, _d;
35
- var _e;
26
+ var _a;
36
27
  super(params);
37
- (_a = this.model) !== null && _a !== void 0 ? _a : (this.model = "Webda/CoreModel");
28
+ this.model ?? (this.model = "Webda/CoreModel");
38
29
  let expose = params.expose;
39
30
  if (typeof expose == "boolean") {
40
31
  expose = {};
@@ -51,7 +42,8 @@ class StoreParameters extends service_1.ServiceParameters {
51
42
  if (expose) {
52
43
  expose.restrict = expose.restrict || {};
53
44
  this.expose = expose;
54
- (_b = (_e = this.expose).queryMethod) !== null && _b !== void 0 ? _b : (_e.queryMethod = "GET");
45
+ (_a = this.expose).queryMethod ?? (_a.queryMethod = "GET");
46
+ this.url = expose.url;
55
47
  }
56
48
  if (params.map) {
57
49
  throw new Error("Deprecated map usage, use a MapperService");
@@ -59,11 +51,10 @@ class StoreParameters extends service_1.ServiceParameters {
59
51
  if (params.index) {
60
52
  throw new Error("Deprecated index usage, use an AggregatorService");
61
53
  }
62
- (_c = this.strict) !== null && _c !== void 0 ? _c : (this.strict = true);
63
- (_d = this.slowQueryThreshold) !== null && _d !== void 0 ? _d : (this.slowQueryThreshold = 30000);
54
+ this.strict ?? (this.strict = true);
55
+ this.slowQueryThreshold ?? (this.slowQueryThreshold = 30000);
64
56
  }
65
57
  }
66
- exports.StoreParameters = StoreParameters;
67
58
  /**
68
59
  * This class handle NoSQL storage and mapping (duplication) between NoSQL object
69
60
  * TODO Create the mapping documentation
@@ -98,7 +89,7 @@ exports.StoreParameters = StoreParameters;
98
89
  * }
99
90
  * @category CoreServices
100
91
  */
101
- class Store extends service_1.Service {
92
+ class Store extends Service {
102
93
  constructor() {
103
94
  super(...arguments);
104
95
  /**
@@ -127,26 +118,19 @@ class Store extends service_1.Service {
127
118
  slowQueries: 0
128
119
  };
129
120
  }
130
- /**
131
- * Load the parameters for a service
132
- */
133
- loadParameters(params) {
134
- return new StoreParameters(params, this);
135
- }
136
121
  /**
137
122
  * Retrieve the Model
138
123
  *
139
124
  * @throws Error if model is not found
140
125
  */
141
126
  computeParameters() {
142
- var _a;
143
127
  super.computeParameters();
144
128
  const p = this.parameters;
145
129
  this._model = this._webda.getModel(p.model);
146
130
  this._uuidField = this._model.getUuidField();
147
131
  this._lastUpdateField = this._model.getLastUpdateField();
148
132
  this._creationDateField = this._model.getCreationField();
149
- (_a = this._cacheStore) === null || _a === void 0 ? void 0 : _a.computeParameters();
133
+ this._cacheStore?.computeParameters();
150
134
  this.cacheStorePatchException();
151
135
  }
152
136
  logSlowQuery(_query, _reason, _time) {
@@ -168,29 +152,45 @@ class Store extends service_1.Service {
168
152
  * @param raiseIfNotFound
169
153
  * @returns
170
154
  */
171
- _getFromCache(uid, raiseIfNotFound = false) {
172
- var _a;
173
- return __awaiter(this, void 0, void 0, function* () {
174
- let res = yield ((_a = this._cacheStore) === null || _a === void 0 ? void 0 : _a._get(uid));
175
- if (!res) {
176
- res = yield this._get(uid, raiseIfNotFound);
177
- }
178
- else {
179
- res.__store = this;
180
- }
181
- return res;
182
- });
155
+ async _getFromCache(uid, raiseIfNotFound = false) {
156
+ let res = await this._cacheStore?._get(uid);
157
+ if (!res) {
158
+ res = await this._get(uid, raiseIfNotFound);
159
+ }
160
+ else {
161
+ res.__store = this;
162
+ }
163
+ return res;
183
164
  }
184
165
  /**
185
166
  * Get object from store
186
167
  * @param uid
187
168
  * @returns
188
169
  */
189
- getObject(uid) {
190
- return __awaiter(this, void 0, void 0, function* () {
191
- this.metrics.get++;
192
- return this._getFromCache(uid);
193
- });
170
+ async getObject(uid) {
171
+ this.metrics.get++;
172
+ return this._getFromCache(uid);
173
+ }
174
+ /**
175
+ * @override
176
+ */
177
+ getUrl(url, methods) {
178
+ // If url is absolute
179
+ if (url.startsWith("/")) {
180
+ return url;
181
+ }
182
+ const expose = this.parameters.expose;
183
+ if (!expose.url ||
184
+ (url === "." && methods.includes("POST") && expose.restrict.create) ||
185
+ (url === "./{uuid}" && methods.includes("DELETE") && expose.restrict.delete) ||
186
+ (url === "./{uuid}" && methods.includes("PATCH") && expose.restrict.update) ||
187
+ (url === "./{uuid}" && methods.includes("PUT") && expose.restrict.update) ||
188
+ (url === "./{uuid}" && methods.includes("GET") && expose.restrict.get) ||
189
+ (url === ".{?q}" && methods.includes("GET") && expose.restrict.query) ||
190
+ (url === "." && methods.includes("PUT") && expose.restrict.query)) {
191
+ return undefined;
192
+ }
193
+ return super.getUrl(url, methods);
194
194
  }
195
195
  /**
196
196
  * @inheritdoc
@@ -199,60 +199,52 @@ class Store extends service_1.Service {
199
199
  if (!this.parameters.expose) {
200
200
  return;
201
201
  }
202
+ super.initRoutes();
202
203
  // We enforce ExposeParameters within the constructor
203
204
  const expose = this.parameters.expose;
204
- if (!expose.restrict.create) {
205
- this.addRoute(expose.url, ["POST"], this.httpCreate, {
206
- model: this._model.name,
207
- post: {
208
- description: `The way to create a new ${this._model.name} model`,
209
- summary: "Create a new " + this._model.name,
210
- operationId: `create${this._model.name}`,
211
- responses: {
212
- "200": {
213
- description: "Retrieve model",
214
- content: {
215
- "application/json": {
216
- // schema: this._model.name
205
+ // Query endpoint
206
+ if (!expose.restrict.query) {
207
+ let requestBody;
208
+ if (expose.queryMethod === "PUT") {
209
+ requestBody = {
210
+ content: {
211
+ "application/json": {
212
+ schema: {
213
+ properties: {
214
+ q: {
215
+ type: "string"
216
+ }
217
217
  }
218
218
  }
219
- },
220
- "400": {
221
- description: "Object is invalid"
222
- },
223
- "403": {
224
- description: "You don't have permissions"
225
- },
226
- "409": {
227
- description: "Object already exists"
228
219
  }
229
220
  }
230
- }
231
- });
232
- }
233
- // Dont even create the route that are restricted so we can ease up the test on handler
234
- let methods = [];
235
- if (!expose.restrict.update) {
236
- methods.push("PUT");
237
- methods.push("PATCH");
238
- }
239
- if (!expose.restrict.get) {
240
- methods.push("GET");
241
- }
242
- // Query endpoint
243
- if (!expose.restrict.query) {
244
- this.addRoute(expose.queryMethod === "GET" ? `${expose.url}{?q}` : expose.url, [expose.queryMethod], this.httpQuery, {
221
+ };
222
+ }
223
+ this.addRoute(expose.queryMethod === "GET" ? `.{?q}` : ".", [expose.queryMethod], this.httpQuery, {
245
224
  model: this._model.name,
246
225
  [expose.queryMethod.toLowerCase()]: {
247
226
  description: `Query on ${this._model.name} model with WebdaQL`,
248
227
  summary: "Query " + this._model.name,
249
- operationId: `create${this._model.name}`,
228
+ operationId: `query${this._model.name}`,
229
+ requestBody,
250
230
  responses: {
251
231
  "200": {
252
232
  description: "Retrieve models",
253
233
  content: {
254
234
  "application/json": {
255
- // schema: this._model.name
235
+ schema: {
236
+ properties: {
237
+ contiuationToken: {
238
+ type: "string"
239
+ },
240
+ results: {
241
+ type: "array",
242
+ items: {
243
+ $ref: `#/components/schemas/${this._model.name}`
244
+ }
245
+ }
246
+ }
247
+ }
256
248
  }
257
249
  }
258
250
  },
@@ -266,87 +258,7 @@ class Store extends service_1.Service {
266
258
  }
267
259
  });
268
260
  }
269
- if (!expose.restrict.delete) {
270
- methods.push("DELETE");
271
- }
272
- if (methods.length) {
273
- this.addRoute(expose.url + "/{uuid}", methods, this.httpRoute, {
274
- model: this._model.name,
275
- get: {
276
- description: `Retrieve ${this._model.name} model if permissions allow`,
277
- summary: "Retrieve a " + this._model.name,
278
- operationId: `get${this._model.name}`,
279
- responses: {
280
- "200": {
281
- //model: this._model.name
282
- },
283
- "400": {
284
- description: "Object is invalid"
285
- },
286
- "403": {
287
- description: "You don't have permissions"
288
- },
289
- "404": {
290
- description: "Unknown object"
291
- }
292
- }
293
- },
294
- put: {
295
- description: `Update a ${this._model.name} if the permissions allow`,
296
- summary: "Update a " + this._model.name,
297
- operationId: `updatet${this._model.name}`,
298
- responses: {
299
- "200": {
300
- // model: this._model.name
301
- },
302
- "400": {
303
- description: "Object is invalid"
304
- },
305
- "403": {
306
- description: "You don't have permissions"
307
- },
308
- "404": {
309
- description: "Unknown object"
310
- }
311
- }
312
- },
313
- patch: {
314
- description: `Patch a ${this._model.name} if the permissions allow`,
315
- summary: "Patch a " + this._model.name,
316
- operationId: `updatet${this._model.name}`,
317
- responses: {
318
- "204": {
319
- description: ""
320
- },
321
- "400": {
322
- description: "Object is invalid"
323
- },
324
- "403": {
325
- description: "You don't have permissions"
326
- },
327
- "404": {
328
- description: "Unknown object"
329
- }
330
- }
331
- },
332
- delete: {
333
- operationId: `delete${this._model.name}`,
334
- description: `Delete ${this._model.name} if the permissions allow`,
335
- summary: "Delete a " + this._model.name,
336
- responses: {
337
- "204": {
338
- description: ""
339
- },
340
- "403": {
341
- description: "You don't have permissions"
342
- },
343
- "404": {
344
- description: "Unknown object"
345
- }
346
- }
347
- }
348
- });
349
- }
261
+ // Model actions
350
262
  if (this._model && this._model.getActions) {
351
263
  let actions = this._model.getActions();
352
264
  Object.keys(actions).forEach(name => {
@@ -361,7 +273,7 @@ class Store extends service_1.Service {
361
273
  throw Error("Action static method _" + name + " does not exist");
362
274
  }
363
275
  executer = this.httpGlobalAction;
364
- this.addRoute(expose.url + "/" + name, action.methods, executer, action.openapi);
276
+ this.addRoute(`./${name}`, action.methods, executer, action.openapi);
365
277
  }
366
278
  else {
367
279
  // By default will grab the object and then call the action
@@ -369,7 +281,7 @@ class Store extends service_1.Service {
369
281
  throw Error("Action method _" + name + " does not exist");
370
282
  }
371
283
  executer = this.httpAction;
372
- this.addRoute(expose.url + "/{uuid}/" + name, action.methods, executer, action.openapi);
284
+ this.addRoute(`./{uuid}/${name}`, action.methods, executer, action.openapi);
373
285
  }
374
286
  });
375
287
  }
@@ -379,17 +291,10 @@ class Store extends service_1.Service {
379
291
  * Used mainly in test
380
292
  */
381
293
  setModel(model) {
382
- var _a;
383
294
  this._model = model;
384
- (_a = this._cacheStore) === null || _a === void 0 ? void 0 : _a.setModel(model);
295
+ this._cacheStore?.setModel(model);
385
296
  this.parameters.strict = false;
386
297
  }
387
- /**
388
- * Get the url where the store is exposed
389
- */
390
- getUrl() {
391
- return this.parameters.expose.url;
392
- }
393
298
  /**
394
299
  * We should ignore exception from the store
395
300
  */
@@ -429,7 +334,6 @@ class Store extends service_1.Service {
429
334
  */
430
335
  initModel(object = {}) {
431
336
  var _a;
432
- var _b;
433
337
  // Make sure to send a model object
434
338
  if (!(object instanceof this._model)) {
435
339
  object = this._model.factory(this._model, object);
@@ -438,16 +342,26 @@ class Store extends service_1.Service {
438
342
  object.setUuid(object.generateUid(object));
439
343
  }
440
344
  object.__store = this;
441
- for (var i in this._reverseMap) {
442
- (_a = object[_b = this._reverseMap[i].property]) !== null && _a !== void 0 ? _a : (object[_b] = []);
443
- for (var j in object[this._reverseMap[i].property]) {
345
+ for (let i in this._reverseMap) {
346
+ object[_a = this._reverseMap[i].property] ?? (object[_a] = []);
347
+ for (let j in object[this._reverseMap[i].property]) {
444
348
  // Use Partial
445
- object[this._reverseMap[i].property][j] = this._reverseMap[i].mapper.initModel(object[this._reverseMap[i].property][j]);
349
+ object[this._reverseMap[i].property][j] = this._reverseMap[i].mapper.newModel(object[this._reverseMap[i].property][j]);
446
350
  object[this._reverseMap[i].property][j].setContext(object.getContext());
447
351
  }
448
352
  }
449
353
  return object;
450
354
  }
355
+ /**
356
+ * Get a new model with this data preloaded
357
+ * @param object
358
+ * @returns
359
+ */
360
+ newModel(object = {}) {
361
+ let result = this.initModel(object);
362
+ Object.keys(object).forEach(k => result.__dirty.add(k));
363
+ return result;
364
+ }
451
365
  /**
452
366
  * Add reverse map information
453
367
  *
@@ -461,72 +375,60 @@ class Store extends service_1.Service {
461
375
  mapper: store
462
376
  });
463
377
  }
464
- incrementAttribute(uid, prop, value) {
465
- var _a;
466
- return __awaiter(this, void 0, void 0, function* () {
467
- // If value === 0 no need to update anything
468
- if (value === 0) {
469
- return Promise.resolve();
470
- }
471
- let updateDate = new Date();
472
- this.metrics.increment++;
473
- yield this._incrementAttribute(uid, prop, value, updateDate);
474
- yield ((_a = this._cacheStore) === null || _a === void 0 ? void 0 : _a._incrementAttribute(uid, prop, value, updateDate));
475
- return this.emitSync("Store.PartialUpdated", {
476
- object_id: uid,
477
- store: this,
478
- updateDate,
479
- partial_update: {
480
- increment: {
481
- value: value,
482
- property: prop
483
- }
378
+ async incrementAttribute(uid, prop, value) {
379
+ // If value === 0 no need to update anything
380
+ if (value === 0) {
381
+ return Promise.resolve();
382
+ }
383
+ let updateDate = new Date();
384
+ this.metrics.increment++;
385
+ await this._incrementAttribute(uid, prop, value, updateDate);
386
+ await this._cacheStore?._incrementAttribute(uid, prop, value, updateDate);
387
+ return this.emitSync("Store.PartialUpdated", {
388
+ object_id: uid,
389
+ store: this,
390
+ updateDate,
391
+ partial_update: {
392
+ increment: {
393
+ value: value,
394
+ property: prop
484
395
  }
485
- });
396
+ }
486
397
  });
487
398
  }
488
- upsertItemToCollection(uid, prop, item, index = undefined, itemWriteCondition = undefined, itemWriteConditionField = undefined) {
489
- var _a;
490
- return __awaiter(this, void 0, void 0, function* () {
491
- if (itemWriteConditionField === undefined) {
492
- itemWriteConditionField = this._uuidField;
493
- }
494
- let updateDate = new Date();
495
- this.metrics.collectionUpsert++;
496
- yield this._upsertItemToCollection(uid, prop, item, index, itemWriteCondition, itemWriteConditionField, updateDate);
497
- yield ((_a = this._cacheStore) === null || _a === void 0 ? void 0 : _a._upsertItemToCollection(uid, prop, item, index, itemWriteCondition, itemWriteConditionField, updateDate));
498
- yield this.emitSync("Store.PartialUpdated", {
499
- object_id: uid,
500
- store: this,
501
- updateDate,
502
- partial_update: {
503
- addItem: {
504
- value: item,
505
- property: prop,
506
- index: index
507
- }
399
+ async upsertItemToCollection(uid, prop, item, index = undefined, itemWriteCondition = undefined, itemWriteConditionField = this._uuidField) {
400
+ let updateDate = new Date();
401
+ this.metrics.collectionUpsert++;
402
+ await this._upsertItemToCollection(uid, prop, item, index, itemWriteCondition, itemWriteConditionField, updateDate);
403
+ await this._cacheStore?._upsertItemToCollection(uid, prop, item, index, itemWriteCondition, itemWriteConditionField, updateDate);
404
+ await this.emitSync("Store.PartialUpdated", {
405
+ object_id: uid,
406
+ store: this,
407
+ updateDate,
408
+ partial_update: {
409
+ addItem: {
410
+ value: item,
411
+ property: prop,
412
+ index: index
508
413
  }
509
- });
414
+ }
510
415
  });
511
416
  }
512
- deleteItemFromCollection(uid, prop, index, itemWriteCondition, itemWriteConditionField = this._uuidField) {
513
- var _a;
514
- return __awaiter(this, void 0, void 0, function* () {
515
- let updateDate = new Date();
516
- this.metrics.collectionDelete++;
517
- yield this._deleteItemFromCollection(uid, prop, index, itemWriteCondition, itemWriteConditionField, updateDate);
518
- yield ((_a = this._cacheStore) === null || _a === void 0 ? void 0 : _a._deleteItemFromCollection(uid, prop, index, itemWriteCondition, itemWriteConditionField, updateDate));
519
- yield this.emitSync("Store.PartialUpdated", {
520
- object_id: uid,
521
- store: this,
522
- updateDate,
523
- partial_update: {
524
- deleteItem: {
525
- property: prop,
526
- index: index
527
- }
417
+ async deleteItemFromCollection(uid, prop, index, itemWriteCondition, itemWriteConditionField = this._uuidField) {
418
+ let updateDate = new Date();
419
+ this.metrics.collectionDelete++;
420
+ await this._deleteItemFromCollection(uid, prop, index, itemWriteCondition, itemWriteConditionField, updateDate);
421
+ await this._cacheStore?._deleteItemFromCollection(uid, prop, index, itemWriteCondition, itemWriteConditionField, updateDate);
422
+ await this.emitSync("Store.PartialUpdated", {
423
+ object_id: uid,
424
+ store: this,
425
+ updateDate,
426
+ partial_update: {
427
+ deleteItem: {
428
+ property: prop,
429
+ index: index
528
430
  }
529
- });
431
+ }
530
432
  });
531
433
  }
532
434
  /**
@@ -534,136 +436,132 @@ class Store extends service_1.Service {
534
436
  * @param query
535
437
  * @param context to apply permission
536
438
  */
537
- query(query, context) {
538
- return __awaiter(this, void 0, void 0, function* () {
539
- let permissionQuery = this._model.getPermissionQuery(context);
540
- let partialPermission = true;
541
- let fullQuery;
542
- if (permissionQuery) {
543
- partialPermission = permissionQuery.partial;
544
- if (query.trim() !== "") {
545
- fullQuery = `(${permissionQuery.query}) AND ${query}`;
546
- }
547
- else {
548
- fullQuery = permissionQuery.query;
549
- }
439
+ async query(query, context) {
440
+ let permissionQuery = this._model.getPermissionQuery(context);
441
+ let partialPermission = true;
442
+ let fullQuery;
443
+ if (permissionQuery) {
444
+ partialPermission = permissionQuery.partial;
445
+ if (query.trim() !== "") {
446
+ fullQuery = `(${permissionQuery.query}) AND ${query}`;
550
447
  }
551
448
  else {
552
- fullQuery = query;
449
+ fullQuery = permissionQuery.query;
553
450
  }
554
- let queryValidator = new query_1.WebdaQL.QueryValidator(fullQuery);
555
- let offset = queryValidator.getOffset();
556
- const limit = queryValidator.getLimit();
557
- const parsedQuery = queryValidator.getQuery();
558
- // Emit the default event
559
- yield this.emitSync("Store.Query", {
560
- query,
561
- parsedQuery,
562
- store: this,
563
- context
564
- });
565
- const result = {
566
- results: [],
567
- continuationToken: undefined
568
- };
569
- /*
570
- Offset are split in two with _
571
-
572
- MainOffset is the database offset, retrieving a page from the database
573
- SubOffset is the offset within the page
574
-
575
- As we filter through the page, for additional filters or permissions, the page cut
576
- by database does not endup being our final page cut, so we need a page offset to
577
- abstract this completely
578
- */
579
- let [mainOffset, subOffset] = offset.split("_");
580
- let secondOffset = parseInt(subOffset || "0");
581
- let duration = Date.now();
582
- this.metrics.query++;
583
- while (result.results.length < limit) {
584
- let tmpResults = yield this.find(Object.assign(Object.assign({}, parsedQuery), { continuationToken: mainOffset }));
585
- // If no filter is returned assume it is by mistake and apply filtering
586
- if (tmpResults.filter === undefined) {
587
- tmpResults.filter = queryValidator.getExpression();
588
- this.log("WARN", `Store '${this.getName()}' postquery full filtering`);
451
+ }
452
+ else {
453
+ fullQuery = query;
454
+ }
455
+ let queryValidator = new WebdaQL.QueryValidator(fullQuery);
456
+ let offset = queryValidator.getOffset();
457
+ const limit = queryValidator.getLimit();
458
+ const parsedQuery = queryValidator.getQuery();
459
+ // Emit the default event
460
+ await this.emitSync("Store.Query", {
461
+ query,
462
+ parsedQuery,
463
+ store: this,
464
+ context
465
+ });
466
+ const result = {
467
+ results: [],
468
+ continuationToken: undefined
469
+ };
470
+ /*
471
+ Offset are split in two with _
472
+
473
+ MainOffset is the database offset, retrieving a page from the database
474
+ SubOffset is the offset within the page
475
+
476
+ As we filter through the page, for additional filters or permissions, the page cut
477
+ by database does not endup being our final page cut, so we need a page offset to
478
+ abstract this completely
479
+ */
480
+ let [mainOffset, subOffset] = offset.split("_");
481
+ let secondOffset = parseInt(subOffset || "0");
482
+ let duration = Date.now();
483
+ this.metrics.query++;
484
+ while (result.results.length < limit) {
485
+ let tmpResults = await this.find({ ...parsedQuery, continuationToken: mainOffset });
486
+ // If no filter is returned assume it is by mistake and apply filtering
487
+ if (tmpResults.filter === undefined) {
488
+ tmpResults.filter = queryValidator.getExpression();
489
+ this.log("WARN", `Store '${this.getName()}' postquery full filtering`);
490
+ }
491
+ let subOffsetCount = 0;
492
+ for (let item of tmpResults.results) {
493
+ // Because of dynamic filter and permission we need to suboffset the pagination
494
+ subOffsetCount++;
495
+ if (subOffsetCount <= secondOffset) {
496
+ continue;
589
497
  }
590
- let subOffsetCount = 0;
591
- for (let item of tmpResults.results) {
592
- // Because of dynamic filter and permission we need to suboffset the pagination
593
- subOffsetCount++;
594
- if (subOffsetCount <= secondOffset) {
595
- continue;
498
+ if (tmpResults.filter !== true && !tmpResults.filter.eval(item)) {
499
+ continue;
500
+ }
501
+ if (context && partialPermission) {
502
+ try {
503
+ await item.canAct(context, "get");
596
504
  }
597
- if (tmpResults.filter !== true && !tmpResults.filter.eval(item)) {
505
+ catch (err) {
598
506
  continue;
599
507
  }
600
- if (context && partialPermission) {
601
- try {
602
- yield item.canAct(context, "get");
603
- }
604
- catch (err) {
605
- continue;
606
- }
508
+ }
509
+ result.results.push(item);
510
+ if (result.results.length >= limit) {
511
+ if (subOffsetCount === tmpResults.results.length) {
512
+ result.continuationToken = tmpResults.continuationToken;
607
513
  }
608
- result.results.push(item);
609
- if (result.results.length >= limit) {
610
- if (subOffsetCount === tmpResults.results.length) {
611
- result.continuationToken = tmpResults.continuationToken;
612
- }
613
- else {
614
- result.continuationToken = `${mainOffset}_${subOffsetCount}`;
615
- }
616
- break;
514
+ else {
515
+ result.continuationToken = `${mainOffset}_${subOffsetCount}`;
617
516
  }
618
- }
619
- // Update both offset
620
- mainOffset = tmpResults.continuationToken;
621
- // Fresh new query so we do not need to skip
622
- secondOffset = 0;
623
- if (mainOffset === undefined || result.results.length >= limit) {
624
517
  break;
625
518
  }
626
519
  }
627
- duration = Date.now() - duration;
628
- this.metrics.queryDuration =
629
- (this.metrics.queryDuration * (this.metrics.query - 1) + duration) / this.metrics.query;
630
- if (duration > this.parameters.slowQueryThreshold) {
631
- this.logSlowQuery(query, "", duration);
520
+ // Update both offset
521
+ mainOffset = tmpResults.continuationToken;
522
+ // Fresh new query so we do not need to skip
523
+ secondOffset = 0;
524
+ if (mainOffset === undefined || result.results.length >= limit) {
525
+ break;
632
526
  }
633
- yield this.emitSync("Store.Queried", {
634
- query,
635
- parsedQuery: parsedQuery,
636
- store: this,
637
- continuationToken: result.continuationToken,
638
- results: result.results,
639
- context
640
- });
641
- return result;
527
+ }
528
+ duration = Date.now() - duration;
529
+ this.metrics.queryDuration =
530
+ (this.metrics.queryDuration * (this.metrics.query - 1) + duration) / this.metrics.query;
531
+ if (duration > this.parameters.slowQueryThreshold) {
532
+ this.logSlowQuery(query, "", duration);
533
+ }
534
+ await this.emitSync("Store.Queried", {
535
+ query,
536
+ parsedQuery: parsedQuery,
537
+ store: this,
538
+ continuationToken: result.continuationToken,
539
+ results: result.results,
540
+ context
642
541
  });
542
+ return result;
643
543
  }
644
544
  /**
645
545
  * Expose query to http
646
546
  */
647
- httpQuery(ctx) {
648
- return __awaiter(this, void 0, void 0, function* () {
649
- let query;
650
- if (ctx.getHttpContext().getMethod() === "GET") {
651
- query = ctx.getParameters().q;
652
- }
653
- else {
654
- query = (yield ctx.getRequestBody()).q;
655
- }
656
- try {
657
- ctx.write(yield this.query(query, ctx));
658
- }
659
- catch (err) {
660
- if (err instanceof SyntaxError) {
661
- this.log("INFO", "Query syntax error");
662
- throw 400;
663
- }
664
- throw err;
547
+ async httpQuery(ctx) {
548
+ let query;
549
+ if (ctx.getHttpContext().getMethod() === "GET") {
550
+ query = ctx.getParameters().q;
551
+ }
552
+ else {
553
+ query = (await ctx.getRequestBody()).q;
554
+ }
555
+ try {
556
+ ctx.write(await this.query(query, ctx));
557
+ }
558
+ catch (err) {
559
+ if (err instanceof SyntaxError) {
560
+ this.log("INFO", "Query syntax error");
561
+ throw 400;
665
562
  }
666
- });
563
+ throw err;
564
+ }
667
565
  }
668
566
  /**
669
567
  * Save an object
@@ -674,36 +572,33 @@ class Store extends service_1.Service {
674
572
  *
675
573
  * Might want to rename to create
676
574
  */
677
- save(object, ctx = undefined) {
678
- var _a, _b;
679
- var _c;
680
- return __awaiter(this, void 0, void 0, function* () {
681
- object = this.initModel(object);
682
- // Dates should be store by the Store
683
- (_a = object[_c = this._creationDateField]) !== null && _a !== void 0 ? _a : (object[_c] = new Date());
684
- object[this._lastUpdateField] = new Date();
685
- if (ctx) {
686
- object.setContext(ctx);
687
- }
688
- yield this.emitSync("Store.Save", {
689
- object: object,
690
- store: this,
691
- context: ctx
692
- });
693
- // Handle object auto listener
694
- yield object._onSave();
695
- this.metrics.save++;
696
- let res = yield this._save(object);
697
- yield ((_b = this._cacheStore) === null || _b === void 0 ? void 0 : _b._save(object));
698
- object = this.initModel(res);
699
- yield this.emitSync("Store.Saved", {
700
- object: object,
701
- store: this,
702
- context: ctx
703
- });
704
- yield object._onSaved();
705
- return object;
575
+ async save(object, ctx = undefined) {
576
+ var _a;
577
+ object = this.initModel(object);
578
+ // Dates should be store by the Store
579
+ object[_a = this._creationDateField] ?? (object[_a] = new Date());
580
+ object[this._lastUpdateField] = new Date();
581
+ if (ctx) {
582
+ object.setContext(ctx);
583
+ }
584
+ await this.emitSync("Store.Save", {
585
+ object: object,
586
+ store: this,
587
+ context: ctx
588
+ });
589
+ // Handle object auto listener
590
+ await object._onSave();
591
+ this.metrics.save++;
592
+ let res = await this._save(object);
593
+ await this._cacheStore?._save(object);
594
+ object = this.initModel(res);
595
+ await this.emitSync("Store.Saved", {
596
+ object: object,
597
+ store: this,
598
+ context: ctx
706
599
  });
600
+ await object._onSaved();
601
+ return object;
707
602
  }
708
603
  /**
709
604
  * Patch an object
@@ -712,10 +607,8 @@ class Store extends service_1.Service {
712
607
  * @param reverseMap
713
608
  * @returns
714
609
  */
715
- patch(object, reverseMap = true) {
716
- return __awaiter(this, void 0, void 0, function* () {
717
- return this.update(object, reverseMap, true);
718
- });
610
+ async patch(object, reverseMap = true, conditionField, conditionValue) {
611
+ return this.update(object, reverseMap, true, conditionField, conditionValue);
719
612
  }
720
613
  /**
721
614
  * Check if an UpdateCondition is met
@@ -726,7 +619,8 @@ class Store extends service_1.Service {
726
619
  */
727
620
  checkUpdateCondition(model, conditionField, condition, uid) {
728
621
  if (conditionField) {
729
- if (model[conditionField] !== condition) {
622
+ // Add toString to manage Date object
623
+ if (model[conditionField].toString() !== condition.toString()) {
730
624
  throw new UpdateConditionFailError(uid ? uid : model.getUuid(), conditionField, condition);
731
625
  }
732
626
  }
@@ -757,21 +651,18 @@ class Store extends service_1.Service {
757
651
  * @param conditionField
758
652
  * @param condition
759
653
  */
760
- conditionalPatch(uuid, updates, conditionField, condition) {
761
- var _a;
762
- return __awaiter(this, void 0, void 0, function* () {
763
- try {
764
- yield this._patch(updates, uuid, condition, conditionField);
765
- yield ((_a = this._cacheStore) === null || _a === void 0 ? void 0 : _a.patch(Object.assign({ uuid }, updates)));
766
- return true;
767
- }
768
- catch (err) {
769
- if (err instanceof UpdateConditionFailError) {
770
- return false;
771
- }
772
- throw err;
654
+ async conditionalPatch(uuid, updates, conditionField, condition) {
655
+ try {
656
+ await this._patch(updates, uuid, condition, conditionField);
657
+ await this._cacheStore?.patch({ uuid, ...updates });
658
+ return true;
659
+ }
660
+ catch (err) {
661
+ if (err instanceof UpdateConditionFailError) {
662
+ return false;
773
663
  }
774
- });
664
+ throw err;
665
+ }
775
666
  }
776
667
  /**
777
668
  *
@@ -783,26 +674,24 @@ class Store extends service_1.Service {
783
674
  * @param itemWriteConditionField
784
675
  * @param updateDate
785
676
  */
786
- simulateUpsertItemToCollection(model, prop, item, updateDate, index, itemWriteCondition, itemWriteConditionField) {
787
- return __awaiter(this, void 0, void 0, function* () {
788
- if (prop === "__proto__") {
789
- throw new Error("Cannot update __proto__: js/prototype-polluting-assignment");
790
- }
791
- this.checkCollectionUpdateCondition(model, prop, itemWriteConditionField, itemWriteCondition, index);
792
- if (index === undefined) {
793
- if (model[prop] === undefined) {
794
- model[prop] = [item];
795
- }
796
- else {
797
- model[prop].push(item);
798
- }
677
+ async simulateUpsertItemToCollection(model, prop, item, updateDate, index, itemWriteCondition, itemWriteConditionField) {
678
+ if (prop === "__proto__") {
679
+ throw new Error("Cannot update __proto__: js/prototype-polluting-assignment");
680
+ }
681
+ this.checkCollectionUpdateCondition(model, prop, itemWriteConditionField, itemWriteCondition, index);
682
+ if (index === undefined) {
683
+ if (model[prop] === undefined) {
684
+ model[prop] = [item];
799
685
  }
800
686
  else {
801
- model[prop][index] = item;
687
+ model[prop].push(item);
802
688
  }
803
- model[this._lastUpdateField] = updateDate;
804
- yield this._save(model);
805
- });
689
+ }
690
+ else {
691
+ model[prop][index] = item;
692
+ }
693
+ model[this._lastUpdateField] = updateDate;
694
+ await this._save(model);
806
695
  }
807
696
  /**
808
697
  * Update an object
@@ -813,88 +702,90 @@ class Store extends service_1.Service {
813
702
  * @param {Boolean} reverseMap internal use only, for disable map resolution
814
703
  * @return {Promise} with saved object
815
704
  */
816
- update(object, reverseMap = true, partial = false) {
817
- var _a, _b;
818
- return __awaiter(this, void 0, void 0, function* () {
819
- /** @ignore */
820
- var saved;
821
- var loaded;
822
- // Dont allow to update collections from map
823
- if (this._reverseMap != undefined && reverseMap) {
824
- for (let i in this._reverseMap) {
825
- if (object[this._reverseMap[i].property] != undefined) {
826
- delete object[this._reverseMap[i].property];
827
- }
828
- }
829
- }
830
- if (Object.keys(object).length < 2) {
831
- return undefined;
832
- }
833
- object[this._lastUpdateField] = new Date();
834
- this.metrics.get++;
835
- let load = yield this._getFromCache(object[this._uuidField], true);
836
- if (load.__type !== this._model.name && this.parameters.strict) {
837
- this.log("WARN", `Object '${object[this._uuidField]}' was not created by this store`);
838
- throw new StoreNotFoundError(object[this._uuidField], this.getName());
839
- }
840
- loaded = this.initModel(load);
841
- if (object instanceof coremodel_1.CoreModel) {
842
- loaded.setContext(object.getContext());
843
- }
844
- if (partial) {
845
- yield this.emitSync(`Store.PatchUpdate`, {
846
- object: loaded,
847
- store: this,
848
- update: object
849
- });
850
- }
851
- else {
852
- yield this.emitSync(`Store.Update`, {
853
- object: loaded,
854
- store: this,
855
- update: object
856
- });
857
- }
858
- yield loaded._onUpdate(object);
859
- let res;
860
- if (partial) {
861
- this.metrics.partialUpdate++;
862
- yield this._patch(object, object[this._uuidField], load[this._lastUpdateField], this._lastUpdateField);
863
- yield ((_a = this._cacheStore) === null || _a === void 0 ? void 0 : _a._patch(object, object[this._uuidField], load[this._lastUpdateField], this._lastUpdateField));
864
- res = object;
865
- }
866
- else {
867
- // Copy back the mappers
868
- for (let i in this._reverseMap) {
869
- object[this._reverseMap[i].property] = loaded[this._reverseMap[i].property];
705
+ async update(object, reverseMap = true, partial = false, conditionField, conditionValue) {
706
+ /** @ignore */
707
+ let saved;
708
+ let loaded;
709
+ // Dont allow to update collections from map
710
+ if (this._reverseMap != undefined && reverseMap) {
711
+ for (let i in this._reverseMap) {
712
+ if (object[this._reverseMap[i].property] != undefined) {
713
+ delete object[this._reverseMap[i].property];
870
714
  }
871
- this.metrics.update++;
872
- res = yield this._update(object, object[this._uuidField], load[this._lastUpdateField], this._lastUpdateField);
873
- yield ((_b = this._cacheStore) === null || _b === void 0 ? void 0 : _b._update(object, object[this._uuidField], load[this._lastUpdateField], this._lastUpdateField));
874
- }
875
- // Return updated
876
- for (let i in res) {
877
- loaded[i] = res[i];
878
715
  }
879
- for (let i in object) {
880
- loaded[i] = object[i];
881
- }
882
- saved = this.initModel(loaded);
883
- if (partial) {
884
- yield this.emitSync(`Store.PatchUpdated`, {
885
- object: saved,
886
- store: this
887
- });
888
- }
889
- else {
890
- yield this.emitSync(`Store.Updated`, {
891
- object: saved,
892
- store: this
893
- });
716
+ }
717
+ if (Object.keys(object).length < 2) {
718
+ return undefined;
719
+ }
720
+ object[this._lastUpdateField] = new Date();
721
+ this.metrics.get++;
722
+ let load = await this._getFromCache(object[this._uuidField], true);
723
+ if (load.__type !== this._model.name && this.parameters.strict) {
724
+ this.log("WARN", `Object '${object[this._uuidField]}' was not created by this store`);
725
+ throw new StoreNotFoundError(object[this._uuidField], this.getName());
726
+ }
727
+ loaded = this.initModel(load);
728
+ if (object instanceof CoreModel) {
729
+ loaded.setContext(object.getContext());
730
+ }
731
+ if (partial) {
732
+ await this.emitSync(`Store.PatchUpdate`, {
733
+ object: loaded,
734
+ store: this,
735
+ update: object
736
+ });
737
+ }
738
+ else {
739
+ await this.emitSync(`Store.Update`, {
740
+ object: loaded,
741
+ store: this,
742
+ update: object
743
+ });
744
+ }
745
+ await loaded._onUpdate(object);
746
+ let res;
747
+ if (conditionField !== null) {
748
+ conditionField ?? (conditionField = this._lastUpdateField);
749
+ conditionValue ?? (conditionValue = load[conditionField]);
750
+ }
751
+ if (partial) {
752
+ this.metrics.partialUpdate++;
753
+ await this._patch(object, object[this._uuidField], conditionValue, conditionField);
754
+ await this._cacheStore?._patch(object, object[this._uuidField], load[this._lastUpdateField], this._lastUpdateField);
755
+ res = object;
756
+ }
757
+ else {
758
+ // Copy back the mappers
759
+ for (let i in this._reverseMap) {
760
+ object[this._reverseMap[i].property] = loaded[this._reverseMap[i].property];
894
761
  }
895
- yield saved._onUpdated();
896
- return saved;
897
- });
762
+ object = this.initModel(object);
763
+ this.metrics.update++;
764
+ res = await this._update(object, object[this._uuidField], conditionValue, conditionField);
765
+ await this._cacheStore?._update(object, object[this._uuidField], load[this._lastUpdateField], this._lastUpdateField);
766
+ }
767
+ // Return updated
768
+ for (let i in res) {
769
+ loaded[i] = res[i];
770
+ }
771
+ for (let i in object) {
772
+ loaded[i] = object[i];
773
+ }
774
+ saved = this.initModel(loaded);
775
+ if (partial) {
776
+ await this.emitSync(`Store.PatchUpdated`, {
777
+ object: saved,
778
+ store: this
779
+ });
780
+ }
781
+ else {
782
+ await this.emitSync(`Store.Updated`, {
783
+ object: saved,
784
+ store: this
785
+ });
786
+ }
787
+ await saved._onUpdated();
788
+ return saved;
898
789
  }
899
790
  /**
900
791
  * Remove an attribute from an object
@@ -903,18 +794,15 @@ class Store extends service_1.Service {
903
794
  * @param attribute
904
795
  * @returns
905
796
  */
906
- removeAttribute(uuid, attribute, itemWriteCondition, itemWriteConditionField) {
907
- var _a;
908
- return __awaiter(this, void 0, void 0, function* () {
909
- this.metrics.attributeDelete++;
910
- yield this._removeAttribute(uuid, attribute, itemWriteCondition, itemWriteConditionField);
911
- yield ((_a = this._cacheStore) === null || _a === void 0 ? void 0 : _a._removeAttribute(uuid, attribute, itemWriteCondition, itemWriteConditionField));
912
- yield this.emitSync("Store.PartialUpdated", {
913
- object_id: uuid,
914
- partial_update: {
915
- deleteAttribute: attribute
916
- }
917
- });
797
+ async removeAttribute(uuid, attribute, itemWriteCondition, itemWriteConditionField) {
798
+ this.metrics.attributeDelete++;
799
+ await this._removeAttribute(uuid, attribute, itemWriteCondition, itemWriteConditionField);
800
+ await this._cacheStore?._removeAttribute(uuid, attribute, itemWriteCondition, itemWriteConditionField);
801
+ await this.emitSync("Store.PartialUpdated", {
802
+ object_id: uuid,
803
+ partial_update: {
804
+ deleteAttribute: attribute
805
+ }
918
806
  });
919
807
  }
920
808
  /**
@@ -924,21 +812,17 @@ class Store extends service_1.Service {
924
812
  * @param uuid
925
813
  * @returns
926
814
  */
927
- cascadeDelete(obj, _uuid) {
928
- return __awaiter(this, void 0, void 0, function* () {
929
- // We dont need uuid but Binary store will need it
930
- return this.delete(obj.getUuid());
931
- });
815
+ async cascadeDelete(obj, _uuid) {
816
+ // We dont need uuid but Binary store will need it
817
+ return this.delete(obj.getUuid());
932
818
  }
933
819
  /**
934
820
  * Delete an object from the store without condition nor async
935
821
  * @param uid to delete
936
822
  * @returns
937
823
  */
938
- forceDelete(uid) {
939
- return __awaiter(this, void 0, void 0, function* () {
940
- return this.delete(uid, undefined, undefined, true);
941
- });
824
+ async forceDelete(uid) {
825
+ return this.delete(uid, undefined, undefined, true);
942
826
  }
943
827
  /**
944
828
  * Delete an object
@@ -947,62 +831,59 @@ class Store extends service_1.Service {
947
831
  * @param {Boolean} delete sync even if asyncDelete is active
948
832
  * @return {Promise} the deletion promise
949
833
  */
950
- delete(uid, writeCondition, writeConditionField, sync = false) {
951
- var _a, _b;
952
- return __awaiter(this, void 0, void 0, function* () {
953
- /** @ignore */
954
- let to_delete;
955
- // Allow full object or just its uuid
956
- if (typeof uid === "object") {
957
- to_delete = uid;
958
- }
959
- else {
960
- this.metrics.get++;
961
- to_delete = yield this._getFromCache(uid);
962
- if (to_delete === undefined) {
963
- return;
964
- }
965
- if (to_delete.__type !== this._model.name && this.parameters.strict) {
966
- this.log("WARN", `Object '${uid}' was not created by this store`);
967
- return;
968
- }
969
- to_delete = this.initModel(to_delete);
970
- }
971
- // Check condition as we have the object
972
- if (writeCondition) {
973
- if (to_delete[writeConditionField] !== writeCondition) {
974
- throw new UpdateConditionFailError(to_delete.getUuid(), writeConditionField, writeCondition);
975
- }
834
+ async delete(uid, writeCondition, writeConditionField, sync = false) {
835
+ /** @ignore */
836
+ let to_delete;
837
+ // Allow full object or just its uuid
838
+ if (typeof uid === "object") {
839
+ to_delete = uid;
840
+ }
841
+ else {
842
+ this.metrics.get++;
843
+ to_delete = await this._getFromCache(uid);
844
+ if (to_delete === undefined) {
845
+ return;
976
846
  }
977
- // Send preevent
978
- yield this.emitSync("Store.Delete", {
979
- object: to_delete,
980
- store: this
981
- });
982
- yield to_delete._onDelete();
983
- // If async we just tag the object as deleted
984
- if (this.parameters.asyncDelete && !sync) {
985
- this.metrics.partialUpdate++;
986
- yield this._patch({
987
- __deleted: true
988
- }, to_delete.getUuid());
989
- yield ((_a = this._cacheStore) === null || _a === void 0 ? void 0 : _a._patch({
990
- __deleted: true
991
- }, to_delete.getUuid()));
847
+ if (to_delete.__type !== this._model.name && this.parameters.strict) {
848
+ this.log("WARN", `Object '${uid}' was not created by this store`);
849
+ return;
992
850
  }
993
- else {
994
- this.metrics.delete++;
995
- // Delete from the DB for real
996
- yield this._delete(to_delete.getUuid(), writeCondition, writeConditionField);
997
- yield ((_b = this._cacheStore) === null || _b === void 0 ? void 0 : _b._delete(to_delete.getUuid(), writeCondition, writeConditionField));
851
+ to_delete = this.initModel(to_delete);
852
+ }
853
+ // Check condition as we have the object
854
+ if (writeCondition) {
855
+ if (to_delete[writeConditionField] !== writeCondition) {
856
+ throw new UpdateConditionFailError(to_delete.getUuid(), writeConditionField, writeCondition);
998
857
  }
999
- // Send post event
1000
- yield this.emitSync("Store.Deleted", {
1001
- object: to_delete,
1002
- store: this
1003
- });
1004
- yield to_delete._onDeleted();
858
+ }
859
+ // Send preevent
860
+ await this.emitSync("Store.Delete", {
861
+ object: to_delete,
862
+ store: this
863
+ });
864
+ await to_delete._onDelete();
865
+ // If async we just tag the object as deleted
866
+ if (this.parameters.asyncDelete && !sync) {
867
+ this.metrics.partialUpdate++;
868
+ await this._patch({
869
+ __deleted: true
870
+ }, to_delete.getUuid());
871
+ await this._cacheStore?._patch({
872
+ __deleted: true
873
+ }, to_delete.getUuid());
874
+ }
875
+ else {
876
+ this.metrics.delete++;
877
+ // Delete from the DB for real
878
+ await this._delete(to_delete.getUuid(), writeCondition, writeConditionField);
879
+ await this._cacheStore?._delete(to_delete.getUuid(), writeCondition, writeConditionField);
880
+ }
881
+ // Send post event
882
+ await this.emitSync("Store.Deleted", {
883
+ object: to_delete,
884
+ store: this
1005
885
  });
886
+ await to_delete._onDeleted();
1006
887
  }
1007
888
  /**
1008
889
  * By default we cannot know if the store will trigger or not
@@ -1018,32 +899,31 @@ class Store extends service_1.Service {
1018
899
  * @param {string} id
1019
900
  * @returns {Promise<Map<string, any>>}
1020
901
  */
1021
- getConfiguration(id) {
1022
- return __awaiter(this, void 0, void 0, function* () {
1023
- this.metrics.get++;
1024
- let object = yield this._getFromCache(id);
1025
- if (!object) {
1026
- return undefined;
1027
- }
1028
- let result = {};
1029
- for (let i in object) {
1030
- if (i === this._uuidField || i === this._lastUpdateField || i.startsWith("_")) {
1031
- continue;
1032
- }
1033
- result[i] = object[i];
902
+ async getConfiguration(id) {
903
+ this.metrics.get++;
904
+ let object = await this._getFromCache(id);
905
+ if (!object) {
906
+ return undefined;
907
+ }
908
+ let result = {};
909
+ for (let i in object) {
910
+ if (i === this._uuidField || i === this._lastUpdateField || i.startsWith("_")) {
911
+ continue;
1034
912
  }
1035
- return result;
1036
- });
913
+ result[i] = object[i];
914
+ }
915
+ return result;
1037
916
  }
1038
917
  /**
1039
- * Alias for save
918
+ * Upsert the uuid object
1040
919
  * @param uuid
1041
920
  * @param data
1042
921
  */
1043
- put(uuid, data) {
1044
- return __awaiter(this, void 0, void 0, function* () {
1045
- return this.save(Object.assign(Object.assign({}, data), { uuid }));
1046
- });
922
+ async put(uuid, data) {
923
+ if (await this.exists(uuid)) {
924
+ return this.update({ ...data, uuid });
925
+ }
926
+ return this.save({ ...data, uuid });
1047
927
  }
1048
928
  /**
1049
929
  * Get an object
@@ -1051,31 +931,29 @@ class Store extends service_1.Service {
1051
931
  * @param {String} uuid to get
1052
932
  * @return {Promise} the object retrieved ( can be undefined if not found )
1053
933
  */
1054
- get(uid, ctx = undefined) {
1055
- return __awaiter(this, void 0, void 0, function* () {
1056
- /** @ignore */
1057
- if (!uid) {
1058
- return undefined;
1059
- }
1060
- this.metrics.get++;
1061
- let object = yield this._getFromCache(uid);
1062
- if (!object) {
1063
- return undefined;
1064
- }
1065
- if (object.__type !== this._model.name && this.parameters.strict) {
1066
- this.log("WARN", `Object '${uid}' was not created by this store`);
1067
- return undefined;
1068
- }
1069
- object = this.initModel(object);
1070
- object.setContext(ctx);
1071
- yield this.emitSync("Store.Get", {
1072
- object: object,
1073
- store: this,
1074
- context: ctx
1075
- });
1076
- yield object._onGet();
1077
- return object;
934
+ async get(uid, ctx = undefined, defaultValue = undefined) {
935
+ /** @ignore */
936
+ if (!uid) {
937
+ return undefined;
938
+ }
939
+ this.metrics.get++;
940
+ let object = await this._getFromCache(uid);
941
+ if (!object) {
942
+ return defaultValue ? this.initModel(defaultValue) : undefined;
943
+ }
944
+ if (object.__type !== this._model.name && this.parameters.strict) {
945
+ this.log("WARN", `Object '${uid}' was not created by this store`);
946
+ return undefined;
947
+ }
948
+ object = this.initModel(object);
949
+ object.setContext(ctx);
950
+ await this.emitSync("Store.Get", {
951
+ object: object,
952
+ store: this,
953
+ context: ctx
1078
954
  });
955
+ await object._onGet();
956
+ return object;
1079
957
  }
1080
958
  /**
1081
959
  * Set one attribute in an object
@@ -1087,159 +965,154 @@ class Store extends service_1.Service {
1087
965
  * @param value new value
1088
966
  * @returns
1089
967
  */
1090
- setAttribute(uid, property, value) {
1091
- return __awaiter(this, void 0, void 0, function* () {
1092
- let patch = {};
1093
- patch[property] = value;
1094
- patch[this.getUuidField()] = uid;
1095
- yield this.patch(patch);
1096
- });
968
+ async setAttribute(uid, property, value) {
969
+ let patch = {};
970
+ patch[property] = value;
971
+ patch[this.getUuidField()] = uid;
972
+ await this.patch(patch);
1097
973
  }
1098
974
  /**
1099
975
  * @override
1100
976
  */
1101
- simulateFind(query, uuids) {
1102
- return __awaiter(this, void 0, void 0, function* () {
1103
- let result = {
1104
- results: [],
1105
- continuationToken: undefined,
1106
- filter: true
1107
- };
1108
- let count = 0;
1109
- let limit = query.limit;
1110
- let offset = parseInt(query.continuationToken || "0");
1111
- let originalOffset = offset;
1112
- if (query.orderBy && query.orderBy.length) {
1113
- offset = 0;
1114
- // We need to retrieve everything to orderBy after
1115
- limit = Number.MAX_SAFE_INTEGER;
977
+ async simulateFind(query, uuids) {
978
+ let result = {
979
+ results: [],
980
+ continuationToken: undefined,
981
+ filter: true
982
+ };
983
+ let count = 0;
984
+ let limit = query.limit;
985
+ let offset = parseInt(query.continuationToken || "0");
986
+ let originalOffset = offset;
987
+ if (query.orderBy && query.orderBy.length) {
988
+ offset = 0;
989
+ // We need to retrieve everything to orderBy after
990
+ limit = Number.MAX_SAFE_INTEGER;
991
+ }
992
+ // Need to transfert to Array
993
+ for (let uuid of uuids) {
994
+ count++;
995
+ // Offset start
996
+ if (offset >= count) {
997
+ continue;
1116
998
  }
1117
- // Need to transfert to Array
1118
- for (let uuid of uuids) {
1119
- count++;
1120
- // Offset start
1121
- if (offset >= count) {
1122
- continue;
1123
- }
1124
- let obj = yield this._getFromCache(uuid);
1125
- if (obj && query.filter.eval(obj)) {
1126
- result.results.push(obj);
1127
- if (result.results.length >= limit) {
1128
- result.continuationToken = count.toString();
1129
- return result;
1130
- }
999
+ let obj = await this._getFromCache(uuid);
1000
+ if (obj && query.filter.eval(obj)) {
1001
+ result.results.push(obj);
1002
+ if (result.results.length >= limit) {
1003
+ result.continuationToken = count.toString();
1004
+ return result;
1131
1005
  }
1132
1006
  }
1133
- // Order by
1134
- if (query.orderBy && query.orderBy.length) {
1135
- // Sorting the results
1136
- result.results.sort((a, b) => {
1137
- let valA, valB;
1138
- for (let orderBy of query.orderBy) {
1139
- let invert = orderBy.direction === "ASC" ? 1 : -1;
1140
- valA = query_1.WebdaQL.ComparisonExpression.getAttributeValue(a, orderBy.field.split("."));
1141
- valB = query_1.WebdaQL.ComparisonExpression.getAttributeValue(b, orderBy.field.split("."));
1142
- if (valA === valB) {
1143
- continue;
1144
- }
1145
- if (typeof valA === "string") {
1146
- return valA.localeCompare(valB) * invert;
1147
- }
1148
- return (valA < valB ? -1 : 1) * invert;
1007
+ }
1008
+ // Order by
1009
+ if (query.orderBy && query.orderBy.length) {
1010
+ // Sorting the results
1011
+ result.results.sort((a, b) => {
1012
+ let valA, valB;
1013
+ for (let orderBy of query.orderBy) {
1014
+ let invert = orderBy.direction === "ASC" ? 1 : -1;
1015
+ valA = WebdaQL.ComparisonExpression.getAttributeValue(a, orderBy.field.split("."));
1016
+ valB = WebdaQL.ComparisonExpression.getAttributeValue(b, orderBy.field.split("."));
1017
+ if (valA === valB) {
1018
+ continue;
1149
1019
  }
1150
- return -1;
1151
- });
1152
- result.results = result.results.slice(originalOffset, query.limit + originalOffset);
1153
- if (result.results.length >= query.limit) {
1154
- result.continuationToken = (query.limit + originalOffset).toString();
1020
+ if (typeof valA === "string") {
1021
+ return valA.localeCompare(valB) * invert;
1022
+ }
1023
+ return (valA < valB ? -1 : 1) * invert;
1155
1024
  }
1025
+ return -1;
1026
+ });
1027
+ result.results = result.results.slice(originalOffset, query.limit + originalOffset);
1028
+ if (result.results.length >= query.limit) {
1029
+ result.continuationToken = (query.limit + originalOffset).toString();
1156
1030
  }
1157
- return result;
1158
- });
1031
+ }
1032
+ return result;
1033
+ }
1034
+ getOpenApiReplacements() {
1035
+ return {
1036
+ modelName: this._model.name
1037
+ };
1159
1038
  }
1160
1039
  /**
1161
1040
  * Handle POST
1162
1041
  * @param ctx
1163
1042
  */
1164
- httpCreate(ctx) {
1165
- return __awaiter(this, void 0, void 0, function* () {
1166
- let body = yield ctx.getRequestBody();
1167
- let object = this._model.factory(this._model, body, ctx);
1168
- object[this._creationDateField] = new Date();
1169
- yield object.canAct(ctx, "create");
1170
- try {
1171
- yield object.validate(ctx, body);
1172
- }
1173
- catch (err) {
1174
- this.log("INFO", "Object is not valid", err);
1175
- throw 400;
1176
- }
1177
- if (object[this._uuidField] && (yield this.exists(object[this._uuidField]))) {
1178
- throw 409;
1179
- }
1180
- yield this.save(object, ctx);
1181
- ctx.write(object);
1182
- yield this.emitSync("Store.WebCreate", {
1183
- context: ctx,
1184
- values: body,
1185
- object: object,
1186
- store: this
1187
- });
1043
+ async httpCreate(ctx) {
1044
+ let body = await ctx.getRequestBody();
1045
+ let object = this._model.factory(this._model, body, ctx);
1046
+ object[this._creationDateField] = new Date();
1047
+ await object.canAct(ctx, "create");
1048
+ try {
1049
+ await object.validate(ctx, body);
1050
+ }
1051
+ catch (err) {
1052
+ this.log("INFO", "Object is not valid", err);
1053
+ throw 400;
1054
+ }
1055
+ if (object[this._uuidField] && (await this.exists(object[this._uuidField]))) {
1056
+ throw 409;
1057
+ }
1058
+ await this.save(object, ctx);
1059
+ ctx.write(object);
1060
+ await this.emitSync("Store.WebCreate", {
1061
+ context: ctx,
1062
+ values: body,
1063
+ object: object,
1064
+ store: this
1188
1065
  });
1189
1066
  }
1190
1067
  /**
1191
1068
  * Handle obect action
1192
1069
  * @param ctx
1193
1070
  */
1194
- httpAction(ctx) {
1195
- return __awaiter(this, void 0, void 0, function* () {
1196
- let action = ctx.getHttpContext().getUrl().split("/").pop();
1197
- let object = yield this.get(ctx.parameter("uuid"), ctx);
1198
- if (object === undefined || object.__deleted) {
1199
- throw 404;
1200
- }
1201
- yield object.canAct(ctx, action);
1202
- yield this.emitSync("Store.Action", {
1203
- action: action,
1204
- object: object,
1205
- store: this,
1206
- context: ctx
1207
- });
1208
- let res = yield object["_" + action](ctx);
1209
- if (res) {
1210
- ctx.write(res);
1211
- }
1212
- yield this.emitSync("Store.Actioned", {
1213
- action: action,
1214
- object: object,
1215
- store: this,
1216
- context: ctx,
1217
- result: res
1218
- });
1071
+ async httpAction(ctx) {
1072
+ let action = ctx.getHttpContext().getUrl().split("/").pop();
1073
+ let object = await this.get(ctx.parameter("uuid"), ctx);
1074
+ if (object === undefined || object.__deleted) {
1075
+ throw 404;
1076
+ }
1077
+ await object.canAct(ctx, action);
1078
+ await this.emitSync("Store.Action", {
1079
+ action: action,
1080
+ object: object,
1081
+ store: this,
1082
+ context: ctx
1083
+ });
1084
+ let res = await object["_" + action](ctx);
1085
+ if (res) {
1086
+ ctx.write(res);
1087
+ }
1088
+ await this.emitSync("Store.Actioned", {
1089
+ action: action,
1090
+ object: object,
1091
+ store: this,
1092
+ context: ctx,
1093
+ result: res
1219
1094
  });
1220
1095
  }
1221
1096
  /**
1222
1097
  * Handle collection action
1223
1098
  * @param ctx
1224
1099
  */
1225
- httpGlobalAction(ctx) {
1226
- return __awaiter(this, void 0, void 0, function* () {
1227
- let action = ctx.getHttpContext().getUrl().split("/").pop();
1228
- yield this.emitSync("Store.Action", {
1229
- action: action,
1230
- store: this,
1231
- context: ctx
1232
- });
1233
- let res = yield this._model["_" + action](ctx);
1234
- if (res) {
1235
- ctx.write(res);
1236
- }
1237
- yield this.emitSync("Store.Actioned", {
1238
- action: action,
1239
- store: this,
1240
- context: ctx,
1241
- result: res
1242
- });
1100
+ async httpGlobalAction(ctx) {
1101
+ let action = ctx.getHttpContext().getUrl().split("/").pop();
1102
+ await this.emitSync("Store.Action", {
1103
+ action: action,
1104
+ store: this,
1105
+ context: ctx
1106
+ });
1107
+ let res = await this._model["_" + action](ctx);
1108
+ if (res) {
1109
+ ctx.write(res);
1110
+ }
1111
+ await this.emitSync("Store.Actioned", {
1112
+ action: action,
1113
+ store: this,
1114
+ context: ctx,
1115
+ result: res
1243
1116
  });
1244
1117
  }
1245
1118
  /**
@@ -1247,62 +1120,60 @@ class Store extends service_1.Service {
1247
1120
  *
1248
1121
  * @param ctx context of the request
1249
1122
  */
1250
- httpUpdate(ctx) {
1251
- return __awaiter(this, void 0, void 0, function* () {
1252
- let body = yield ctx.getRequestBody();
1253
- let uuid = ctx.parameter("uuid");
1254
- body[this._uuidField] = uuid;
1255
- let object = yield this.get(uuid, ctx);
1256
- if (!object || object.__deleted)
1257
- throw 404;
1258
- yield object.canAct(ctx, "update");
1259
- if (ctx.getHttpContext().getMethod() === "PATCH") {
1260
- try {
1261
- yield object.validate(ctx, body);
1262
- }
1263
- catch (err) {
1264
- this.log("INFO", "Object invalid", err);
1265
- throw 400;
1266
- }
1267
- let updateObject = new this._model();
1268
- // Clean any default attributes from the model
1269
- Object.keys(updateObject)
1270
- .filter(i => i !== "__class")
1271
- .forEach(i => {
1272
- delete updateObject[i];
1273
- });
1274
- updateObject.setContext(ctx);
1275
- updateObject.load(body);
1276
- yield this.patch(updateObject);
1277
- object = undefined;
1123
+ async httpUpdate(ctx) {
1124
+ let body = await ctx.getRequestBody();
1125
+ let uuid = ctx.parameter("uuid");
1126
+ body[this._uuidField] = uuid;
1127
+ let object = await this.get(uuid, ctx);
1128
+ if (!object || object.__deleted)
1129
+ throw 404;
1130
+ await object.canAct(ctx, "update");
1131
+ if (ctx.getHttpContext().getMethod() === "PATCH") {
1132
+ try {
1133
+ await object.validate(ctx, body);
1278
1134
  }
1279
- else {
1280
- let updateObject = new this._model();
1281
- updateObject.load(body);
1282
- // Copy back the _ attributes
1283
- Object.keys(object)
1284
- .filter(i => i.startsWith("_"))
1285
- .forEach(i => {
1286
- updateObject[i] = object[i];
1287
- });
1288
- try {
1289
- yield updateObject.validate(ctx, body);
1290
- }
1291
- catch (err) {
1292
- this.log("INFO", "Object invalid", err);
1293
- throw 400;
1294
- }
1295
- // Add mappers back to
1296
- object = yield this.update(updateObject);
1135
+ catch (err) {
1136
+ this.log("INFO", "Object invalid", err);
1137
+ throw 400;
1297
1138
  }
1298
- ctx.write(object);
1299
- yield this.emitSync("Store.WebUpdate", {
1300
- context: ctx,
1301
- updates: body,
1302
- object: object,
1303
- store: this,
1304
- method: ctx.getHttpContext().getMethod()
1139
+ let updateObject = new this._model();
1140
+ // Clean any default attributes from the model
1141
+ Object.keys(updateObject)
1142
+ .filter(i => i !== "__class")
1143
+ .forEach(i => {
1144
+ delete updateObject[i];
1305
1145
  });
1146
+ updateObject.setContext(ctx);
1147
+ updateObject.load(body);
1148
+ await this.patch(updateObject);
1149
+ object = undefined;
1150
+ }
1151
+ else {
1152
+ let updateObject = new this._model();
1153
+ updateObject.load(body);
1154
+ // Copy back the _ attributes
1155
+ Object.keys(object)
1156
+ .filter(i => i.startsWith("_"))
1157
+ .forEach(i => {
1158
+ updateObject[i] = object[i];
1159
+ });
1160
+ try {
1161
+ await updateObject.validate(ctx, body);
1162
+ }
1163
+ catch (err) {
1164
+ this.log("INFO", "Object invalid", err);
1165
+ throw 400;
1166
+ }
1167
+ // Add mappers back to
1168
+ object = await this.update(updateObject);
1169
+ }
1170
+ ctx.write(object);
1171
+ await this.emitSync("Store.WebUpdate", {
1172
+ context: ctx,
1173
+ updates: body,
1174
+ object: object,
1175
+ store: this,
1176
+ method: ctx.getHttpContext().getMethod()
1306
1177
  });
1307
1178
  }
1308
1179
  /**
@@ -1310,32 +1181,25 @@ class Store extends service_1.Service {
1310
1181
  *
1311
1182
  * @param ctx context of the request
1312
1183
  */
1313
- httpGet(ctx) {
1314
- return __awaiter(this, void 0, void 0, function* () {
1315
- let uuid = ctx.parameter("uuid");
1316
- if (uuid) {
1317
- let object = yield this.get(uuid, ctx);
1318
- yield this.emitSync("Store.WebGetNotFound", {
1319
- context: ctx,
1320
- uuid,
1321
- store: this
1322
- });
1323
- if (object === undefined || object.__deleted) {
1324
- throw 404;
1325
- }
1326
- yield object.canAct(ctx, "get");
1327
- ctx.write(object);
1328
- yield this.emitSync("Store.WebGet", {
1329
- context: ctx,
1330
- object: object,
1331
- store: this
1332
- });
1333
- ctx.write(object);
1334
- }
1335
- else {
1336
- // List probably
1337
- }
1184
+ async httpGet(ctx) {
1185
+ let uuid = ctx.parameter("uuid");
1186
+ let object = await this.get(uuid, ctx);
1187
+ await this.emitSync("Store.WebGetNotFound", {
1188
+ context: ctx,
1189
+ uuid,
1190
+ store: this
1338
1191
  });
1192
+ if (object === undefined || object.__deleted) {
1193
+ throw 404;
1194
+ }
1195
+ await object.canAct(ctx, "get");
1196
+ ctx.write(object);
1197
+ await this.emitSync("Store.WebGet", {
1198
+ context: ctx,
1199
+ object: object,
1200
+ store: this
1201
+ });
1202
+ ctx.write(object);
1339
1203
  }
1340
1204
  /**
1341
1205
  * Handle HTTP request
@@ -1343,31 +1207,21 @@ class Store extends service_1.Service {
1343
1207
  * @param ctx context of the request
1344
1208
  * @returns
1345
1209
  */
1346
- httpRoute(ctx) {
1347
- return __awaiter(this, void 0, void 0, function* () {
1348
- let uuid = ctx.parameter("uuid");
1349
- if (ctx.getHttpContext().getMethod() == "GET") {
1350
- return this.httpGet(ctx);
1351
- }
1352
- else if (ctx.getHttpContext().getMethod() == "DELETE") {
1353
- let object = yield this.get(uuid, ctx);
1354
- if (!object || object.__deleted)
1355
- throw 404;
1356
- yield object.canAct(ctx, "delete");
1357
- // http://stackoverflow.com/questions/28684209/huge-delay-on-delete-requests-with-204-response-and-no-content-in-objectve-c#
1358
- // IOS don't handle 204 with Content-Length != 0 it seems
1359
- // Have trouble to handle the Content-Length on API Gateway so returning an empty object for now
1360
- ctx.write({});
1361
- yield this.delete(uuid);
1362
- yield this.emitSync("Store.WebDelete", {
1363
- context: ctx,
1364
- object_id: uuid,
1365
- store: this
1366
- });
1367
- }
1368
- else if (ctx.getHttpContext().getMethod() === "PUT" || ctx.getHttpContext().getMethod() === "PATCH") {
1369
- return this.httpUpdate(ctx);
1370
- }
1210
+ async httpRoute(ctx) {
1211
+ let uuid = ctx.parameter("uuid");
1212
+ let object = await this.get(uuid, ctx);
1213
+ if (!object || object.__deleted)
1214
+ throw 404;
1215
+ await object.canAct(ctx, "delete");
1216
+ // http://stackoverflow.com/questions/28684209/huge-delay-on-delete-requests-with-204-response-and-no-content-in-objectve-c#
1217
+ // IOS don't handle 204 with Content-Length != 0 it seems
1218
+ // Have trouble to handle the Content-Length on API Gateway so returning an empty object for now
1219
+ ctx.write({});
1220
+ await this.delete(uuid);
1221
+ await this.emitSync("Store.WebDelete", {
1222
+ context: ctx,
1223
+ object_id: uuid,
1224
+ store: this
1371
1225
  });
1372
1226
  }
1373
1227
  /**
@@ -1377,5 +1231,135 @@ class Store extends service_1.Service {
1377
1231
  return this._uuidField;
1378
1232
  }
1379
1233
  }
1380
- exports.Store = Store;
1234
+ __decorate([
1235
+ Route(".", ["POST"], false, {
1236
+ post: {
1237
+ description: "The way to create a new ${modelName} model",
1238
+ summary: "Create a new ${modelName}",
1239
+ operationId: "create${modelName}",
1240
+ requestBody: {
1241
+ content: {
1242
+ "application/json": {
1243
+ schema: {
1244
+ $ref: "#/components/schemas/${modelName}"
1245
+ }
1246
+ }
1247
+ }
1248
+ },
1249
+ responses: {
1250
+ "200": {
1251
+ description: "Retrieve model",
1252
+ content: {
1253
+ "application/json": {
1254
+ schema: {
1255
+ $ref: "#/components/schemas/${modelName}"
1256
+ }
1257
+ }
1258
+ }
1259
+ },
1260
+ "400": {
1261
+ description: "Object is invalid"
1262
+ },
1263
+ "403": {
1264
+ description: "You don't have permissions"
1265
+ },
1266
+ "409": {
1267
+ description: "Object already exists"
1268
+ }
1269
+ }
1270
+ }
1271
+ })
1272
+ ], Store.prototype, "httpCreate", null);
1273
+ __decorate([
1274
+ Route("./{uuid}", ["PUT", "PATCH"], false, {
1275
+ put: {
1276
+ description: "Update a ${modelName} if the permissions allow",
1277
+ summary: "Update a ${modelName}",
1278
+ operationId: "update${modelName}",
1279
+ schemas: {
1280
+ input: "${modelName}",
1281
+ output: "${modelName}"
1282
+ },
1283
+ responses: {
1284
+ "200": {},
1285
+ "400": {
1286
+ description: "Object is invalid"
1287
+ },
1288
+ "403": {
1289
+ description: "You don't have permissions"
1290
+ },
1291
+ "404": {
1292
+ description: "Unknown object"
1293
+ }
1294
+ }
1295
+ },
1296
+ patch: {
1297
+ description: "Patch a ${modelName} if the permissions allow",
1298
+ summary: "Patch a ${modelName}",
1299
+ operationId: "partialUpdatet${modelName}",
1300
+ schemas: {
1301
+ input: "${modelName}"
1302
+ },
1303
+ responses: {
1304
+ "204": {
1305
+ description: ""
1306
+ },
1307
+ "400": {
1308
+ description: "Object is invalid"
1309
+ },
1310
+ "403": {
1311
+ description: "You don't have permissions"
1312
+ },
1313
+ "404": {
1314
+ description: "Unknown object"
1315
+ }
1316
+ }
1317
+ }
1318
+ })
1319
+ ], Store.prototype, "httpUpdate", null);
1320
+ __decorate([
1321
+ Route("./{uuid}", ["GET"], false, {
1322
+ get: {
1323
+ description: "Retrieve ${modelName} model if permissions allow",
1324
+ summary: "Retrieve a ${modelName}",
1325
+ operationId: "get${modelName}",
1326
+ schemas: {
1327
+ output: "${modelName}"
1328
+ },
1329
+ responses: {
1330
+ "200": {},
1331
+ "400": {
1332
+ description: "Object is invalid"
1333
+ },
1334
+ "403": {
1335
+ description: "You don't have permissions"
1336
+ },
1337
+ "404": {
1338
+ description: "Unknown object"
1339
+ }
1340
+ }
1341
+ }
1342
+ })
1343
+ ], Store.prototype, "httpGet", null);
1344
+ __decorate([
1345
+ Route("./{uuid}", ["DELETE"], false, {
1346
+ delete: {
1347
+ operationId: "delete${modelName}",
1348
+ description: "Delete ${modelName} if the permissions allow",
1349
+ summary: "Delete a ${modelName}",
1350
+ responses: {
1351
+ "204": {
1352
+ description: ""
1353
+ },
1354
+ "403": {
1355
+ description: "You don't have permissions"
1356
+ },
1357
+ "404": {
1358
+ description: "Unknown object"
1359
+ }
1360
+ }
1361
+ }
1362
+ })
1363
+ ], Store.prototype, "httpRoute", null);
1364
+ export { Store };
1381
1365
  //# sourceMappingURL=store.js.map