@faasjs/func 0.0.2-beta.3 → 0.0.2-beta.302
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 +1 -1
- package/lib/index.d.ts +54 -44
- package/lib/index.es.js +83 -43
- package/lib/index.js +85 -45
- package/lib/plugins/run_handler/index.d.ts +3 -4
- package/package.json +19 -7
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
云函数模块。
|
|
4
4
|
|
|
5
|
-
[](https://github.com/faasjs/faasjs/blob/
|
|
5
|
+
[](https://github.com/faasjs/faasjs/blob/main/packages/faasjs/func/LICENSE)
|
|
6
6
|
[](https://www.npmjs.com/package/@faasjs/func)
|
|
7
7
|
[](https://www.npmjs.com/package/@faasjs/func)
|
|
8
8
|
|
package/lib/index.d.ts
CHANGED
|
@@ -1,37 +1,38 @@
|
|
|
1
|
-
import Logger from '@faasjs/logger';
|
|
2
|
-
export declare type Handler = (data: InvokeData) =>
|
|
1
|
+
import { Logger } from '@faasjs/logger';
|
|
2
|
+
export declare type Handler<TEvent = any, TContext = any, TResult = any> = (data: InvokeData<TEvent, TContext>) => Promise<TResult>;
|
|
3
3
|
export declare type Next = () => Promise<void>;
|
|
4
|
-
export declare type ExportedHandler = (event:
|
|
5
|
-
export
|
|
4
|
+
export declare type ExportedHandler<TEvent = any, TContext = any, TResult = any> = (event: TEvent, context?: TContext, callback?: (...args: any) => any) => Promise<TResult>;
|
|
5
|
+
export declare type Plugin = {
|
|
6
6
|
[key: string]: any;
|
|
7
|
+
readonly type: string;
|
|
8
|
+
readonly name: string;
|
|
9
|
+
onDeploy?: (data: DeployData, next: Next) => void | Promise<void>;
|
|
10
|
+
onMount?: (data: MountData, next: Next) => void | Promise<void>;
|
|
11
|
+
onInvoke?: (data: InvokeData, next: Next) => void | Promise<void>;
|
|
12
|
+
};
|
|
13
|
+
export declare type ProviderConfig = {
|
|
7
14
|
type: string;
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
export interface Config {
|
|
15
|
+
config: {
|
|
16
|
+
[key: string]: any;
|
|
17
|
+
};
|
|
18
|
+
};
|
|
19
|
+
export declare type Config = {
|
|
14
20
|
[key: string]: any;
|
|
15
|
-
providers
|
|
16
|
-
[key: string]:
|
|
17
|
-
type: string;
|
|
18
|
-
config: {
|
|
19
|
-
[key: string]: any;
|
|
20
|
-
};
|
|
21
|
-
};
|
|
21
|
+
providers?: {
|
|
22
|
+
[key: string]: ProviderConfig;
|
|
22
23
|
};
|
|
23
|
-
plugins
|
|
24
|
+
plugins?: {
|
|
24
25
|
[key: string]: {
|
|
25
26
|
[key: string]: any;
|
|
26
|
-
provider?: string;
|
|
27
|
+
provider?: string | ProviderConfig;
|
|
27
28
|
type: string;
|
|
28
29
|
config?: {
|
|
29
30
|
[key: string]: any;
|
|
30
31
|
};
|
|
31
32
|
};
|
|
32
33
|
};
|
|
33
|
-
}
|
|
34
|
-
export
|
|
34
|
+
};
|
|
35
|
+
export declare type DeployData = {
|
|
35
36
|
[key: string]: any;
|
|
36
37
|
root: string;
|
|
37
38
|
filename: string;
|
|
@@ -39,7 +40,7 @@ export interface DeployData {
|
|
|
39
40
|
name?: string;
|
|
40
41
|
config?: Config;
|
|
41
42
|
version?: string;
|
|
42
|
-
dependencies
|
|
43
|
+
dependencies: {
|
|
43
44
|
[name: string]: string;
|
|
44
45
|
};
|
|
45
46
|
plugins?: {
|
|
@@ -55,31 +56,36 @@ export interface DeployData {
|
|
|
55
56
|
};
|
|
56
57
|
};
|
|
57
58
|
logger?: Logger;
|
|
58
|
-
}
|
|
59
|
-
export
|
|
59
|
+
};
|
|
60
|
+
export declare type MountData = {
|
|
60
61
|
[key: string]: any;
|
|
61
62
|
config: Config;
|
|
62
63
|
event: any;
|
|
63
64
|
context: any;
|
|
64
|
-
}
|
|
65
|
-
export
|
|
65
|
+
};
|
|
66
|
+
export declare type InvokeData<TEvent = any, TContext = any, TResult = any> = {
|
|
66
67
|
[key: string]: any;
|
|
67
|
-
event:
|
|
68
|
-
context:
|
|
68
|
+
event: TEvent;
|
|
69
|
+
context: TContext;
|
|
69
70
|
callback: any;
|
|
70
71
|
response: any;
|
|
71
72
|
logger: Logger;
|
|
72
|
-
handler
|
|
73
|
+
handler?: Handler<TEvent, TContext, TResult>;
|
|
73
74
|
config: Config;
|
|
74
|
-
}
|
|
75
|
+
};
|
|
75
76
|
export declare type LifeCycleKey = 'onDeploy' | 'onMount' | 'onInvoke';
|
|
76
|
-
export declare
|
|
77
|
+
export declare type FuncConfig<TEvent = any, TContext = any, TResult = any> = {
|
|
78
|
+
plugins?: Plugin[];
|
|
79
|
+
handler?: Handler<TEvent, TContext, TResult>;
|
|
80
|
+
};
|
|
81
|
+
export declare class Func<TEvent = any, TContext = any, TResult = any> {
|
|
77
82
|
[key: string]: any;
|
|
78
83
|
plugins: Plugin[];
|
|
79
|
-
handler?: Handler
|
|
84
|
+
handler?: Handler<TEvent, TContext, TResult>;
|
|
80
85
|
logger: Logger;
|
|
81
86
|
config: Config;
|
|
82
|
-
|
|
87
|
+
mounted: boolean;
|
|
88
|
+
filename?: string;
|
|
83
89
|
private cachedFunctions;
|
|
84
90
|
/**
|
|
85
91
|
* 新建流程
|
|
@@ -87,10 +93,7 @@ export declare class Func {
|
|
|
87
93
|
* @param config.plugins {Plugin[]} 插件
|
|
88
94
|
* @param config.handler {Handler} 业务函数
|
|
89
95
|
*/
|
|
90
|
-
constructor(config:
|
|
91
|
-
plugins?: Plugin[];
|
|
92
|
-
handler?: Handler;
|
|
93
|
-
});
|
|
96
|
+
constructor(config: FuncConfig<TEvent, TContext>);
|
|
94
97
|
compose(key: LifeCycleKey): (data: any, next?: () => void) => any;
|
|
95
98
|
/**
|
|
96
99
|
* 发布云资源
|
|
@@ -104,19 +107,26 @@ export declare class Func {
|
|
|
104
107
|
* 启动云实例
|
|
105
108
|
*/
|
|
106
109
|
mount(data: {
|
|
107
|
-
event:
|
|
108
|
-
context:
|
|
109
|
-
config?:
|
|
110
|
-
}): Promise<
|
|
110
|
+
event: TEvent;
|
|
111
|
+
context: TContext;
|
|
112
|
+
config?: Config;
|
|
113
|
+
}): Promise<void>;
|
|
111
114
|
/**
|
|
112
115
|
* 执行云函数
|
|
113
116
|
* @param data {object} 执行信息
|
|
114
117
|
*/
|
|
115
|
-
invoke(data: InvokeData): Promise<
|
|
118
|
+
invoke(data: InvokeData<TEvent, TContext, TResult>): Promise<void>;
|
|
116
119
|
/**
|
|
117
120
|
* 创建触发函数
|
|
118
121
|
*/
|
|
119
|
-
export(): {
|
|
120
|
-
handler: ExportedHandler
|
|
122
|
+
export(config?: Config): {
|
|
123
|
+
handler: ExportedHandler<TEvent, TContext, TResult>;
|
|
121
124
|
};
|
|
122
125
|
}
|
|
126
|
+
export declare type UseifyPlugin = {
|
|
127
|
+
mount?: (data: {
|
|
128
|
+
config: Config;
|
|
129
|
+
}) => Promise<void>;
|
|
130
|
+
};
|
|
131
|
+
export declare function usePlugin<T extends Plugin>(plugin: T & UseifyPlugin): T & UseifyPlugin;
|
|
132
|
+
export declare function useFunc<TEvent = any, TContext = any, TResult = any>(handler: () => Handler<TEvent, TContext, TResult>): Func<TEvent, TContext, TResult>;
|
package/lib/index.es.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import Logger from '@faasjs/logger';
|
|
1
|
+
import { Logger } from '@faasjs/logger';
|
|
2
2
|
|
|
3
3
|
class RunHandler {
|
|
4
4
|
constructor() {
|
|
@@ -6,19 +6,15 @@ class RunHandler {
|
|
|
6
6
|
this.name = 'handler';
|
|
7
7
|
}
|
|
8
8
|
async onInvoke(data, next) {
|
|
9
|
-
if (data.handler)
|
|
9
|
+
if (data.handler)
|
|
10
10
|
if (!data.runHandler) {
|
|
11
|
-
data.logger.debug('[RunHandler] begin');
|
|
12
|
-
data.logger.time('RunHandler');
|
|
13
11
|
try {
|
|
14
12
|
data.response = await new Promise(function (resolve, reject) {
|
|
15
13
|
data.callback = function (error, result) {
|
|
16
|
-
if (error)
|
|
14
|
+
if (error)
|
|
17
15
|
reject(error);
|
|
18
|
-
|
|
19
|
-
else {
|
|
16
|
+
else
|
|
20
17
|
resolve(result);
|
|
21
|
-
}
|
|
22
18
|
};
|
|
23
19
|
Promise.resolve(data.handler(data)).then(function (result) {
|
|
24
20
|
resolve(result);
|
|
@@ -32,16 +28,14 @@ class RunHandler {
|
|
|
32
28
|
data.response = error;
|
|
33
29
|
}
|
|
34
30
|
data.runHandler = true;
|
|
35
|
-
data.logger.timeEnd('RunHandler', '[RunHandler] end %o', data.response);
|
|
36
31
|
}
|
|
37
|
-
else
|
|
32
|
+
else
|
|
38
33
|
data.logger.warn('[RunHandler] handler has been run');
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
34
|
await next();
|
|
42
35
|
}
|
|
43
36
|
}
|
|
44
37
|
|
|
38
|
+
let startedAt = Date.now();
|
|
45
39
|
class Func {
|
|
46
40
|
/**
|
|
47
41
|
* 新建流程
|
|
@@ -50,9 +44,10 @@ class Func {
|
|
|
50
44
|
* @param config.handler {Handler} 业务函数
|
|
51
45
|
*/
|
|
52
46
|
constructor(config) {
|
|
47
|
+
var _a;
|
|
53
48
|
this.logger = new Logger('Func');
|
|
54
49
|
this.handler = config.handler;
|
|
55
|
-
this.plugins = config.plugins
|
|
50
|
+
this.plugins = (_a = config.plugins) !== null && _a !== void 0 ? _a : [];
|
|
56
51
|
this.plugins.push(new RunHandler());
|
|
57
52
|
this.config = {
|
|
58
53
|
providers: Object.create(null),
|
|
@@ -60,23 +55,35 @@ class Func {
|
|
|
60
55
|
};
|
|
61
56
|
this.mounted = false;
|
|
62
57
|
this.cachedFunctions = Object.create(null);
|
|
58
|
+
try {
|
|
59
|
+
this.filename = new Error().stack
|
|
60
|
+
.split('\n')
|
|
61
|
+
.find(s => /[^/]\.func\.ts/.test(s))
|
|
62
|
+
.match(/\((.*\.func\.ts).*\)/)[1];
|
|
63
|
+
}
|
|
64
|
+
catch (error) {
|
|
65
|
+
this.logger.debug(error.message);
|
|
66
|
+
}
|
|
63
67
|
}
|
|
64
68
|
compose(key) {
|
|
69
|
+
const logger = new Logger(key);
|
|
65
70
|
let list = [];
|
|
66
|
-
if (this.cachedFunctions[key])
|
|
71
|
+
if (this.cachedFunctions[key])
|
|
67
72
|
list = this.cachedFunctions[key];
|
|
68
|
-
}
|
|
69
73
|
else {
|
|
70
74
|
for (const plugin of this.plugins) {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
75
|
+
const handler = plugin[key];
|
|
76
|
+
if (typeof handler === 'function')
|
|
77
|
+
list.push({
|
|
78
|
+
key: plugin.name,
|
|
79
|
+
handler: handler.bind(plugin)
|
|
80
|
+
});
|
|
74
81
|
}
|
|
75
82
|
this.cachedFunctions[key] = list;
|
|
76
83
|
}
|
|
77
|
-
return function (data, next) {
|
|
84
|
+
return async function (data, next) {
|
|
78
85
|
let index = -1;
|
|
79
|
-
const dispatch = function (i) {
|
|
86
|
+
const dispatch = async function (i) {
|
|
80
87
|
if (i <= index)
|
|
81
88
|
return Promise.reject(Error('next() called multiple times'));
|
|
82
89
|
index = i;
|
|
@@ -85,14 +92,22 @@ class Func {
|
|
|
85
92
|
fn = next;
|
|
86
93
|
if (!fn)
|
|
87
94
|
return Promise.resolve();
|
|
95
|
+
if (typeof fn.key === 'undefined')
|
|
96
|
+
fn.key = `UnNamedPlugin#${i}`;
|
|
97
|
+
logger.debug(`[${fn.key}] begin`);
|
|
98
|
+
logger.time(fn.key);
|
|
88
99
|
try {
|
|
89
|
-
|
|
100
|
+
const res = await Promise.resolve(fn.handler(data, dispatch.bind(null, i + 1)));
|
|
101
|
+
logger.timeEnd(fn.key, `[${fn.key}] end`);
|
|
102
|
+
return res;
|
|
90
103
|
}
|
|
91
104
|
catch (err) {
|
|
105
|
+
logger.timeEnd(fn.key, `[${fn.key}] failed`);
|
|
106
|
+
console.error(err);
|
|
92
107
|
return Promise.reject(err);
|
|
93
108
|
}
|
|
94
109
|
};
|
|
95
|
-
return dispatch(0);
|
|
110
|
+
return await dispatch(0);
|
|
96
111
|
};
|
|
97
112
|
}
|
|
98
113
|
/**
|
|
@@ -118,12 +133,12 @@ class Func {
|
|
|
118
133
|
data.config = this.config;
|
|
119
134
|
try {
|
|
120
135
|
this.logger.time('mount');
|
|
136
|
+
this.logger.debug('Plugins: ' + this.plugins.map(p => `${p.type}#${p.name}`).join(','));
|
|
121
137
|
await this.compose('onMount')(data);
|
|
122
138
|
this.mounted = true;
|
|
123
139
|
}
|
|
124
|
-
|
|
140
|
+
finally {
|
|
125
141
|
this.logger.timeEnd('mount', 'mounted');
|
|
126
|
-
throw error;
|
|
127
142
|
}
|
|
128
143
|
}
|
|
129
144
|
/**
|
|
@@ -131,60 +146,85 @@ class Func {
|
|
|
131
146
|
* @param data {object} 执行信息
|
|
132
147
|
*/
|
|
133
148
|
async invoke(data) {
|
|
134
|
-
this.logger.debug('onInvoke');
|
|
135
149
|
// 实例未启动时执行启动函数
|
|
136
|
-
if (!this.mounted)
|
|
150
|
+
if (!this.mounted)
|
|
137
151
|
await this.mount({
|
|
138
152
|
event: data.event,
|
|
139
153
|
context: data.context,
|
|
154
|
+
config: data.config
|
|
140
155
|
});
|
|
141
|
-
}
|
|
142
156
|
try {
|
|
143
157
|
await this.compose('onInvoke')(data);
|
|
144
158
|
}
|
|
145
159
|
catch (error) {
|
|
146
160
|
// 执行异常时回传异常
|
|
147
161
|
this.logger.error(error);
|
|
148
|
-
// eslint-disable-next-line require-atomic-updates
|
|
149
162
|
data.response = error;
|
|
150
163
|
}
|
|
151
164
|
}
|
|
152
165
|
/**
|
|
153
166
|
* 创建触发函数
|
|
154
167
|
*/
|
|
155
|
-
export() {
|
|
168
|
+
export(config) {
|
|
169
|
+
if (!this.config)
|
|
170
|
+
this.config = config || Object.create(null);
|
|
156
171
|
return {
|
|
157
172
|
handler: async (event, context, callback) => {
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
173
|
+
const logger = new Logger();
|
|
174
|
+
if (startedAt) {
|
|
175
|
+
logger.debug(`Container started +${Date.now() - startedAt}ms`);
|
|
176
|
+
startedAt = 0;
|
|
162
177
|
}
|
|
163
|
-
|
|
178
|
+
logger.debug('event: %j', event);
|
|
179
|
+
logger.debug('context: %j', context);
|
|
180
|
+
if (typeof context === 'undefined')
|
|
181
|
+
context = {};
|
|
182
|
+
if (!context.request_id)
|
|
164
183
|
context.request_id = new Date().getTime().toString();
|
|
165
|
-
|
|
166
|
-
if (!context.request_at) {
|
|
184
|
+
if (!context.request_at)
|
|
167
185
|
context.request_at = Math.round(new Date().getTime() / 1000);
|
|
168
|
-
|
|
186
|
+
context.callbackWaitsForEmptyEventLoop = false;
|
|
169
187
|
const data = {
|
|
170
188
|
event,
|
|
171
189
|
context,
|
|
172
190
|
callback,
|
|
173
191
|
response: undefined,
|
|
174
192
|
handler: this.handler,
|
|
175
|
-
logger
|
|
193
|
+
logger,
|
|
176
194
|
config: this.config
|
|
177
195
|
};
|
|
178
|
-
this.logger.time('invoke');
|
|
179
196
|
await this.invoke(data);
|
|
180
|
-
|
|
181
|
-
if (typeof data.response !== 'undefined' && (data.response instanceof Error || data.response.constructor.name === 'Error')) {
|
|
197
|
+
if (Object.prototype.toString.call(data.response) === '[object Error]')
|
|
182
198
|
throw data.response;
|
|
183
|
-
}
|
|
184
199
|
return data.response;
|
|
185
200
|
}
|
|
186
201
|
};
|
|
187
202
|
}
|
|
203
|
+
}
|
|
204
|
+
let plugins = [];
|
|
205
|
+
function usePlugin(plugin) {
|
|
206
|
+
if (!plugins.find(p => p.name === plugin.name))
|
|
207
|
+
plugins.push(plugin);
|
|
208
|
+
if (plugin.mount == null)
|
|
209
|
+
plugin.mount = async function ({ config }) {
|
|
210
|
+
if (plugin.onMount)
|
|
211
|
+
await plugin.onMount({
|
|
212
|
+
config,
|
|
213
|
+
event: {},
|
|
214
|
+
context: {}
|
|
215
|
+
}, async () => await Promise.resolve());
|
|
216
|
+
};
|
|
217
|
+
return plugin;
|
|
218
|
+
}
|
|
219
|
+
function useFunc(handler) {
|
|
220
|
+
plugins = [];
|
|
221
|
+
const invokeHandler = handler();
|
|
222
|
+
const func = new Func({
|
|
223
|
+
plugins,
|
|
224
|
+
handler: invokeHandler
|
|
225
|
+
});
|
|
226
|
+
plugins = [];
|
|
227
|
+
return func;
|
|
188
228
|
}
|
|
189
229
|
|
|
190
|
-
export { Func };
|
|
230
|
+
export { Func, useFunc, usePlugin };
|
package/lib/index.js
CHANGED
|
@@ -2,9 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
var Logger = _interopDefault(require('@faasjs/logger'));
|
|
5
|
+
var logger = require('@faasjs/logger');
|
|
8
6
|
|
|
9
7
|
class RunHandler {
|
|
10
8
|
constructor() {
|
|
@@ -12,19 +10,15 @@ class RunHandler {
|
|
|
12
10
|
this.name = 'handler';
|
|
13
11
|
}
|
|
14
12
|
async onInvoke(data, next) {
|
|
15
|
-
if (data.handler)
|
|
13
|
+
if (data.handler)
|
|
16
14
|
if (!data.runHandler) {
|
|
17
|
-
data.logger.debug('[RunHandler] begin');
|
|
18
|
-
data.logger.time('RunHandler');
|
|
19
15
|
try {
|
|
20
16
|
data.response = await new Promise(function (resolve, reject) {
|
|
21
17
|
data.callback = function (error, result) {
|
|
22
|
-
if (error)
|
|
18
|
+
if (error)
|
|
23
19
|
reject(error);
|
|
24
|
-
|
|
25
|
-
else {
|
|
20
|
+
else
|
|
26
21
|
resolve(result);
|
|
27
|
-
}
|
|
28
22
|
};
|
|
29
23
|
Promise.resolve(data.handler(data)).then(function (result) {
|
|
30
24
|
resolve(result);
|
|
@@ -38,16 +32,14 @@ class RunHandler {
|
|
|
38
32
|
data.response = error;
|
|
39
33
|
}
|
|
40
34
|
data.runHandler = true;
|
|
41
|
-
data.logger.timeEnd('RunHandler', '[RunHandler] end %o', data.response);
|
|
42
35
|
}
|
|
43
|
-
else
|
|
36
|
+
else
|
|
44
37
|
data.logger.warn('[RunHandler] handler has been run');
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
38
|
await next();
|
|
48
39
|
}
|
|
49
40
|
}
|
|
50
41
|
|
|
42
|
+
let startedAt = Date.now();
|
|
51
43
|
class Func {
|
|
52
44
|
/**
|
|
53
45
|
* 新建流程
|
|
@@ -56,9 +48,10 @@ class Func {
|
|
|
56
48
|
* @param config.handler {Handler} 业务函数
|
|
57
49
|
*/
|
|
58
50
|
constructor(config) {
|
|
59
|
-
|
|
51
|
+
var _a;
|
|
52
|
+
this.logger = new logger.Logger('Func');
|
|
60
53
|
this.handler = config.handler;
|
|
61
|
-
this.plugins = config.plugins
|
|
54
|
+
this.plugins = (_a = config.plugins) !== null && _a !== void 0 ? _a : [];
|
|
62
55
|
this.plugins.push(new RunHandler());
|
|
63
56
|
this.config = {
|
|
64
57
|
providers: Object.create(null),
|
|
@@ -66,23 +59,35 @@ class Func {
|
|
|
66
59
|
};
|
|
67
60
|
this.mounted = false;
|
|
68
61
|
this.cachedFunctions = Object.create(null);
|
|
62
|
+
try {
|
|
63
|
+
this.filename = new Error().stack
|
|
64
|
+
.split('\n')
|
|
65
|
+
.find(s => /[^/]\.func\.ts/.test(s))
|
|
66
|
+
.match(/\((.*\.func\.ts).*\)/)[1];
|
|
67
|
+
}
|
|
68
|
+
catch (error) {
|
|
69
|
+
this.logger.debug(error.message);
|
|
70
|
+
}
|
|
69
71
|
}
|
|
70
72
|
compose(key) {
|
|
73
|
+
const logger$1 = new logger.Logger(key);
|
|
71
74
|
let list = [];
|
|
72
|
-
if (this.cachedFunctions[key])
|
|
75
|
+
if (this.cachedFunctions[key])
|
|
73
76
|
list = this.cachedFunctions[key];
|
|
74
|
-
}
|
|
75
77
|
else {
|
|
76
78
|
for (const plugin of this.plugins) {
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
79
|
+
const handler = plugin[key];
|
|
80
|
+
if (typeof handler === 'function')
|
|
81
|
+
list.push({
|
|
82
|
+
key: plugin.name,
|
|
83
|
+
handler: handler.bind(plugin)
|
|
84
|
+
});
|
|
80
85
|
}
|
|
81
86
|
this.cachedFunctions[key] = list;
|
|
82
87
|
}
|
|
83
|
-
return function (data, next) {
|
|
88
|
+
return async function (data, next) {
|
|
84
89
|
let index = -1;
|
|
85
|
-
const dispatch = function (i) {
|
|
90
|
+
const dispatch = async function (i) {
|
|
86
91
|
if (i <= index)
|
|
87
92
|
return Promise.reject(Error('next() called multiple times'));
|
|
88
93
|
index = i;
|
|
@@ -91,14 +96,22 @@ class Func {
|
|
|
91
96
|
fn = next;
|
|
92
97
|
if (!fn)
|
|
93
98
|
return Promise.resolve();
|
|
99
|
+
if (typeof fn.key === 'undefined')
|
|
100
|
+
fn.key = `UnNamedPlugin#${i}`;
|
|
101
|
+
logger$1.debug(`[${fn.key}] begin`);
|
|
102
|
+
logger$1.time(fn.key);
|
|
94
103
|
try {
|
|
95
|
-
|
|
104
|
+
const res = await Promise.resolve(fn.handler(data, dispatch.bind(null, i + 1)));
|
|
105
|
+
logger$1.timeEnd(fn.key, `[${fn.key}] end`);
|
|
106
|
+
return res;
|
|
96
107
|
}
|
|
97
108
|
catch (err) {
|
|
109
|
+
logger$1.timeEnd(fn.key, `[${fn.key}] failed`);
|
|
110
|
+
console.error(err);
|
|
98
111
|
return Promise.reject(err);
|
|
99
112
|
}
|
|
100
113
|
};
|
|
101
|
-
return dispatch(0);
|
|
114
|
+
return await dispatch(0);
|
|
102
115
|
};
|
|
103
116
|
}
|
|
104
117
|
/**
|
|
@@ -124,12 +137,12 @@ class Func {
|
|
|
124
137
|
data.config = this.config;
|
|
125
138
|
try {
|
|
126
139
|
this.logger.time('mount');
|
|
140
|
+
this.logger.debug('Plugins: ' + this.plugins.map(p => `${p.type}#${p.name}`).join(','));
|
|
127
141
|
await this.compose('onMount')(data);
|
|
128
142
|
this.mounted = true;
|
|
129
143
|
}
|
|
130
|
-
|
|
144
|
+
finally {
|
|
131
145
|
this.logger.timeEnd('mount', 'mounted');
|
|
132
|
-
throw error;
|
|
133
146
|
}
|
|
134
147
|
}
|
|
135
148
|
/**
|
|
@@ -137,60 +150,87 @@ class Func {
|
|
|
137
150
|
* @param data {object} 执行信息
|
|
138
151
|
*/
|
|
139
152
|
async invoke(data) {
|
|
140
|
-
this.logger.debug('onInvoke');
|
|
141
153
|
// 实例未启动时执行启动函数
|
|
142
|
-
if (!this.mounted)
|
|
154
|
+
if (!this.mounted)
|
|
143
155
|
await this.mount({
|
|
144
156
|
event: data.event,
|
|
145
157
|
context: data.context,
|
|
158
|
+
config: data.config
|
|
146
159
|
});
|
|
147
|
-
}
|
|
148
160
|
try {
|
|
149
161
|
await this.compose('onInvoke')(data);
|
|
150
162
|
}
|
|
151
163
|
catch (error) {
|
|
152
164
|
// 执行异常时回传异常
|
|
153
165
|
this.logger.error(error);
|
|
154
|
-
// eslint-disable-next-line require-atomic-updates
|
|
155
166
|
data.response = error;
|
|
156
167
|
}
|
|
157
168
|
}
|
|
158
169
|
/**
|
|
159
170
|
* 创建触发函数
|
|
160
171
|
*/
|
|
161
|
-
export() {
|
|
172
|
+
export(config) {
|
|
173
|
+
if (!this.config)
|
|
174
|
+
this.config = config || Object.create(null);
|
|
162
175
|
return {
|
|
163
176
|
handler: async (event, context, callback) => {
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
177
|
+
const logger$1 = new logger.Logger();
|
|
178
|
+
if (startedAt) {
|
|
179
|
+
logger$1.debug(`Container started +${Date.now() - startedAt}ms`);
|
|
180
|
+
startedAt = 0;
|
|
168
181
|
}
|
|
169
|
-
|
|
182
|
+
logger$1.debug('event: %j', event);
|
|
183
|
+
logger$1.debug('context: %j', context);
|
|
184
|
+
if (typeof context === 'undefined')
|
|
185
|
+
context = {};
|
|
186
|
+
if (!context.request_id)
|
|
170
187
|
context.request_id = new Date().getTime().toString();
|
|
171
|
-
|
|
172
|
-
if (!context.request_at) {
|
|
188
|
+
if (!context.request_at)
|
|
173
189
|
context.request_at = Math.round(new Date().getTime() / 1000);
|
|
174
|
-
|
|
190
|
+
context.callbackWaitsForEmptyEventLoop = false;
|
|
175
191
|
const data = {
|
|
176
192
|
event,
|
|
177
193
|
context,
|
|
178
194
|
callback,
|
|
179
195
|
response: undefined,
|
|
180
196
|
handler: this.handler,
|
|
181
|
-
logger:
|
|
197
|
+
logger: logger$1,
|
|
182
198
|
config: this.config
|
|
183
199
|
};
|
|
184
|
-
this.logger.time('invoke');
|
|
185
200
|
await this.invoke(data);
|
|
186
|
-
|
|
187
|
-
if (typeof data.response !== 'undefined' && (data.response instanceof Error || data.response.constructor.name === 'Error')) {
|
|
201
|
+
if (Object.prototype.toString.call(data.response) === '[object Error]')
|
|
188
202
|
throw data.response;
|
|
189
|
-
}
|
|
190
203
|
return data.response;
|
|
191
204
|
}
|
|
192
205
|
};
|
|
193
206
|
}
|
|
207
|
+
}
|
|
208
|
+
let plugins = [];
|
|
209
|
+
function usePlugin(plugin) {
|
|
210
|
+
if (!plugins.find(p => p.name === plugin.name))
|
|
211
|
+
plugins.push(plugin);
|
|
212
|
+
if (plugin.mount == null)
|
|
213
|
+
plugin.mount = async function ({ config }) {
|
|
214
|
+
if (plugin.onMount)
|
|
215
|
+
await plugin.onMount({
|
|
216
|
+
config,
|
|
217
|
+
event: {},
|
|
218
|
+
context: {}
|
|
219
|
+
}, async () => await Promise.resolve());
|
|
220
|
+
};
|
|
221
|
+
return plugin;
|
|
222
|
+
}
|
|
223
|
+
function useFunc(handler) {
|
|
224
|
+
plugins = [];
|
|
225
|
+
const invokeHandler = handler();
|
|
226
|
+
const func = new Func({
|
|
227
|
+
plugins,
|
|
228
|
+
handler: invokeHandler
|
|
229
|
+
});
|
|
230
|
+
plugins = [];
|
|
231
|
+
return func;
|
|
194
232
|
}
|
|
195
233
|
|
|
196
234
|
exports.Func = Func;
|
|
235
|
+
exports.useFunc = useFunc;
|
|
236
|
+
exports.usePlugin = usePlugin;
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import { InvokeData } from '../../index';
|
|
2
|
-
export default class RunHandler {
|
|
1
|
+
import { InvokeData, Plugin } from '../../index';
|
|
2
|
+
export default class RunHandler implements Plugin {
|
|
3
3
|
readonly type: string;
|
|
4
|
-
name
|
|
5
|
-
constructor();
|
|
4
|
+
readonly name: string;
|
|
6
5
|
onInvoke(data: InvokeData, next: () => Promise<void>): Promise<void>;
|
|
7
6
|
}
|
package/package.json
CHANGED
|
@@ -1,21 +1,30 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@faasjs/func",
|
|
3
|
-
"version": "0.0.2-beta.
|
|
3
|
+
"version": "0.0.2-beta.302",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"types": "lib/index.d.ts",
|
|
7
7
|
"module": "lib/index.es.js",
|
|
8
|
+
"homepage": "https://faasjs.com/docs/func",
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "git+https://github.com/faasjs/faasjs.git",
|
|
12
|
+
"directory": "packages/func"
|
|
13
|
+
},
|
|
14
|
+
"bugs": {
|
|
15
|
+
"url": "https://github.com/faasjs/faasjs/issues"
|
|
16
|
+
},
|
|
17
|
+
"funding": "https://github.com/sponsors/faasjs",
|
|
8
18
|
"scripts": {
|
|
9
19
|
"lint": "eslint --ext .ts src",
|
|
10
|
-
"prepack": "rm -rf ./lib && rollup -c && mv lib/*/src/* lib/"
|
|
11
|
-
"ci": "yarn lint && jest --silent"
|
|
20
|
+
"prepack": "rm -rf ./lib && rollup -c && mv lib/*/src/* lib/"
|
|
12
21
|
},
|
|
13
22
|
"files": [
|
|
14
23
|
"lib"
|
|
15
24
|
],
|
|
16
|
-
"
|
|
17
|
-
"@faasjs/deep_merge": "^0.0.2-beta.
|
|
18
|
-
"@faasjs/logger": "^0.0.2-beta.
|
|
25
|
+
"peerDependencies": {
|
|
26
|
+
"@faasjs/deep_merge": "^0.0.2-beta.244",
|
|
27
|
+
"@faasjs/logger": "^0.0.2-beta.243"
|
|
19
28
|
},
|
|
20
29
|
"devDependencies": {
|
|
21
30
|
"@types/debug": "*",
|
|
@@ -25,5 +34,8 @@
|
|
|
25
34
|
"rollup-plugin-typescript2": "*",
|
|
26
35
|
"typescript": "*"
|
|
27
36
|
},
|
|
28
|
-
"
|
|
37
|
+
"engines": {
|
|
38
|
+
"npm": ">=8.0.0"
|
|
39
|
+
},
|
|
40
|
+
"gitHead": "b53fb35a91369afd0185fb555d98e5c9d90b54bd"
|
|
29
41
|
}
|