├── .gitignore ├── .stackery-config.yaml ├── README.md ├── src ├── createUser │ ├── .stackery-config.yaml │ ├── README.md │ ├── index.js │ └── package.json ├── deleteUser │ ├── .stackery-config.yaml │ ├── README.md │ ├── index.js │ └── package.json ├── getUser │ ├── .stackery-config.yaml │ ├── README.md │ ├── index.js │ └── package.json ├── listUsers │ ├── .stackery-config.yaml │ ├── README.md │ ├── index.js │ └── package.json └── updateUser │ ├── .stackery-config.yaml │ ├── README.md │ ├── index.js │ └── package.json └── template.yaml /.gitignore: -------------------------------------------------------------------------------- 1 | # local build directories 2 | .aws-sam 3 | .stackery 4 | 5 | # dependencies 6 | node_modules -------------------------------------------------------------------------------- /.stackery-config.yaml: -------------------------------------------------------------------------------- 1 | stack-name: sam-crud-demo 2 | template-path: template.yaml 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Stackery CRUD Demo - NodeJS 12.x 2 | 3 | This is a sample template for a serverless AWS Lambda application, written in JavaScript. 4 | 5 | The application implements a CRUD interface in front of an AWS DynamoDB table that 6 | manages a simple user record. An API Gateway distributes requests to the various 7 | AWS Lambda functions based on their HTTP paths and methods. 8 | 9 | The application architecture is defined in template.yaml, a Serverless 10 | Application Model (SAM) template which can be managed through the Stackery UI 11 | at app.stackery.io. 12 | 13 | Here is an overview of the files: 14 | 15 | ```text 16 | . 17 | ├── README.md <-- This README file 18 | ├── src <-- Source code dir for all AWS Lambda functions 19 | │   ├── createUser <-- Source code dir for createUser function 20 | │      ├── package.json <-- Build dependencies for createUser 21 | │      ├── .stackery-config.yaml <-- Default CLI parameters for this directory 22 | │      └── index.js <-- Lambda createUser function code 23 | │   ├── getUser <-- Source code dir for getUser function 24 | │      ├── package.json <-- Build dependencies for getUser 25 | │      ├── .stackery-config.yaml <-- Default CLI parameters for this directory 26 | │      └── index.js <-- Lambda getUser function code 27 | │   ├── updateUser <-- Source code dir for updateUser function 28 | │      ├── package.json <-- Build dependencies for updateUser 29 | │      ├── .stackery-config.yaml <-- Default CLI parameters for this directory 30 | │      └── index.js <-- Lambda updateUser function code 31 | │   ├── deleteUser <-- Source code dir for deleteUser function 32 | │      ├── package.json <-- Build dependencies for deleteUser 33 | │      ├── .stackery-config.yaml <-- Default CLI parameters for this directory 34 | │      └── index.js <-- Lambda deleteUser function code 35 | │   └── listUsers <-- Source code dir for listUsers function 36 | │      ├── package.json <-- Build dependencies for listUsers 37 | │      ├── .stackery-config.yaml <-- Default CLI parameters for this directory 38 | │      └── index.js <-- Lambda listUsers function code 39 | ├── .stackery-config.yaml <-- Default CLI parameters for root directory 40 | └── template.yaml <-- SAM infrastructure-as-code template 41 | ``` 42 | 43 | Clone this stack in Stackery, deploy it, and test as follows: 44 | 45 | - Set `STAGE_LOCATION` from the deployed Rest Api resource properties. 46 | 47 | - Create a user: 48 | 49 | curl --header "Content-Type: application/json" \ 50 | --request POST \ 51 | --data '{"id": "unique001", "firstName": "Alice", "lastName": "Smith", "color": "blue"}' \ 52 | ${STAGE_LOCATION}/users 53 | 54 | - List users: 55 | 56 | curl ${STAGE_LOCATION}/users 57 | 58 | - Read a user: 59 | 60 | curl ${STAGE_LOCATION}/users/unique001 61 | 62 | - Update a user: 63 | 64 | curl --header "Content-Type: application/json" \ 65 | --request PUT \ 66 | --data '{"firstName": "Alice", "lastName": "Smith", "color": "green"}' \ 67 | ${STAGE_LOCATION}/users/unique001 68 | 69 | - Delete a user: 70 | 71 | curl --request DELETE ${STAGE_LOCATION}/users/unique001 72 | -------------------------------------------------------------------------------- /src/createUser/.stackery-config.yaml: -------------------------------------------------------------------------------- 1 | function-id: createUser 2 | template-path: ../../template.yaml -------------------------------------------------------------------------------- /src/createUser/README.md: -------------------------------------------------------------------------------- 1 | 2 | This Stackery function node was generated by [Stackery.io](https://www.stackery.io). 3 | 4 | We recommend updating this readme with your own function specific documentation. 5 | 6 | # Dependencies 7 | You can add dependencies on other files and packages. 8 | Within this directory, local dependencies can be added as individual files and 9 | package dependencies can be added to [package.json](https://docs.npmjs.com/files/package.json). 10 | Package dependencies will be installed when the stack is deployed. 11 | 12 | # Stackery Documentation 13 | Documentation for Stackery function nodes can be found at [https://docs.stackery.io/nodes/Function/](https://docs.stackery.io/nodes/Function/). 14 | -------------------------------------------------------------------------------- /src/createUser/index.js: -------------------------------------------------------------------------------- 1 | const AWS = require('aws-sdk'); 2 | var dynamodb = new AWS.DynamoDB() 3 | 4 | exports.handler = async message => { 5 | console.log(message); 6 | 7 | if (message.body) { 8 | let user = JSON.parse(message.body); 9 | let params = { 10 | TableName: process.env.TABLE_NAME, 11 | Item: { 12 | id: { S: user.id }, 13 | FirstName: { S: user.firstName }, 14 | LastName: { S: user.lastName }, 15 | FavoriteColor: { S: user.color } 16 | } 17 | }; 18 | 19 | console.log(`Adding user to table ${process.env.TABLE_NAME}`); 20 | await dynamodb.putItem(params).promise() 21 | console.log(`User added to table, done`); 22 | } 23 | 24 | return {}; 25 | } 26 | -------------------------------------------------------------------------------- /src/createUser/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "createuser", 3 | "version": "1.0.0", 4 | "private": true, 5 | "dependencies": { 6 | "aws-sdk": "~2" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/deleteUser/.stackery-config.yaml: -------------------------------------------------------------------------------- 1 | function-id: deleteUser 2 | template-path: ../../template.yaml -------------------------------------------------------------------------------- /src/deleteUser/README.md: -------------------------------------------------------------------------------- 1 | 2 | This Stackery function node was generated by [Stackery.io](https://www.stackery.io). 3 | 4 | We recommend updating this readme with your own function specific documentation. 5 | 6 | # Dependencies 7 | You can add dependencies on other files and packages. 8 | Within this directory, local dependencies can be added as individual files and 9 | package dependencies can be added to [package.json](https://docs.npmjs.com/files/package.json). 10 | Package dependencies will be installed when the stack is deployed. 11 | 12 | # Stackery Documentation 13 | Documentation for Stackery function nodes can be found at [https://docs.stackery.io/nodes/Function/](https://docs.stackery.io/nodes/Function/). 14 | -------------------------------------------------------------------------------- /src/deleteUser/index.js: -------------------------------------------------------------------------------- 1 | const AWS = require('aws-sdk'); 2 | var dynamodb = new AWS.DynamoDB() 3 | 4 | exports.handler = async message => { 5 | console.log(message); 6 | let userId = message.pathParameters.id 7 | let params = { 8 | TableName: process.env.TABLE_NAME, 9 | Key: { 10 | id: { S: userId } 11 | } 12 | }; 13 | 14 | console.log(`Deleting user ${userId} from table ${process.env.TABLE_NAME}`); 15 | let results = await dynamodb.deleteItem(params).promise() 16 | console.log(`Done: ${JSON.stringify(results)}`); 17 | 18 | return { 19 | statusCode: 204, 20 | headers: {}, 21 | body: JSON.stringify({}) 22 | }; 23 | } 24 | -------------------------------------------------------------------------------- /src/deleteUser/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "deleteuser", 3 | "version": "1.0.0", 4 | "private": true, 5 | "dependencies": { 6 | "aws-sdk": "~2" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/getUser/.stackery-config.yaml: -------------------------------------------------------------------------------- 1 | function-id: getUser 2 | template-path: ../../template.yaml -------------------------------------------------------------------------------- /src/getUser/README.md: -------------------------------------------------------------------------------- 1 | 2 | This Stackery function node was generated by [Stackery.io](https://www.stackery.io). 3 | 4 | We recommend updating this readme with your own function specific documentation. 5 | 6 | # Dependencies 7 | You can add dependencies on other files and packages. 8 | Within this directory, local dependencies can be added as individual files and 9 | package dependencies can be added to [package.json](https://docs.npmjs.com/files/package.json). 10 | Package dependencies will be installed when the stack is deployed. 11 | 12 | # Stackery Documentation 13 | Documentation for Stackery function nodes can be found at [https://docs.stackery.io/nodes/Function/](https://docs.stackery.io/nodes/Function/). 14 | -------------------------------------------------------------------------------- /src/getUser/index.js: -------------------------------------------------------------------------------- 1 | const AWS = require('aws-sdk'); 2 | var dynamodb = new AWS.DynamoDB() 3 | 4 | exports.handler = async message => { 5 | console.log(message); 6 | let userId = message.pathParameters.id 7 | let params = { 8 | TableName: process.env.TABLE_NAME, 9 | Key: { 10 | id: { S: userId } 11 | } 12 | }; 13 | 14 | console.log(`Getting user ${userId} from table ${process.env.TABLE_NAME}`); 15 | let results = await dynamodb.getItem(params).promise() 16 | console.log(`Done: ${JSON.stringify(results)}`); 17 | 18 | return { 19 | statusCode: 200, 20 | headers: {}, 21 | body: JSON.stringify(results.Item) 22 | }; 23 | } 24 | -------------------------------------------------------------------------------- /src/getUser/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "getuser", 3 | "version": "1.0.0", 4 | "private": true, 5 | "dependencies": { 6 | "aws-sdk": "~2" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/listUsers/.stackery-config.yaml: -------------------------------------------------------------------------------- 1 | function-id: listUsers 2 | template-path: ../../template.yaml -------------------------------------------------------------------------------- /src/listUsers/README.md: -------------------------------------------------------------------------------- 1 | 2 | This Stackery function node was generated by [Stackery.io](https://www.stackery.io). 3 | 4 | We recommend updating this readme with your own function specific documentation. 5 | 6 | # Dependencies 7 | You can add dependencies on other files and packages. 8 | Within this directory, local dependencies can be added as individual files and 9 | package dependencies can be added to [package.json](https://docs.npmjs.com/files/package.json). 10 | Package dependencies will be installed when the stack is deployed. 11 | 12 | # Stackery Documentation 13 | Documentation for Stackery function nodes can be found at [https://docs.stackery.io/nodes/Function/](https://docs.stackery.io/nodes/Function/). 14 | -------------------------------------------------------------------------------- /src/listUsers/index.js: -------------------------------------------------------------------------------- 1 | const AWS = require('aws-sdk'); 2 | var dynamodb = new AWS.DynamoDB() 3 | 4 | exports.handler = async message => { 5 | console.log(message); 6 | 7 | let params = { 8 | TableName: process.env.TABLE_NAME, 9 | Select: 'ALL_ATTRIBUTES' 10 | }; 11 | 12 | console.log(`Getting all users from table ${process.env.TABLE_NAME}`); 13 | let results = await dynamodb.scan(params).promise() 14 | console.log(`Done: ${JSON.stringify(results)}`); 15 | 16 | return { 17 | statusCode: 200, 18 | headers: {}, 19 | body: JSON.stringify(results.Items) 20 | }; 21 | } 22 | -------------------------------------------------------------------------------- /src/listUsers/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "listusers", 3 | "version": "1.0.0", 4 | "private": true, 5 | "dependencies": { 6 | "aws-sdk": "~2" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/updateUser/.stackery-config.yaml: -------------------------------------------------------------------------------- 1 | function-id: udpateUser 2 | template-path: ../../template.yaml -------------------------------------------------------------------------------- /src/updateUser/README.md: -------------------------------------------------------------------------------- 1 | 2 | This Stackery function node was generated by [Stackery.io](https://www.stackery.io). 3 | 4 | We recommend updating this readme with your own function specific documentation. 5 | 6 | # Dependencies 7 | You can add dependencies on other files and packages. 8 | Within this directory, local dependencies can be added as individual files and 9 | package dependencies can be added to [package.json](https://docs.npmjs.com/files/package.json). 10 | Package dependencies will be installed when the stack is deployed. 11 | 12 | # Stackery Documentation 13 | Documentation for Stackery function nodes can be found at [https://docs.stackery.io/nodes/Function/](https://docs.stackery.io/nodes/Function/). 14 | -------------------------------------------------------------------------------- /src/updateUser/index.js: -------------------------------------------------------------------------------- 1 | const AWS = require('aws-sdk'); 2 | var dynamodb = new AWS.DynamoDB() 3 | 4 | exports.handler = async message => { 5 | console.log(message); 6 | 7 | if (message.body) { 8 | let userId = message.pathParameters.id 9 | let user = JSON.parse(message.body); 10 | let params = { 11 | TableName: process.env.TABLE_NAME, 12 | Item: { 13 | id: { S: userId }, 14 | FirstName: { S: user.firstName }, 15 | LastName: { S: user.lastName }, 16 | FavoriteColor: { S: user.color } 17 | } 18 | }; 19 | 20 | console.log(`Updating user ${userId} in table ${process.env.TABLE_NAME}`); 21 | await dynamodb.putItem(params).promise() 22 | console.log(`User added to table, done`); 23 | } 24 | 25 | return { 26 | statusCode: 204, 27 | headers: {}, 28 | body: JSON.stringify({}) 29 | }; 30 | } 31 | -------------------------------------------------------------------------------- /src/updateUser/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "updateuser", 3 | "version": "1.0.0", 4 | "private": true, 5 | "dependencies": { 6 | "aws-sdk": "~2" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /template.yaml: -------------------------------------------------------------------------------- 1 | AWSTemplateFormatVersion: 2010-09-09 2 | Transform: AWS::Serverless-2016-10-31 3 | Description: Stackery Serverless CRUD API Demo 4 | Resources: 5 | api: 6 | Type: AWS::Serverless::Api 7 | Properties: 8 | Name: !Sub 9 | - ${ResourceName} From Stackery Stack ${StackeryStackTagName} Environment ${StackeryEnvironmentTagName} 10 | - ResourceName: /users 11 | StageName: !Ref StackeryEnvironmentAPIGatewayStageName 12 | DefinitionBody: 13 | swagger: '2.0' 14 | info: {} 15 | paths: 16 | /users: 17 | get: 18 | x-amazon-apigateway-integration: 19 | httpMethod: POST 20 | type: aws_proxy 21 | uri: !Sub arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${listUsers.Arn}/invocations 22 | responses: {} 23 | post: 24 | x-amazon-apigateway-integration: 25 | httpMethod: POST 26 | type: aws_proxy 27 | uri: !Sub arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${createUser.Arn}/invocations 28 | responses: {} 29 | /users/{id}: 30 | get: 31 | x-amazon-apigateway-integration: 32 | httpMethod: POST 33 | type: aws_proxy 34 | uri: !Sub arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${getUser.Arn}/invocations 35 | responses: {} 36 | put: 37 | x-amazon-apigateway-integration: 38 | httpMethod: POST 39 | type: aws_proxy 40 | uri: !Sub arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${updateUser.Arn}/invocations 41 | responses: {} 42 | delete: 43 | x-amazon-apigateway-integration: 44 | httpMethod: POST 45 | type: aws_proxy 46 | uri: !Sub arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${deleteUser.Arn}/invocations 47 | responses: {} 48 | EndpointConfiguration: REGIONAL 49 | Metadata: 50 | StackeryName: /users 51 | getUser: 52 | Type: AWS::Serverless::Function 53 | Properties: 54 | FunctionName: !Sub ${AWS::StackName}-getUser 55 | Description: !Sub 56 | - Stackery Stack ${StackeryStackTagName} Environment ${StackeryEnvironmentTagName} Function ${ResourceName} 57 | - ResourceName: getUser 58 | CodeUri: src/getUser 59 | Handler: index.handler 60 | Runtime: nodejs12.x 61 | MemorySize: 3008 62 | Timeout: 30 63 | Tracing: Active 64 | Policies: 65 | - AWSXrayWriteOnlyAccess 66 | - DynamoDBCrudPolicy: 67 | TableName: !Ref usersTable 68 | Environment: 69 | Variables: 70 | TABLE_NAME: !Ref usersTable 71 | TABLE_ARN: !GetAtt usersTable.Arn 72 | Events: 73 | apiGETusersid: 74 | Type: Api 75 | Properties: 76 | Path: /users/{id} 77 | Method: GET 78 | RestApiId: !Ref api 79 | Metadata: 80 | StackeryName: getUser 81 | updateUser: 82 | Type: AWS::Serverless::Function 83 | Properties: 84 | FunctionName: !Sub ${AWS::StackName}-updateUser 85 | Description: !Sub 86 | - Stackery Stack ${StackeryStackTagName} Environment ${StackeryEnvironmentTagName} Function ${ResourceName} 87 | - ResourceName: updateUser 88 | CodeUri: src/updateUser 89 | Handler: index.handler 90 | Runtime: nodejs12.x 91 | MemorySize: 3008 92 | Timeout: 30 93 | Tracing: Active 94 | Policies: 95 | - AWSXrayWriteOnlyAccess 96 | - DynamoDBCrudPolicy: 97 | TableName: !Ref usersTable 98 | Environment: 99 | Variables: 100 | TABLE_NAME: !Ref usersTable 101 | TABLE_ARN: !GetAtt usersTable.Arn 102 | Events: 103 | apiPUTusersid: 104 | Type: Api 105 | Properties: 106 | Path: /users/{id} 107 | Method: PUT 108 | RestApiId: !Ref api 109 | Metadata: 110 | StackeryName: updateUser 111 | createUser: 112 | Type: AWS::Serverless::Function 113 | Properties: 114 | FunctionName: !Sub ${AWS::StackName}-createUser 115 | Description: !Sub 116 | - Stackery Stack ${StackeryStackTagName} Environment ${StackeryEnvironmentTagName} Function ${ResourceName} 117 | - ResourceName: createUser 118 | CodeUri: src/createUser 119 | Handler: index.handler 120 | Runtime: nodejs12.x 121 | MemorySize: 3008 122 | Timeout: 30 123 | Tracing: Active 124 | Policies: 125 | - AWSXrayWriteOnlyAccess 126 | - DynamoDBCrudPolicy: 127 | TableName: !Ref usersTable 128 | Environment: 129 | Variables: 130 | TABLE_NAME: !Ref usersTable 131 | TABLE_ARN: !GetAtt usersTable.Arn 132 | Events: 133 | apiPOSTusers: 134 | Type: Api 135 | Properties: 136 | Path: /users 137 | Method: POST 138 | RestApiId: !Ref api 139 | Metadata: 140 | StackeryName: createUser 141 | deleteUser: 142 | Type: AWS::Serverless::Function 143 | Properties: 144 | FunctionName: !Sub ${AWS::StackName}-deleteUser 145 | Description: !Sub 146 | - Stackery Stack ${StackeryStackTagName} Environment ${StackeryEnvironmentTagName} Function ${ResourceName} 147 | - ResourceName: deleteUser 148 | CodeUri: src/deleteUser 149 | Handler: index.handler 150 | Runtime: nodejs12.x 151 | MemorySize: 3008 152 | Timeout: 30 153 | Tracing: Active 154 | Policies: 155 | - AWSXrayWriteOnlyAccess 156 | - DynamoDBCrudPolicy: 157 | TableName: !Ref usersTable 158 | Environment: 159 | Variables: 160 | TABLE_NAME: !Ref usersTable 161 | TABLE_ARN: !GetAtt usersTable.Arn 162 | Events: 163 | apiDELETEusersid: 164 | Type: Api 165 | Properties: 166 | Path: /users/{id} 167 | Method: DELETE 168 | RestApiId: !Ref api 169 | Metadata: 170 | StackeryName: deleteUser 171 | listUsers: 172 | Type: AWS::Serverless::Function 173 | Properties: 174 | FunctionName: !Sub ${AWS::StackName}-listUsers 175 | Description: !Sub 176 | - Stackery Stack ${StackeryStackTagName} Environment ${StackeryEnvironmentTagName} Function ${ResourceName} 177 | - ResourceName: listUsers 178 | CodeUri: src/listUsers 179 | Handler: index.handler 180 | Runtime: nodejs12.x 181 | MemorySize: 3008 182 | Timeout: 30 183 | Tracing: Active 184 | Policies: 185 | - AWSXrayWriteOnlyAccess 186 | - DynamoDBCrudPolicy: 187 | TableName: !Ref usersTable 188 | Environment: 189 | Variables: 190 | TABLE_NAME: !Ref usersTable 191 | TABLE_ARN: !GetAtt usersTable.Arn 192 | Events: 193 | apiGETusers: 194 | Type: Api 195 | Properties: 196 | Path: /users 197 | Method: GET 198 | RestApiId: !Ref api 199 | Metadata: 200 | StackeryName: listUsers 201 | usersTable: 202 | Type: AWS::DynamoDB::Table 203 | Properties: 204 | AttributeDefinitions: 205 | - AttributeName: id 206 | AttributeType: S 207 | KeySchema: 208 | - AttributeName: id 209 | KeyType: HASH 210 | ProvisionedThroughput: 211 | ReadCapacityUnits: 5 212 | WriteCapacityUnits: 5 213 | StreamSpecification: 214 | StreamViewType: NEW_AND_OLD_IMAGES 215 | TableName: !Sub ${AWS::StackName}-usersTable 216 | Metadata: 217 | StackeryName: Users 218 | Parameters: 219 | StackeryStackTagName: 220 | Type: String 221 | Description: Stack Name (injected by Stackery at deployment time) 222 | StackeryEnvironmentTagName: 223 | Type: String 224 | Description: Environment Name (injected by Stackery at deployment time) 225 | StackeryEnvironmentAPIGatewayStageName: 226 | Type: String 227 | Description: Environment name used for API Gateway Stage names (injected by Stackery at deployment time) --------------------------------------------------------------------------------