Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(gatsby-plugin-functions): Add the ability to run functions locally and on Gatsby Cloud #30192

Merged
merged 76 commits into from
Apr 16, 2021
Merged
Show file tree
Hide file tree
Changes from 42 commits
Commits
Show all changes
76 commits
Select commit Hold shift + click to select a range
098a209
Add new plugin
sidharthachatterjee Nov 16, 2020
7576e2a
Add functions plugin by default
sidharthachatterjee Nov 16, 2020
df0496f
Add stub
sidharthachatterjee Nov 16, 2020
5d0c3e8
Bump up package.json
sidharthachatterjee Nov 16, 2020
9febad5
wip
sidharthachatterjee Nov 24, 2020
0597a5f
Compile all functions found in build
sidharthachatterjee Nov 24, 2020
2536188
Add plugin by default only if GATSBY_EXPERIMENT_FUNCTIONS is set
sidharthachatterjee Nov 24, 2020
29159df
Move to public for now
sidharthachatterjee Nov 25, 2020
eec2a09
Move to functions dir
sidharthachatterjee Nov 25, 2020
6470ee4
Run a dev server for functions
sidharthachatterjee Nov 30, 2020
9635aa1
wip
sidharthachatterjee Nov 30, 2020
4a59a47
Move to onPreBootstrap
sidharthachatterjee Jan 5, 2021
85d7cfa
Add target node
abhiaiyer91 Jan 11, 2021
ef07abd
Bump up package.json
sidharthachatterjee Jan 7, 2021
72877bc
Bump up package.json
sidharthachatterjee Jan 12, 2021
daf3b04
Add support for env vars
sidharthachatterjee Feb 19, 2021
32bd3d6
Publish 0.1.0-4
sidharthachatterjee Feb 19, 2021
a2ae24e
Bump up peerDependencies
sidharthachatterjee Mar 2, 2021
c1a2a05
Update yarn lock
sidharthachatterjee Mar 11, 2021
3d9ecbc
Use a parameter in express middleware and ignore extension (#30222)
sidharthachatterjee Mar 12, 2021
6067919
Merge remote-tracking branch 'upstream/master' into feat/functions
Mar 16, 2021
2aacbcc
Publish 0.1.0-6
sidharthachatterjee Mar 16, 2021
1587dc2
Set a default functions directory path (#30277)
sidharthachatterjee Mar 17, 2021
f0ab110
feat(functions): Add body parser
julienp Mar 21, 2021
b5324f9
Require files from the .cache directory so user can run es/commonjs (…
abhiaiyer91 Mar 25, 2021
21e1841
Publish 0.1.0-7
sidharthachatterjee Mar 25, 2021
6ce15fa
Prefer directory from program in state
sidharthachatterjee Apr 2, 2021
b2c4aa8
Log invocations as verbose
sidharthachatterjee Apr 2, 2021
bd0acc5
Add timeout constant
sidharthachatterjee Apr 2, 2021
4cfde03
Add internal plugin
sidharthachatterjee Apr 2, 2021
cc98e76
Load functions internal plugin
sidharthachatterjee Apr 2, 2021
17730bd
Load functions during initialize and stick em in redux
sidharthachatterjee Apr 2, 2021
80a9882
Merge branch 'master' into feat/functions
sidharthachatterjee Apr 7, 2021
56176d3
Clean up comments
sidharthachatterjee Apr 7, 2021
eace7e8
Move initialization code back to plugin
sidharthachatterjee Apr 7, 2021
5c1f96e
Add experiment for Gatsby Functions
sidharthachatterjee Apr 7, 2021
6b8d414
Revert yarn changes
sidharthachatterjee Apr 7, 2021
b325d12
Remove plugin package
sidharthachatterjee Apr 7, 2021
88d76a1
Do not extract comments
sidharthachatterjee Apr 7, 2021
311c9ec
Update yarn.lock
sidharthachatterjee Apr 7, 2021
d554093
Update packages/gatsby/src/internal-plugins/functions/gatsby-node.ts
julienp Apr 13, 2021
63bc54c
chore(functions): Remove console.logs
julienp Apr 13, 2021
f08d0ee
chore(functions): Remove unused urlResolve import
julienp Apr 13, 2021
5d6d072
Merge remote-tracking branch 'upstream/master' into feat/functions
Apr 13, 2021
7fbac4a
get internal plugin functions working + some cleanups
KyleAMathews Apr 13, 2021
4af22f9
Fix regex per @jamo's suggestion + update yarn.lock
KyleAMathews Apr 13, 2021
324bd99
remove accidentally committed file
KyleAMathews Apr 13, 2021
92e05c9
globby isn't a dependency of gatsby
KyleAMathews Apr 13, 2021
2163f08
fix(functions): End request with status 500 on function error
julienp Apr 13, 2021
aad744d
Hot reload functions
KyleAMathews Apr 13, 2021
c5c61ec
Load env variables from .env.* files
KyleAMathews Apr 13, 2021
aaf53f9
Resolve result of function so we can catch errors from async functions
KyleAMathews Apr 13, 2021
d2d7af0
Log webpack warnings/errors when compiling to the terminal
KyleAMathews Apr 13, 2021
02fcfbe
Log how long function took to execute
KyleAMathews Apr 13, 2021
4bec919
reload watch when .env files change & use all process.env vars
KyleAMathews Apr 13, 2021
ac9e55d
Allow for arbitrarily deep functions
KyleAMathews Apr 13, 2021
a26ac14
Detect new functions and incorporate
KyleAMathews Apr 13, 2021
5cc3661
Log when functions rebuild or we restart the watcher
KyleAMathews Apr 13, 2021
ae8f46f
List functions on dev-404-page
KyleAMathews Apr 13, 2021
0336739
Only show new API instructions when trying to reach an API route + ad…
KyleAMathews Apr 13, 2021
7282d1f
Fix linting
KyleAMathews Apr 14, 2021
6caff93
put new code behind conditional
KyleAMathews Apr 14, 2021
4b5aa4e
Properly close webpack watcher + handle deleting functions
KyleAMathews Apr 14, 2021
10226e4
Ignore non-js extensions (so make typescript work)
KyleAMathews Apr 14, 2021
1ee2d24
Write out manifest file so can serve functions from 'gatsby serve'
KyleAMathews Apr 14, 2021
4a9fffd
Address @lekoart's comments
KyleAMathews Apr 15, 2021
3cba097
Add default type for SiteFunction & fix small bugs when site doesn't …
KyleAMathews Apr 15, 2021
9c164f7
Add initial suite of tests
KyleAMathews Apr 15, 2021
771fb62
Update snapshots
KyleAMathews Apr 15, 2021
b2f2af2
Fix more tests
KyleAMathews Apr 15, 2021
73dceb4
Add functions tests to circleci setup
KyleAMathews Apr 15, 2021
10cd117
Only parse once
KyleAMathews Apr 16, 2021
42de7d5
Small tweaks
KyleAMathews Apr 16, 2021
8405b31
add comment
KyleAMathews Apr 16, 2021
af36e09
Fix typescript support
KyleAMathews Apr 16, 2021
2b7c7cf
Add tests for apis with special characters h/t @lekoarts
KyleAMathews Apr 16, 2021
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
190 changes: 190 additions & 0 deletions packages/gatsby-plugin-functions/gatsby-node.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
"use strict";

var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard");

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");

exports.__esModule = true;
exports.onPreBootstrap = onPreBootstrap;
exports.onCreateDevServer = onCreateDevServer;

var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));

var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));

