├── .gitignore ├── README.md ├── __tests__ └── lambdaTest.spec.js ├── generator.js ├── index.js ├── package.json ├── scripts └── testSetup.js ├── template ├── netlify.toml └── src │ └── lambda │ └── hello.js ├── testProject └── .gitkeep ├── ui.js └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | .DS_Store 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # vue-cli-plugin-netlify-lambda 2 | 3 | > netlify-lambda plugin for vue-cli 4 | 5 | Sets up [netlify-lambda](https://github.com/netlify/netlify-lambda) for vue-cli projects to build and serve AWS lambda functions. 6 | 7 | ## Installing in an Already Created Project 8 | 9 | ``` 10 | vue add netlify-lambda 11 | ``` 12 | 13 | ## Usage 14 | 15 | This ads a `netlify.toml` and a `src/lambda` folder with an example `hello.js` lambda function. 16 | 17 | Any js file added in `src/lambda` will be built as a lambda. It will be compiled with webpack and babel and any imports will be bundled (no native dependencies, though). 18 | 19 | When deployed to Netlify, the AWS lambda's are reachable under `/.netlify/functions/:name` - ie, the `hello.js` Lambda will be available under `/.netlify/functions/hello`. 20 | 21 | The plugin also sets up a proxy and runs the Lambdas locally, to simplify local development. 22 | -------------------------------------------------------------------------------- /__tests__/lambdaTest.spec.js: -------------------------------------------------------------------------------- 1 | jest.setTimeout(90000); 2 | 3 | const create = require("@vue/cli-test-utils/createTestProject"); 4 | const path = require("path"); 5 | const cwd = path.resolve(__dirname, "../testProject"); 6 | const rimraf = require("rimraf"); 7 | 8 | beforeAll(async () => { 9 | rimraf(path.resolve(cwd, "example-netlify-lambda-project"), () => {}); 10 | }); 11 | 12 | test("should create vuex modules", async () => { 13 | const project = await create( 14 | "example-netlify-lambda-project", 15 | { 16 | plugins: { 17 | "@vue/cli-plugin-babel": {} 18 | } 19 | }, 20 | cwd 21 | ); 22 | await project.run( 23 | `${require.resolve( 24 | "@vue/cli/bin/vue" 25 | )} add vue-cli-plugin-netlify-lambda@file:../../` 26 | ); 27 | await project.run( 28 | `${require.resolve( 29 | "@vue/cli/bin/vue" 30 | )} invoke vue-cli-plugin-netlify-lambda` 31 | ); 32 | expect(await project.has("src/lambda/hello.js")).toBe(true); 33 | }); 34 | -------------------------------------------------------------------------------- /generator.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs') 2 | 3 | module.exports = (api, options, rootOptions) => { 4 | api.render("./template") 5 | 6 | fs.appendFileSync(api.resolve(".gitignore"), "\n# Compiled Lambda functions\n/lambda/\n") 7 | } -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | const { fork } = require('child_process') 2 | const path = require('path') 3 | const lambdaBuild = require('netlify-lambda/lib/build') 4 | 5 | module.exports = (api, projectOptions) => { 6 | const {build, serve} = api.service.commands; 7 | const buildFn = build.fn; 8 | const serveFn = serve.fn; 9 | const webpackConfig = projectOptions.pluginOptions && projectOptions.pluginOptions.netlify && projectOptions.pluginOptions.netlify.webpackConfig; 10 | 11 | build.fn = async (...args) => { 12 | try { 13 | const [res, stats] = await Promise.all([ 14 | buildFn(...args), 15 | lambdaBuild.run('src/lambda', webpackConfig), 16 | ]); 17 | console.log(stats.toString({ color: true })); 18 | return res; 19 | } catch (err) { 20 | console.error(err); 21 | process.exit(1); 22 | } 23 | } 24 | 25 | serve.fn = (...args) => { 26 | const devServer = api.service.projectOptions.devServer = api.service.projectOptions.devServer || {} 27 | if (!devServer.proxy) { 28 | devServer.proxy = {} 29 | } 30 | devServer.proxy['/.netlify/functions'] = { 31 | "target": "http://localhost:9000", 32 | "pathRewrite": { 33 | "^/\\.netlify/functions": "" 34 | } 35 | } 36 | 37 | fork(require.resolve('netlify-lambda'), ['serve', 'src/lambda', ...(webpackConfig ? ['-c', webpackConfig] : [])]); 38 | return serveFn(...args) 39 | } 40 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue-cli-plugin-netlify-lambda", 3 | "version": "0.1.1", 4 | "description": "Vue Cli plugin for adding Netlify Lambda", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "jest" 8 | }, 9 | "jest": { 10 | "testEnvironment": "node", 11 | "setupFiles": [ 12 | "/scripts/testSetup.js" 13 | ], 14 | "testPathIgnorePatterns": [ 15 | "./generator/template/", 16 | "./generator/generator.js" 17 | ] 18 | }, 19 | "author": "Netlify", 20 | "license": "MIT", 21 | "repository": "netlify/vue-cli-plugin-netlify-lambda", 22 | "dependencies": { 23 | "@vue/cli": "^3.0.1", 24 | "@vue/cli-plugin-babel": "^3.0.1", 25 | "@vue/cli-service": "^3.0.1", 26 | "@vue/cli-test-utils": "^3.0.1", 27 | "jest": "^23.5.0", 28 | "netlify-lambda": "1.0.0-babel-7-beta", 29 | "rimraf": "^2.6.2" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /scripts/testSetup.js: -------------------------------------------------------------------------------- 1 | process.env.VUE_CLI_TEST = true; 2 | -------------------------------------------------------------------------------- /template/netlify.toml: -------------------------------------------------------------------------------- 1 | [build] 2 | command = "yarn build" 3 | functions = "lambda" 4 | publish = "dist" -------------------------------------------------------------------------------- /template/src/lambda/hello.js: -------------------------------------------------------------------------------- 1 | export function handler(event, context, callback) { 2 | console.log(event) 3 | callback(null, { 4 | statusCode: 200, 5 | body: JSON.stringify({msg: "Hello, World!"}) 6 | }) 7 | } -------------------------------------------------------------------------------- /testProject/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/netlify/vue-cli-plugin-netlify-lambda/4a4dc4dbfa97284d79f729859ea7af7d6d5b6b5c/testProject/.gitkeep -------------------------------------------------------------------------------- /ui.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const path = require('path'); 3 | 4 | function getConfigData(data) { 5 | return (data.vue && data.vue.pluginOptions && data.vue.pluginOptions.netlify) || {}; 6 | } 7 | 8 | module.exports = api => api.describeConfig({ 9 | id: 'com.netlify.netlify-lambda', 10 | name: 'Netlify configuration', 11 | description: 'Configure Netlify Functions', 12 | link: 'https://github.com/netlify/vue-cli-plugin-netlify-lambda', 13 | files: { 14 | vue: { 15 | js: ['vue.config.js'], 16 | }, 17 | }, 18 | onRead({ data, cwd }) { 19 | return { 20 | prompts: [ 21 | { 22 | name: 'webpackConfig', 23 | type: 'input', 24 | default: null, 25 | value: getConfigData(data).webpackConfig, 26 | validate: input => fs.existsSync(path.join(cwd, input)), 27 | message: 'Webpack config module', 28 | description: 'Additional webpack configuration', 29 | }, 30 | ], 31 | }; 32 | }, 33 | async onWrite({ api: writeApi, prompts }) { 34 | const result = {}; 35 | for (const prompt of prompts) { 36 | result[`pluginOptions.netlify.${prompt.id}`] = await writeApi.getAnswer(prompt.id); 37 | } 38 | writeApi.setData('vue', result); 39 | }, 40 | }); 41 | --------------------------------------------------------------------------------