UNPKG

10.5 kBJavaScriptView Raw
1/* eslint no-console: 0 */
2const { getAddons, createAddon } = require('netlify/src/addons')
3// const chalk = require("chalk");
4// const fetch = require("node-fetch");
5
6/** main section - shamelessly adapted from CLI. we can extract and dedupe later. */
7/** but we can DRY things up later. */
8// eslint-disable-next-line max-params
9module.exports.createSiteAddon = async function(accessToken, addonName, siteId, siteData, log) {
10 const addons = await getAddons(siteId, accessToken)
11 if (typeof addons === 'object' && addons.error) {
12 log('API Error', addons)
13 return false
14 }
15 // Filter down addons to current args.name
16 const currentAddon = addons.find(addon => addon.service_path === `/.netlify/${addonName}`)
17 const rawFlags = {}
18
19 if (currentAddon && currentAddon.id) {
20 log(`The "${addonName} add-on" already exists for ${siteData.name}`)
21 // // just exit
22 // log()
23 // const cmd = chalk.cyan(`\`netlify addons:config ${addonName}\``)
24 // log(`- To update this add-on run: ${cmd}`)
25 // const deleteCmd = chalk.cyan(`\`netlify addons:delete ${addonName}\``)
26 // log(`- To remove this add-on run: ${deleteCmd}`)
27 // log()
28 return false
29 }
30
31 // const manifest = await getAddonManifest(addonName, accessToken);
32
33 let configValues = rawFlags
34 // if (manifest.config) {
35 // const required = requiredConfigValues(manifest.config);
36 // console.log(`Starting the setup for "${addonName} add-on"`);
37 // console.log();
38
39 // // const missingValues = missingConfigValues(required, rawFlags);
40 // // if (Object.keys(rawFlags).length) {
41 // // const newConfig = updateConfigValues(manifest.config, {}, rawFlags)
42
43 // // if (missingValues.length) {
44 // // /* Warn user of missing required values */
45 // // console.log(
46 // // `${chalk.redBright.underline.bold(`Error: Missing required configuration for "${addonName} add-on"`)}`
47 // // )
48 // // console.log()
49 // // render.missingValues(missingValues, manifest)
50 // // console.log()
51 // // const msg = `netlify addons:create ${addonName}`
52 // // console.log(`Please supply the configuration values as CLI flags`)
53 // // console.log()
54 // // console.log(`Alternatively, you can run ${chalk.cyan(msg)} with no flags to walk through the setup steps`)
55 // // console.log()
56 // // return false
57 // // }
58
59 // // await createSiteAddon({
60 // // addonName,
61 // // settings: {
62 // // siteId: siteId,
63 // // addon: addonName,
64 // // config: newConfig
65 // // },
66 // // accessToken,
67 // // siteData
68 // // })
69 // // return false
70 // // }
71
72 // const words = `The ${addonName} add-on has the following configurable options:`;
73 // console.log(` ${chalk.yellowBright.bold(words)}`);
74 // render.configValues(addonName, manifest.config);
75 // console.log();
76 // console.log(` ${chalk.greenBright.bold("Lets configure those!")}`);
77
78 // console.log();
79 // console.log(
80 // ` - Hit ${chalk.white.bold("enter")} to confirm value or set empty value`
81 // );
82 // console.log(
83 // ` - Hit ${chalk.white.bold("ctrl + C")} to cancel & exit configuration`
84 // );
85 // console.log();
86
87 // const prompts = generatePrompts({
88 // config: manifest.config,
89 // configValues: rawFlags
90 // });
91
92 // const userInput = await inquirer.prompt(prompts);
93 // // Merge user input with the flags specified
94 // configValues = updateConfigValues(manifest.config, rawFlags, userInput);
95 // const missingRequiredValues = missingConfigValues(required, configValues);
96 // if (missingRequiredValues && missingRequiredValues.length) {
97 // missingRequiredValues.forEach(val => {
98 // console.log(
99 // `Missing required value "${val}". Please run the command again`
100 // );
101 // });
102 // return false;
103 // }
104 // }
105
106 await actuallyCreateSiteAddon({
107 addonName,
108 settings: {
109 siteId: siteId,
110 addon: addonName,
111 config: configValues
112 },
113 accessToken,
114 siteData
115 })
116 return addonName // we dont really use this right now but may be helpful to know that an addon installation was successful
117}
118
119async function actuallyCreateSiteAddon({ addonName, settings, accessToken, siteData }) {
120 const addonResponse = await createAddon(settings, accessToken)
121
122 if (addonResponse.code === 404) {
123 console.log(`No add-on "${addonName}" found. Please double check your add-on name and try again`)
124 return false
125 }
126 console.log(`Add-on "${addonName}" created for ${siteData.name}`)
127 if (addonResponse.config && addonResponse.config.message) {
128 console.log()
129 console.log(`${addonResponse.config.message}`)
130 }
131 return addonResponse
132}
133
134/** all the utils used in the main section */
135
136// async function getAddonManifest(addonName, netlifyApiToken) {
137// const url = `https://api.netlify.com/api/v1/services/${addonName}/manifest`;
138// const response = await fetch(url, {
139// method: "GET",
140// headers: {
141// "Content-Type": "application/json",
142// Authorization: `Bearer ${netlifyApiToken}`
143// }
144// });
145
146// const data = await response.json();
147
148// if (response.status === 422) {
149// throw new Error(`Error ${JSON.stringify(data)}`);
150// }
151
152// return data;
153// }
154
155// function requiredConfigValues(config) {
156// return Object.keys(config).filter(key => {
157// return config[key].required;
158// });
159// }
160
161// function missingConfigValues(requiredConfig, providedConfig) {
162// return requiredConfig.filter(key => {
163// return !providedConfig[key];
164// });
165// }
166
167// function missingConfigValues(allowedConfig, currentConfig, newConfig) {
168// return Object.keys(allowedConfig).reduce((acc, key) => {
169// if (newConfig[key]) {
170// acc[key] = newConfig[key];
171// return acc;
172// }
173// acc[key] = currentConfig[key];
174// return acc;
175// }, {});
176// }
177
178// const chalk = require('chalk')
179
180// /* programmatically generate CLI prompts */
181// function generatePrompts(settings) {
182// const { config, configValues } = settings;
183// const configItems = Object.keys(config);
184
185// const prompts = configItems
186// .map((key, i) => {
187// const setting = config[key];
188// // const { type, displayName } = setting
189// let prompt;
190// // Tell user to use types
191// if (!setting.type) {
192// console.log(
193// `⚠️ ${chalk.yellowBright(
194// `Warning: no \`type\` is set for config key: ${configItems[i]}`
195// )}`
196// );
197// console.log(
198// `It's highly recommended that you type your configuration values. It will help with automatic documentation, sharing of your services, and make your services configurable through a GUI`
199// );
200// console.log("");
201// }
202
203// // Handle shorthand config. Probably will be removed. Severly limited + not great UX
204// if (typeof setting === "string" || typeof setting === "boolean") {
205// if (typeof setting === "string") {
206// prompt = {
207// type: "input",
208// name: key,
209// message: `Enter string value for '${key}':`
210// };
211// // if current stage value set show as default
212// if (configValues[key]) {
213// prompt.default = configValues[key];
214// }
215// } else if (typeof setting === "boolean") {
216// prompt = {
217// type: "confirm",
218// name: key,
219// message: `Do you want '${key}':`
220// };
221// }
222// return prompt;
223// }
224
225// // For future use. Once UX is decided
226// // const defaultValidation = (setting.required) ? validateRequired : noValidate
227// const defaultValidation = noValidate;
228// const validateFunction = setting.pattern
229// ? validate(setting.pattern)
230// : defaultValidation;
231// const isRequiredText = setting.required
232// ? ` (${chalk.yellow("required")})`
233// : "";
234// if (setting.type === "string" || setting.type.match(/string/)) {
235// prompt = {
236// type: "input",
237// name: key,
238// message:
239// `${chalk.white(key)}${isRequiredText} - ${setting.displayName}` ||
240// `Please enter value for ${key}`,
241// validate: validateFunction
242// };
243// // if value previously set show it
244// if (configValues[key]) {
245// prompt.default = configValues[key];
246// // else show default value if provided
247// } else if (setting.default) {
248// prompt.default = setting.default;
249// }
250// return prompt;
251// }
252// return undefined;
253// })
254// .filter(item => {
255// return typeof item !== "undefined";
256// });
257// return prompts;
258// }
259
260// function noValidate() {
261// return true;
262// }
263
264// function validate(pattern) {
265// return function(value) {
266// const regex = new RegExp(pattern);
267// if (value.match(regex)) {
268// return true;
269// }
270// return `Please enter a value matching regex pattern: /${chalk.yellowBright(
271// pattern
272// )}/`;
273// };
274// }
275
276// const chalk = require('chalk')
277// const AsciiTable = require("ascii-table");
278
279// function missingValues(values, manifest) {
280// const display = values
281// .map(item => {
282// const itemDisplay = chalk.redBright.bold(`${item}`);
283// const niceNameDisplay = manifest.config[item].displayName;
284// return ` - ${itemDisplay} ${niceNameDisplay}`;
285// })
286// .join("\n");
287// console.log(display);
288// }
289
290// function configValues(addonName, configValues, currentValue) {
291// const table = new AsciiTable(`${addonName} add-on settings`);
292
293// const tableHeader = currentValue
294// ? ["Setting Name", "Current Value", "Description"]
295// : ["Setting Name", "Description", "Type", "Required"];
296
297// table.setHeading(...tableHeader);
298
299// Object.keys(configValues).map(key => {
300// const { type, displayName, required } = configValues[key];
301// let requiredText = required ? `true` : `false`;
302// const typeInfo = type || "";
303// const description = displayName || "";
304// if (currentValue) {
305// const value = currentValue[key] || "Not supplied";
306// table.addRow(key, value, description);
307// } else {
308// table.addRow(key, description, typeInfo, requiredText);
309// }
310// });
311// console.log(table.toString());
312// }