@opra/core 0.22.0 → 0.23.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.
Files changed (118) hide show
  1. package/cjs/adapter/execution-context.host.js +48 -0
  2. package/cjs/adapter/http/express-adapter.host.js +24 -0
  3. package/cjs/adapter/http/express-adapter.js +12 -45
  4. package/cjs/adapter/http/helpers/concat-readable.js +20 -0
  5. package/cjs/adapter/http/helpers/multipart-helper.js +96 -0
  6. package/cjs/adapter/http/helpers/query-parsers.js +16 -0
  7. package/cjs/adapter/http/http-adapter-base.js +127 -0
  8. package/cjs/adapter/http/http-adapter.host.js +57 -0
  9. package/cjs/adapter/http/http-adapter.js +11 -133
  10. package/cjs/adapter/http/{impl/http-server-request.js → http-server-request.js} +11 -5
  11. package/cjs/adapter/http/{impl/http-server-response.js → http-server-response.js} +4 -4
  12. package/cjs/adapter/http/impl/http-incoming-message.host.js +148 -0
  13. package/cjs/adapter/http/impl/{http-outgoing-message-host.js → http-outgoing-message.host.js} +26 -38
  14. package/cjs/adapter/http/request-handlers/entity-request-handler.js +405 -0
  15. package/cjs/adapter/http/request-handlers/request-handler-base.js +27 -0
  16. package/cjs/adapter/http/request-handlers/storage-request-handler.js +134 -0
  17. package/cjs/adapter/operation-context.js +16 -0
  18. package/cjs/adapter/platform-adapter.host.js +107 -0
  19. package/cjs/adapter/request.host.js +1 -2
  20. package/cjs/adapter/request.js +2 -0
  21. package/cjs/adapter/response.js +2 -0
  22. package/cjs/adapter/services/logger.js +36 -0
  23. package/cjs/augmentation/collection.augmentation.js +2 -0
  24. package/cjs/augmentation/singleton.augmentation.js +2 -0
  25. package/cjs/augmentation/storage.augmentation.js +2 -0
  26. package/cjs/index.js +15 -9
  27. package/esm/adapter/execution-context.host.js +44 -0
  28. package/esm/adapter/http/express-adapter.host.js +20 -0
  29. package/esm/adapter/http/express-adapter.js +11 -20
  30. package/esm/adapter/http/helpers/concat-readable.js +16 -0
  31. package/esm/adapter/http/helpers/multipart-helper.js +91 -0
  32. package/esm/adapter/http/helpers/query-parsers.js +12 -0
  33. package/esm/adapter/http/http-adapter-base.js +123 -0
  34. package/esm/adapter/http/http-adapter.host.js +52 -0
  35. package/esm/adapter/http/http-adapter.js +11 -132
  36. package/esm/adapter/http/{impl/http-server-request.js → http-server-request.js} +12 -6
  37. package/esm/adapter/http/{impl/http-server-response.js → http-server-response.js} +4 -4
  38. package/esm/adapter/http/impl/http-incoming-message.host.js +144 -0
  39. package/esm/adapter/http/impl/{http-outgoing-message-host.js → http-outgoing-message.host.js} +25 -36
  40. package/esm/adapter/http/request-handlers/entity-request-handler.js +400 -0
  41. package/esm/adapter/http/request-handlers/request-handler-base.js +23 -0
  42. package/esm/adapter/http/request-handlers/storage-request-handler.js +129 -0
  43. package/esm/adapter/operation-context.js +13 -0
  44. package/esm/adapter/platform-adapter.host.js +102 -0
  45. package/esm/adapter/request.host.js +1 -2
  46. package/esm/adapter/request.js +1 -0
  47. package/esm/adapter/response.js +1 -0
  48. package/esm/adapter/services/logger.js +32 -0
  49. package/esm/augmentation/collection.augmentation.js +1 -0
  50. package/esm/augmentation/singleton.augmentation.js +1 -0
  51. package/esm/augmentation/storage.augmentation.js +1 -0
  52. package/esm/index.js +15 -9
  53. package/i18n/en/error.json +7 -2
  54. package/package.json +7 -6
  55. package/types/adapter/execution-context.d.ts +31 -0
  56. package/types/adapter/execution-context.host.d.ts +27 -0
  57. package/types/adapter/http/express-adapter.d.ts +12 -8
  58. package/types/adapter/http/express-adapter.host.d.ts +11 -0
  59. package/types/adapter/http/helpers/concat-readable.d.ts +3 -0
  60. package/types/adapter/http/helpers/multipart-helper.d.ts +25 -0
  61. package/types/adapter/http/helpers/query-parsers.d.ts +1 -0
  62. package/types/adapter/http/http-adapter-base.d.ts +23 -0
  63. package/types/adapter/http/http-adapter.d.ts +13 -29
  64. package/types/adapter/http/http-adapter.host.d.ts +18 -0
  65. package/types/adapter/http/{impl/http-server-request.d.ts → http-server-request.d.ts} +7 -6
  66. package/types/adapter/http/{impl/http-server-response.d.ts → http-server-response.d.ts} +2 -2
  67. package/types/adapter/http/impl/{http-incoming-message-host.d.ts → http-incoming-message.host.d.ts} +16 -12
  68. package/types/adapter/http/impl/{http-outgoing-message-host.d.ts → http-outgoing-message.host.d.ts} +12 -16
  69. package/types/adapter/http/request-handlers/entity-request-handler.d.ts +24 -0
  70. package/types/adapter/http/request-handlers/request-handler-base.d.ts +15 -0
  71. package/types/adapter/http/request-handlers/storage-request-handler.d.ts +23 -0
  72. package/types/adapter/interfaces/logger.interface.d.ts +7 -6
  73. package/types/adapter/interfaces/request-handler.interface.d.ts +4 -0
  74. package/types/adapter/operation-context.d.ts +11 -0
  75. package/types/adapter/{adapter.d.ts → platform-adapter.d.ts} +18 -28
  76. package/types/adapter/platform-adapter.host.d.ts +31 -0
  77. package/types/adapter/request.d.ts +11 -0
  78. package/types/adapter/request.host.d.ts +12 -21
  79. package/types/adapter/{interfaces/response.interface.d.ts → response.d.ts} +2 -2
  80. package/types/adapter/response.host.d.ts +2 -2
  81. package/types/adapter/services/logger.d.ts +14 -0
  82. package/types/augmentation/collection.augmentation.d.ts +112 -0
  83. package/types/augmentation/singleton.augmentation.d.ts +64 -0
  84. package/types/augmentation/storage.augmentation.d.ts +39 -0
  85. package/types/index.d.ts +15 -9
  86. package/cjs/adapter/adapter.js +0 -118
  87. package/cjs/adapter/http/impl/http-incoming-message-host.js +0 -127
  88. package/cjs/adapter/http/request-parsers/parse-collection-request.js +0 -165
  89. package/cjs/adapter/http/request-parsers/parse-request.js +0 -24
  90. package/cjs/adapter/http/request-parsers/parse-singleton-request.js +0 -96
  91. package/cjs/adapter/internal/metadata.resource.js +0 -26
  92. package/cjs/adapter/request-context.host.js +0 -44
  93. package/cjs/shared/collection-resource-base.js +0 -20
  94. package/esm/adapter/adapter.js +0 -113
  95. package/esm/adapter/http/impl/http-incoming-message-host.js +0 -122
  96. package/esm/adapter/http/request-parsers/parse-collection-request.js +0 -161
  97. package/esm/adapter/http/request-parsers/parse-request.js +0 -20
  98. package/esm/adapter/http/request-parsers/parse-singleton-request.js +0 -92
  99. package/esm/adapter/internal/metadata.resource.js +0 -23
  100. package/esm/adapter/request-context.host.js +0 -40
  101. package/esm/shared/collection-resource-base.js +0 -16
  102. package/types/adapter/http/request-parsers/parse-collection-request.d.ts +0 -4
  103. package/types/adapter/http/request-parsers/parse-request.d.ts +0 -4
  104. package/types/adapter/http/request-parsers/parse-singleton-request.d.ts +0 -4
  105. package/types/adapter/interfaces/request-context.interface.d.ts +0 -31
  106. package/types/adapter/interfaces/request.interface.d.ts +0 -15
  107. package/types/adapter/internal/metadata.resource.d.ts +0 -7
  108. package/types/adapter/request-context.host.d.ts +0 -22
  109. package/types/shared/collection-resource-base.d.ts +0 -11
  110. /package/cjs/adapter/{interfaces/request-context.interface.js → execution-context.js} +0 -0
  111. /package/cjs/adapter/http/{request-parsers/batch-request-parser.js → request-handlers/parse-batch-request.js} +0 -0
  112. /package/cjs/adapter/interfaces/{request.interface.js → request-handler.interface.js} +0 -0
  113. /package/cjs/adapter/{interfaces/response.interface.js → platform-adapter.js} +0 -0
  114. /package/esm/adapter/{interfaces/request-context.interface.js → execution-context.js} +0 -0
  115. /package/esm/adapter/http/{request-parsers/batch-request-parser.js → request-handlers/parse-batch-request.js} +0 -0
  116. /package/esm/adapter/interfaces/{request.interface.js → request-handler.interface.js} +0 -0
  117. /package/esm/adapter/{interfaces/response.interface.js → platform-adapter.js} +0 -0
  118. /package/types/adapter/http/{request-parsers/batch-request-parser.d.ts → request-handlers/parse-batch-request.d.ts} +0 -0