var _fsExtra = _interopRequireDefault(require("fs-extra"));

var _globby = _interopRequireDefault(require("globby"));

var _path = _interopRequireDefault(require("path"));

var _webpack = _interopRequireDefault(require("webpack"));

var _multer = _interopRequireDefault(require("multer"));

var express = _interopRequireWildcard(require("express"));

var _gatsbyCoreUtils = require("gatsby-core-utils");

var DEFAULT_FUNCTIONS_DIRECTORY_PATH = _path.default.join(process.cwd(), "src/api");

function onPreBootstrap(_x, _x2) {
return _onPreBootstrap.apply(this, arguments);
}

function _onPreBootstrap() {
_onPreBootstrap = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee(_ref, _ref2) {
var reporter, _ref2$path, functionsDirectoryPath, activity, functionsDirectory, functionsGlob, files, knownFunctions, gatsbyVarObject, varObject;

return _regenerator.default.wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
reporter = _ref.reporter;
_ref2$path = _ref2.path, functionsDirectoryPath = _ref2$path === void 0 ? DEFAULT_FUNCTIONS_DIRECTORY_PATH : _ref2$path;
activity = reporter.activityTimer("building functions");
activity.start();
functionsDirectory = _path.default.resolve(process.cwd(), functionsDirectoryPath);
functionsGlob = "**/*.{js,ts}"; // Get initial list of files

_context.next = 8;
return (0, _globby.default)(functionsGlob, {
cwd: functionsDirectory
});

case 8:
files = _context.sent;
// console.log({ files })
knownFunctions = new Set(files); // console.log({ knownFunctions })
// if (![`develop`, `build-javascript`].includes(stage)) {
// return Promise.resolve()
// }

_context.next = 12;
return _fsExtra.default.ensureDir(_path.default.join(process.cwd(), ".cache", "functions"));

case 12:
_context.next = 14;
return _fsExtra.default.emptyDir(_path.default.join(process.cwd(), ".cache", "functions"));

case 14:
// console.log({
// path: path.join(functionsDirectory, `month.js`),
// })
gatsbyVarObject = Object.keys(process.env).reduce(function (acc, key) {
if (key.match(/^GATSBY_/)) {
acc[key] = JSON.stringify(process.env[key]);
}

return acc;
}, {});
varObject = Object.keys(gatsbyVarObject).reduce(function (acc, key) {
acc["process.env." + key] = gatsbyVarObject[key];
return acc;
}, {
"process.env": "({})"
});
_context.next = 18;
return Promise.all(files.map(function (file) {
var config = {
entry: _path.default.join(functionsDirectory, file),
output: {
path: _path.default.join(process.cwd(), ".cache", "functions"),
filename: file.replace(".ts", ".js"),
libraryTarget: "commonjs2"
},
target: "node",
// library: "yourLibName",
mode: "production",
module: {
rules: [{
test: [/.js$/, /.ts$/],
exclude: /node_modules/,
loader: "babel-loader"
}]
},
plugins: [new _webpack.default.DefinePlugin(varObject)] // devtool: `source-map`,

};
return new Promise(function (resolve, reject) {
return (// if (stage === `develop`) {
// webpack(config).watch({}, () => {})
// return resolve()
// }
(0, _webpack.default)(config).run(function (err, stats) {
console.log({
warnings: stats.compilation.warnings
});
if (err) return reject(err);
var errors = stats.compilation.errors || [];
if (errors.length > 0) return reject(stats.compilation.errors);
return resolve();
})
);
});
}));

case 18:
activity.end();

case 19:
case "end":
return _context.stop();
}
}
}, _callee);
}));
return _onPreBootstrap.apply(this, arguments);
}

