UNPKG

3.4 kBPlain TextView Raw
1import path from 'path';
2import { parseYaml } from '../../shared/yaml';
3import { Plugin } from '../universal-pkg/schema/plugin';
4import { UniversalPkg } from '../universal-pkg/dep/pkg';
5import {
6 UNIVERSAL_MODULES,
7 UNIVERSAL_PLUGIN_CONFIG,
8 FEFLOW_BIN,
9 FEF_ENV_PLUGIN_PATH,
10 SILENT_ARG,
11 DISABLE_ARG
12} from '../../shared/constant';
13import Binp from '../universal-pkg/binp';
14import Commander from '../commander';
15import { CommandPickConfig, COMMAND_TYPE } from '../command-picker';
16import { escape } from '../../shared/args';
17
18const toolRegex = /^feflow-(?:devkit|plugin)-(.*)/i;
19
20const excludeAgrs = [DISABLE_ARG, SILENT_ARG];
21
22export function loadPlugin(
23 ctx: any,
24 pkg: string,
25 version: string
26): Plugin {
27 const pluginPath = path.join(
28 ctx.root,
29 UNIVERSAL_MODULES,
30 `${pkg}@${version}`
31 );
32 const pluginConfigPath = path.join(pluginPath, UNIVERSAL_PLUGIN_CONFIG);
33 const config = parseYaml(pluginConfigPath) || {};
34 return new Plugin(ctx, pluginPath, config);
35}
36
37function register(ctx: any, pkg: string, version: string, global = false) {
38 const commander: Commander = ctx.commander;
39 const pluginCommand = (toolRegex.exec(pkg) || [])[1] || pkg;
40 if (!pluginCommand) {
41 ctx.logger.debug(`invalid universal plugin name: ${pluginCommand}`);
42 return;
43 }
44 if (global) {
45 // load plugin.yml delay
46 commander.register(pluginCommand, () => {
47 return loadPlugin(ctx, pkg, version).desc || `${pkg} universal plugin description`;
48 }, async () => {
49 await execPlugin(ctx, pkg, version);
50 }, [() => {
51 let plugin = loadPlugin(ctx, pkg, version);
52 return plugin.usage ? {
53 type: "usage",
54 content: plugin.usage
55 } : {
56 type: "path",
57 content: plugin.path
58 }
59 }], pkg);
60 } else {
61 commander.registerInvisible(`${pluginCommand}@${version}`, async () => {
62 await execPlugin(ctx, pkg, version);
63 }, [], `${pkg}@${version}`);
64 }
65}
66
67export async function execPlugin(
68 ctx: any,
69 pkg: string,
70 version: string
71) {
72 const pluginPath = path.join(
73 ctx.root,
74 UNIVERSAL_MODULES,
75 `${pkg}@${version}`
76 );
77 let plugin = loadPlugin(ctx, pkg, version);
78 // make it find dependencies
79 new Binp().register(path.join(pluginPath, `.${FEFLOW_BIN}`), true, true);
80 // injection plugin path into the env
81 process.env[FEF_ENV_PLUGIN_PATH] = pluginPath;
82 plugin.preRun.run();
83 const args = process.argv.slice(3).filter(arg => {
84 if (excludeAgrs.includes(arg)) {
85 return false;
86 }
87 return true;
88 }).map(arg => escape(arg));
89 plugin.command.run(...args);
90 plugin.postRun.runLess();
91}
92
93export default async function loadUniversalPlugin(ctx: any): Promise<any> {
94 const universalPkg: UniversalPkg = ctx.universalPkg;
95 const pickConfig = new CommandPickConfig(ctx);
96
97 const installed = universalPkg.getInstalled();
98 for (const [pkg, version] of installed) {
99 pickConfig.registSubCommand(COMMAND_TYPE.UNIVERSAL_PLUGIN_TYPE, ctx.commander.store, pkg, version);
100 register(ctx, pkg, version, true);
101 }
102
103 const dependencies = universalPkg.getAllDependencies();
104 for (const [pkg, versionRelations] of dependencies) {
105 for (const [version] of versionRelations) {
106 register(ctx, pkg, version, false);
107 }
108 }
109
110 pickConfig.registSubCommand(COMMAND_TYPE.UNIVERSAL_PLUGIN_TYPE, ctx.commander.store);
111 pickConfig.updateCache(COMMAND_TYPE.UNIVERSAL_PLUGIN_TYPE);
112}