@opra/core 0.5.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cjs/adapter/adapter.js +103 -122
- package/cjs/adapter/classes/execution-context.host.js +17 -0
- package/cjs/adapter/classes/express-request-wrapper.host.js +37 -0
- package/cjs/adapter/classes/express-response-wrapper.host.js +56 -0
- package/cjs/adapter/classes/http-execution-context.host.js +31 -0
- package/cjs/adapter/{metadata-resource.js → classes/metadata.resource.js} +3 -3
- package/cjs/adapter/express-adapter.js +6 -104
- package/cjs/adapter/http-adapter.js +270 -68
- package/cjs/adapter/request-contexts/batch-request-context.js +12 -0
- package/cjs/adapter/{query-context.js → request-contexts/request-context.js} +8 -12
- package/cjs/adapter/request-contexts/single-request-context.js +15 -0
- package/cjs/index.js +2 -1
- package/cjs/interfaces/i18n-options.interface.js +2 -0
- package/cjs/services/json-collection-service.js +36 -39
- package/cjs/services/json-singleton-service.js +9 -10
- package/cjs/utils/create-i18n.js +2 -2
- package/esm/adapter/adapter.d.ts +13 -44
- package/esm/adapter/adapter.js +89 -108
- package/esm/adapter/classes/execution-context.host.d.ts +10 -0
- package/esm/adapter/classes/execution-context.host.js +13 -0
- package/esm/adapter/classes/express-request-wrapper.host.d.ts +19 -0
- package/esm/adapter/classes/express-request-wrapper.host.js +33 -0
- package/esm/adapter/classes/express-response-wrapper.host.d.ts +22 -0
- package/esm/adapter/classes/express-response-wrapper.host.js +52 -0
- package/esm/adapter/classes/http-execution-context.host.d.ts +13 -0
- package/esm/adapter/classes/http-execution-context.host.js +27 -0
- package/esm/adapter/classes/metadata.resource.d.ts +8 -0
- package/esm/adapter/{metadata-resource.js → classes/metadata.resource.js} +2 -2
- package/esm/adapter/express-adapter.d.ts +1 -1
- package/esm/adapter/express-adapter.js +5 -103
- package/esm/adapter/http-adapter.d.ts +23 -12
- package/esm/adapter/http-adapter.js +248 -46
- package/esm/adapter/request-contexts/batch-request-context.d.ts +7 -0
- package/esm/adapter/request-contexts/batch-request-context.js +8 -0
- package/esm/adapter/request-contexts/request-context.d.ts +22 -0
- package/esm/adapter/{query-context.js → request-contexts/request-context.js} +6 -10
- package/esm/adapter/request-contexts/single-request-context.d.ts +10 -0
- package/esm/adapter/request-contexts/single-request-context.js +11 -0
- package/esm/index.d.ts +2 -1
- package/esm/index.js +2 -1
- package/esm/interfaces/execution-context.interface.d.ts +19 -11
- package/esm/interfaces/i18n-options.interface.d.ts +28 -0
- package/esm/interfaces/i18n-options.interface.js +1 -0
- package/esm/interfaces/resource.interface.d.ts +1 -1
- package/esm/services/json-collection-service.d.ts +3 -4
- package/esm/services/json-collection-service.js +17 -20
- package/esm/services/json-singleton-service.d.ts +3 -3
- package/esm/services/json-singleton-service.js +8 -8
- package/esm/utils/create-i18n.d.ts +3 -3
- package/esm/utils/create-i18n.js +1 -1
- package/package.json +7 -8
- package/cjs/utils/path-to-tree.js +0 -28
- package/esm/adapter/metadata-resource.d.ts +0 -8
- package/esm/adapter/query-context.d.ts +0 -24
- package/esm/utils/path-to-tree.d.ts +0 -4
- package/esm/utils/path-to-tree.js +0 -24
|
@@ -2,49 +2,138 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.OpraHttpAdapter = void 0;
|
|
4
4
|
const common_1 = require("@opra/common");
|
|
5
|
-
const exception_1 = require("@opra/exception");
|
|
6
|
-
const schema_1 = require("@opra/schema");
|
|
7
|
-
const url_1 = require("@opra/url");
|
|
8
5
|
const adapter_js_1 = require("./adapter.js");
|
|
9
|
-
const
|
|
6
|
+
const single_request_context_js_1 = require("./request-contexts/single-request-context.js");
|
|
10
7
|
class OpraHttpAdapter extends adapter_js_1.OpraAdapter {
|
|
11
|
-
|
|
12
|
-
const req = executionContext.
|
|
13
|
-
|
|
14
|
-
if (
|
|
15
|
-
|
|
8
|
+
async parse(executionContext) {
|
|
9
|
+
const req = executionContext.getRequest();
|
|
10
|
+
const contentType = req.getHeader('content-type');
|
|
11
|
+
if (!contentType || contentType === 'application/json') {
|
|
12
|
+
const body = req.getBody();
|
|
13
|
+
const url = new common_1.OpraURL(req.getUrl());
|
|
14
|
+
return this.parseSingleQuery({
|
|
15
|
+
executionContext,
|
|
16
|
+
url,
|
|
17
|
+
method: req.getMethod(),
|
|
18
|
+
headers: req.getHeaders(),
|
|
19
|
+
body
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
if (typeof contentType === 'string' && contentType.startsWith('multipart/mixed')) {
|
|
23
|
+
// const m = BOUNDARY_PATTERN.exec(contentType);
|
|
24
|
+
// if (!m)
|
|
25
|
+
// throw new BadRequestError({message: 'Content-Type header does not match required format'});
|
|
26
|
+
// const url = new OpraURL(req.getUrl());
|
|
27
|
+
// return await this.parseMultiPart(executionContext, url, req.getHeaders(), req.getStream(), m[1]);
|
|
16
28
|
}
|
|
17
|
-
|
|
18
|
-
return [
|
|
19
|
-
this.prepareRequest(executionContext, url, req.getMethod(), new common_1.HeadersMap(req.getHeaders()), req.getBody())
|
|
20
|
-
];
|
|
29
|
+
throw new common_1.BadRequestError({ message: 'Unsupported Content-Type' });
|
|
21
30
|
}
|
|
22
|
-
|
|
31
|
+
parseSingleQuery(args) {
|
|
32
|
+
const { executionContext, url, method, headers, body, contentId } = args;
|
|
23
33
|
if (!url.path.size)
|
|
24
|
-
throw new
|
|
34
|
+
throw new common_1.BadRequestError();
|
|
25
35
|
if (method !== 'GET' && url.path.size > 1)
|
|
26
|
-
throw new
|
|
36
|
+
throw new common_1.BadRequestError();
|
|
27
37
|
const query = this.buildQuery(url, method, body);
|
|
28
38
|
if (!query)
|
|
29
|
-
throw new
|
|
39
|
+
throw new common_1.MethodNotAllowedError({
|
|
30
40
|
message: `Method "${method}" is not allowed by target endpoint`
|
|
31
41
|
});
|
|
32
|
-
return new
|
|
42
|
+
return new single_request_context_js_1.SingleRequestContext({
|
|
33
43
|
service: this.document,
|
|
34
44
|
executionContext,
|
|
45
|
+
headers,
|
|
35
46
|
query,
|
|
36
|
-
headers: new common_1.HeadersMap(),
|
|
37
47
|
params: url.searchParams,
|
|
48
|
+
contentId,
|
|
38
49
|
continueOnError: query.operation === 'read'
|
|
39
50
|
});
|
|
40
51
|
}
|
|
52
|
+
// async parseMultiPart(
|
|
53
|
+
// executionContext: TExecutionContext,
|
|
54
|
+
// url: OpraURL,
|
|
55
|
+
// headers: IncomingHttpHeaders,
|
|
56
|
+
// input: Readable,
|
|
57
|
+
// boundary: string
|
|
58
|
+
// ): Promise<BatchRequestContext> {
|
|
59
|
+
// return await new Promise((resolve, reject) => {
|
|
60
|
+
// let _resolved = false;
|
|
61
|
+
// const dicer = new Dicer({boundary});
|
|
62
|
+
// const doReject = (e) => {
|
|
63
|
+
// if (_resolved) return;
|
|
64
|
+
// _resolved = true;
|
|
65
|
+
// reject(e);
|
|
66
|
+
// taskQueue.clearQueue();
|
|
67
|
+
// dicer.destroy();
|
|
68
|
+
// }
|
|
69
|
+
// const taskQueue = new TaskQueue({concurrency: 1});
|
|
70
|
+
// taskQueue.on('error', doReject);
|
|
71
|
+
//
|
|
72
|
+
// const queries: SingleRequestContext[] = [];
|
|
73
|
+
// let partCounter = 0;
|
|
74
|
+
// dicer.on('error', doReject);
|
|
75
|
+
// dicer.on('part', part => {
|
|
76
|
+
// const partIndex = partCounter++;
|
|
77
|
+
// let header: any;
|
|
78
|
+
// const chunks: Buffer[] = [];
|
|
79
|
+
// part.on('error', doReject);
|
|
80
|
+
// part.on('header', (_header) => header = normalizeHeaders(_header));
|
|
81
|
+
// part.on('data', (chunk: Buffer) => chunks.push(chunk));
|
|
82
|
+
// part.on('end', () => {
|
|
83
|
+
// if (_resolved || !(header || chunks.length))
|
|
84
|
+
// return;
|
|
85
|
+
// const ct = header['content-type'];
|
|
86
|
+
// if (ct === 'application/http') {
|
|
87
|
+
// taskQueue.enqueue(async () => {
|
|
88
|
+
// const data = Buffer.concat(chunks);
|
|
89
|
+
// if (!(data && data.length))
|
|
90
|
+
// return;
|
|
91
|
+
// const r = HttpRequest.parse(data);
|
|
92
|
+
// await callMiddlewares(r, [jsonBodyParser]);
|
|
93
|
+
// const subUrl = new OpraURL(r.url);
|
|
94
|
+
// const contentId = header && header['content-id'];
|
|
95
|
+
// queries.push(this.parseSingleQuery({
|
|
96
|
+
// executionContext,
|
|
97
|
+
// url: subUrl,
|
|
98
|
+
// method: r.method,
|
|
99
|
+
// headers: r.headers,
|
|
100
|
+
// body: r.body,
|
|
101
|
+
// contentId
|
|
102
|
+
// }));
|
|
103
|
+
// });
|
|
104
|
+
// } else doReject(new BadRequestError({
|
|
105
|
+
// message: 'Unaccepted "content-type" header in multipart data',
|
|
106
|
+
// details: {
|
|
107
|
+
// position: `${boundary}[${partIndex}]`
|
|
108
|
+
// }
|
|
109
|
+
// }))
|
|
110
|
+
// });
|
|
111
|
+
// });
|
|
112
|
+
// dicer.on('finish', () => {
|
|
113
|
+
// taskQueue.enqueue(() => {
|
|
114
|
+
// if (_resolved) return;
|
|
115
|
+
// _resolved = true;
|
|
116
|
+
// const batch = new BatchRequestContext({
|
|
117
|
+
// service: this.document,
|
|
118
|
+
// executionContext,
|
|
119
|
+
// headers,
|
|
120
|
+
// queries,
|
|
121
|
+
// params: url.searchParams,
|
|
122
|
+
// continueOnError: false
|
|
123
|
+
// });
|
|
124
|
+
// resolve(batch);
|
|
125
|
+
// });
|
|
126
|
+
// });
|
|
127
|
+
// input.pipe(dicer);
|
|
128
|
+
// });
|
|
129
|
+
// }
|
|
41
130
|
buildQuery(url, method, body) {
|
|
42
131
|
const pathLen = url.path.size;
|
|
43
132
|
let p = url.path.get(0);
|
|
44
133
|
let resource = this._internalResources.get(p.resource) || this.document.getResource(p.resource);
|
|
45
134
|
let container;
|
|
46
135
|
let pathIndex = 0;
|
|
47
|
-
while (resource && resource instanceof
|
|
136
|
+
while (resource && resource instanceof common_1.ContainerResourceInfo) {
|
|
48
137
|
container = resource;
|
|
49
138
|
p = url.path.get(++pathIndex);
|
|
50
139
|
resource = container.getResource(p.resource);
|
|
@@ -52,19 +141,24 @@ class OpraHttpAdapter extends adapter_js_1.OpraAdapter {
|
|
|
52
141
|
try {
|
|
53
142
|
method = method.toUpperCase();
|
|
54
143
|
let query;
|
|
55
|
-
if (resource instanceof
|
|
144
|
+
if (resource instanceof common_1.SingletonResourceInfo && !p.key) {
|
|
56
145
|
switch (method) {
|
|
57
146
|
case 'GET': {
|
|
58
|
-
|
|
147
|
+
const searchParams = url.searchParams;
|
|
148
|
+
query = new common_1.SingletonGetQuery(resource, {
|
|
149
|
+
pick: searchParams.get('$pick'),
|
|
150
|
+
omit: searchParams.get('$omit'),
|
|
151
|
+
include: searchParams.get('$include')
|
|
152
|
+
});
|
|
59
153
|
}
|
|
60
154
|
}
|
|
61
155
|
}
|
|
62
|
-
else if (resource instanceof
|
|
156
|
+
else if (resource instanceof common_1.CollectionResourceInfo) {
|
|
63
157
|
switch (method) {
|
|
64
158
|
case 'GET': {
|
|
65
159
|
if (p.key) {
|
|
66
160
|
const searchParams = url.searchParams;
|
|
67
|
-
query = new
|
|
161
|
+
query = new common_1.CollectionGetQuery(resource, p.key, {
|
|
68
162
|
pick: searchParams.get('$pick'),
|
|
69
163
|
omit: searchParams.get('$omit'),
|
|
70
164
|
include: searchParams.get('$include')
|
|
@@ -72,7 +166,7 @@ class OpraHttpAdapter extends adapter_js_1.OpraAdapter {
|
|
|
72
166
|
}
|
|
73
167
|
else {
|
|
74
168
|
const searchParams = url.searchParams;
|
|
75
|
-
query = new
|
|
169
|
+
query = new common_1.CollectionSearchQuery(resource, {
|
|
76
170
|
filter: searchParams.get('$filter'),
|
|
77
171
|
limit: searchParams.get('$limit'),
|
|
78
172
|
skip: searchParams.get('$skip'),
|
|
@@ -89,8 +183,8 @@ class OpraHttpAdapter extends adapter_js_1.OpraAdapter {
|
|
|
89
183
|
case 'DELETE': {
|
|
90
184
|
const searchParams = url.searchParams;
|
|
91
185
|
query = p.key
|
|
92
|
-
? new
|
|
93
|
-
: new
|
|
186
|
+
? new common_1.CollectionDeleteQuery(resource, p.key)
|
|
187
|
+
: new common_1.CollectionDeleteManyQuery(resource, {
|
|
94
188
|
filter: searchParams.get('$filter'),
|
|
95
189
|
});
|
|
96
190
|
break;
|
|
@@ -98,7 +192,7 @@ class OpraHttpAdapter extends adapter_js_1.OpraAdapter {
|
|
|
98
192
|
case 'POST': {
|
|
99
193
|
if (!p.key) {
|
|
100
194
|
const searchParams = url.searchParams;
|
|
101
|
-
query = new
|
|
195
|
+
query = new common_1.CollectionCreateQuery(resource, body, {
|
|
102
196
|
pick: searchParams.get('$pick'),
|
|
103
197
|
omit: searchParams.get('$omit'),
|
|
104
198
|
include: searchParams.get('$include')
|
|
@@ -109,7 +203,7 @@ class OpraHttpAdapter extends adapter_js_1.OpraAdapter {
|
|
|
109
203
|
case 'PATCH': {
|
|
110
204
|
if (p.key) {
|
|
111
205
|
const searchParams = url.searchParams;
|
|
112
|
-
query = new
|
|
206
|
+
query = new common_1.CollectionUpdateQuery(resource, p.key, body, {
|
|
113
207
|
pick: searchParams.get('$pick'),
|
|
114
208
|
omit: searchParams.get('$omit'),
|
|
115
209
|
include: searchParams.get('$include')
|
|
@@ -117,7 +211,7 @@ class OpraHttpAdapter extends adapter_js_1.OpraAdapter {
|
|
|
117
211
|
}
|
|
118
212
|
else {
|
|
119
213
|
const searchParams = url.searchParams;
|
|
120
|
-
query = new
|
|
214
|
+
query = new common_1.CollectionUpdateManyQuery(resource, body, {
|
|
121
215
|
filter: searchParams.get('$filter')
|
|
122
216
|
});
|
|
123
217
|
}
|
|
@@ -126,8 +220,8 @@ class OpraHttpAdapter extends adapter_js_1.OpraAdapter {
|
|
|
126
220
|
}
|
|
127
221
|
}
|
|
128
222
|
else
|
|
129
|
-
throw new
|
|
130
|
-
if (query instanceof
|
|
223
|
+
throw new common_1.InternalServerError();
|
|
224
|
+
if (query instanceof common_1.SingletonGetQuery || query instanceof common_1.CollectionGetQuery || query instanceof common_1.FieldGetQuery) {
|
|
131
225
|
// Move through properties
|
|
132
226
|
let parentType;
|
|
133
227
|
const curPath = [];
|
|
@@ -135,68 +229,152 @@ class OpraHttpAdapter extends adapter_js_1.OpraAdapter {
|
|
|
135
229
|
while (++pathIndex < pathLen) {
|
|
136
230
|
p = url.path.get(pathIndex);
|
|
137
231
|
parentType = parent.dataType;
|
|
138
|
-
if (parent.dataType instanceof
|
|
232
|
+
if (parent.dataType instanceof common_1.UnionType) {
|
|
139
233
|
if (parent.dataType.name === 'any')
|
|
140
234
|
parentType = this.document.getComplexDataType('object');
|
|
141
235
|
else
|
|
142
236
|
throw new TypeError(`"${resource.name}.${curPath.join()}" is a UnionType and needs type casting.`);
|
|
143
237
|
}
|
|
144
|
-
if (!(parentType instanceof
|
|
238
|
+
if (!(parentType instanceof common_1.ComplexType))
|
|
145
239
|
throw new TypeError(`"${resource.name}.${curPath.join()}" is not a ComplexType and has no fields.`);
|
|
146
240
|
curPath.push(p.resource);
|
|
147
|
-
parent.child = new
|
|
241
|
+
parent.child = new common_1.FieldGetQuery(parent, p.resource, { castingType: parentType });
|
|
148
242
|
parent = parent.child;
|
|
149
243
|
}
|
|
150
244
|
}
|
|
151
245
|
return query;
|
|
152
246
|
}
|
|
153
247
|
catch (e) {
|
|
154
|
-
if (e instanceof
|
|
248
|
+
if (e instanceof common_1.OpraException)
|
|
155
249
|
throw e;
|
|
156
|
-
throw new
|
|
250
|
+
throw new common_1.BadRequestError(e);
|
|
157
251
|
}
|
|
158
252
|
}
|
|
159
|
-
async sendResponse(executionContext,
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
253
|
+
async sendResponse(executionContext, requestContext) {
|
|
254
|
+
// if (requestContext instanceof BatchRequestContext)
|
|
255
|
+
// return this.sendBatchResponse(executionContext, requestContext);
|
|
256
|
+
if (requestContext instanceof single_request_context_js_1.SingleRequestContext)
|
|
257
|
+
return this.sendSingleResponse(executionContext, requestContext);
|
|
258
|
+
/* istanbul ignore next */
|
|
259
|
+
throw new TypeError('Invalid request context instance');
|
|
260
|
+
}
|
|
261
|
+
// protected async sendBatchResponse(executionContext: TExecutionContext, requestContext: BatchRequestContext) {
|
|
262
|
+
// const resp = executionContext.getResponse();
|
|
263
|
+
// resp.setStatus(HttpStatus.OK);
|
|
264
|
+
// resp.setHeader(HttpHeaders.Cache_Control, 'no-cache');
|
|
265
|
+
// resp.setHeader(HttpHeaders.Pragma, 'no-cache');
|
|
266
|
+
// resp.setHeader(HttpHeaders.Expires, '-1');
|
|
267
|
+
// if (requestContext.headers) {
|
|
268
|
+
// for (const [k, v] of Object.entries(requestContext.headers)) {
|
|
269
|
+
// if (v)
|
|
270
|
+
// resp.setHeader(k, v);
|
|
271
|
+
// }
|
|
272
|
+
// }
|
|
273
|
+
// const boundary = 'batch_' + uuid();
|
|
274
|
+
// resp.setHeader(HttpHeaders.Content_Type, 'multipart/mixed;boundary=' + boundary);
|
|
275
|
+
// resp.setHeader(HttpHeaders.X_Opra_Version, OpraSchema.Version);
|
|
276
|
+
//
|
|
277
|
+
// const bodyBuilder = new HttpMultipartData();
|
|
278
|
+
//
|
|
279
|
+
// const chunks: any[] = [];
|
|
280
|
+
// let msgIdx = 0;
|
|
281
|
+
// for (const ctx of requestContext.queries) {
|
|
282
|
+
// msgIdx++;
|
|
283
|
+
// const out = this.createOutput(ctx);
|
|
284
|
+
//
|
|
285
|
+
//
|
|
286
|
+
// // chunks.push('--' + boundary + CRLF);
|
|
287
|
+
// // let s = 'Content-Type: application/http' + CRLF +
|
|
288
|
+
// // 'Content-Transfer-Encoding: binary' + CRLF +
|
|
289
|
+
// // 'Content-ID:' + (ctx.contentId || msgIdx) + CRLF +
|
|
290
|
+
// // CRLF +
|
|
291
|
+
// // 'HTTP/1.1 ' + out.status + (HttpStatus[out.status] || 'Unknown') + CRLF;
|
|
292
|
+
//
|
|
293
|
+
// let body = out.body;
|
|
294
|
+
// const headers = out.headers || {};
|
|
295
|
+
// if (body) {
|
|
296
|
+
// const contentType = String(headers['content-type'] || '').split(/\s*;\s*/);
|
|
297
|
+
// let charset = '';
|
|
298
|
+
// if (Highland.isStream(body)) {
|
|
299
|
+
// const l = parseInt(String(headers['content-length']), 10);
|
|
300
|
+
// if (isNaN(l))
|
|
301
|
+
// throw new TypeError('"content-length" header required for streamed responses');
|
|
302
|
+
// } else if (typeof body === 'object') {
|
|
303
|
+
// if (typeof body.stream === 'function') { // File and Blob
|
|
304
|
+
// contentType[0] = body.type || 'binary';
|
|
305
|
+
// headers['content-length'] = String(body.size);
|
|
306
|
+
// body = body.stream();
|
|
307
|
+
// } else if (Buffer.isBuffer(body)) {
|
|
308
|
+
// headers['content-length'] = String(body.length);
|
|
309
|
+
// } else {
|
|
310
|
+
// contentType[0] = contentType[0] || 'application/json';
|
|
311
|
+
// charset = 'utf-8';
|
|
312
|
+
// body = Buffer.from(JSON.stringify(body), 'utf-8');
|
|
313
|
+
// headers['content-length'] = String(body.length);
|
|
314
|
+
// }
|
|
315
|
+
// } else {
|
|
316
|
+
// contentType[0] = contentType[0] || 'text/plain';
|
|
317
|
+
// charset = 'utf-8';
|
|
318
|
+
// body = Buffer.from(String(body), 'utf-8');
|
|
319
|
+
// headers['content-length'] = String(body.length);
|
|
320
|
+
// }
|
|
321
|
+
// if (contentType[0]) {
|
|
322
|
+
// if (charset) {
|
|
323
|
+
// const i = contentType.findIndex(x => CHARSET_PATTERN.test(String(x)));
|
|
324
|
+
// if (i > 0) contentType[i] = 'charset=' + charset;
|
|
325
|
+
// else contentType.join('charset=' + charset);
|
|
326
|
+
// }
|
|
327
|
+
// headers['content-type'] = contentType.join(';');
|
|
328
|
+
// }
|
|
329
|
+
// }
|
|
330
|
+
// for (const [k, v] of Object.entries(headers))
|
|
331
|
+
// s += k + ': ' + (Array.isArray(v) ? v.join(';') : v) + CRLF
|
|
332
|
+
//
|
|
333
|
+
// chunks.push(s + CRLF);
|
|
334
|
+
//
|
|
335
|
+
// if (body) {
|
|
336
|
+
// if (typeof body === 'string')
|
|
337
|
+
// chunks.push(body + CRLF + CRLF);
|
|
338
|
+
// else {
|
|
339
|
+
// chunks.push(body);
|
|
340
|
+
// chunks.push(CRLF + CRLF);
|
|
341
|
+
// }
|
|
342
|
+
// }
|
|
343
|
+
// }
|
|
344
|
+
//
|
|
345
|
+
// chunks.push('--' + boundary + '--' + CRLF);
|
|
346
|
+
//
|
|
347
|
+
// resp.setHeader('content-type', 'multipart/mixed;boundary=' + boundary);
|
|
348
|
+
// resp.send(Highland(chunks).flatten());
|
|
349
|
+
// resp.end();
|
|
350
|
+
// }
|
|
351
|
+
async sendSingleResponse(executionContext, requestContext) {
|
|
352
|
+
const out = this.createOutput(requestContext);
|
|
353
|
+
const resp = executionContext.getResponse();
|
|
173
354
|
resp.setStatus(out.status);
|
|
174
|
-
resp.setHeader(common_1.HttpHeaders.Content_Type, 'application/json');
|
|
175
355
|
resp.setHeader(common_1.HttpHeaders.Cache_Control, 'no-cache');
|
|
176
356
|
resp.setHeader(common_1.HttpHeaders.Pragma, 'no-cache');
|
|
177
357
|
resp.setHeader(common_1.HttpHeaders.Expires, '-1');
|
|
178
|
-
resp.setHeader(common_1.HttpHeaders.X_Opra_Version, schema_1.OpraSchema.Version);
|
|
179
358
|
if (out.headers) {
|
|
180
359
|
for (const [k, v] of Object.entries(out.headers)) {
|
|
181
|
-
|
|
360
|
+
if (v)
|
|
361
|
+
resp.setHeader(k, v);
|
|
182
362
|
}
|
|
183
363
|
}
|
|
184
|
-
resp.
|
|
364
|
+
resp.setHeader(common_1.HttpHeaders.X_Opra_Version, common_1.OpraSchema.Version);
|
|
365
|
+
if (out.body)
|
|
366
|
+
resp.send(out.body);
|
|
185
367
|
resp.end();
|
|
186
368
|
}
|
|
187
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
188
|
-
isBatch(executionContext) {
|
|
189
|
-
return false;
|
|
190
|
-
}
|
|
191
369
|
createOutput(ctx) {
|
|
192
370
|
const { query } = ctx;
|
|
193
371
|
let body;
|
|
194
372
|
let status = ctx.status || 0;
|
|
195
|
-
const errors = ctx.errors.map(e => (0,
|
|
373
|
+
const errors = ctx.errors.map(e => (0, common_1.wrapException)(e));
|
|
196
374
|
if (errors && errors.length) {
|
|
197
375
|
// Sort errors from fatal to info
|
|
198
376
|
errors.sort((a, b) => {
|
|
199
|
-
const i =
|
|
377
|
+
const i = common_1.IssueSeverity.Keys.indexOf(a.issue.severity) - common_1.IssueSeverity.Keys.indexOf(b.issue.severity);
|
|
200
378
|
if (i === 0)
|
|
201
379
|
return b.status - a.status;
|
|
202
380
|
return i;
|
|
@@ -206,30 +384,35 @@ class OpraHttpAdapter extends adapter_js_1.OpraAdapter {
|
|
|
206
384
|
if (status < common_1.HttpStatus.BAD_REQUEST)
|
|
207
385
|
status = common_1.HttpStatus.INTERNAL_SERVER_ERROR;
|
|
208
386
|
}
|
|
209
|
-
body = {
|
|
387
|
+
body = this.i18n.deep({
|
|
210
388
|
operation: ctx.query.method,
|
|
211
389
|
errors: errors.map(e => e.issue)
|
|
212
|
-
};
|
|
390
|
+
});
|
|
391
|
+
body = JSON.stringify(body);
|
|
392
|
+
ctx.responseHeaders['content-type'] = 'application/json; charset=utf-8';
|
|
213
393
|
}
|
|
214
394
|
else {
|
|
215
|
-
|
|
395
|
+
if (typeof ctx.response === 'object' && !((0, common_1.isReadable)(ctx.response) || Buffer.isBuffer(ctx.response))) {
|
|
396
|
+
body = this.i18n.deep(ctx.response);
|
|
397
|
+
body = JSON.stringify(body);
|
|
398
|
+
ctx.responseHeaders['content-type'] = 'application/json; charset=utf-8';
|
|
399
|
+
}
|
|
216
400
|
status = status || (query.operation === 'create' ? common_1.HttpStatus.CREATED : common_1.HttpStatus.OK);
|
|
217
401
|
}
|
|
218
|
-
body = this.i18n.deep(body);
|
|
219
402
|
return {
|
|
220
403
|
status,
|
|
221
|
-
headers: ctx.responseHeaders
|
|
404
|
+
headers: (0, common_1.normalizeHeaders)(ctx.responseHeaders),
|
|
222
405
|
body
|
|
223
406
|
};
|
|
224
407
|
}
|
|
225
408
|
async sendError(executionContext, error) {
|
|
226
|
-
const resp = executionContext.
|
|
409
|
+
const resp = executionContext.getResponse();
|
|
227
410
|
resp.setStatus(error.status || 500);
|
|
228
411
|
resp.setHeader(common_1.HttpHeaders.Content_Type, 'application/json');
|
|
229
412
|
resp.setHeader(common_1.HttpHeaders.Cache_Control, 'no-cache');
|
|
230
413
|
resp.setHeader(common_1.HttpHeaders.Pragma, 'no-cache');
|
|
231
414
|
resp.setHeader(common_1.HttpHeaders.Expires, '-1');
|
|
232
|
-
resp.setHeader(common_1.HttpHeaders.X_Opra_Version,
|
|
415
|
+
resp.setHeader(common_1.HttpHeaders.X_Opra_Version, common_1.OpraSchema.Version);
|
|
233
416
|
const issue = this.i18n.deep(error.issue);
|
|
234
417
|
const body = {
|
|
235
418
|
operation: 'unknown',
|
|
@@ -239,3 +422,22 @@ class OpraHttpAdapter extends adapter_js_1.OpraAdapter {
|
|
|
239
422
|
}
|
|
240
423
|
}
|
|
241
424
|
exports.OpraHttpAdapter = OpraHttpAdapter;
|
|
425
|
+
// async function callMiddlewares(req: HttpRequest, middlewares: NextHandleFunction[]): Promise<void> {
|
|
426
|
+
// return new Promise<void>((resolve, reject) => {
|
|
427
|
+
// let i = 0;
|
|
428
|
+
// const next = (err?: any) => {
|
|
429
|
+
// if (err)
|
|
430
|
+
// return reject(err);
|
|
431
|
+
// const fn = middlewares[i++];
|
|
432
|
+
// if (!fn)
|
|
433
|
+
// return resolve();
|
|
434
|
+
// try {
|
|
435
|
+
// fn(req as any, {} as any, next);
|
|
436
|
+
// } catch (e) {
|
|
437
|
+
// reject(e);
|
|
438
|
+
// }
|
|
439
|
+
// }
|
|
440
|
+
// next();
|
|
441
|
+
// });
|
|
442
|
+
//
|
|
443
|
+
// }
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.BatchRequestContext = void 0;
|
|
4
|
+
const request_context_js_1 = require("./request-context.js");
|
|
5
|
+
class BatchRequestContext extends request_context_js_1.RequestContext {
|
|
6
|
+
queries;
|
|
7
|
+
constructor(args) {
|
|
8
|
+
super(args);
|
|
9
|
+
this.queries = args.queries;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
exports.BatchRequestContext = BatchRequestContext;
|
|
@@ -1,31 +1,27 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.RequestContext = void 0;
|
|
4
4
|
const common_1 = require("@opra/common");
|
|
5
|
-
|
|
6
|
-
class QueryContext {
|
|
5
|
+
class RequestContext {
|
|
7
6
|
service;
|
|
8
7
|
executionContext;
|
|
9
|
-
query;
|
|
10
8
|
params;
|
|
11
9
|
headers;
|
|
10
|
+
contentId;
|
|
12
11
|
parentValue;
|
|
13
12
|
resultPath;
|
|
14
13
|
responseHeaders;
|
|
15
14
|
response;
|
|
16
15
|
errors = [];
|
|
17
16
|
status;
|
|
18
|
-
userContext;
|
|
19
17
|
continueOnError;
|
|
20
18
|
constructor(args) {
|
|
21
|
-
// Object.assign(this, args);
|
|
22
19
|
this.service = args.service;
|
|
23
20
|
this.executionContext = args.executionContext;
|
|
24
|
-
this.
|
|
25
|
-
|
|
26
|
-
this.
|
|
27
|
-
this.
|
|
28
|
-
this.responseHeaders = new common_1.HeadersMap();
|
|
21
|
+
this.params = this.params || new common_1.OpraURLSearchParams();
|
|
22
|
+
this.headers = args.headers;
|
|
23
|
+
this.contentId = args.contentId;
|
|
24
|
+
this.responseHeaders = {};
|
|
29
25
|
this.resultPath = this.resultPath || '';
|
|
30
26
|
}
|
|
31
27
|
get type() {
|
|
@@ -37,4 +33,4 @@ class QueryContext {
|
|
|
37
33
|
return this.executionContext;
|
|
38
34
|
}
|
|
39
35
|
}
|
|
40
|
-
exports.
|
|
36
|
+
exports.RequestContext = RequestContext;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SingleRequestContext = void 0;
|
|
4
|
+
const request_context_js_1 = require("./request-context.js");
|
|
5
|
+
class SingleRequestContext extends request_context_js_1.RequestContext {
|
|
6
|
+
query;
|
|
7
|
+
constructor(args) {
|
|
8
|
+
super(args);
|
|
9
|
+
this.query = args.query;
|
|
10
|
+
}
|
|
11
|
+
get userContext() {
|
|
12
|
+
return this.executionContext.userContext;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
exports.SingleRequestContext = SingleRequestContext;
|
package/cjs/index.js
CHANGED
|
@@ -5,7 +5,8 @@ require("reflect-metadata");
|
|
|
5
5
|
tslib_1.__exportStar(require("./types.js"), exports);
|
|
6
6
|
tslib_1.__exportStar(require("./interfaces/execution-context.interface.js"), exports);
|
|
7
7
|
tslib_1.__exportStar(require("./interfaces/resource.interface.js"), exports);
|
|
8
|
-
tslib_1.__exportStar(require("./
|
|
8
|
+
tslib_1.__exportStar(require("./interfaces/i18n-options.interface.js"), exports);
|
|
9
|
+
tslib_1.__exportStar(require("./adapter/request-contexts/single-request-context.js"), exports);
|
|
9
10
|
tslib_1.__exportStar(require("./adapter/adapter.js"), exports);
|
|
10
11
|
tslib_1.__exportStar(require("./adapter/http-adapter.js"), exports);
|
|
11
12
|
tslib_1.__exportStar(require("./adapter/express-adapter.js"), exports);
|