@@ -0,0 +1,134 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.StorageRequestHandler = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const promises_1 = tslib_1.__importDefault(require("fs/promises"));
6
+ const os_1 = tslib_1.__importDefault(require("os"));
7
+ const common_1 = require("@opra/common");
8
+ const operation_context_js_1 = require("../../operation-context.js");
9
+ const request_host_js_1 = require("../../request.host.js");
10
+ const response_host_js_1 = require("../../response.host.js");
11
+ const multipart_helper_js_1 = require("../helpers/multipart-helper.js");
12
+ const request_handler_base_js_1 = require("./request-handler-base.js");
13
+ /**
14
+ * @class StorageRequestHandler
15
+ */
16
+ class StorageRequestHandler extends request_handler_base_js_1.RequestHandlerBase {
17
+ constructor(adapter, options) {
18
+ super(adapter);
19
+ this.adapter = adapter;
20
+ this._uploadDir = options?.uploadDir || os_1.default.tmpdir();
21
+ }
22
+ async processRequest(executionContext) {
23
+ const { incoming, outgoing } = executionContext.switchToHttp();
24
+ // Parse incoming message and create Request object
25
+ const request = await this.parseRequest(executionContext, incoming);
26
+ if (!request)
27
+ return;
28
+ const response = new response_host_js_1.ResponseHost({ http: outgoing });
29
+ const context = operation_context_js_1.OperationContext.from(executionContext, request, response);
30
+ // Execute operation
31
+ await this.executeOperation(context);
32
+ if (response.errors.length) {
33
+ context.errors.push(...response.errors);
34
+ return;
35
+ }
36
+ await this.sendResponse(context);
37
+ }
38
+ async parseRequest(executionContext, incoming) {
39
+ const contentId = incoming.headers['content-id'];
40
+ const p = incoming.parsedUrl.path[0];
41
+ const resource = this.adapter.api.getResource(p.resource);
42
+ try {
43
+ if (!(resource instanceof common_1.Storage))
44
+ return;
45
+ switch (incoming.method) {
46
+ case 'GET': {
47
+ const operationMeta = await this.assertOperation(resource, 'get');
48
+ return new request_host_js_1.RequestHost({
49
+ controller: operationMeta.controller,
50
+ http: incoming,
51
+ resource,
52
+ operation: 'get',
53
+ contentId
54
+ });
55
+ }
56
+ case 'DELETE': {
57
+ const operationMeta = await this.assertOperation(resource, 'delete');
58
+ return new request_host_js_1.RequestHost({
59
+ controller: operationMeta.controller,
60
+ http: incoming,
61
+ resource,
62
+ operation: 'delete',
63
+ contentId
64
+ });
65
+ }
66
+ case 'POST': {
67
+ const operationMeta = await this.assertOperation(resource, 'post');
68
+ await promises_1.default.mkdir(this._uploadDir, { recursive: true });
69
+ const multipartIterator = new multipart_helper_js_1.MultipartIterator(incoming, {
70
+ ...operationMeta,
71
+ filename: () => this.adapter.serviceName + '_p' + process.pid +
72
+ 't' + String(Date.now()).substring(8) + 'r' + (0, common_1.uid)(12)
73
+ });
74
+ multipartIterator.pause();
75
+ // Add an hook to clean up files after request finished
76
+ executionContext.on('finish', async () => {
77
+ multipartIterator.cancel();
78
+ await multipartIterator.deleteFiles().catch(() => void 0);
79
+ });
80
+ return new request_host_js_1.RequestHost({
81
+ controller: operationMeta.controller,
82
+ http: incoming,
83
+ resource,
84
+ operation: 'post',
85
+ contentId,
86
+ parts: multipartIterator
87
+ });
88
+ }
89
+ }
90
+ }
91
+ catch (e) {
92
+ if (e instanceof common_1.OpraException)
93
+ throw e;
94
+ throw new common_1.BadRequestError(e);
95
+ }
96
+ }
97
+ async executeOperation(context) {
98
+ const request = context.request;
99
+ const { response } = context;
100
+ // Call operation handler method
101
+ let value;
102
+ try {
103
+ value = await request.controller[request.operation].call(request.controller, context);
104
+ if (response.value == null)
105
+ response.value = value;
106
+ }
107
+ catch (error) {
108
+ response.errors.push(error);
109
+ }
110
+ }
111
+ async sendResponse(context) {
112
+ const { response } = context;
113
+ const outgoing = response.switchToHttp();
114
+ outgoing.statusCode = outgoing.statusCode || common_1.HttpStatusCodes.OK;
115
+ if (response.value != null) {
116
+ if (typeof response.value === 'string') {
117
+ if (!outgoing.hasHeader('content-type'))
118
+ outgoing.setHeader('content-type', 'text/plain');
119
+ outgoing.send(response.value);
120
+ }
121
+ else if (Buffer.isBuffer(response.value) || (0, common_1.isReadable)(response.value)) {
122
+ if (!outgoing.hasHeader('content-type'))
123
+ outgoing.setHeader('content-type', 'application/octet-stream');
124
+ outgoing.send(response.value);
125
+ }
126
+ else {
127
+ outgoing.setHeader('content-type', 'application/json; charset=utf-8');
128
+ outgoing.send(JSON.stringify(response.value));
129
+ }
130
+ }
131
+ outgoing.end();
132
+ }
133
+ }
134
+ exports.StorageRequestHandler = StorageRequestHandler;
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.OperationContext = void 0;
4
+ var OperationContext;
5
+ (function (OperationContext) {
6
+ function from(executionContext, request, response) {
7
+ const out = {
8
+ request,
9
+ response,
10
+ requestScope: {}
11
+ };
12
+ Object.setPrototypeOf(out, executionContext);
13
+ return out;
14
+ }
15
+ OperationContext.from = from;
16
+ })(OperationContext || (exports.OperationContext = OperationContext = {}));
@@ -0,0 +1,107 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PlatformAdapterHost = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const path_1 = tslib_1.__importDefault(require("path"));
6
+ const putil_varhelpers_1 = require("putil-varhelpers");
7
+ const strict_typed_events_1 = require("strict-typed-events");
8
+ const common_1 = require("@opra/common");
9
+ const logger_js_1 = require("./services/logger.js");
10
+ /**
11
+ * @class PlatformAdapterHost
12
+ */
13
+ class PlatformAdapterHost extends strict_typed_events_1.AsyncEventEmitter {
14
+ constructor(api, options) {
15
+ super();
16
+ this.api = api;
17
+ this._controllers = new WeakMap();
18
+ this._initialized = false;
19
+ this._options = options || {};
20
+ this._logger = options?.logger && options.logger instanceof logger_js_1.Logger
21
+ ? options.logger
22
+ : new logger_js_1.Logger({ instance: options?.logger });
23
+ // Assign events
24
+ if (options?.on) {
25
+ for (const [event, fn] of Object.entries(options.on)) {
26
+ /* istanbul ignore next */
27
+ if (typeof fn === 'function')
28
+ this.on(event, fn);
29
+ }
30
+ }
31
+ // Make a safe service name
32
+ this._serviceName = (0, putil_varhelpers_1.pascalCase)((api.info.title || '').replace(/[^a-z0-9_ ]/ig, '')) || 'OpraService';
33
+ if (!/^[a-z]/i.test(this._serviceName))
34
+ this._serviceName = 'X' + this._serviceName;
35
+ }
36
+ get platform() {
37
+ return this._platform;
38
+ }
39
+ get protocol() {
40
+ return this._protocol;
41
+ }
42
+ get serviceName() {
43
+ return this.api.info.title;
44
+ }
45
+ async close() {
46
+ const promises = [];
47
+ for (const r of this.api.resources.values()) {
48
+ const onShutdown = r.onShutdown;
49
+ if (onShutdown)
50
+ promises.push((async () => onShutdown.call(r.controller, r))());
51
+ }
52
+ await Promise.allSettled(promises);
53
+ }
54
+ /**
55
+ * Initializes the adapter
56
+ */
57
+ async init() {
58
+ if (this._initialized)
59
+ return;
60
+ // Init I18n
61
+ if (this._options?.i18n instanceof common_1.I18n)
62
+ this._i18n = this._options.i18n;
63
+ else if (typeof this._options?.i18n === 'function')
64
+ this._i18n = await this._options.i18n();
65
+ else
66
+ this._i18n = await this._createI18n(this._options?.i18n);
67
+ this._i18n = this._i18n || common_1.I18n.defaultInstance;
68
+ if (!this._i18n.isInitialized)
69
+ await this._i18n.init();
70
+ // Initialize all controllers
71
+ for (const resource of this.api.resources.values()) {
72
+ await this.getController(resource);
73
+ }
74
+ this._initialized = true;
75
+ }
76
+ async getController(resource) {
77
+ resource = typeof resource === 'object' && resource instanceof common_1.Resource
78
+ ? resource : this.api.getResource(resource);
79
+ let controller = this._controllers.get(resource);
80
+ if (!controller) {
81
+ if (resource.controller) {
82
+ controller = typeof resource.controller === 'function' ?
83
+ new resource.controller()
84
+ : resource.controller;
85
+ // Initialize controller
86
+ if (typeof controller.onInit === 'function')
87
+ await controller.onInit.call(controller);
88
+ this._controllers.set(resource, controller);
89
+ }
90
+ }
91
+ return controller;
92
+ }
93
+ async _createI18n(options) {
94
+ const opts = {
95
+ ...options,
96
+ };
97
+ delete opts.resourceDirs;
98
+ const instance = common_1.I18n.createInstance(opts);
99
+ await instance.init();
100
+ await instance.loadResourceDir(path_1.default.resolve((0, common_1.getStackFileName)(), '../../../i18n'));
101
+ if (options?.resourceDirs)
102
+ for (const dir of options.resourceDirs)
103
+ await instance.loadResourceDir(dir);
104
+ return instance;
105
+ }
106
+ }
107
+ exports.PlatformAdapterHost = PlatformAdapterHost;
@@ -3,9 +3,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.RequestHost = void 0;
4
4
  class RequestHost {
5
5
  constructor(init) {
6
- this.contentId = '';
7
6
  Object.assign(this, init);
8
- this.resourceKind = this.resource.kind;
7
+ this.params = this.params || {};
9
8
  }
10
9
  switchToHttp() {
11
10
  if (this.http)
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,36 @@
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 ||
7
+ (!(process.env.NODE_ENV || '').includes('test') ? globalThis.console : {});
8
+ }
9
+ info(message, ...optionalParams) {
10
+ (this._instance.info || this._instance.log)?.(message, ...optionalParams);
11
+ }
12
+ error(message, ...optionalParams) {
13
+ if (this._instance.error) {
14
+ this._instance.error(message, ...optionalParams);
15
+ return;
16
+ }
17
+ this.info(message, ...optionalParams);
18
+ }
19
+ fatal(message, ...optionalParams) {
20
+ if (this._instance.fatal) {
21
+ this._instance.fatal(message, ...optionalParams);
22
+ return;
23
+ }
24
+ this.error(message, ...optionalParams);
25
+ }
26
+ warn(message, ...optionalParams) {
27
+ this._instance.warn?.(message, ...optionalParams);
28
+ }
29
+ debug(message, ...optionalParams) {
30
+ this._instance.debug?.(message, ...optionalParams);
31
+ }
32
+ verbose(message, ...optionalParams) {
33
+ this._instance.verbose?.(message, ...optionalParams);
34
+ }
35
+ }
36
+ exports.Logger = Logger;
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
package/cjs/index.js CHANGED
@@ -3,16 +3,22 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const tslib_1 = require("tslib");
4
4
  require("reflect-metadata");
