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

implement basic netlify functions:list command #211

Merged
merged 5 commits into from
Jul 8, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
111 changes: 84 additions & 27 deletions src/commands/functions/list.js
Original file line number Diff line number Diff line change
@@ -1,41 +1,98 @@
const { Command, flags } = require("@oclif/command");
const chalk = require("chalk");
const Command = require("@netlify/cli-utils");
const { flags } = require("@oclif/command");
const AsciiTable = require("ascii-table");

const { getFunctions } = require("../../utils/get-functions");
class FunctionsListCommand extends Command {
async run() {
var table = new AsciiTable("Netlify Functions");
table
.setHeading("Name", "Url", "Type", "id")
.addRow(
"function-abc",
"site.com/.netlify/function-abc",
"http GET",
"124123-ddhshs1212-1211"
)
.addRow(
"send-email-function",
"site.com/.netlify/send-email-function",
"http POST",
"x3123-22345-1211"
)
.addRow(
"lol-function-cool",
"site.com/.netlify/lol-function-cool",
"scheduled",
"weyhfd-hjjk-67533"
let { flags } = this.parse(FunctionsListCommand);
const { api, site, config } = this.netlify;

// get deployed site details
// copied from `netlify status`
const siteId = site.id;
if (!siteId) {
this.warn("Did you run `netlify link` yet?");
this.error(`You don't appear to be in a folder that is linked to a site`);
}
let siteData;
try {
siteData = await api.getSite({ siteId });
} catch (e) {
if (e.status === 401 /* unauthorized*/) {
this.warn(
`Log in with a different account or re-link to a site you have permission for`
);
this.error(
`Not authorized to view the currently linked site (${siteId})`
);
}
if (e.status === 404 /* missing */) {
this.error(`The site this folder is linked to can't be found`);
}
this.error(e);
}
const deploy = siteData.published_deploy || {};
const deployed_functions = deploy.available_functions || [];

const functionsDir =
flags.functions ||
(config.dev && config.dev.functions) ||
(config.build && config.build.functions);
if (typeof functionsDir === "undefined") {
this.error(
"functions directory is undefined, did you forget to set it in netlify.toml?"
);
process.exit(1);
}
var table = new AsciiTable(
`Netlify Functions (based on local functions folder "${functionsDir}")`
);
const functions = getFunctions(functionsDir);

table.setHeading("Name", "Url", "moduleDir", "deployed");
Object.entries(functions).forEach(([functionName, { moduleDir }]) => {
const isDeployed = deployed_functions
.map(({ n }) => n)
.includes(functionName);

// this.log(`${chalk.yellow("function name")}: ${functionName}`);
// this.log(
// ` ${chalk.yellow(
// "url"
// )}: ${`/.netlify/functions/${functionName}`}`
// );
// this.log(` ${chalk.yellow("moduleDir")}: ${moduleDir}`);
// this.log(
// ` ${chalk.yellow("deployed")}: ${
// isDeployed ? chalk.green("yes") : chalk.yellow("no")
// }`
// );
// this.log("----------");
table.addRow(
functionName,
`/.netlify/functions/${functionName}`,
moduleDir,
isDeployed ? "yes" : "no"
);
this.log(`netlify functions:list NOT IMPLEMENTED YET`);
});
this.log(table.toString());
}
}

FunctionsListCommand.description = `list sites
...
Extra documentation goes here
FunctionsListCommand.description = `list functions that exist locally

Helpful for making sure that you have formatted your functions correctly

NOT the same as listing the functions that have been deployed. For that info you need to go to your Netlify deploy log.
`;
FunctionsListCommand.aliases = ["function:list"];
FunctionsListCommand.flags = {
name: flags.string({ char: "n", description: "name to print" })
name: flags.string({ char: "n", description: "name to print" }),
functions: flags.string({
char: "f",
description: "Specify a functions folder to serve"
})
};

// TODO make visible once implementation complete
Expand Down
33 changes: 33 additions & 0 deletions src/utils/get-functions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
const fs = require("fs");
const path = require("path");
const { findModuleDir, findHandler } = require("./finders");

module.exports = {
getFunctions(dir) {
const functions = {};
if (fs.existsSync(dir)) {
fs.readdirSync(dir).forEach(file => {
if (dir === "node_modules") {
return;
}
const functionPath = path.resolve(path.join(dir, file));
const handlerPath = findHandler(functionPath);
if (!handlerPath) {
return;
}
if (path.extname(functionPath) === ".js") {
functions[file.replace(/\.js$/, "")] = {
functionPath,
moduleDir: findModuleDir(functionPath)
};
} else if (fs.lstatSync(functionPath).isDirectory()) {
functions[file] = {
functionPath: handlerPath,
moduleDir: findModuleDir(functionPath)
};
}
});
}
return functions;
}
};
29 changes: 3 additions & 26 deletions src/utils/serve-functions.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,7 @@ const {
// NETLIFYDEVWARN,
NETLIFYDEVERR
} = require("netlify-cli-logo");

const { findModuleDir, findHandler } = require("./finders");
const { getFunctions } = require("./get-functions");

const defaultPort = 34567;

Expand Down Expand Up @@ -55,30 +54,7 @@ function buildClientContext(headers) {
}

function createHandler(dir) {
const functions = {};
if (fs.existsSync(dir)) {
fs.readdirSync(dir).forEach(file => {
if (dir === "node_modules") {
return;
}
const functionPath = path.resolve(path.join(dir, file));
const handlerPath = findHandler(functionPath);
if (!handlerPath) {
return;
}
if (path.extname(functionPath) === ".js") {
functions[file.replace(/\.js$/, "")] = {
functionPath,
moduleDir: findModuleDir(functionPath)
};
} else if (fs.lstatSync(functionPath).isDirectory()) {
functions[file] = {
functionPath: handlerPath,
moduleDir: findModuleDir(functionPath)
};
}
});
}
const functions = getFunctions(dir);

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

let callbackWasCalled = false;
const callback = createCallback(response);
// we already checked that it exports a function named handler above
const promise = handler.handler(
lambdaRequest,
{ clientContext: buildClientContext(request.headers) || {} },
Expand Down