@webda/core 2.0.0-beta.1 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (279) hide show
  1. package/lib/application.d.ts +9 -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 +86 -46
  7. package/lib/core.js +254 -316
  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 +127 -151
  18. package/lib/models/aclmodel.spec.js.map +1 -1
  19. package/lib/models/coremodel.d.ts +84 -11
  20. package/lib/models/coremodel.js +104 -103
  21. package/lib/models/coremodel.js.map +1 -1
  22. package/lib/models/coremodel.spec.js +91 -91
  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 +5 -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 +12 -2
  31. package/lib/models/ownermodel.js +54 -62
  32. package/lib/models/ownermodel.js.map +1 -1
  33. package/lib/models/ownermodel.spec.js +129 -152
  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 +5 -5
  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 +7 -3
  65. package/lib/router.js +49 -48
  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 +539 -571
  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 -244
  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 +46 -71
  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 +15 -5
  118. package/lib/services/filebinary.js +171 -200
  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 +9 -9
  129. package/lib/services/invitationservice.js +275 -313
  130. package/lib/services/invitationservice.js.map +1 -1
  131. package/lib/services/invitationservice.spec.js +442 -448
  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 -147
  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 +33 -7
  165. package/lib/services/service.js +74 -42
  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 +261 -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 +112 -137
  185. package/lib/stores/mapper.js.map +1 -1
  186. package/lib/stores/mapper.spec.js +131 -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 +35 -15
  195. package/lib/stores/store.js +839 -821
  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 +627 -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 +25 -31
  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 +147 -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 +37 -9
  244. package/lib/utils/httpcontext.js +86 -57
  245. package/lib/utils/httpcontext.js.map +1 -1
  246. package/lib/utils/httpcontext.spec.js +37 -48
  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 +956 -188
@@ -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,20 +334,17 @@ 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
- let model = new this._model();
436
- model.load(object, true);
437
- object = model;
339
+ object = this._model.factory(this._model, object);
438
340
  }
439
341
  if (!object.getUuid()) {
440
342
  object.setUuid(object.generateUid(object));
441
343
  }
442
344
  object.__store = this;
443
- for (var i in this._reverseMap) {
444
- (_a = object[_b = this._reverseMap[i].property]) !== null && _a !== void 0 ? _a : (object[_b] = []);
445
- 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]) {
446
348
  // Use Partial
447
349
  object[this._reverseMap[i].property][j] = this._reverseMap[i].mapper.initModel(object[this._reverseMap[i].property][j]);
448
350
  object[this._reverseMap[i].property][j].setContext(object.getContext());
@@ -463,72 +365,63 @@ class Store extends service_1.Service {
463
365
  mapper: store
464
366
  });
465
367
  }
