UNPKG

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