From 12e54150c19a4776c4ca9176276e0e07dbed4b67 Mon Sep 17 00:00:00 2001 From: ac360 Date: Tue, 5 May 2020 10:47:00 -0700 Subject: [PATCH 01/34] remove unnecessary loading views --- README.md | 1 - site/src/pages/Auth/Auth.js | 28 +++++----------------------- 2 files changed, 5 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index 233b24d..22d9640 100644 --- a/README.md +++ b/README.md @@ -77,5 +77,4 @@ And deploy! `serverless deploy --stage prod` - Enjoy! This is a work in progress and we will continue to add funcitonality to this. diff --git a/site/src/pages/Auth/Auth.js b/site/src/pages/Auth/Auth.js index d968244..a794acf 100644 --- a/site/src/pages/Auth/Auth.js +++ b/site/src/pages/Auth/Auth.js @@ -108,14 +108,6 @@ class Auth extends Component { window.location.replace('/') } - renderLoading() { - return ( -
- { < Loading className={styles.containerLoading} /> } -
- ) - } - render() { return ( @@ -190,21 +182,11 @@ class Auth extends Component {
{this.state.formError}
)} - - { this.state.loading ? ( - - ) : ( - - )} + From 4f08e8493f1235ecbd6f00c54054cf2f3d493f71 Mon Sep 17 00:00:00 2001 From: ac360 Date: Tue, 5 May 2020 10:58:18 -0700 Subject: [PATCH 02/34] add links to other resources --- README.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/README.md b/README.md index 22d9640..797f06c 100644 --- a/README.md +++ b/README.md @@ -78,3 +78,13 @@ And deploy! `serverless deploy --stage prod` Enjoy! This is a work in progress and we will continue to add funcitonality to this. + +## Other Resources + +For more details on each part of this fullstack application, check out these resources: + +* [Serverless Components](https://github.com/serverless/components) +* [Serverless Express](https://github.com/serverless-components/express) +* [Serverless Website](https://github.com/serverless-components/website) +* [Serverless AWS DynamoDB](https://github.com/serverless-components/aws-dynamodb) +* [Serverless AWS IAM Role](https://github.com/serverless-components/aws-iam-role) \ No newline at end of file From 9fc52c1fa94e3413c4df6286b3c631afd888ea72 Mon Sep 17 00:00:00 2001 From: Austen Date: Wed, 6 May 2020 22:54:06 -0700 Subject: [PATCH 03/34] Update README.md --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 797f06c..7bfbfad 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,8 @@ A complete, serverless, full-stack application built on AWS Lambda, AWS HTTP API ## Quick Start +Clone this repo. + Run `npm i` in all subdirectories that contain `package.json` Add your AWS credentials in `.env` file in the root directory, like this: @@ -87,4 +89,4 @@ For more details on each part of this fullstack application, check out these res * [Serverless Express](https://github.com/serverless-components/express) * [Serverless Website](https://github.com/serverless-components/website) * [Serverless AWS DynamoDB](https://github.com/serverless-components/aws-dynamodb) -* [Serverless AWS IAM Role](https://github.com/serverless-components/aws-iam-role) \ No newline at end of file +* [Serverless AWS IAM Role](https://github.com/serverless-components/aws-iam-role) From e069201e0e5fcdf59d53244c5426c7025c229f8e Mon Sep 17 00:00:00 2001 From: ac360 Date: Thu, 7 May 2020 19:13:07 -0700 Subject: [PATCH 04/34] updated express, comment out domain --- api/app.js | 3 ++- api/config/passport.js | 2 +- api/serverless.yml | 4 ++-- site/serverless.yml | 2 +- site/src/pages/Auth/Auth.js | 2 +- 5 files changed, 7 insertions(+), 6 deletions(-) diff --git a/api/app.js b/api/app.js index f5c9c63..c7d4363 100644 --- a/api/app.js +++ b/api/app.js @@ -43,7 +43,8 @@ app.post(`/users/login`, users.login) app.post(`/user`, passport.authenticate('jwt', { session: false }), users.get) app.get(`/test`, (req, res) => { - res.status(200).send('Request received') + console.log('this is a real-time streaming log') + res.status(200).send('Route updated') }) app.get(`/*`, (req, res) => { diff --git a/api/config/passport.js b/api/config/passport.js index 000253b..a6c7120 100644 --- a/api/config/passport.js +++ b/api/config/passport.js @@ -20,7 +20,7 @@ module.exports = (passport) => { console.log(error) return done(error, null) } - console.log(user) + if (!user) { return done(null, false) } return done(null, user) })) diff --git a/api/serverless.yml b/api/serverless.yml index 6b8b152..2053734 100644 --- a/api/serverless.yml +++ b/api/serverless.yml @@ -1,11 +1,11 @@ app: fullstack -component: express@1.0.5 +component: express@1.0.8 name: fullstack-api inputs: src: ./ roleName: ${output:fullstack-permissions.name} - domain: api.${env:domain} + # domain: api.${env:domain} Uncomment this when you want to use a custom domain env: db: ${output:fullstack-db.name} dbIndex1: ${output:fullstack-db.indexes.gsi1.name} diff --git a/site/serverless.yml b/site/serverless.yml index d6cc09d..31fd107 100644 --- a/site/serverless.yml +++ b/site/serverless.yml @@ -7,4 +7,4 @@ inputs: src: ./ hook: npm run build dist: build - domain: ${env:domain} \ No newline at end of file + # domain: ${env:domain} Uncomment this when you want to use a custom domain \ No newline at end of file diff --git a/site/src/pages/Auth/Auth.js b/site/src/pages/Auth/Auth.js index a794acf..1ee273a 100644 --- a/site/src/pages/Auth/Auth.js +++ b/site/src/pages/Auth/Auth.js @@ -185,7 +185,7 @@ class Auth extends Component { From f78c9416d0bd0d55c24551cefd2e743b93db253d Mon Sep 17 00:00:00 2001 From: ac360 Date: Thu, 7 May 2020 19:13:54 -0700 Subject: [PATCH 05/34] update express --- api/serverless.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/serverless.yml b/api/serverless.yml index 6b8b152..69a94b2 100644 --- a/api/serverless.yml +++ b/api/serverless.yml @@ -1,5 +1,5 @@ app: fullstack -component: express@1.0.5 +component: express@1.0.8 name: fullstack-api inputs: From 68cd9f08b49ce8f445b0de6e46864ff0d849d913 Mon Sep 17 00:00:00 2001 From: ac360 Date: Thu, 7 May 2020 19:46:48 -0700 Subject: [PATCH 06/34] improve readme --- README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/README.md b/README.md index 7bfbfad..6669e15 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,13 @@ domain=serverless-fullstack-app.com In the root folder of the project, run `serverless deploy --all` +Lastly, you will need to update the URL in the `site` so that you interact with the correct API endpoint. Take the `/api` `url` and put it in the site React app [here](./site/index.js). + +Note: Upon the first deployment of your website, it will take a 2-3 minutes for the Cloudfront (CDN) URL to work. Until then, you can access it via the `bucketUrl`. + + + + After initial deployment, we recommend deploying only the parts you are changing, not the entire thing together (why risk deploying your database with a code change?). To do this, `cd` into a part of the application and run `serverless deploy`. When working on the `./api` we highly recommend using `serverless dev`. This command watches your code, auto-deploys it, and streams `console.log()` statements and errors directly to your CLI in real-time! From 9c839c79cab8ef81aa4432e1349c0fe9231ee206 Mon Sep 17 00:00:00 2001 From: ac360 Date: Wed, 20 May 2020 10:14:26 -0700 Subject: [PATCH 07/34] minor tweaks --- site/src/pages/Auth/Auth.js | 58 ++++++++++++++++++------------------- site/src/pages/Home/Home.js | 24 +++++++-------- 2 files changed, 41 insertions(+), 41 deletions(-) diff --git a/site/src/pages/Auth/Auth.js b/site/src/pages/Auth/Auth.js index a794acf..c9e10e0 100644 --- a/site/src/pages/Auth/Auth.js +++ b/site/src/pages/Auth/Auth.js @@ -5,9 +5,9 @@ import { } from 'react-router-dom' import Loading from '../../fragments/Loading' import styles from './Auth.module.css' -import { +import { userRegister, - userLogin, + userLogin, userGet, saveSession, } from '../../utils' @@ -17,7 +17,7 @@ class Auth extends Component { constructor(props) { super(props) - const pathName = window.location.pathname.replace('/','') + const pathName = window.location.pathname.replace('/', '') this.state = {} this.state.state = pathName @@ -37,7 +37,7 @@ class Auth extends Component { */ componentDidMount() { this.setState({ - loading: false + loading: false }) // Clear query params @@ -49,7 +49,7 @@ class Auth extends Component { * Handles a form change */ handleFormTypeChange(type) { - this.setState({ state: type }, + this.setState({ state: type }, () => { this.props.history.push(`/${type}`) }) @@ -92,9 +92,9 @@ class Auth extends Component { if (error.message) { this.setState({ formError: error.message, loading: false }) } else { - this.setState({ - formError: 'Sorry, something unknown went wrong. Please try again.', - loading: false + this.setState({ + formError: 'Sorry, something unknown went wrong. Please try again.', + loading: false }) } return @@ -114,38 +114,38 @@ class Auth extends Component {
- { /* Logo */ } + { /* Logo */} - serverless-fullstack-application - { /* Loading */ } + { /* Loading */} - { this.state.loading && ( + {this.state.loading && (
- { < Loading className={styles.containerLoading} /> } + {< Loading className={styles.containerLoading} />}
)} - { /* Registration Form */ } - - { !this.state.loading && ( + { /* Registration Form */} + + {!this.state.loading && (
-
{ this.handleFormTypeChange('register') }}> Register
-
{ this.handleFormTypeChange('login') }}> Sign-In @@ -153,7 +153,7 @@ class Auth extends Component {
)} - { this.state.state === 'register' && !this.state.loading && ( + {this.state.state === 'register' && !this.state.loading && (
@@ -182,19 +182,19 @@ class Auth extends Component {
{this.state.formError}
)} -
)} - { this.state.state === 'login' && !this.state.loading && ( + {this.state.state === 'login' && !this.state.loading && (
- +
diff --git a/site/src/pages/Home/Home.js b/site/src/pages/Home/Home.js index 8e4cd4a..a9675d7 100644 --- a/site/src/pages/Home/Home.js +++ b/site/src/pages/Home/Home.js @@ -1,7 +1,7 @@ import React, { Component } from 'react' -import { +import { Link, - withRouter + withRouter } from 'react-router-dom' import styles from './Home.module.css' @@ -12,7 +12,7 @@ class Home extends Component { this.state = {} } - async componentDidMount() {} + async componentDidMount() { } render() { @@ -20,30 +20,30 @@ class Home extends Component {
- { /* Hero Artwork */ } + { /* Hero Artwork */}
- serverless-fullstack-application
- serverless-fullstack-application
- { /* Hero Description */ } + { /* Hero Description */}
A serverless full-stack application built with AWS Lambda, AWS HTTP API, Express.js, React & AWS DynamoDB.
- { /* Call To Action */ } + { /* Call To Action */}
From 62c50f06846f700b9c8b4e034bc69e076b3c65af Mon Sep 17 00:00:00 2001 From: mileswright Date: Wed, 24 Jun 2020 14:04:11 -0600 Subject: [PATCH 08/34] Update README.md API path when using localhost --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6669e15..3ca9a7a 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ domain=serverless-fullstack-app.com In the root folder of the project, run `serverless deploy --all` -Lastly, you will need to update the URL in the `site` so that you interact with the correct API endpoint. Take the `/api` `url` and put it in the site React app [here](./site/index.js). +Lastly, you will need to update the URL in the `site` so that you interact with the correct API endpoint. Take the `/api` `url` and put it in the site React app [here](./site/src/index.js). Note: Upon the first deployment of your website, it will take a 2-3 minutes for the Cloudfront (CDN) URL to work. Until then, you can access it via the `bucketUrl`. From 201575e8f300d6a2120ce8ee57bfc33c895a59c7 Mon Sep 17 00:00:00 2001 From: ac360 Date: Wed, 24 Jun 2020 17:36:57 -0700 Subject: [PATCH 09/34] add template file --- serverless.yml | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 serverless.yml diff --git a/serverless.yml b/serverless.yml new file mode 100644 index 0000000..6893801 --- /dev/null +++ b/serverless.yml @@ -0,0 +1,6 @@ +name: fullstack-app +org: serverlessinc +description: Deploy a serverless fullstack application using Express.js and React on AWS Lambda and AWS HTTP API +keywords: serverless, express, react, fullstack, aws, aws lambda +repo: https://github.com/serverless-components/fullstack-app +license: MIT \ No newline at end of file From 8312b240106adddb99f25f9bdd1909db8c69ee6c Mon Sep 17 00:00:00 2001 From: ac360 Date: Fri, 26 Jun 2020 16:29:37 -0700 Subject: [PATCH 10/34] improve comments and codebase --- api/app.js | 113 +++++++++++++++++++++++++++++++++--- api/serverless.yml | 5 +- site/serverless.yml | 2 +- site/src/pages/Auth/Auth.js | 9 +-- 4 files changed, 110 insertions(+), 19 deletions(-) diff --git a/api/app.js b/api/app.js index c7d4363..bc8432e 100644 --- a/api/app.js +++ b/api/app.js @@ -5,15 +5,28 @@ const { users } = require('./controllers') -// Configure Passport -require('./config/passport')(passport) +/** + * Inference: + * + * When "inference" in serverless.yml is "true", the Serverless Framework will attempt to + * initialize this application on every deployment, extract its endpoints and generate an OpenAPI specification (super cool) + * However, the Framework won't have access to the environment variables, causing some things to crash on load. + * That is why some things have try/catch blocks around them when they are required. + */ + +/** + * Configure Passport + */ + +try { require('./config/passport')(passport) } +catch (error) { console.log(error) } /** * Configure Express.js Middleware */ // Enable CORS -app.use(function(req, res, next) { +app.use(function (req, res, next) { res.header('Access-Control-Allow-Origin', '*') res.header('Access-Control-Allow-Methods', '*') res.header('Access-Control-Allow-Headers', '*') @@ -29,7 +42,7 @@ app.use(passport.session()) app.use(express.json()) /** - * Routes + * Routes - Public */ app.options(`*`, (req, res) => { @@ -40,13 +53,20 @@ app.post(`/users/register`, users.register) app.post(`/users/login`, users.login) -app.post(`/user`, passport.authenticate('jwt', { session: false }), users.get) - -app.get(`/test`, (req, res) => { - console.log('this is a real-time streaming log') +app.get(`/test/`, (req, res) => { res.status(200).send('Route updated') }) +/** + * Routes - Protected + */ + +app.post(`/user`, passport.authenticate('jwt', { session: false }), users.get) + +/** + * Routes - Catch-All + */ + app.get(`/*`, (req, res) => { res.status(404).send('Route not found') }) @@ -59,4 +79,81 @@ app.use(function (err, req, res, next) { res.status(500).send('Internal Serverless Error') }) +/** + * OpenAPI Auto-Generation + */ + +const openApi = { + openapi: '3.0.3', + info: { + title: null, + description: null, + termsOfService: null, + contact: { + name: null, + url: null, + email: null + }, + license: { + name: null, + url: null + }, + version: '0.0.1' + }, + servers: { + url: null, + description: null, + variables: {} + }, + paths: {}, + components: { + schemas: {}, + responses: {}, + parameters: {}, + examples: {}, + requestBodies: {}, + headers: {}, + securitySchemes: {}, + links: {}, + callbacks: {} + }, + security: {}, + tags: {}, + externalDocs: {}, +} + +const openApiPathItem = { + description: null, + summary: null, + operationId: null, + responses: {} +} + +if (app && app._router && app._router.stack && app._router.stack.length) { + app._router.stack.forEach((route) => { + + // This array holds all middleware layers, which include routes and more + // First check if this 'layer' is an express route type, otherwise skip + if (!route.route) return + + // Define key data + const ePath = route.route.path + + if (['*', '/*'].indexOf(ePath) > -1) { + return + } + + // Save path + openApi.paths[ePath] = openApi.paths[ePath] || {} + + for (const method in route.route.methods) { + // Save method + openApi.paths[ePath][method] = openApiPathItem + } + }) +} + +console.log(openApi) + + module.exports = app \ No newline at end of file diff --git a/api/serverless.yml b/api/serverless.yml index 2053734..d04ff96 100644 --- a/api/serverless.yml +++ b/api/serverless.yml @@ -1,11 +1,12 @@ app: fullstack -component: express@1.0.8 +component: express@1.1.0 name: fullstack-api inputs: src: ./ roleName: ${output:fullstack-permissions.name} - # domain: api.${env:domain} Uncomment this when you want to use a custom domain + domain: api.${env:domain} + inference: true env: db: ${output:fullstack-db.name} dbIndex1: ${output:fullstack-db.indexes.gsi1.name} diff --git a/site/serverless.yml b/site/serverless.yml index 31fd107..d6cc09d 100644 --- a/site/serverless.yml +++ b/site/serverless.yml @@ -7,4 +7,4 @@ inputs: src: ./ hook: npm run build dist: build - # domain: ${env:domain} Uncomment this when you want to use a custom domain \ No newline at end of file + domain: ${env:domain} \ No newline at end of file diff --git a/site/src/pages/Auth/Auth.js b/site/src/pages/Auth/Auth.js index 9835fa5..c9abe56 100644 --- a/site/src/pages/Auth/Auth.js +++ b/site/src/pages/Auth/Auth.js @@ -182,17 +182,10 @@ class Auth extends Component {
{this.state.formError}
)} -<<<<<<< HEAD >>>>>> master + value='Register' /> From 86d8d0efc933ad38e3a294fa76ed12b9d8f0462e Mon Sep 17 00:00:00 2001 From: ac360 Date: Fri, 26 Jun 2020 16:38:38 -0700 Subject: [PATCH 11/34] add helpful comments and more --- api/serverless.yml | 10 +++++++++- database/serverless.yml | 1 + permissions/serverless.yml | 4 ++-- site/serverless.yml | 4 +++- 4 files changed, 15 insertions(+), 4 deletions(-) diff --git a/api/serverless.yml b/api/serverless.yml index d04ff96..1bbed5e 100644 --- a/api/serverless.yml +++ b/api/serverless.yml @@ -3,11 +3,19 @@ component: express@1.1.0 name: fullstack-api inputs: + # Express application source code. src: ./ + # Permissions required for the AWS Lambda function to interact with other resources roleName: ${output:fullstack-permissions.name} - domain: api.${env:domain} + # Enable this when you want to set a custom domain. + # domain: api.${env:domain} + # Leaving this on auto-generates an OpenAPI spec each time this is deployed. inference: true + # Environment variables env: + # AWS DynamoDB Table name. Needed for the code to access it. db: ${output:fullstack-db.name} + # AWS DynamoDB Table Index name. Needed for the code to access it. dbIndex1: ${output:fullstack-db.indexes.gsi1.name} + # A secret token to sign the JWT tokens with. tokenSecret: ${env:tokenSecret} \ No newline at end of file diff --git a/database/serverless.yml b/database/serverless.yml index 538b317..60b10d8 100644 --- a/database/serverless.yml +++ b/database/serverless.yml @@ -5,6 +5,7 @@ name: fullstack-db inputs: name: ${name}-${stage} region: us-east-1 + # Don't delete the Database Table if "serverless remove" is run deletionPolicy: retain attributeDefinitions: - AttributeName: hk diff --git a/permissions/serverless.yml b/permissions/serverless.yml index 034534b..8e51eaa 100644 --- a/permissions/serverless.yml +++ b/permissions/serverless.yml @@ -7,7 +7,7 @@ inputs: region: us-east-1 service: lambda.amazonaws.com policy: - # Marketing API Logs and Assume Role access + # AWS Lambda function containing Express Logs and Assume Role access - Effect: Allow Action: - sts:AssumeRole @@ -15,7 +15,7 @@ inputs: - logs:CreateLogStream - logs:PutLogEvents Resource: '*' - # Marketing Database access + # AWS DynamoDB Table access - Effect: Allow Action: - dynamodb:DescribeTable diff --git a/site/serverless.yml b/site/serverless.yml index d6cc09d..d61d115 100644 --- a/site/serverless.yml +++ b/site/serverless.yml @@ -3,8 +3,10 @@ component: website@1.0.0 name: fullstack-site inputs: + # React application. "hook" runs before deployment to build the source code. "dist" is the built artifact directory which is uploaded. src: src: ./ hook: npm run build dist: build - domain: ${env:domain} \ No newline at end of file + # Enable this when you want to set a custom domain. + # domain: ${env:domain} \ No newline at end of file From a93d45d8f2d46c4f6b694cf1b5a202d185aea5a3 Mon Sep 17 00:00:00 2001 From: ac360 Date: Wed, 1 Jul 2020 01:07:08 -0700 Subject: [PATCH 12/34] update express component to enable metrics in the new dashboard --- api/app.js | 77 ---------------------------------------------- api/serverless.yml | 2 +- site/src/index.js | 3 +- 3 files changed, 3 insertions(+), 79 deletions(-) diff --git a/api/app.js b/api/app.js index bc8432e..babcb48 100644 --- a/api/app.js +++ b/api/app.js @@ -79,81 +79,4 @@ app.use(function (err, req, res, next) { res.status(500).send('Internal Serverless Error') }) -/** - * OpenAPI Auto-Generation - */ - -const openApi = { - openapi: '3.0.3', - info: { - title: null, - description: null, - termsOfService: null, - contact: { - name: null, - url: null, - email: null - }, - license: { - name: null, - url: null - }, - version: '0.0.1' - }, - servers: { - url: null, - description: null, - variables: {} - }, - paths: {}, - components: { - schemas: {}, - responses: {}, - parameters: {}, - examples: {}, - requestBodies: {}, - headers: {}, - securitySchemes: {}, - links: {}, - callbacks: {} - }, - security: {}, - tags: {}, - externalDocs: {}, -} - -const openApiPathItem = { - description: null, - summary: null, - operationId: null, - responses: {} -} - -if (app && app._router && app._router.stack && app._router.stack.length) { - app._router.stack.forEach((route) => { - - // This array holds all middleware layers, which include routes and more - // First check if this 'layer' is an express route type, otherwise skip - if (!route.route) return - - // Define key data - const ePath = route.route.path - - if (['*', '/*'].indexOf(ePath) > -1) { - return - } - - // Save path - openApi.paths[ePath] = openApi.paths[ePath] || {} - - for (const method in route.route.methods) { - // Save method - openApi.paths[ePath][method] = openApiPathItem - } - }) -} - -console.log(openApi) - - module.exports = app \ No newline at end of file diff --git a/api/serverless.yml b/api/serverless.yml index 1bbed5e..80a57f1 100644 --- a/api/serverless.yml +++ b/api/serverless.yml @@ -1,5 +1,5 @@ app: fullstack -component: express@1.1.0 +component: express@1.2.0 name: fullstack-api inputs: diff --git a/site/src/index.js b/site/src/index.js index 6254ac6..88699fe 100644 --- a/site/src/index.js +++ b/site/src/index.js @@ -10,7 +10,8 @@ import './index.css' window.serverless = {} window.serverless.urls = {} if (window.location.host.includes('localhost:')) { - window.serverless.urls.api = `https://api.serverless-fullstack-app-dev.com` + console.log('here') + window.serverless.urls.api = `https://5xm2qt2k4m.execute-api.us-east-1.amazonaws.com` } else { window.serverless.root = window.location.hostname.replace('www.', '') window.serverless.urls.api = `https://api.${window.serverless.root}` From d5822aa0b1c6193dda227a3104a40da54f89a726 Mon Sep 17 00:00:00 2001 From: ac360 Date: Wed, 1 Jul 2020 16:26:23 -0700 Subject: [PATCH 13/34] simplify names --- api/serverless.yml | 10 +++++----- database/serverless.yml | 2 +- permissions/serverless.yml | 2 +- site/serverless.yml | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/api/serverless.yml b/api/serverless.yml index 80a57f1..465e4e3 100644 --- a/api/serverless.yml +++ b/api/serverless.yml @@ -1,12 +1,12 @@ app: fullstack -component: express@1.2.0 -name: fullstack-api +component: express@1.2.1 +name: api inputs: # Express application source code. src: ./ # Permissions required for the AWS Lambda function to interact with other resources - roleName: ${output:fullstack-permissions.name} + roleName: ${output:permissions.name} # Enable this when you want to set a custom domain. # domain: api.${env:domain} # Leaving this on auto-generates an OpenAPI spec each time this is deployed. @@ -14,8 +14,8 @@ inputs: # Environment variables env: # AWS DynamoDB Table name. Needed for the code to access it. - db: ${output:fullstack-db.name} + db: ${output:database.name} # AWS DynamoDB Table Index name. Needed for the code to access it. - dbIndex1: ${output:fullstack-db.indexes.gsi1.name} + dbIndex1: ${output:database.indexes.gsi1.name} # A secret token to sign the JWT tokens with. tokenSecret: ${env:tokenSecret} \ No newline at end of file diff --git a/database/serverless.yml b/database/serverless.yml index 60b10d8..31b205b 100644 --- a/database/serverless.yml +++ b/database/serverless.yml @@ -1,6 +1,6 @@ app: fullstack component: aws-dynamodb@1.1.1 -name: fullstack-db +name: database inputs: name: ${name}-${stage} diff --git a/permissions/serverless.yml b/permissions/serverless.yml index 8e51eaa..6f4bd66 100644 --- a/permissions/serverless.yml +++ b/permissions/serverless.yml @@ -1,6 +1,6 @@ app: fullstack component: aws-iam-role@2.0.0 -name: fullstack-permissions +name: permissions inputs: name: ${name}-${stage} diff --git a/site/serverless.yml b/site/serverless.yml index d61d115..40db46e 100644 --- a/site/serverless.yml +++ b/site/serverless.yml @@ -1,6 +1,6 @@ app: fullstack component: website@1.0.0 -name: fullstack-site +name: site inputs: # React application. "hook" runs before deployment to build the source code. "dist" is the built artifact directory which is uploaded. From 913e846923004d7be7dcaf2244ce36aee2ace882 Mon Sep 17 00:00:00 2001 From: ac360 Date: Thu, 2 Jul 2020 00:24:30 -0700 Subject: [PATCH 14/34] simplify names --- permissions/serverless.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/permissions/serverless.yml b/permissions/serverless.yml index 6f4bd66..f5ecb27 100644 --- a/permissions/serverless.yml +++ b/permissions/serverless.yml @@ -25,5 +25,5 @@ inputs: - dynamodb:UpdateItem - dynamodb:DeleteItem Resource: - - ${output:fullstack-db.arn} - - ${output:fullstack-db.arn}/index/* \ No newline at end of file + - ${output:database.arn} + - ${output:database.arn}/index/* \ No newline at end of file From bdaff1e10d24a9a5d00c05a55f522e26d3e2760c Mon Sep 17 00:00:00 2001 From: ac360 Date: Thu, 2 Jul 2020 00:26:40 -0700 Subject: [PATCH 15/34] bump website version --- site/serverless.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/serverless.yml b/site/serverless.yml index 40db46e..2c0b8e9 100644 --- a/site/serverless.yml +++ b/site/serverless.yml @@ -1,5 +1,5 @@ app: fullstack -component: website@1.0.0 +component: website@1.0.3 name: site inputs: From 057fd2601601a201fe248c5c650be79ec46becd6 Mon Sep 17 00:00:00 2001 From: ac360 Date: Thu, 2 Jul 2020 11:45:21 -0700 Subject: [PATCH 16/34] improve onboarding by putting in temp token --- api/serverless.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/serverless.yml b/api/serverless.yml index 465e4e3..f6aabc2 100644 --- a/api/serverless.yml +++ b/api/serverless.yml @@ -18,4 +18,4 @@ inputs: # AWS DynamoDB Table Index name. Needed for the code to access it. dbIndex1: ${output:database.indexes.gsi1.name} # A secret token to sign the JWT tokens with. - tokenSecret: ${env:tokenSecret} \ No newline at end of file + tokenSecret: secret_1234 # Change to environment variable: ${env:tokenSecret} \ No newline at end of file From 824ae5af227f78f2b5a603c9f81aa620d3e95b74 Mon Sep 17 00:00:00 2001 From: ac360 Date: Thu, 2 Jul 2020 16:37:27 -0700 Subject: [PATCH 17/34] add coments --- database/serverless.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/database/serverless.yml b/database/serverless.yml index 31b205b..ec15890 100644 --- a/database/serverless.yml +++ b/database/serverless.yml @@ -7,6 +7,7 @@ inputs: region: us-east-1 # Don't delete the Database Table if "serverless remove" is run deletionPolicy: retain + # Simple, single-table design attributeDefinitions: - AttributeName: hk AttributeType: S From 18b65ce460344e37187e728f0115cc160817d614 Mon Sep 17 00:00:00 2001 From: ac360 Date: Fri, 3 Jul 2020 16:58:08 -0700 Subject: [PATCH 18/34] auto-add secret token for onboarding ease --- api/config/passport.js | 8 ++++---- api/serverless.yml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/api/config/passport.js b/api/config/passport.js index a6c7120..d96ee55 100644 --- a/api/config/passport.js +++ b/api/config/passport.js @@ -1,7 +1,7 @@ /** * Config: Passport.js */ - + const StrategyJWT = require('passport-jwt').Strategy const ExtractJWT = require('passport-jwt').ExtractJwt const { users } = require('../models') @@ -11,14 +11,14 @@ module.exports = (passport) => { const options = {} options.jwtFromRequest = ExtractJWT.fromAuthHeaderAsBearerToken() - options.secretOrKey = process.env.tokenSecret + options.secretOrKey = process.env.tokenSecret || 'secret_j91jasf0j1asfkl' // Change this to only use your own secret token passport.use(new StrategyJWT(options, async (jwtPayload, done) => { let user try { user = await users.getById(jwtPayload.id) } - catch (error) { + catch (error) { console.log(error) - return done(error, null) + return done(error, null) } if (!user) { return done(null, false) } diff --git a/api/serverless.yml b/api/serverless.yml index f6aabc2..8309337 100644 --- a/api/serverless.yml +++ b/api/serverless.yml @@ -18,4 +18,4 @@ inputs: # AWS DynamoDB Table Index name. Needed for the code to access it. dbIndex1: ${output:database.indexes.gsi1.name} # A secret token to sign the JWT tokens with. - tokenSecret: secret_1234 # Change to environment variable: ${env:tokenSecret} \ No newline at end of file + # tokenSecret: secret_1234 # Change to secret via environment variable: ${env:tokenSecret} \ No newline at end of file From 4dc81c19b10a1f1fb94486fed067d0337bf836e1 Mon Sep 17 00:00:00 2001 From: ac360 Date: Mon, 6 Jul 2020 10:00:19 -0700 Subject: [PATCH 19/34] improve help for when api domain is not configured --- README.md | 11 ++++------- site/src/config.js | 18 ++++++++++++++++++ site/src/index.js | 14 -------------- site/src/pages/Auth/Auth.js | 19 +++++++++++++++++-- site/src/utils/api.js | 13 ++++++++++--- 5 files changed, 49 insertions(+), 26 deletions(-) create mode 100644 site/src/config.js diff --git a/README.md b/README.md index 3ca9a7a..3fb7c2e 100644 --- a/README.md +++ b/README.md @@ -17,20 +17,18 @@ Add your AWS credentials in `.env` file in the root directory, like this: AWS_ACCESS_KEY_ID=JAFJ89109JASFKLJASF AWS_SECRET_ACCESS_KEY=AJ91J9A0SFA0S9FSKAFLASJFLJ +# This signs you JWT tokens used for auth. Enter a random string in here that's ~40 characters in length. tokenSecret=yourSecretKey # Only add this if you want a custom domain. Purchase it on AWS Route53 in your target AWS account first. domain=serverless-fullstack-app.com ``` -In the root folder of the project, run `serverless deploy --all` - -Lastly, you will need to update the URL in the `site` so that you interact with the correct API endpoint. Take the `/api` `url` and put it in the site React app [here](./site/src/index.js). - -Note: Upon the first deployment of your website, it will take a 2-3 minutes for the Cloudfront (CDN) URL to work. Until then, you can access it via the `bucketUrl`. - +In the root folder of the project, run `serverless deploy` +Lastly, you will need to add your API domain manually to your React application in `./site/src/config.js`, so that you interact with your serverless Express.js back-end. You can find the your API url by going into `./api` and running `serverless info` and copying the `url:` value. It should look something like this `https://9jfalnal19.execute-api.us-east-1.amazonaws.com` or it will look like the custom domain you have set. +**Note:** Upon the first deployment of your website, it will take a 2-3 minutes for the Cloudfront (CDN) URL to work. Until then, you can access it via the `bucketUrl`. After initial deployment, we recommend deploying only the parts you are changing, not the entire thing together (why risk deploying your database with a code change?). To do this, `cd` into a part of the application and run `serverless deploy`. @@ -52,7 +50,6 @@ Support for stages is built in. You can deploy everything or individual components to different stages via the `--stage` flag, like this: `serverless deploy --stage prod` -`serverless deploy --all --stage prod` Or, you can hardcode the stage in `serverless.yml` (not recommended): diff --git a/site/src/config.js b/site/src/config.js new file mode 100644 index 0000000..3044c1b --- /dev/null +++ b/site/src/config.js @@ -0,0 +1,18 @@ +/** + * Global Config + */ + +const config = {} + +// Domains +config.domains = {} + +/** + * API Domain + * Add the domain from your serverless express.js back-end here. + * This will enable your front-end to communicate with your back-end. + * (e.g. 'https://api.mydomain.com' or 'https://091jafsl10.execute-api.us-east-1.amazonaws.com') + */ +config.domains.api = null + +export default config \ No newline at end of file diff --git a/site/src/index.js b/site/src/index.js index 88699fe..9e3c542 100644 --- a/site/src/index.js +++ b/site/src/index.js @@ -3,20 +3,6 @@ import ReactDOM from 'react-dom' import App from './App' import './index.css' -/** - * Global Config - */ - -window.serverless = {} -window.serverless.urls = {} -if (window.location.host.includes('localhost:')) { - console.log('here') - window.serverless.urls.api = `https://5xm2qt2k4m.execute-api.us-east-1.amazonaws.com` -} else { - window.serverless.root = window.location.hostname.replace('www.', '') - window.serverless.urls.api = `https://api.${window.serverless.root}` -} - /** * Render App */ diff --git a/site/src/pages/Auth/Auth.js b/site/src/pages/Auth/Auth.js index c9abe56..3477728 100644 --- a/site/src/pages/Auth/Auth.js +++ b/site/src/pages/Auth/Auth.js @@ -78,7 +78,18 @@ class Auth extends Component { // Validate email if (!this.state.formEmail) { - return this.setState({ formError: 'email is required' }) + return this.setState({ + loading: false, + formError: 'email is required' + }) + } + + // Validate password + if (!this.state.formPassword) { + return this.setState({ + loading: false, + formError: 'password is required' + }) } let token @@ -89,8 +100,12 @@ class Auth extends Component { token = await userLogin(this.state.formEmail, this.state.formPassword) } } catch (error) { + console.log(error) if (error.message) { - this.setState({ formError: error.message, loading: false }) + this.setState({ + formError: error.message, + loading: false + }) } else { this.setState({ formError: 'Sorry, something unknown went wrong. Please try again.', diff --git a/site/src/utils/api.js b/site/src/utils/api.js index 845d9cd..715f60f 100644 --- a/site/src/utils/api.js +++ b/site/src/utils/api.js @@ -2,6 +2,8 @@ * Utils: Back-end */ +import config from '../config' + /** * Register a new user */ @@ -20,7 +22,7 @@ export const userLogin = async (email, password) => { * userGet */ export const userGet = async (token) => { - return await requestApi('/user', 'POST', null, { + return await requestApi('/user', 'POST', null, { Authorization: `Bearer ${token}` }) } @@ -29,16 +31,21 @@ export const userGet = async (token) => { * API request to call the backend */ export const requestApi = async ( - path = '', + path = '', method = 'GET', data = null, headers = {}) => { + // Check if API URL has been set + if (!config?.domains?.api) { + throw new Error(`Error: Missing API Domain – Please add the API domain from your serverless Express.js back-end to this front-end application. You can do this in the "./config.js" file. Instructions are listed there and in the documentation.`) + } + // Prepare URL if (!path.startsWith('/')) { path = `/${path}` } - const url = `${window.serverless.urls.api}${path}` + const url = `${config.domains.api}${path}` // Set headers headers = Object.assign( From 6e2a0694a3a951baf958d28968aa89dd991b7bda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eslam=20=CE=BB=20Hefnawy?= Date: Tue, 7 Jul 2020 15:50:44 +0300 Subject: [PATCH 20/34] Update README.md --- README.md | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 3fb7c2e..9cfabd1 100644 --- a/README.md +++ b/README.md @@ -7,11 +7,21 @@ A complete, serverless, full-stack application built on AWS Lambda, AWS HTTP API ## Quick Start -Clone this repo. +Install the latest version of the Serverless Framework: -Run `npm i` in all subdirectories that contain `package.json` -Add your AWS credentials in `.env` file in the root directory, like this: +``` +npm i -g serverless +``` + +Then, initialize the `fullstack-app` template: + +``` +serverless init fullstack-app +cd fullstack-app +``` + +Then, add your AWS credentials in the `.env` file in the root directory, like this: ```text AWS_ACCESS_KEY_ID=JAFJ89109JASFKLJASF From cb484ff6d85857fb0f8164454621aeb8efb9df64 Mon Sep 17 00:00:00 2001 From: ac360 Date: Tue, 7 Jul 2020 18:54:41 -0700 Subject: [PATCH 21/34] bump express version --- api/serverless.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/serverless.yml b/api/serverless.yml index 613700e..1a9dc16 100644 --- a/api/serverless.yml +++ b/api/serverless.yml @@ -1,5 +1,5 @@ app: fullstack -component: express@1.3.1 +component: express@1.4.1 name: api inputs: From 36dd2c9e59e3e83b76a1c9dee27611f4a072a919 Mon Sep 17 00:00:00 2001 From: ac360 Date: Wed, 8 Jul 2020 14:12:07 -0700 Subject: [PATCH 22/34] remove version pinning --- api/serverless.yml | 2 +- database/serverless.yml | 2 +- permissions/serverless.yml | 2 +- site/serverless.yml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/api/serverless.yml b/api/serverless.yml index 1a9dc16..e7f9c7c 100644 --- a/api/serverless.yml +++ b/api/serverless.yml @@ -1,5 +1,5 @@ app: fullstack -component: express@1.4.1 +component: express name: api inputs: diff --git a/database/serverless.yml b/database/serverless.yml index ec15890..a960fc2 100644 --- a/database/serverless.yml +++ b/database/serverless.yml @@ -1,5 +1,5 @@ app: fullstack -component: aws-dynamodb@1.1.1 +component: aws-dynamodb name: database inputs: diff --git a/permissions/serverless.yml b/permissions/serverless.yml index f5ecb27..1a86879 100644 --- a/permissions/serverless.yml +++ b/permissions/serverless.yml @@ -1,5 +1,5 @@ app: fullstack -component: aws-iam-role@2.0.0 +component: aws-iam-role name: permissions inputs: diff --git a/site/serverless.yml b/site/serverless.yml index 2c0b8e9..e284da9 100644 --- a/site/serverless.yml +++ b/site/serverless.yml @@ -1,5 +1,5 @@ app: fullstack -component: website@1.0.3 +component: website name: site inputs: From dde999c08c8bf43cd8483eaf209886624e6daa0b Mon Sep 17 00:00:00 2001 From: ac360 Date: Fri, 10 Jul 2020 00:12:40 -0700 Subject: [PATCH 23/34] enable openApi input --- api/app.js | 2 +- api/serverless.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/api/app.js b/api/app.js index babcb48..472d3e3 100644 --- a/api/app.js +++ b/api/app.js @@ -54,7 +54,7 @@ app.post(`/users/register`, users.register) app.post(`/users/login`, users.login) app.get(`/test/`, (req, res) => { - res.status(200).send('Route updated') + res.status(200).send('Request received') }) /** diff --git a/api/serverless.yml b/api/serverless.yml index e7f9c7c..7658225 100644 --- a/api/serverless.yml +++ b/api/serverless.yml @@ -9,8 +9,8 @@ inputs: roleName: ${output:permissions.name} # Enable this when you want to set a custom domain. # domain: api.${env:domain} - # Leaving this on auto-generates an OpenAPI spec each time this is deployed. - inference: true + # Enabling this auto-generates an OpenAPI spec each time this is deployed. Note: this feature is still experimental. + openApi: true # Environment variables env: # AWS DynamoDB Table name. Needed for the code to access it. From 09d4a67a3c841b44afe4b2ac40b286aa92140381 Mon Sep 17 00:00:00 2001 From: "Eslam A. Hefnawy" Date: Tue, 14 Jul 2020 16:56:39 +0300 Subject: [PATCH 24/34] reorder app for spacing --- api/serverless.yml | 4 ++-- database/serverless.yml | 4 ++-- permissions/serverless.yml | 12 ++++++------ site/serverless.yml | 4 ++-- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/api/serverless.yml b/api/serverless.yml index 7658225..fccf700 100644 --- a/api/serverless.yml +++ b/api/serverless.yml @@ -1,6 +1,6 @@ -app: fullstack component: express name: api +app: fullstack inputs: # Express application source code. @@ -18,4 +18,4 @@ inputs: # AWS DynamoDB Table Index name. Needed for the code to access it. dbIndex1: ${output:database.indexes.gsi1.name} # A secret token to sign the JWT tokens with. - # tokenSecret: secret_1234 # Change to secret via environment variable: ${env:tokenSecret} \ No newline at end of file + # tokenSecret: secret_1234 # Change to secret via environment variable: ${env:tokenSecret} diff --git a/database/serverless.yml b/database/serverless.yml index a960fc2..4767b77 100644 --- a/database/serverless.yml +++ b/database/serverless.yml @@ -1,6 +1,6 @@ -app: fullstack component: aws-dynamodb name: database +app: fullstack inputs: name: ${name}-${stage} @@ -28,4 +28,4 @@ inputs: - AttributeName: sk KeyType: RANGE Projection: - ProjectionType: ALL \ No newline at end of file + ProjectionType: ALL diff --git a/permissions/serverless.yml b/permissions/serverless.yml index 1a86879..a0e45b4 100644 --- a/permissions/serverless.yml +++ b/permissions/serverless.yml @@ -1,11 +1,11 @@ -app: fullstack component: aws-iam-role name: permissions +app: fullstack inputs: name: ${name}-${stage} - region: us-east-1 - service: lambda.amazonaws.com + region: us-east-1 + service: lambda.amazonaws.com policy: # AWS Lambda function containing Express Logs and Assume Role access - Effect: Allow @@ -14,7 +14,7 @@ inputs: - logs:CreateLogGroup - logs:CreateLogStream - logs:PutLogEvents - Resource: '*' + Resource: "*" # AWS DynamoDB Table access - Effect: Allow Action: @@ -24,6 +24,6 @@ inputs: - dynamodb:PutItem - dynamodb:UpdateItem - dynamodb:DeleteItem - Resource: + Resource: - ${output:database.arn} - - ${output:database.arn}/index/* \ No newline at end of file + - ${output:database.arn}/index/* diff --git a/site/serverless.yml b/site/serverless.yml index e284da9..221bfb1 100644 --- a/site/serverless.yml +++ b/site/serverless.yml @@ -1,6 +1,6 @@ -app: fullstack component: website name: site +app: fullstack inputs: # React application. "hook" runs before deployment to build the source code. "dist" is the built artifact directory which is uploaded. @@ -9,4 +9,4 @@ inputs: hook: npm run build dist: build # Enable this when you want to set a custom domain. - # domain: ${env:domain} \ No newline at end of file + # domain: ${env:domain} From 6d66f94095b8f51cea55d1a60c195b8237906736 Mon Sep 17 00:00:00 2001 From: ac360 Date: Wed, 12 Aug 2020 20:10:51 -0700 Subject: [PATCH 25/34] improve error handling --- api/app.js | 16 ++++++++++++---- api/controllers/users.js | 10 +++++----- api/serverless.yml | 4 ++-- 3 files changed, 19 insertions(+), 11 deletions(-) diff --git a/api/app.js b/api/app.js index 472d3e3..66650f7 100644 --- a/api/app.js +++ b/api/app.js @@ -41,6 +41,14 @@ app.use(passport.session()) // Enable JSON use app.use(express.json()) +// Since Express doesn't support error handling of promises out of the box, +// this handler enables that +const asyncHandler = fn => (req, res, next) => { + return Promise + .resolve(fn(req, res, next)) + .catch(next); +}; + /** * Routes - Public */ @@ -49,9 +57,9 @@ app.options(`*`, (req, res) => { res.status(200).send() }) -app.post(`/users/register`, users.register) +app.post(`/users/register`, asyncHandler(users.register)) -app.post(`/users/login`, users.login) +app.post(`/users/login`, asyncHandler(users.login)) app.get(`/test/`, (req, res) => { res.status(200).send('Request received') @@ -61,7 +69,7 @@ app.get(`/test/`, (req, res) => { * Routes - Protected */ -app.post(`/user`, passport.authenticate('jwt', { session: false }), users.get) +app.post(`/user`, passport.authenticate('jwt', { session: false }), asyncHandler(users.get)) /** * Routes - Catch-All @@ -76,7 +84,7 @@ app.get(`/*`, (req, res) => { */ app.use(function (err, req, res, next) { console.error(err) - res.status(500).send('Internal Serverless Error') + res.status(500).json({ error: `Internal Serverless Error - "${err.message}"` }) }) module.exports = app \ No newline at end of file diff --git a/api/controllers/users.js b/api/controllers/users.js index 20a3812..4a042df 100644 --- a/api/controllers/users.js +++ b/api/controllers/users.js @@ -16,16 +16,16 @@ const register = async (req, res, next) => { try { await users.register(req.body) - } catch(error) { + } catch (error) { return res.status(400).json({ error: error.message }) } let user - try { - user = await users.getByEmail(req.body.email) - } catch (error) { + try { + user = await users.getByEmail(req.body.email) + } catch (error) { console.log(error) - return next(error, null) + return next(error, null) } const token = jwt.sign(user, process.env.tokenSecret, { diff --git a/api/serverless.yml b/api/serverless.yml index 7658225..16b87e6 100644 --- a/api/serverless.yml +++ b/api/serverless.yml @@ -1,5 +1,5 @@ app: fullstack -component: express +component: express@dev name: api inputs: @@ -18,4 +18,4 @@ inputs: # AWS DynamoDB Table Index name. Needed for the code to access it. dbIndex1: ${output:database.indexes.gsi1.name} # A secret token to sign the JWT tokens with. - # tokenSecret: secret_1234 # Change to secret via environment variable: ${env:tokenSecret} \ No newline at end of file + tokenSecret: secret_1234 # Change to secret via environment variable: ${env:tokenSecret} \ No newline at end of file From 77d036b95533bfd041314719c39a1700cff23131 Mon Sep 17 00:00:00 2001 From: ac360 Date: Wed, 12 Aug 2020 20:21:23 -0700 Subject: [PATCH 26/34] adjust properties --- api/serverless.yml | 2 +- database/serverless.yml | 2 +- permissions/serverless.yml | 2 +- site/serverless.yml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/api/serverless.yml b/api/serverless.yml index 62c555d..aead9ad 100644 --- a/api/serverless.yml +++ b/api/serverless.yml @@ -1,6 +1,6 @@ component: express -name: api app: fullstack +name: api inputs: # Express application source code. diff --git a/database/serverless.yml b/database/serverless.yml index 4767b77..59829eb 100644 --- a/database/serverless.yml +++ b/database/serverless.yml @@ -1,6 +1,6 @@ component: aws-dynamodb -name: database app: fullstack +name: database inputs: name: ${name}-${stage} diff --git a/permissions/serverless.yml b/permissions/serverless.yml index a0e45b4..e3e99a9 100644 --- a/permissions/serverless.yml +++ b/permissions/serverless.yml @@ -1,6 +1,6 @@ component: aws-iam-role -name: permissions app: fullstack +name: permissions inputs: name: ${name}-${stage} diff --git a/site/serverless.yml b/site/serverless.yml index 221bfb1..6b6c418 100644 --- a/site/serverless.yml +++ b/site/serverless.yml @@ -1,6 +1,6 @@ component: website -name: site app: fullstack +name: site inputs: # React application. "hook" runs before deployment to build the source code. "dist" is the built artifact directory which is uploaded. From b876bb32189430dcfdfdd8d263d659f93788a8d6 Mon Sep 17 00:00:00 2001 From: ac360 Date: Wed, 12 Aug 2020 23:52:02 -0700 Subject: [PATCH 27/34] update create react app --- site/package.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/site/package.json b/site/package.json index 992333f..9525e65 100644 --- a/site/package.json +++ b/site/package.json @@ -6,12 +6,12 @@ "@testing-library/jest-dom": "^4.2.4", "@testing-library/react": "^9.3.2", "@testing-library/user-event": "^7.1.2", - "js-cookie": "^2.2.1", - "moment": "^2.24.0", "react": "^16.13.1", "react-dom": "^16.13.1", - "react-router-dom": "^5.1.2", - "react-scripts": "3.4.1" + "react-scripts": "3.4.3", + "js-cookie": "^2.2.1", + "moment": "^2.24.0", + "react-router-dom": "^5.1.2" }, "scripts": { "start": "react-scripts start", From 00214cfc79d327a77e27b0645823b74369c1a591 Mon Sep 17 00:00:00 2001 From: Austen Date: Thu, 13 Aug 2020 01:09:28 -0700 Subject: [PATCH 28/34] Update README.md --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index 9cfabd1..0298f14 100644 --- a/README.md +++ b/README.md @@ -104,3 +104,9 @@ For more details on each part of this fullstack application, check out these res * [Serverless Website](https://github.com/serverless-components/website) * [Serverless AWS DynamoDB](https://github.com/serverless-components/aws-dynamodb) * [Serverless AWS IAM Role](https://github.com/serverless-components/aws-iam-role) + +## Guides + +### How To Debug CORS Errors + +If you are running into CORS errors, see our guide on debugging them [within the Express Component's repo](https://github.com/serverless-components/express/blob/master/README.md#how-to-debug-cors-errors) From 3df766cc4be8a5e7f06dd5d7c78e07ec04d38fad Mon Sep 17 00:00:00 2001 From: ac360 Date: Fri, 11 Sep 2020 01:53:54 -0700 Subject: [PATCH 29/34] fix app name --- api/serverless.yml | 2 +- database/serverless.yml | 2 +- permissions/serverless.yml | 2 +- site/serverless.yml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/api/serverless.yml b/api/serverless.yml index aead9ad..ac1bc79 100644 --- a/api/serverless.yml +++ b/api/serverless.yml @@ -1,5 +1,5 @@ component: express -app: fullstack +app: fullstack-app name: api inputs: diff --git a/database/serverless.yml b/database/serverless.yml index 59829eb..631d8a3 100644 --- a/database/serverless.yml +++ b/database/serverless.yml @@ -1,5 +1,5 @@ component: aws-dynamodb -app: fullstack +app: fullstack-app name: database inputs: diff --git a/permissions/serverless.yml b/permissions/serverless.yml index e3e99a9..9090b9b 100644 --- a/permissions/serverless.yml +++ b/permissions/serverless.yml @@ -1,5 +1,5 @@ component: aws-iam-role -app: fullstack +app: fullstack-app name: permissions inputs: diff --git a/site/serverless.yml b/site/serverless.yml index 6b6c418..3bbf7f5 100644 --- a/site/serverless.yml +++ b/site/serverless.yml @@ -1,5 +1,5 @@ component: website -app: fullstack +app: fullstack-app name: site inputs: From 2382fd889e27b55226d3c56345488af99c4225e8 Mon Sep 17 00:00:00 2001 From: ac360 Date: Thu, 17 Sep 2020 22:27:58 -0700 Subject: [PATCH 30/34] remove openapi generation --- api/app.js | 9 --------- api/serverless.yml | 4 +--- 2 files changed, 1 insertion(+), 12 deletions(-) diff --git a/api/app.js b/api/app.js index 66650f7..d478c04 100644 --- a/api/app.js +++ b/api/app.js @@ -5,15 +5,6 @@ const { users } = require('./controllers') -/** - * Inference: - * - * When "inference" in serverless.yml is "true", the Serverless Framework will attempt to - * initialize this application on every deployment, extract its endpoints and generate an OpenAPI specification (super cool) - * However, the Framework won't have access to the environment variables, causing some things to crash on load. - * That is why some things have try/catch blocks around them when they are required. - */ - /** * Configure Passport */ diff --git a/api/serverless.yml b/api/serverless.yml index ac1bc79..cc209b4 100644 --- a/api/serverless.yml +++ b/api/serverless.yml @@ -1,5 +1,5 @@ -component: express app: fullstack-app +component: express name: api inputs: @@ -9,8 +9,6 @@ inputs: roleName: ${output:permissions.name} # Enable this when you want to set a custom domain. # domain: api.${env:domain} - # Enabling this auto-generates an OpenAPI spec each time this is deployed. Note: this feature is still experimental. - openApi: true # Environment variables env: # AWS DynamoDB Table name. Needed for the code to access it. From 0bdb345d8b086f94e3726708e06b7e852ed028d2 Mon Sep 17 00:00:00 2001 From: Thibault Dalban Date: Fri, 2 Oct 2020 10:36:40 +0200 Subject: [PATCH 31/34] Fix confusing comments in User model The comments above the dynamodb params in `getByEmail` and `getById` functions were indicating a save instead of a query, probably due to a copy/paste from the `register` function. --- api/models/users.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/api/models/users.js b/api/models/users.js index cfef68f..b29e60f 100644 --- a/api/models/users.js +++ b/api/models/users.js @@ -67,7 +67,7 @@ const getByEmail = async(email) => { throw new Error(`"${email}" is not a valid email address`) } - // Save + // Query const params = { TableName: process.env.db, KeyConditionExpression: 'hk = :hk', @@ -96,7 +96,7 @@ const getById = async(id) => { throw new Error(`"id" is required`) } - // Save + // Query const params = { TableName: process.env.db, IndexName: process.env.dbIndex1, @@ -133,4 +133,4 @@ module.exports = { getByEmail, getById, convertToPublicFormat, -} \ No newline at end of file +} From 53251f04759af48ac4eb3bb2b1ad9272adac7902 Mon Sep 17 00:00:00 2001 From: Maciej Skierkowski Date: Mon, 19 Oct 2020 10:22:39 -0700 Subject: [PATCH 32/34] create serverless.template.yml --- serverless.yml => serverless.template.yml | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename serverless.yml => serverless.template.yml (100%) diff --git a/serverless.yml b/serverless.template.yml similarity index 100% rename from serverless.yml rename to serverless.template.yml From ebb5af4c266229090a2f17ae27ff3cd0e7be4757 Mon Sep 17 00:00:00 2001 From: "Eslam A. Hefnawy" Date: Wed, 28 Oct 2020 15:47:58 +0300 Subject: [PATCH 33/34] remove app props as its determined on init --- api/serverless.yml | 1 - database/serverless.yml | 1 - permissions/serverless.yml | 1 - site/serverless.yml | 1 - 4 files changed, 4 deletions(-) diff --git a/api/serverless.yml b/api/serverless.yml index cc209b4..99da196 100644 --- a/api/serverless.yml +++ b/api/serverless.yml @@ -1,4 +1,3 @@ -app: fullstack-app component: express name: api diff --git a/database/serverless.yml b/database/serverless.yml index 631d8a3..f9081af 100644 --- a/database/serverless.yml +++ b/database/serverless.yml @@ -1,5 +1,4 @@ component: aws-dynamodb -app: fullstack-app name: database inputs: diff --git a/permissions/serverless.yml b/permissions/serverless.yml index 9090b9b..5229904 100644 --- a/permissions/serverless.yml +++ b/permissions/serverless.yml @@ -1,5 +1,4 @@ component: aws-iam-role -app: fullstack-app name: permissions inputs: diff --git a/site/serverless.yml b/site/serverless.yml index 3bbf7f5..845044b 100644 --- a/site/serverless.yml +++ b/site/serverless.yml @@ -1,5 +1,4 @@ component: website -app: fullstack-app name: site inputs: From 188365a1a16eb4d1daeee280d0a15d56dd6d672d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eslam=20=CE=BB=20Hefnawy?= Date: Mon, 15 Feb 2021 20:39:25 +0300 Subject: [PATCH 34/34] Update README.md --- README.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 0298f14..bc39dff 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,8 @@ Install the latest version of the Serverless Framework: npm i -g serverless ``` +After installation, make sure you connect your AWS account by setting a provider in the org setting page on the [Serverless Dashboard](https://app.serverless.com). + Then, initialize the `fullstack-app` template: ``` @@ -21,12 +23,9 @@ serverless init fullstack-app cd fullstack-app ``` -Then, add your AWS credentials in the `.env` file in the root directory, like this: +Then, add the following environment variables in an `.env` file in the root directory, like this: ```text -AWS_ACCESS_KEY_ID=JAFJ89109JASFKLJASF -AWS_SECRET_ACCESS_KEY=AJ91J9A0SFA0S9FSKAFLASJFLJ - # This signs you JWT tokens used for auth. Enter a random string in here that's ~40 characters in length. tokenSecret=yourSecretKey