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