├── .gitignore ├── package.json ├── template.yml ├── databaseManager.js ├── README.md └── handler.js /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | node_modules/ 3 | packaged-template.yaml 4 | .aws-sam/ 5 | commands-dpeloying 6 | sam-test-basic-project-packaged.yaml 7 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sam-test-basic-project", 3 | "version": "1.0.0", 4 | "description": "aws cloudformation package --template-file template.yml --s3-bucket --output-template-file packaged-template.yaml", 5 | "main": "databaseManager.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/mavi888/sam-test-basic-project.git" 12 | }, 13 | "keywords": [], 14 | "author": "", 15 | "license": "ISC", 16 | "bugs": { 17 | "url": "https://github.com/mavi888/sam-test-basic-project/issues" 18 | }, 19 | "homepage": "https://github.com/mavi888/sam-test-basic-project#readme", 20 | "dependencies": { 21 | "uuid": "^3.3.3" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /template.yml: -------------------------------------------------------------------------------- 1 | AWSTemplateFormatVersion: '2010-09-09' 2 | Transform: 'AWS::Serverless-2016-10-31' 3 | 4 | Parameters: 5 | TableName: 6 | Type: String 7 | Default: 'yourTableName' 8 | Description: (Required) The name of the new DynamoDB table you want to create and save to. Minimum 3 characters 9 | MinLength: 3 10 | MaxLength: 50 11 | AllowedPattern: ^[A-Za-z]+$ 12 | ConstraintDescription: 'Required parameter. Must be characters only. No numbers allowed.' 13 | 14 | Resources: 15 | hello: 16 | Type: 'AWS::Serverless::Function' 17 | Properties: 18 | Handler: handler.hello 19 | Runtime: nodejs10.x 20 | CodeUri: . 21 | Policies: 22 | - DynamoDBCrudPolicy: 23 | TableName: !Ref TableName 24 | Environment: 25 | Variables: 26 | TABLE_NAME: !Ref TableName 27 | Events: 28 | CreateAPI: 29 | Type: Api 30 | Properties: 31 | Path: /hello 32 | Method: POST 33 | OtherOperationsAPI: 34 | Type: Api 35 | Properties: 36 | Path: /hello/{itemId} 37 | Method: ANY 38 | DynamoDBTable: 39 | Type: 'AWS::DynamoDB::Table' 40 | Properties: 41 | TableName: !Ref TableName 42 | AttributeDefinitions: 43 | - AttributeName: itemId 44 | AttributeType: S 45 | KeySchema: 46 | - AttributeName: itemId 47 | KeyType: HASH 48 | BillingMode: PAY_PER_REQUEST 49 | 50 | -------------------------------------------------------------------------------- /databaseManager.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const AWS = require('aws-sdk'); 4 | let dynamo = new AWS.DynamoDB.DocumentClient(); 5 | 6 | const TABLE_NAME = process.env.TABLE_NAME; 7 | 8 | module.exports.initializateDynamoClient = newDynamo => { 9 | dynamo = newDynamo; 10 | }; 11 | 12 | module.exports.saveItem = item => { 13 | const params = { 14 | TableName: TABLE_NAME, 15 | Item: item 16 | }; 17 | 18 | return dynamo 19 | .put(params) 20 | .promise() 21 | .then(() => { 22 | return item.itemId; 23 | }); 24 | }; 25 | 26 | module.exports.getItem = itemId => { 27 | const params = { 28 | Key: { 29 | itemId: itemId 30 | }, 31 | TableName: TABLE_NAME 32 | }; 33 | 34 | return dynamo 35 | .get(params) 36 | .promise() 37 | .then(result => { 38 | return result.Item; 39 | }); 40 | }; 41 | 42 | module.exports.deleteItem = itemId => { 43 | const params = { 44 | Key: { 45 | itemId: itemId 46 | }, 47 | TableName: TABLE_NAME 48 | }; 49 | 50 | return dynamo.delete(params).promise(); 51 | }; 52 | 53 | module.exports.updateItem = (itemId, paramsName, paramsValue) => { 54 | const params = { 55 | TableName: TABLE_NAME, 56 | Key: { 57 | itemId 58 | }, 59 | ConditionExpression: 'attribute_exists(itemId)', 60 | UpdateExpression: 'set ' + paramsName + ' = :v', 61 | ExpressionAttributeValues: { 62 | ':v': paramsValue 63 | }, 64 | ReturnValues: 'ALL_NEW' 65 | }; 66 | 67 | return dynamo 68 | .update(params) 69 | .promise() 70 | .then(response => { 71 | return response.Attributes; 72 | }); 73 | }; 74 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### To build, package and deploy this project follow this steps 2 | 3 | 1. Build SAM project 4 | 5 | ``` 6 | sam build --region 7 | ``` 8 | 9 | Example 10 | ``` 11 | sam build --region us-east-1 12 | ``` 13 | 14 | 2. Create a S3 bucket. Only to do the first time you package this project 15 | ``` 16 | aws s3api create-bucket --bucket --region 17 | ``` 18 | 19 | Example: 20 | ``` 21 | aws s3api create-bucket --bucket learning-serverless-publish-sam-app --region us-east-1 22 | ``` 23 | 24 | 3. Package project 25 | 26 | ``` 27 | sam package --template-file --s3-bucket --output-template-file 28 | ``` 29 | 30 | Example: 31 | ``` 32 | sam package --template-file template.yaml --s3-bucket learning-serverless-publish-sam-app --output-template-file packaged.yaml 33 | ``` 34 | 35 | 4. Deploy project to cloudformation 36 | 37 | Run this if there is no nested applications 38 | 39 | ``` 40 | sam deploy --region --template-file --stack-name --capabilities CAPABILITY_IAM 41 | ```` 42 | 43 | Example: 44 | ``` 45 | sam deploy --region us-east-1 --template-file packaged.yaml --stack-name learning-serverless-publish-sam-app --capabilities CAPABILITY_IAM 46 | ````` 47 | 48 | ## To clean up the application from your account 49 | 50 | ```` 51 | aws cloudformation delete-stack --region 52 | aws s3 rb s3:// --region 53 | ```` -------------------------------------------------------------------------------- /handler.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const databaseManager = require('./databaseManager'); 4 | const uuidv1 = require('uuid/v1'); 5 | 6 | exports.hello = async (event) => { 7 | console.log(event); 8 | 9 | switch (event.httpMethod) { 10 | case 'DELETE': 11 | return deleteItem(event); 12 | case 'GET': 13 | return getItem(event); 14 | case 'POST': 15 | return saveItem(event); 16 | case 'PUT': 17 | return updateItem(event); 18 | default: 19 | return sendResponse(404, `Unsupported method "${event.httpMethod}"`); 20 | } 21 | }; 22 | 23 | function saveItem(event) { 24 | const item = JSON.parse(event.body); 25 | item.itemId = uuidv1(); 26 | 27 | return databaseManager.saveItem(item).then(response => { 28 | console.log(response); 29 | return sendResponse(200, item.itemId); 30 | }); 31 | } 32 | 33 | function getItem(event) { 34 | const itemId = event.pathParameters.itemId; 35 | 36 | return databaseManager.getItem(itemId).then(response => { 37 | console.log(response); 38 | return sendResponse(200, JSON.stringify(response)); 39 | }); 40 | } 41 | 42 | function deleteItem(event) { 43 | const itemId = event.pathParameters.itemId; 44 | 45 | return databaseManager.deleteItem(itemId).then(response => { 46 | return sendResponse(200, 'DELETE ITEM'); 47 | }); 48 | } 49 | 50 | function updateItem(event) { 51 | const itemId = event.pathParameters.itemId; 52 | 53 | const body = JSON.parse(event.body); 54 | const paramName = body.paramName; 55 | const paramValue = body.paramValue; 56 | 57 | return databaseManager.updateItem(itemId, paramName, paramValue).then(response => { 58 | console.log(response); 59 | return sendResponse(200, JSON.stringify(response)); 60 | }); 61 | } 62 | 63 | function sendResponse(statusCode, message) { 64 | const response = { 65 | statusCode: statusCode, 66 | body: JSON.stringify(message) 67 | }; 68 | return response 69 | } 70 | --------------------------------------------------------------------------------