UNPKG

8.21 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3const command_1 = require("@heroku-cli/command");
4const deps_1 = require("@heroku-cli/command/lib/deps");
5const git_1 = require("@heroku-cli/command/lib/git");
6const path = require("path");
7const flatten = require("lodash.flatten");
8exports.oneDay = 60 * 60 * 24;
9exports.herokuGet = async (resource, ctx) => {
10 const heroku = new command_1.APIClient(ctx.config);
11 let { body } = await heroku.get(`/${resource}`, { retryAuth: false });
12 if (typeof body === 'string')
13 body = JSON.parse(body);
14 return body.map((a) => a.name).sort();
15};
16exports.AppCompletion = {
17 cacheDuration: exports.oneDay,
18 options: async (ctx) => {
19 const teams = await exports.herokuGet('teams', ctx);
20 const apps = {
21 personal: await exports.herokuGet('users/~/apps', ctx),
22 teams: flatten(await Promise.all(teams.map((team) => exports.herokuGet(`teams/${team}/apps`, ctx)))),
23 };
24 return apps.personal.concat(apps.teams);
25 },
26};
27exports.AppAddonCompletion = {
28 cacheDuration: exports.oneDay,
29 cacheKey: async (ctx) => {
30 return ctx.flags && ctx.flags.app ? `${ctx.flags.app}_addons` : '';
31 },
32 options: async (ctx) => {
33 const addons = ctx.flags && ctx.flags.app ? await exports.herokuGet(`apps/${ctx.flags.app}/addons`, ctx) : [];
34 return addons;
35 },
36};
37exports.AppDynoCompletion = {
38 cacheDuration: exports.oneDay,
39 cacheKey: async (ctx) => {
40 return ctx.flags && ctx.flags.app ? `${ctx.flags.app}_dynos` : '';
41 },
42 options: async (ctx) => {
43 const dynos = ctx.flags && ctx.flags.app ? await exports.herokuGet(`apps/${ctx.flags.app}/dynos`, ctx) : [];
44 return dynos;
45 },
46};
47exports.BuildpackCompletion = {
48 skipCache: true,
49 options: async () => {
50 return [
51 'heroku/ruby',
52 'heroku/nodejs',
53 'heroku/clojure',
54 'heroku/python',
55 'heroku/java',
56 'heroku/gradle',
57 'heroku/scala',
58 'heroku/php',
59 'heroku/go',
60 ];
61 },
62};
63const ConfigCompletion = {
64 cacheDuration: 60 * 60 * 24 * 7,
65 cacheKey: async (ctx) => {
66 return ctx.flags && ctx.flags.app ? `${ctx.flags.app}_config_vars` : '';
67 },
68 options: async (ctx) => {
69 const heroku = new command_1.APIClient(ctx.config);
70 if (ctx.flags && ctx.flags.app) {
71 const { body: configs } = await heroku.get(`/apps/${ctx.flags.app}/config-vars`, { retryAuth: false });
72 return Object.keys(configs);
73 }
74 return [];
75 },
76};
77const ConfigSetCompletion = {
78 cacheDuration: 60 * 60 * 24 * 7,
79 cacheKey: async (ctx) => {
80 return ctx.flags && ctx.flags.app ? `${ctx.flags.app}_config_set_vars` : '';
81 },
82 options: async (ctx) => {
83 const heroku = new command_1.APIClient(ctx.config);
84 if (ctx.flags && ctx.flags.app) {
85 const { body: configs } = await heroku.get(`/apps/${ctx.flags.app}/config-vars`, { retryAuth: false });
86 return Object.keys(configs).map(k => `${k}=`);
87 }
88 return [];
89 },
90};
91exports.DynoSizeCompletion = {
92 cacheDuration: exports.oneDay * 90,
93 options: async (ctx) => {
94 let sizes = await exports.herokuGet('dyno-sizes', ctx);
95 if (sizes)
96 sizes = sizes.map(s => s.toLowerCase());
97 return sizes;
98 },
99};
100exports.FileCompletion = {
101 skipCache: true,
102 options: async () => {
103 const files = await deps_1.deps.file.readdir(process.cwd());
104 return files;
105 },
106};
107exports.PipelineCompletion = {
108 cacheDuration: exports.oneDay,
109 options: async (ctx) => {
110 const pipelines = await exports.herokuGet('pipelines', ctx);
111 return pipelines;
112 },
113};
114exports.ProcessTypeCompletion = {
115 skipCache: true,
116 options: async () => {
117 let types = [];
118 const procfile = path.join(process.cwd(), 'Procfile');
119 try {
120 const buff = await deps_1.deps.file.readFile(procfile);
121 types = buff
122 .toString()
123 .split('\n')
124 .map(s => {
125 if (!s)
126 return false;
127 const m = s.match(/^([A-Za-z0-9_-]+)/);
128 return m ? m[0] : false;
129 })
130 .filter(t => t);
131 }
132 catch (error) {
133 if (error.code !== 'ENOENT')
134 throw error;
135 }
136 return types;
137 },
138};
139exports.RegionCompletion = {
140 cacheDuration: exports.oneDay * 7,
141 options: async (ctx) => {
142 const regions = await exports.herokuGet('regions', ctx);
143 return regions;
144 },
145};
146exports.RemoteCompletion = {
147 skipCache: true,
148 options: async () => {
149 const remotes = git_1.getGitRemotes(git_1.configRemote());
150 return remotes.map(r => r.remote);
151 },
152};
153exports.RoleCompletion = {
154 skipCache: true,
155 options: async () => {
156 return ['admin', 'collaborator', 'member', 'owner'];
157 },
158};
159exports.ScopeCompletion = {
160 skipCache: true,
161 options: async () => {
162 return ['global', 'identity', 'read', 'write', 'read-protected', 'write-protected'];
163 },
164};
165exports.SpaceCompletion = {
166 cacheDuration: exports.oneDay,
167 options: async (ctx) => {
168 const spaces = await exports.herokuGet('spaces', ctx);
169 return spaces;
170 },
171};
172exports.StackCompletion = {
173 cacheDuration: exports.oneDay,
174 options: async (ctx) => {
175 const stacks = await exports.herokuGet('stacks', ctx);
176 return stacks;
177 },
178};
179exports.StageCompletion = {
180 skipCache: true,
181 options: async () => {
182 return ['test', 'review', 'development', 'staging', 'production'];
183 },
184};
185exports.TeamCompletion = {
186 cacheDuration: exports.oneDay,
187 options: async (ctx) => {
188 const teams = await exports.herokuGet('teams', ctx);
189 return teams;
190 },
191};
192exports.CompletionMapping = {
193 app: exports.AppCompletion,
194 addon: exports.AppAddonCompletion,
195 dyno: exports.AppDynoCompletion,
196 buildpack: exports.BuildpackCompletion,
197 config: ConfigCompletion,
198 configSet: ConfigSetCompletion,
199 dynosize: exports.DynoSizeCompletion,
200 pipeline: exports.PipelineCompletion,
201 processtype: exports.ProcessTypeCompletion,
202 region: exports.RegionCompletion,
203 remote: exports.RemoteCompletion,
204 role: exports.RoleCompletion,
205 scope: exports.ScopeCompletion,
206 space: exports.SpaceCompletion,
207 stack: exports.StackCompletion,
208 stage: exports.StageCompletion,
209 team: exports.TeamCompletion,
210};
211class CompletionLookup {
212 // eslint-disable-next-line no-useless-constructor
213 constructor(cmdId, name, description) {
214 this.cmdId = cmdId;
215 this.name = name;
216 this.description = description;
217 this.blocklistMap = {
218 app: ['apps:create'],
219 space: ['spaces:create'],
220 };
221 this.keyAliasMap = {
222 key: {
223 'config:get': 'config',
224 },
225 };
226 this.commandArgsMap = {
227 key: {
228 'config:set': 'configSet',
229 },
230 };
231 }
232 get key() {
233 return this.argAlias() || this.keyAlias() || this.descriptionAlias() || this.name;
234 }
235 run() {
236 if (this.blocklisted())
237 return;
238 return exports.CompletionMapping[this.key];
239 }
240 argAlias() {
241 return this.commandArgsMap[this.name] && this.commandArgsMap[this.name][this.cmdId];
242 }
243 keyAlias() {
244 return this.keyAliasMap[this.name] && this.keyAliasMap[this.name][this.cmdId];
245 }
246 descriptionAlias() {
247 const d = this.description;
248 // eslint-disable-next-line unicorn/prefer-starts-ends-with
249 if (d.match(/^dyno size/))
250 return 'dynosize';
251 // eslint-disable-next-line unicorn/prefer-starts-ends-with
252 if (d.match(/^process type/))
253 return 'processtype';
254 }
255 blocklisted() {
256 return this.blocklistMap[this.name] && this.blocklistMap[this.name].includes(this.cmdId);
257 }
258}
259exports.CompletionLookup = CompletionLookup;