function onCreateDevServer(_x3, _x4) {
return _onCreateDevServer.apply(this, arguments);
}

function _onCreateDevServer() {
_onCreateDevServer = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee2(_ref3, _ref4) {
var reporter, app, _ref4$path, functionsDirectoryPath, functionsGlob, functionsDirectory, files, knownFunctions;

return _regenerator.default.wrap(function _callee2$(_context2) {
while (1) {
switch (_context2.prev = _context2.next) {
case 0:
reporter = _ref3.reporter, app = _ref3.app;
_ref4$path = _ref4.path, functionsDirectoryPath = _ref4$path === void 0 ? DEFAULT_FUNCTIONS_DIRECTORY_PATH : _ref4$path;
functionsGlob = "**/*.{js,ts}";
functionsDirectory = _path.default.resolve(process.cwd(), functionsDirectoryPath);
_context2.next = 6;
return (0, _globby.default)(functionsGlob, {
cwd: functionsDirectory
});

case 6:
files = _context2.sent;
// console.log({ files })
knownFunctions = new Map(files.map(function (file) {
return [(0, _gatsbyCoreUtils.urlResolve)(_path.default.parse(file).dir, _path.default.parse(file).name), file];
})); // console.log(app, functionsDirectoryPath)

app.use("/api/:functionName", (0, _multer.default)().none(), express.urlencoded({
extended: true
}), express.text(), express.json(), express.raw(), function (req, res, next) {
var functionName = req.params.functionName;

if (knownFunctions.has(functionName)) {
var fn = require(_path.default.join(functionsDirectory, knownFunctions.get(functionName)));

fn(req, res);
} else {
next();
}
});

case 9:
case "end":
return _context2.stop();
}
}
}, _callee2);
}));
return _onCreateDevServer.apply(this, arguments);
}
1 change: 1 addition & 0 deletions packages/gatsby/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@
"gatsby-react-router-scroll": "^4.3.0-next.0",
"gatsby-telemetry": "^2.3.0-next.0",
"glob": "^7.1.6",
"gatsby-plugin-functions": "^0.1.0-0",
KyleAMathews marked this conversation as resolved.
Show resolved Hide resolved
"got": "8.3.2",
"graphql": "^15.4.0",
"graphql-compose": "~7.25.0",
Expand Down
17 changes: 16 additions & 1 deletion packages/gatsby/src/bootstrap/load-plugins/load.ts
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,9 @@ export function loadPlugins(
`../../internal-plugins/prod-404`,
`../../internal-plugins/webpack-theme-component-shadowing`,
`../../internal-plugins/bundle-optimisations`,
]
process.env.GATSBY_EXPERIMENTAL_FUNCTIONS &&
`../../internal-plugins/functions`,
].filter(Boolean) as Array<string>
internalPlugins.forEach(relPath => {
const absPath = path.join(__dirname, relPath)
plugins.push(processPlugin(absPath))
Expand Down Expand Up @@ -240,6 +242,19 @@ export function loadPlugins(
)
})

// Gatsby Functions

if (process.env.GATSBY_EXPERIMENT_FUNCTIONS) {
plugins.push(
processPlugin({
resolve: require.resolve(`gatsby-plugin-functions`),
options: {
path: slash(path.join(process.cwd(), `src/api`)),
},
})
)
}

// TypeScript support by default! use the user-provided one if it exists
const typescriptPlugin = (config.plugins || []).find(
plugin => plugin.resolve === `gatsby-plugin-typescript`
Expand Down
Loading