Skip to content
This repository was archived by the owner on Sep 12, 2019. It is now read-only.

Commit 92b9ea4

Browse files
authored
Merge pull request #88 from netlify/injectEnvVarsEverywhere
inject env vars everywhere
2 parents fcc03ea + a2e8969 commit 92b9ea4

File tree

7 files changed

+131
-99
lines changed

7 files changed

+131
-99
lines changed

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -132,11 +132,11 @@ Function templates can specify `addons` that they rely on as well as execute arb
132132
```js
133133
// .netlify-function-template.js
134134
module.exports = {
135-
addons: ['fauna'],
135+
addons: ["fauna"],
136136
onComplete() {
137-
console.log(`custom-template function created from template!`)
137+
console.log(`custom-template function created from template!`);
138138
}
139-
}
139+
};
140140
```
141141
142142
#### Executing Netlify Functions

src/commands/dev/exec.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@ const { track } = require("@netlify/cli-utils/src/utils/telemetry");
44

55
class ExecCommand extends Command {
66
async run() {
7-
const { site } = this.netlify;
7+
const { site, api } = this.netlify;
88
if (site.id) {
99
const accessToken = await this.authenticate();
10-
const { addEnvVarsFromAddons } = require("../../utils/dev-exec");
11-
await addEnvVarsFromAddons(site, accessToken);
10+
const { addEnvVariables } = require("../../utils/dev");
11+
await addEnvVariables(api, site, accessToken);
1212
}
1313
execa(this.argv[0], this.argv.slice(1), {
1414
env: process.env,

src/commands/dev/index.js

Lines changed: 47 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ const Command = require("@netlify/cli-utils");
1010
const { getAddons } = require("netlify/src/addons");
1111
const { track } = require("@netlify/cli-utils/src/utils/telemetry");
1212
const chalk = require("chalk");
13+
const NETLIFYDEV = `[${chalk.cyan("Netlify Dev")}]`;
1314
const boxen = require("boxen");
1415
const { createTunnel, connectTunnel } = require("../../live-tunnel");
1516

@@ -24,58 +25,62 @@ function addonUrl(addonUrls, req) {
2425
}
2526

2627
// Used as an optimization to avoid dual lookups for missing assets
27-
const assetExtensionRegExp = /\.(html?|png|jpg|js|css|svg|gif|ico|woff|woff2)$/
28+
const assetExtensionRegExp = /\.(html?|png|jpg|js|css|svg|gif|ico|woff|woff2)$/;
2829

2930
function alternativePathsFor(url) {
30-
const paths = []
31-
if (url[url.length - 1] === '/') {
32-
const end = url.length - 1
33-
if (url !== '/') {
34-
paths.push(url.slice(0, end) + '.html')
35-
paths.push(url.slice(0, end) + '.htm')
31+
const paths = [];
32+
if (url[url.length - 1] === "/") {
33+
const end = url.length - 1;
34+
if (url !== "/") {
35+
paths.push(url.slice(0, end) + ".html");
36+
paths.push(url.slice(0, end) + ".htm");
3637
}
37-
paths.push(url + 'index.html')
38-
paths.push(url + 'index.htm')
38+
paths.push(url + "index.html");
39+
paths.push(url + "index.htm");
3940
} else if (!url.match(assetExtensionRegExp)) {
40-
paths.push(url + '.html')
41-
paths.push(url + '.htm')
42-
paths.push(url + '/index.html')
43-
paths.push(url + '/index.htm')
41+
paths.push(url + ".html");
42+
paths.push(url + ".htm");
43+
paths.push(url + "/index.html");
44+
paths.push(url + "/index.htm");
4445
}
4546

46-
return paths
47+
return paths;
4748
}
4849

4950
function initializeProxy(port) {
5051
const proxy = httpProxy.createProxyServer({
5152
selfHandleResponse: true,
5253
target: {
53-
host: 'localhost',
54+
host: "localhost",
5455
port: port
5556
}
56-
})
57+
});
5758

58-
proxy.on('proxyRes', (proxyRes, req, res) => {
59-
if (proxyRes.statusCode === 404 && req.alternativePaths && req.alternativePaths.length) {
60-
req.url = req.alternativePaths.shift()
61-
return proxy.web(req, res, req.proxyOptions)
59+
proxy.on("proxyRes", (proxyRes, req, res) => {
60+
if (
61+
proxyRes.statusCode === 404 &&
62+
req.alternativePaths &&
63+
req.alternativePaths.length
64+
) {
65+
req.url = req.alternativePaths.shift();
66+
return proxy.web(req, res, req.proxyOptions);
6267
}
63-
res.writeHead(proxyRes.statusCode, proxyRes.headers)
64-
proxyRes.on('data', function(data) {
65-
res.write(data)
66-
})
67-
proxyRes.on('end', function() {
68-
res.end()
69-
})
70-
})
68+
res.writeHead(proxyRes.statusCode, proxyRes.headers);
69+
proxyRes.on("data", function(data) {
70+
res.write(data);
71+
});
72+
proxyRes.on("end", function() {
73+
res.end();
74+
});
75+
});
7176

7277
return {
7378
web: (req, res, options) => {
74-
req.proxyOptions = options
75-
req.alternativePaths = alternativePathsFor(req.url)
76-
return proxy.web(req, res, options)
79+
req.proxyOptions = options;
80+
req.alternativePaths = alternativePathsFor(req.url);
81+
return proxy.web(req, res, options);
7782
}
78-
}
83+
};
7984
}
8085

8186
async function startProxy(settings, addonUrls) {
@@ -134,7 +139,7 @@ function startDevServer(settings, log, error) {
134139
const StaticServer = require("static-server");
135140
if (!settings.dist) {
136141
log(
137-
"Unable to determine public folder for the dev server.\nSetup a netlify.toml file with a [dev] section to specify your dev server settings."
142+
`${NETLIFYDEV} Unable to determine public folder for the dev server. \n Setup a netlify.toml file with a [dev] section to specify your dev server settings.`
138143
);
139144
process.exit(1);
140145
}
@@ -149,10 +154,10 @@ function startDevServer(settings, log, error) {
149154
});
150155

151156
server.start(function() {
152-
log("Server listening to", settings.proxyPort);
157+
log(`${NETLIFYDEV} Server listening to`, settings.proxyPort);
153158
});
154159
} else {
155-
log(`Starting netlify dev with ${settings.type}`);
160+
log(`${NETLIFYDEV} Starting Netlify Dev with ${settings.type}`);
156161
const ps = execa(settings.command, settings.args, {
157162
env: settings.env,
158163
stdio: "inherit"
@@ -171,39 +176,21 @@ class DevCommand extends Command {
171176
flags.functions ||
172177
(config.dev && config.dev.functions) ||
173178
(config.build && config.build.functions);
174-
const addonUrls = {};
179+
let addonUrls = {};
175180

176181
let accessToken = api.accessToken;
177182
if (site.id && !flags.offline) {
178183
accessToken = await this.authenticate();
179-
const addons = await getAddons(site.id, accessToken);
180-
if (Array.isArray(addons)) {
181-
addons.forEach(addon => {
182-
addonUrls[addon.slug] = `${addon.config.site_url}/.netlify/${
183-
addon.slug
184-
}`;
185-
for (const key in addon.env) {
186-
process.env[key] = process.env[key] || addon.env[key];
187-
}
188-
});
189-
}
190-
const api = this.netlify.api;
191-
const apiSite = await api.getSite({ site_id: site.id });
192-
// TODO: We should move the environment outside of build settings and possibly have a
193-
// `/api/v1/sites/:site_id/environment` endpoint for it that we can also gate access to
194-
// In the future and that we could make context dependend
195-
if (apiSite.build_settings && apiSite.build_settings.env) {
196-
for (const key in apiSite.build_settings.env) {
197-
process.env[key] =
198-
process.env[key] || apiSite.build_settings.env[key];
199-
}
200-
}
184+
const { addEnvVariables } = require("../../utils/dev");
185+
addonUrls = await addEnvVariables(api, site, accessToken);
201186
}
202187
process.env.NETLIFY_DEV = "true";
203188

204189
let settings = serverSettings(config.dev);
205190
if (!(settings && settings.command)) {
206-
this.log("No dev server detected, using simple static server");
191+
this.log(
192+
"[Netlify Dev] No dev server detected, using simple static server"
193+
);
207194
const dist =
208195
(config.dev && config.dev.publish) ||
209196
(config.build && config.build.publish);
@@ -253,7 +240,7 @@ class DevCommand extends Command {
253240
live: flags.live || false
254241
});
255242

256-
const banner = chalk.bold(`Netlify dev server is now ready on ${url}`);
243+
const banner = chalk.bold(`Netlify Dev Server now ready on ${url}`);
257244
this.log(
258245
boxen(banner, {
259246
padding: 1,

src/commands/functions/create.js

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -395,10 +395,8 @@ async function installAddons(addons = [], fnPath) {
395395
if (addonCreateMsg) {
396396
// spinner.success("installed addon: " + addonName);
397397
if (addonDidInstall) {
398-
const {
399-
addEnvVarsFromAddons
400-
} = require("../../utils/dev-exec");
401-
await addEnvVarsFromAddons(site, accessToken);
398+
const { addEnvVariables } = require("../../utils/dev");
399+
await addEnvVariables(api, site, accessToken);
402400
const { confirmPostInstall } = await inquirer.prompt([
403401
{
404402
type: "confirm",

src/detect-server.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
const path = require("path");
2+
const chalk = require("chalk");
3+
const NETLIFYDEV = `[${chalk.cyan("Netlify Dev")}]`;
4+
25
const detectors = require("fs")
36
.readdirSync(path.join(__dirname, "detectors"))
47
.filter(x => x.endsWith(".js")) // only accept .js detector files
@@ -39,7 +42,7 @@ function assignLoudly(settings, settingsField, newValue) {
3942
if (settings[settingsField] !== newValue) {
4043
// silent if command is exactly same
4144
console.log(
42-
`Overriding ${settingsField} with setting derived from netlify.toml [dev] block: `,
45+
`${NETLIFYDEV} Overriding ${settingsField} with setting derived from netlify.toml [dev] block: `,
4346
newValue
4447
);
4548
settings[settingsField] === newValue;

src/utils/dev-exec.js

Lines changed: 0 additions & 28 deletions
This file was deleted.

src/utils/dev.js

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
// reusable code for netlify dev
2+
// bit of a hasty abstraction but recommended by oclif
3+
const { getAddons } = require("netlify/src/addons");
4+
const chalk = require("chalk");
5+
const NETLIFYDEV = `[${chalk.cyan("Netlify Dev")}]`;
6+
/**
7+
* inject environment variables from netlify addons and buildbot
8+
* into your local dev process.env
9+
*
10+
* ```
11+
* // usage example
12+
* const { site } = this.netlify
13+
* if (site.id) {
14+
* const accessToken = await this.authenticate()
15+
* const addonUrls = await addEnvVariables(site, accessToken)
16+
* // addonUrls is only for startProxy in netlify dev:index
17+
* }
18+
* ```
19+
*/
20+
async function addEnvVariables(api, site, accessToken) {
21+
/** from addons */
22+
const addonUrls = {};
23+
const addons = await getAddons(site.id, accessToken);
24+
if (Array.isArray(addons)) {
25+
addons.forEach(addon => {
26+
addonUrls[addon.slug] = `${addon.config.site_url}/.netlify/${addon.slug}`;
27+
for (const key in addon.env) {
28+
const msg = () =>
29+
console.log(`${NETLIFYDEV} Injected addon env var: `, key);
30+
process.env[key] = assignLoudly(process.env[key], addon.env[key], msg);
31+
}
32+
});
33+
}
34+
35+
/** from web UI */
36+
const apiSite = await api.getSite({ site_id: site.id });
37+
// TODO: We should move the environment outside of build settings and possibly have a
38+
// `/api/v1/sites/:site_id/environment` endpoint for it that we can also gate access to
39+
// In the future and that we could make context dependend
40+
if (apiSite.build_settings && apiSite.build_settings.env) {
41+
for (const key in apiSite.build_settings.env) {
42+
const msg = () =>
43+
console.log(`${NETLIFYDEV} Injected build setting env var: `, key);
44+
process.env[key] = assignLoudly(
45+
process.env[key],
46+
apiSite.build_settings.env[key],
47+
msg
48+
);
49+
}
50+
}
51+
52+
return addonUrls;
53+
}
54+
55+
module.exports = {
56+
addEnvVariables
57+
};
58+
59+
// if first arg is undefined, use default, but tell user about it in case it is unintentional
60+
function assignLoudly(
61+
optionalValue,
62+
defaultValue,
63+
tellUser = dV => console.log(`No value specified, using fallback of `, dV)
64+
) {
65+
if (defaultValue === undefined) throw new Error("must have a defaultValue");
66+
if (defaultValue !== optionalValue && optionalValue === undefined) {
67+
tellUser(defaultValue);
68+
return defaultValue;
69+
} else {
70+
return optionalValue;
71+
}
72+
}

0 commit comments

Comments
 (0)