@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.
- package/lib/application.d.ts +5 -21
- package/lib/application.js +71 -84
- package/lib/application.js.map +1 -1
- package/lib/application.spec.js +121 -140
- package/lib/application.spec.js.map +1 -1
- package/lib/core.d.ts +44 -45
- package/lib/core.js +239 -320
- package/lib/core.js.map +1 -1
- package/lib/core.spec.js +326 -391
- package/lib/core.spec.js.map +1 -1
- package/lib/index.d.ts +49 -45
- package/lib/index.js +54 -67
- package/lib/index.js.map +1 -1
- package/lib/models/aclmodel.d.ts +2 -2
- package/lib/models/aclmodel.js +63 -90
- package/lib/models/aclmodel.js.map +1 -1
- package/lib/models/aclmodel.spec.js +128 -151
- package/lib/models/aclmodel.spec.js.map +1 -1
- package/lib/models/coremodel.d.ts +39 -17
- package/lib/models/coremodel.js +160 -117
- package/lib/models/coremodel.js.map +1 -1
- package/lib/models/coremodel.spec.js +143 -107
- package/lib/models/coremodel.spec.js.map +1 -1
- package/lib/models/deployment.js +1 -2
- package/lib/models/ident.d.ts +3 -3
- package/lib/models/ident.js +4 -9
- package/lib/models/ident.js.map +1 -1
- package/lib/models/ident.spec.js +9 -11
- package/lib/models/ident.spec.js.map +1 -1
- package/lib/models/ownermodel.d.ts +2 -2
- package/lib/models/ownermodel.js +39 -62
- package/lib/models/ownermodel.js.map +1 -1
- package/lib/models/ownermodel.spec.js +126 -166
- package/lib/models/ownermodel.spec.js.map +1 -1
- package/lib/models/rolemodel.d.ts +2 -2
- package/lib/models/rolemodel.js +24 -40
- package/lib/models/rolemodel.js.map +1 -1
- package/lib/models/rolemodel.spec.js +44 -61
- package/lib/models/rolemodel.spec.js.map +1 -1
- package/lib/models/user.d.ts +9 -9
- package/lib/models/user.js +3 -8
- package/lib/models/user.js.map +1 -1
- package/lib/models/user.spec.js +14 -16
- package/lib/models/user.spec.js.map +1 -1
- package/lib/queues/filequeue.d.ts +2 -2
- package/lib/queues/filequeue.js +72 -93
- package/lib/queues/filequeue.js.map +1 -1
- package/lib/queues/filequeue.spec.js +53 -70
- package/lib/queues/filequeue.spec.js.map +1 -1
- package/lib/queues/memoryqueue.d.ts +2 -2
- package/lib/queues/memoryqueue.js +37 -61
- package/lib/queues/memoryqueue.js.map +1 -1
- package/lib/queues/memoryqueue.spec.js +142 -165
- package/lib/queues/memoryqueue.spec.js.map +1 -1
- package/lib/queues/pubsubservice.d.ts +2 -2
- package/lib/queues/pubsubservice.js +3 -7
- package/lib/queues/pubsubservice.js.map +1 -1
- package/lib/queues/queue.spec.d.ts +1 -1
- package/lib/queues/queue.spec.js +42 -56
- package/lib/queues/queue.spec.js.map +1 -1
- package/lib/queues/queueservice.d.ts +4 -4
- package/lib/queues/queueservice.js +52 -67
- package/lib/queues/queueservice.js.map +1 -1
- package/lib/router.d.ts +3 -3
- package/lib/router.js +46 -47
- package/lib/router.js.map +1 -1
- package/lib/router.spec.js +64 -61
- package/lib/router.spec.js.map +1 -1
- package/lib/services/asyncevents.d.ts +2 -2
- package/lib/services/asyncevents.js +44 -64
- package/lib/services/asyncevents.js.map +1 -1
- package/lib/services/asyncevents.spec.js +81 -98
- package/lib/services/asyncevents.spec.js.map +1 -1
- package/lib/services/authentication.d.ts +28 -19
- package/lib/services/authentication.js +542 -574
- package/lib/services/authentication.js.map +1 -1
- package/lib/services/authentication.spec.js +411 -447
- package/lib/services/authentication.spec.js.map +1 -1
- package/lib/services/binary.d.ts +9 -7
- package/lib/services/binary.js +213 -245
- package/lib/services/binary.js.map +1 -1
- package/lib/services/binary.spec.d.ts +3 -3
- package/lib/services/binary.spec.js +390 -443
- package/lib/services/binary.spec.js.map +1 -1
- package/lib/services/cloudbinary.d.ts +3 -3
- package/lib/services/cloudbinary.js +45 -70
- package/lib/services/cloudbinary.js.map +1 -1
- package/lib/services/cloudbinary.spec.d.ts +3 -3
- package/lib/services/cloudbinary.spec.js +133 -162
- package/lib/services/cloudbinary.spec.js.map +1 -1
- package/lib/services/configuration.d.ts +6 -3
- package/lib/services/configuration.js +78 -103
- package/lib/services/configuration.js.map +1 -1
- package/lib/services/configuration.spec.js +63 -83
- package/lib/services/configuration.spec.js.map +1 -1
- package/lib/services/cron.d.ts +3 -2
- package/lib/services/cron.js +9 -13
- package/lib/services/cron.js.map +1 -1
- package/lib/services/cron.spec.js +18 -21
- package/lib/services/cron.spec.js.map +1 -1
- package/lib/services/cryptoservice.d.ts +258 -0
- package/lib/services/cryptoservice.js +312 -0
- package/lib/services/cryptoservice.js.map +1 -0
- package/lib/services/cryptoservice.spec.d.ts +1 -0
- package/lib/services/cryptoservice.spec.js +137 -0
- package/lib/services/cryptoservice.spec.js.map +1 -0
- package/lib/services/debugmailer.d.ts +1 -1
- package/lib/services/debugmailer.js +13 -34
- package/lib/services/debugmailer.js.map +1 -1
- package/lib/services/debugmailer.spec.js +16 -29
- package/lib/services/debugmailer.spec.js.map +1 -1
- package/lib/services/echo.d.ts +2 -2
- package/lib/services/echo.js +15 -31
- package/lib/services/echo.js.map +1 -1
- package/lib/services/echo.spec.js +27 -40
- package/lib/services/echo.spec.js.map +1 -1
- package/lib/services/filebinary.d.ts +10 -5
- package/lib/services/filebinary.js +171 -205
- package/lib/services/filebinary.js.map +1 -1
- package/lib/services/filebinary.spec.d.ts +2 -1
- package/lib/services/filebinary.spec.js +106 -117
- package/lib/services/filebinary.spec.js.map +1 -1
- package/lib/services/fileconfiguration.d.ts +2 -2
- package/lib/services/fileconfiguration.js +25 -43
- package/lib/services/fileconfiguration.js.map +1 -1
- package/lib/services/fileconfiguration.spec.js +79 -109
- package/lib/services/fileconfiguration.spec.js.map +1 -1
- package/lib/services/invitationservice.d.ts +10 -10
- package/lib/services/invitationservice.js +275 -313
- package/lib/services/invitationservice.js.map +1 -1
- package/lib/services/invitationservice.spec.js +443 -449
- package/lib/services/invitationservice.spec.js.map +1 -1
- package/lib/services/kubernetesconfiguration.d.ts +2 -2
- package/lib/services/kubernetesconfiguration.js +41 -59
- package/lib/services/kubernetesconfiguration.js.map +1 -1
- package/lib/services/kubernetesconfiguration.spec.js +80 -98
- package/lib/services/kubernetesconfiguration.spec.js.map +1 -1
- package/lib/services/mailer.d.ts +4 -4
- package/lib/services/mailer.js +62 -86
- package/lib/services/mailer.js.map +1 -1
- package/lib/services/mailer.spec.js +86 -127
- package/lib/services/mailer.spec.js.map +1 -1
- package/lib/services/notificationservice.d.ts +4 -4
- package/lib/services/notificationservice.js +23 -42
- package/lib/services/notificationservice.js.map +1 -1
- package/lib/services/notificationservice.spec.js +47 -73
- package/lib/services/notificationservice.spec.js.map +1 -1
- package/lib/services/oauth.d.ts +32 -6
- package/lib/services/oauth.js +73 -78
- package/lib/services/oauth.js.map +1 -1
- package/lib/services/oauth.spec.js +128 -148
- package/lib/services/oauth.spec.js.map +1 -1
- package/lib/services/proxy.d.ts +74 -0
- package/lib/services/proxy.js +126 -0
- package/lib/services/proxy.js.map +1 -0
- package/lib/services/proxy.spec.d.ts +1 -0
- package/lib/services/proxy.spec.js +59 -0
- package/lib/services/proxy.spec.js.map +1 -0
- package/lib/services/resource.d.ts +2 -2
- package/lib/services/resource.js +12 -18
- package/lib/services/resource.js.map +1 -1
- package/lib/services/resource.spec.js +67 -99
- package/lib/services/resource.spec.js.map +1 -1
- package/lib/services/service.d.ts +29 -6
- package/lib/services/service.js +69 -39
- package/lib/services/service.js.map +1 -1
- package/lib/services/service.spec.js +62 -67
- package/lib/services/service.spec.js.map +1 -1
- package/lib/services/version.d.ts +1 -1
- package/lib/services/version.js +3 -8
- package/lib/services/version.js.map +1 -1
- package/lib/services/version.spec.js +11 -24
- package/lib/services/version.spec.js.map +1 -1
- package/lib/stores/aggregator.d.ts +3 -3
- package/lib/stores/aggregator.js +37 -57
- package/lib/stores/aggregator.js.map +1 -1
- package/lib/stores/file.d.ts +3 -3
- package/lib/stores/file.js +93 -131
- package/lib/stores/file.js.map +1 -1
- package/lib/stores/file.spec.d.ts +2 -2
- package/lib/stores/file.spec.js +262 -289
- package/lib/stores/file.spec.js.map +1 -1
- package/lib/stores/mapper.d.ts +4 -4
- package/lib/stores/mapper.js +111 -137
- package/lib/stores/mapper.js.map +1 -1
- package/lib/stores/mapper.spec.js +133 -150
- package/lib/stores/mapper.spec.js.map +1 -1
- package/lib/stores/memory.d.ts +67 -6
- package/lib/stores/memory.js +155 -117
- package/lib/stores/memory.js.map +1 -1
- package/lib/stores/memory.spec.d.ts +3 -2
- package/lib/stores/memory.spec.js +127 -105
- package/lib/stores/memory.spec.js.map +1 -1
- package/lib/stores/store.d.ts +40 -16
- package/lib/stores/store.js +847 -830
- package/lib/stores/store.js.map +1 -1
- package/lib/stores/store.spec.d.ts +6 -4
- package/lib/stores/store.spec.js +628 -647
- package/lib/stores/store.spec.js.map +1 -1
- package/lib/stores/webdaql/WebdaQLLexer.d.ts +4 -4
- package/lib/stores/webdaql/WebdaQLLexer.js +9 -13
- package/lib/stores/webdaql/WebdaQLLexer.js.map +1 -1
- package/lib/stores/webdaql/WebdaQLParserLexer.d.ts +4 -4
- package/lib/stores/webdaql/WebdaQLParserLexer.js +9 -13
- package/lib/stores/webdaql/WebdaQLParserLexer.js.map +1 -1
- package/lib/stores/webdaql/WebdaQLParserListener.d.ts +2 -2
- package/lib/stores/webdaql/WebdaQLParserListener.js +1 -2
- package/lib/stores/webdaql/WebdaQLParserListener.js.map +1 -1
- package/lib/stores/webdaql/WebdaQLParserParser.d.ts +10 -10
- package/lib/stores/webdaql/WebdaQLParserParser.js +62 -91
- package/lib/stores/webdaql/WebdaQLParserParser.js.map +1 -1
- package/lib/stores/webdaql/WebdaQLParserVisitor.d.ts +2 -2
- package/lib/stores/webdaql/WebdaQLParserVisitor.js +1 -2
- package/lib/stores/webdaql/WebdaQLParserVisitor.js.map +1 -1
- package/lib/stores/webdaql/query.d.ts +4 -5
- package/lib/stores/webdaql/query.js +16 -19
- package/lib/stores/webdaql/query.js.map +1 -1
- package/lib/stores/webdaql/query.spec.js +30 -32
- package/lib/stores/webdaql/query.spec.js.map +1 -1
- package/lib/test.d.ts +3 -3
- package/lib/test.js +74 -94
- package/lib/test.js.map +1 -1
- package/lib/unpackedapplication.d.ts +1 -1
- package/lib/unpackedapplication.js +44 -38
- package/lib/unpackedapplication.js.map +1 -1
- package/lib/utils/abstractdeployer.js +1 -5
- package/lib/utils/abstractdeployer.js.map +1 -1
- package/lib/utils/abstractdeployer.spec.js +6 -8
- package/lib/utils/abstractdeployer.spec.js.map +1 -1
- package/lib/utils/context.d.ts +61 -29
- package/lib/utils/context.js +133 -127
- package/lib/utils/context.js.map +1 -1
- package/lib/utils/context.spec.js +144 -153
- package/lib/utils/context.spec.js.map +1 -1
- package/lib/utils/cookie.d.ts +66 -45
- package/lib/utils/cookie.js +69 -158
- package/lib/utils/cookie.js.map +1 -1
- package/lib/utils/cookie.spec.js +220 -238
- package/lib/utils/cookie.spec.js.map +1 -1
- package/lib/utils/esm.d.ts +4 -0
- package/lib/utils/esm.js +10 -0
- package/lib/utils/esm.js.map +1 -0
- package/lib/utils/httpcontext.d.ts +3 -0
- package/lib/utils/httpcontext.js +48 -65
- package/lib/utils/httpcontext.js.map +1 -1
- package/lib/utils/httpcontext.spec.js +37 -56
- package/lib/utils/httpcontext.spec.js.map +1 -1
- package/lib/utils/logger.d.ts +2 -2
- package/lib/utils/logger.js +15 -28
- package/lib/utils/logger.js.map +1 -1
- package/lib/utils/logger.spec.js +9 -11
- package/lib/utils/logger.spec.js.map +1 -1
- package/lib/utils/serializers.js +17 -20
- package/lib/utils/serializers.js.map +1 -1
- package/lib/utils/serializers.spec.js +43 -44
- package/lib/utils/serializers.spec.js.map +1 -1
- package/lib/utils/session.d.ts +120 -0
- package/lib/utils/session.js +155 -0
- package/lib/utils/session.js.map +1 -0
- package/lib/utils/session.spec.d.ts +1 -0
- package/lib/utils/session.spec.js +66 -0
- package/lib/utils/session.spec.js.map +1 -0
- package/lib/utils/waiter.d.ts +1 -1
- package/lib/utils/waiter.js +32 -52
- package/lib/utils/waiter.js.map +1 -1
- package/lib/utils/waiter.spec.js +75 -92
- package/lib/utils/waiter.spec.js.map +1 -1
- package/package.json +22 -14
- package/test/config-invitation.json +1 -3
- package/test/config.json +3 -3
- package/test/config.old.json +1 -2
- package/test/moddas/annotatedservice.js +5 -5
- package/test/moddas/debugmailer.js +2 -3
- package/test/moddas/fakeservice.js +2 -3
- package/test/moddas/voidstore.js +6 -4
- package/test/models/ident.js +2 -6
- package/test/models/task.js +3 -7
- package/test/package.json +2 -1
- package/webda.module.json +895 -189
package/lib/stores/store.js
CHANGED
|
@@ -1,40 +1,31 @@
|
|
|
1
|
-
|
|
2
|
-
var
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
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
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
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
|
-
|
|
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
|
|
24
|
+
export class StoreParameters extends ServiceParameters {
|
|
33
25
|
constructor(params, service) {
|
|
34
|
-
var _a
|
|
35
|
-
var _e;
|
|
26
|
+
var _a;
|
|
36
27
|
super(params);
|
|
37
|
-
|
|
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
|
-
(
|
|
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
|
-
|
|
63
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
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
|
-
|
|
191
|
-
|
|
192
|
-
|
|
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
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
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: `
|
|
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
|
-
|
|
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
|
-
|
|
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(
|
|
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(
|
|
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
|
-
|
|
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 (
|
|
442
|
-
|
|
443
|
-
for (
|
|
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.
|
|
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
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
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 =
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
this
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
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
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
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
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
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
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
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
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
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
|
-
|
|
505
|
+
catch (err) {
|
|
598
506
|
continue;
|
|
599
507
|
}
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
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
|
-
|
|
609
|
-
|
|
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
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
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
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
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
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
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
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
object
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
object
|
|
699
|
-
|
|
700
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
if (
|
|
770
|
-
|
|
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]
|
|
687
|
+
model[prop].push(item);
|
|
779
688
|
}
|
|
780
|
-
|
|
781
|
-
|
|
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
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
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
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
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
|
-
|
|
873
|
-
|
|
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
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
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
|
-
|
|
906
|
-
|
|
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
|
|
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
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
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
|
-
|
|
955
|
-
|
|
956
|
-
|
|
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
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
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
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
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
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
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
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
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
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
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
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
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
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
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
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
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
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
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
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
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
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
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
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
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
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
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
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
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
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
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
|
-
|
|
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
|