1 | "use strict";
|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
3 | const cli_ux_1 = require("cli-ux");
|
4 | const fs = require("fs");
|
5 | const loadJSON = require("load-json-file");
|
6 | const path = require("path");
|
7 | const semver = require("semver");
|
8 | const util_1 = require("./util");
|
9 | const yarn_1 = require("./yarn");
|
10 | const initPJSON = { private: true, anycli: { schema: 1, plugins: [] }, dependencies: {} };
|
11 | class 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 |
|
43 |
|
44 |
|
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 |
|
117 |
|
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 | }
|
156 | exports.default = Plugins;
|