@opra/core 1.0.0-alpha.23 → 1.0.0-alpha.24
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/constants.js +1 -2
- package/cjs/execution-context.js +1 -0
- package/cjs/http/express-adapter.js +15 -18
- package/cjs/http/http-adapter.js +2 -5
- package/cjs/http/http-context.js +14 -10
- package/cjs/http/{impl/http-handler.js → http-handler.js} +80 -93
- package/cjs/http/impl/multipart-reader.js +130 -37
- package/cjs/index.js +1 -1
- package/cjs/platform-adapter.js +0 -3
- package/esm/constants.js +0 -1
- package/esm/execution-context.js +1 -0
- package/esm/http/express-adapter.js +15 -18
- package/esm/http/http-adapter.js +2 -5
- package/esm/http/http-context.js +14 -10
- package/esm/http/{impl/http-handler.js → http-handler.js} +69 -82
- package/esm/http/impl/multipart-reader.js +132 -39
- package/esm/index.js +1 -1
- package/esm/platform-adapter.js +0 -3
- package/package.json +5 -5
- package/types/constants.d.ts +0 -1
- package/types/execution-context.d.ts +2 -1
- package/types/http/http-adapter.d.ts +23 -5
- package/types/http/{impl/http-handler.d.ts → http-handler.d.ts} +8 -8
- package/types/http/impl/multipart-reader.d.ts +38 -19
- package/types/index.d.ts +1 -1
- package/types/platform-adapter.d.ts +0 -4
- package/cjs/helpers/logger.js +0 -35
- package/esm/helpers/logger.js +0 -31
- package/i18n/i18n/en/error.json +0 -21
- package/types/helpers/logger.d.ts +0 -14
|
@@ -1,55 +1,144 @@
|
|
|
1
|
+
import { randomFillSync } from 'node:crypto';
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import os from 'node:os';
|
|
4
|
+
import nodePath from 'node:path';
|
|
5
|
+
import typeIs from '@browsery/type-is';
|
|
6
|
+
import { BadRequestError } from '@opra/common';
|
|
7
|
+
import busboy from 'busboy';
|
|
1
8
|
import { EventEmitter } from 'events';
|
|
2
|
-
import
|
|
3
|
-
import
|
|
9
|
+
import fsPromise from 'fs/promises';
|
|
10
|
+
import { isNotNullish } from 'valgen';
|
|
4
11
|
export class MultipartReader extends EventEmitter {
|
|
5
|
-
constructor(
|
|
12
|
+
constructor(context, options, mediaType) {
|
|
6
13
|
super();
|
|
14
|
+
this.context = context;
|
|
15
|
+
this.mediaType = mediaType;
|
|
7
16
|
this._started = false;
|
|
17
|
+
this._finished = false;
|
|
8
18
|
this._cancelled = false;
|
|
9
19
|
this._items = [];
|
|
10
20
|
this._stack = [];
|
|
11
21
|
this.setMaxListeners(1000);
|
|
12
|
-
this.
|
|
13
|
-
const
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
form.once('error', () => {
|
|
22
|
+
this.tempDirectory = options?.tempDirectory || os.tmpdir();
|
|
23
|
+
const { request } = context;
|
|
24
|
+
const form = busboy({ headers: request.headers });
|
|
25
|
+
this._form = form;
|
|
26
|
+
form.once('error', (e) => {
|
|
18
27
|
this._cancelled = true;
|
|
28
|
+
this._finished = true;
|
|
19
29
|
if (this.listenerCount('error') > 0)
|
|
20
|
-
this.emit('error');
|
|
30
|
+
this.emit('error', e);
|
|
21
31
|
});
|
|
22
|
-
form.on('
|
|
23
|
-
|
|
32
|
+
form.on('close', () => {
|
|
33
|
+
this._finished = true;
|
|
34
|
+
});
|
|
35
|
+
form.on('field', (field, value, info) => {
|
|
36
|
+
const item = {
|
|
37
|
+
kind: 'field',
|
|
38
|
+
field,
|
|
39
|
+
value,
|
|
40
|
+
mimeType: info.mimeType,
|
|
41
|
+
encoding: info.encoding,
|
|
42
|
+
};
|
|
24
43
|
this._items.push(item);
|
|
25
44
|
this._stack.push(item);
|
|
26
45
|
this.emit('field', item);
|
|
27
46
|
this.emit('item', item);
|
|
28
47
|
});
|
|
29
|
-
form.on('file', (
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
48
|
+
form.on('file', (field, file, info) => {
|
|
49
|
+
const saveTo = nodePath.join(this.tempDirectory, `opra-${generateFileName()}`);
|
|
50
|
+
file.pipe(fs.createWriteStream(saveTo));
|
|
51
|
+
file.once('end', () => {
|
|
52
|
+
const item = {
|
|
53
|
+
kind: 'file',
|
|
54
|
+
field,
|
|
55
|
+
storedPath: saveTo,
|
|
56
|
+
filename: info.filename,
|
|
57
|
+
mimeType: info.mimeType,
|
|
58
|
+
encoding: info.encoding,
|
|
59
|
+
};
|
|
60
|
+
this._items.push(item);
|
|
61
|
+
this._stack.push(item);
|
|
62
|
+
this.emit('file', item);
|
|
63
|
+
this.emit('item', item);
|
|
64
|
+
});
|
|
35
65
|
});
|
|
36
66
|
}
|
|
37
67
|
get items() {
|
|
38
68
|
return this._items;
|
|
39
69
|
}
|
|
40
|
-
getNext() {
|
|
41
|
-
|
|
70
|
+
async getNext() {
|
|
71
|
+
let item = this._stack.shift();
|
|
72
|
+
if (!item && !this._finished) {
|
|
42
73
|
this.resume();
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
74
|
+
item = await new Promise((resolve, reject) => {
|
|
75
|
+
if (this._stack.length)
|
|
76
|
+
return resolve(this._stack.shift());
|
|
77
|
+
if (this._form.ended)
|
|
78
|
+
return resolve(undefined);
|
|
79
|
+
this._form.once('close', () => {
|
|
80
|
+
resolve(this._stack.shift());
|
|
81
|
+
});
|
|
82
|
+
this.once('item', () => {
|
|
83
|
+
this.pause();
|
|
84
|
+
resolve(this._stack.shift());
|
|
85
|
+
});
|
|
86
|
+
this.once('error', e => reject(e));
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
if (item && this.mediaType) {
|
|
90
|
+
const field = this.mediaType.findMultipartField(item.field);
|
|
91
|
+
if (!field)
|
|
92
|
+
throw new BadRequestError(`Unknown multipart field (${item.field})`);
|
|
93
|
+
if (item.kind === 'field') {
|
|
94
|
+
const codec = field.generateCodec('decode');
|
|
95
|
+
item.value = codec(item.value);
|
|
96
|
+
}
|
|
97
|
+
else if (item.kind === 'file') {
|
|
98
|
+
if (field.contentType) {
|
|
99
|
+
const arr = Array.isArray(field.contentType) ? field.contentType : [field.contentType];
|
|
100
|
+
if (!(item.mimeType && arr.find(ct => typeIs.is(item.mimeType, [ct])))) {
|
|
101
|
+
throw new BadRequestError(`Multipart field (${item.field}) do not accept this content type`);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
/** if all items received we check for required items */
|
|
107
|
+
if (!item && this.mediaType && this.mediaType.multipartFields?.length > 0) {
|
|
108
|
+
const fieldsLeft = new Set(this.mediaType.multipartFields);
|
|
109
|
+
for (const x of this._items) {
|
|
110
|
+
const field = this.mediaType.findMultipartField(x.field);
|
|
111
|
+
if (field)
|
|
112
|
+
fieldsLeft.delete(field);
|
|
113
|
+
}
|
|
114
|
+
let issues;
|
|
115
|
+
for (const field of fieldsLeft) {
|
|
116
|
+
try {
|
|
117
|
+
isNotNullish(null, { onFail: () => `Multi part field "${String(field.fieldName)}" is required` });
|
|
118
|
+
}
|
|
119
|
+
catch (e) {
|
|
120
|
+
if (!issues) {
|
|
121
|
+
issues = e.issues;
|
|
122
|
+
this.context.errors.push(e);
|
|
123
|
+
}
|
|
124
|
+
else
|
|
125
|
+
issues.push(...e.issues);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
if (this.context.errors.length)
|
|
129
|
+
throw this.context.errors[0];
|
|
130
|
+
}
|
|
131
|
+
return item;
|
|
132
|
+
}
|
|
133
|
+
async getAll() {
|
|
134
|
+
const items = [];
|
|
135
|
+
let item;
|
|
136
|
+
while (!this._cancelled && (item = await this.getNext())) {
|
|
137
|
+
items.push(item);
|
|
138
|
+
}
|
|
139
|
+
return items;
|
|
51
140
|
}
|
|
52
|
-
|
|
141
|
+
getAll_() {
|
|
53
142
|
if (this._form.ended)
|
|
54
143
|
return Promise.resolve([...this._items]);
|
|
55
144
|
this.resume();
|
|
@@ -66,29 +155,33 @@ export class MultipartReader extends EventEmitter {
|
|
|
66
155
|
this.resume();
|
|
67
156
|
}
|
|
68
157
|
resume() {
|
|
69
|
-
if (!this._started)
|
|
70
|
-
this.
|
|
71
|
-
|
|
72
|
-
|
|
158
|
+
if (!this._started) {
|
|
159
|
+
this._started = true;
|
|
160
|
+
this.context.request.pipe(this._form);
|
|
161
|
+
}
|
|
162
|
+
this.context.request.resume();
|
|
73
163
|
}
|
|
74
164
|
pause() {
|
|
75
|
-
|
|
76
|
-
this._form.pause();
|
|
165
|
+
this.context.request.pause();
|
|
77
166
|
}
|
|
78
|
-
async
|
|
167
|
+
async purge() {
|
|
79
168
|
const promises = [];
|
|
80
169
|
this._items.forEach(item => {
|
|
81
|
-
if (
|
|
170
|
+
if (item.kind !== 'file')
|
|
82
171
|
return;
|
|
83
|
-
const file = item.
|
|
172
|
+
const file = item.storedPath;
|
|
84
173
|
promises.push(new Promise(resolve => {
|
|
85
174
|
if (file._writeStream.closed)
|
|
86
175
|
return resolve();
|
|
87
176
|
file._writeStream.once('close', resolve);
|
|
88
177
|
})
|
|
89
|
-
.then(() =>
|
|
178
|
+
.then(() => fsPromise.unlink(file.filepath))
|
|
90
179
|
.then(() => 0));
|
|
91
180
|
});
|
|
92
181
|
return Promise.allSettled(promises);
|
|
93
182
|
}
|
|
94
183
|
}
|
|
184
|
+
function generateFileName() {
|
|
185
|
+
const buf = Buffer.alloc(10);
|
|
186
|
+
return new Date().toISOString().substring(0, 10).replaceAll('-', '') + randomFillSync(buf).toString('hex');
|
|
187
|
+
}
|
package/esm/index.js
CHANGED
|
@@ -6,11 +6,11 @@ import * as HttpOutgoingHost_ from './http/impl/http-outgoing.host.js';
|
|
|
6
6
|
import * as NodeIncomingMessageHost_ from './http/impl/node-incoming-message.host.js';
|
|
7
7
|
import * as NodeOutgoingMessageHost_ from './http/impl/node-outgoing-message.host.js';
|
|
8
8
|
export * from './execution-context.js';
|
|
9
|
-
export * from './helpers/logger.js';
|
|
10
9
|
export * from './helpers/service-base.js';
|
|
11
10
|
export * from './http/express-adapter.js';
|
|
12
11
|
export * from './http/http-adapter.js';
|
|
13
12
|
export * from './http/http-context.js';
|
|
13
|
+
export * from './http/http-handler.js';
|
|
14
14
|
export * from './http/impl/multipart-reader.js';
|
|
15
15
|
export * from './http/interfaces/http-incoming.interface.js';
|
|
16
16
|
export * from './http/interfaces/http-outgoing.interface.js';
|
package/esm/platform-adapter.js
CHANGED
|
@@ -2,7 +2,6 @@ import './augmentation/18n.augmentation.js';
|
|
|
2
2
|
import { I18n } from '@opra/common';
|
|
3
3
|
import { AsyncEventEmitter } from 'strict-typed-events';
|
|
4
4
|
import { kAssetCache } from './constants.js';
|
|
5
|
-
import { Logger } from './helpers/logger.js';
|
|
6
5
|
import { AssetCache } from './http/impl/asset-cache.js';
|
|
7
6
|
/**
|
|
8
7
|
* @class PlatformAdapter
|
|
@@ -12,8 +11,6 @@ export class PlatformAdapter extends AsyncEventEmitter {
|
|
|
12
11
|
super();
|
|
13
12
|
this[kAssetCache] = new AssetCache();
|
|
14
13
|
this.document = document;
|
|
15
|
-
this.logger =
|
|
16
|
-
options?.logger && options.logger instanceof Logger ? options.logger : new Logger({ instance: options?.logger });
|
|
17
14
|
this.i18n = options?.i18n || I18n.defaultInstance;
|
|
18
15
|
}
|
|
19
16
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opra/core",
|
|
3
|
-
"version": "1.0.0-alpha.
|
|
3
|
+
"version": "1.0.0-alpha.24",
|
|
4
4
|
"description": "Opra schema package",
|
|
5
5
|
"author": "Panates",
|
|
6
6
|
"license": "MIT",
|
|
@@ -33,10 +33,10 @@
|
|
|
33
33
|
"dependencies": {
|
|
34
34
|
"@browsery/http-parser": "^0.5.8",
|
|
35
35
|
"@browsery/type-is": "^1.6.18-r2",
|
|
36
|
-
"@opra/common": "^1.0.0-alpha.
|
|
37
|
-
"@types/formidable": "^3.4.5",
|
|
36
|
+
"@opra/common": "^1.0.0-alpha.24",
|
|
38
37
|
"accepts": "^1.3.8",
|
|
39
38
|
"base64-stream": "^1.0.0",
|
|
39
|
+
"busboy": "^1.6.0",
|
|
40
40
|
"bytes": "^3.1.2",
|
|
41
41
|
"content-disposition": "^0.5.4",
|
|
42
42
|
"content-type": "^1.0.5",
|
|
@@ -44,7 +44,6 @@
|
|
|
44
44
|
"cookie-signature": "^1.2.1",
|
|
45
45
|
"cppzst": "^2.0.12",
|
|
46
46
|
"encodeurl": "^2.0.0",
|
|
47
|
-
"formidable": "^3.5.1",
|
|
48
47
|
"fresh": "^0.5.2",
|
|
49
48
|
"iconv-lite": "^0.6.3",
|
|
50
49
|
"mime-types": "^2.1.35",
|
|
@@ -55,7 +54,7 @@
|
|
|
55
54
|
"range-parser": "^1.2.1",
|
|
56
55
|
"raw-body": "^2.5.2",
|
|
57
56
|
"reflect-metadata": "^0.2.2",
|
|
58
|
-
"strict-typed-events": "^2.
|
|
57
|
+
"strict-typed-events": "^2.4.0",
|
|
59
58
|
"vary": "^1.1.2"
|
|
60
59
|
},
|
|
61
60
|
"optionalDependencies": {
|
|
@@ -66,6 +65,7 @@
|
|
|
66
65
|
"@faker-js/faker": "^8.4.1",
|
|
67
66
|
"@types/accepts": "^1.3.7",
|
|
68
67
|
"@types/base64-stream": "^1.0.5",
|
|
68
|
+
"@types/busboy": "^1.5.4",
|
|
69
69
|
"@types/bytes": "^3.1.4",
|
|
70
70
|
"@types/content-disposition": "^0.5.8",
|
|
71
71
|
"@types/content-type": "^1.1.8",
|
package/types/constants.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ApiDocument, OpraSchema } from '@opra/common';
|
|
1
|
+
import { ApiDocument, OpraException, OpraSchema } from '@opra/common';
|
|
2
2
|
import { AsyncEventEmitter } from 'strict-typed-events';
|
|
3
3
|
/**
|
|
4
4
|
* @namespace ExecutionContext
|
|
@@ -18,6 +18,7 @@ export declare abstract class ExecutionContext extends AsyncEventEmitter {
|
|
|
18
18
|
readonly document: ApiDocument;
|
|
19
19
|
readonly protocol: OpraSchema.Protocol;
|
|
20
20
|
readonly platform: string;
|
|
21
|
+
errors: OpraException[];
|
|
21
22
|
protected constructor(init: ExecutionContext.Initiator);
|
|
22
23
|
addListener(event: 'finish', listener: ExecutionContext.OnFinishListener): this;
|
|
23
24
|
removeListener(event: 'finish', listener: ExecutionContext.OnFinishListener): this;
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import { ApiDocument, HttpApi, OpraSchema } from '@opra/common';
|
|
2
|
-
import { kHandler } from '../constants.js';
|
|
1
|
+
import { ApiDocument, HttpApi, OpraException, OpraSchema } from '@opra/common';
|
|
3
2
|
import { PlatformAdapter } from '../platform-adapter.js';
|
|
4
3
|
import { HttpContext } from './http-context.js';
|
|
5
|
-
import { HttpHandler } from './
|
|
4
|
+
import { HttpHandler } from './http-handler.js';
|
|
6
5
|
export declare namespace HttpAdapter {
|
|
7
6
|
/**
|
|
8
7
|
* @type Interceptor
|
|
@@ -11,15 +10,34 @@ export declare namespace HttpAdapter {
|
|
|
11
10
|
interface Options extends PlatformAdapter.Options {
|
|
12
11
|
basePath?: string;
|
|
13
12
|
interceptors?: HttpAdapter.Interceptor[];
|
|
14
|
-
onRequest?: (ctx: HttpContext) => void | Promise<void>;
|
|
15
13
|
}
|
|
14
|
+
interface Events {
|
|
15
|
+
error: (error: OpraException, context: HttpContext) => void | Promise<void>;
|
|
16
|
+
request: (context: HttpContext) => void | Promise<void>;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
export interface HttpAdapter {
|
|
20
|
+
addListener<Event extends keyof HttpAdapter.Events>(event: Event, listener: HttpAdapter.Events[Event]): this;
|
|
21
|
+
addListener(event: string | symbol, listener: (...args: any[]) => void): this;
|
|
22
|
+
on<Event extends keyof HttpAdapter.Events>(event: Event, listener: HttpAdapter.Events[Event]): this;
|
|
23
|
+
on(event: string | symbol, listener: (...args: any[]) => void): this;
|
|
24
|
+
once<Event extends keyof HttpAdapter.Events>(event: Event, listener: HttpAdapter.Events[Event]): this;
|
|
25
|
+
once(event: string | symbol, listener: (...args: any[]) => void): this;
|
|
26
|
+
removeListener<Event extends keyof HttpAdapter.Events>(event: Event, listener: HttpAdapter.Events[Event]): this;
|
|
27
|
+
removeListener(event: string | symbol, listener: (...args: any[]) => void): this;
|
|
28
|
+
off<Event extends keyof HttpAdapter.Events>(event: Event, listener: HttpAdapter.Events[Event]): this;
|
|
29
|
+
off(event: string | symbol, listener: (...args: any[]) => void): this;
|
|
30
|
+
prependListener<Event extends keyof HttpAdapter.Events>(event: Event, listener: HttpAdapter.Events[Event]): this;
|
|
31
|
+
prependListener(event: string | symbol, listener: (...args: any[]) => void): this;
|
|
32
|
+
prependOnceListener<Event extends keyof HttpAdapter.Events>(event: Event, listener: HttpAdapter.Events[Event]): this;
|
|
33
|
+
prependOnceListener(event: string | symbol, listener: (...args: any[]) => void): this;
|
|
16
34
|
}
|
|
17
35
|
/**
|
|
18
36
|
*
|
|
19
37
|
* @class HttpAdapter
|
|
20
38
|
*/
|
|
21
39
|
export declare abstract class HttpAdapter extends PlatformAdapter {
|
|
22
|
-
|
|
40
|
+
readonly handler: HttpHandler;
|
|
23
41
|
readonly protocol: OpraSchema.Protocol;
|
|
24
42
|
interceptors: HttpAdapter.Interceptor[];
|
|
25
43
|
protected constructor(document: ApiDocument, options?: HttpAdapter.Options);
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import { HttpOperationResponse } from '@opra/common';
|
|
2
|
-
import { kAssetCache } from '
|
|
3
|
-
import type { HttpAdapter } from '
|
|
4
|
-
import { HttpContext } from '
|
|
5
|
-
import {
|
|
6
|
-
import { AssetCache } from './asset-cache.js';
|
|
1
|
+
import { HttpOperationResponse, OpraException } from '@opra/common';
|
|
2
|
+
import { kAssetCache } from '../constants';
|
|
3
|
+
import type { HttpAdapter } from './http-adapter';
|
|
4
|
+
import { HttpContext } from './http-context';
|
|
5
|
+
import { AssetCache } from './impl/asset-cache';
|
|
7
6
|
/**
|
|
8
7
|
* @namespace
|
|
9
8
|
*/
|
|
@@ -24,6 +23,7 @@ export declare namespace HttpHandler {
|
|
|
24
23
|
export declare class HttpHandler {
|
|
25
24
|
readonly adapter: HttpAdapter;
|
|
26
25
|
protected [kAssetCache]: AssetCache;
|
|
26
|
+
onError?: (context: HttpContext, error: OpraException) => void | Promise<void>;
|
|
27
27
|
constructor(adapter: HttpAdapter);
|
|
28
28
|
/**
|
|
29
29
|
* Main http request handler
|
|
@@ -60,7 +60,8 @@ export declare class HttpHandler {
|
|
|
60
60
|
* @param responseValue
|
|
61
61
|
* @protected
|
|
62
62
|
*/
|
|
63
|
-
|
|
63
|
+
sendResponse(context: HttpContext, responseValue?: any): Promise<void>;
|
|
64
|
+
sendErrorResponse(context: HttpContext, errors: any[]): Promise<void>;
|
|
64
65
|
/**
|
|
65
66
|
*
|
|
66
67
|
* @param context
|
|
@@ -69,5 +70,4 @@ export declare class HttpHandler {
|
|
|
69
70
|
*/
|
|
70
71
|
protected _determineResponseArgs(context: HttpContext, body: any): HttpHandler.ResponseArgs;
|
|
71
72
|
sendDocumentSchema(context: HttpContext): Promise<void>;
|
|
72
|
-
sendErrorResponse(response: HttpOutgoing, errors: any[]): Promise<void>;
|
|
73
73
|
}
|
|
@@ -1,27 +1,46 @@
|
|
|
1
|
+
import { HttpMediaType } from '@opra/common';
|
|
2
|
+
import busboy from 'busboy';
|
|
1
3
|
import { EventEmitter } from 'events';
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
4
|
+
import { StrictOmit } from 'ts-gems';
|
|
5
|
+
import { HttpContext } from '../http-context';
|
|
6
|
+
export declare namespace MultipartReader {
|
|
7
|
+
interface Options extends StrictOmit<busboy.BusboyConfig, 'headers'> {
|
|
8
|
+
tempDirectory?: string;
|
|
9
|
+
}
|
|
10
|
+
interface FieldInfo {
|
|
11
|
+
kind: 'field';
|
|
12
|
+
field: string;
|
|
13
|
+
value?: string;
|
|
14
|
+
mimeType?: string;
|
|
15
|
+
encoding?: string;
|
|
16
|
+
}
|
|
17
|
+
interface FileInfo {
|
|
18
|
+
kind: 'file';
|
|
19
|
+
field: string;
|
|
20
|
+
filename: string;
|
|
21
|
+
storedPath: string;
|
|
22
|
+
mimeType?: string;
|
|
23
|
+
encoding?: string;
|
|
24
|
+
}
|
|
25
|
+
type Item = FieldInfo | FileInfo;
|
|
26
|
+
}
|
|
12
27
|
export declare class MultipartReader extends EventEmitter {
|
|
13
|
-
protected
|
|
28
|
+
protected context: HttpContext;
|
|
29
|
+
protected mediaType?: HttpMediaType | undefined;
|
|
14
30
|
protected _started: boolean;
|
|
31
|
+
protected _finished: boolean;
|
|
15
32
|
protected _cancelled: boolean;
|
|
16
|
-
protected _form:
|
|
17
|
-
protected _items:
|
|
18
|
-
protected _stack:
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
33
|
+
protected _form: busboy.Busboy;
|
|
34
|
+
protected _items: MultipartReader.Item[];
|
|
35
|
+
protected _stack: MultipartReader.Item[];
|
|
36
|
+
protected tempDirectory: string;
|
|
37
|
+
constructor(context: HttpContext, options?: MultipartReader.Options, mediaType?: HttpMediaType | undefined);
|
|
38
|
+
get items(): MultipartReader.Item[];
|
|
39
|
+
getNext(): Promise<MultipartReader.Item | undefined>;
|
|
40
|
+
getAll(): Promise<MultipartReader.Item[]>;
|
|
41
|
+
getAll_(): Promise<MultipartReader.Item[]>;
|
|
23
42
|
cancel(): void;
|
|
24
43
|
resume(): void;
|
|
25
44
|
pause(): void;
|
|
26
|
-
|
|
45
|
+
purge(): Promise<PromiseSettledResult<any>[]>;
|
|
27
46
|
}
|
package/types/index.d.ts
CHANGED
|
@@ -6,11 +6,11 @@ import * as HttpOutgoingHost_ from './http/impl/http-outgoing.host.js';
|
|
|
6
6
|
import * as NodeIncomingMessageHost_ from './http/impl/node-incoming-message.host.js';
|
|
7
7
|
import * as NodeOutgoingMessageHost_ from './http/impl/node-outgoing-message.host.js';
|
|
8
8
|
export * from './execution-context.js';
|
|
9
|
-
export * from './helpers/logger.js';
|
|
10
9
|
export * from './helpers/service-base.js';
|
|
11
10
|
export * from './http/express-adapter.js';
|
|
12
11
|
export * from './http/http-adapter.js';
|
|
13
12
|
export * from './http/http-context.js';
|
|
13
|
+
export * from './http/http-handler.js';
|
|
14
14
|
export * from './http/impl/multipart-reader.js';
|
|
15
15
|
export * from './http/interfaces/http-incoming.interface.js';
|
|
16
16
|
export * from './http/interfaces/http-outgoing.interface.js';
|
|
@@ -2,16 +2,13 @@ import './augmentation/18n.augmentation.js';
|
|
|
2
2
|
import { ApiDocument, I18n, OpraSchema } from '@opra/common';
|
|
3
3
|
import { AsyncEventEmitter } from 'strict-typed-events';
|
|
4
4
|
import { kAssetCache } from './constants.js';
|
|
5
|
-
import { Logger } from './helpers/logger.js';
|
|
6
5
|
import { AssetCache } from './http/impl/asset-cache.js';
|
|
7
|
-
import type { ILogger } from './interfaces/logger.interface.js';
|
|
8
6
|
/**
|
|
9
7
|
* @namespace PlatformAdapter
|
|
10
8
|
*/
|
|
11
9
|
export declare namespace PlatformAdapter {
|
|
12
10
|
interface Options {
|
|
13
11
|
i18n?: I18n;
|
|
14
|
-
logger?: ILogger;
|
|
15
12
|
}
|
|
16
13
|
}
|
|
17
14
|
/**
|
|
@@ -21,7 +18,6 @@ export declare abstract class PlatformAdapter extends AsyncEventEmitter {
|
|
|
21
18
|
protected [kAssetCache]: AssetCache;
|
|
22
19
|
readonly document: ApiDocument;
|
|
23
20
|
abstract readonly protocol: OpraSchema.Protocol;
|
|
24
|
-
logger: Logger;
|
|
25
21
|
i18n: I18n;
|
|
26
22
|
protected constructor(document: ApiDocument, options?: PlatformAdapter.Options);
|
|
27
23
|
abstract close(): Promise<void>;
|
package/cjs/helpers/logger.js
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.Logger = void 0;
|
|
4
|
-
class Logger {
|
|
5
|
-
constructor(options = {}) {
|
|
6
|
-
this._instance = options.instance || (!(process.env.NODE_ENV || '').includes('test') ? globalThis.console : {});
|
|
7
|
-
}
|
|
8
|
-
info(message, ...optionalParams) {
|
|
9
|
-
(this._instance.info || this._instance.log)?.(message, ...optionalParams);
|
|
10
|
-
}
|
|
11
|
-
error(message, ...optionalParams) {
|
|
12
|
-
if (this._instance.error) {
|
|
13
|
-
this._instance.error(message, ...optionalParams);
|
|
14
|
-
return;
|
|
15
|
-
}
|
|
16
|
-
this.info(message, ...optionalParams);
|
|
17
|
-
}
|
|
18
|
-
fatal(message, ...optionalParams) {
|
|
19
|
-
if (this._instance.fatal) {
|
|
20
|
-
this._instance.fatal(message, ...optionalParams);
|
|
21
|
-
return;
|
|
22
|
-
}
|
|
23
|
-
this.error(message, ...optionalParams);
|
|
24
|
-
}
|
|
25
|
-
warn(message, ...optionalParams) {
|
|
26
|
-
this._instance.warn?.(message, ...optionalParams);
|
|
27
|
-
}
|
|
28
|
-
debug(message, ...optionalParams) {
|
|
29
|
-
this._instance.debug?.(message, ...optionalParams);
|
|
30
|
-
}
|
|
31
|
-
verbose(message, ...optionalParams) {
|
|
32
|
-
this._instance.verbose?.(message, ...optionalParams);
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
exports.Logger = Logger;
|
package/esm/helpers/logger.js
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
export class Logger {
|
|
2
|
-
constructor(options = {}) {
|
|
3
|
-
this._instance = options.instance || (!(process.env.NODE_ENV || '').includes('test') ? globalThis.console : {});
|
|
4
|
-
}
|
|
5
|
-
info(message, ...optionalParams) {
|
|
6
|
-
(this._instance.info || this._instance.log)?.(message, ...optionalParams);
|
|
7
|
-
}
|
|
8
|
-
error(message, ...optionalParams) {
|
|
9
|
-
if (this._instance.error) {
|
|
10
|
-
this._instance.error(message, ...optionalParams);
|
|
11
|
-
return;
|
|
12
|
-
}
|
|
13
|
-
this.info(message, ...optionalParams);
|
|
14
|
-
}
|
|
15
|
-
fatal(message, ...optionalParams) {
|
|
16
|
-
if (this._instance.fatal) {
|
|
17
|
-
this._instance.fatal(message, ...optionalParams);
|
|
18
|
-
return;
|
|
19
|
-
}
|
|
20
|
-
this.error(message, ...optionalParams);
|
|
21
|
-
}
|
|
22
|
-
warn(message, ...optionalParams) {
|
|
23
|
-
this._instance.warn?.(message, ...optionalParams);
|
|
24
|
-
}
|
|
25
|
-
debug(message, ...optionalParams) {
|
|
26
|
-
this._instance.debug?.(message, ...optionalParams);
|
|
27
|
-
}
|
|
28
|
-
verbose(message, ...optionalParams) {
|
|
29
|
-
this._instance.verbose?.(message, ...optionalParams);
|
|
30
|
-
}
|
|
31
|
-
}
|
package/i18n/i18n/en/error.json
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"BAD_REQUEST": "Bad request",
|
|
3
|
-
"FAILED_DEPENDENCY": "The request failed due to failure of a previous request",
|
|
4
|
-
"FORBIDDEN": "You are not authorized to perform this action",
|
|
5
|
-
"INTERNAL_SERVER_ERROR": "Internal server error",
|
|
6
|
-
"METHOD_NOT_ALLOWED": "Method not allowed",
|
|
7
|
-
"NOT_ACCEPTABLE": "Not acceptable",
|
|
8
|
-
"NOT_FOUND": "Not found",
|
|
9
|
-
"UNAUTHORIZED": "You have not been authenticated to perform this action",
|
|
10
|
-
"UNPROCESSABLE_ENTITY": "Unprocessable entity",
|
|
11
|
-
"REQUEST_VALIDATION": "Request validation failed",
|
|
12
|
-
"RESPONSE_VALIDATION": "Response validation failed",
|
|
13
|
-
"RESOURCE_NOT_AVAILABLE": "Resource is not available or you dont have access",
|
|
14
|
-
"RESOURCE_CONFLICT": "There is already an other {{resource}} resource with same field values ({{fields}})",
|
|
15
|
-
"OPERATION_FORBIDDEN": "The {{resource}} resource does not accept '{{operation}}' operations",
|
|
16
|
-
"ACTION_NOT_FOUND": "The {{resource}} resource doesn't have an action named '{{action}}'",
|
|
17
|
-
"UNKNOWN_FIELD": "Unknown field '{{field}}'",
|
|
18
|
-
"UNACCEPTED_SORT_FIELD": "Field '{{field}}' is not available for sort operation",
|
|
19
|
-
"UNACCEPTED_FILTER_FIELD": "Field '{{field}}' is not available for filter operation",
|
|
20
|
-
"UNACCEPTED_FILTER_OPERATION": "'{{operation}}' for field '{{field}}' is not available for filter operation"
|
|
21
|
-
}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { ILogger } from '../interfaces/logger.interface.js';
|
|
2
|
-
export interface LoggerOptions {
|
|
3
|
-
instance?: ILogger;
|
|
4
|
-
}
|
|
5
|
-
export declare class Logger implements ILogger {
|
|
6
|
-
protected _instance: ILogger;
|
|
7
|
-
constructor(options?: LoggerOptions);
|
|
8
|
-
info(message: any, ...optionalParams: any[]): void;
|
|
9
|
-
error(message: any, ...optionalParams: any[]): void;
|
|
10
|
-
fatal(message: any, ...optionalParams: any[]): void;
|
|
11
|
-
warn(message: any, ...optionalParams: any[]): void;
|
|
12
|
-
debug(message: any, ...optionalParams: any[]): void;
|
|
13
|
-
verbose(message: any, ...optionalParams: any[]): void;
|
|
14
|
-
}
|