@midwayjs/faas 3.3.5 → 3.3.6-beta.3

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.
@@ -1,6 +1,8 @@
1
+ /// <reference types="node" />
1
2
  import { FaaSContext, IFaaSConfigurationOptions, IMidwayFaaSApplication } from './interface';
2
- import { BaseFramework, FunctionMiddleware, IMidwayBootstrapOptions, MidwayEnvironmentService, MidwayFrameworkType, MidwayMiddlewareService, RouterInfo } from '@midwayjs/core';
3
+ import { BaseFramework, ContextMiddlewareManager, FunctionMiddleware, IMidwayBootstrapOptions, MidwayEnvironmentService, MidwayFrameworkType, MidwayMiddlewareService, RouterInfo } from '@midwayjs/core';
3
4
  import { LoggerOptions } from '@midwayjs/logger';
5
+ import * as http from 'http';
4
6
  export declare class MidwayFaaSFramework extends BaseFramework<IMidwayFaaSApplication, FaaSContext, IFaaSConfigurationOptions> {
5
7
  protected defaultHandlerMethod: string;
6
8
  protected funMappingStore: Map<string, RouterInfo>;
@@ -9,6 +11,11 @@ export declare class MidwayFaaSFramework extends BaseFramework<IMidwayFaaSApplic
9
11
  app: IMidwayFaaSApplication;
10
12
  private isReplaceLogger;
11
13
  private developmentRun;
14
+ private serverlessRoutes;
15
+ private server;
16
+ private respond;
17
+ private applicationAdapter;
18
+ protected eventMiddlewareManager: ContextMiddlewareManager<FaaSContext, unknown, unknown>;
12
19
  environmentService: MidwayEnvironmentService;
13
20
  middlewareService: MidwayMiddlewareService<FaaSContext, any>;
14
21
  configure(options: IFaaSConfigurationOptions): any;
@@ -22,11 +29,13 @@ export declare class MidwayFaaSFramework extends BaseFramework<IMidwayFaaSApplic
22
29
  * @param middlewareId
23
30
  */
24
31
  generateMiddleware(middlewareId: string): Promise<FunctionMiddleware<FaaSContext, any>>;
25
- getContext(context: any): any;
32
+ getContext(context?: any): any;
26
33
  private invokeHandler;
27
34
  protected getFunctionHandler(ctx: any, args: any, target: any, method: any): string;
28
35
  createLogger(name: string, option?: LoggerOptions): import("@midwayjs/core").ILogger;
29
36
  getFrameworkName(): string;
37
+ getServer(): http.Server;
38
+ protected createHttpContext(req: any, res: any): Promise<unknown>;
30
39
  }
31
40
  export declare const createModuleServerlessFramework: (globalOption: Omit<IMidwayBootstrapOptions, 'applicationContext'> & IFaaSConfigurationOptions) => Promise<MidwayFaaSFramework>;
32
41
  //# sourceMappingURL=framework.d.ts.map
package/dist/framework.js CHANGED
@@ -14,6 +14,8 @@ const core_1 = require("@midwayjs/core");
14
14
  const decorator_1 = require("@midwayjs/decorator");
15
15
  const simple_lock_1 = require("@midwayjs/simple-lock");
16
16
  const logger_1 = require("@midwayjs/logger");
17
+ const serverless_http_parser_1 = require("@midwayjs/serverless-http-parser");
18
+ const http = require("http");
17
19
  const LOCK_KEY = '_faas_starter_start_key';
