5 |
6 |
7 |
8 |
9 |
10 |
11 |
15 |
16 |
25 | My App
26 |
27 |
28 |
29 |
30 |
31 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/.github/workflows/on-push-to-master.yaml:
--------------------------------------------------------------------------------
1 | name: On push to master
2 |
3 | on:
4 | push:
5 | branches: [ master ]
6 |
7 | jobs:
8 | test-deploy-to-staging-and-package:
9 | runs-on: ubuntu-latest
10 | steps:
11 | - name: Checkout
12 | uses: actions/checkout@v2
13 |
14 | - name: Setup Node.js
15 | uses: actions/setup-node@v1
16 | with:
17 | node-version: 12.x
18 |
19 | - name: Install package
20 | run: |
21 | (npm ci && npm audit --audit-level high && npm test) & \
22 | (cd packages/ui && npm ci && npm audit --audit-level high && npm test) & \
23 | (cd packages/api && npm ci && npm audit --audit-level high && npm test)
24 |
25 | - name: Deploy to staging
26 | run: |
27 | mkdir ~/.aws
28 | echo "[myapp_staging]
29 | aws_access_key_id = ${{ secrets.AWS_ACCESS_KEY_ID_STAGING }}
30 | aws_secret_access_key = ${{ secrets.AWS_SECRET_ACCESS_KEY_STAGING }}" > ~/.aws/credentials
31 | NODE_ENV=production npm run deploy:staging
32 |
33 | # TODO: Additional end-to-end tests
34 |
35 | - name: Package
36 | # TODO: Ideally, we'd package up the prod version, deploy that to stage,
37 | # then deploy the same packge to prod
38 | # NOTE: We need prod profile so that the package command can run describeStack to get
39 | # the Amplify App ID and create an Amplify deployment
40 | run: |
41 | echo "
42 |
43 | [myapp_prod]
44 | aws_access_key_id = ${{ secrets.AWS_ACCESS_KEY_ID_PROD }}
45 | aws_secret_access_key = ${{ secrets.AWS_SECRET_ACCESS_KEY_PROD }}" > ~/.aws/credentials
46 | npm run package:prod
47 | npm run zip-release
48 |
49 | - name: Release
50 | run: npx semantic-release
51 | env:
52 | # NOTE: GitHub Actions won't trigger on release when using the default GITHUB_TOKEN
53 | # Make sure the Personal Access Token is enabled for SSO if relevant to your organization/repo
54 | GITHUB_TOKEN: ${{ secrets.GH_PERSONAL_ACCESS_TOKEN }}
55 |
--------------------------------------------------------------------------------
/packages/api/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "myapp-api",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "handler.js",
6 | "scripts": {
7 | "test": "jest",
8 | "start:dev": "IS_OFFLINE=true serverless offline start",
9 | "package": "serverless package && zip -r api.zip .serverless serverless.yaml package.json package-lock.json",
10 | "deploy": "sls deploy",
11 | "deploy-package": "serverless deploy --package .serverless"
12 | },
13 | "keywords": [],
14 | "author": "",
15 | "license": "ISC",
16 | "devDependencies": {
17 | "@babel/cli": "^7.8.4",
18 | "@babel/core": "^7.9.0",
19 | "@babel/node": "^7.8.7",
20 | "@babel/plugin-transform-async-to-generator": "^7.8.3",
21 | "@babel/preset-env": "^7.9.5",
22 | "@serverless/event-mocks": "^1.1.1",
23 | "aws-lambda-mock-context": "^3.2.1",
24 | "babel-plugin-transform-es2015-modules-commonjs": "^6.26.2",
25 | "jest": "^25.3.0",
26 | "serverless": "^1.72.0",
27 | "serverless-apigateway-service-proxy": "^1.7.0",
28 | "serverless-domain-manager": "^3.3.1",
29 | "serverless-iam-roles-per-function": "^2.0.2",
30 | "serverless-offline": "^6.1.4",
31 | "serverless-plugin-tracing": "^2.0.0",
32 | "serverless-prune-plugin": "^1.4.2",
33 | "serverless-webpack": "^5.3.1",
34 | "webpack": "^4.42.1",
35 | "webpack-cli": "^3.3.11"
36 | },
37 | "dependencies": {
38 | "@dazn/lambda-powertools-middleware-correlation-ids": "^1.23.0",
39 | "@dazn/lambda-powertools-middleware-log-timeout": "^1.23.0",
40 | "@dazn/lambda-powertools-middleware-sample-logging": "^1.23.0",
41 | "@middy/core": "^1.0.0-beta.10",
42 | "@middy/sqs-partial-batch-failure": "^1.0.0-beta.10",
43 | "aws-sdk": "^2.656.0",
44 | "body-parser": "^1.19.0",
45 | "cors": "^2.8.5",
46 | "discord.js": "^12.1.1",
47 | "dotenv": "^8.2.0",
48 | "dynamodb-toolbox": "github:jeremydaly/dynamodb-toolbox#v0.2",
49 | "express": "^4.17.1",
50 | "lodash": "^4.17.19",
51 | "node-fetch": "^2.6.0",
52 | "serverless-http": "^2.3.2",
53 | "shortid": "^2.2.15"
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/docs/diagrams/ci-cd/diagram.drawio:
--------------------------------------------------------------------------------
1 | 7Vtbc5s4FP41fkwHg43txziXbmfTmUy83d087chwDGoFokLEdn79SiBuEWBy9WXSmTToCAnpfN+5CTKwLoLNV4Yi/zt1gQxMw90MrMuBaZqGbYtfUrLNJEPTHmcSj2FXyUrBAj+CEhpKmmAX4tqNnFLCcVQXOjQMweE1GWKMruu3rSipPzVCHmiChYOILv0Hu9xX0qFhlB1/APZ89ejpWHUskfPLYzQJ1fMGprVK/2XdAcrnUvfHPnLpuiKyrgbWBaOUZ1fB5gKIVG6utmzcdUtvsW4GIe8zYDIB25lNVsOZ7aLp1DpTMzwgkihdXMIDEBoFckbTuMErcLaOUFS2fr7NdRavcUBQKFpznwdECIfi0vExcW/QliZyPTEX+slbc9FiXIEv1mnNU8WBXJpsFbqRDYKWQOaFdi8ooUx0hTR9YMwZ/VVAJZ+7oiG/RgEmkoJ/A3NRiJRYPXEqmohgLxTXjtgciPnmuv5yhQDjsKmIlD6/Ag2As624RfVOFLSK+yPVXJc8mtlK5lcoZOUUQoq7XjFziZ+4UBD2hNPshrMXhBpMupJaabRba9vcaWhqGjaqyepQk5r9TrgEFHqSox3TWw2zT57OjojgRYg4zCXrYg2LYiMvg2faBg+wWPrPrCHX4yEcxtIAuVgvE7/pOpQOkNDELe9URpqamYZuaV0S1bWPOSwi5MjetfDjT0A/CONr5XNvazTr1pjHoSrNjAYi2O9hjJaG9m2SjriD3wnEh2GPea9dV9yb2Gdfzc3C3/9B/OPhzwU12NnjuRf9uDsbaeoBVwRt1aSM+9SjISJXpfRJQCnvuaHCqjJt/gTOt0qbKOG0rmvYYP6vHP5lrFr3lZ7LjZo5bWzzRii2Wxkkm/fVvnJY2srHZfuTm2oN5m2UimnCHGjDPs+gEPOglSDjZjowIIjjh/qS3tQqhq0pR+YEWW4cIttzIRU8YFjLrhWjQSonBJAn7pLTYCT+rxtWfJK+MHcnvW3aOiBfOBxrqJ/LgAaRDwEwJAdHGdJlQDOwRNhhIAKym9YEkg6JHCdNN8jFGeQGCmULEULXBW0yTqUDAxQmonNb9BVDeJMz/qRMxeXvhTMjjTLfUSz3fkBx0zIPLW6OP+NmK5U64+ZMD5uNCrb2FTln3YFTuFFPxkvHF8UQFG6vxWZOwb3lDuIYImI7lWqI/uXDzqiYMq0MiDwd8rS0yGKnCwTSW48TfQ3ZPoQ4juCm50MLjjwceocU3UbTPUY3ffn66dZF4evEvlO+R4RuS9uIc53myWFT2piOTNPK47SSTszHz8X8kKoGWwP8Tjg0FPc9jf4QI7FHh5YCTjS1fQuChKMlyepppULBfI5XyKlYQVlrqcoIeV7aXGOxFyEVPwsQlRTHjrgUTI0xPVrDeW54sY/GcHQG3DLqJg5vQmuPtjM1Ds128uOp062fIHTP5TtTaQ8ExbGw5FR4jUm+nMELSixFuWqJ1ajghjJL51GLpb15jdVMAT3PuKOELI/4JctzPd3kOZ7OHH9gIt3FqaY8oSHIPU0So4prPOU88V1JsPdaemhpuJyu41YEKb32Sw/GGrx2izfucTKWOc69uW39vPge9FdBUj830uzqQGo2I60FO4icq44Au27GGYjxY5pLZ2qPKA55upnxfDC+7DI39f2SGjwo0p0qRB3kbrXFM+OLadsKy97aVtPdyvVX5jJrdj2qj6erVQxcw+qV30UMGwq9IuLaRH48tGTiyuMpUogFsS7nDItihUlrvtZdtE+DZRLvds+H+E1Sa3rf/yBn99HX9EOd9T59dX59X/Pbu3x1zVOXjvsNX1LkSnn1y/3ZPt2w+Qnty6DtVRjtNcJOTx3adyqNexm22TPJasnKPyjHMj4p8FYU6Dq63cmCvbr44V6/MTgtFrR9I9wdBlqyvdfCL5rl3yJkiX35Fx/W1f8=
--------------------------------------------------------------------------------
/.github/workflows/on-pr.yaml:
--------------------------------------------------------------------------------
1 | name: On Pull Request
2 |
3 | on:
4 | pull_request:
5 | types: [synchronize, opened, reopened]
6 |
7 | jobs:
8 | auto-approve-dependabot:
9 | if: github.actor == 'dependabot[bot]' || github.actor == 'dependabot-preview[bot]'
10 | runs-on: ubuntu-latest
11 | steps:
12 | - uses: hmarr/auto-approve-action@v2.0.0
13 | with:
14 | github-token: "${{ secrets.GITHUB_TOKEN }}"
15 |
16 | test-and-deploy-to-sandbox:
17 | if: github.actor != 'dependabot[bot]' && github.actor != 'dependabot-preview[bot]'
18 | runs-on: ubuntu-latest
19 | steps:
20 | - name: Checkout
21 | uses: actions/checkout@v2
22 |
23 | - name: Setup Node.js
24 | uses: actions/setup-node@v1
25 | with:
26 | node-version: 12.x
27 |
28 | - name: Install package
29 | run: |
30 | (npm ci && npm audit --audit-level high && npm test) & \
31 | (cd packages/ui && npm ci && npm audit --audit-level high && npm test) & \
32 | (cd packages/api && npm ci && npm audit --audit-level high && npm test)
33 |
34 | - name: Deploy to sandboxed stack
35 | id: deploy_to_sandboxed_stack
36 | run: |
37 | mkdir ~/.aws
38 | echo "[myapp_dev]
39 | aws_access_key_id = ${{ secrets.AWS_ACCESS_KEY_ID_DEV }}
40 | aws_secret_access_key = ${{ secrets.AWS_SECRET_ACCESS_KEY_DEV }}" > ~/.aws/credentials
41 | # TODO: How to also get the PR origin repo if it's coming from an external contributor
42 | # See: env.GITHUB_REF, env.GITHUB_HEAD_REF, GITHUB_BASE_REF https://help.github.com/en/actions/configuring-and-managing-workflows/using-environment-variables
43 | NODE_ENV=production ALARMS_NOTIFICATION_EMAIL=alert@example.com SERVERLESS_SERVICE_SUFFIX=-${{ github.head_ref }} npm run deploy:dev
44 | WEBSITE_URL=https://$(grep -o 'DefaultDomain": "[^"]*' ./stack-outputs.json | grep -o '[^"]*$')
45 | echo "::set-output name=websiteUrl::$WEBSITE_URL"
46 |
47 | - name: Comment on PR with stack outputs
48 | uses: unsplash/comment-on-pr@v1.2.0
49 | env:
50 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
51 | with:
52 | msg: "Website: [${{steps.deploy_to_sandboxed_stack.outputs.websiteUrl}}](${{steps.deploy_to_sandboxed_stack.outputs.websiteUrl}})"
53 | check_for_duplicate_msg: true
54 |
55 | # TODO: Additional end-to-end tests
56 |
--------------------------------------------------------------------------------
/packages/ui/src/logo.svg:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "myapp",
3 | "version": "1.3.0",
4 | "private": true,
5 | "description": "",
6 | "main": "handler.js",
7 | "scripts": {
8 | "test": "echo \"Error: no test specified\" && exit 1",
9 | "start:ui": "cd packages/ui && npm start",
10 | "start:ui:offline": "REACT_APP_ApiEndpoint=http://localhost:4911 npm run start:ui",
11 | "start:api": "sls offline cloudside",
12 | "package:dev": "sls package --stage development",
13 | "deploy-prepack:dev": "sls deploy --package .serverless --stage development",
14 | "deploy:dev": "sls deploy --stage development",
15 | "package:staging": "NODE_ENV=production sls package --stage staging",
16 | "deploy-prepack:staging": "NODE_ENV=production sls deploy --package .serverless --stage staging",
17 | "deploy:staging": "NODE_ENV=production sls deploy --stage staging",
18 | "package:prod": "NODE_ENV=production sls package --stage production",
19 | "deploy-prepack:prod": "NODE_ENV=production sls deploy --package .serverless --stage production",
20 | "deploy:prod": "NODE_ENV=production sls deploy --stage production",
21 | "remove-stack:dev": "sls remove --stage development",
22 | "zip-release": "zip -r release.zip .serverless serverless.yaml package.json package-lock.json",
23 | "setup": "node scripts/setup/setup.js",
24 | "setup-file": "node scripts/setup/createSetupFile.js"
25 | },
26 | "keywords": [],
27 | "author": "",
28 | "license": "ISC",
29 | "devDependencies": {
30 | "@semantic-release/changelog": "^5.0.1",
31 | "@semantic-release/commit-analyzer": "^8.0.1",
32 | "@semantic-release/git": "^9.0.0",
33 | "@semantic-release/github": "^7.0.5",
34 | "@semantic-release/npm": "^7.0.5",
35 | "@semantic-release/release-notes-generator": "^9.0.1",
36 | "@wizeline/serverless-amplify-plugin": "^1.6.2",
37 | "eslint": "^5.16.0 || ^6.1.0",
38 | "eslint-config-airbnb": "^18.0.1",
39 | "eslint-plugin-import": "^2.18.2",
40 | "eslint-plugin-jsx-a11y": "^6.2.3",
41 | "eslint-plugin-react": "^7.14.3",
42 | "eslint-plugin-react-hooks": "^1.7.0",
43 | "nodemon": "^2.0.3",
44 | "semantic-release": "^17.0.4",
45 | "serverless": "^1.70.0",
46 | "serverless-apigateway-service-proxy": "^1.7.0",
47 | "serverless-cloudside-plugin": "^1.0.3",
48 | "serverless-domain-manager": "^3.3.2",
49 | "serverless-dotenv-plugin": "^2.4.2",
50 | "serverless-iam-roles-per-function": "^2.0.2",
51 | "serverless-offline": "^6.1.5",
52 | "serverless-plugin-aws-alerts": "^1.4.0",
53 | "serverless-plugin-split-stacks": "^1.9.3",
54 | "serverless-plugin-tracing": "^2.0.0",
55 | "serverless-prune-plugin": "^1.4.2",
56 | "serverless-stack-output": "^0.2.3",
57 | "serverless-stack-termination-protection": "^1.0.4",
58 | "serverless-webpack": "^5.3.2",
59 | "webpack": "^4.43.0"
60 | },
61 | "dependencies": {
62 | "replace-in-file": "^6.0.0"
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/packages/ui/README.md:
--------------------------------------------------------------------------------
1 | This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).
2 |
3 | ## Available Scripts
4 |
5 | In the project directory, you can run:
6 |
7 | ### `npm start`
8 |
9 | Runs the app in the development mode.
10 | Open [http://localhost:3000](http://localhost:3000) to view it in the browser.
11 |
12 | The page will reload if you make edits.
13 | You will also see any lint errors in the console.
14 |
15 | ### `npm test`
16 |
17 | Launches the test runner in the interactive watch mode.
18 | See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information.
19 |
20 | ### `npm run build`
21 |
22 | Builds the app for production to the `build` folder.
23 | It correctly bundles React in production mode and optimizes the build for the best performance.
24 |
25 | The build is minified and the filenames include the hashes.
26 | Your app is ready to be deployed!
27 |
28 | See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information.
29 |
30 | ### `npm run eject`
31 |
32 | **Note: this is a one-way operation. Once you `eject`, you can’t go back!**
33 |
34 | If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project.
35 |
36 | Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own.
37 |
38 | You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it.
39 |
40 | ## Learn More
41 |
42 | You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started).
43 |
44 | To learn React, check out the [React documentation](https://reactjs.org/).
45 |
46 | ### Code Splitting
47 |
48 | This section has moved here: https://facebook.github.io/create-react-app/docs/code-splitting
49 |
50 | ### Analyzing the Bundle Size
51 |
52 | This section has moved here: https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size
53 |
54 | ### Making a Progressive Web App
55 |
56 | This section has moved here: https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app
57 |
58 | ### Advanced Configuration
59 |
60 | This section has moved here: https://facebook.github.io/create-react-app/docs/advanced-configuration
61 |
62 | ### Deployment
63 |
64 | This section has moved here: https://facebook.github.io/create-react-app/docs/deployment
65 |
66 | ### `npm run build` fails to minify
67 |
68 | This section has moved here: https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify
69 |
--------------------------------------------------------------------------------
/packages/ui/src/AuthenticatedApp.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import Amplify, { Auth } from 'aws-amplify'
3 | import {
4 | withAuthenticator,
5 | Loading,
6 | SignIn,
7 | ConfirmSignIn,
8 | VerifyContact,
9 | SignUp,
10 | ForgotPassword,
11 | RequireNewPassword,
12 | Greetings
13 | } from 'aws-amplify-react'
14 | import '@aws-amplify/ui/dist/style.css'
15 | import axios from 'axios'
16 |
17 | const {
18 | REACT_APP_ApiEndpoint,
19 | REACT_APP_CognitoIdentityPoolId,
20 | REACT_APP_CognitoUserPoolId,
21 | REACT_APP_CognitoUserPoolClientId,
22 | } = process.env
23 |
24 | // Set Authorization header on all requests if user is signed in
25 | axios.interceptors.request.use(async function (config) {
26 | try {
27 | const currentUserSession = await Auth.currentSession()
28 | const Authorization = currentUserSession.idToken.jwtToken
29 | config.headers.Authorization = Authorization
30 | } catch (e) { /* Auth.currentSession() throws if not signed in 🤷♂️ */ }
31 |
32 | return config
33 | })
34 |
35 | axios.defaults.baseURL = REACT_APP_ApiEndpoint
36 |
37 | async function fetchAndSetUsers({ setUsers }) {
38 | const fetchUsersResponse = await axios.get('/users')
39 | const users = fetchUsersResponse.data
40 | setUsers(users)
41 | }
42 |
43 | function AuthenticatedApp() {
44 | const [users, setUsers] = React.useState(null)
45 | React.useEffect(() => {
46 | fetchAndSetUsers({ setUsers })
47 | }, [])
48 |
49 | return
50 |
51 | {users && users.Items.map(user =>
{user.id}
)}
52 |
53 |
54 | }
55 |
56 | Amplify.configure({
57 | Auth: {
58 | // region: process.env.region,
59 | identityPoolId: REACT_APP_CognitoIdentityPoolId,
60 | userPoolId: REACT_APP_CognitoUserPoolId,
61 | userPoolWebClientId: REACT_APP_CognitoUserPoolClientId,
62 | },
63 | })
64 |
65 | // We're auto-confirming via the Lambda Function
66 | // Hack to skip the ConfirmSignUp view
67 | function ConfirmSignUpRedirectToSignIn({ authState, onStateChange }) {
68 | React.useEffect(() => {
69 | if (authState === 'confirmSignUp') onStateChange('signIn', {})
70 | }, [authState, onStateChange])
71 |
72 | return null
73 | }
74 |
75 | const signUpConfig = {
76 | hideAllDefaults: true,
77 | hiddenDefaults: ['phone_number'],
78 | }
79 |
80 | const federated = {
81 | // google_client_id: 'abc123abc123abc123abc123',
82 | // facebook_app_id: 'abc123abc123abc123abc123',
83 | // amazon_client_id: 'abc123abc123abc123abc123',
84 | }
85 |
86 | export default withAuthenticator(AuthenticatedApp, {
87 | usernameAttributes: 'email',
88 | signUpConfig,
89 | includeGreetings: true,
90 | hideDefault: true,
91 | authenticatorComponents: [
92 | ,
93 | ,
94 | ,
95 | ,
96 | ,
97 | ,
98 | ,
99 | ,
100 |
101 | ],
102 | })
--------------------------------------------------------------------------------
/docs/diagrams/diagram.drawio:
--------------------------------------------------------------------------------
1 | 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
--------------------------------------------------------------------------------
/docs/diagrams/cloud-architecture/diagram.drawio:
--------------------------------------------------------------------------------
1 | 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
--------------------------------------------------------------------------------
/packages/ui/src/serviceWorker.js:
--------------------------------------------------------------------------------
1 | // This optional code is used to register a service worker.
2 | // register() is not called by default.
3 |
4 | // This lets the app load faster on subsequent visits in production, and gives
5 | // it offline capabilities. However, it also means that developers (and users)
6 | // will only see deployed updates on subsequent visits to a page, after all the
7 | // existing tabs open on the page have been closed, since previously cached
8 | // resources are updated in the background.
9 |
10 | // To learn more about the benefits of this model and instructions on how to
11 | // opt-in, read https://bit.ly/CRA-PWA
12 |
13 | const isLocalhost = Boolean(
14 | window.location.hostname === 'localhost' ||
15 | // [::1] is the IPv6 localhost address.
16 | window.location.hostname === '[::1]' ||
17 | // 127.0.0.0/8 are considered localhost for IPv4.
18 | window.location.hostname.match(
19 | /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
20 | )
21 | );
22 |
23 | export function register(config) {
24 | if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
25 | // The URL constructor is available in all browsers that support SW.
26 | const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href);
27 | if (publicUrl.origin !== window.location.origin) {
28 | // Our service worker won't work if PUBLIC_URL is on a different origin
29 | // from what our page is served on. This might happen if a CDN is used to
30 | // serve assets; see https://github.com/facebook/create-react-app/issues/2374
31 | return;
32 | }
33 |
34 | window.addEventListener('load', () => {
35 | const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
36 |
37 | if (isLocalhost) {
38 | // This is running on localhost. Let's check if a service worker still exists or not.
39 | checkValidServiceWorker(swUrl, config);
40 |
41 | // Add some additional logging to localhost, pointing developers to the
42 | // service worker/PWA documentation.
43 | navigator.serviceWorker.ready.then(() => {
44 | console.log(
45 | 'This web app is being served cache-first by a service ' +
46 | 'worker. To learn more, visit https://bit.ly/CRA-PWA'
47 | );
48 | });
49 | } else {
50 | // Is not localhost. Just register service worker
51 | registerValidSW(swUrl, config);
52 | }
53 | });
54 | }
55 | }
56 |
57 | function registerValidSW(swUrl, config) {
58 | navigator.serviceWorker
59 | .register(swUrl)
60 | .then(registration => {
61 | registration.onupdatefound = () => {
62 | const installingWorker = registration.installing;
63 | if (installingWorker == null) {
64 | return;
65 | }
66 | installingWorker.onstatechange = () => {
67 | if (installingWorker.state === 'installed') {
68 | if (navigator.serviceWorker.controller) {
69 | // At this point, the updated precached content has been fetched,
70 | // but the previous service worker will still serve the older
71 | // content until all client tabs are closed.
72 | console.log(
73 | 'New content is available and will be used when all ' +
74 | 'tabs for this page are closed. See https://bit.ly/CRA-PWA.'
75 | );
76 |
77 | // Execute callback
78 | if (config && config.onUpdate) {
79 | config.onUpdate(registration);
80 | }
81 | } else {
82 | // At this point, everything has been precached.
83 | // It's the perfect time to display a
84 | // "Content is cached for offline use." message.
85 | console.log('Content is cached for offline use.');
86 |
87 | // Execute callback
88 | if (config && config.onSuccess) {
89 | config.onSuccess(registration);
90 | }
91 | }
92 | }
93 | };
94 | };
95 | })
96 | .catch(error => {
97 | console.error('Error during service worker registration:', error);
98 | });
99 | }
100 |
101 | function checkValidServiceWorker(swUrl, config) {
102 | // Check if the service worker can be found. If it can't reload the page.
103 | fetch(swUrl, {
104 | headers: { 'Service-Worker': 'script' },
105 | })
106 | .then(response => {
107 | // Ensure service worker exists, and that we really are getting a JS file.
108 | const contentType = response.headers.get('content-type');
109 | if (
110 | response.status === 404 ||
111 | (contentType != null && contentType.indexOf('javascript') === -1)
112 | ) {
113 | // No service worker found. Probably a different app. Reload the page.
114 | navigator.serviceWorker.ready.then(registration => {
115 | registration.unregister().then(() => {
116 | window.location.reload();
117 | });
118 | });
119 | } else {
120 | // Service worker found. Proceed as normal.
121 | registerValidSW(swUrl, config);
122 | }
123 | })
124 | .catch(() => {
125 | console.log(
126 | 'No internet connection found. App is running in offline mode.'
127 | );
128 | });
129 | }
130 |
131 | export function unregister() {
132 | if ('serviceWorker' in navigator) {
133 | navigator.serviceWorker.ready
134 | .then(registration => {
135 | registration.unregister();
136 | })
137 | .catch(error => {
138 | console.error(error.message);
139 | });
140 | }
141 | }
142 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # [1.3.0](https://github.com/wizeline/serverless-fullstack/compare/v1.2.2...v1.3.0) (2020-06-26)
2 |
3 |
4 | ### Features
5 |
6 | * add cloudformation stacktermination ([#25](https://github.com/wizeline/serverless-fullstack/issues/25)) ([1e47b1a](https://github.com/wizeline/serverless-fullstack/commit/1e47b1a63e68c883f3c24fb49cad4d478f8472f9))
7 |
8 | ## [1.2.2](https://github.com/wizeline/serverless-fullstack/compare/v1.2.1...v1.2.2) (2020-06-10)
9 |
10 |
11 | ### Bug Fixes
12 |
13 | * **dependencies:** update dependencies ([08dd83c](https://github.com/wizeline/serverless-fullstack/commit/08dd83c9d92ed092fe2ce71615bcaf585f5a0694))
14 |
15 | ## [1.2.1](https://github.com/wizeline/serverless-fullstack/compare/v1.2.0...v1.2.1) (2020-06-10)
16 |
17 |
18 | ### Bug Fixes
19 |
20 | * shorten Lambda Fn names to mitigate hitting length limit ([#19](https://github.com/wizeline/serverless-fullstack/issues/19)) ([fea1357](https://github.com/wizeline/serverless-fullstack/commit/fea1357e933c429c96bc6e1364da37cfac95811b))
21 |
22 | # [1.2.0](https://github.com/wizeline/serverless-fullstack/compare/v1.1.4...v1.2.0) (2020-06-09)
23 |
24 |
25 | ### Features
26 |
27 | * add setup script ([#17](https://github.com/wizeline/serverless-fullstack/issues/17)) ([094edd2](https://github.com/wizeline/serverless-fullstack/commit/094edd2e2223546529a56c2facc1deea87bc5169))
28 |
29 | ## [1.1.4](https://github.com/wizeline/serverless-fullstack/compare/v1.1.3...v1.1.4) (2020-05-12)
30 |
31 |
32 | ### Bug Fixes
33 |
34 | * split GitHub Action Secrets for AWS Creds into DEV, STAGING, and PROD ([cd0482b](https://github.com/wizeline/serverless-fullstack/commit/cd0482b54fbcb554774529f0280c66079f212d87))
35 |
36 | ## [1.1.3](https://github.com/wizeline/serverless-fullstack/compare/v1.1.2...v1.1.3) (2020-05-08)
37 |
38 |
39 | ### Bug Fixes
40 |
41 | * **ci:** add prod aws profile ([46c35af](https://github.com/wizeline/serverless-fullstack/commit/46c35affb437ca0849f643bec958f9a84ed47b4c))
42 |
43 | ## [1.1.2](https://github.com/wizeline/serverless-fullstack/compare/v1.1.1...v1.1.2) (2020-05-07)
44 |
45 |
46 | ### Bug Fixes
47 |
48 | * remove stage-specific .env vars; pass via command during CI instead ([92ed71b](https://github.com/wizeline/serverless-fullstack/commit/92ed71b116f77eb7d8dd828ca61b8c9326953fa2))
49 | * update to latest serverless-amplify-plugin to fix deploying prepacks ([e0b4ac6](https://github.com/wizeline/serverless-fullstack/commit/e0b4ac6037f88a69fb5fb318db18df1bf6f71736))
50 |
51 | ## [1.1.1](https://github.com/wizeline/serverless-fullstack/compare/v1.1.0...v1.1.1) (2020-05-06)
52 |
53 |
54 | ### Bug Fixes
55 |
56 | * shorten cognito lambda functions and add stage-specific .env vars ([6015c68](https://github.com/wizeline/serverless-fullstack/commit/6015c6823bfa1ec33911276a560e185507f9c563))
57 |
58 | # [1.1.0](https://github.com/wizeline/serverless-fullstack/compare/v1.0.4...v1.1.0) (2020-05-06)
59 |
60 |
61 | ### Bug Fixes
62 |
63 | * PR stack preview and commenting ([#9](https://github.com/wizeline/serverless-fullstack/issues/9)) ([b00cebe](https://github.com/wizeline/serverless-fullstack/commit/b00cebe879fd080ed2ef489e32aa97cc4f4b0aee))
64 | * **ui:** cp-stack-outputs before running build ([b1268f2](https://github.com/wizeline/serverless-fullstack/commit/b1268f2e43335d2caa726914c3e4969d535f4973))
65 | * update dynamodb-toolbox to fix invalid table error ([90bb4e5](https://github.com/wizeline/serverless-fullstack/commit/90bb4e5fd0089495fb95a8169b7b866aa0cc4fe6))
66 | * use SERVERLESS_SERVICE_SUFFIX instead of cli option and rename dev stage to development ([871d3bb](https://github.com/wizeline/serverless-fullstack/commit/871d3bb575370bc3dd32ec3ed4952cb03079cfcd))
67 |
68 |
69 | ### Features
70 |
71 | * set AWS_NODEJS_CONNECTION_REUSE_ENABLED for perf boost ([6a2962e](https://github.com/wizeline/serverless-fullstack/commit/6a2962e58c63433a4b6f56bbaeaa7731e4d74ea2))
72 | * use Amplify manual deployments ([f0e8607](https://github.com/wizeline/serverless-fullstack/commit/f0e8607321f4bb8eda672af838c235decbab84fb))
73 | * use stack outputs as env vars for UI build command ([f71be15](https://github.com/wizeline/serverless-fullstack/commit/f71be1508356eab4f3acb42cbcbd4ac883c76e26))
74 |
75 | ## [1.0.4](https://github.com/wizeline/serverless-nodejs-fullstack/compare/v1.0.3...v1.0.4) (2020-04-29)
76 |
77 |
78 | ### Bug Fixes
79 |
80 | * package for prod ([5e4f07a](https://github.com/wizeline/serverless-nodejs-fullstack/commit/5e4f07a8fdc28b27638410d3b45b46c1ea90163e))
81 |
82 | ## [1.0.3](https://github.com/wizeline/serverless-nodejs-fullstack/compare/v1.0.2...v1.0.3) (2020-04-29)
83 |
84 |
85 | ### Bug Fixes
86 |
87 | * fix release.config.js ([10010cd](https://github.com/wizeline/serverless-nodejs-fullstack/commit/10010cd90ceb05ca55b2294f993f1283bd680450))
88 |
89 | ## [1.0.2](https://github.com/wizeline/serverless-nodejs-fullstack/compare/v1.0.1...v1.0.2) (2020-04-29)
90 |
91 |
92 | ### Bug Fixes
93 |
94 | * replace dynamodb with dynamodb-toolbox v0.2 ([267711a](https://github.com/wizeline/serverless-nodejs-fullstack/commit/267711a5c28eb1ebb4007d6e9c3b74140cc0c20f))
95 |
96 | ## [1.0.1](https://github.com/wizeline/serverless-nodejs-fullstack/compare/v1.0.0...v1.0.1) (2020-04-29)
97 |
98 |
99 | ### Bug Fixes
100 |
101 | * add remove-stack:dev script ([#5](https://github.com/wizeline/serverless-nodejs-fullstack/issues/5)) ([6f063ab](https://github.com/wizeline/serverless-nodejs-fullstack/commit/6f063ab6afd86ec11e89b2ae7db740449c20dbcf))
102 |
103 | # 1.0.0 (2020-04-28)
104 |
105 |
106 | ### Bug Fixes
107 |
108 | * add Authorization header on all HTTP requests when signed in ([aecfbd7](https://github.com/wizeline/serverless-nodejs-fullstack/commit/aecfbd7a8aba1a971914f08df5172b0945108d98))
109 | * allow creating multiple stacks in same account ([e10800b](https://github.com/wizeline/serverless-nodejs-fullstack/commit/e10800be92b1ac12c3da0651a1b3ad754a49a843))
110 | * fix alarms and add stage setting for email notification ([e24fa98](https://github.com/wizeline/serverless-nodejs-fullstack/commit/e24fa98131c272d6119a59f88a28fb275fa49970))
111 |
112 |
113 | ### Features
114 |
115 | * add api gateway cognito authorizer ([9707c2d](https://github.com/wizeline/serverless-nodejs-fullstack/commit/9707c2d90fbaceb5eb4d6957d940fe6a35670313))
116 | * add serverless-dotenv-plugin ([eb79e88](https://github.com/wizeline/serverless-nodejs-fullstack/commit/eb79e8865386a1c61bda63a7e2a41f69ef2a60f7))
117 | * add serverless-plugin-aws-alerts ([77f523a](https://github.com/wizeline/serverless-nodejs-fullstack/commit/77f523a78bfd3ad7e6a9d4ee69f17d813813756a))
118 | * separated services ([927511d](https://github.com/wizeline/serverless-nodejs-fullstack/commit/927511dfeb1970f4f5962002a66e64347c1edfdd))
119 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Serverless FullStack starter
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | Get started developing applications quickly with best practices using Serverless on AWS.
12 |
13 | ## Pre-requisites
14 |
15 | * [AWS CLI](https://docs.aws.amazon.com/polly/latest/dg/setup-aws-cli.html)
16 | * Node.js
17 | * Git
18 | * GitHub Account
19 |
20 | ## Getting started
21 | To get started, run the following commands:
22 |
23 | ```
24 | git clone https://github.com/wizeline/serverless-fullstack
25 | cd serverless-fullstack
26 | npm run setup-file
27 | ```
28 |
29 | The last command will create a setup.config.json file, adjust it to set your application name and your aws credentials.
30 |
31 | Application name is required, if it's not provided, the setup will throw an error.
32 | The AWS DEV profile is required, if prod and stage are not provided, the dev will be used instead.
33 |
34 | Once you're done with the configuration file, run the following commands:
35 |
36 | ```
37 | npm i
38 | npm run setup
39 | ```
40 |
41 | Add your AWS credentials as secrets to your GitHub Repository with the following keys:
42 |
43 | * `AWS_ACCESS_KEY_ID_DEV`
44 | * `AWS_SECRET_ACCESS_KEY_DEV`
45 | * `AWS_ACCESS_KEY_ID_STAGING`
46 | * `AWS_SECRET_ACCESS_KEY_STAGING`
47 | * `AWS_ACCESS_KEY_ID_PROD`
48 | * `AWS_SECRET_ACCESS_KEY_PROD`
49 |
50 | It's advised that development, staging, and production environments exist in separate AWS accounts. However, if you'd prefer to deploy to a single AWS Account for simplicity, you can simply specify the same credentials for each.
51 |
52 | Create a GitHub Personal Access Token and add it as a repository secret called `GH_PERSONAL_ACCESS_TOKEN`. This is used to create GitHub releases.
53 |
54 | Coming soon: setup script to automate this.
55 |
56 | ## Features
57 |
58 | ### UI
59 |
60 |
61 |
62 | The UI was bootstrapped with Create React App and modified to include an Auth flow using AWS Amplify and Cognito.
63 |
64 | Static website hosting is provided by AWS Ampify, backed by S3 and CloudFront.
65 |
66 | ### Auth
67 |
68 |
69 |
70 | User authentication is provided by AWS Cognito.
71 |
72 | Social sign-in coming soon.
73 |
74 | ### REST API
75 |
76 |
77 |
78 | A Node.js Express API running on Lambda and API Gateway allows for a familiar developer experience while leveraging the benefits of Serverless.
79 |
80 | ### Database
81 |
82 |
83 |
84 | DynamoDB is capable of scaling to meet any requirements you may have.
85 |
86 | ### Continuous Deployment (CI/CD)
87 |
88 |
89 |
90 | GitHub Actions is used to create a Continuous Deployment Pipeline from developer preview, to staging, to production. Each environment is deployed to an isolated AWS Account (optionally, these can be deployed to the same account for simplicity).
91 |
92 | Changes are automatically versioned with Semantic Versioning based on git commit messages and immutable release packages created as GitHub relesaes.
93 |
94 | ### Pull Request Previews
95 |
96 | Each PR gets its own stack deployed so that reviewers can see the results for themselves, and end-to-end tests can be run.
97 |
98 | ### Infrastructure as Code
99 |
100 | Serverless Framework is used to describe our infrastruture
101 |
102 | ### And more...
103 |
104 | * CloudWatch Alarms
105 | * Per-function IAM Roles
106 | * REST API Logs in JSON
107 | * Custom Domain Names
108 | * .env support
109 | * Pruning of old Lambda Function Versions
110 | * Lambda Functions optimized with Webpack
111 |
112 | ## GitHub Actions Continuous Deployments (CI/CD)
113 |
114 |