@webda/core 2.0.0-beta.2 → 2.0.1

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 (279) hide show
  1. package/lib/application.d.ts +5 -21
  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 +44 -45
  7. package/lib/core.js +239 -320
  8. package/lib/core.js.map +1 -1
  9. package/lib/core.spec.js +326 -391
  10. package/lib/core.spec.js.map +1 -1
  11. package/lib/index.d.ts +49 -45
  12. package/lib/index.js +54 -67
  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 -151
  18. package/lib/models/aclmodel.spec.js.map +1 -1
  19. package/lib/models/coremodel.d.ts +39 -17
  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 -166
  34. package/lib/models/ownermodel.spec.js.map +1 -1
  35. package/lib/models/rolemodel.d.ts +2 -2
  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 -61
  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 +4 -4
  62. package/lib/queues/queueservice.js +52 -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 +28 -19
  75. package/lib/services/authentication.js +542 -574
  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 +9 -7
  80. package/lib/services/binary.js +213 -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 +6 -3
  92. package/lib/services/configuration.js +78 -103
  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 +258 -0
  102. package/lib/services/cryptoservice.js +312 -0
  103. package/lib/services/cryptoservice.js.map +1 -0
  104. package/lib/services/cryptoservice.spec.d.ts +1 -0
  105. package/lib/services/cryptoservice.spec.js +137 -0
  106. package/lib/services/cryptoservice.spec.js.map +1 -0
  107. package/lib/services/debugmailer.d.ts +1 -1
  108. package/lib/services/debugmailer.js +13 -34
  109. package/lib/services/debugmailer.js.map +1 -1
  110. package/lib/services/debugmailer.spec.js +16 -29
  111. package/lib/services/debugmailer.spec.js.map +1 -1
  112. package/lib/services/echo.d.ts +2 -2
  113. package/lib/services/echo.js +15 -31
  114. package/lib/services/echo.js.map +1 -1
  115. package/lib/services/echo.spec.js +27 -40
  116. package/lib/services/echo.spec.js.map +1 -1
  117. package/lib/services/filebinary.d.ts +10 -5
  118. package/lib/services/filebinary.js +171 -205
  119. package/lib/services/filebinary.js.map +1 -1
  120. package/lib/services/filebinary.spec.d.ts +2 -1
  121. package/lib/services/filebinary.spec.js +106 -117
  122. package/lib/services/filebinary.spec.js.map +1 -1
  123. package/lib/services/fileconfiguration.d.ts +2 -2
  124. package/lib/services/fileconfiguration.js +25 -43
  125. package/lib/services/fileconfiguration.js.map +1 -1
  126. package/lib/services/fileconfiguration.spec.js +79 -109
  127. package/lib/services/fileconfiguration.spec.js.map +1 -1
  128. package/lib/services/invitationservice.d.ts +10 -10
  129. package/lib/services/invitationservice.js +275 -313
  130. package/lib/services/invitationservice.js.map +1 -1
  131. package/lib/services/invitationservice.spec.js +443 -449
  132. package/lib/services/invitationservice.spec.js.map +1 -1
  133. package/lib/services/kubernetesconfiguration.d.ts +2 -2
  134. package/lib/services/kubernetesconfiguration.js +41 -59
  135. package/lib/services/kubernetesconfiguration.js.map +1 -1
  136. package/lib/services/kubernetesconfiguration.spec.js +80 -98
  137. package/lib/services/kubernetesconfiguration.spec.js.map +1 -1
  138. package/lib/services/mailer.d.ts +4 -4
  139. package/lib/services/mailer.js +62 -86
  140. package/lib/services/mailer.js.map +1 -1
  141. package/lib/services/mailer.spec.js +86 -127
  142. package/lib/services/mailer.spec.js.map +1 -1
  143. package/lib/services/notificationservice.d.ts +4 -4
  144. package/lib/services/notificationservice.js +23 -42
  145. package/lib/services/notificationservice.js.map +1 -1
  146. package/lib/services/notificationservice.spec.js +47 -73
  147. package/lib/services/notificationservice.spec.js.map +1 -1
  148. package/lib/services/oauth.d.ts +32 -6
  149. package/lib/services/oauth.js +73 -78
  150. package/lib/services/oauth.js.map +1 -1
  151. package/lib/services/oauth.spec.js +128 -148
  152. package/lib/services/oauth.spec.js.map +1 -1
  153. package/lib/services/proxy.d.ts +74 -0
  154. package/lib/services/proxy.js +126 -0
  155. package/lib/services/proxy.js.map +1 -0
  156. package/lib/services/proxy.spec.d.ts +1 -0
  157. package/lib/services/proxy.spec.js +59 -0
  158. package/lib/services/proxy.spec.js.map +1 -0
  159. package/lib/services/resource.d.ts +2 -2
  160. package/lib/services/resource.js +12 -18
  161. package/lib/services/resource.js.map +1 -1
  162. package/lib/services/resource.spec.js +67 -99
  163. package/lib/services/resource.spec.js.map +1 -1
  164. package/lib/services/service.d.ts +29 -6
  165. package/lib/services/service.js +69 -39
  166. package/lib/services/service.js.map +1 -1
  167. package/lib/services/service.spec.js +62 -67
  168. package/lib/services/service.spec.js.map +1 -1
  169. package/lib/services/version.d.ts +1 -1
  170. package/lib/services/version.js +3 -8
  171. package/lib/services/version.js.map +1 -1
  172. package/lib/services/version.spec.js +11 -24
  173. package/lib/services/version.spec.js.map +1 -1
  174. package/lib/stores/aggregator.d.ts +3 -3
  175. package/lib/stores/aggregator.js +37 -57
  176. package/lib/stores/aggregator.js.map +1 -1
  177. package/lib/stores/file.d.ts +3 -3
  178. package/lib/stores/file.js +93 -131
  179. package/lib/stores/file.js.map +1 -1
  180. package/lib/stores/file.spec.d.ts +2 -2
  181. package/lib/stores/file.spec.js +262 -289
  182. package/lib/stores/file.spec.js.map +1 -1
  183. package/lib/stores/mapper.d.ts +4 -4
  184. package/lib/stores/mapper.js +111 -137
  185. package/lib/stores/mapper.js.map +1 -1
  186. package/lib/stores/mapper.spec.js +133 -150
  187. package/lib/stores/mapper.spec.js.map +1 -1
  188. package/lib/stores/memory.d.ts +67 -6
  189. package/lib/stores/memory.js +155 -117
  190. package/lib/stores/memory.js.map +1 -1
  191. package/lib/stores/memory.spec.d.ts +3 -2
  192. package/lib/stores/memory.spec.js +127 -105
  193. package/lib/stores/memory.spec.js.map +1 -1
  194. package/lib/stores/store.d.ts +40 -16
  195. package/lib/stores/store.js +847 -830
  196. package/lib/stores/store.js.map +1 -1
  197. package/lib/stores/store.spec.d.ts +6 -4
  198. package/lib/stores/store.spec.js +628 -647
  199. package/lib/stores/store.spec.js.map +1 -1
  200. package/lib/stores/webdaql/WebdaQLLexer.d.ts +4 -4
  201. package/lib/stores/webdaql/WebdaQLLexer.js +9 -13
  202. package/lib/stores/webdaql/WebdaQLLexer.js.map +1 -1
  203. package/lib/stores/webdaql/WebdaQLParserLexer.d.ts +4 -4
  204. package/lib/stores/webdaql/WebdaQLParserLexer.js +9 -13
  205. package/lib/stores/webdaql/WebdaQLParserLexer.js.map +1 -1
  206. package/lib/stores/webdaql/WebdaQLParserListener.d.ts +2 -2
  207. package/lib/stores/webdaql/WebdaQLParserListener.js +1 -2
  208. package/lib/stores/webdaql/WebdaQLParserListener.js.map +1 -1
  209. package/lib/stores/webdaql/WebdaQLParserParser.d.ts +10 -10
  210. package/lib/stores/webdaql/WebdaQLParserParser.js +62 -91
  211. package/lib/stores/webdaql/WebdaQLParserParser.js.map +1 -1
  212. package/lib/stores/webdaql/WebdaQLParserVisitor.d.ts +2 -2
  213. package/lib/stores/webdaql/WebdaQLParserVisitor.js +1 -2
  214. package/lib/stores/webdaql/WebdaQLParserVisitor.js.map +1 -1
  215. package/lib/stores/webdaql/query.d.ts +4 -5
  216. package/lib/stores/webdaql/query.js +16 -19
  217. package/lib/stores/webdaql/query.js.map +1 -1
  218. package/lib/stores/webdaql/query.spec.js +30 -32
  219. package/lib/stores/webdaql/query.spec.js.map +1 -1
  220. package/lib/test.d.ts +3 -3
  221. package/lib/test.js +74 -94
  222. package/lib/test.js.map +1 -1
  223. package/lib/unpackedapplication.d.ts +1 -1
  224. package/lib/unpackedapplication.js +44 -38
  225. package/lib/unpackedapplication.js.map +1 -1
  226. package/lib/utils/abstractdeployer.js +1 -5
  227. package/lib/utils/abstractdeployer.js.map +1 -1
  228. package/lib/utils/abstractdeployer.spec.js +6 -8
  229. package/lib/utils/abstractdeployer.spec.js.map +1 -1
  230. package/lib/utils/context.d.ts +61 -29
  231. package/lib/utils/context.js +133 -127
  232. package/lib/utils/context.js.map +1 -1
  233. package/lib/utils/context.spec.js +144 -153
  234. package/lib/utils/context.spec.js.map +1 -1
  235. package/lib/utils/cookie.d.ts +66 -45
  236. package/lib/utils/cookie.js +69 -158
  237. package/lib/utils/cookie.js.map +1 -1
  238. package/lib/utils/cookie.spec.js +220 -238
  239. package/lib/utils/cookie.spec.js.map +1 -1
  240. package/lib/utils/esm.d.ts +4 -0
  241. package/lib/utils/esm.js +10 -0
  242. package/lib/utils/esm.js.map +1 -0
  243. package/lib/utils/httpcontext.d.ts +3 -0
  244. package/lib/utils/httpcontext.js +48 -65
  245. package/lib/utils/httpcontext.js.map +1 -1
  246. package/lib/utils/httpcontext.spec.js +37 -56
  247. package/lib/utils/httpcontext.spec.js.map +1 -1
  248. package/lib/utils/logger.d.ts +2 -2
  249. package/lib/utils/logger.js +15 -28
  250. package/lib/utils/logger.js.map +1 -1
  251. package/lib/utils/logger.spec.js +9 -11
  252. package/lib/utils/logger.spec.js.map +1 -1
  253. package/lib/utils/serializers.js +17 -20
  254. package/lib/utils/serializers.js.map +1 -1
  255. package/lib/utils/serializers.spec.js +43 -44
  256. package/lib/utils/serializers.spec.js.map +1 -1
  257. package/lib/utils/session.d.ts +120 -0
  258. package/lib/utils/session.js +155 -0
  259. package/lib/utils/session.js.map +1 -0
  260. package/lib/utils/session.spec.d.ts +1 -0
  261. package/lib/utils/session.spec.js +66 -0
  262. package/lib/utils/session.spec.js.map +1 -0
  263. package/lib/utils/waiter.d.ts +1 -1
  264. package/lib/utils/waiter.js +32 -52
  265. package/lib/utils/waiter.js.map +1 -1
  266. package/lib/utils/waiter.spec.js +75 -92
  267. package/lib/utils/waiter.spec.js.map +1 -1
  268. package/package.json +22 -14
  269. package/test/config-invitation.json +1 -3
  270. package/test/config.json +3 -3
  271. package/test/config.old.json +1 -2
  272. package/test/moddas/annotatedservice.js +5 -5
  273. package/test/moddas/debugmailer.js +2 -3
  274. package/test/moddas/fakeservice.js +2 -3
  275. package/test/moddas/voidstore.js +6 -4
  276. package/test/models/ident.js +2 -6
  277. package/test/models/task.js +3 -7
  278. package/test/package.json +2 -1
  279. package/webda.module.json +895 -189
