@opra/core 0.4.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 -123
- 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 +282 -81
- package/cjs/adapter/request-contexts/batch-request-context.js +12 -0
- package/cjs/adapter/{query-context.js → request-contexts/request-context.js} +9 -13
- package/cjs/adapter/request-contexts/single-request-context.js +15 -0
- package/cjs/index.js +2 -2
- 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 -109
- 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 -47
- 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 -2
- package/esm/index.js +2 -2
- 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/enums/http-headers.enum.js +0 -395
- package/cjs/enums/http-status.enum.js +0 -300
- package/cjs/enums/index.js +0 -5
- package/cjs/helpers/headers-map.js +0 -18
- 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 -25
- package/esm/enums/http-headers.enum.d.ts +0 -370
- package/esm/enums/http-headers.enum.js +0 -392
- package/esm/enums/http-status.enum.d.ts +0 -290
- package/esm/enums/http-status.enum.js +0 -297
- package/esm/enums/index.d.ts +0 -2
- package/esm/enums/index.js +0 -2
- package/esm/helpers/headers-map.d.ts +0 -5
- package/esm/helpers/headers-map.js +0 -14
- package/esm/utils/path-to-tree.d.ts +0 -4
- package/esm/utils/path-to-tree.js +0 -24
|
@@ -1,51 +1,139 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.OpraHttpAdapter = void 0;
|
|
4
|
-
const
|
|
5
|
-
const schema_1 = require("@opra/schema");
|
|
6
|
-
const url_1 = require("@opra/url");
|
|
7
|
-
const index_js_1 = require("../enums/index.js");
|
|
8
|
-
const headers_map_js_1 = require("../helpers/headers-map.js");
|
|
4
|
+
const common_1 = require("@opra/common");
|
|
9
5
|
const adapter_js_1 = require("./adapter.js");
|
|
10
|
-
const
|
|
6
|
+
const single_request_context_js_1 = require("./request-contexts/single-request-context.js");
|
|
11
7
|
class OpraHttpAdapter extends adapter_js_1.OpraAdapter {
|
|
12
|
-
|
|
13
|
-
const req = executionContext.
|
|
14
|
-
|
|
15
|
-
if (
|
|
16
|
-
|
|
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]);
|
|
17
28
|
}
|
|
18
|
-
|
|
19
|
-
return [
|
|
20
|
-
this.prepareRequest(executionContext, url, req.getMethod(), new headers_map_js_1.HeadersMap(req.getHeaders()), req.getBody())
|
|
21
|
-
];
|
|
29
|
+
throw new common_1.BadRequestError({ message: 'Unsupported Content-Type' });
|
|
22
30
|
}
|
|
23
|
-
|
|
31
|
+
parseSingleQuery(args) {
|
|
32
|
+
const { executionContext, url, method, headers, body, contentId } = args;
|
|
24
33
|
if (!url.path.size)
|
|
25
|
-
throw new
|
|
34
|
+
throw new common_1.BadRequestError();
|
|
26
35
|
if (method !== 'GET' && url.path.size > 1)
|
|
27
|
-
throw new
|
|
36
|
+
throw new common_1.BadRequestError();
|
|
28
37
|
const query = this.buildQuery(url, method, body);
|
|
29
38
|
if (!query)
|
|
30
|
-
throw new
|
|
39
|
+
throw new common_1.MethodNotAllowedError({
|
|
31
40
|
message: `Method "${method}" is not allowed by target endpoint`
|
|
32
41
|
});
|
|
33
|
-
return new
|
|
42
|
+
return new single_request_context_js_1.SingleRequestContext({
|
|
34
43
|
service: this.document,
|
|
35
44
|
executionContext,
|
|
45
|
+
headers,
|
|
36
46
|
query,
|
|
37
|
-
headers: new headers_map_js_1.HeadersMap(),
|
|
38
47
|
params: url.searchParams,
|
|
48
|
+
contentId,
|
|
39
49
|
continueOnError: query.operation === 'read'
|
|
40
50
|
});
|
|
41
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
|
+
// }
|
|
42
130
|
buildQuery(url, method, body) {
|
|
43
131
|
const pathLen = url.path.size;
|
|
44
132
|
let p = url.path.get(0);
|
|
45
133
|
let resource = this._internalResources.get(p.resource) || this.document.getResource(p.resource);
|
|
46
134
|
let container;
|
|
47
135
|
let pathIndex = 0;
|
|
48
|
-
while (resource && resource instanceof
|
|
136
|
+
while (resource && resource instanceof common_1.ContainerResourceInfo) {
|
|
49
137
|
container = resource;
|
|
50
138
|
p = url.path.get(++pathIndex);
|
|
51
139
|
resource = container.getResource(p.resource);
|
|
@@ -53,19 +141,24 @@ class OpraHttpAdapter extends adapter_js_1.OpraAdapter {
|
|
|
53
141
|
try {
|
|
54
142
|
method = method.toUpperCase();
|
|
55
143
|
let query;
|
|
56
|
-
if (resource instanceof
|
|
144
|
+
if (resource instanceof common_1.SingletonResourceInfo && !p.key) {
|
|
57
145
|
switch (method) {
|
|
58
146
|
case 'GET': {
|
|
59
|
-
|
|
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
|
+
});
|
|
60
153
|
}
|
|
61
154
|
}
|
|
62
155
|
}
|
|
63
|
-
else if (resource instanceof
|
|
156
|
+
else if (resource instanceof common_1.CollectionResourceInfo) {
|
|
64
157
|
switch (method) {
|
|
65
158
|
case 'GET': {
|
|
66
159
|
if (p.key) {
|
|
67
160
|
const searchParams = url.searchParams;
|
|
68
|
-
query = new
|
|
161
|
+
query = new common_1.CollectionGetQuery(resource, p.key, {
|
|
69
162
|
pick: searchParams.get('$pick'),
|
|
70
163
|
omit: searchParams.get('$omit'),
|
|
71
164
|
include: searchParams.get('$include')
|
|
@@ -73,7 +166,7 @@ class OpraHttpAdapter extends adapter_js_1.OpraAdapter {
|
|
|
73
166
|
}
|
|
74
167
|
else {
|
|
75
168
|
const searchParams = url.searchParams;
|
|
76
|
-
query = new
|
|
169
|
+
query = new common_1.CollectionSearchQuery(resource, {
|
|
77
170
|
filter: searchParams.get('$filter'),
|
|
78
171
|
limit: searchParams.get('$limit'),
|
|
79
172
|
skip: searchParams.get('$skip'),
|
|
@@ -90,8 +183,8 @@ class OpraHttpAdapter extends adapter_js_1.OpraAdapter {
|
|
|
90
183
|
case 'DELETE': {
|
|
91
184
|
const searchParams = url.searchParams;
|
|
92
185
|
query = p.key
|
|
93
|
-
? new
|
|
94
|
-
: new
|
|
186
|
+
? new common_1.CollectionDeleteQuery(resource, p.key)
|
|
187
|
+
: new common_1.CollectionDeleteManyQuery(resource, {
|
|
95
188
|
filter: searchParams.get('$filter'),
|
|
96
189
|
});
|
|
97
190
|
break;
|
|
@@ -99,7 +192,7 @@ class OpraHttpAdapter extends adapter_js_1.OpraAdapter {
|
|
|
99
192
|
case 'POST': {
|
|
100
193
|
if (!p.key) {
|
|
101
194
|
const searchParams = url.searchParams;
|
|
102
|
-
query = new
|
|
195
|
+
query = new common_1.CollectionCreateQuery(resource, body, {
|
|
103
196
|
pick: searchParams.get('$pick'),
|
|
104
197
|
omit: searchParams.get('$omit'),
|
|
105
198
|
include: searchParams.get('$include')
|
|
@@ -110,7 +203,7 @@ class OpraHttpAdapter extends adapter_js_1.OpraAdapter {
|
|
|
110
203
|
case 'PATCH': {
|
|
111
204
|
if (p.key) {
|
|
112
205
|
const searchParams = url.searchParams;
|
|
113
|
-
query = new
|
|
206
|
+
query = new common_1.CollectionUpdateQuery(resource, p.key, body, {
|
|
114
207
|
pick: searchParams.get('$pick'),
|
|
115
208
|
omit: searchParams.get('$omit'),
|
|
116
209
|
include: searchParams.get('$include')
|
|
@@ -118,7 +211,7 @@ class OpraHttpAdapter extends adapter_js_1.OpraAdapter {
|
|
|
118
211
|
}
|
|
119
212
|
else {
|
|
120
213
|
const searchParams = url.searchParams;
|
|
121
|
-
query = new
|
|
214
|
+
query = new common_1.CollectionUpdateManyQuery(resource, body, {
|
|
122
215
|
filter: searchParams.get('$filter')
|
|
123
216
|
});
|
|
124
217
|
}
|
|
@@ -127,8 +220,8 @@ class OpraHttpAdapter extends adapter_js_1.OpraAdapter {
|
|
|
127
220
|
}
|
|
128
221
|
}
|
|
129
222
|
else
|
|
130
|
-
throw new
|
|
131
|
-
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) {
|
|
132
225
|
// Move through properties
|
|
133
226
|
let parentType;
|
|
134
227
|
const curPath = [];
|
|
@@ -136,101 +229,190 @@ class OpraHttpAdapter extends adapter_js_1.OpraAdapter {
|
|
|
136
229
|
while (++pathIndex < pathLen) {
|
|
137
230
|
p = url.path.get(pathIndex);
|
|
138
231
|
parentType = parent.dataType;
|
|
139
|
-
if (parent.dataType instanceof
|
|
232
|
+
if (parent.dataType instanceof common_1.UnionType) {
|
|
140
233
|
if (parent.dataType.name === 'any')
|
|
141
234
|
parentType = this.document.getComplexDataType('object');
|
|
142
235
|
else
|
|
143
236
|
throw new TypeError(`"${resource.name}.${curPath.join()}" is a UnionType and needs type casting.`);
|
|
144
237
|
}
|
|
145
|
-
if (!(parentType instanceof
|
|
238
|
+
if (!(parentType instanceof common_1.ComplexType))
|
|
146
239
|
throw new TypeError(`"${resource.name}.${curPath.join()}" is not a ComplexType and has no fields.`);
|
|
147
240
|
curPath.push(p.resource);
|
|
148
|
-
parent.child = new
|
|
241
|
+
parent.child = new common_1.FieldGetQuery(parent, p.resource, { castingType: parentType });
|
|
149
242
|
parent = parent.child;
|
|
150
243
|
}
|
|
151
244
|
}
|
|
152
245
|
return query;
|
|
153
246
|
}
|
|
154
247
|
catch (e) {
|
|
155
|
-
if (e instanceof
|
|
248
|
+
if (e instanceof common_1.OpraException)
|
|
156
249
|
throw e;
|
|
157
|
-
throw new
|
|
250
|
+
throw new common_1.BadRequestError(e);
|
|
158
251
|
}
|
|
159
252
|
}
|
|
160
|
-
async sendResponse(executionContext,
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
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();
|
|
174
354
|
resp.setStatus(out.status);
|
|
175
|
-
resp.setHeader(
|
|
176
|
-
resp.setHeader(
|
|
177
|
-
resp.setHeader(
|
|
178
|
-
resp.setHeader(index_js_1.HttpHeaders.Expires, '-1');
|
|
179
|
-
resp.setHeader(index_js_1.HttpHeaders.X_Opra_Version, schema_1.OpraSchema.Version);
|
|
355
|
+
resp.setHeader(common_1.HttpHeaders.Cache_Control, 'no-cache');
|
|
356
|
+
resp.setHeader(common_1.HttpHeaders.Pragma, 'no-cache');
|
|
357
|
+
resp.setHeader(common_1.HttpHeaders.Expires, '-1');
|
|
180
358
|
if (out.headers) {
|
|
181
359
|
for (const [k, v] of Object.entries(out.headers)) {
|
|
182
|
-
|
|
360
|
+
if (v)
|
|
361
|
+
resp.setHeader(k, v);
|
|
183
362
|
}
|
|
184
363
|
}
|
|
185
|
-
resp.
|
|
364
|
+
resp.setHeader(common_1.HttpHeaders.X_Opra_Version, common_1.OpraSchema.Version);
|
|
365
|
+
if (out.body)
|
|
366
|
+
resp.send(out.body);
|
|
186
367
|
resp.end();
|
|
187
368
|
}
|
|
188
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
189
|
-
isBatch(executionContext) {
|
|
190
|
-
return false;
|
|
191
|
-
}
|
|
192
369
|
createOutput(ctx) {
|
|
193
370
|
const { query } = ctx;
|
|
194
371
|
let body;
|
|
195
372
|
let status = ctx.status || 0;
|
|
196
|
-
const errors = ctx.errors.map(e => (0,
|
|
373
|
+
const errors = ctx.errors.map(e => (0, common_1.wrapException)(e));
|
|
197
374
|
if (errors && errors.length) {
|
|
198
375
|
// Sort errors from fatal to info
|
|
199
376
|
errors.sort((a, b) => {
|
|
200
|
-
const i =
|
|
377
|
+
const i = common_1.IssueSeverity.Keys.indexOf(a.issue.severity) - common_1.IssueSeverity.Keys.indexOf(b.issue.severity);
|
|
201
378
|
if (i === 0)
|
|
202
379
|
return b.status - a.status;
|
|
203
380
|
return i;
|
|
204
381
|
});
|
|
205
|
-
if (!status || status <
|
|
382
|
+
if (!status || status < common_1.HttpStatus.BAD_REQUEST) {
|
|
206
383
|
status = errors[0].status;
|
|
207
|
-
if (status <
|
|
208
|
-
status =
|
|
384
|
+
if (status < common_1.HttpStatus.BAD_REQUEST)
|
|
385
|
+
status = common_1.HttpStatus.INTERNAL_SERVER_ERROR;
|
|
209
386
|
}
|
|
210
|
-
body = {
|
|
387
|
+
body = this.i18n.deep({
|
|
211
388
|
operation: ctx.query.method,
|
|
212
389
|
errors: errors.map(e => e.issue)
|
|
213
|
-
};
|
|
390
|
+
});
|
|
391
|
+
body = JSON.stringify(body);
|
|
392
|
+
ctx.responseHeaders['content-type'] = 'application/json; charset=utf-8';
|
|
214
393
|
}
|
|
215
394
|
else {
|
|
216
|
-
|
|
217
|
-
|
|
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
|
+
}
|
|
400
|
+
status = status || (query.operation === 'create' ? common_1.HttpStatus.CREATED : common_1.HttpStatus.OK);
|
|
218
401
|
}
|
|
219
|
-
body = this.i18n.deep(body);
|
|
220
402
|
return {
|
|
221
403
|
status,
|
|
222
|
-
headers: ctx.responseHeaders
|
|
404
|
+
headers: (0, common_1.normalizeHeaders)(ctx.responseHeaders),
|
|
223
405
|
body
|
|
224
406
|
};
|
|
225
407
|
}
|
|
226
408
|
async sendError(executionContext, error) {
|
|
227
|
-
const resp = executionContext.
|
|
409
|
+
const resp = executionContext.getResponse();
|
|
228
410
|
resp.setStatus(error.status || 500);
|
|
229
|
-
resp.setHeader(
|
|
230
|
-
resp.setHeader(
|
|
231
|
-
resp.setHeader(
|
|
232
|
-
resp.setHeader(
|
|
233
|
-
resp.setHeader(
|
|
411
|
+
resp.setHeader(common_1.HttpHeaders.Content_Type, 'application/json');
|
|
412
|
+
resp.setHeader(common_1.HttpHeaders.Cache_Control, 'no-cache');
|
|
413
|
+
resp.setHeader(common_1.HttpHeaders.Pragma, 'no-cache');
|
|
414
|
+
resp.setHeader(common_1.HttpHeaders.Expires, '-1');
|
|
415
|
+
resp.setHeader(common_1.HttpHeaders.X_Opra_Version, common_1.OpraSchema.Version);
|
|
234
416
|
const issue = this.i18n.deep(error.issue);
|
|
235
417
|
const body = {
|
|
236
418
|
operation: 'unknown',
|
|
@@ -240,3 +422,22 @@ class OpraHttpAdapter extends adapter_js_1.OpraAdapter {
|
|
|
240
422
|
}
|
|
241
423
|
}
|
|
242
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.
|
|
4
|
-
const
|
|
5
|
-
|
|
6
|
-
class QueryContext {
|
|
3
|
+
exports.RequestContext = void 0;
|
|
4
|
+
const common_1 = require("@opra/common");
|
|
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 headers_map_js_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
|
@@ -3,10 +3,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
const tslib_1 = require("tslib");
|
|
4
4
|
require("reflect-metadata");
|
|
5
5
|
tslib_1.__exportStar(require("./types.js"), exports);
|
|
6
|
-
tslib_1.__exportStar(require("./enums/index.js"), exports);
|
|
7
6
|
tslib_1.__exportStar(require("./interfaces/execution-context.interface.js"), exports);
|
|
8
7
|
tslib_1.__exportStar(require("./interfaces/resource.interface.js"), exports);
|
|
9
|
-
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);
|
|
10
10
|
tslib_1.__exportStar(require("./adapter/adapter.js"), exports);
|
|
11
11
|
tslib_1.__exportStar(require("./adapter/http-adapter.js"), exports);
|
|
12
12
|
tslib_1.__exportStar(require("./adapter/express-adapter.js"), exports);
|