@sap/xsodata 8.3.0 → 8.3.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/CHANGELOG.md +4 -0
- package/index.js +2 -2
- package/lib/configuration.js +1 -1
- package/lib/db/connect.js +1 -1
- package/lib/db/dbSegment.js +68 -123
- package/lib/db/dbVersionChecks.js +2 -8
- package/lib/handlerConfiguration.js +2 -2
- package/lib/http/conditionalHttpHandler.js +27 -34
- package/lib/http/simpleHttpRequest.js +14 -18
- package/lib/http/simpleHttpResponse.js +4 -4
- package/lib/http/uriParser.js +9 -9
- package/lib/http/validator/httpRequestValidator.js +9 -9
- package/lib/model/annotationFactory.js +11 -11
- package/lib/model/association.js +3 -3
- package/lib/model/entityType.js +33 -67
- package/lib/model/metadataReader.js +31 -52
- package/lib/model/model.js +0 -1
- package/lib/model/validator/xsoDataConcurrencyTokenValidator.js +6 -6
- package/lib/model/xsodataReader.js +36 -28
- package/lib/processor/authorizationProcessor.js +22 -33
- package/lib/processor/batchProcessor.js +22 -33
- package/lib/processor/errorProcessor.js +4 -4
- package/lib/processor/exitProcessor.js +19 -19
- package/lib/processor/processor.js +9 -9
- package/lib/processor/resourceProcessor.js +31 -61
- package/lib/processor/resourceProcessorDelete.js +16 -16
- package/lib/processor/resourceProcessorDeleteLinks.js +25 -25
- package/lib/processor/resourceProcessorGet.js +5 -5
- package/lib/processor/resourceProcessorPost.js +43 -45
- package/lib/processor/resourceProcessorPut.js +35 -39
- package/lib/processor/resourceProcessorPutPostLinks.js +38 -39
- package/lib/security/securityContext.js +5 -5
- package/lib/serializer/atomSerializer.js +54 -55
- package/lib/serializer/atomXmlToJsonSerializer.js +32 -44
- package/lib/serializer/content.js +5 -5
- package/lib/serializer/json.js +31 -33
- package/lib/serializer/jsonSerializer.js +4 -4
- package/lib/serializer/metadataSerializer.js +32 -35
- package/lib/serializer/serializer.js +29 -43
- package/lib/serializer/serviceSerializer.js +19 -24
- package/lib/serializer/value.js +1 -2
- package/lib/serializer/xmlToJsonSerializer.js +18 -18
- package/lib/sql/createDeleteLinksStatements.js +10 -10
- package/lib/sql/createDeleteStatements.js +12 -12
- package/lib/sql/createGetStatements.js +49 -107
- package/lib/sql/createLinksSQLStatements_1_n.js +27 -27
- package/lib/sql/createPutPostLinksStatements.js +9 -9
- package/lib/sql/createPutStatements.js +0 -1
- package/lib/sql/dataCollectorDelete.js +9 -9
- package/lib/sql/dataCollectorDeleteLinks.js +3 -3
- package/lib/sql/dataCollectorGet.js +9 -17
- package/lib/sql/dataCollectorLinks.js +23 -27
- package/lib/sql/dataCollectorPost.js +20 -20
- package/lib/sql/dataCollectorPut.js +36 -36
- package/lib/sql/dataCollectorPutPostLinks.js +3 -3
- package/lib/sql/sqlStatement.js +81 -128
- package/lib/sql/sqlTools.js +3 -7
- package/lib/sql/statementProcessor.js +7 -14
- package/lib/uri/applyChecks.js +3 -3
- package/lib/uri/checks/checkAllowedMethod.js +3 -3
- package/lib/uri/checks/checkAllowedMethodForBatch.js +2 -2
- package/lib/uri/checks/checkAllowedMethodsForResourcePath.js +3 -3
- package/lib/uri/checks/checkFilterOnAggregatedColumn.js +5 -5
- package/lib/uri/checks/checkFilterOrderByOnGenKeyColumn.js +6 -6
- package/lib/uri/checks/checkGenKeyRestrictions.js +2 -2
- package/lib/uri/checks/checkModificationForbidden.js +3 -3
- package/lib/uri/checks/checkPostPutDeleteChecks.js +5 -5
- package/lib/uri/checks/checkSystemQueryOptions.js +10 -10
- package/lib/uri/checks.js +15 -15
- package/lib/uri/expandSelectTreeBuilder.js +12 -16
- package/lib/uri/oDataUriParser.js +20 -20
- package/lib/uri/queryParameterParser.js +25 -33
- package/lib/uri/resourcePathParser.js +47 -62
- package/lib/uri/uriType.js +4 -4
- package/lib/utils/associations.js +4 -4
- package/lib/utils/batch/batchExecutor.js +49 -51
- package/lib/utils/batch/batchObjects.js +10 -10
- package/lib/utils/batch/batchParser.js +27 -28
- package/lib/utils/batch/batchWriter.js +1 -1
- package/lib/utils/checkContentType.js +34 -39
- package/lib/utils/debugView.js +35 -36
- package/lib/utils/errors/applicationError.js +2 -2
- package/lib/utils/errors/debugInfo.js +2 -2
- package/lib/utils/errors/http/badRequest.js +2 -2
- package/lib/utils/errors/http/forbidden.js +2 -2
- package/lib/utils/errors/http/methodNotAllowed.js +2 -2
- package/lib/utils/errors/http/notAcceptable.js +2 -2
- package/lib/utils/errors/http/notFound.js +2 -2
- package/lib/utils/errors/http/notImplemented.js +2 -2
- package/lib/utils/errors/http/notModified.js +2 -2
- package/lib/utils/errors/http/notSupported.js +2 -2
- package/lib/utils/errors/http/preconditionFailed.js +2 -2
- package/lib/utils/errors/http/preconditionRequired.js +2 -2
- package/lib/utils/errors/http/unauthorized.js +2 -2
- package/lib/utils/errors/http/unsupportedMediaType.js +2 -2
- package/lib/utils/errors/httpError.js +2 -2
- package/lib/utils/errors/internalError.js +2 -2
- package/lib/utils/errors/modelFileError.js +2 -2
- package/lib/utils/errors/sqlError.js +2 -2
- package/lib/utils/errors/testError.js +2 -2
- package/lib/utils/errors/typeError.js +5 -5
- package/lib/utils/errors/xsODataError.js +1 -1
- package/lib/utils/logger.js +21 -32
- package/lib/utils/measurement.js +14 -13
- package/lib/utils/requestContext.js +2 -2
- package/lib/utils/stateMaschine.js +6 -6
- package/lib/utils/tableCleanup.js +3 -3
- package/lib/utils/typeConverter.js +21 -21
- package/lib/utils/typeConverters/converterTools.js +25 -331
- package/lib/utils/typeConverters/dbToJson.js +3 -3
- package/lib/utils/typeConverters/dbToUri.js +7 -7
- package/lib/utils/typeConverters/dbToXml.js +9 -9
- package/lib/utils/typeConverters/jsonToDb.js +20 -27
- package/lib/utils/typeConverters/uriToDb.js +45 -92
- package/lib/utils/typeConverters/xmlValueToJson.js +9 -13
- package/lib/utils/typedObjects.js +11 -79
- package/lib/utils/utils.js +20 -23
- package/lib/xsodata.js +37 -47
- package/package.json +3 -5
- package/.npmignore +0 -40
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
3
|
+
const StateMaschine = require('./../utils/stateMaschine');
|
|
4
|
+
const PreconditionFailedError = require('./../utils/errors/http/preconditionFailed');
|
|
5
|
+
const PreconditionRequiredError = require('./../utils/errors/http/preconditionRequired');
|
|
6
|
+
const NotModifiedError = require('./../utils/errors/http/notModified');
|
|
7
|
+
const BadRequestError = require('./../utils/errors/http/badRequest');
|
|
8
|
+
const NotFoundError = require('./../utils/errors/http/notFound');
|
|
9
|
+
const InternalError = require('./../utils/errors/internalError');
|
|
10
|
+
const uriTypes = require('./../uri/uriType');
|
|
11
11
|
|
|
12
12
|
function debug(context, text, arg1) {
|
|
13
13
|
if (context && context.logger && context.logger.debug) {
|
|
@@ -24,7 +24,7 @@ module.exports = ConditionalHttpHandler;
|
|
|
24
24
|
*@param {object} context Current xsodata context object
|
|
25
25
|
*/
|
|
26
26
|
function ConditionalHttpHandler(context) {
|
|
27
|
-
|
|
27
|
+
const states = createStates();
|
|
28
28
|
this._stateMaschine = new StateMaschine(states, context);
|
|
29
29
|
this.on = this._stateMaschine.on.bind(this._stateMaschine);
|
|
30
30
|
}
|
|
@@ -39,7 +39,7 @@ function ConditionalHttpHandler(context) {
|
|
|
39
39
|
ConditionalHttpHandler.processConditionalRequest =
|
|
40
40
|
function processConditionalRequest(context, asyncDone) {
|
|
41
41
|
|
|
42
|
-
|
|
42
|
+
const handler = new ConditionalHttpHandler(context);
|
|
43
43
|
|
|
44
44
|
handler.on("error", function (error) {
|
|
45
45
|
asyncDone(error, context);
|
|
@@ -101,7 +101,7 @@ function createStates() {
|
|
|
101
101
|
"Is conditional request supported 1": {
|
|
102
102
|
// We need more than one kind of this state because there will be different outcomes
|
|
103
103
|
action: function () {
|
|
104
|
-
|
|
104
|
+
const isSupported = isConditionalRequestSupported(this.getExternalContext());
|
|
105
105
|
debug(this.getExternalContext(),"Is conditional request supported 1: ", isSupported);
|
|
106
106
|
if (isSupported === true) {
|
|
107
107
|
this.next("Is concurrent entity 1");
|
|
@@ -113,7 +113,7 @@ function createStates() {
|
|
|
113
113
|
"Is conditional request supported 2": {
|
|
114
114
|
action: function () {
|
|
115
115
|
// We need more than one kind of this state because there will be different outcomes
|
|
116
|
-
|
|
116
|
+
const isSupported = isConditionalRequestSupported(this.getExternalContext());
|
|
117
117
|
debug(this.getExternalContext(),"Is conditional request supported 2: ", isSupported);
|
|
118
118
|
if (isSupported) {
|
|
119
119
|
this.next("428 Precondition required");
|
|
@@ -125,7 +125,7 @@ function createStates() {
|
|
|
125
125
|
"Is conditional request supported 3": {
|
|
126
126
|
action: function () {
|
|
127
127
|
// We need more than one kind of this state because there will be different outcomes
|
|
128
|
-
|
|
128
|
+
const isSupported = isConditionalRequestSupported(this.getExternalContext());
|
|
129
129
|
debug(this.getExternalContext(),"Is conditional request supported 3: ", isSupported);
|
|
130
130
|
if (isSupported) {
|
|
131
131
|
this.next("Is concurrent entity 3");
|
|
@@ -137,7 +137,7 @@ function createStates() {
|
|
|
137
137
|
"Is concurrent entity 1": {
|
|
138
138
|
action: function () {
|
|
139
139
|
// We need more than one kind of this state because there will be different outcomes
|
|
140
|
-
|
|
140
|
+
const hasToken = hasConcurrencyToken(this.getExternalContext());
|
|
141
141
|
debug(this.getExternalContext(),"Is concurrent entity 1: ", hasToken);
|
|
142
142
|
if (hasToken === true) {
|
|
143
143
|
this.next("Evaluate If-Match");
|
|
@@ -150,7 +150,7 @@ function createStates() {
|
|
|
150
150
|
"Is concurrent entity 2": {
|
|
151
151
|
action: function () {
|
|
152
152
|
// We need more than one kind of this state because there will be different outcomes
|
|
153
|
-
|
|
153
|
+
const hasToken = hasConcurrencyToken(this.getExternalContext());
|
|
154
154
|
debug(this.getExternalContext(),"Is concurrent entity 2: ", hasToken);
|
|
155
155
|
if (hasToken === true) {
|
|
156
156
|
this.next("Is conditional request supported 2");
|
|
@@ -163,7 +163,7 @@ function createStates() {
|
|
|
163
163
|
"Is concurrent entity 3": {
|
|
164
164
|
action: function () {
|
|
165
165
|
// We need more than one kind of this state because there will be different outcomes
|
|
166
|
-
|
|
166
|
+
const hasToken = hasConcurrencyToken(this.getExternalContext());
|
|
167
167
|
debug(this.getExternalContext(),"Is concurrent entity 3: ", hasToken);
|
|
168
168
|
if (hasToken === true) {
|
|
169
169
|
this.next("Evaluate If-None-Match");
|
|
@@ -175,8 +175,8 @@ function createStates() {
|
|
|
175
175
|
},
|
|
176
176
|
"Evaluate If-Match": {
|
|
177
177
|
action: function () {
|
|
178
|
-
|
|
179
|
-
ifMatchHeader = getHeader(this.getExternalContext(), "If-Match");
|
|
178
|
+
let etagTemp;
|
|
179
|
+
const ifMatchHeader = getHeader(this.getExternalContext(), "If-Match");
|
|
180
180
|
|
|
181
181
|
debug(this.getExternalContext(),"Evaluate If-Match");
|
|
182
182
|
debug(this.getExternalContext()," If-Match header: ", ifMatchHeader);
|
|
@@ -209,8 +209,8 @@ function createStates() {
|
|
|
209
209
|
},
|
|
210
210
|
"Evaluate If-None-Match": {
|
|
211
211
|
action: function () {
|
|
212
|
-
|
|
213
|
-
ifNoneMatchHeader = getHeader(this.getExternalContext(), "If-None-Match");
|
|
212
|
+
let etagTemp;
|
|
213
|
+
const ifNoneMatchHeader = getHeader(this.getExternalContext(), "If-None-Match");
|
|
214
214
|
|
|
215
215
|
debug(this.getExternalContext(),"Evaluate If-None-Match");
|
|
216
216
|
debug(this.getExternalContext()," If-None-Match header: ", ifNoneMatchHeader);
|
|
@@ -262,7 +262,7 @@ function createStates() {
|
|
|
262
262
|
},
|
|
263
263
|
"Is modification request": {
|
|
264
264
|
action: function () {
|
|
265
|
-
|
|
265
|
+
const isModification = isModificationRequest(this.getExternalContext());
|
|
266
266
|
debug(this.getExternalContext(),"Is modification request: ", isModification);
|
|
267
267
|
if (isModification){
|
|
268
268
|
this.next("Is concurrent entity 2");
|
|
@@ -317,7 +317,7 @@ function createStates() {
|
|
|
317
317
|
"UnexpectedError": {
|
|
318
318
|
action: function (source, error) {
|
|
319
319
|
debug(this.getExternalContext(),"UnexpectedError occured", error);
|
|
320
|
-
|
|
320
|
+
const context = this.getExternalContext();
|
|
321
321
|
throw new InternalError("Unexpected error", context, error);
|
|
322
322
|
}
|
|
323
323
|
}
|
|
@@ -358,7 +358,7 @@ function getHeader(context, name) {
|
|
|
358
358
|
*@return {boolean} true if the request is kind of modification else false
|
|
359
359
|
*/
|
|
360
360
|
function isModificationRequest(context) {
|
|
361
|
-
|
|
361
|
+
const method = context.request.method;
|
|
362
362
|
return method === "PUT" || method === "DELETE";
|
|
363
363
|
}
|
|
364
364
|
|
|
@@ -370,11 +370,6 @@ function isModificationRequest(context) {
|
|
|
370
370
|
*@return {boolean} true if the entity is a concurrent entity else false
|
|
371
371
|
*/
|
|
372
372
|
function hasConcurrencyToken(context) {
|
|
373
|
-
|
|
374
|
-
// if (!context.oData.dbSegment || !context.oData.dbSegment.entityType) {
|
|
375
|
-
// return false;
|
|
376
|
-
// }
|
|
377
|
-
|
|
378
373
|
return context.oData.dbSegment.entityType.hasConcurrencyToken();
|
|
379
374
|
}
|
|
380
375
|
|
|
@@ -388,7 +383,7 @@ function hasConcurrencyToken(context) {
|
|
|
388
383
|
*/
|
|
389
384
|
function getEtag(context, callback) {
|
|
390
385
|
/*jshint validthis:true */
|
|
391
|
-
|
|
386
|
+
const self = this;
|
|
392
387
|
if (self._cachedEtag) {
|
|
393
388
|
callback(null, self._cachedEtag);
|
|
394
389
|
} else {
|
|
@@ -407,11 +402,9 @@ function getEtag(context, callback) {
|
|
|
407
402
|
*@return {boolean} true if the request is supported else false
|
|
408
403
|
*/
|
|
409
404
|
function isConditionalRequestSupported(context) {
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
uriType === uriTypes.URI5B || uriType === uriTypes.URI6A;
|
|
413
|
-
|
|
414
|
-
isSupported = context.request.method !== "POST" && isSupported;
|
|
405
|
+
const uriType = context.uriTree.uriType;
|
|
406
|
+
const isSupported = context.request.method !== "POST" && (uriType === uriTypes.URI2 || uriType === uriTypes.URI5A ||
|
|
407
|
+
uriType === uriTypes.URI5B || uriType === uriTypes.URI6A);
|
|
415
408
|
|
|
416
409
|
return isSupported;
|
|
417
410
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
const _ = require('lodash');
|
|
4
|
+
const utils = require('./../utils/utils');
|
|
5
|
+
const bodyParser = require('body-parser');
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Load the limit information from the xsodata file
|
|
@@ -21,7 +21,7 @@ function getLimit(context, name) {
|
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
module.exports.createRequest = function (originalRequest, context) {
|
|
24
|
-
|
|
24
|
+
let request = {
|
|
25
25
|
headers: {}
|
|
26
26
|
};
|
|
27
27
|
|
|
@@ -57,13 +57,10 @@ module.exports.createRequest = function (originalRequest, context) {
|
|
|
57
57
|
}
|
|
58
58
|
|
|
59
59
|
|
|
60
|
-
|
|
60
|
+
const parser = bodyParser.raw({ type: '*/*', limit: maxBodySize });
|
|
61
61
|
|
|
62
62
|
parser(originalRequest, null, function next(err) {
|
|
63
|
-
|
|
64
|
-
// throw new BadRequest('Error while parsing http content', null, err);
|
|
65
|
-
//}
|
|
66
|
-
var body = originalRequest.body;
|
|
63
|
+
const body = originalRequest.body;
|
|
67
64
|
return cb(err, body.toString('utf8'));
|
|
68
65
|
});
|
|
69
66
|
|
|
@@ -74,24 +71,23 @@ module.exports.createRequest = function (originalRequest, context) {
|
|
|
74
71
|
};
|
|
75
72
|
|
|
76
73
|
module.exports.createRequestFromAppHttp = function (appHttp, options) {
|
|
77
|
-
|
|
78
|
-
var appData = appHttp.rawData;
|
|
74
|
+
const appData = appHttp.rawData;
|
|
79
75
|
|
|
80
|
-
|
|
76
|
+
const s = appData.url.split(' ');
|
|
81
77
|
if (s.length !== 3) {
|
|
82
78
|
throw new Error('Invalid URI format inside batch request.');
|
|
83
79
|
}
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
80
|
+
const method = s[0];
|
|
81
|
+
let uri = s[1];
|
|
82
|
+
const version = s[2];
|
|
87
83
|
|
|
88
|
-
|
|
84
|
+
const body = appData.payload.join('\r\n');
|
|
89
85
|
|
|
90
86
|
if (uri.substr(0, 1) !== '/') {
|
|
91
87
|
uri = '/' + uri;
|
|
92
88
|
}
|
|
93
89
|
|
|
94
|
-
request = {
|
|
90
|
+
const request = {
|
|
95
91
|
httpVersion: version,
|
|
96
92
|
headers: utils.clone(appData.headers),
|
|
97
93
|
method: method,
|
|
@@ -113,7 +109,7 @@ module.exports.createRequestFromAppHttp = function (appHttp, options) {
|
|
|
113
109
|
};
|
|
114
110
|
|
|
115
111
|
function createUrlData(request) {
|
|
116
|
-
|
|
112
|
+
const protocol = request.connection && request.connection.encrypted ? 'https' : 'http';
|
|
117
113
|
|
|
118
114
|
return {
|
|
119
115
|
host: request.headers['x-forwarded-host'] || request.headers.host,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
const _ = require('lodash');
|
|
4
|
+
const http = require('http');
|
|
5
5
|
|
|
6
6
|
module.exports.createResponse = function () {
|
|
7
7
|
return new SimpleResponse();
|
|
@@ -41,8 +41,8 @@ SimpleResponse.prototype.end = function () {
|
|
|
41
41
|
};
|
|
42
42
|
|
|
43
43
|
SimpleResponse.prototype.writeToBatchResponse = function (response,contentId) {
|
|
44
|
-
|
|
45
|
-
|
|
44
|
+
let value;
|
|
45
|
+
const headers = this.headers;
|
|
46
46
|
response.write('HTTP/1.1 ' + this.statusCode + ' ' + http.STATUS_CODES['' + this.statusCode] + '\r\n');
|
|
47
47
|
|
|
48
48
|
Object.keys(headers).forEach(function (key) {
|
package/lib/http/uriParser.js
CHANGED
|
@@ -16,13 +16,13 @@
|
|
|
16
16
|
*/
|
|
17
17
|
|
|
18
18
|
//Includes
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
19
|
+
const url = require('url');
|
|
20
|
+
const Http404_NotFound = require('./../utils/errors/http/notFound');
|
|
21
|
+
const _ = require('lodash');
|
|
22
|
+
const Measurement = require('./../utils/measurement');
|
|
23
23
|
|
|
24
24
|
function extractSegments(pathname) {
|
|
25
|
-
|
|
25
|
+
let i,
|
|
26
26
|
s = pathname.split('/'),
|
|
27
27
|
segments = {};
|
|
28
28
|
|
|
@@ -59,7 +59,7 @@ exports.prepareUri = function (context, asyncDone) {
|
|
|
59
59
|
///E.g. ///url
|
|
60
60
|
context.logger.silly('http', 'prepareUri');
|
|
61
61
|
|
|
62
|
-
|
|
62
|
+
const uriTree = context.uriTree = {};
|
|
63
63
|
|
|
64
64
|
uriTree.rawUrl = context.request.url; //may contain a xsodata file in first segment or not
|
|
65
65
|
uriTree.rawUrlParts = Measurement.measureSync(url.parse, uriTree.rawUrl, true, 'url.parse');
|
|
@@ -86,7 +86,7 @@ exports.prepareUri = function (context, asyncDone) {
|
|
|
86
86
|
uriTree.segments.raw.shift();
|
|
87
87
|
|
|
88
88
|
//build baseUrl
|
|
89
|
-
|
|
89
|
+
const urlData = {
|
|
90
90
|
protocol: context.request.urlData.proto,
|
|
91
91
|
host: context.request.urlData.host,
|
|
92
92
|
pathname: determineBasePath(context.request.baseUrl + '/' + uriTree.xsoFile, uriTree.segments.decoded, context.request.urlData)
|
|
@@ -98,7 +98,7 @@ exports.prepareUri = function (context, asyncDone) {
|
|
|
98
98
|
|
|
99
99
|
//USE Case this instance of the xsodata handler only processes a single xsodata file
|
|
100
100
|
//so the name of this odata file MUST NOT inside the url
|
|
101
|
-
|
|
101
|
+
const tmp2 = {
|
|
102
102
|
protocol: context.request.urlData.proto,
|
|
103
103
|
host: context.request.urlData.host,
|
|
104
104
|
pathname: determineBasePath(context.request.baseUrl, uriTree.segments.decoded, context.request.urlData)
|
|
@@ -114,7 +114,7 @@ exports._getSegments = extractSegments;
|
|
|
114
114
|
|
|
115
115
|
function determineBasePath(uriPrefix, urlSegmentsNoXso, urlData){
|
|
116
116
|
if (urlData.forwarded){
|
|
117
|
-
|
|
117
|
+
const fSegs = extractSegments(urlData.path).decoded;
|
|
118
118
|
return _.dropRight(fSegs, urlSegmentsNoXso.length).join('/') + '/';
|
|
119
119
|
}
|
|
120
120
|
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
const async = require("async");
|
|
4
|
+
const NotSupportedError = require("./../../utils/errors/http/notSupported");
|
|
5
|
+
const contentTypeTools = require("./../../utils/checkContentType");
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
const api = module.exports = {
|
|
8
8
|
validate: validate,
|
|
9
9
|
_validateHttpHeader: _validateHttpHeader,
|
|
10
10
|
_validateAcceptHeader: _validateAcceptHeader
|
|
@@ -18,7 +18,7 @@ var api = module.exports = {
|
|
|
18
18
|
* function(error, context){}
|
|
19
19
|
*/
|
|
20
20
|
function validate(context, done) {
|
|
21
|
-
|
|
21
|
+
const validationStrategy = getValidationStrategy(context);
|
|
22
22
|
|
|
23
23
|
context.logger.silly("httpRequestValidator", "validate");
|
|
24
24
|
|
|
@@ -53,14 +53,14 @@ function _validateHttpHeader(context, done) {
|
|
|
53
53
|
* function(error, context){}
|
|
54
54
|
*/
|
|
55
55
|
function _validateAcceptHeader(context, done) {
|
|
56
|
-
|
|
56
|
+
const acceptHeader = context.request.headers["accept"] || context.request.headers["Accept"];
|
|
57
57
|
|
|
58
58
|
context.logger.silly("httpRequestValidator", "validateAcceptHeader");
|
|
59
59
|
|
|
60
60
|
if (!acceptHeader) {
|
|
61
61
|
return done(new NotSupportedError("A valid http Accept header must be provided"));
|
|
62
62
|
}
|
|
63
|
-
|
|
63
|
+
let contentType;
|
|
64
64
|
try {
|
|
65
65
|
contentType = contentTypeTools.checkEntry(context.request, getCustomFormat(context));
|
|
66
66
|
} catch (ex) {
|
|
@@ -98,7 +98,7 @@ function isBatchRequest(context) {
|
|
|
98
98
|
*@param {Object} context The xsodata context
|
|
99
99
|
*/
|
|
100
100
|
function getValidationStrategy(context) {
|
|
101
|
-
|
|
101
|
+
let initialStrategy;
|
|
102
102
|
|
|
103
103
|
context.logger.silly("httpRequestValidator", "getValidationStrategy");
|
|
104
104
|
|
|
@@ -123,7 +123,7 @@ function getValidationStrategy(context) {
|
|
|
123
123
|
* Returns value of the custom 'format' URL parameter.
|
|
124
124
|
*/
|
|
125
125
|
function getCustomFormat(context) {
|
|
126
|
-
|
|
126
|
+
const queryParameters = context.uriTree.queryParameters;
|
|
127
127
|
if (queryParameters) {
|
|
128
128
|
return queryParameters['format'];
|
|
129
129
|
}
|
|
@@ -2,28 +2,28 @@
|
|
|
2
2
|
|
|
3
3
|
// This module is used only internally from the entityType.js and is not intended to be used publicly.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
const EntityType = require('./entityType');
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Mapping of the values of SEMANTIC_TYPE column of the BIMC_DIMENSION_VIEW_HDI / BIMC_VARIABLE_VIEW_HDI DB views to
|
|
9
9
|
* the values of sap:semantics OData annotation, which is added to the EDM properties. Only the values in the map are
|
|
10
10
|
* supported.
|
|
11
11
|
*/
|
|
12
|
-
|
|
12
|
+
const SEMANTIC_MAPPINGS = {
|
|
13
13
|
"currencyCode": "currency-code",
|
|
14
14
|
"unitOfMeasure": "unit-of-measure",
|
|
15
15
|
"date.businessDateFrom": "dtstart",
|
|
16
16
|
"date.businessDateTo": "dtend"
|
|
17
17
|
};
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
const NAVIGATION_PROPERTY_ANNOTATIONS = {
|
|
20
20
|
"sap:creatable": "false", // deep inserts are not supported
|
|
21
21
|
"sap:filterable": "false" // for now, $filter is not supported for navigation properties
|
|
22
22
|
};
|
|
23
23
|
|
|
24
24
|
// Annotations for the association set, which connects CalcView input parameters (IP) entity set with the entity set
|
|
25
25
|
// representing the CalcView results. Such associations cannot be modified, i.e. $links requests are not supported.
|
|
26
|
-
|
|
26
|
+
const IP_ASSOCIATION_SET_ANNOTATIONS = {
|
|
27
27
|
"sap:creatable": "false",
|
|
28
28
|
"sap:updatable": "false",
|
|
29
29
|
"sap:deletable": "false"
|
|
@@ -55,7 +55,7 @@ exports.createPropertyAnnotations = createPropertyAnnotations;
|
|
|
55
55
|
* }
|
|
56
56
|
*/
|
|
57
57
|
function createPropertyAnnotations(entityType, property) {
|
|
58
|
-
|
|
58
|
+
const propertyAnnotations = {};
|
|
59
59
|
|
|
60
60
|
setPropertyParameter(property, propertyAnnotations);
|
|
61
61
|
setPropertyDisplayFormat(property, propertyAnnotations);
|
|
@@ -88,9 +88,9 @@ function setPropertyDisplayFormat(property, propertyAnnotations) {
|
|
|
88
88
|
|
|
89
89
|
function setPropertyLabel(property, propertyAnnotations) {
|
|
90
90
|
// depending on the property's kind, the different DB column (of the different DB table) contains the description
|
|
91
|
-
|
|
91
|
+
const labelColumn = property.KIND === EntityType.entityKind.inputParameters ? "DESCRIPTION" : "COLUMN_CAPTION";
|
|
92
92
|
|
|
93
|
-
|
|
93
|
+
const propertyLabel = property[labelColumn];
|
|
94
94
|
|
|
95
95
|
if (propertyLabel) {
|
|
96
96
|
propertyAnnotations["sap:label"] = propertyLabel;
|
|
@@ -100,7 +100,7 @@ function setPropertyLabel(property, propertyAnnotations) {
|
|
|
100
100
|
exports._setPropertySemantics = setPropertySemantics;
|
|
101
101
|
|
|
102
102
|
function setPropertySemantics(property, propertyAnnotations) {
|
|
103
|
-
|
|
103
|
+
let odataSemantic;
|
|
104
104
|
|
|
105
105
|
if (!property.SEMANTIC_TYPE) {
|
|
106
106
|
return;
|
|
@@ -143,7 +143,7 @@ function setPropertyText(property, propertyAnnotations) {
|
|
|
143
143
|
exports._setPropertyFilterRestriction = setPropertyFilterRestriction;
|
|
144
144
|
|
|
145
145
|
function setPropertyFilterRestriction(property, propertyAnnotations) {
|
|
146
|
-
|
|
146
|
+
const selectionType = property.SELECTION_TYPE,
|
|
147
147
|
multiline = property.MULTILINE;
|
|
148
148
|
|
|
149
149
|
if (selectionType === "SingleValue") {
|
|
@@ -173,7 +173,7 @@ exports.createEntityTypeAnnotations = createEntityTypeAnnotations;
|
|
|
173
173
|
* }
|
|
174
174
|
*/
|
|
175
175
|
function createEntityTypeAnnotations(entityType) {
|
|
176
|
-
|
|
176
|
+
const entityTypeAnnotations = {};
|
|
177
177
|
|
|
178
178
|
setEntityTypeSemantics(entityType, entityTypeAnnotations);
|
|
179
179
|
return entityTypeAnnotations;
|
|
@@ -204,7 +204,7 @@ exports.createEntitySetAnnotations = createEntitySetAnnotations;
|
|
|
204
204
|
* }
|
|
205
205
|
*/
|
|
206
206
|
function createEntitySetAnnotations(entityType) {
|
|
207
|
-
|
|
207
|
+
const entitySetAnnotations = {};
|
|
208
208
|
|
|
209
209
|
setEntitySetAddressable(entityType, entitySetAnnotations);
|
|
210
210
|
setEntitySetCreatable(entityType, entitySetAnnotations);
|
package/lib/model/association.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
module.exports = Association;
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
const utils = require('../utils/utils');
|
|
5
|
+
const _ = require('lodash');
|
|
6
|
+
const annotationFactory = require('./annotationFactory');
|
|
7
7
|
|
|
8
8
|
function Association(association) {
|
|
9
9
|
_.assign(this, utils.clone(association));
|