466
- incrementAttribute(uid, prop, value) {
467
- var _a;
468
- return __awaiter(this, void 0, void 0, function* () {
469
- // If value === 0 no need to update anything
470
- if (value === 0) {
471
- return Promise.resolve();
472
- }
473
- let updateDate = new Date();
474
- this.metrics.increment++;
475
- yield this._incrementAttribute(uid, prop, value, updateDate);
476
- yield ((_a = this._cacheStore) === null || _a === void 0 ? void 0 : _a._incrementAttribute(uid, prop, value, updateDate));
477
- return this.emitSync("Store.PartialUpdated", {
478
- object_id: uid,
479
- store: this,
480
- updateDate,
481
- partial_update: {
482
- increment: {
483
- value: value,
484
- property: prop
485
- }
368
+ async incrementAttribute(uid, prop, value) {
369
+ // If value === 0 no need to update anything
370
+ if (value === 0) {
371
+ return Promise.resolve();
372
+ }
373
+ let updateDate = new Date();
374
+ this.metrics.increment++;
375
+ await this._incrementAttribute(uid, prop, value, updateDate);
376
+ await this._cacheStore?._incrementAttribute(uid, prop, value, updateDate);
377
+ return this.emitSync("Store.PartialUpdated", {
378
+ object_id: uid,
379
+ store: this,
380
+ updateDate,
381
+ partial_update: {
382
+ increment: {
383
+ value: value,
384
+ property: prop
486
385
  }
487
- });
386
+ }
488
387
  });
489
388
  }
490
- upsertItemToCollection(uid, prop, item, index = undefined, itemWriteCondition = undefined, itemWriteConditionField = undefined) {
491
- var _a;
492
- return __awaiter(this, void 0, void 0, function* () {
493
- if (itemWriteConditionField === undefined) {
494
- itemWriteConditionField = this._uuidField;
495
- }
496
- let updateDate = new Date();
497
- this.metrics.collectionUpsert++;
498
- yield this._upsertItemToCollection(uid, prop, item, index, itemWriteCondition, itemWriteConditionField, updateDate);
499
- yield ((_a = this._cacheStore) === null || _a === void 0 ? void 0 : _a._upsertItemToCollection(uid, prop, item, index, itemWriteCondition, itemWriteConditionField, updateDate));
500
- yield this.emitSync("Store.PartialUpdated", {
501
- object_id: uid,
502
- store: this,
503
- updateDate,
504
- partial_update: {
505
- addItem: {
506
- value: item,
507
- property: prop,
508
- index: index
509
- }
389
+ async upsertItemToCollection(uid, prop, item, index = undefined, itemWriteCondition = undefined, itemWriteConditionField = undefined) {
390
+ if (itemWriteConditionField === undefined) {
391
+ itemWriteConditionField = this._uuidField;
392
+ }
393
+ let updateDate = new Date();
394
+ this.metrics.collectionUpsert++;
395
+ await this._upsertItemToCollection(uid, prop, item, index, itemWriteCondition, itemWriteConditionField, updateDate);
396
+ await this._cacheStore?._upsertItemToCollection(uid, prop, item, index, itemWriteCondition, itemWriteConditionField, updateDate);
397
+ await this.emitSync("Store.PartialUpdated", {
398
+ object_id: uid,
399
+ store: this,
400
+ updateDate,
401
+ partial_update: {
402
+ addItem: {
403
+ value: item,
404
+ property: prop,
405
+ index: index
510
406
  }
511
- });
407
+ }
512
408
  });
513
409
  }
514
- deleteItemFromCollection(uid, prop, index, itemWriteCondition, itemWriteConditionField = this._uuidField) {
515
- var _a;
516
- return __awaiter(this, void 0, void 0, function* () {
517
- let updateDate = new Date();
518
- this.metrics.collectionDelete++;
519
- yield this._deleteItemFromCollection(uid, prop, index, itemWriteCondition, itemWriteConditionField, updateDate);
520
- yield ((_a = this._cacheStore) === null || _a === void 0 ? void 0 : _a._deleteItemFromCollection(uid, prop, index, itemWriteCondition, itemWriteConditionField, updateDate));
521
- yield this.emitSync("Store.PartialUpdated", {
522
- object_id: uid,
523
- store: this,
524
- updateDate,
525
- partial_update: {
526
- deleteItem: {
527
- property: prop,
528
- index: index
529
- }
410
+ async deleteItemFromCollection(uid, prop, index, itemWriteCondition, itemWriteConditionField = this._uuidField) {
411
+ let updateDate = new Date();
412
+ this.metrics.collectionDelete++;
413
+ await this._deleteItemFromCollection(uid, prop, index, itemWriteCondition, itemWriteConditionField, updateDate);
414
+ await this._cacheStore?._deleteItemFromCollection(uid, prop, index, itemWriteCondition, itemWriteConditionField, updateDate);
415
+ await this.emitSync("Store.PartialUpdated", {
416
+ object_id: uid,
417
+ store: this,
418
+ updateDate,
419
+ partial_update: {
420
+ deleteItem: {
421
+ property: prop,
422
+ index: index
530
423
  }
531
- });
424
+ }
532
425
  });
533
426
  }
534
427
  /**
@@ -536,121 +429,132 @@ class Store extends service_1.Service {
536
429
  * @param query
537
430
  * @param context to apply permission
538
431
  */
539
- query(query, context) {
540
- return __awaiter(this, void 0, void 0, function* () {
541
- let queryValidator = new query_1.WebdaQL.QueryValidator(query);
542
- let offset = queryValidator.getOffset();
543
- const limit = queryValidator.getLimit();
544
- const parsedQuery = queryValidator.getQuery();
545
- // Emit the default event
546
- yield this.emitSync("Store.Query", {
547
- query,
548
- parsedQuery,
549
- store: this,
550
- context
551
- });
552
- const result = {
553
- results: [],
554
- continuationToken: undefined
555
- };
556
- /*
557
- Offset are split in two with _
558
-
559
- MainOffset is the database offset, retrieving a page from the database
560
- SubOffset is the offset within the page
561
-
562
- As we filter through the page, for additional filters or permissions, the page cut
563
- by database does not endup being our final page cut, so we need a page offset to
564
- abstract this completely
565
- */
566
- let [mainOffset, subOffset] = offset.split("_");
567
- let secondOffset = parseInt(subOffset || "0");
568
- let duration = Date.now();
569
- this.metrics.query++;
570
- while (result.results.length < limit) {
571
- let tmpResults = yield this.find(Object.assign(Object.assign({}, parsedQuery), { continuationToken: mainOffset }));
572
- // If no filter is returned assume it is by mistake and apply filtering
573
- if (tmpResults.filter === undefined) {
574
- tmpResults.filter = queryValidator.getExpression();
575
- this.log("WARN", `Store '${this.getName()}' postquery full filtering`);
432
+ async query(query, context) {
433
+ let permissionQuery = this._model.getPermissionQuery(context);
434
+ let partialPermission = true;
435
+ let fullQuery;
436
+ if (permissionQuery) {
437
+ partialPermission = permissionQuery.partial;
438
+ if (query.trim() !== "") {
439
+ fullQuery = `(${permissionQuery.query}) AND ${query}`;
440
+ }
441
+ else {
442
+ fullQuery = permissionQuery.query;
443
+ }
444
+ }
445
+ else {
446
+ fullQuery = query;
447
+ }
448
+ let queryValidator = new WebdaQL.QueryValidator(fullQuery);
449
+ let offset = queryValidator.getOffset();
450
+ const limit = queryValidator.getLimit();
451
+ const parsedQuery = queryValidator.getQuery();
452
+ // Emit the default event
453
+ await this.emitSync("Store.Query", {
454
+ query,
455
+ parsedQuery,
456
+ store: this,
457
+ context
458
+ });
459
+ const result = {
460
+ results: [],
461
+ continuationToken: undefined
462
+ };
463
+ /*
464
+ Offset are split in two with _
465
+
466
+ MainOffset is the database offset, retrieving a page from the database
467
+ SubOffset is the offset within the page
468
+
469
+ As we filter through the page, for additional filters or permissions, the page cut
470
+ by database does not endup being our final page cut, so we need a page offset to
471
+ abstract this completely
472
+ */
473
+ let [mainOffset, subOffset] = offset.split("_");
474
+ let secondOffset = parseInt(subOffset || "0");
475
+ let duration = Date.now();
476
+ this.metrics.query++;
477
+ while (result.results.length < limit) {
478
+ let tmpResults = await this.find({ ...parsedQuery, continuationToken: mainOffset });
479
+ // If no filter is returned assume it is by mistake and apply filtering
480
+ if (tmpResults.filter === undefined) {
481
+ tmpResults.filter = queryValidator.getExpression();
482
+ this.log("WARN", `Store '${this.getName()}' postquery full filtering`);
483
+ }
484
+ let subOffsetCount = 0;
485
+ for (let item of tmpResults.results) {
486
+ // Because of dynamic filter and permission we need to suboffset the pagination
487
+ subOffsetCount++;
488
+ if (subOffsetCount <= secondOffset) {
489
+ continue;
576
490
  }
577
- let subOffsetCount = 0;
578
- for (let item of tmpResults.results) {
579
- // Because of dynamic filter and permission we need to suboffset the pagination
580
- subOffsetCount++;
581
- if (subOffsetCount <= secondOffset) {
582
- continue;
491
+ if (tmpResults.filter !== true && !tmpResults.filter.eval(item)) {
492
+ continue;
493
+ }
494
+ if (context && partialPermission) {
495
+ try {
496
+ await item.canAct(context, "get");
583
497
  }
584
- if (tmpResults.filter !== true && !tmpResults.filter.eval(item)) {
498
+ catch (err) {
585
499
  continue;
586
500
  }
587
- if (context) {
588
- try {
589
- yield item.canAct(context, "get");
590
- }
591
- catch (err) {
592
- continue;
593
- }
501
+ }
502
+ result.results.push(item);
503
+ if (result.results.length >= limit) {
504
+ if (subOffsetCount === tmpResults.results.length) {
505
+ result.continuationToken = tmpResults.continuationToken;
594
506
  }
595
- result.results.push(item);
596
- if (result.results.length >= limit) {
597
- if (subOffsetCount === tmpResults.results.length) {
598
- result.continuationToken = tmpResults.continuationToken;
599
- }
600
- else {
601
- result.continuationToken = `${mainOffset}_${subOffsetCount}`;
602
- }
603
- break;
507
+ else {
508
+ result.continuationToken = `${mainOffset}_${subOffsetCount}`;
604
509
  }
605
- }
606
- // Update both offset
607
- mainOffset = tmpResults.continuationToken;
608
- // Fresh new query so we do not need to skip
609
- secondOffset = 0;
610
- if (mainOffset === undefined || result.results.length >= limit) {
611
510
  break;
612
511
  }
613
512
  }
614
- duration = Date.now() - duration;
615
- this.metrics.queryDuration =
616
- (this.metrics.queryDuration * (this.metrics.query - 1) + duration) / this.metrics.query;
617
- if (duration > this.parameters.slowQueryThreshold) {
618
- this.logSlowQuery(query, "", duration);
513
+ // Update both offset
514
+ mainOffset = tmpResults.continuationToken;
515
+ // Fresh new query so we do not need to skip
516
+ secondOffset = 0;
517
+ if (mainOffset === undefined || result.results.length >= limit) {
518
+ break;
619
519
  }
620
- yield this.emitSync("Store.Queried", {
621
- query,
622
- parsedQuery: parsedQuery,
623
- store: this,
624
- continuationToken: result.continuationToken,
625
- results: result.results,
626
- context
627
- });
628
- return result;
520
+ }
521
+ duration = Date.now() - duration;
522
+ this.metrics.queryDuration =
523
+ (this.metrics.queryDuration * (this.metrics.query - 1) + duration) / this.metrics.query;
524
+ if (duration > this.parameters.slowQueryThreshold) {
525
+ this.logSlowQuery(query, "", duration);
526
+ }
527
+ await this.emitSync("Store.Queried", {
528
+ query,
529
+ parsedQuery: parsedQuery,
530
+ store: this,
531
+ continuationToken: result.continuationToken,
532
+ results: result.results,
533
+ context
629
534
  });
535
+ return result;
630
536
  }
631
537
  /**
632
538
  * Expose query to http
633
539
  */
634
- httpQuery(ctx) {
635
- return __awaiter(this, void 0, void 0, function* () {
636
- let query;
637
- if (ctx.getHttpContext().getMethod() === "GET") {
638
- query = ctx.getParameters().q;
639
- }
640
- else {
641
- query = (yield ctx.getRequestBody()).q;
642
- }
643
- try {
644
- ctx.write(yield this.query(query, ctx));
645
- }
646
- catch (err) {
647
- if (err instanceof SyntaxError) {
648
- this.log("INFO", "Query syntax error");
649
- throw 400;
650
- }
651
- throw err;
540
+ async httpQuery(ctx) {
541
+ let query;
542
+ if (ctx.getHttpContext().getMethod() === "GET") {
543
+ query = ctx.getParameters().q;
544
+ }
545
+ else {
546
+ query = (await ctx.getRequestBody()).q;
547
+ }
548
+ try {
549
+ ctx.write(await this.query(query, ctx));
550
+ }
551
+ catch (err) {
552
+ if (err instanceof SyntaxError) {
553
+ this.log("INFO", "Query syntax error");
554
+ throw 400;
652
555
  }
653
- });
556
+ throw err;
557
+ }
654
558
  }
655
559
  /**
656
560
  * Save an object
@@ -661,36 +565,33 @@ class Store extends service_1.Service {
661
565
  *
662
566
  * Might want to rename to create
663
567
  */
664
- save(object, ctx = undefined) {
665
- var _a, _b;
666
- var _c;
667
- return __awaiter(this, void 0, void 0, function* () {
668
- object = this.initModel(object);
669
- // Dates should be store by the Store
670
- (_a = object[_c = this._creationDateField]) !== null && _a !== void 0 ? _a : (object[_c] = new Date());
671
- object[this._lastUpdateField] = new Date();
672
- if (ctx) {
673
- object.setContext(ctx);
674
- }
675
- yield this.emitSync("Store.Save", {
676
- object: object,
677
- store: this,
678
- context: ctx
679
- });
680
- // Handle object auto listener
681
- yield object._onSave();
682
- this.metrics.save++;
683
- let res = yield this._save(object);
684
- yield ((_b = this._cacheStore) === null || _b === void 0 ? void 0 : _b._save(object));
685
- object = this.initModel(res);
686
- yield this.emitSync("Store.Saved", {
687
- object: object,
688
- store: this,
689
- context: ctx
690
- });
691
- yield object._onSaved();
692
- return object;
568
+ async save(object, ctx = undefined) {
569
+ var _a;
570
+ object = this.initModel(object);
571
+ // Dates should be store by the Store
572
+ object[_a = this._creationDateField] ?? (object[_a] = new Date());
573
+ object[this._lastUpdateField] = new Date();
574
+ if (ctx) {
575
+ object.setContext(ctx);
576
+ }
577
+ await this.emitSync("Store.Save", {
578
+ object: object,
579
+ store: this,
580
+ context: ctx
581
+ });
582
+ // Handle object auto listener
583
+ await object._onSave();
584
+ this.metrics.save++;
585
+ let res = await this._save(object);
586
+ await this._cacheStore?._save(object);
587
+ object = this.initModel(res);
588
+ await this.emitSync("Store.Saved", {
589
+ object: object,
590
+ store: this,
591
+ context: ctx
693
592
  });
593
+ await object._onSaved();
594
+ return object;
694
595
  }
695
596
  /**
696
597
  * Patch an object
@@ -699,10 +600,8 @@ class Store extends service_1.Service {
699
600
  * @param reverseMap
700
601
  * @returns
701
602
  */
702
- patch(object, reverseMap = true) {
703
- return __awaiter(this, void 0, void 0, function* () {
704
- return this.update(object, reverseMap, true);
705
- });
603
+ async patch(object, reverseMap = true) {
604
+ return this.update(object, reverseMap, true);
706
605
  }
707
606
  /**
708
607
  * Check if an UpdateCondition is met
@@ -737,6 +636,26 @@ class Store extends service_1.Service {
737
636
  throw new UpdateConditionFailError(model.getUuid(), `${collection}[${index}].${conditionField}`, condition);
738
637
  }
739
638
  }
639
+ /**
640
+ * Update conditionally
641
+ * @param uuid
642
+ * @param updates
643
+ * @param conditionField
644
+ * @param condition
645
+ */
646
+ async conditionalPatch(uuid, updates, conditionField, condition) {
647
+ try {
648
+ await this._patch(updates, uuid, condition, conditionField);
649
+ await this._cacheStore?.patch({ uuid, ...updates });
650
+ return true;
651
+ }
652
+ catch (err) {
653
+ if (err instanceof UpdateConditionFailError) {
654
+ return false;
655
+ }
656
+ throw err;
657
+ }
658
+ }
740
659
  /**
741
660
  *
742
661
  * @param model
@@ -747,116 +666,114 @@ class Store extends service_1.Service {
747
666
  * @param itemWriteConditionField
748
667
  * @param updateDate
749
668
  */
750
- simulateUpsertItemToCollection(model, prop, item, updateDate, index, itemWriteCondition, itemWriteConditionField) {
751
- return __awaiter(this, void 0, void 0, function* () {
752
- if (prop === "__proto__") {
753
- throw new Error("Cannot update __proto__: js/prototype-polluting-assignment");
754
- }
755
- this.checkCollectionUpdateCondition(model, prop, itemWriteConditionField, itemWriteCondition, index);
756
- if (index === undefined) {
757
- if (model[prop] === undefined) {
758
- model[prop] = [item];
759
- }
760
- else {
761
- model[prop].push(item);
762
- }
669
+ async simulateUpsertItemToCollection(model, prop, item, updateDate, index, itemWriteCondition, itemWriteConditionField) {
670
+ if (prop === "__proto__") {
671
+ throw new Error("Cannot update __proto__: js/prototype-polluting-assignment");
672
+ }
673
+ this.checkCollectionUpdateCondition(model, prop, itemWriteConditionField, itemWriteCondition, index);
674
+ if (index === undefined) {
675
+ if (model[prop] === undefined) {
676
+ model[prop] = [item];
763
677
  }
764
678
  else {
765
- model[prop][index] = item;
679
+ model[prop].push(item);
766
680
  }
767
- model[this._lastUpdateField] = updateDate;
768
- yield this._save(model);
769
- });
681
+ }
682
+ else {
683
+ model[prop][index] = item;
684
+ }
685
+ model[this._lastUpdateField] = updateDate;
686
+ await this._save(model);
770
687
  }
771
688
  /**
772
689
  * Update an object
773
690
  *
691
+ * If no attribute can be updated then return undefined
692
+ *
774
693
  * @param {Object} Object to save
775
694
  * @param {Boolean} reverseMap internal use only, for disable map resolution
776
695
  * @return {Promise} with saved object
777
696
  */
778
- update(object, reverseMap = true, partial = false) {
779
- var _a, _b;
780
- return __awaiter(this, void 0, void 0, function* () {
781
- /** @ignore */
782
- var saved;
783
- var loaded;
784
- // Dont allow to update collections from map
785
- if (this._reverseMap != undefined && reverseMap) {
786
- for (let i in this._reverseMap) {
787
- if (object[this._reverseMap[i].property] != undefined) {
788
- delete object[this._reverseMap[i].property];
789
- }
697
+ async update(object, reverseMap = true, partial = false) {
698
+ /** @ignore */
699
+ let saved;
700
+ let loaded;
701
+ // Dont allow to update collections from map
702
+ if (this._reverseMap != undefined && reverseMap) {
703
+ for (let i in this._reverseMap) {
704
+ if (object[this._reverseMap[i].property] != undefined) {
705
+ delete object[this._reverseMap[i].property];
790
706
  }
791
707
  }
792
- if (Object.keys(object).length < 2) {
793
- return {};
794
- }
795
- object[this._lastUpdateField] = new Date();
796
- this.metrics.get++;
797
- let load = yield this._getFromCache(object[this._uuidField], true);
798
- if (load.__type !== this._model.name && this.parameters.strict) {
799
- this.log("WARN", `Object '${object[this._uuidField]}' was not created by this store`);
800
- throw new StoreNotFoundError(object[this._uuidField], this.getName());
801
- }
802
- loaded = this.initModel(load);
803
- if (object instanceof coremodel_1.CoreModel) {
804
- loaded.setContext(object.getContext());
805
- }
806
- if (partial) {
807
- yield this.emitSync(`Store.PatchUpdate`, {
808
- object: loaded,
809
- store: this,
810
- update: object
811
- });
812
- }
813
- else {
814
- yield this.emitSync(`Store.Update`, {
815
- object: loaded,
816
- store: this,
817
- update: object
818
- });
819
- }
820
- yield loaded._onUpdate(object);
821
- let res;
822
- if (partial) {
823
- this.metrics.partialUpdate++;
824
- yield this._patch(object, object[this._uuidField], load[this._lastUpdateField], this._lastUpdateField);
825
- yield ((_a = this._cacheStore) === null || _a === void 0 ? void 0 : _a._patch(object, object[this._uuidField], load[this._lastUpdateField], this._lastUpdateField));
826
- res = object;
827
- }
828
- else {
829
- // Copy back the mappers
830
- for (let i in this._reverseMap) {
831
- object[this._reverseMap[i].property] = loaded[this._reverseMap[i].property];
832
- }
833
- this.metrics.update++;
834
- res = yield this._update(object, object[this._uuidField], load[this._lastUpdateField], this._lastUpdateField);
835
- yield ((_b = this._cacheStore) === null || _b === void 0 ? void 0 : _b._update(object, object[this._uuidField], load[this._lastUpdateField], this._lastUpdateField));
836
- }
837
- // Return updated
838
- for (let i in res) {
839
- loaded[i] = res[i];
840
- }
841
- for (let i in object) {
842
- loaded[i] = object[i];
843
- }
844
- saved = this.initModel(loaded);
845
- if (partial) {
846
- yield this.emitSync(`Store.PatchUpdated`, {
847
- object: saved,
848
- store: this
849
- });
850
- }
851
- else {
852
- yield this.emitSync(`Store.Updated`, {
853
- object: saved,
854
- store: this
855
- });
708
+ }
709
+ if (Object.keys(object).length < 2) {
710
+ return undefined;
711
+ }
712
+ object[this._lastUpdateField] = new Date();
713
+ this.metrics.get++;
714
+ let load = await this._getFromCache(object[this._uuidField], true);
715
+ if (load.__type !== this._model.name && this.parameters.strict) {
716
+ this.log("WARN", `Object '${object[this._uuidField]}' was not created by this store`);
717
+ throw new StoreNotFoundError(object[this._uuidField], this.getName());
718
+ }
719
+ loaded = this.initModel(load);
720
+ if (object instanceof CoreModel) {
721
+ loaded.setContext(object.getContext());
722
+ }
723
+ if (partial) {
724
+ await this.emitSync(`Store.PatchUpdate`, {
725
+ object: loaded,
726
+ store: this,
727
+ update: object
728
+ });
729
+ }
730
+ else {
731
+ await this.emitSync(`Store.Update`, {
732
+ object: loaded,
733
+ store: this,
734
+ update: object
735
+ });
736
+ }
737
+ await loaded._onUpdate(object);
738
+ let res;
739
+ if (partial) {
740
+ this.metrics.partialUpdate++;
741
+ await this._patch(object, object[this._uuidField], load[this._lastUpdateField], this._lastUpdateField);
742
+ await this._cacheStore?._patch(object, object[this._uuidField], load[this._lastUpdateField], this._lastUpdateField);
743
+ res = object;
744
+ }
745
+ else {
746
+ // Copy back the mappers
747
+ for (let i in this._reverseMap) {
748
+ object[this._reverseMap[i].property] = loaded[this._reverseMap[i].property];
856
749
  }
857
- yield saved._onUpdated();
858
- return saved;
859
- });
750
+ object = this.initModel(object);
751
+ this.metrics.update++;
752
+ res = await this._update(object, object[this._uuidField], load[this._lastUpdateField], this._lastUpdateField);
753
+ await this._cacheStore?._update(object, object[this._uuidField], load[this._lastUpdateField], this._lastUpdateField);
754
+ }
755
+ // Return updated
756
+ for (let i in res) {
757
+ loaded[i] = res[i];
758
+ }
759
+ for (let i in object) {
760
+ loaded[i] = object[i];
761
+ }
762
+ saved = this.initModel(loaded);
763
+ if (partial) {
764
+ await this.emitSync(`Store.PatchUpdated`, {
765
+ object: saved,
766
+ store: this
767
+ });
768
+ }
769
+ else {
770
+ await this.emitSync(`Store.Updated`, {
771
+ object: saved,
772
+ store: this
773
+ });
774
+ }
775
+ await saved._onUpdated();
776
+ return saved;
860
777
  }
861
778
  /**
862
779
  * Remove an attribute from an object
@@ -865,18 +782,15 @@ class Store extends service_1.Service {
865
782
  * @param attribute
866
783
  * @returns
867
784
  */
868
- removeAttribute(uuid, attribute, itemWriteCondition, itemWriteConditionField) {
869
- var _a;
870
- return __awaiter(this, void 0, void 0, function* () {
871
- this.metrics.attributeDelete++;
872
- yield this._removeAttribute(uuid, attribute, itemWriteCondition, itemWriteConditionField);
873
- yield ((_a = this._cacheStore) === null || _a === void 0 ? void 0 : _a._removeAttribute(uuid, attribute, itemWriteCondition, itemWriteConditionField));
874
- yield this.emitSync("Store.PartialUpdated", {
875
- object_id: uuid,
876
- partial_update: {
877
- deleteAttribute: attribute
878
- }
879
- });
785
+ async removeAttribute(uuid, attribute, itemWriteCondition, itemWriteConditionField) {
786
+ this.metrics.attributeDelete++;
787
+ await this._removeAttribute(uuid, attribute, itemWriteCondition, itemWriteConditionField);
788
+ await this._cacheStore?._removeAttribute(uuid, attribute, itemWriteCondition, itemWriteConditionField);
789
+ await this.emitSync("Store.PartialUpdated", {
790
+ object_id: uuid,
791
+ partial_update: {
792
+ deleteAttribute: attribute
793
+ }
880
794
  });
881
795
  }
882
796
  /**
@@ -886,21 +800,17 @@ class Store extends service_1.Service {
886
800
  * @param uuid
887
801
  * @returns
888
802
  */
889
- cascadeDelete(obj, _uuid) {
890
- return __awaiter(this, void 0, void 0, function* () {
891
- // We dont need uuid but Binary store will need it
892
- return this.delete(obj.getUuid());
893
- });
803
+ async cascadeDelete(obj, _uuid) {
804
+ // We dont need uuid but Binary store will need it
805
+ return this.delete(obj.getUuid());
894
806
  }
895
807
  /**
896
808
  * Delete an object from the store without condition nor async
897
809
  * @param uid to delete
898
810
  * @returns
899
811
  */
900
- forceDelete(uid) {
901
- return __awaiter(this, void 0, void 0, function* () {
902
- return this.delete(uid, undefined, undefined, true);
903
- });
812
+ async forceDelete(uid) {
813
+ return this.delete(uid, undefined, undefined, true);
904
814
  }
905
815
  /**
906
816
  * Delete an object
@@ -909,62 +819,59 @@ class Store extends service_1.Service {
909
819
  * @param {Boolean} delete sync even if asyncDelete is active
910
820
  * @return {Promise} the deletion promise
911
821
  */
912
- delete(uid, writeCondition, writeConditionField, sync = false) {
913
- var _a, _b;
914
- return __awaiter(this, void 0, void 0, function* () {
915
- /** @ignore */
916
- let to_delete;
917
- // Allow full object or just its uuid
918
- if (typeof uid === "object") {
919
- to_delete = uid;
920
- }
921
- else {
922
- this.metrics.get++;
923
- to_delete = yield this._getFromCache(uid);
924
- if (to_delete === undefined) {
925
- return;
926
- }
927
- if (to_delete.__type !== this._model.name && this.parameters.strict) {
928
- this.log("WARN", `Object '${uid}' was not created by this store`);
929
- return;
930
- }
931
- to_delete = this.initModel(to_delete);
932
- }
933
- // Check condition as we have the object
934
- if (writeCondition) {
935
- if (to_delete[writeConditionField] !== writeCondition) {
936
- throw new UpdateConditionFailError(to_delete.getUuid(), writeConditionField, writeCondition);
937
- }
822
+ async delete(uid, writeCondition, writeConditionField, sync = false) {
823
+ /** @ignore */
824
+ let to_delete;
825
+ // Allow full object or just its uuid
826
+ if (typeof uid === "object") {
827
+ to_delete = uid;
828
+ }
829
+ else {
830
+ this.metrics.get++;
831
+ to_delete = await this._getFromCache(uid);
832
+ if (to_delete === undefined) {
833
+ return;
938
834
  }
939
- // Send preevent
940
- yield this.emitSync("Store.Delete", {
941
- object: to_delete,
942
- store: this
943
- });
944
- yield to_delete._onDelete();
945
- // If async we just tag the object as deleted
946
- if (this.parameters.asyncDelete && !sync) {
947
- this.metrics.partialUpdate++;
948
- yield this._patch({
949
- __deleted: true
950
- }, to_delete.getUuid());
951
- yield ((_a = this._cacheStore) === null || _a === void 0 ? void 0 : _a._patch({
952
- __deleted: true
953
- }, to_delete.getUuid()));
835
+ if (to_delete.__type !== this._model.name && this.parameters.strict) {
836
+ this.log("WARN", `Object '${uid}' was not created by this store`);
837
+ return;
954
838
  }
955
- else {
956
- this.metrics.delete++;
957
- // Delete from the DB for real
958
- yield this._delete(to_delete.getUuid(), writeCondition, writeConditionField);
959
- yield ((_b = this._cacheStore) === null || _b === void 0 ? void 0 : _b._delete(to_delete.getUuid(), writeCondition, writeConditionField));
839
+ to_delete = this.initModel(to_delete);
840
+ }
841
+ // Check condition as we have the object
842
+ if (writeCondition) {
843
+ if (to_delete[writeConditionField] !== writeCondition) {
844
+ throw new UpdateConditionFailError(to_delete.getUuid(), writeConditionField, writeCondition);
960
845
  }
961
- // Send post event
962
- yield this.emitSync("Store.Deleted", {
963
- object: to_delete,
964
- store: this
965
- });
966
- yield to_delete._onDeleted();
846
+ }
847
+ // Send preevent
848
+ await this.emitSync("Store.Delete", {
849
+ object: to_delete,
850
+ store: this
851
+ });
852
+ await to_delete._onDelete();
853
+ // If async we just tag the object as deleted
854
+ if (this.parameters.asyncDelete && !sync) {
855
+ this.metrics.partialUpdate++;
856
+ await this._patch({
857
+ __deleted: true
858
+ }, to_delete.getUuid());
859
+ await this._cacheStore?._patch({
860
+ __deleted: true
861
+ }, to_delete.getUuid());
862
+ }
863
+ else {
864
+ this.metrics.delete++;
865
+ // Delete from the DB for real
866
+ await this._delete(to_delete.getUuid(), writeCondition, writeConditionField);
867
+ await this._cacheStore?._delete(to_delete.getUuid(), writeCondition, writeConditionField);
868
+ }
869
+ // Send post event
870
+ await this.emitSync("Store.Deleted", {
871
+ object: to_delete,
872
+ store: this
967
873
  });
874
+ await to_delete._onDeleted();
968
875
  }
969
876
  /**
970
877
  * By default we cannot know if the store will trigger or not
@@ -980,22 +887,31 @@ class Store extends service_1.Service {
980
887
  * @param {string} id
981
888
  * @returns {Promise<Map<string, any>>}
982
889
  */
983
- getConfiguration(id) {
984
- return __awaiter(this, void 0, void 0, function* () {
985
- this.metrics.get++;
986
- let object = yield this._getFromCache(id);
987
- if (!object) {
988
- return undefined;
989
- }
990
- let result = {};
991
- for (let i in object) {
992
- if (i === this._uuidField || i === this._lastUpdateField || i.startsWith("_")) {
993
- continue;
994
- }
995
- result[i] = object[i];
890
+ async getConfiguration(id) {
891
+ this.metrics.get++;
892
+ let object = await this._getFromCache(id);
893
+ if (!object) {
894
+ return undefined;
895
+ }
896
+ let result = {};
897
+ for (let i in object) {
898
+ if (i === this._uuidField || i === this._lastUpdateField || i.startsWith("_")) {
899
+ continue;
996
900
  }
997
- return result;
998
- });
901
+ result[i] = object[i];
902
+ }
903
+ return result;
904
+ }
905
+ /**
906
+ * Upsert the uuid object
907
+ * @param uuid
908
+ * @param data
909
+ */
910
+ async put(uuid, data) {
911
+ if (await this.exists(uuid)) {
912
+ return this.update({ ...data, uuid });
913
+ }
914
+ return this.save({ ...data, uuid });
999
915
  }
1000
916
  /**
1001
917
  * Get an object
@@ -1003,31 +919,29 @@ class Store extends service_1.Service {
1003
919
  * @param {String} uuid to get
1004
920
  * @return {Promise} the object retrieved ( can be undefined if not found )
1005
921
  */
1006
- get(uid, ctx = undefined) {
1007
- return __awaiter(this, void 0, void 0, function* () {
1008
- /** @ignore */
1009
- if (!uid) {
1010
- return undefined;
1011
- }
1012
- this.metrics.get++;
1013
- let object = yield this._getFromCache(uid);
1014
- if (!object) {
1015
- return undefined;
1016
- }
1017
- if (object.__type !== this._model.name && this.parameters.strict) {
1018
- this.log("WARN", `Object '${uid}' was not created by this store`);
1019
- return undefined;
1020
- }
1021
- object = this.initModel(object);
1022
- object.setContext(ctx);
1023
- yield this.emitSync("Store.Get", {
1024
- object: object,
1025
- store: this,
1026
- context: ctx
1027
- });
1028
- yield object._onGet();
1029
- return object;
922
+ async get(uid, ctx = undefined, defaultValue = undefined) {
923
+ /** @ignore */
924
+ if (!uid) {
925
+ return undefined;
926
+ }
927
+ this.metrics.get++;
928
+ let object = await this._getFromCache(uid);
929
+ if (!object) {
930
+ return defaultValue ? this.initModel(defaultValue) : undefined;
931
+ }
932
+ if (object.__type !== this._model.name && this.parameters.strict) {
933
+ this.log("WARN", `Object '${uid}' was not created by this store`);
934
+ return undefined;
935
+ }
936
+ object = this.initModel(object);
937
+ object.setContext(ctx);
938
+ await this.emitSync("Store.Get", {
939
+ object: object,
940
+ store: this,
941
+ context: ctx
1030
942
  });
943
+ await object._onGet();
944
+ return object;
1031
945
  }
1032
946
  /**
1033
947
  * Set one attribute in an object
@@ -1039,161 +953,154 @@ class Store extends service_1.Service {
1039
953
  * @param value new value
1040
954
  * @returns
1041
955
  */
1042
- setAttribute(uid, property, value) {
1043
- return __awaiter(this, void 0, void 0, function* () {
1044
- let patch = {};
1045
- patch[property] = value;
1046
- patch[this.getUuidField()] = uid;
1047
- yield this.patch(patch);
1048
- });
956
+ async setAttribute(uid, property, value) {
957
+ let patch = {};
958
+ patch[property] = value;
959
+ patch[this.getUuidField()] = uid;
960
+ await this.patch(patch);
1049
961
  }
1050
962
  /**
1051
963
  * @override
1052
964
  */
1053
- simulateFind(query, uuids) {
1054
- return __awaiter(this, void 0, void 0, function* () {
1055
- let result = {
1056
- results: [],
1057
- continuationToken: undefined,
1058
- filter: true
1059
- };
1060
- let count = 0;
1061
- let limit = query.limit;
1062
- let offset = parseInt(query.continuationToken || "0");
1063
- let originalOffset = offset;
1064
- if (query.orderBy && query.orderBy.length) {
1065
- offset = 0;
1066
- // We need to retrieve everything to orderBy after
1067
- limit = Number.MAX_SAFE_INTEGER;
965
+ async simulateFind(query, uuids) {
966
+ let result = {
967
+ results: [],
968
+ continuationToken: undefined,
969
+ filter: true
970
+ };
971
+ let count = 0;
972
+ let limit = query.limit;
973
+ let offset = parseInt(query.continuationToken || "0");
974
+ let originalOffset = offset;
975
+ if (query.orderBy && query.orderBy.length) {
976
+ offset = 0;
977
+ // We need to retrieve everything to orderBy after
978
+ limit = Number.MAX_SAFE_INTEGER;
979
+ }
980
+ // Need to transfert to Array
981
+ for (let uuid of uuids) {
982
+ count++;
983
+ // Offset start
984
+ if (offset >= count) {
985
+ continue;
1068
986
  }
1069
- // Need to transfert to Array
1070
- for (let uuid of uuids) {
1071
- count++;
1072
- // Offset start
1073
- if (offset >= count) {
1074
- continue;
1075
- }
1076
- let obj = yield this._getFromCache(uuid);
1077
- if (obj && query.filter.eval(obj)) {
1078
- result.results.push(obj);
1079
- if (result.results.length >= limit) {
1080
- result.continuationToken = count.toString();
1081
- return result;
1082
- }
987
+ let obj = await this._getFromCache(uuid);
988
+ if (obj && query.filter.eval(obj)) {
989
+ result.results.push(obj);
990
+ if (result.results.length >= limit) {
991
+ result.continuationToken = count.toString();
992
+ return result;
1083
993
  }
1084
994
  }
1085
- // Order by
1086
- if (query.orderBy && query.orderBy.length) {
1087
- // Sorting the results
1088
- result.results.sort((a, b) => {
1089
- let valA, valB;
1090
- for (let orderBy of query.orderBy) {
1091
- let invert = orderBy.direction === "ASC" ? 1 : -1;
1092
- valA = query_1.WebdaQL.ComparisonExpression.getAttributeValue(a, orderBy.field.split("."));
1093
- valB = query_1.WebdaQL.ComparisonExpression.getAttributeValue(b, orderBy.field.split("."));
1094
- if (valA === valB) {
1095
- continue;
1096
- }
1097
- if (typeof valA === "string") {
1098
- return valA.localeCompare(valB) * invert;
1099
- }
1100
- return (valA < valB ? -1 : 1) * invert;
995
+ }
996
+ // Order by
997
+ if (query.orderBy && query.orderBy.length) {
998
+ // Sorting the results
999
+ result.results.sort((a, b) => {
1000
+ let valA, valB;
1001
+ for (let orderBy of query.orderBy) {
1002
+ let invert = orderBy.direction === "ASC" ? 1 : -1;
1003
+ valA = WebdaQL.ComparisonExpression.getAttributeValue(a, orderBy.field.split("."));
1004
+ valB = WebdaQL.ComparisonExpression.getAttributeValue(b, orderBy.field.split("."));
1005
+ if (valA === valB) {
1006
+ continue;
1101
1007
  }
1102
- return -1;
1103
- });
1104
- result.results = result.results.slice(originalOffset, query.limit + originalOffset);
1105
- if (result.results.length >= query.limit) {
1106
- result.continuationToken = (query.limit + originalOffset).toString();
1008
+ if (typeof valA === "string") {
1009
+ return valA.localeCompare(valB) * invert;
1010
+ }
1011
+ return (valA < valB ? -1 : 1) * invert;
1107
1012
  }
1013
+ return -1;
1014
+ });
1015
+ result.results = result.results.slice(originalOffset, query.limit + originalOffset);
1016
+ if (result.results.length >= query.limit) {
1017
+ result.continuationToken = (query.limit + originalOffset).toString();
1108
1018
  }
1109
- return result;
1110
- });
1019
+ }
1020
+ return result;
1021
+ }
1022
+ getOpenApiReplacements() {
1023
+ return {
1024
+ modelName: this._model.name
1025
+ };
1111
1026
  }
1112
1027
  /**
1113
1028
  * Handle POST
1114
1029
  * @param ctx
1115
1030
  */
1116
- httpCreate(ctx) {
1117
- return __awaiter(this, void 0, void 0, function* () {
1118
- let body = yield ctx.getRequestBody();
1119
- var object = new this._model();
1120
- object.setContext(ctx);
1121
- object.load(body);
1122
- object[this._creationDateField] = new Date();
1123
- yield object.canAct(ctx, "create");
1124
- try {
1125
- yield object.validate(ctx, body);
1126
- }
1127
- catch (err) {
1128
- this.log("INFO", "Object is not valid", err);
1129
- throw 400;
1130
- }
1131
- if (object[this._uuidField] && (yield this.exists(object[this._uuidField]))) {
1132
- throw 409;
1133
- }
1134
- yield this.save(object, ctx);
1135
- ctx.write(object);
1136
- yield this.emitSync("Store.WebCreate", {
1137
- context: ctx,
1138
- values: body,
1139
- object: object,
1140
- store: this
1141
- });
1031
+ async httpCreate(ctx) {
1032
+ let body = await ctx.getRequestBody();
1033
+ let object = this._model.factory(this._model, body, ctx);
1034
+ object[this._creationDateField] = new Date();
1035
+ await object.canAct(ctx, "create");
1036
+ try {
1037
+ await object.validate(ctx, body);
1038
+ }
1039
+ catch (err) {
1040
+ this.log("INFO", "Object is not valid", err);
1041
+ throw 400;
1042
+ }
1043
+ if (object[this._uuidField] && (await this.exists(object[this._uuidField]))) {
1044
+ throw 409;
1045
+ }
1046
+ await this.save(object, ctx);
1047
+ ctx.write(object);
1048
+ await this.emitSync("Store.WebCreate", {
1049
+ context: ctx,
1050
+ values: body,
1051
+ object: object,
1052
+ store: this
1142
1053
  });
1143
1054
  }
1144
1055
  /**
1145
1056
  * Handle obect action
1146
1057
  * @param ctx
1147
1058
  */
1148
- httpAction(ctx) {
1149
- return __awaiter(this, void 0, void 0, function* () {
1150
- let action = ctx.getHttpContext().getUrl().split("/").pop();
1151
- let object = yield this.get(ctx.parameter("uuid"), ctx);
1152
- if (object === undefined || object.__deleted) {
1153
- throw 404;
1154
- }
1155
- yield object.canAct(ctx, action);
1156
- yield this.emitSync("Store.Action", {
1157
- action: action,
1158
- object: object,
1159
- store: this,
1160
- context: ctx
1161
- });
1162
- let res = yield object["_" + action](ctx);
1163
- if (res) {
1164
- ctx.write(res);
1165
- }
1166
- yield this.emitSync("Store.Actioned", {
1167
- action: action,
1168
- object: object,
1169
- store: this,
1170
- context: ctx,
1171
- result: res
1172
- });
1059
+ async httpAction(ctx) {
1060
+ let action = ctx.getHttpContext().getUrl().split("/").pop();
1061
+ let object = await this.get(ctx.parameter("uuid"), ctx);
1062
+ if (object === undefined || object.__deleted) {
1063
+ throw 404;
1064
+ }
1065
+ await object.canAct(ctx, action);
1066
+ await this.emitSync("Store.Action", {
1067
+ action: action,
1068
+ object: object,
1069
+ store: this,
1070
+ context: ctx
1071
+ });
1072
+ let res = await object["_" + action](ctx);
1073
+ if (res) {
1074
+ ctx.write(res);
1075
+ }
1076
+ await this.emitSync("Store.Actioned", {
1077
+ action: action,
1078
+ object: object,
1079
+ store: this,
1080
+ context: ctx,
1081
+ result: res
1173
1082
  });
1174
1083
  }
1175
1084
  /**
1176
1085
  * Handle collection action
1177
1086
  * @param ctx
1178
1087
  */
1179
- httpGlobalAction(ctx) {
1180
- return __awaiter(this, void 0, void 0, function* () {
1181
- let action = ctx.getHttpContext().getUrl().split("/").pop();
1182
- yield this.emitSync("Store.Action", {
1183
- action: action,
1184
- store: this,
1185
- context: ctx
1186
- });
1187
- let res = yield this._model["_" + action](ctx);
1188
- if (res) {
1189
- ctx.write(res);
1190
- }
1191
- yield this.emitSync("Store.Actioned", {
1192
- action: action,
1193
- store: this,
1194
- context: ctx,
1195
- result: res
1196
- });
1088
+ async httpGlobalAction(ctx) {
1089
+ let action = ctx.getHttpContext().getUrl().split("/").pop();
1090
+ await this.emitSync("Store.Action", {
1091
+ action: action,
1092
+ store: this,
1093
+ context: ctx
1094
+ });
1095
+ let res = await this._model["_" + action](ctx);
1096
+ if (res) {
1097
+ ctx.write(res);
1098
+ }
1099
+ await this.emitSync("Store.Actioned", {
1100
+ action: action,
1101
+ store: this,
1102
+ context: ctx,
1103
+ result: res
1197
1104
  });
1198
1105
  }
1199
1106
  /**
@@ -1201,62 +1108,60 @@ class Store extends service_1.Service {
1201
1108
  *
1202
1109
  * @param ctx context of the request
1203
1110
  */
1204
- httpUpdate(ctx) {
1205
- return __awaiter(this, void 0, void 0, function* () {
1206
- let body = yield ctx.getRequestBody();
1207
- let uuid = ctx.parameter("uuid");
1208
- body[this._uuidField] = uuid;
1209
- let object = yield this.get(uuid, ctx);
1210
- if (!object || object.__deleted)
1211
- throw 404;
1212
- yield object.canAct(ctx, "update");
1213
- if (ctx.getHttpContext().getMethod() === "PATCH") {
1214
- try {
1215
- yield object.validate(ctx, body);
1216
- }
1217
- catch (err) {
1218
- this.log("INFO", "Object invalid", err);
1219
- throw 400;
1220
- }
1221
- let updateObject = new this._model();
1222
- // Clean any default attributes from the model
1223
- Object.keys(updateObject)
1224
- .filter(i => i !== "__class")
1225
- .forEach(i => {
1226
- delete updateObject[i];
1227
- });
1228
- updateObject.setContext(ctx);
1229
- updateObject.load(body);
1230
- yield this.patch(updateObject);
1231
- object = undefined;
1111
+ async httpUpdate(ctx) {
1112
+ let body = await ctx.getRequestBody();
1113
+ let uuid = ctx.parameter("uuid");
1114
+ body[this._uuidField] = uuid;
1115
+ let object = await this.get(uuid, ctx);
1116
+ if (!object || object.__deleted)
1117
+ throw 404;
1118
+ await object.canAct(ctx, "update");
1119
+ if (ctx.getHttpContext().getMethod() === "PATCH") {
1120
+ try {
1121
+ await object.validate(ctx, body);
1232
1122
  }
1233
- else {
1234
- let updateObject = new this._model();
1235
- updateObject.load(body);
1236
- // Copy back the _ attributes
1237
- Object.keys(object)
1238
- .filter(i => i.startsWith("_"))
1239
- .forEach(i => {
1240
- updateObject[i] = object[i];
1241
- });
1242
- try {
1243
- yield updateObject.validate(ctx, body);
1244
- }
1245
- catch (err) {
1246
- this.log("INFO", "Object invalid", err);
1247
- throw 400;
1248
- }
1249
- // Add mappers back to
1250
- object = yield this.update(updateObject);
1123
+ catch (err) {
1124
+ this.log("INFO", "Object invalid", err);
1125
+ throw 400;
1251
1126
  }
1252
- ctx.write(object);
1253
- yield this.emitSync("Store.WebUpdate", {
1254
- context: ctx,
1255
- updates: body,
1256
- object: object,
1257
- store: this,
1258
- method: ctx.getHttpContext().getMethod()
1127
+ let updateObject = new this._model();
1128
+ // Clean any default attributes from the model
1129
+ Object.keys(updateObject)
1130
+ .filter(i => i !== "__class")
1131
+ .forEach(i => {
1132
+ delete updateObject[i];
1259
1133
  });
1134
+ updateObject.setContext(ctx);
1135
+ updateObject.load(body);
1136
+ await this.patch(updateObject);
1137
+ object = undefined;
1138
+ }
1139
+ else {
1140
+ let updateObject = new this._model();
1141
+ updateObject.load(body);
1142
+ // Copy back the _ attributes
1143
+ Object.keys(object)
1144
+ .filter(i => i.startsWith("_"))
1145
+ .forEach(i => {
1146
+ updateObject[i] = object[i];
1147
+ });
1148
+ try {
1149
+ await updateObject.validate(ctx, body);
1150
+ }
1151
+ catch (err) {
1152
+ this.log("INFO", "Object invalid", err);
1153
+ throw 400;
1154
+ }
1155
+ // Add mappers back to
1156
+ object = await this.update(updateObject);
1157
+ }
1158
+ ctx.write(object);
1159
+ await this.emitSync("Store.WebUpdate", {
1160
+ context: ctx,
1161
+ updates: body,
1162
+ object: object,
1163
+ store: this,
1164
+ method: ctx.getHttpContext().getMethod()
1260
1165
  });
1261
1166
  }
1262
1167
  /**
@@ -1264,32 +1169,25 @@ class Store extends service_1.Service {
1264
1169
  *
1265
1170
  * @param ctx context of the request
1266
1171
  */
1267
- httpGet(ctx) {
1268
- return __awaiter(this, void 0, void 0, function* () {
1269
- let uuid = ctx.parameter("uuid");
1270
- if (uuid) {
1271
- let object = yield this.get(uuid, ctx);
1272
- yield this.emitSync("Store.WebGetNotFound", {
1273
- context: ctx,
1274
- uuid,
1275
- store: this
1276
- });
1277
- if (object === undefined || object.__deleted) {
1278
- throw 404;
1279
- }
1280
- yield object.canAct(ctx, "get");
1281
- ctx.write(object);
1282
- yield this.emitSync("Store.WebGet", {
1283
- context: ctx,
1284
- object: object,
1285
- store: this
1286
- });
1287
- ctx.write(object);
1288
- }
1289
- else {
1290
- // List probably
1291
- }
1172
+ async httpGet(ctx) {
1173
+ let uuid = ctx.parameter("uuid");
1174
+ let object = await this.get(uuid, ctx);
1175
+ await this.emitSync("Store.WebGetNotFound", {
1176
+ context: ctx,
1177
+ uuid,
1178
+ store: this
1292
1179
  });
1180
+ if (object === undefined || object.__deleted) {
1181
+ throw 404;
1182
+ }
1183
+ await object.canAct(ctx, "get");
1184
+ ctx.write(object);
1185
+ await this.emitSync("Store.WebGet", {
1186
+ context: ctx,
1187
+ object: object,
1188
+ store: this
1189
+ });
1190
+ ctx.write(object);
1293
1191
  }
1294
1192
  /**
1295
1193
  * Handle HTTP request
@@ -1297,31 +1195,21 @@ class Store extends service_1.Service {
1297
1195
  * @param ctx context of the request
1298
1196
  * @returns
1299
1197
  */
1300
- httpRoute(ctx) {
1301
- return __awaiter(this, void 0, void 0, function* () {
1302
- let uuid = ctx.parameter("uuid");
1303
- if (ctx.getHttpContext().getMethod() == "GET") {
1304
- return this.httpGet(ctx);
1305
- }
1306
- else if (ctx.getHttpContext().getMethod() == "DELETE") {
1307
- let object = yield this.get(uuid, ctx);
1308
- if (!object || object.__deleted)
1309
- throw 404;
1310
- yield object.canAct(ctx, "delete");
1311
- // http://stackoverflow.com/questions/28684209/huge-delay-on-delete-requests-with-204-response-and-no-content-in-objectve-c#
1312
- // IOS don't handle 204 with Content-Length != 0 it seems
1313
- // Have trouble to handle the Content-Length on API Gateway so returning an empty object for now
1314
- ctx.write({});
1315
- yield this.delete(uuid);
1316
- yield this.emitSync("Store.WebDelete", {
1317
- context: ctx,
1318
- object_id: uuid,
1319
- store: this
1320
- });
1321
- }
1322
- else if (ctx.getHttpContext().getMethod() === "PUT" || ctx.getHttpContext().getMethod() === "PATCH") {
1323
- return this.httpUpdate(ctx);
1324
- }
1198
+ async httpRoute(ctx) {
1199
+ let uuid = ctx.parameter("uuid");
1200
+ let object = await this.get(uuid, ctx);
1201
+ if (!object || object.__deleted)
1202
+ throw 404;
1203
+ await object.canAct(ctx, "delete");
1204
+ // http://stackoverflow.com/questions/28684209/huge-delay-on-delete-requests-with-204-response-and-no-content-in-objectve-c#
1205
+ // IOS don't handle 204 with Content-Length != 0 it seems
1206
+ // Have trouble to handle the Content-Length on API Gateway so returning an empty object for now
1207
+ ctx.write({});
1208
+ await this.delete(uuid);
1209
+ await this.emitSync("Store.WebDelete", {
1210
+ context: ctx,
1211
+ object_id: uuid,
1212
+ store: this
1325
1213
  });
1326
1214
  }
1327
1215
  /**
@@ -1331,5 +1219,135 @@ class Store extends service_1.Service {
1331
1219
  return this._uuidField;
1332
1220
  }
1333
1221
  }
1334
- exports.Store = Store;
1222
+ __decorate([
1223
+ Route(".", ["POST"], false, {
1224
+ post: {
1225
+ description: "The way to create a new ${modelName} model",
1226
+ summary: "Create a new ${modelName}",
1227
+ operationId: "create${modelName}",
1228
+ requestBody: {
1229
+ content: {
1230
+ "application/json": {
1231
+ schema: {
1232
+ $ref: "#/components/schemas/${modelName}"
1233
+ }
1234
+ }
1235
+ }
1236
+ },
1237
+ responses: {
1238
+ "200": {
1239
+ description: "Retrieve model",
1240
+ content: {
1241
+ "application/json": {
1242
+ schema: {
1243
+ $ref: "#/components/schemas/${modelName}"
1244
+ }
1245
+ }
1246
+ }
1247
+ },
1248
+ "400": {
1249
+ description: "Object is invalid"
1250
+ },
1251
+ "403": {
1252
+ description: "You don't have permissions"
1253
+ },
1254
+ "409": {
1255
+ description: "Object already exists"
1256
+ }
1257
+ }
1258
+ }
1259
+ })
1260
+ ], Store.prototype, "httpCreate", null);
1261
+ __decorate([
1262
+ Route("./{uuid}", ["PUT", "PATCH"], false, {
1263
+ put: {
1264
+ description: "Update a ${modelName} if the permissions allow",
1265
+ summary: "Update a ${modelName}",
1266
+ operationId: "updatet${modelName}",
1267
+ schemas: {
1268
+ input: "${modelName}",
1269
+ output: "${modelName}"
1270
+ },
1271
+ responses: {
1272
+ "200": {},
1273
+ "400": {
1274
+ description: "Object is invalid"
1275
+ },
1276
+ "403": {
1277
+ description: "You don't have permissions"
1278
+ },
1279
+ "404": {
1280
+ description: "Unknown object"
1281
+ }
1282
+ }
1283
+ },
1284
+ patch: {
1285
+ description: "Patch a ${modelName} if the permissions allow",
1286
+ summary: "Patch a ${modelName}",
1287
+ operationId: "partialUpdatet${modelName}",
1288
+ schemas: {
1289
+ input: "${modelName}"
1290
+ },
1291
+ responses: {
1292
+ "204": {
1293
+ description: ""
1294
+ },
1295
+ "400": {
1296
+ description: "Object is invalid"
1297
+ },
1298
+ "403": {
1299
+ description: "You don't have permissions"
1300
+ },
1301
+ "404": {
1302
+ description: "Unknown object"
1303
+ }
1304
+ }
1305
+ }
1306
+ })
1307
+ ], Store.prototype, "httpUpdate", null);
1308
+ __decorate([
1309
+ Route("./{uuid}", ["GET"], false, {
1310
+ get: {
1311
+ description: "Retrieve ${modelName} model if permissions allow",
1312
+ summary: "Retrieve a ${modelName}",
1313
+ operationId: "get${modelName}",
1314
+ schemas: {
1315
+ output: "${modelName}"
1316
+ },
1317
+ responses: {
1318
+ "200": {},
1319
+ "400": {
1320
+ description: "Object is invalid"
1321
+ },
1322
+ "403": {
1323
+ description: "You don't have permissions"
1324
+ },
1325
+ "404": {
1326
+ description: "Unknown object"
1327
+ }
1328
+ }
1329
+ }
1330
+ })
1331
+ ], Store.prototype, "httpGet", null);
1332
+ __decorate([
1333
+ Route("./{uuid}", ["DELETE"], false, {
1334
+ delete: {
1335
+ operationId: "delete${modelName}",
1336
+ description: "Delete ${modelName} if the permissions allow",
1337
+ summary: "Delete a ${modelName}",
1338
+ responses: {
1339
+ "204": {
1340
+ description: ""
1341
+ },
1342
+ "403": {
1343
+ description: "You don't have permissions"
1344
+ },
1345
+ "404": {
1346
+ description: "Unknown object"
1347
+ }
1348
+ }
1349
+ }
1350
+ })
1351
+ ], Store.prototype, "httpRoute", null);
1352
+ export { Store };
1335
1353
  //# sourceMappingURL=store.js.map