├── .eslintignore ├── .tools ├── stopOffline.sh ├── startOffline.sh └── check-boilerplate-packages.js ├── .travis.yml ├── stacks-map.js ├── .eslintrc.js ├── templates └── function.ejs ├── .gitignore ├── webpack.config.js ├── LICENSE ├── package.json ├── serverless.yml └── README.md /.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | tmp -------------------------------------------------------------------------------- /.tools/stopOffline.sh: -------------------------------------------------------------------------------- 1 | kill `cat .offline.pid` 2 | rm .offline.pid -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - '6.10.0' 4 | script: 5 | - npm run lint 6 | - npm test 7 | -------------------------------------------------------------------------------- /stacks-map.js: -------------------------------------------------------------------------------- 1 | // Split IAM Roles to separate cloudformation stack 2 | const stacksMap = require('serverless-plugin-split-stacks').stacksMap; 3 | 4 | stacksMap['AWS::IAM::Role'] = { 5 | destination: 'Roles', 6 | }; 7 | -------------------------------------------------------------------------------- /.tools/startOffline.sh: -------------------------------------------------------------------------------- 1 | TMPFILE=/var/tmp/offline$$.log 2 | if [ -f .offline.pid ]; then 3 | echo "Found file .offline.pid. Not starting." 4 | exit 1 5 | fi 6 | 7 | serverless offline start 2>1 > $TMPFILE & 8 | PID=$! 9 | echo $PID > .offline.pid 10 | 11 | while ! grep "Offline listening" $TMPFILE 12 | do sleep 1; done 13 | 14 | rm $TMPFILE -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | "extends": "airbnb", 3 | "plugins": [], 4 | "rules": { 5 | "func-names": "off", 6 | 7 | // doesn't work in node v4 :( 8 | "strict": "off", 9 | "prefer-rest-params": "off", 10 | "react/require-extension" : "off", 11 | "import/no-extraneous-dependencies" : "off" 12 | }, 13 | "env": { 14 | "mocha": true 15 | } 16 | }; 17 | -------------------------------------------------------------------------------- /templates/function.ejs: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | // Template from serverless-boilerplate 4 | // Set the env vars for the function 5 | 6 | module.exports.<%= handlerFunction %> = async (event, context, callback) => { 7 | const response = { 8 | statusCode: 200, 9 | body: JSON.stringify({ 10 | message: 'Go Serverless v1.0! Your function executed successfully!', 11 | input: event, 12 | }), 13 | }; 14 | 15 | callback(null, response); 16 | 17 | // Use this code if you don't use the http event with the LAMBDA-PROXY integration 18 | // callback(null, { message: 'Go Serverless v1.0! Your function executed successfully!', event }); 19 | }; 20 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log 5 | 6 | # Runtime data 7 | pids 8 | *.pid 9 | *.seed 10 | dist 11 | 12 | # Directory for instrumented libs generated by jscoverage/JSCover 13 | lib-cov 14 | 15 | # Coverage directory used by tools like istanbul 16 | coverage 17 | 18 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 19 | .grunt 20 | 21 | # node-waf configuration 22 | .lock-wscript 23 | 24 | # Compiled binary addons (http://nodejs.org/api/addons.html) 25 | build/Release 26 | 27 | # Dependency directory 28 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git 29 | node_modules 30 | 31 | #IDE Stuff 32 | **/.idea 33 | 34 | #OS STUFF 35 | .DS_Store 36 | .tmp 37 | 38 | #SERVERLESS STUFF 39 | admin.env 40 | .env 41 | _meta 42 | .serverless -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const CopyWebpackPlugin = require('copy-webpack-plugin'); 3 | const yaml = require('node-yaml'); 4 | const nodeExternals = require('webpack-node-externals'); 5 | 6 | function getFunctions() { 7 | const serverlessYml = yaml.readSync('serverless.yml'); 8 | const webPackFunctions = {}; 9 | const functionNames = Object.keys(serverlessYml.functions || {}); 10 | functionNames.forEach((name) => { 11 | const handlerFile = serverlessYml.functions[name].handler.replace(/.[^.]*$/, ''); 12 | webPackFunctions[handlerFile] = `./${handlerFile}.js`; 13 | }); 14 | return webPackFunctions; 15 | } 16 | 17 | module.exports = { 18 | entry: getFunctions(), 19 | target: 'node', 20 | module: { 21 | rules: [ 22 | { test: /\.json/, loader: 'json-loader' }, 23 | ], 24 | }, 25 | plugins: [ 26 | new CopyWebpackPlugin([ 27 | { from: '.env' }, 28 | ]), 29 | ], 30 | output: { 31 | libraryTarget: 'commonjs', 32 | path: path.join(__dirname, '.webpack'), 33 | filename: '[name].js', 34 | }, 35 | externals: [nodeExternals()], 36 | }; 37 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Nordcloud Ltd 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /.tools/check-boilerplate-packages.js: -------------------------------------------------------------------------------- 1 | const request = require('request-json'); 2 | const client = request.createClient('https://raw.githubusercontent.com'); 3 | const boilerplatePackagesPath = "/nordcloud/serverless-boilerplate/master/package.json"; 4 | 5 | const currentPackages = require('../package.json'); 6 | 7 | client.get(boilerplatePackagesPath, function(err, res, body) { 8 | const boilerPackages = body; 9 | console.log('DEVDEPENDENCIES'); 10 | 11 | const devPackages = Object.keys(boilerPackages.devDependencies); 12 | devPackages.forEach((pkg) => { 13 | if (boilerPackages.devDependencies[pkg] != currentPackages.devDependencies[pkg]) { 14 | console.log(` ${pkg}: ${boilerPackages.devDependencies[pkg]} <=> ${currentPackages.devDependencies[pkg]}`); 15 | } 16 | }); 17 | 18 | console.log('DEPENDENCIES'); 19 | const prodPackages = Object.keys(boilerPackages.dependencies); 20 | prodPackages.forEach((pkg) => { 21 | if (boilerPackages.dependencies[pkg] != currentPackages.dependencies[pkg]) { 22 | console.log(` ${pkg}: ${boilerPackages.dependencies[pkg]} <=> ${currentPackages.dependencies[pkg]}`); 23 | } 24 | }); 25 | 26 | console.log('SCRIPTS'); 27 | const scripts = Object.keys(boilerPackages.scripts); 28 | scripts.forEach((script) => { 29 | if (boilerPackages.scripts[script] != currentPackages.scripts[script]) { 30 | console.log(` ${script}: ${boilerPackages.scripts[script]} <=> ${currentPackages.scripts[script]}`); 31 | } 32 | }); 33 | }); -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "serverless-boilerplate", 3 | "version": "1.4.1", 4 | "description": "A boilerplate for Serverless applications by Nordcloud", 5 | "keywords": [ 6 | "serverless", 7 | "aws" 8 | ], 9 | "author": "Mikael Puittinen", 10 | "contributors": [ 11 | "Eetu Tuomala" 12 | ], 13 | "license": "MIT", 14 | "repository": { 15 | "type": "git", 16 | "url": "https://github.com/nordcloud/serverless-boilerplate.git" 17 | }, 18 | "dependencies": { 19 | "diff": "^3.5.0" 20 | }, 21 | "devDependencies": { 22 | "aws-sdk": "^2.54.0", 23 | "copy-webpack-plugin": "^3.0.1", 24 | "eslint": "^4.19.1", 25 | "eslint-config-airbnb": "^10.0.1", 26 | "eslint-config-airbnb-base": "^5.0.3", 27 | "eslint-plugin-import": "^1.16.0", 28 | "eslint-plugin-jsx-a11y": "^2.2.3", 29 | "eslint-plugin-react": "^6.10.3", 30 | "json-loader": "^0.5.4", 31 | "license-checker": "^8.0.3", 32 | "node-yaml": "^4.0.1", 33 | "request-json": "^0.6.4", 34 | "serverless-kms-secrets": "^1.0.3", 35 | "serverless-mocha-plugin": "^1.11.0", 36 | "serverless-offline": "^5.8.0", 37 | "serverless-plugin-custom-roles": "^1.0.0", 38 | "serverless-plugin-split-stacks": "^1.4.1", 39 | "serverless-webpack": "^3.0.0", 40 | "webpack": "^4.28.2", 41 | "webpack-node-externals": "^1.5.4" 42 | }, 43 | "scripts": { 44 | "test": "SLS_DEBUG=true serverless invoke test", 45 | "lint": "eslint .", 46 | "check-licenses": "license-checker --exclude 'MIT, MIT/X11, ISC, Apache-2.0, Unlicense, WTFPL, BSD-2-Clause, BSD-3-Clause, (MIT AND CC-BY-3.0)'", 47 | "compare-boilerplate": "node .tools/check-boilerplate-packages.js" 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /serverless.yml: -------------------------------------------------------------------------------- 1 | frameworkVersion: ">=1.2.0 <2.0.0" 2 | 3 | service: serverless-boilerplate # NOTE: update this with your service name 4 | 5 | provider: 6 | name: aws 7 | runtime: nodejs10.x 8 | cfLogs: true 9 | environment: 10 | SERVERLESS_STAGE: ${opt:stage, self:provider.stage} 11 | SERVERLESS_PROJECT: ${self:service} 12 | SERVERLESS_REGION: ${opt:region, self:provider.region} 13 | TABLE_NAME: ${self:provider.environment.SERVERLESS_PROJECT}-${self:provider.environment.SERVERLESS_STAGE} 14 | iamRoleStatements: 15 | # - Effect: Allow 16 | # Action: 17 | # - dynamodb:* 18 | # Resource: arn:aws:dynamodb:${self:provider.environment.SERVERLESS_REGION}:*:* 19 | # - Effect: Allow 20 | # Action: 21 | # - SNS:* 22 | # Resource: arn:aws:sns:${self:provider.environment.SERVERLESS_REGION}:*:* 23 | # - Effect: Allow 24 | # Action: 25 | # - KMS:Decrypt 26 | # Resource: ${self:custom.kmsSecrets.keyArn} 27 | package: 28 | individually: true 29 | exclude: 30 | - test/** 31 | - .git/** 32 | 33 | functions: 34 | 35 | plugins: 36 | - serverless-mocha-plugin 37 | - serverless-webpack 38 | - serverless-offline 39 | - serverless-kms-secrets 40 | - serverless-plugin-custom-roles 41 | - serverless-plugin-split-stacks 42 | 43 | custom: 44 | serverless-mocha-plugin: 45 | functionTemplate: templates/function.ejs 46 | # Uncomment these if you need to run the service offline for testing 47 | # preTestCommands: 48 | # - bash .tools/startOffline.sh 49 | # postTestCommands: 50 | # - bash .tools/stopOffline.sh 51 | webpackIncludeModules: true 52 | # kmsSecrets: ${file(kms-secrets.${opt:stage, self:provider.stage}.${opt:region, self:provider.region}.yml)} 53 | 54 | 55 | 56 | #resources: 57 | # Resources: 58 | # SessionsTable: 59 | # Type: AWS::DynamoDB::Table 60 | # DeletionPolicy: Delete 61 | # Properties: 62 | # AttributeDefinitions: 63 | # - AttributeName: id 64 | # AttributeType: S 65 | # KeySchema: 66 | # - AttributeName: id 67 | # KeyType: HASH 68 | # ProvisionedThroughput: 69 | # ReadCapacityUnits: 1 70 | # WriteCapacityUnits: 1 71 | # TableName: ${self:provider.environment.TABLE_NAME} -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Nordcloud Serverless Boilerplate 2 | 3 | The Nordcloud serverless-boilerplate is a project template for new serverless services. Contents of the template: 4 | * plugin [serverless-mocha-plugin](https://github.com/nordcloud/serverless-mocha-plugin): enable test driven development using mocha, creation of functions from command line 5 | * plugin [serverless-offline](https://github.com/dherault/serverless-offline): run your services offline for e.g. testing 6 | * plugin [serverless-webpack](https://github.com/elastic-coders/serverless-webpack): optimize pacakge size with webpack 7 | * plugin [serverless-kms-secrets](https://github.com/nordcloud/serverless-kms-secrets): ease handling of KMS encrypted secrets 8 | * plugin [serverless-plugin-custom-roles](https://www.npmjs.com/package/serverless-plugin-custom-roles): enable setting roles on a per function basis 9 | * plugin [serverless-plugin-split-stacks](https://github.com/dougmoscrop/serverless-plugin-split-stacks): Split Cloudformation stack to multiple stacks to overcome the 200 resource limit 10 | * file `serverless.yml.json`: Register plugins above 11 | * file `webpack.config.js`: Settings for webpack-plugin 12 | * file `templates/function.ejs`: Template to use for new functions 13 | 14 | ## Creating new project 15 | 16 | With Serverless Framework v1.5 and later, a new project based on the project template is initialized with the command 17 | 18 | ``` 19 | > sls install -u https://github.com/nordcloud/serverless-boilerplate -n myservicename 20 | > cd myservicename 21 | > npm install 22 | ``` 23 | 24 | ## Testing vulnerabilities 25 | 26 | Test vulnerabilities with 27 | ``` 28 | > npm audit 29 | ``` 30 | (NSP is no longer available) 31 | 32 | ## Comparing setup with boilerplate 33 | 34 | You can compare your project setup (dependencies, devdependencies, scripts) with the boilerplate using the command 35 | 36 | ``` 37 | > npm run compare-boilerplate 38 | ``` 39 | 40 | The script reports only for items that are in the boilerplate and differ from your current project. 41 | 42 | ## TODO 43 | 44 | Please see project GitHub [issue tracker](https://github.com/nordcloud/serverless-boilerplate/issues). 45 | 46 | ## Release History 47 | 48 | * 2016/11/02 - v1.0.0 - Initial version for Serverless 1.0 49 | 50 | ## License 51 | 52 | Copyright (c) 2016 [Nordcloud](https://www.nordcloud.com/), licensed for users and contributors under MIT license. 53 | https://github.com/nordcloud/serverless-boilerplate/blob/master/LICENSE-MIT 54 | --------------------------------------------------------------------------------