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