@midwayjs/fc-starter 3.4.0-beta.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.
package/README.md ADDED
@@ -0,0 +1,29 @@
1
+ # serverless fc starter
2
+
3
+ 本模块用于包裹无法定制运行时的 FaaS 平台,比如阿里云 FC。
4
+
5
+ ## 阿里云 FC
6
+
7
+ ```ts
8
+ import { asyncWrapper, start } from '@midwayjs/serverless-fc-starter';
9
+
10
+ let runtime;
11
+ exports.init = asyncWrapper(async () => {
12
+ runtime = await start();
13
+ });
14
+
15
+ // for web request
16
+ exports.handler = asyncWrapper(async (...args) => {
17
+ return runtime.asyncEvent(async function(ctx) {
18
+ return 'hello world'; // ctx.body = 'hello world';
19
+ })(...args);
20
+ });
21
+
22
+ // for event
23
+ exports.handler = asyncWrapper(async (...args) => {
24
+ return runtime.asyncEvent(async function(ctx, event) {
25
+ return {data: 1};
26
+ })(...args);
27
+ });
28
+
29
+ ```
@@ -0,0 +1,7 @@
1
+ import type { ServerlessStarterOptions } from '@midwayjs/faas';
2
+ export declare class BootstrapStarter {
3
+ applicationContext: any;
4
+ start(options?: ServerlessStarterOptions): {};
5
+ getApplicationContext(): any;
6
+ }
7
+ //# sourceMappingURL=index.d.ts.map
package/dist/index.js ADDED
@@ -0,0 +1,199 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.BootstrapStarter = void 0;
4
+ const core_1 = require("@midwayjs/core");
5
+ const getRawBody = require("raw-body");
6
+ function isOutputError() {
7
+ return (process.env.SERVERLESS_OUTPUT_ERROR_STACK === 'true' ||
8
+ ['local', 'development'].includes(process.env.MIDWAY_SERVER_ENV) ||
9
+ ['local', 'development'].includes(process.env.NODE_ENV));
10
+ }
11
+ class BootstrapStarter {
12
+ start(options = {}) {
13
+ if (!process.env.NODE_ENV) {
14
+ process.env.NODE_ENV = 'production';
15
+ }
16
+ if (process.env['FC_FUNC_CODE_PATH']) {
17
+ // 用于替换默认的上下文日志
18
+ process.env['MIDWAY_SERVERLESS_REPLACE_LOGGER'] = 'true';
19
+ // 移除控制台颜色,fc 控制台无法探测是否支持,日志采集也必须把颜色禁用掉
20
+ process.env['MIDWAY_LOGGER_DISABLE_COLORS'] = 'true';
21
+ }
22
+ const exports = {};
23
+ let framework;
24
+ exports[options.initializeMethodName || 'initializer'] = (0, core_1.wrapAsync)(async (context) => {
25
+ var _a, _b, _c;
26
+ const applicationAdapter = {
27
+ getFunctionName() {
28
+ return context.function.name;
29
+ },
30
+ getFunctionServiceName() {
31
+ return context.service.name;
32
+ },
33
+ };
34
+ (_a = options.performance) === null || _a === void 0 ? void 0 : _a.mark('starterRuntimeStartTime');
35
+ // init midway
36
+ const applicationContext = (this.applicationContext =
37
+ await (0, core_1.initializeGlobalApplicationContext)(Object.assign(options, {
38
+ globalConfig: {
39
+ faas: {
40
+ applicationAdapter,
41
+ },
42
+ },
43
+ })));
44
+ (_b = options.performance) === null || _b === void 0 ? void 0 : _b.mark('frameworkStartTime');
45
+ const midwayFrameworkService = applicationContext.get(core_1.MidwayFrameworkService);
46
+ framework = midwayFrameworkService.getMainFramework();
47
+ const handlerWrapper = (0, core_1.wrapAsync)(async (event, context, oldContext) => {
48
+ var _a, _b, _c, _d;
49
+ const isHTTPMode = event.constructor.name === 'IncomingMessage' ||
50
+ event.constructor.name === 'EventEmitter';
51
+ const isApiGateway = event &&
52
+ event.headers &&
53
+ 'queryParameters' in event &&
54
+ 'httpMethod' in event;
55
+ if (isHTTPMode) {
56
+ if (!((_a = oldContext.logger) === null || _a === void 0 ? void 0 : _a.info)) {
57
+ oldContext.logger = console;
58
+ }
59
+ }
60
+ else {
61
+ if (!((_b = context.logger) === null || _b === void 0 ? void 0 : _b.info)) {
62
+ context.logger = console;
63
+ }
64
+ }
65
+ const triggerFunction = framework.getTriggerFunction((oldContext === null || oldContext === void 0 ? void 0 : oldContext.function.handler) || context.function.handler);
66
+ let ctx;
67
+ if (isHTTPMode) {
68
+ event.getOriginContext = () => {
69
+ return oldContext;
70
+ };
71
+ // 如果需要解析body并且body是个stream
72
+ if (['post', 'put', 'delete'].indexOf(event.method.toLowerCase()) !==
73
+ -1 &&
74
+ !event.body &&
75
+ typeof event.on === 'function') {
76
+ event.body = await getRawBody(event, {
77
+ limit: '10mb',
78
+ });
79
+ }
80
+ ctx = await framework.wrapHttpRequest(event);
81
+ }
82
+ else if (isApiGateway) {
83
+ ctx = await framework.wrapHttpRequest(event, context);
84
+ }
85
+ else {
86
+ // 阿里云事件触发器,入参是 buffer
87
+ if (Buffer.isBuffer(event)) {
88
+ event = event.toString('utf8');
89
+ try {
90
+ event = JSON.parse(event);
91
+ }
92
+ catch (_err) {
93
+ /** ignore */
94
+ }
95
+ }
96
+ // format context
97
+ ctx = {
98
+ originEvent: event,
99
+ originContext: context,
100
+ logger: context.logger,
101
+ };
102
+ }
103
+ try {
104
+ const result = await triggerFunction(ctx, {
105
+ isHttpFunction: isHTTPMode || isApiGateway,
106
+ originEvent: event,
107
+ originContext: context,
108
+ });
109
+ if (isHTTPMode || isApiGateway) {
110
+ const { isBase64Encoded, statusCode, headers, body } = result;
111
+ if (isApiGateway) {
112
+ const newHeader = {};
113
+ for (const key in headers) {
114
+ // The length after base64 is wrong.
115
+ if (!['content-length'].includes(key)) {
116
+ if ('set-cookie' === key && !isHTTPMode) {
117
+ // unsupport multiple cookie when use apiGateway
118
+ newHeader[key] = headers[key][0];
119
+ if (headers[key].length > 1) {
120
+ ctx.logger.warn('[fc-starter]: unsupport multiple cookie when use apiGateway');
121
+ }
122
+ }
123
+ else {
124
+ newHeader[key] = headers[key];
125
+ }
126
+ }
127
+ }
128
+ return {
129
+ isBase64Encoded,
130
+ statusCode,
131
+ headers: newHeader,
132
+ body,
133
+ };
134
+ }
135
+ else {
136
+ const res = context;
137
+ if (res.headersSent) {
138
+ return;
139
+ }
140
+ if (res.setHeader) {
141
+ for (const key in headers) {
142
+ res.setHeader(key, headers[key]);
143
+ }
144
+ }
145
+ if (res.statusCode !== statusCode) {
146
+ if (res.setStatusCode) {
147
+ res.setStatusCode(statusCode);
148
+ }
149
+ if (res.statusCode) {
150
+ res.statusCode = statusCode;
151
+ }
152
+ }
153
+ if (res.send) {
154
+ // http trigger only support `Buffer` or a `string` or a `stream.Readable`
155
+ res.send(body);
156
+ }
157
+ }
158
+ }
159
+ else {
160
+ return result;
161
+ }
162
+ }
163
+ catch (err) {
164
+ ctx.logger.error(err);
165
+ const res = context;
166
+ if (res.setHeader) {
167
+ res.setHeader('content-type', 'text/plain');
168
+ }
169
+ if (res.send) {
170
+ res.setStatusCode((_c = err.status) !== null && _c !== void 0 ? _c : 500);
171
+ res.send(isOutputError() ? err.stack : 'Internal Server Error');
172
+ }
173
+ return {
174
+ isBase64Encoded: false,
175
+ statusCode: (_d = err.status) !== null && _d !== void 0 ? _d : 500,
176
+ headers: {},
177
+ body: isOutputError() ? err.stack : 'Internal Server Error',
178
+ };
179
+ }
180
+ });
181
+ if (options.exportAllHandler) {
182
+ for (const handlerName of framework.getAllHandlerNames()) {
183
+ exports[handlerName.split('.')[1]] = handlerWrapper;
184
+ }
185
+ }
186
+ else {
187
+ const handlerMethodName = context.function.handler.split('.')[1];
188
+ exports[handlerMethodName] = handlerWrapper;
189
+ }
190
+ (_c = options.performance) === null || _c === void 0 ? void 0 : _c.end();
191
+ });
192
+ return exports;
193
+ }
194
+ getApplicationContext() {
195
+ return this.applicationContext;
196
+ }
197
+ }
198
+ exports.BootstrapStarter = BootstrapStarter;
199
+ //# sourceMappingURL=index.js.map
package/package.json ADDED
@@ -0,0 +1,34 @@
1
+ {
2
+ "name": "@midwayjs/fc-starter",
3
+ "version": "3.4.0-beta.1",
4
+ "main": "dist/index",
5
+ "typings": "dist/index.d.ts",
6
+ "dependencies": {
7
+ "@midwayjs/faas": "^3.4.0-beta.1",
8
+ "raw-body": "2.5.1"
9
+ },
10
+ "devDependencies": {
11
+ "@midwayjs/core": "^3.4.0-beta.1",
12
+ "@midwayjs/decorator": "^3.4.0-beta.1",
13
+ "@midwayjs/runtime-mock": "^3.0.4",
14
+ "@midwayjs/serverless-http-parser": "^3.3.5"
15
+ },
16
+ "engines": {
17
+ "node": ">=12"
18
+ },
19
+ "files": [
20
+ "dist/**/*.js",
21
+ "dist/**/*.d.ts"
22
+ ],
23
+ "scripts": {
24
+ "build": "tsc",
25
+ "test": "node --require=ts-node/register ../../node_modules/.bin/jest --runInBand",
26
+ "cov": "node --require=ts-node/register ../../node_modules/.bin/jest --runInBand --coverage --forceExit"
27
+ },
28
+ "repository": {
29
+ "type": "git",
30
+ "url": "git@github.com:midwayjs/midway.git"
31
+ },
32
+ "license": "MIT",
33
+ "gitHead": "14d8440f20978426184c988808343cc24bcf6e20"
34
+ }