@@ -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
  }
@@ -750,6 +644,26 @@ class Store extends service_1.Service {
750
644
  throw new UpdateConditionFailError(model.getUuid(), `${collection}[${index}].${conditionField}`, condition);
751
645
  }
752
646
  }
647
+ /**
648
+ * Update conditionally
649
+ * @param uuid
650
+ * @param updates
651
+ * @param conditionField
652
+ * @param condition
653
+ */
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;
663
+ }
664
+ throw err;
665
+ }
666
+ }
753
667
  /**
754
668
  *
755
669
  * @param model
@@ -760,26 +674,24 @@ class Store extends service_1.Service {
760
674
  * @param itemWriteConditionField
761
675
  * @param updateDate
762
676
  */
763
- simulateUpsertItemToCollection(model, prop, item, updateDate, index, itemWriteCondition, itemWriteConditionField) {
764
- return __awaiter(this, void 0, void 0, function* () {
765
- if (prop === "__proto__") {
766
- throw new Error("Cannot update __proto__: js/prototype-polluting-assignment");
767
- }
768
- this.checkCollectionUpdateCondition(model, prop, itemWriteConditionField, itemWriteCondition, index);
769
- if (index === undefined) {
770
- if (model[prop] === undefined) {
771
- model[prop] = [item];
772
- }
773
- else {
774
- model[prop].push(item);
775
- }
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];
776
685
  }
777
686
  else {
778
- model[prop][index] = item;
687
+ model[prop].push(item);
779
688
  }
780
- model[this._lastUpdateField] = updateDate;
781
- yield this._save(model);
782
- });
689
+ }
690
+ else {
691
+ model[prop][index] = item;
692
+ }
693
+ model[this._lastUpdateField] = updateDate;
694
+ await this._save(model);
783
695
  }