5
5
  require("./augmentation/resource.augmentation.js");
6
+ require("./augmentation/collection.augmentation.js");
7
+ require("./augmentation/singleton.augmentation.js");
8
+ require("./augmentation/storage.augmentation.js");
6
9
  tslib_1.__exportStar(require("./types.js"), exports);
7
- tslib_1.__exportStar(require("./adapter/adapter.js"), exports);
10
+ tslib_1.__exportStar(require("./adapter/execution-context.js"), exports);
11
+ tslib_1.__exportStar(require("./adapter/operation-context.js"), exports);
12
+ tslib_1.__exportStar(require("./adapter/platform-adapter.js"), exports);
13
+ tslib_1.__exportStar(require("./adapter/request.js"), exports);
14
+ tslib_1.__exportStar(require("./adapter/response.js"), exports);
8
15
  tslib_1.__exportStar(require("./adapter/http/express-adapter.js"), exports);
9
16
  tslib_1.__exportStar(require("./adapter/http/http-adapter.js"), exports);
10
- tslib_1.__exportStar(require("./adapter/http/impl/http-server-request.js"), exports);
11
- tslib_1.__exportStar(require("./adapter/http/impl/http-server-response.js"), exports);
12
- tslib_1.__exportStar(require("./adapter/http/impl/http-incoming-message-host.js"), exports);
13
- tslib_1.__exportStar(require("./adapter/http/impl/http-outgoing-message-host.js"), exports);
14
- tslib_1.__exportStar(require("./adapter/interfaces/request-context.interface.js"), exports);
17
+ tslib_1.__exportStar(require("./adapter/http/impl/http-incoming-message.host.js"), exports);
18
+ tslib_1.__exportStar(require("./adapter/http/impl/http-outgoing-message.host.js"), exports);
19
+ tslib_1.__exportStar(require("./adapter/http/http-server-request.js"), exports);
20
+ tslib_1.__exportStar(require("./adapter/http/http-server-response.js"), exports);
15
21
  tslib_1.__exportStar(require("./adapter/interfaces/logger.interface.js"), exports);
