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

Commit

Permalink
implement basic netlify functions:list command (#211)
Browse files Browse the repository at this point in the history
* implement basic netlify functions:list command

* add check against deployment

* note and check functions folder source
  • Loading branch information
swyxio authored Jul 8, 2019
1 parent ff8ea5d commit 5ef5230
Show file tree
Hide file tree
Showing 3 changed files with 120 additions and 53 deletions.
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

0 comments on commit 5ef5230

Please sign in to comment.