18
20
  let MidwayFaaSFramework = class MidwayFaaSFramework extends core_1.BaseFramework {
19
21
  constructor() {
@@ -23,6 +25,8 @@ let MidwayFaaSFramework = class MidwayFaaSFramework extends core_1.BaseFramework
23
25
  this.lock = new simple_lock_1.default();
24
26
  this.isReplaceLogger = process.env['MIDWAY_SERVERLESS_REPLACE_LOGGER'] === 'true';
25
27
  this.developmentRun = false;
28
+ this.serverlessRoutes = [];
29
+ this.eventMiddlewareManager = this.createMiddlewareManager();
26
30
  }
27
31
  configure(options) {
28
32
  var _a;
@@ -39,13 +43,14 @@ let MidwayFaaSFramework = class MidwayFaaSFramework extends core_1.BaseFramework
39
43
  return !this.developmentRun;
40
44
  }
41
45
  async applicationInitialize(options) {
42
- var _a;
46
+ var _a, _b;
43
47
  if (!this.logger) {
44
48
  this.logger = options.logger || logger_1.loggers.getLogger('appLogger');
45
49
  }
50
+ this.applicationAdapter = this.configurationOptions.applicationAdapter;
46
51
  this.app =
47
- ((_a = this.configurationOptions.applicationAdapter) === null || _a === void 0 ? void 0 : _a.getApplication()) ||
48
- {};
52
+ ((_a = this.applicationAdapter) === null || _a === void 0 ? void 0 : _a.getApplication()) ||
53
+ new serverless_http_parser_1.Application();
49
54
  this.defineApplicationProperties({
50
55
  /**
51
56
  * return init context value such as aliyun fc
@@ -68,21 +73,48 @@ let MidwayFaaSFramework = class MidwayFaaSFramework extends core_1.BaseFramework
68
73
  var _a;
69
74
  return (_a = this.configurationOptions.applicationAdapter) === null || _a === void 0 ? void 0 : _a.getFunctionServiceName();
70
75
  },
76
+ useEventMiddleware: () => { },
71
77
  });
72
78
  // hack use method
73
79
  this.app.originUse = this.app.use;
74
80
  this.app.use = this.app.useMiddleware;
81
+ if ((_b = this.configurationOptions.applicationAdapter) === null || _b === void 0 ? void 0 : _b.runAppHook) {
82
+ this.configurationOptions.applicationAdapter.runAppHook(this.app);
83
+ }
75
84
  }
76
85
  async run() {
77
86
  return this.lock.sureOnce(async () => {
78
- var _a;
87
+ var _a, _b;
79
88
  // set app keys
80
89
  this.app['keys'] = (_a = this.configService.getConfiguration('keys')) !== null && _a !== void 0 ? _a : '';
81
90
  // store all http function entry
82
91
  const collector = new core_1.ServerlessTriggerCollector();
83
92
  const functionList = await collector.getFunctionList();
84
93
  for (const funcInfo of functionList) {
94
+ // store handler
85
95
  this.funMappingStore.set(funcInfo.funcHandlerName, funcInfo);
96
+ if (funcInfo.url) {
97
+ // store router
98
+ this.serverlessRoutes.push({
99
+ matchPattern: (0, core_1.pathToRegexp)(funcInfo.url, [], { end: false }),
100
+ funcInfo: funcInfo,
101
+ });
102
+ }
103
+ }
104
+ this.respond = this.app.callback();
105
+ if (this.environmentService.isDevelopmentEnvironment()) {
106
+ const faasConfig = (_b = this.configService.getConfiguration('faas')) !== null && _b !== void 0 ? _b : {};
107
+ this.server = await new Promise(resolve => {
108
+ const server = http.createServer((req, res) => {
109
+ const url = new URL(req.url, `http://${req.headers.host}`);
110
+ // create event and invoke
111
+ this.handleInvokeWrapper(url.pathname)(req, res, {});
112
+ });
113
+ if (faasConfig['port']) {
114
+ server.listen(faasConfig['port']);
115
+ }
116
+ resolve(server);
117
+ });
86
118
  }
87
119
  }, LOCK_KEY);
88
120
  }
@@ -90,16 +122,41 @@ let MidwayFaaSFramework = class MidwayFaaSFramework extends core_1.BaseFramework
90
122
  return core_1.MidwayFrameworkType.FAAS;
91
123
  }
92
124
  handleInvokeWrapper(handlerMapping) {
93
- const funOptions = this.funMappingStore.get(handlerMapping);
125
+ let funOptions = this.funMappingStore.get(handlerMapping);
94
126
  return async (...args) => {
127
+ var _a, _b;
95
128
  if (args.length === 0) {
96
129
  throw new Error('first parameter must be function context');
97
130
  }
131
+ const event = args[0];
132
+ const isLegacyMode = event.originContext && event.originEvent;
133
+ const isHttpFunction = event.constructor.name === 'IncomingMessage' ||
134
+ event.constructor.name === 'EventEmitter' ||
135
+ !!(event.headers && event.get);
136
+ if (!funOptions && isHttpFunction) {
137
+ for (const item of this.serverlessRoutes) {
138
+ if (item.matchPattern.test(event.path)) {
139
+ funOptions = item.funcInfo;
140
+ break;
141
+ }
142
+ }
143
+ }
98
144
  if (!funOptions) {
99
145
  throw new Error(`function handler = ${handlerMapping} not found`);
100
146
  }
101
- const context = this.getContext(args.shift());
102
- const isHttpFunction = !!(context.headers && context.get);
147
+ let context;
148
+ if (isLegacyMode) {
149
+ context = this.getContext(args.shift());
150
+ }
151
+ else if (isHttpFunction) {
152
+ const newReq = ((_a = this.applicationAdapter) === null || _a === void 0 ? void 0 : _a.runRequestHook(...args)) ||
153
+ new serverless_http_parser_1.HTTPRequest(args[0], args[1]);
154
+ const newRes = new serverless_http_parser_1.HTTPResponse();
155
+ context = this.getContext(await this.createHttpContext(newReq, newRes));
156
+ }
157
+ else {
158
+ context = this.getContext(await ((_b = this.applicationAdapter) === null || _b === void 0 ? void 0 : _b.runEventHook(...args)));
159
+ }
103
160
  const globalMiddlewareFn = await this.applyMiddleware();
104
161
  const middlewareManager = new core_1.ContextMiddlewareManager();
105
162
  middlewareManager.insertLast(globalMiddlewareFn);
@@ -122,7 +179,58 @@ let MidwayFaaSFramework = class MidwayFaaSFramework extends core_1.BaseFramework
122
179
  return await fn(ctx, next);
123
180
  });
124
181
  const composeMiddleware = await this.middlewareService.compose(middlewareManager, this.app);
125
- return await composeMiddleware(context);
182
+ const result = await composeMiddleware(context);
183
+ if (isLegacyMode) {
184
+ return result;
185
+ }
186
+ else if (isHttpFunction) {
187
+ if (!context.response._explicitStatus) {
188
+ if (context.body === null || context.body === 'undefined') {
189
+ context.body = '';
190
+ context.type = 'text';
191
+ context.status = 204;
192
+ }
193
+ }
194
+ let encoded = false;
195
+ let data = context.body;
196
+ if (typeof data === 'string') {
197
+ if (!context.type) {
198
+ context.type = 'text/plain';
199
+ }
200
+ context.body = data;
201
+ }
202
+ else if (Buffer.isBuffer(data)) {
203
+ encoded = true;
204
+ if (!context.type) {
205
+ context.type = 'application/octet-stream';
206
+ }
207
+ // data is reserved as buffer
208
+ context.body = data.toString('base64');
209
+ }
210
+ else if (typeof data === 'object') {
211
+ if (!context.type) {
212
+ context.type = 'application/json';
213
+ }
214
+ // set data to string
215
+ context.body = data = JSON.stringify(data);
216
+ }
217
+ else {
218
+ if (!context.type) {
219
+ context.type = 'text/plain';
220
+ }
221
+ // set data to string
222
+ context.body = data = data + '';
223
+ }
224
+ return {
225
+ isBase64Encoded: encoded,
226
+ statusCode: context.status,
227
+ headers: context.res.headers,
228
+ body: context.body,
229
+ };
230
+ }
231
+ else {
232
+ return result;
233
+ }
126
234
  };
127
235
  }
128
236
  /**
@@ -133,7 +241,7 @@ let MidwayFaaSFramework = class MidwayFaaSFramework extends core_1.BaseFramework
133
241
  const mwIns = await this.getApplicationContext().getAsync(middlewareId);
134
242
  return mwIns.resolve();
135
243
  }
136
- getContext(context) {
244
+ getContext(context = {}) {
137
245
  if (!context.env) {
138
246
  context.env = this.environmentService.getCurrentEnvironment();
139
247
  }
@@ -201,6 +309,14 @@ let MidwayFaaSFramework = class MidwayFaaSFramework extends core_1.BaseFramework
201
309
  getFrameworkName() {
202
310
  return 'midway:faas';
203
311
  }
312
+ getServer() {
313
+ return this.server;
314
+ }
315
+ async createHttpContext(req, res) {
316
+ return new Promise(resolve => {
317
+ this.respond(req, res, resolve);
318
+ });
319
+ }
204
320
  };
205
321
  __decorate([
206
322
  (0, decorator_1.Inject)(),
@@ -1,12 +1,16 @@
1
1
  import { MidwayRequestContainer, IMidwayApplication, IConfigurationOptions, IMidwayContext, NextFunction as BaseNextFunction } from '@midwayjs/core';
2
2
  import { FaaSHTTPContext } from '@midwayjs/faas-typings';
3
3
  import { ILogger } from '@midwayjs/logger';
4
+ import { Application as ServerlessHttpApplication } from '@midwayjs/serverless-http-parser';
4
5
  export interface FaaSContext extends IMidwayContext<FaaSHTTPContext> {
5
6
  logger: ILogger;
6
7
  env: string;
7
8
  requestContext: MidwayRequestContainer;
8
9
  originContext: any;
9
10
  }
11
+ /**
12
+ * @deprecated
13
+ */
10
14
  export declare type FaaSMiddleware = ((context: FaaSContext, next: () => Promise<any>) => any) | string;
11
15
  export declare type IMidwayFaaSApplication = IMidwayApplication<FaaSContext, {
12
16
  getInitializeContext(): any;
@@ -24,7 +28,8 @@ export declare type IMidwayFaaSApplication = IMidwayApplication<FaaSContext, {
24
28
  * Get function service name in serverless environment
25
29
  */
26
30
  getFunctionServiceName(): string;
27
- }>;
31
+ useEventMiddleware(): void;
32
+ }> & ServerlessHttpApplication;
28
33
  export interface Application extends IMidwayFaaSApplication {
29
34
  }
30
35
  export interface Context extends FaaSContext {
@@ -37,8 +42,14 @@ export interface IFaaSConfigurationOptions extends IConfigurationOptions {
37
42
  getApplication(): IMidwayFaaSApplication;
38
43
  getFunctionName(): string;
39
44
  getFunctionServiceName(): string;
45
+ runAppHook?(app: IMidwayFaaSApplication): void;
46
+ runEventHook?(...args: any[]): any | void;
47
+ runRequestHook?(...args: any[]): any | void;
40
48
  };
41
49
  }
50
+ /**
51
+ * @deprecated
52
+ */
42
53
  export interface IWebMiddleware {
43
54
  resolve(): FaaSMiddleware;
44
55
  }
package/package.json CHANGED
@@ -1,13 +1,14 @@
1
1
  {
2
2
  "name": "@midwayjs/faas",
3
- "version": "3.3.5",
3
+ "version": "3.3.6-beta.3",
4
4
  "main": "dist/index",
5
5
  "typings": "index.d.ts",
6
6
  "dependencies": {
7
7
  "@midwayjs/core": "^3.3.5",
8
8
  "@midwayjs/faas-typings": "^3.3.5",
9
9
  "@midwayjs/logger": "^2.15.0",
10
- "@midwayjs/simple-lock": "^1.1.4"
10
+ "@midwayjs/simple-lock": "^1.1.4",
11
+ "@midwayjs/serverless-http-parser": "^3.3.5"
11
12
  },
12
13
  "devDependencies": {
13
14
  "@midwayjs/decorator": "^3.3.4",
@@ -45,5 +46,5 @@
45
46
  "url": "git@github.com:midwayjs/midway.git"
46
47
  },
47
48
  "license": "MIT",
48
- "gitHead": "5a835008aaa26e1b3c7d99c525f4a9fdaa3e41d1"
49
+ "gitHead": "a603d2348d6141f8f723901498f03a162a037708"
49
50
  }
package/LICENSE DELETED
@@ -1,21 +0,0 @@
1
- MIT License
2
-
3
- Copyright (c) 2013 - Now midwayjs
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.