784
696
  /**
785
697
  * Update an object
@@ -790,88 +702,90 @@ class Store extends service_1.Service {
790
702
  * @param {Boolean} reverseMap internal use only, for disable map resolution
791
703
  * @return {Promise} with saved object
792
704
  */
793
- update(object, reverseMap = true, partial = false) {
794
- var _a, _b;
795
- return __awaiter(this, void 0, void 0, function* () {
796
- /** @ignore */
797
- var saved;
798
- var loaded;
799
- // Dont allow to update collections from map
800
- if (this._reverseMap != undefined && reverseMap) {
801
- for (let i in this._reverseMap) {
802
- if (object[this._reverseMap[i].property] != undefined) {
803
- delete object[this._reverseMap[i].property];
804
- }
805
- }
806
- }
807
- if (Object.keys(object).length < 2) {
808
- return undefined;
809
- }
810
- object[this._lastUpdateField] = new Date();
811
- this.metrics.get++;
812
- let load = yield this._getFromCache(object[this._uuidField], true);
813
- if (load.__type !== this._model.name && this.parameters.strict) {
814
- this.log("WARN", `Object '${object[this._uuidField]}' was not created by this store`);
815
- throw new StoreNotFoundError(object[this._uuidField], this.getName());
816
- }
817
- loaded = this.initModel(load);
818
- if (object instanceof coremodel_1.CoreModel) {
819
- loaded.setContext(object.getContext());
820
- }
821
- if (partial) {
822
- yield this.emitSync(`Store.PatchUpdate`, {
823
- object: loaded,
824
- store: this,
825
- update: object
826
- });
827
- }
828
- else {
829
- yield this.emitSync(`Store.Update`, {
830
- object: loaded,
831
- store: this,
832
- update: object
833
- });
834
- }
835
- yield loaded._onUpdate(object);
836
- let res;
837
- if (partial) {
838
- this.metrics.partialUpdate++;
839
- yield this._patch(object, object[this._uuidField], load[this._lastUpdateField], this._lastUpdateField);
840
- yield ((_a = this._cacheStore) === null || _a === void 0 ? void 0 : _a._patch(object, object[this._uuidField], load[this._lastUpdateField], this._lastUpdateField));
841
- res = object;
842
- }
843
- else {
844
- // Copy back the mappers
845
- for (let i in this._reverseMap) {
846
- 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];
847
714
  }
848
- this.metrics.update++;
849
- res = yield this._update(object, object[this._uuidField], load[this._lastUpdateField], this._lastUpdateField);
850
- yield ((_b = this._cacheStore) === null || _b === void 0 ? void 0 : _b._update(object, object[this._uuidField], load[this._lastUpdateField], this._lastUpdateField));
851
- }
852
- // Return updated
853
- for (let i in res) {
854
- loaded[i] = res[i];
855
- }
856
- for (let i in object) {
857
- loaded[i] = object[i];
858
715
  }
859
- saved = this.initModel(loaded);
860
- if (partial) {
861
- yield this.emitSync(`Store.PatchUpdated`, {
862
- object: saved,
863
- store: this
864
- });
865
- }
866
- else {
867
- yield this.emitSync(`Store.Updated`, {
868
- object: saved,
869
- store: this
870
- });
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];
871
761
  }
872
- yield saved._onUpdated();
873
- return saved;
874
- });
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;
875
789
  }
