@sap/xsodata 8.2.1 → 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 +10 -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 +9 -6
- 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 +9 -11
- package/.npmignore +0 -40
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
const utils = require('./../utils');
|
|
4
|
+
const batchObjects = require('./batchObjects');
|
|
5
5
|
|
|
6
6
|
exports.getBoundary = function (headerValue) {
|
|
7
|
-
|
|
7
|
+
const l = headerValue.split(';');
|
|
8
8
|
|
|
9
|
-
for (
|
|
10
|
-
|
|
9
|
+
for (const element of l) {
|
|
10
|
+
const ll = element.split('=');
|
|
11
11
|
if (ll[0].trim() === 'boundary') {
|
|
12
12
|
return ll[1];
|
|
13
13
|
}
|
|
@@ -16,14 +16,14 @@ exports.getBoundary = function (headerValue) {
|
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
function readAppHttp(batchContent, boundary) {
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
const headers = {};
|
|
20
|
+
const payload = [];
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
let state = 0; //read url
|
|
23
|
+
const url = batchContent.readLine();
|
|
24
24
|
|
|
25
25
|
state = 1; //read header
|
|
26
|
-
|
|
26
|
+
let line = batchContent.lookLine();
|
|
27
27
|
|
|
28
28
|
while ((line !== null && line !== undefined) && line.indexOf(boundary) !== 0) {
|
|
29
29
|
if (state === 1) {
|
|
@@ -31,7 +31,7 @@ function readAppHttp(batchContent, boundary) {
|
|
|
31
31
|
state = 2; //read body
|
|
32
32
|
batchContent.inc();
|
|
33
33
|
} else {
|
|
34
|
-
|
|
34
|
+
const h = readHeader(line);
|
|
35
35
|
headers[h.name] = h.value;
|
|
36
36
|
batchContent.inc();
|
|
37
37
|
}
|
|
@@ -50,13 +50,13 @@ function readAppHttp(batchContent, boundary) {
|
|
|
50
50
|
|
|
51
51
|
|
|
52
52
|
function parsePart(batchContent, boundary) {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
53
|
+
const boundaryNext = boundary;
|
|
54
|
+
const boundaryEnd = boundary + '--';
|
|
55
|
+
const headers = {};
|
|
56
|
+
let content;
|
|
57
57
|
|
|
58
|
-
|
|
59
|
-
|
|
58
|
+
let state = 1; //read header
|
|
59
|
+
let line = batchContent.lookLine();
|
|
60
60
|
|
|
61
61
|
while ((line !== null && line !== undefined) && line !== boundaryNext && line !== boundaryEnd) {
|
|
62
62
|
if (state === 1) {
|
|
@@ -64,7 +64,7 @@ function parsePart(batchContent, boundary) {
|
|
|
64
64
|
state = 2; //read body
|
|
65
65
|
batchContent.inc();
|
|
66
66
|
} else {
|
|
67
|
-
|
|
67
|
+
const h = readHeader(line);
|
|
68
68
|
headers[h.name] = h.value;
|
|
69
69
|
batchContent.inc();
|
|
70
70
|
}
|
|
@@ -74,7 +74,7 @@ function parsePart(batchContent, boundary) {
|
|
|
74
74
|
} else if (headers['content-type'] === 'application/http') {
|
|
75
75
|
content = readAppHttp(batchContent, boundary);
|
|
76
76
|
} else if (utils.startsWith(headers['content-type'], 'multipart/mixed;')) {
|
|
77
|
-
|
|
77
|
+
const changeSetBoundary = exports.getBoundary(headers['content-type']);
|
|
78
78
|
content = parseBatch(batchContent, changeSetBoundary, "changeset");
|
|
79
79
|
} else {
|
|
80
80
|
//TODO not supported
|
|
@@ -87,18 +87,17 @@ function parsePart(batchContent, boundary) {
|
|
|
87
87
|
}
|
|
88
88
|
|
|
89
89
|
return content;
|
|
90
|
-
//return new batchObjects.BatchPart(headers, content);
|
|
91
90
|
}
|
|
92
91
|
|
|
93
92
|
|
|
94
93
|
function readHeader(line) {
|
|
95
|
-
|
|
94
|
+
const colPos = line.indexOf(':');
|
|
96
95
|
if (colPos === -1) {
|
|
97
96
|
throw new Error('Invalid header "content-type" in batch part');
|
|
98
97
|
}
|
|
99
98
|
|
|
100
|
-
|
|
101
|
-
|
|
99
|
+
const s0 = line.substr(0, colPos);
|
|
100
|
+
const s1 = line.substr(colPos + 1);
|
|
102
101
|
return {
|
|
103
102
|
name: s0.toLowerCase(),
|
|
104
103
|
value: s1.trim()
|
|
@@ -106,14 +105,14 @@ function readHeader(line) {
|
|
|
106
105
|
}
|
|
107
106
|
|
|
108
107
|
function parseBatch(content, boundary, type) {
|
|
109
|
-
|
|
110
|
-
|
|
108
|
+
const boundaryNext = '--' + boundary;
|
|
109
|
+
const boundaryEnd = '--' + boundary + '--';
|
|
111
110
|
|
|
112
|
-
|
|
111
|
+
const batch = new batchObjects.Batch(type);
|
|
113
112
|
|
|
114
|
-
|
|
113
|
+
let part;
|
|
115
114
|
|
|
116
|
-
|
|
115
|
+
let line = content.readLine();
|
|
117
116
|
while ((line !== null && line !== undefined) && line !== boundaryNext) { //read lines before first boundary
|
|
118
117
|
line = content.readLine();
|
|
119
118
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
//Includes
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
const Negotiator = require('negotiator');
|
|
5
|
+
const NotAcceptable = require('./../utils/errors/http/notAcceptable');
|
|
6
|
+
const UnsupportedMediaType = require('./../utils/errors/http/unsupportedMediaType');
|
|
7
7
|
|
|
8
8
|
exports.cTypes = {
|
|
9
9
|
ctJson: 'application/json',
|
|
@@ -22,11 +22,11 @@ exports.cTypes = {
|
|
|
22
22
|
fAtom: 'atom'
|
|
23
23
|
};
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
const cTypes = exports.cTypes;
|
|
26
26
|
|
|
27
27
|
exports.checkInputContentType = function (actual, expected) {
|
|
28
|
-
|
|
29
|
-
|
|
28
|
+
const cS = actual.split(';');
|
|
29
|
+
const type = cS[0];
|
|
30
30
|
|
|
31
31
|
if (type !== expected) {
|
|
32
32
|
throw new UnsupportedMediaType('Content-Type ' + type + ' not supported.');
|
|
@@ -41,7 +41,7 @@ exports.checkInputContentType = function (actual, expected) {
|
|
|
41
41
|
* @returns {boolean} true if actual equals expected, alse false
|
|
42
42
|
*/
|
|
43
43
|
function isContentType(actual, expected) {
|
|
44
|
-
|
|
44
|
+
let cS, type;
|
|
45
45
|
|
|
46
46
|
if (actual) {
|
|
47
47
|
cS = actual.split(';');
|
|
@@ -53,11 +53,7 @@ function isContentType(actual, expected) {
|
|
|
53
53
|
expected = expected.toLowerCase();
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
-
|
|
57
|
-
return true;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
return false;
|
|
56
|
+
return type === expected;
|
|
61
57
|
}
|
|
62
58
|
|
|
63
59
|
exports.isContentType = isContentType;
|
|
@@ -106,7 +102,7 @@ exports.isContentTypeJson = isContentTypeJson;
|
|
|
106
102
|
|
|
107
103
|
///Code
|
|
108
104
|
exports.checkServiceDocument = function (request, format) {
|
|
109
|
-
|
|
105
|
+
const def = cTypes.ctAxml;
|
|
110
106
|
|
|
111
107
|
//check $format
|
|
112
108
|
if (format === cTypes.fJson) {
|
|
@@ -124,16 +120,15 @@ exports.checkServiceDocument = function (request, format) {
|
|
|
124
120
|
}
|
|
125
121
|
|
|
126
122
|
//check header
|
|
127
|
-
|
|
123
|
+
const inOut = {};
|
|
128
124
|
inOut[cTypes.ctAst] = cTypes.ctAxml;
|
|
129
125
|
inOut[cTypes.ctAppast] = cTypes.ctAxml;
|
|
130
126
|
inOut[cTypes.ctJson] = cTypes.ctJson;
|
|
131
|
-
//inOut[cTypes.ctAtomSvc] = cTypes.ctAtomSvc;
|
|
132
127
|
inOut[cTypes.ctAxml] = cTypes.ctAxml;
|
|
133
128
|
|
|
134
|
-
|
|
129
|
+
const availableMediaTypes = [cTypes.ctAst, cTypes.ctAppast, cTypes.ctJson, /*cTypes.ctAtomSvc,*/ cTypes.ctAxml];
|
|
135
130
|
|
|
136
|
-
|
|
131
|
+
const match = new Negotiator(request).mediaType(availableMediaTypes);
|
|
137
132
|
if (!match) {
|
|
138
133
|
throw new NotAcceptable('Format not supported.');
|
|
139
134
|
}
|
|
@@ -141,7 +136,7 @@ exports.checkServiceDocument = function (request, format) {
|
|
|
141
136
|
};
|
|
142
137
|
|
|
143
138
|
exports.checkServiceMetadata = function (request, format) {
|
|
144
|
-
|
|
139
|
+
const def = cTypes.ctAxml;
|
|
145
140
|
|
|
146
141
|
//check $format
|
|
147
142
|
if (format === cTypes.fJson) {
|
|
@@ -159,14 +154,14 @@ exports.checkServiceMetadata = function (request, format) {
|
|
|
159
154
|
}
|
|
160
155
|
|
|
161
156
|
//check header
|
|
162
|
-
|
|
157
|
+
const inOut = {};
|
|
163
158
|
inOut[cTypes.ctAst] = cTypes.ctAxml;
|
|
164
159
|
inOut[cTypes.ctAppast] = cTypes.ctAxml;
|
|
165
160
|
inOut[cTypes.ctAxml] = cTypes.ctAxml;
|
|
166
161
|
|
|
167
|
-
|
|
162
|
+
const availableMediaTypes = [cTypes.ctAst, cTypes.ctAppast/*, cTypes.ctJson*/, cTypes.ctAtomSvc, cTypes.ctAxml];
|
|
168
163
|
|
|
169
|
-
|
|
164
|
+
const match = new Negotiator(request).mediaType(availableMediaTypes);
|
|
170
165
|
if (!match) {
|
|
171
166
|
throw new NotAcceptable('Format not supported.');
|
|
172
167
|
}
|
|
@@ -176,7 +171,7 @@ exports.checkServiceMetadata = function (request, format) {
|
|
|
176
171
|
|
|
177
172
|
|
|
178
173
|
exports.checkFeed = function (request, format) {
|
|
179
|
-
|
|
174
|
+
const def = cTypes.ctAtomFeed;
|
|
180
175
|
|
|
181
176
|
//check $format
|
|
182
177
|
if (format === cTypes.fJson) {
|
|
@@ -193,7 +188,7 @@ exports.checkFeed = function (request, format) {
|
|
|
193
188
|
}
|
|
194
189
|
|
|
195
190
|
//check header
|
|
196
|
-
|
|
191
|
+
const inOut = {};
|
|
197
192
|
inOut[cTypes.ctAst] = cTypes.ctAtomFeed;
|
|
198
193
|
inOut[cTypes.ctAppast] = cTypes.ctAtomFeed;
|
|
199
194
|
inOut[cTypes.ctJson] = cTypes.ctJson;
|
|
@@ -201,9 +196,9 @@ exports.checkFeed = function (request, format) {
|
|
|
201
196
|
inOut[cTypes.ctAtom] = cTypes.ctAtom;
|
|
202
197
|
inOut[cTypes.ctAtomFeed] = cTypes.ctAtomFeed;
|
|
203
198
|
|
|
204
|
-
|
|
199
|
+
const availableMediaTypes = [/*cTypes.ctAst, cTypes.ctAppast, */cTypes.ctJson/*, cTypes.ctAxml, cTypes.ctAtom, cTypes.ctAtomFeed*/];
|
|
205
200
|
|
|
206
|
-
|
|
201
|
+
const match = new Negotiator(request).mediaType(availableMediaTypes);
|
|
207
202
|
if (!match) {
|
|
208
203
|
throw new NotAcceptable('Format not supported.');
|
|
209
204
|
}
|
|
@@ -217,7 +212,7 @@ exports.checkFeed = function (request, format) {
|
|
|
217
212
|
|
|
218
213
|
exports.checkEntry = function (request, format) {
|
|
219
214
|
|
|
220
|
-
|
|
215
|
+
const def = cTypes.ctAtomEntry;
|
|
221
216
|
|
|
222
217
|
//check $format
|
|
223
218
|
if (format === cTypes.fJson) {
|
|
@@ -235,7 +230,7 @@ exports.checkEntry = function (request, format) {
|
|
|
235
230
|
}
|
|
236
231
|
|
|
237
232
|
//check header
|
|
238
|
-
|
|
233
|
+
const inOut = {};
|
|
239
234
|
inOut[cTypes.ctAst] = cTypes.ctAtomEntry;
|
|
240
235
|
inOut[cTypes.ctAppast] = cTypes.ctAtomEntry;
|
|
241
236
|
inOut[cTypes.ctJson] = cTypes.ctJson;
|
|
@@ -243,9 +238,9 @@ exports.checkEntry = function (request, format) {
|
|
|
243
238
|
inOut[cTypes.ctAtom] = cTypes.ctAtom;
|
|
244
239
|
inOut[cTypes.ctAtomEntry] = cTypes.ctAtomEntry;
|
|
245
240
|
|
|
246
|
-
|
|
241
|
+
const availableMediaTypes = [/*cTypes.ctAst, cTypes.ctAppast,*/ cTypes.ctJson/*, cTypes.ctPlain, cTypes.ctAxml, cTypes.ctAtom, cTypes.ctAtomFeed*/];
|
|
247
242
|
|
|
248
|
-
|
|
243
|
+
const match = new Negotiator(request).mediaType(availableMediaTypes);
|
|
249
244
|
if (!match) {
|
|
250
245
|
throw new NotAcceptable('Format not supported.');
|
|
251
246
|
}
|
|
@@ -259,7 +254,7 @@ exports.checkEntry = function (request, format) {
|
|
|
259
254
|
|
|
260
255
|
exports.checkProperty = function (request, format) {
|
|
261
256
|
|
|
262
|
-
|
|
257
|
+
const def = cTypes.ctAxml;
|
|
263
258
|
|
|
264
259
|
//check $format
|
|
265
260
|
if (format === cTypes.fJson) {
|
|
@@ -274,7 +269,7 @@ exports.checkProperty = function (request, format) {
|
|
|
274
269
|
}
|
|
275
270
|
|
|
276
271
|
//check header
|
|
277
|
-
|
|
272
|
+
const inOut = {};
|
|
278
273
|
inOut[cTypes.ctAst] = cTypes.ctAxml;
|
|
279
274
|
inOut[cTypes.ctTast] = cTypes.ctTxml;
|
|
280
275
|
inOut[cTypes.ctAppast] = cTypes.ctAxml;
|
|
@@ -282,9 +277,9 @@ exports.checkProperty = function (request, format) {
|
|
|
282
277
|
inOut[cTypes.ctTxml] = cTypes.ctTxml;
|
|
283
278
|
inOut[cTypes.ctAxml] = cTypes.ctAxml;
|
|
284
279
|
|
|
285
|
-
|
|
280
|
+
const availableMediaTypes = [/*cTypes.ctAst, cTypes.ctTast, cTypes.ctAppast,*/ cTypes.ctJson/*, cTypes.ctTxml, cTypes.ctAxml*/];
|
|
286
281
|
|
|
287
|
-
|
|
282
|
+
const match = new Negotiator(request).mediaType(availableMediaTypes);
|
|
288
283
|
if (!match) {
|
|
289
284
|
throw new NotAcceptable('Format not supported.');
|
|
290
285
|
}
|
|
@@ -311,14 +306,14 @@ exports.checkValue = function (request, format) {
|
|
|
311
306
|
}
|
|
312
307
|
|
|
313
308
|
//check header
|
|
314
|
-
|
|
309
|
+
const inOut = {};
|
|
315
310
|
inOut[cTypes.ctAst] = cTypes.ctPlain;
|
|
316
311
|
inOut[cTypes.ctTast] = cTypes.ctPlain;
|
|
317
312
|
inOut[cTypes.ctPlain] = cTypes.ctPlain;
|
|
318
313
|
|
|
319
|
-
|
|
314
|
+
const availableMediaTypes = [cTypes.ctAst, cTypes.ctTast, cTypes.ctPlain];
|
|
320
315
|
|
|
321
|
-
|
|
316
|
+
const match = new Negotiator(request).mediaType(availableMediaTypes);
|
|
322
317
|
if (!match) {
|
|
323
318
|
throw new NotAcceptable('Format not supported.');
|
|
324
319
|
}
|
|
@@ -344,14 +339,14 @@ exports.checkCount = function (request, format) {
|
|
|
344
339
|
}
|
|
345
340
|
|
|
346
341
|
//check header
|
|
347
|
-
|
|
342
|
+
const inOut = {};
|
|
348
343
|
inOut[cTypes.ctAst] = cTypes.ctPlain;
|
|
349
344
|
inOut[cTypes.ctTast] = cTypes.ctPlain;
|
|
350
345
|
inOut[cTypes.ctPlain] = cTypes.ctPlain;
|
|
351
346
|
|
|
352
|
-
|
|
347
|
+
const availableMediaTypes = [cTypes.ctAst, cTypes.ctTast, cTypes.ctPlain];
|
|
353
348
|
|
|
354
|
-
|
|
349
|
+
const match = new Negotiator(request).mediaType(availableMediaTypes);
|
|
355
350
|
if (!match) {
|
|
356
351
|
throw new NotAcceptable('Format not supported.');
|
|
357
352
|
}
|
package/lib/utils/debugView.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const sql = require('./../sql/sqlStatement');
|
|
5
|
+
const path = require('path');
|
|
6
6
|
|
|
7
7
|
//cache the css file
|
|
8
|
-
|
|
8
|
+
const styleCSS = fs.readFileSync(path.join(__dirname, '/style.css'));
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* Checks if query parameter "sap-ds-debug" exists, and if yes
|
|
@@ -15,7 +15,7 @@ var styleCSS = fs.readFileSync(path.join(__dirname, '/style.css'));
|
|
|
15
15
|
* @returns {*}
|
|
16
16
|
*/
|
|
17
17
|
exports.checkParameter = function (context, asyncDone) {
|
|
18
|
-
|
|
18
|
+
const showDebugViewFormat = context.uriTree.queryParameters["sap-ds-debug"];
|
|
19
19
|
|
|
20
20
|
if (showDebugViewFormat) {
|
|
21
21
|
context.debugView = { "format": showDebugViewFormat };
|
|
@@ -43,7 +43,7 @@ exports.writeDebugInfo = function (context, rFrom, rTo) {
|
|
|
43
43
|
|
|
44
44
|
function generateHead(responseHeaders, contentType) {
|
|
45
45
|
// clone the response headers using JSON
|
|
46
|
-
|
|
46
|
+
const debugHeaders = JSON.parse(JSON.stringify(responseHeaders));
|
|
47
47
|
|
|
48
48
|
// change the application type according to query parameters: e.g. json, html, ..
|
|
49
49
|
debugHeaders['Content-Type'] = contentType + ';charset=utf-8';
|
|
@@ -52,7 +52,7 @@ function generateHead(responseHeaders, contentType) {
|
|
|
52
52
|
}
|
|
53
53
|
|
|
54
54
|
function generateViewJSON(context) {
|
|
55
|
-
|
|
55
|
+
const debView = {
|
|
56
56
|
'request': {},
|
|
57
57
|
'response': {},
|
|
58
58
|
'server': {},
|
|
@@ -78,7 +78,7 @@ function generateViewJSON(context) {
|
|
|
78
78
|
}
|
|
79
79
|
|
|
80
80
|
function generateViewHTML(context) {
|
|
81
|
-
|
|
81
|
+
let debView = "<html>";
|
|
82
82
|
try {
|
|
83
83
|
debView += getHTMLHead();
|
|
84
84
|
debView += getHTMLBody(context);
|
|
@@ -95,7 +95,7 @@ function getHTMLHead() {
|
|
|
95
95
|
}
|
|
96
96
|
|
|
97
97
|
function getHTMLBody(context) {
|
|
98
|
-
|
|
98
|
+
let body = '<body>';
|
|
99
99
|
body += objectToHTML(createRequestInfo(context), 'Request', true);
|
|
100
100
|
body += objectToHTML(createResponseInfo(context), 'Response', true);
|
|
101
101
|
body += objectToHTML(createServerInfo(context), 'Server', true);
|
|
@@ -108,8 +108,8 @@ function getHTMLBody(context) {
|
|
|
108
108
|
}
|
|
109
109
|
|
|
110
110
|
function createRequestInfo(context) {
|
|
111
|
-
|
|
112
|
-
|
|
111
|
+
const req = {};
|
|
112
|
+
let pr, obj;
|
|
113
113
|
|
|
114
114
|
req.method = context.request.method;
|
|
115
115
|
req.uri = context.request.url;
|
|
@@ -126,8 +126,8 @@ function createRequestInfo(context) {
|
|
|
126
126
|
}
|
|
127
127
|
|
|
128
128
|
function createResponseInfo(context) {
|
|
129
|
-
|
|
130
|
-
|
|
129
|
+
const res = {};
|
|
130
|
+
let pr, obj;
|
|
131
131
|
|
|
132
132
|
res.status = context.response.statusCode;
|
|
133
133
|
res.headers = {};
|
|
@@ -143,9 +143,9 @@ function createResponseInfo(context) {
|
|
|
143
143
|
}
|
|
144
144
|
|
|
145
145
|
function createServerInfo(context) {
|
|
146
|
-
|
|
146
|
+
let pr, obj, prSub, segment;
|
|
147
147
|
|
|
148
|
-
|
|
148
|
+
const server = {
|
|
149
149
|
'version': '',
|
|
150
150
|
'dbVersion': '',
|
|
151
151
|
'environment': {},
|
|
@@ -162,22 +162,21 @@ function createServerInfo(context) {
|
|
|
162
162
|
server.environment.remoteAddr = context.httpResponse.connection.remoteAddress;
|
|
163
163
|
server.environment.remotePort = context.httpResponse.connection.remotePort;
|
|
164
164
|
server.environment.remoteFamily = context.httpResponse.connection.remoteFamily;
|
|
165
|
-
//server.environment = process.env;
|
|
166
165
|
|
|
167
166
|
//// Server.uri
|
|
168
167
|
////// Query parameters
|
|
169
168
|
obj = context.uriTree.queryParameters;
|
|
170
169
|
for (pr in obj) {
|
|
171
|
-
if (Object.prototype.hasOwnProperty.call(obj, pr) && pr.
|
|
170
|
+
if (Object.prototype.hasOwnProperty.call(obj, pr) && pr.startsWith('$')) { // ignore non-property parameters
|
|
172
171
|
prSub = pr.substring(1, pr.length); // ignore $ sign in the output
|
|
173
172
|
server.uri[prSub] = (prSub === 'select' ? obj[pr].split(',') : obj[pr]);
|
|
174
173
|
}
|
|
175
174
|
}
|
|
176
175
|
////// uriResourceParts
|
|
177
|
-
|
|
176
|
+
const segmentKind = ['empty', '', 'entity', 'resourceNavigation', 'property', 'count', 'navigation']; // read from dbSegment.js
|
|
178
177
|
server.uri.uriResourceParts = [];
|
|
179
178
|
segment = (context.oData === null ? null : context.oData.dbSegment);
|
|
180
|
-
|
|
179
|
+
let segObj;
|
|
181
180
|
while (typeof segment !== 'undefined' && segment !== null) {
|
|
182
181
|
segObj = {};
|
|
183
182
|
segObj.segment = segment._AliasName || "";
|
|
@@ -199,7 +198,7 @@ function createServerInfo(context) {
|
|
|
199
198
|
server.runtime = measurementsToObject(context.measurements);
|
|
200
199
|
|
|
201
200
|
function measurementsToObject(measurementsArr) {
|
|
202
|
-
|
|
201
|
+
const measurementsObj = {};
|
|
203
202
|
measurementsArr.forEach(function (m) {
|
|
204
203
|
measurementsObj[m.name] = {};
|
|
205
204
|
measurementsObj[m.name].duration = m.time + ' microSec';
|
|
@@ -223,11 +222,11 @@ function createSQLInfo(context) {
|
|
|
223
222
|
if (!context.sql) {
|
|
224
223
|
return;
|
|
225
224
|
}
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
225
|
+
const container = context.sql.container;
|
|
226
|
+
let i;
|
|
227
|
+
let tmp;
|
|
229
228
|
|
|
230
|
-
|
|
229
|
+
const out = {
|
|
231
230
|
createTmp: [],
|
|
232
231
|
insertTmp: [],
|
|
233
232
|
selectTmp: [],
|
|
@@ -249,14 +248,13 @@ function createSQLInfo(context) {
|
|
|
249
248
|
if (container.select[i].getFallbackStatement) {
|
|
250
249
|
tmp = container.select[i].getFallbackStatement();
|
|
251
250
|
if (tmp) {
|
|
252
|
-
//sqlLocal = 'Count Fallback: ' + tmp.toSqlHana(new sql.SqlBuildHanaContext(context), out.parameters);
|
|
253
251
|
out.select.push(stmToObject(tmp));
|
|
254
252
|
}
|
|
255
253
|
}
|
|
256
254
|
}
|
|
257
255
|
|
|
258
256
|
function stmToObject(stm) {
|
|
259
|
-
|
|
257
|
+
const sqlLocal = {
|
|
260
258
|
sql: null,
|
|
261
259
|
parameters: []
|
|
262
260
|
};
|
|
@@ -269,8 +267,8 @@ function createSQLInfo(context) {
|
|
|
269
267
|
|
|
270
268
|
|
|
271
269
|
function getXSOData(context) {
|
|
272
|
-
|
|
273
|
-
|
|
270
|
+
const xs = {};
|
|
271
|
+
let entity; // temporary variables
|
|
274
272
|
|
|
275
273
|
//// Database objects
|
|
276
274
|
xs['Database Objects'] = {};
|
|
@@ -319,9 +317,10 @@ function getXSOData(context) {
|
|
|
319
317
|
|
|
320
318
|
|
|
321
319
|
function createNavigationText(navigation) {
|
|
320
|
+
const principal = navigation.from.principal ? 'principal' : '-';
|
|
322
321
|
return navigation.association +
|
|
323
322
|
' as ' + navigation.name + ' from ' +
|
|
324
|
-
(navigation.from.dependent ? 'dependent' :
|
|
323
|
+
(navigation.from.dependent ? 'dependent' : principal);
|
|
325
324
|
}
|
|
326
325
|
|
|
327
326
|
function createAssociationEndText(association, end) {
|
|
@@ -338,10 +337,10 @@ function getXSOData(context) {
|
|
|
338
337
|
}
|
|
339
338
|
|
|
340
339
|
function serializeStacktrace(reponse) {
|
|
341
|
-
|
|
340
|
+
const error = JSON.parse(reponse).error;
|
|
342
341
|
|
|
343
|
-
|
|
344
|
-
|
|
342
|
+
let line = [];
|
|
343
|
+
const serliaized = {};
|
|
345
344
|
serliaized.exception = error.message.value;
|
|
346
345
|
serliaized.stack = error.message.stack.split(' at ').map(function (value) {
|
|
347
346
|
// input example: ResourcePathReader.processResourcePath (C:\\git\\xsodata\\lib\\uri\\resourcePathParser.js:275:34)
|
|
@@ -356,7 +355,7 @@ function serializeStacktrace(reponse) {
|
|
|
356
355
|
return value !== null;
|
|
357
356
|
}).map(function (value) {
|
|
358
357
|
try {
|
|
359
|
-
|
|
358
|
+
const node = {};
|
|
360
359
|
node.method = value[0];
|
|
361
360
|
node.path = value[1].split('.js')[0] + '.js'; // first segment before .js
|
|
362
361
|
node.line = value[1].split('.js')[1].split(':')[1]; // first segment after .js -> e.g. ':275:34'
|
|
@@ -374,8 +373,8 @@ function serializeStacktrace(reponse) {
|
|
|
374
373
|
}
|
|
375
374
|
|
|
376
375
|
function objectToHTML(objIn, varName, firstLevel) {
|
|
377
|
-
|
|
378
|
-
|
|
376
|
+
let pr;
|
|
377
|
+
let html = '';
|
|
379
378
|
if (firstLevel) {
|
|
380
379
|
html += '<div class="header" id="sec_' + varName + '">' +
|
|
381
380
|
'<h1><a href="#sec_' + varName + '">' + varName + '</a></h1>' +
|
|
@@ -419,7 +418,7 @@ function objectToHTML(objIn, varName, firstLevel) {
|
|
|
419
418
|
}
|
|
420
419
|
|
|
421
420
|
function sectionDownload() {
|
|
422
|
-
|
|
421
|
+
let html = '';
|
|
423
422
|
html += '<div class="header2" id="sec_download">' +
|
|
424
423
|
'<h1><a href="#sec_download"> Download </a></h1>' +
|
|
425
424
|
'</div>';
|