UNPKG

5.38 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3const cli_ux_1 = require("cli-ux");
4const fs = require("fs");
5const loadJSON = require("load-json-file");
6const path = require("path");
7const semver = require("semver");
8const util_1 = require("./util");
9const yarn_1 = require("./yarn");
10const initPJSON = { private: true, anycli: { schema: 1, plugins: [] }, dependencies: {} };
11class Plugins {
12 constructor(config) {
13 this.config = config;
14 this.yarn = new yarn_1.default({ config, cwd: this.config.dataDir });
15 this.debug = require('debug')('@anycli/plugins');
16 }
17 async pjson() {
18 try {
19 const pjson = await loadJSON(this.pjsonPath);
20 return Object.assign({}, initPJSON, { anycli: Object.assign({}, initPJSON.anycli, pjson.anycli), dependencies: {} }, pjson);
21 }
22 catch (err) {
23 this.debug(err);
24 if (err.code !== 'ENOENT')
25 process.emitWarning(err);
26 return initPJSON;
27 }
28 }
29 async list() {
30 const pjson = await this.pjson();
31 return this.normalizePlugins(pjson.anycli.plugins);
32 }
33 async install(name, tag = 'latest') {
34 try {
35 const range = semver.validRange(tag);
36 const unfriendly = this.unfriendlyName(name);
37 if (unfriendly && await this.npmHasPackage(unfriendly)) {
38 name = unfriendly;
39 }
40 await this.createPJSON();
41 await this.yarn.exec(['add', `${name}@${tag}`]);
42 // const plugin = await this.loadPlugin(name, range || tag)
43 // if (!plugin.valid) {
44 // throw new Error('no commands found in plugin')
45 // }
46 await this.add({ name, tag: range || tag, type: 'user' });
47 }
48 catch (err) {
49 await this.uninstall(name).catch(err => this.debug(err));
50 throw err;
51 }
52 }
53 async add(plugin) {
54 const pjson = await this.pjson();
55 pjson.anycli.plugins = util_1.uniq([...pjson.anycli.plugins || [], plugin]);
56 await this.savePJSON(pjson);
57 }
58 async remove(name) {
59 const pjson = await this.pjson();
60 if (pjson.dependencies)
61 delete pjson.dependencies[name];
62 pjson.anycli.plugins = this.normalizePlugins(pjson.anycli.plugins)
63 .filter(p => p.name !== name);
64 await this.savePJSON(pjson);
65 }
66 async uninstall(name) {
67 try {
68 await this.yarn.exec(['remove', name]);
69 }
70 finally {
71 await this.remove(name);
72 }
73 }
74 async update() {
75 const plugins = await this.list();
76 if (plugins.length === 0)
77 return;
78 cli_ux_1.default.action.start(`${this.config.name}: Updating plugins`);
79 await this.yarn.exec(['add', ...plugins
80 .filter((p) => p.type === 'user')
81 .map(p => `${p.name}@${p.tag}`)
82 ]);
83 cli_ux_1.default.action.stop();
84 }
85 async hasPlugin(name) {
86 const list = await this.list();
87 return list.find(p => this.friendlyName(p.name) === this.friendlyName(name));
88 }
89 async yarnNodeVersion() {
90 try {
91 let f = await loadJSON(path.join(this.config.dataDir, 'node_modules', '.yarn-integrity'));
92 return f.nodeVersion;
93 }
94 catch (err) {
95 if (err.code !== 'ENOENT')
96 cli_ux_1.default.warn(err);
97 }
98 }
99 unfriendlyName(name) {
100 if (name.includes('@'))
101 return;
102 const scope = this.config.pjson.anycli.scope;
103 if (!scope)
104 return;
105 return `@${scope}/plugin-${name}`;
106 }
107 friendlyName(name) {
108 const scope = this.config.pjson.anycli.scope;
109 if (!scope)
110 return name;
111 const match = name.match(`@${scope}/plugin-(.+)`);
112 if (!match)
113 return name;
114 return match[1];
115 }
116 // private async loadPlugin(plugin: Config.PJSON.PluginTypes) {
117 // return Config.load({...plugin as any, root: this.config.dataDir})
118 // }
119 async createPJSON() {
120 if (!fs.existsSync(this.pjsonPath)) {
121 await this.savePJSON(initPJSON);
122 }
123 }
124 get pjsonPath() {
125 return path.join(this.config.dataDir, 'package.json');
126 }
127 async npmHasPackage(name) {
128 try {
129 const http = require('http-call').HTTP;
130 let url = `${this.config.npmRegistry}/-/package/${name.replace('/', '%2f')}/dist-tags`;
131 await http.get(url);
132 return true;
133 }
134 catch (err) {
135 this.debug(err);
136 return false;
137 }
138 }
139 async savePJSON(pjson) {
140 pjson.anycli.plugins = this.normalizePlugins(pjson.anycli.plugins);
141 const fs = require('fs-extra');
142 await fs.outputJSON(this.pjsonPath, pjson, { spaces: 2 });
143 }
144 normalizePlugins(input) {
145 let plugins = (input || []).map(p => {
146 if (typeof p === 'string') {
147 return { name: p, type: 'user', tag: 'latest' };
148 }
149 else
150 return p;
151 });
152 plugins = util_1.uniqWith(plugins, (a, b) => a.name === b.name || (a.type === 'link' && b.type === 'link' && a.root === b.root));
153 return plugins;
154 }
155}
156exports.default = Plugins;