876
790
  /**
877
791
  * Remove an attribute from an object
@@ -880,18 +794,15 @@ class Store extends service_1.Service {
880
794
  * @param attribute
881
795
  * @returns
882
796
  */
883
- removeAttribute(uuid, attribute, itemWriteCondition, itemWriteConditionField) {
884
- var _a;
885
- return __awaiter(this, void 0, void 0, function* () {
886
- this.metrics.attributeDelete++;
887
- yield this._removeAttribute(uuid, attribute, itemWriteCondition, itemWriteConditionField);
888
- yield ((_a = this._cacheStore) === null || _a === void 0 ? void 0 : _a._removeAttribute(uuid, attribute, itemWriteCondition, itemWriteConditionField));
889
- yield this.emitSync("Store.PartialUpdated", {
890
- object_id: uuid,
891
- partial_update: {
892
- deleteAttribute: attribute
893
- }
894
- });
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
+ }
895
806
  });
896
807
  }
897
808
  /**
@@ -901,21 +812,17 @@ class Store extends service_1.Service {
901
812
  * @param uuid
902
813
  * @returns
903
814
  */
904
- cascadeDelete(obj, _uuid) {
905
- return __awaiter(this, void 0, void 0, function* () {
906
- // We dont need uuid but Binary store will need it
907
- return this.delete(obj.getUuid());
908
- });
815
+ async cascadeDelete(obj, _uuid) {
816
+ // We dont need uuid but Binary store will need it
817
+ return this.delete(obj.getUuid());
909
818
  }
910
819
  /**
911
820
  * Delete an object from the store without condition nor async
912
821
  * @param uid to delete
913
822
  * @returns
914
823
  */
915
- forceDelete(uid) {
916
- return __awaiter(this, void 0, void 0, function* () {
917
- return this.delete(uid, undefined, undefined, true);
918
- });
824
+ async forceDelete(uid) {
825
+ return this.delete(uid, undefined, undefined, true);
919
826
  }
920
827
  /**
921
828
  * Delete an object
@@ -924,62 +831,59 @@ class Store extends service_1.Service {
924
831
  * @param {Boolean} delete sync even if asyncDelete is active
925
832
  * @return {Promise} the deletion promise
926
833
  */
927
- delete(uid, writeCondition, writeConditionField, sync = false) {
928
- var _a, _b;
929
- return __awaiter(this, void 0, void 0, function* () {
930
- /** @ignore */
931
- let to_delete;
932
- // Allow full object or just its uuid
933
- if (typeof uid === "object") {
934
- to_delete = uid;
935
- }
936
- else {
937
- this.metrics.get++;
938
- to_delete = yield this._getFromCache(uid);
939
- if (to_delete === undefined) {
940
- return;
941
- }
942
- if (to_delete.__type !== this._model.name && this.parameters.strict) {
943
- this.log("WARN", `Object '${uid}' was not created by this store`);
944
- return;
945
- }
946
- to_delete = this.initModel(to_delete);
947
- }
948
- // Check condition as we have the object
949
- if (writeCondition) {
950
- if (to_delete[writeConditionField] !== writeCondition) {
951
- throw new UpdateConditionFailError(to_delete.getUuid(), writeConditionField, writeCondition);
952
- }
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;
953
846
  }
954
- // Send preevent
955
- yield this.emitSync("Store.Delete", {
956
- object: to_delete,
957
- store: this
958
- });
959
- yield to_delete._onDelete();
960
- // If async we just tag the object as deleted
961
- if (this.parameters.asyncDelete && !sync) {
962
- this.metrics.partialUpdate++;
963
- yield this._patch({
964
- __deleted: true
965
- }, to_delete.getUuid());
966
- yield ((_a = this._cacheStore) === null || _a === void 0 ? void 0 : _a._patch({
967
- __deleted: true
968
- }, 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;
969
850
  }
970
- else {
971
- this.metrics.delete++;
972
- // Delete from the DB for real
973
- yield this._delete(to_delete.getUuid(), writeCondition, writeConditionField);
974
- 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);
975
857
  }
976
- // Send post event
977
- yield this.emitSync("Store.Deleted", {
978
- object: to_delete,
979
- store: this
980
- });
981
- 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
982
885
  });
886
+ await to_delete._onDeleted();
983
887
  }
984
888
  /**
985
889
  * By default we cannot know if the store will trigger or not
@@ -995,22 +899,31 @@ class Store extends service_1.Service {
995
899
  * @param {string} id
996
900
  * @returns {Promise<Map<string, any>>}
997
901
  */
998
- getConfiguration(id) {
999
- return __awaiter(this, void 0, void 0, function* () {
1000
- this.metrics.get++;
1001
- let object = yield this._getFromCache(id);
1002
- if (!object) {
1003
- return undefined;
1004
- }
1005
- let result = {};
1006
- for (let i in object) {
1007
- if (i === this._uuidField || i === this._lastUpdateField || i.startsWith("_")) {
1008
- continue;
1009
- }
1010
- 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;
1011
912
  }
1012
- return result;
1013
- });
913
+ result[i] = object[i];
914
+ }
915
+ return result;
916
+ }
917
+ /**
918
+ * Upsert the uuid object
919
+ * @param uuid
920
+ * @param data
921
+ */
922
+ async put(uuid, data) {
923
+ if (await this.exists(uuid)) {
924
+ return this.update({ ...data, uuid });
925
+ }
926
+ return this.save({ ...data, uuid });
1014
927
  }
1015
928
  /**
1016
929
  * Get an object
@@ -1018,31 +931,29 @@ class Store extends service_1.Service {
1018
931
  * @param {String} uuid to get
1019
932
  * @return {Promise} the object retrieved ( can be undefined if not found )
1020
933
  */
1021
- get(uid, ctx = undefined) {
1022
- return __awaiter(this, void 0, void 0, function* () {
1023
- /** @ignore */
1024
- if (!uid) {
1025
- return undefined;
1026
- }
1027
- this.metrics.get++;
1028
- let object = yield this._getFromCache(uid);
1029
- if (!object) {
1030
- return undefined;
1031
- }
1032
- if (object.__type !== this._model.name && this.parameters.strict) {
1033
- this.log("WARN", `Object '${uid}' was not created by this store`);
1034
- return undefined;
1035
- }
1036
- object = this.initModel(object);
1037
- object.setContext(ctx);
1038
- yield this.emitSync("Store.Get", {
1039
- object: object,
1040
- store: this,
1041
- context: ctx
1042
- });
1043
- yield object._onGet();
1044
- 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
1045
954
  });
955
+ await object._onGet();
956
+ return object;
1046
957
  }
1047
958
  /**
1048
959
  * Set one attribute in an object
@@ -1054,159 +965,154 @@ class Store extends service_1.Service {
1054
965
  * @param value new value
1055
966
  * @returns
1056
967
  */
1057
- setAttribute(uid, property, value) {
1058
- return __awaiter(this, void 0, void 0, function* () {
1059
- let patch = {};
1060
- patch[property] = value;
1061
- patch[this.getUuidField()] = uid;
1062
- yield this.patch(patch);
1063
- });
968
+ async setAttribute(uid, property, value) {
969
+ let patch = {};
970
+ patch[property] = value;
971
+ patch[this.getUuidField()] = uid;
972
+ await this.patch(patch);
1064
973
  }
1065
974
  /**
1066
975
  * @override
1067
976
  */
1068
- simulateFind(query, uuids) {
1069
- return __awaiter(this, void 0, void 0, function* () {
1070
- let result = {
1071
- results: [],
1072
- continuationToken: undefined,
1073
- filter: true
1074
- };
1075
- let count = 0;
1076
- let limit = query.limit;
1077
- let offset = parseInt(query.continuationToken || "0");
1078
- let originalOffset = offset;
1079
- if (query.orderBy && query.orderBy.length) {
1080
- offset = 0;
1081
- // We need to retrieve everything to orderBy after
1082
- 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;
1083
998
  }
1084
- // Need to transfert to Array
1085
- for (let uuid of uuids) {
1086
- count++;
1087
- // Offset start
1088
- if (offset >= count) {
1089
- continue;
1090
- }
1091
- let obj = yield this._getFromCache(uuid);
1092
- if (obj && query.filter.eval(obj)) {
1093
- result.results.push(obj);
1094
- if (result.results.length >= limit) {
1095
- result.continuationToken = count.toString();
1096
- return result;
1097
- }
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;
1098
1005
  }
1099
1006
  }
1100
- // Order by
1101
- if (query.orderBy && query.orderBy.length) {
1102
- // Sorting the results
1103
- result.results.sort((a, b) => {
1104
- let valA, valB;
1105
- for (let orderBy of query.orderBy) {
1106
- let invert = orderBy.direction === "ASC" ? 1 : -1;
1107
- valA = query_1.WebdaQL.ComparisonExpression.getAttributeValue(a, orderBy.field.split("."));
1108
- valB = query_1.WebdaQL.ComparisonExpression.getAttributeValue(b, orderBy.field.split("."));
1109
- if (valA === valB) {
1110
- continue;
1111
- }
1112
- if (typeof valA === "string") {
1113
- return valA.localeCompare(valB) * invert;
1114
- }
1115
- 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;
1116
1019
  }
1117
- return -1;
1118
- });
1119
- result.results = result.results.slice(originalOffset, query.limit + originalOffset);
1120
- if (result.results.length >= query.limit) {
1121
- 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;
1122
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();
1123
1030
  }
1124
- return result;
1125
- });
1031
+ }
1032
+ return result;
1033
+ }
1034
+ getOpenApiReplacements() {
1035
+ return {
1036
+ modelName: this._model.name
1037
+ };
1126
1038
  }
1127
1039
  /**
1128
1040
  * Handle POST
1129
1041
  * @param ctx
1130
1042
  */
1131
- httpCreate(ctx) {
1132
- return __awaiter(this, void 0, void 0, function* () {
1133
- let body = yield ctx.getRequestBody();
1134
- let object = this._model.factory(this._model, body, ctx);
1135
- object[this._creationDateField] = new Date();
1136
- yield object.canAct(ctx, "create");
1137
- try {
1138
- yield object.validate(ctx, body);
1139
- }
1140
- catch (err) {
1141
- this.log("INFO", "Object is not valid", err);
1142
- throw 400;
1143
- }
1144
- if (object[this._uuidField] && (yield this.exists(object[this._uuidField]))) {
1145
- throw 409;
1146
- }
1147
- yield this.save(object, ctx);
1148
- ctx.write(object);
1149
- yield this.emitSync("Store.WebCreate", {
1150
- context: ctx,
1151
- values: body,
1152
- object: object,
1153
- store: this
1154
- });
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
1155
1065
  });
1156
1066
  }
1157
1067
  /**
1158
1068
  * Handle obect action
1159
1069
  * @param ctx
1160
1070
  */
1161
- httpAction(ctx) {
1162
- return __awaiter(this, void 0, void 0, function* () {
1163
- let action = ctx.getHttpContext().getUrl().split("/").pop();
1164
- let object = yield this.get(ctx.parameter("uuid"), ctx);
1165
- if (object === undefined || object.__deleted) {
1166
- throw 404;
1167
- }
1168
- yield object.canAct(ctx, action);
1169
- yield this.emitSync("Store.Action", {
1170
- action: action,
1171
- object: object,
1172
- store: this,
1173
- context: ctx
1174
- });
1175
- let res = yield object["_" + action](ctx);
1176
- if (res) {
1177
- ctx.write(res);
1178
- }
1179
- yield this.emitSync("Store.Actioned", {
1180
- action: action,
1181
- object: object,
1182
- store: this,
1183
- context: ctx,
1184
- result: res
1185
- });
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
1186
1094
  });
1187
1095
  }
1188
1096
  /**
1189
1097
  * Handle collection action
1190
1098
  * @param ctx
1191
1099
  */
1192
- httpGlobalAction(ctx) {
1193
- return __awaiter(this, void 0, void 0, function* () {
1194
- let action = ctx.getHttpContext().getUrl().split("/").pop();
1195
- yield this.emitSync("Store.Action", {
1196
- action: action,
1197
- store: this,
1198
- context: ctx
1199
- });
1200
- let res = yield this._model["_" + action](ctx);
1201
- if (res) {
1202
- ctx.write(res);
1203
- }
1204
- yield this.emitSync("Store.Actioned", {
1205
- action: action,
1206
- store: this,
1207
- context: ctx,
1208
- result: res
1209
- });
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
1210
1116
  });
1211
1117
  }
1212
1118
  /**
@@ -1214,62 +1120,60 @@ class Store extends service_1.Service {
1214
1120
  *
1215
1121
  * @param ctx context of the request
1216
1122
  */
1217
- httpUpdate(ctx) {
1218
- return __awaiter(this, void 0, void 0, function* () {
1219
- let body = yield ctx.getRequestBody();
1220
- let uuid = ctx.parameter("uuid");
1221
- body[this._uuidField] = uuid;
1222
- let object = yield this.get(uuid, ctx);
1223
- if (!object || object.__deleted)
1224
- throw 404;
1225
- yield object.canAct(ctx, "update");
1226
- if (ctx.getHttpContext().getMethod() === "PATCH") {
1227
- try {
1228
- yield object.validate(ctx, body);
1229
- }
1230
- catch (err) {
1231
- this.log("INFO", "Object invalid", err);
1232
- throw 400;
1233
- }
1234
- let updateObject = new this._model();
1235
- // Clean any default attributes from the model
1236
- Object.keys(updateObject)
1237
- .filter(i => i !== "__class")
1238
- .forEach(i => {
1239
- delete updateObject[i];
1240
- });
1241
- updateObject.setContext(ctx);
1242
- updateObject.load(body);
1243
- yield this.patch(updateObject);
1244
- 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);
1245
1134
  }
1246
- else {
1247
- let updateObject = new this._model();
1248
- updateObject.load(body);
1249
- // Copy back the _ attributes
1250
- Object.keys(object)
1251
- .filter(i => i.startsWith("_"))
1252
- .forEach(i => {
1253
- updateObject[i] = object[i];
1254
- });
1255
- try {
1256
- yield updateObject.validate(ctx, body);
1257
- }
1258
- catch (err) {
1259
- this.log("INFO", "Object invalid", err);
1260
- throw 400;
1261
- }
1262
- // Add mappers back to
1263
- object = yield this.update(updateObject);
1135
+ catch (err) {
1136
+ this.log("INFO", "Object invalid", err);
1137
+ throw 400;
1264
1138
  }
1265
- ctx.write(object);
1266
- yield this.emitSync("Store.WebUpdate", {
1267
- context: ctx,
1268
- updates: body,
1269
- object: object,
1270
- store: this,
1271
- 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];
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];
1272
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()
1273
1177
  });
1274
1178
  }
1275
1179
  /**
@@ -1277,32 +1181,25 @@ class Store extends service_1.Service {
1277
1181
  *
1278
1182
  * @param ctx context of the request
1279
1183
  */
1280
- httpGet(ctx) {
1281
- return __awaiter(this, void 0, void 0, function* () {
1282
- let uuid = ctx.parameter("uuid");
1283
- if (uuid) {
1284
- let object = yield this.get(uuid, ctx);
1285
- yield this.emitSync("Store.WebGetNotFound", {
1286
- context: ctx,
1287
- uuid,
1288
- store: this
1289
- });
1290
- if (object === undefined || object.__deleted) {
1291
- throw 404;
1292
- }
1293
- yield object.canAct(ctx, "get");
1294
- ctx.write(object);
1295
- yield this.emitSync("Store.WebGet", {
1296
- context: ctx,
1297
- object: object,
1298
- store: this
1299
- });
1300
- ctx.write(object);
1301
- }
1302
- else {
1303
- // List probably
1304
- }
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
1305
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);
1306
1203
  }
1307
1204
  /**
1308
1205
  * Handle HTTP request
@@ -1310,31 +1207,21 @@ class Store extends service_1.Service {
1310
1207
  * @param ctx context of the request
1311
1208
  * @returns
1312
1209
  */
1313
- httpRoute(ctx) {
1314
- return __awaiter(this, void 0, void 0, function* () {
1315
- let uuid = ctx.parameter("uuid");
1316
- if (ctx.getHttpContext().getMethod() == "GET") {
1317
- return this.httpGet(ctx);
1318
- }
1319
- else if (ctx.getHttpContext().getMethod() == "DELETE") {
1320
- let object = yield this.get(uuid, ctx);
1321
- if (!object || object.__deleted)
1322
- throw 404;
1323
- yield object.canAct(ctx, "delete");
1324
- // http://stackoverflow.com/questions/28684209/huge-delay-on-delete-requests-with-204-response-and-no-content-in-objectve-c#
1325
- // IOS don't handle 204 with Content-Length != 0 it seems
1326
- // Have trouble to handle the Content-Length on API Gateway so returning an empty object for now
1327
- ctx.write({});
1328
- yield this.delete(uuid);
1329
- yield this.emitSync("Store.WebDelete", {
1330
- context: ctx,
1331
- object_id: uuid,
1332
- store: this
1333
- });
1334
- }
1335
- else if (ctx.getHttpContext().getMethod() === "PUT" || ctx.getHttpContext().getMethod() === "PATCH") {
1336
- return this.httpUpdate(ctx);
1337
- }
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
1338
1225
  });
1339
1226
  }
1340
1227
  /**
@@ -1344,5 +1231,135 @@ class Store extends service_1.Service {
1344
1231
  return this._uuidField;
1345
1232
  }
1346
1233
  }
1347
- 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: "updatet${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 };
1348
1365
  //# sourceMappingURL=store.js.map