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

Commit 5ef5230

Browse files
authored
implement basic netlify functions:list command (#211)
* implement basic netlify functions:list command * add check against deployment * note and check functions folder source
1 parent ff8ea5d commit 5ef5230

File tree

3 files changed

+120
-53
lines changed

3 files changed

+120
-53
lines changed

src/commands/functions/list.js

Lines changed: 84 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,98 @@
1-
const { Command, flags } = require("@oclif/command");
1+
const chalk = require("chalk");
2+
const Command = require("@netlify/cli-utils");
3+
const { flags } = require("@oclif/command");
24
const AsciiTable = require("ascii-table");
3-
5+
const { getFunctions } = require("../../utils/get-functions");
46
class FunctionsListCommand extends Command {
57
async run() {
6-
var table = new AsciiTable("Netlify Functions");
7-
table
8-
.setHeading("Name", "Url", "Type", "id")
9-
.addRow(
10-
"function-abc",
11-
"site.com/.netlify/function-abc",
12-
"http GET",
13-
"124123-ddhshs1212-1211"
14-
)
15-
.addRow(
16-
"send-email-function",
17-
"site.com/.netlify/send-email-function",
18-
"http POST",
19-
"x3123-22345-1211"
20-
)
21-
.addRow(
22-
"lol-function-cool",
23-
"site.com/.netlify/lol-function-cool",
24-
"scheduled",
25-
"weyhfd-hjjk-67533"
8+
let { flags } = this.parse(FunctionsListCommand);
9+
const { api, site, config } = this.netlify;
10+
11+
// get deployed site details
12+
// copied from `netlify status`
13+
const siteId = site.id;
14+
if (!siteId) {
15+
this.warn("Did you run `netlify link` yet?");
16+
this.error(`You don't appear to be in a folder that is linked to a site`);
17+
}
18+
let siteData;
19+
try {
20+
siteData = await api.getSite({ siteId });
21+
} catch (e) {
22+
if (e.status === 401 /* unauthorized*/) {
23+
this.warn(
24+
`Log in with a different account or re-link to a site you have permission for`
25+
);
26+
this.error(
27+
`Not authorized to view the currently linked site (${siteId})`
28+
);
29+
}
30+
if (e.status === 404 /* missing */) {
31+
this.error(`The site this folder is linked to can't be found`);
32+
}
33+
this.error(e);
34+
}
35+
const deploy = siteData.published_deploy || {};
36+
const deployed_functions = deploy.available_functions || [];
37+
38+
const functionsDir =
39+
flags.functions ||
40+
(config.dev && config.dev.functions) ||
41+
(config.build && config.build.functions);
42+
if (typeof functionsDir === "undefined") {
43+
this.error(
44+
"functions directory is undefined, did you forget to set it in netlify.toml?"
45+
);
46+
process.exit(1);
47+
}
48+
var table = new AsciiTable(
49+
`Netlify Functions (based on local functions folder "${functionsDir}")`
50+
);
51+
const functions = getFunctions(functionsDir);
52+
53+
table.setHeading("Name", "Url", "moduleDir", "deployed");
54+
Object.entries(functions).forEach(([functionName, { moduleDir }]) => {
55+
const isDeployed = deployed_functions
56+
.map(({ n }) => n)
57+
.includes(functionName);
58+
59+
// this.log(`${chalk.yellow("function name")}: ${functionName}`);
60+
// this.log(
61+
// ` ${chalk.yellow(
62+
// "url"
63+
// )}: ${`/.netlify/functions/${functionName}`}`
64+
// );
65+
// this.log(` ${chalk.yellow("moduleDir")}: ${moduleDir}`);
66+
// this.log(
67+
// ` ${chalk.yellow("deployed")}: ${
68+
// isDeployed ? chalk.green("yes") : chalk.yellow("no")
69+
// }`
70+
// );
71+
// this.log("----------");
72+
table.addRow(
73+
functionName,
74+
`/.netlify/functions/${functionName}`,
75+
moduleDir,
76+
isDeployed ? "yes" : "no"
2677
);
27-
this.log(`netlify functions:list NOT IMPLEMENTED YET`);
78+
});
2879
this.log(table.toString());
2980
}
3081
}
3182

32-
FunctionsListCommand.description = `list sites
33-
...
34-
Extra documentation goes here
83+
FunctionsListCommand.description = `list functions that exist locally
84+
85+
Helpful for making sure that you have formatted your functions correctly
86+
87+
NOT the same as listing the functions that have been deployed. For that info you need to go to your Netlify deploy log.
3588
`;
3689
FunctionsListCommand.aliases = ["function:list"];
3790
FunctionsListCommand.flags = {
38-
name: flags.string({ char: "n", description: "name to print" })
91+
name: flags.string({ char: "n", description: "name to print" }),
92+
functions: flags.string({
93+
char: "f",
94+
description: "Specify a functions folder to serve"
95+
})
3996
};
4097

4198
// TODO make visible once implementation complete

src/utils/get-functions.js

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
const fs = require("fs");
2+
const path = require("path");
3+
const { findModuleDir, findHandler } = require("./finders");
4+
5+
module.exports = {
6+
getFunctions(dir) {
7+
const functions = {};
8+
if (fs.existsSync(dir)) {
9+
fs.readdirSync(dir).forEach(file => {
10+
if (dir === "node_modules") {
11+
return;
12+
}
13+
const functionPath = path.resolve(path.join(dir, file));
14+
const handlerPath = findHandler(functionPath);
15+
if (!handlerPath) {
16+
return;
17+
}
18+
if (path.extname(functionPath) === ".js") {
19+
functions[file.replace(/\.js$/, "")] = {
20+
functionPath,
21+
moduleDir: findModuleDir(functionPath)
22+
};
23+
} else if (fs.lstatSync(functionPath).isDirectory()) {
24+
functions[file] = {
25+
functionPath: handlerPath,
26+
moduleDir: findModuleDir(functionPath)
27+
};
28+
}
29+
});
30+
}
31+
return functions;
32+
}
33+
};

src/utils/serve-functions.js

Lines changed: 3 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,7 @@ const {
1313
// NETLIFYDEVWARN,
1414
NETLIFYDEVERR
1515
} = require("netlify-cli-logo");
16-
17-
const { findModuleDir, findHandler } = require("./finders");
16+
const { getFunctions } = require("./get-functions");
1817

1918
const defaultPort = 34567;
2019

@@ -55,30 +54,7 @@ function buildClientContext(headers) {
5554
}
5655

5756
function createHandler(dir) {
58-
const functions = {};
59-
if (fs.existsSync(dir)) {
60-
fs.readdirSync(dir).forEach(file => {
61-
if (dir === "node_modules") {
62-
return;
63-
}
64-
const functionPath = path.resolve(path.join(dir, file));
65-
const handlerPath = findHandler(functionPath);
66-
if (!handlerPath) {
67-
return;
68-
}
69-
if (path.extname(functionPath) === ".js") {
70-
functions[file.replace(/\.js$/, "")] = {
71-
functionPath,
72-
moduleDir: findModuleDir(functionPath)
73-
};
74-
} else if (fs.lstatSync(functionPath).isDirectory()) {
75-
functions[file] = {
76-
functionPath: handlerPath,
77-
moduleDir: findModuleDir(functionPath)
78-
};
79-
}
80-
});
81-
}
57+
const functions = getFunctions(dir);
8258

8359
const clearCache = action => path => {
8460
console.log(`${NETLIFYDEVLOG} ${path} ${action}, reloading...`); // eslint-disable-line no-console
@@ -144,6 +120,7 @@ function createHandler(dir) {
144120

145121
let callbackWasCalled = false;
146122
const callback = createCallback(response);
123+
// we already checked that it exports a function named handler above
147124
const promise = handler.handler(
148125
lambdaRequest,
149126
{ clientContext: buildClientContext(request.headers) || {} },

0 commit comments

Comments
 (0)