@faasjs/func 8.0.0-beta.4 → 8.0.0-beta.6
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 +11 -0
- package/dist/index.cjs +121 -7
- package/dist/index.d.ts +42 -2
- package/dist/index.mjs +120 -8
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -19,7 +19,9 @@ npm install @faasjs/func
|
|
|
19
19
|
|
|
20
20
|
## Functions
|
|
21
21
|
|
|
22
|
+
- [defineFunc](functions/defineFunc.md)
|
|
22
23
|
- [nameFunc](functions/nameFunc.md)
|
|
24
|
+
- [parseFuncFilenameFromStack](functions/parseFuncFilenameFromStack.md)
|
|
23
25
|
- [useFunc](functions/useFunc.md)
|
|
24
26
|
- [usePlugin](functions/usePlugin.md)
|
|
25
27
|
|
|
@@ -27,6 +29,10 @@ npm install @faasjs/func
|
|
|
27
29
|
|
|
28
30
|
- [Func](classes/Func.md)
|
|
29
31
|
|
|
32
|
+
## Interfaces
|
|
33
|
+
|
|
34
|
+
- [FaasPluginEventMap](interfaces/FaasPluginEventMap.md)
|
|
35
|
+
|
|
30
36
|
## Type Aliases
|
|
31
37
|
|
|
32
38
|
- [Config](type-aliases/Config.md)
|
|
@@ -35,9 +41,14 @@ npm install @faasjs/func
|
|
|
35
41
|
- [FuncEventType](type-aliases/FuncEventType.md)
|
|
36
42
|
- [FuncReturnType](type-aliases/FuncReturnType.md)
|
|
37
43
|
- [Handler](type-aliases/Handler.md)
|
|
44
|
+
- [InferPluginEvent](type-aliases/InferPluginEvent.md)
|
|
38
45
|
- [InvokeData](type-aliases/InvokeData.md)
|
|
39
46
|
- [LifeCycleKey](type-aliases/LifeCycleKey.md)
|
|
40
47
|
- [MountData](type-aliases/MountData.md)
|
|
41
48
|
- [Next](type-aliases/Next.md)
|
|
49
|
+
- [NormalizePluginType](type-aliases/NormalizePluginType.md)
|
|
42
50
|
- [Plugin](type-aliases/Plugin.md)
|
|
51
|
+
- [ResolvePluginEvent](type-aliases/ResolvePluginEvent.md)
|
|
52
|
+
- [Simplify](type-aliases/Simplify.md)
|
|
53
|
+
- [UnionToIntersection](type-aliases/UnionToIntersection.md)
|
|
43
54
|
- [UseifyPlugin](type-aliases/UseifyPlugin.md)
|
package/dist/index.cjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var crypto = require('crypto');
|
|
4
|
+
var url = require('url');
|
|
4
5
|
var logger = require('@faasjs/logger');
|
|
5
6
|
|
|
6
7
|
// src/index.ts
|
|
@@ -38,12 +39,41 @@ function nameFunc(name, handler) {
|
|
|
38
39
|
}
|
|
39
40
|
|
|
40
41
|
// src/index.ts
|
|
42
|
+
function parseFuncFilenameFromStack(stack) {
|
|
43
|
+
if (!stack) return;
|
|
44
|
+
const frame = stack.split("\n").map((line) => line.trim()).find((line) => line.includes(".func.ts"));
|
|
45
|
+
if (!frame) return;
|
|
46
|
+
const content = frame.replace(/^at\s+/, "");
|
|
47
|
+
const location = content.endsWith(")") && content.includes("(") ? content.slice(content.lastIndexOf("(") + 1, -1) : content;
|
|
48
|
+
const match = location.match(/^(.+\.func\.ts):\d+:\d+$/);
|
|
49
|
+
if (!match) return;
|
|
50
|
+
const filename = match[1];
|
|
51
|
+
if (filename.startsWith("file://")) {
|
|
52
|
+
try {
|
|
53
|
+
return url.fileURLToPath(filename);
|
|
54
|
+
} catch (_) {
|
|
55
|
+
return filename;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return filename;
|
|
59
|
+
}
|
|
60
|
+
function formatPluginModuleName(type) {
|
|
61
|
+
if (type.startsWith("npm:")) return type.slice(4);
|
|
62
|
+
if (type.startsWith("@") || type.startsWith(".") || type.startsWith("/") || type.includes(":"))
|
|
63
|
+
return type;
|
|
64
|
+
return `@faasjs/${type}`;
|
|
65
|
+
}
|
|
66
|
+
function formatPluginClassName(type) {
|
|
67
|
+
return type.replace(/^@[^/]+\//, "").split(/[^A-Za-z0-9]+/).filter(Boolean).map((item) => item.slice(0, 1).toUpperCase() + item.slice(1)).join("");
|
|
68
|
+
}
|
|
41
69
|
var Func = class {
|
|
42
70
|
plugins;
|
|
43
71
|
handler;
|
|
44
72
|
config;
|
|
45
73
|
mounted = false;
|
|
46
74
|
filename;
|
|
75
|
+
autoLoadPluginsFromConfig;
|
|
76
|
+
loadedConfigPlugins = false;
|
|
47
77
|
cachedFunctions = /* @__PURE__ */ Object.create(null);
|
|
48
78
|
/**
|
|
49
79
|
* Create a cloud function
|
|
@@ -55,20 +85,90 @@ var Func = class {
|
|
|
55
85
|
this.handler = config.handler;
|
|
56
86
|
this.plugins = config.plugins || [];
|
|
57
87
|
this.plugins.push(new RunHandler());
|
|
88
|
+
this.autoLoadPluginsFromConfig = !!config.autoLoadPluginsFromConfig;
|
|
58
89
|
this.config = {
|
|
59
90
|
plugins: /* @__PURE__ */ Object.create(null)
|
|
60
91
|
};
|
|
61
92
|
try {
|
|
62
|
-
|
|
63
|
-
if (stack) {
|
|
64
|
-
const match = stack.split("\n").find((s) => /[^/]\.func\.ts/.test(s))?.match(/\((.*\.func\.ts).*\)/);
|
|
65
|
-
if (match) {
|
|
66
|
-
this.filename = match[1];
|
|
67
|
-
}
|
|
68
|
-
}
|
|
93
|
+
this.filename = parseFuncFilenameFromStack(new Error().stack);
|
|
69
94
|
} catch (_) {
|
|
70
95
|
}
|
|
71
96
|
}
|
|
97
|
+
insertPluginBeforeRunHandler(plugin) {
|
|
98
|
+
const index = this.plugins.findIndex(
|
|
99
|
+
(p) => p.type === "handler" && p.name === "handler"
|
|
100
|
+
);
|
|
101
|
+
if (index === -1) this.plugins.push(plugin);
|
|
102
|
+
else this.plugins.splice(index, 0, plugin);
|
|
103
|
+
this.cachedFunctions = /* @__PURE__ */ Object.create(null);
|
|
104
|
+
}
|
|
105
|
+
async resolvePluginConstructor(moduleName, className, pluginName) {
|
|
106
|
+
let mod;
|
|
107
|
+
try {
|
|
108
|
+
mod = await import(moduleName);
|
|
109
|
+
} catch (error) {
|
|
110
|
+
throw Error(
|
|
111
|
+
`[defineFunc] Failed to load plugin "${pluginName}" from "${moduleName}": ${error.message}`
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
const constructors = [];
|
|
115
|
+
if (className && mod[className]) constructors.push(mod[className]);
|
|
116
|
+
if (typeof mod.default === "function") constructors.push(mod.default);
|
|
117
|
+
if (mod.default && typeof mod.default === "object" && className && mod.default[className])
|
|
118
|
+
constructors.push(mod.default[className]);
|
|
119
|
+
for (const key in mod) {
|
|
120
|
+
if (key === className || key === "default") continue;
|
|
121
|
+
constructors.push(mod[key]);
|
|
122
|
+
}
|
|
123
|
+
if (mod.default && typeof mod.default === "object")
|
|
124
|
+
for (const key in mod.default) {
|
|
125
|
+
if (key === className) continue;
|
|
126
|
+
constructors.push(mod.default[key]);
|
|
127
|
+
}
|
|
128
|
+
const PluginConstructor = constructors.find(
|
|
129
|
+
(pluginConstructor) => typeof pluginConstructor === "function" && pluginConstructor.prototype && (typeof pluginConstructor.prototype.onMount === "function" || typeof pluginConstructor.prototype.onInvoke === "function")
|
|
130
|
+
);
|
|
131
|
+
if (!PluginConstructor)
|
|
132
|
+
throw Error(
|
|
133
|
+
`[defineFunc] Failed to resolve plugin class "${className}" from "${moduleName}" for plugin "${pluginName}".`
|
|
134
|
+
);
|
|
135
|
+
return PluginConstructor;
|
|
136
|
+
}
|
|
137
|
+
async loadPluginsFromConfig(config) {
|
|
138
|
+
const pluginConfigs = config.plugins || /* @__PURE__ */ Object.create(null);
|
|
139
|
+
for (const key in pluginConfigs) {
|
|
140
|
+
const rawConfig = pluginConfigs[key];
|
|
141
|
+
const configValue = rawConfig && typeof rawConfig === "object" ? Object.assign(/* @__PURE__ */ Object.create(null), rawConfig) : /* @__PURE__ */ Object.create(null);
|
|
142
|
+
const pluginName = typeof configValue.name === "string" && configValue.name.length ? configValue.name : key;
|
|
143
|
+
if (this.plugins.find((plugin2) => plugin2.name === pluginName)) continue;
|
|
144
|
+
const pluginType = typeof configValue.type === "string" && configValue.type || typeof rawConfig === "string" && rawConfig || key;
|
|
145
|
+
const moduleName = formatPluginModuleName(pluginType);
|
|
146
|
+
const className = formatPluginClassName(pluginType);
|
|
147
|
+
const PluginConstructor = await this.resolvePluginConstructor(
|
|
148
|
+
moduleName,
|
|
149
|
+
className,
|
|
150
|
+
pluginName
|
|
151
|
+
);
|
|
152
|
+
let plugin;
|
|
153
|
+
try {
|
|
154
|
+
plugin = new PluginConstructor({
|
|
155
|
+
...configValue,
|
|
156
|
+
name: pluginName,
|
|
157
|
+
type: pluginType
|
|
158
|
+
});
|
|
159
|
+
} catch (error) {
|
|
160
|
+
throw Error(
|
|
161
|
+
`[defineFunc] Failed to initialize plugin "${pluginName}" from "${moduleName}": ${error.message}`
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
if (!plugin || typeof plugin !== "object")
|
|
165
|
+
throw Error(
|
|
166
|
+
`[defineFunc] Invalid plugin instance for "${pluginName}" from "${moduleName}".`
|
|
167
|
+
);
|
|
168
|
+
this.insertPluginBeforeRunHandler(plugin);
|
|
169
|
+
}
|
|
170
|
+
this.loadedConfigPlugins = true;
|
|
171
|
+
}
|
|
72
172
|
compose(key) {
|
|
73
173
|
let list = [];
|
|
74
174
|
if (this.cachedFunctions[key]) list = this.cachedFunctions[key];
|
|
@@ -131,6 +231,8 @@ var Func = class {
|
|
|
131
231
|
return;
|
|
132
232
|
}
|
|
133
233
|
if (!data.config) data.config = this.config;
|
|
234
|
+
if (this.autoLoadPluginsFromConfig && !this.loadedConfigPlugins)
|
|
235
|
+
await this.loadPluginsFromConfig(data.config);
|
|
134
236
|
data.logger.debug(
|
|
135
237
|
`plugins: ${this.plugins.map((p) => `${p.type}#${p.name}`).join(",")}`
|
|
136
238
|
);
|
|
@@ -207,8 +309,20 @@ function useFunc(handler) {
|
|
|
207
309
|
plugins = [];
|
|
208
310
|
return func;
|
|
209
311
|
}
|
|
312
|
+
function defineFunc(handler) {
|
|
313
|
+
plugins = [];
|
|
314
|
+
const func = new Func({
|
|
315
|
+
plugins,
|
|
316
|
+
handler,
|
|
317
|
+
autoLoadPluginsFromConfig: true
|
|
318
|
+
});
|
|
319
|
+
plugins = [];
|
|
320
|
+
return func;
|
|
321
|
+
}
|
|
210
322
|
|
|
211
323
|
exports.Func = Func;
|
|
324
|
+
exports.defineFunc = defineFunc;
|
|
212
325
|
exports.nameFunc = nameFunc;
|
|
326
|
+
exports.parseFuncFilenameFromStack = parseFuncFilenameFromStack;
|
|
213
327
|
exports.useFunc = useFunc;
|
|
214
328
|
exports.usePlugin = usePlugin;
|
package/dist/index.d.ts
CHANGED
|
@@ -55,7 +55,7 @@ type Config = {
|
|
|
55
55
|
plugins?: {
|
|
56
56
|
[key: string]: {
|
|
57
57
|
[key: string]: any;
|
|
58
|
-
type
|
|
58
|
+
type?: string;
|
|
59
59
|
config?: {
|
|
60
60
|
[key: string]: any;
|
|
61
61
|
};
|
|
@@ -82,6 +82,7 @@ type LifeCycleKey = 'onMount' | 'onInvoke';
|
|
|
82
82
|
type FuncConfig<TEvent = any, TContext = any, TResult = any> = {
|
|
83
83
|
plugins?: Plugin[];
|
|
84
84
|
handler?: Handler<TEvent, TContext, TResult>;
|
|
85
|
+
autoLoadPluginsFromConfig?: boolean;
|
|
85
86
|
};
|
|
86
87
|
/**
|
|
87
88
|
* Get the event type of a func
|
|
@@ -109,6 +110,30 @@ type FuncEventType<T extends Func<any, any, any>> = T extends Func<infer P, any,
|
|
|
109
110
|
* ```
|
|
110
111
|
*/
|
|
111
112
|
type FuncReturnType<T extends Func<any, any, any>> = T extends Func<any, any, infer R> ? R : any;
|
|
113
|
+
type NormalizePluginType<TType extends string> = TType extends `npm:${infer Name}` ? Name : TType extends `@faasjs/${infer Name}` ? Name : TType;
|
|
114
|
+
type UnionToIntersection<T> = (T extends unknown ? (arg: T) => void : never) extends (arg: infer TResult) => void ? TResult : never;
|
|
115
|
+
type Simplify<T> = {
|
|
116
|
+
[K in keyof T]: T[K];
|
|
117
|
+
} & {};
|
|
118
|
+
/**
|
|
119
|
+
* Plugin event augmentation map.
|
|
120
|
+
*
|
|
121
|
+
* Extend this interface in plugin packages to describe which event fields are
|
|
122
|
+
* injected when the plugin is enabled through `faas.yaml`.
|
|
123
|
+
*/
|
|
124
|
+
interface FaasPluginEventMap {
|
|
125
|
+
}
|
|
126
|
+
type ResolvePluginEvent<TType extends string> = NormalizePluginType<TType> extends keyof FaasPluginEventMap ? FaasPluginEventMap[NormalizePluginType<TType>] : Record<never, never>;
|
|
127
|
+
/**
|
|
128
|
+
* Infer event type from plugin type names.
|
|
129
|
+
*
|
|
130
|
+
* @example
|
|
131
|
+
* ```ts
|
|
132
|
+
* type Event = InferPluginEvent<['http']>
|
|
133
|
+
* ```
|
|
134
|
+
*/
|
|
135
|
+
type InferPluginEvent<TPlugins extends readonly string[]> = Simplify<Record<string, any> & UnionToIntersection<ResolvePluginEvent<TPlugins[number]>>>;
|
|
136
|
+
declare function parseFuncFilenameFromStack(stack?: string): string | undefined;
|
|
112
137
|
declare class Func<TEvent = any, TContext = any, TResult = any> {
|
|
113
138
|
[key: string]: any;
|
|
114
139
|
plugins: Plugin[];
|
|
@@ -116,6 +141,8 @@ declare class Func<TEvent = any, TContext = any, TResult = any> {
|
|
|
116
141
|
config: Config;
|
|
117
142
|
mounted: boolean;
|
|
118
143
|
filename?: string;
|
|
144
|
+
private readonly autoLoadPluginsFromConfig;
|
|
145
|
+
private loadedConfigPlugins;
|
|
119
146
|
private cachedFunctions;
|
|
120
147
|
/**
|
|
121
148
|
* Create a cloud function
|
|
@@ -124,6 +151,9 @@ declare class Func<TEvent = any, TContext = any, TResult = any> {
|
|
|
124
151
|
* @param config.handler {Handler} business logic
|
|
125
152
|
*/
|
|
126
153
|
constructor(config: FuncConfig<TEvent, TContext>);
|
|
154
|
+
private insertPluginBeforeRunHandler;
|
|
155
|
+
private resolvePluginConstructor;
|
|
156
|
+
private loadPluginsFromConfig;
|
|
127
157
|
private compose;
|
|
128
158
|
/**
|
|
129
159
|
* First time mount the function
|
|
@@ -179,5 +209,15 @@ declare function usePlugin<T extends Plugin>(plugin: T & {
|
|
|
179
209
|
* ```
|
|
180
210
|
*/
|
|
181
211
|
declare function useFunc<TEvent = any, TContext = any, TResult = any>(handler: () => Handler<TEvent, TContext, TResult>): Func<TEvent, TContext, TResult>;
|
|
212
|
+
/**
|
|
213
|
+
* Create a cloud function from business logic and auto-load plugins from
|
|
214
|
+
* `func.config.plugins`.
|
|
215
|
+
*
|
|
216
|
+
* `defineFunc` receives business logic directly (no wrapper function), and
|
|
217
|
+
* resolves plugin modules during the first mount based on config from
|
|
218
|
+
* `faas.yaml` (already loaded into `func.config` by `@faasjs/load`,
|
|
219
|
+
* `@faasjs/server`, or `@faasjs/dev`).
|
|
220
|
+
*/
|
|
221
|
+
declare function defineFunc<TEvent = any, TContext = any, TResult = any>(handler: Handler<TEvent, TContext, TResult>): Func<TEvent, TContext, TResult>;
|
|
182
222
|
|
|
183
|
-
export { type Config, type ExportedHandler, Func, type FuncConfig, type FuncEventType, type FuncReturnType, type Handler, type InvokeData, type LifeCycleKey, type MountData, type Next, type Plugin, type UseifyPlugin, nameFunc, useFunc, usePlugin };
|
|
223
|
+
export { type Config, type ExportedHandler, type FaasPluginEventMap, Func, type FuncConfig, type FuncEventType, type FuncReturnType, type Handler, type InferPluginEvent, type InvokeData, type LifeCycleKey, type MountData, type Next, type NormalizePluginType, type Plugin, type ResolvePluginEvent, type Simplify, type UnionToIntersection, type UseifyPlugin, defineFunc, nameFunc, parseFuncFilenameFromStack, useFunc, usePlugin };
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { randomBytes } from 'crypto';
|
|
2
|
+
import { fileURLToPath } from 'url';
|
|
2
3
|
import { Logger } from '@faasjs/logger';
|
|
3
4
|
|
|
4
5
|
// src/index.ts
|
|
@@ -36,12 +37,41 @@ function nameFunc(name, handler) {
|
|
|
36
37
|
}
|
|
37
38
|
|
|
38
39
|
// src/index.ts
|
|
40
|
+
function parseFuncFilenameFromStack(stack) {
|
|
41
|
+
if (!stack) return;
|
|
42
|
+
const frame = stack.split("\n").map((line) => line.trim()).find((line) => line.includes(".func.ts"));
|
|
43
|
+
if (!frame) return;
|
|
44
|
+
const content = frame.replace(/^at\s+/, "");
|
|
45
|
+
const location = content.endsWith(")") && content.includes("(") ? content.slice(content.lastIndexOf("(") + 1, -1) : content;
|
|
46
|
+
const match = location.match(/^(.+\.func\.ts):\d+:\d+$/);
|
|
47
|
+
if (!match) return;
|
|
48
|
+
const filename = match[1];
|
|
49
|
+
if (filename.startsWith("file://")) {
|
|
50
|
+
try {
|
|
51
|
+
return fileURLToPath(filename);
|
|
52
|
+
} catch (_) {
|
|
53
|
+
return filename;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return filename;
|
|
57
|
+
}
|
|
58
|
+
function formatPluginModuleName(type) {
|
|
59
|
+
if (type.startsWith("npm:")) return type.slice(4);
|
|
60
|
+
if (type.startsWith("@") || type.startsWith(".") || type.startsWith("/") || type.includes(":"))
|
|
61
|
+
return type;
|
|
62
|
+
return `@faasjs/${type}`;
|
|
63
|
+
}
|
|
64
|
+
function formatPluginClassName(type) {
|
|
65
|
+
return type.replace(/^@[^/]+\//, "").split(/[^A-Za-z0-9]+/).filter(Boolean).map((item) => item.slice(0, 1).toUpperCase() + item.slice(1)).join("");
|
|
66
|
+
}
|
|
39
67
|
var Func = class {
|
|
40
68
|
plugins;
|
|
41
69
|
handler;
|
|
42
70
|
config;
|
|
43
71
|
mounted = false;
|
|
44
72
|
filename;
|
|
73
|
+
autoLoadPluginsFromConfig;
|
|
74
|
+
loadedConfigPlugins = false;
|
|
45
75
|
cachedFunctions = /* @__PURE__ */ Object.create(null);
|
|
46
76
|
/**
|
|
47
77
|
* Create a cloud function
|
|
@@ -53,20 +83,90 @@ var Func = class {
|
|
|
53
83
|
this.handler = config.handler;
|
|
54
84
|
this.plugins = config.plugins || [];
|
|
55
85
|
this.plugins.push(new RunHandler());
|
|
86
|
+
this.autoLoadPluginsFromConfig = !!config.autoLoadPluginsFromConfig;
|
|
56
87
|
this.config = {
|
|
57
88
|
plugins: /* @__PURE__ */ Object.create(null)
|
|
58
89
|
};
|
|
59
90
|
try {
|
|
60
|
-
|
|
61
|
-
if (stack) {
|
|
62
|
-
const match = stack.split("\n").find((s) => /[^/]\.func\.ts/.test(s))?.match(/\((.*\.func\.ts).*\)/);
|
|
63
|
-
if (match) {
|
|
64
|
-
this.filename = match[1];
|
|
65
|
-
}
|
|
66
|
-
}
|
|
91
|
+
this.filename = parseFuncFilenameFromStack(new Error().stack);
|
|
67
92
|
} catch (_) {
|
|
68
93
|
}
|
|
69
94
|
}
|
|
95
|
+
insertPluginBeforeRunHandler(plugin) {
|
|
96
|
+
const index = this.plugins.findIndex(
|
|
97
|
+
(p) => p.type === "handler" && p.name === "handler"
|
|
98
|
+
);
|
|
99
|
+
if (index === -1) this.plugins.push(plugin);
|
|
100
|
+
else this.plugins.splice(index, 0, plugin);
|
|
101
|
+
this.cachedFunctions = /* @__PURE__ */ Object.create(null);
|
|
102
|
+
}
|
|
103
|
+
async resolvePluginConstructor(moduleName, className, pluginName) {
|
|
104
|
+
let mod;
|
|
105
|
+
try {
|
|
106
|
+
mod = await import(moduleName);
|
|
107
|
+
} catch (error) {
|
|
108
|
+
throw Error(
|
|
109
|
+
`[defineFunc] Failed to load plugin "${pluginName}" from "${moduleName}": ${error.message}`
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
const constructors = [];
|
|
113
|
+
if (className && mod[className]) constructors.push(mod[className]);
|
|
114
|
+
if (typeof mod.default === "function") constructors.push(mod.default);
|
|
115
|
+
if (mod.default && typeof mod.default === "object" && className && mod.default[className])
|
|
116
|
+
constructors.push(mod.default[className]);
|
|
117
|
+
for (const key in mod) {
|
|
118
|
+
if (key === className || key === "default") continue;
|
|
119
|
+
constructors.push(mod[key]);
|
|
120
|
+
}
|
|
121
|
+
if (mod.default && typeof mod.default === "object")
|
|
122
|
+
for (const key in mod.default) {
|
|
123
|
+
if (key === className) continue;
|
|
124
|
+
constructors.push(mod.default[key]);
|
|
125
|
+
}
|
|
126
|
+
const PluginConstructor = constructors.find(
|
|
127
|
+
(pluginConstructor) => typeof pluginConstructor === "function" && pluginConstructor.prototype && (typeof pluginConstructor.prototype.onMount === "function" || typeof pluginConstructor.prototype.onInvoke === "function")
|
|
128
|
+
);
|
|
129
|
+
if (!PluginConstructor)
|
|
130
|
+
throw Error(
|
|
131
|
+
`[defineFunc] Failed to resolve plugin class "${className}" from "${moduleName}" for plugin "${pluginName}".`
|
|
132
|
+
);
|
|
133
|
+
return PluginConstructor;
|
|
134
|
+
}
|
|
135
|
+
async loadPluginsFromConfig(config) {
|
|
136
|
+
const pluginConfigs = config.plugins || /* @__PURE__ */ Object.create(null);
|
|
137
|
+
for (const key in pluginConfigs) {
|
|
138
|
+
const rawConfig = pluginConfigs[key];
|
|
139
|
+
const configValue = rawConfig && typeof rawConfig === "object" ? Object.assign(/* @__PURE__ */ Object.create(null), rawConfig) : /* @__PURE__ */ Object.create(null);
|
|
140
|
+
const pluginName = typeof configValue.name === "string" && configValue.name.length ? configValue.name : key;
|
|
141
|
+
if (this.plugins.find((plugin2) => plugin2.name === pluginName)) continue;
|
|
142
|
+
const pluginType = typeof configValue.type === "string" && configValue.type || typeof rawConfig === "string" && rawConfig || key;
|
|
143
|
+
const moduleName = formatPluginModuleName(pluginType);
|
|
144
|
+
const className = formatPluginClassName(pluginType);
|
|
145
|
+
const PluginConstructor = await this.resolvePluginConstructor(
|
|
146
|
+
moduleName,
|
|
147
|
+
className,
|
|
148
|
+
pluginName
|
|
149
|
+
);
|
|
150
|
+
let plugin;
|
|
151
|
+
try {
|
|
152
|
+
plugin = new PluginConstructor({
|
|
153
|
+
...configValue,
|
|
154
|
+
name: pluginName,
|
|
155
|
+
type: pluginType
|
|
156
|
+
});
|
|
157
|
+
} catch (error) {
|
|
158
|
+
throw Error(
|
|
159
|
+
`[defineFunc] Failed to initialize plugin "${pluginName}" from "${moduleName}": ${error.message}`
|
|
160
|
+
);
|
|
161
|
+
}
|
|
162
|
+
if (!plugin || typeof plugin !== "object")
|
|
163
|
+
throw Error(
|
|
164
|
+
`[defineFunc] Invalid plugin instance for "${pluginName}" from "${moduleName}".`
|
|
165
|
+
);
|
|
166
|
+
this.insertPluginBeforeRunHandler(plugin);
|
|
167
|
+
}
|
|
168
|
+
this.loadedConfigPlugins = true;
|
|
169
|
+
}
|
|
70
170
|
compose(key) {
|
|
71
171
|
let list = [];
|
|
72
172
|
if (this.cachedFunctions[key]) list = this.cachedFunctions[key];
|
|
@@ -129,6 +229,8 @@ var Func = class {
|
|
|
129
229
|
return;
|
|
130
230
|
}
|
|
131
231
|
if (!data.config) data.config = this.config;
|
|
232
|
+
if (this.autoLoadPluginsFromConfig && !this.loadedConfigPlugins)
|
|
233
|
+
await this.loadPluginsFromConfig(data.config);
|
|
132
234
|
data.logger.debug(
|
|
133
235
|
`plugins: ${this.plugins.map((p) => `${p.type}#${p.name}`).join(",")}`
|
|
134
236
|
);
|
|
@@ -205,5 +307,15 @@ function useFunc(handler) {
|
|
|
205
307
|
plugins = [];
|
|
206
308
|
return func;
|
|
207
309
|
}
|
|
310
|
+
function defineFunc(handler) {
|
|
311
|
+
plugins = [];
|
|
312
|
+
const func = new Func({
|
|
313
|
+
plugins,
|
|
314
|
+
handler,
|
|
315
|
+
autoLoadPluginsFromConfig: true
|
|
316
|
+
});
|
|
317
|
+
plugins = [];
|
|
318
|
+
return func;
|
|
319
|
+
}
|
|
208
320
|
|
|
209
|
-
export { Func, nameFunc, useFunc, usePlugin };
|
|
321
|
+
export { Func, defineFunc, nameFunc, parseFuncFilenameFromStack, useFunc, usePlugin };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@faasjs/func",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "8.0.0-beta.6",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.cjs",
|
|
@@ -30,12 +30,12 @@
|
|
|
30
30
|
"dist"
|
|
31
31
|
],
|
|
32
32
|
"peerDependencies": {
|
|
33
|
-
"@faasjs/deep_merge": ">=
|
|
34
|
-
"@faasjs/logger": ">=
|
|
33
|
+
"@faasjs/deep_merge": ">=8.0.0-beta.6",
|
|
34
|
+
"@faasjs/logger": ">=8.0.0-beta.6"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
|
-
"@faasjs/deep_merge": ">=
|
|
38
|
-
"@faasjs/logger": ">=
|
|
37
|
+
"@faasjs/deep_merge": ">=8.0.0-beta.6",
|
|
38
|
+
"@faasjs/logger": ">=8.0.0-beta.6"
|
|
39
39
|
},
|
|
40
40
|
"engines": {
|
|
41
41
|
"node": ">=24.0.0",
|