16
- tslib_1.__exportStar(require("./adapter/interfaces/request.interface.js"), exports);
17
- tslib_1.__exportStar(require("./adapter/interfaces/response.interface.js"), exports);
18
- tslib_1.__exportStar(require("./shared/collection-resource-base.js"), exports);
22
+ tslib_1.__exportStar(require("./adapter/interfaces/request-handler.interface.js"), exports);
23
+ tslib_1.__exportStar(require("./adapter/services/logger.js"), exports);
24
+ tslib_1.__exportStar(require("./adapter/http/helpers/multipart-helper.js"), exports);
@@ -0,0 +1,44 @@
1
+ import { AsyncEventEmitter } from 'strict-typed-events';
2
+ export class ExecutionContextHost extends AsyncEventEmitter {
3
+ constructor(api, platform, protocol) {
4
+ super();
5
+ this.api = api;
6
+ this.platform = platform;
7
+ this.errors = [];
8
+ this.executionScope = {};
9
+ this.ws = protocol.ws;
10
+ this.rpc = protocol.rpc;
11
+ if (protocol.http) {
12
+ this.protocol = 'http';
13
+ this.http = {
14
+ platform,
15
+ incoming: protocol.http.incoming,
16
+ outgoing: protocol.http.outgoing,
17
+ switchToContext: () => this
18
+ };
19
+ }
20
+ else if (protocol.ws) {
21
+ this.protocol = 'ws';
22
+ this.ws = protocol.ws;
23
+ }
24
+ else if (protocol.rpc) {
25
+ this.protocol = 'rpc';
26
+ this.rpc = protocol.rpc;
27
+ }
28
+ }
29
+ switchToHttp() {
30
+ if (this.http)
31
+ return this.http;
32
+ throw new TypeError('Not executing in an "Http" context');
33
+ }
34
+ switchToWs() {
35
+ if (this.ws)
36
+ return this.ws;
37
+ throw new TypeError('Not executing in an "WebSocket" context');
38
+ }
39
+ switchToRpc() {
40
+ if (this.rpc)
41
+ return this.rpc;
42
+ throw new TypeError('Not executing in an "RPC" context');
43
+ }
44
+ }
@@ -0,0 +1,20 @@
1
+ import { OpraURLPath } from '@opra/common';
2
+ import { HttpAdapterBase } from './http-adapter-base.js';
3
+ import { HttpServerRequest } from './http-server-request.js';
4
+ import { HttpServerResponse } from './http-server-response.js';
5
+ export class ExpressAdapterHost extends HttpAdapterBase {
6
+ constructor(app, api, options) {
7
+ super(api, options);
8
+ this._platform = 'express';
9
+ const basePath = new OpraURLPath(options?.basePath);
10
+ app.use(basePath.toString(), (_req, _res) => {
11
+ const req = HttpServerRequest.from(_req);
12
+ const res = HttpServerResponse.from(_res);
13
+ this.handleIncoming(req, res)
14
+ .catch(() => void 0);
15
+ });
16
+ }
17
+ get app() {
18
+ return this._app;
19
+ }
20
+ }
@@ -1,22 +1,13 @@
1
- import { normalizePath } from '@opra/common';
2
- import { OpraHttpAdapter } from './http-adapter.js';
3
- import { HttpServerRequest } from './impl/http-server-request.js';
4
- import { HttpServerResponse } from './impl/http-server-response.js';
5
- export class OpraExpressAdapter extends OpraHttpAdapter {
6
- constructor() {
7
- super(...arguments);
8
- this.platform = 'express';
9
- }
10
- static async create(app, document, options) {
11
- const express = await import('express');
12
- const adapter = new OpraExpressAdapter(document);
13
- await adapter.init(options);
14
- const prefix = '/' + normalizePath(options?.prefix, true);
15
- app.use(prefix, express.json());
16
- app.use(prefix, (req, res, next) => {
17
- adapter.handler(HttpServerRequest.create(req), HttpServerResponse.create(res))
18
- .catch(e => next(e));
19
- });
1
+ import { ExpressAdapterHost } from './express-adapter.host.js';
2
+ /**
3
+ * @namespace
4
+ */
5
+ export var ExpressAdapter;
6
+ (function (ExpressAdapter) {
7
+ async function create(app, api, options) {
8
+ const adapter = new ExpressAdapterHost(app, api, options);
9
+ await adapter.init();
20
10
  return adapter;
21
11
  }
22
- }
12
+ ExpressAdapter.create = create;
13
+ })(ExpressAdapter || (ExpressAdapter = {}));
@@ -0,0 +1,16 @@
1
+ import { PassThrough } from 'stream';
2
+ export function concatReadable(...streams) {
3
+ const out = new PassThrough();
4
+ const pipeNext = () => {
5
+ const nextStream = streams.shift();
6
+ if (nextStream) {
7
+ nextStream.pipe(out, { end: false });
8
+ nextStream.once('end', () => pipeNext());
9
+ }
10
+ else {
11
+ out.end();
12
+ }
13
+ };
14
+ pipeNext();
15
+ return out;
16
+ }
@@ -0,0 +1,91 @@
1
+ import { EventEmitter } from 'events';
2
+ import formidable from 'formidable';
3
+ import fs from 'fs/promises';
4
+ const noOp = () => void 0;
5
+ export class MultipartIterator extends EventEmitter {
6
+ constructor(incoming, options) {
7
+ super();
8
+ this._cancelled = false;
9
+ this._items = [];
10
+ this._stack = [];
11
+ this.setMaxListeners(1000);
12
+ const form = this._form = formidable({
13
+ ...options,
14
+ filter: (part) => {
15
+ return !this._cancelled && (!options?.filter || options.filter(part));
16
+ }
17
+ });
18
+ form.once('error', () => {
19
+ this._cancelled = true;
20
+ if (this.listenerCount('error') > 0)
21
+ this.emit('error');
22
+ });
23
+ form.on('field', (field, value) => {
24
+ const item = { field, value };
25
+ this._items.push(item);
26
+ this._stack.push(item);
27
+ this.emit('item', item);
28
+ });
29
+ form.on('file', (field, file) => {
30
+ const item = { field, file };
31
+ this._items.push(item);
32
+ this._stack.push(item);
33
+ this.emit('item', item);
34
+ });
35
+ form.parse(incoming).catch(noOp);
36
+ }
37
+ get items() {
38
+ return this._items;
39
+ }
40
+ getNext() {
41
+ if (this._form.ended)
42
+ return Promise.resolve(undefined);
43
+ this.resume();
44
+ return new Promise((resolve, reject) => {
45
+ if (this._stack.length)
46
+ return resolve(this._stack.shift());
47
+ this.once('item', () => resolve(this._stack.shift()));
48
+ this.once('error', (e) => reject(e));
49
+ });
50
+ }
51
+ getAll() {
52
+ if (this._form.ended)
53
+ return Promise.resolve([...this._items]);
54
+ this.resume();
55
+ return new Promise((resolve, reject) => {
56
+ this._form.once('error', reject);
57
+ this._form.once('end', () => {
58
+ resolve([...this._items]);
59
+ });
60
+ });
61
+ }
62
+ cancel() {
63
+ this._cancelled = true;
64
+ this.resume();
65
+ }
66
+ resume() {
67
+ this._form.resume();
68
+ }
69
+ pause() {
70
+ this._form.pause();
71
+ }
72
+ async deleteFiles() {
73
+ const promises = [];
74
+ this._items
75
+ .forEach(item => {
76
+ if (!item.file)
77
+ return;
78
+ const file = item.file;
79
+ promises.push(new Promise(resolve => {
80
+ if (file._writeStream.closed)
81
+ return resolve();
82
+ file._writeStream.once('close', resolve);
83
+ }).then(() => {
84
+ return fs.unlink(file.filepath);
85
+ }).then(() => {
86
+ return 0;
87
+ }));
88
+ });
89
+ return Promise.allSettled(promises);
90
+ }
91
+ }
@@ -0,0 +1,12 @@
1
+ import { splitString } from 'fast-tokenizer';
2
+ export function parseArrayParam(v) {
3
+ if (!v)
4
+ return;
5
+ return splitString(v, {
6
+ delimiters: ',',
7
+ quotes: true,
8
+ brackets: true,
9
+ keepBrackets: true,
10
+ keepQuotes: true
11
+ }).map(x => x.trim());
12
+ }