diff --git a/.editorconfig b/.editorconfig deleted file mode 100644 index 4c92222..0000000 --- a/.editorconfig +++ /dev/null @@ -1,22 +0,0 @@ -# top-most EditorConfig file -root = true - -# Unix-style newlines with a newline ending every file -[*] -end_of_line = lf -insert_final_newline = true - -# Matches multiple files with brace expansion notation -# Set default charset -[*.{js}] -charset = utf-8 - -# 4 space indentation -[*.js] -indent_style = tab -indent_size = 4 - -# Matches the exact files either package.json or .travis.yml -[{package.json,serverless.yml}] -indent_style = tab -indent_size = 4 diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 7e67d39..0000000 --- a/.gitignore +++ /dev/null @@ -1,28 +0,0 @@ -.DS_Store -*.sublime-project -*.sublime-workspace -*.log -.serverless -v8-compile-cache-* -jest/* -coverage -testProjects/*/package-lock.json -testProjects/*/yarn.lock -.serverlessUnzipped -node_modules -.vscode/ -.eslintcache -dist -.idea -build/ -.env* -.cache* -.serverless -.serverless_nextjs -.serverless_plugins -env.js -tmp -package-lock.json -yarn.lock -test -logs/ diff --git a/README.md b/README.md deleted file mode 100644 index 0298f14..0000000 --- a/README.md +++ /dev/null @@ -1,112 +0,0 @@ -[![Serverless Fullstack Application Express React DynamoDB AWS Lambda AWS HTTP API](https://s3.amazonaws.com/assets.github.serverless/components/readme-serverless-framework-fullstack-application.png -)](https://www.serverless-fullstack-app.com) - -A complete, serverless, full-stack application built on AWS Lambda, AWS HTTP API, Express.js, React and DynamoDB. - -#### Live Demo: [https://www.serverless-fullstack-app.com](https://www.serverless-fullstack-app.com) - -## Quick Start - -Install the latest version of the Serverless Framework: - - -``` -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 -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` - -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`. - -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! - -If you want to add custom domains to your landing pages and API, either hardcode them in your `serverless.yml` or reference them as environment variables in `serverless.yml`, like this: - -```yaml -inputs: - domain: ${env:domain} -``` - -```text -domain=serverless-fullstack-app.com -``` - -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` - -Or, you can hardcode the stage in `serverless.yml` (not recommended): - -```yaml -app: fullstack -component: express@0.0.20 -name: fullstack-api -stage: prod # Put the stage in here -``` - -Lastly, you can add separate environment variables for each stage using `.env` files with the stage name in them: - -```bash -.env # Any stage -.env.dev # "dev" stage only -.env.prod # "prod" stage only -``` - -Then simply reference those environment variables using Serverless Variables in your YAML: - -```yaml -app: fullstack -component: express@0.0.20 -name: fullstack-api - -inputs: - domain: api.${env:domain} -``` - -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) - -## 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) diff --git a/api/.eslintrc.json b/api/.eslintrc.json deleted file mode 100644 index 611096a..0000000 --- a/api/.eslintrc.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "extends": ["eslint:recommended", "prettier"], - "env": { - "node": true, - "browser": false, - "es6": true, - "mocha": true - }, - "parserOptions": { - "ecmaVersion": 2018 - } -} diff --git a/api/.prettierignore b/api/.prettierignore deleted file mode 100644 index cce0279..0000000 --- a/api/.prettierignore +++ /dev/null @@ -1,2 +0,0 @@ -package.json -package-lock.json diff --git a/api/app.js b/api/app.js deleted file mode 100644 index 626ee77..0000000 --- a/api/app.js +++ /dev/null @@ -1,105 +0,0 @@ -const express = require(`express`); -const pino = require(`pino`); -const pinoHttp = require("pino-http"); -const app = express(); -const passport = require(`passport`); -const { users } = require(`./controllers`); - -/** - * logging - */ -let logger = pino(); -if (process.env.name === `test`) { - logger = pino(pino.destination({ dest: `../logs/api.json`, sync: false })); -} -app.use( - pinoHttp({ - logger: logger, - }) -); - -/** - * Configure Passport - */ - -try { - require(`./config/passport`)(passport); -} catch (error) { - console.log(error); -} - -/** - * Configure Express.js Middleware - */ - -// Enable CORS -app.use(function (req, res, next) { - res.header(`Access-Control-Allow-Origin`, `*`); - res.header(`Access-Control-Allow-Methods`, `*`); - res.header(`Access-Control-Allow-Headers`, `*`); - res.header(`x-powered-by`, `serverless-express`); - next(); -}); - -// Initialize Passport and restore authentication state, if any, from the session -app.use(passport.initialize()); -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 - */ - -app.options(`*`, (req, res) => { - res.status(200).send(); -}); - -app.post(`/users/register`, asyncHandler(users.register)); - -app.post(`/users/login`, asyncHandler(users.login)); - -app.get(`/test/`, (req, res) => { - res.status(200).send(`Request received`); -}); - -/** - * Routes - Protected - */ - -app.post( - `/user`, - passport.authenticate(`jwt`, { session: false }), - asyncHandler(users.get) -); - -/** - * Routes - Catch-All - */ - -app.get(`/*`, (req, res) => { - res.status(404).send(`Route not found`); -}); - -/** - * Error Handler - */ -app.use(function (err, req, res, next) { - if (res.headersSent) { - return next(err); - } - req.log.error(err); - res.status(err.code || 500); - res.json({ - error: err.message || `Internal Server Error - "${err.message}"`, - }); -}); - -module.exports = app; diff --git a/api/config/passport.js b/api/config/passport.js deleted file mode 100644 index a68a18e..0000000 --- a/api/config/passport.js +++ /dev/null @@ -1,31 +0,0 @@ -/** - * Config: Passport.js - */ - -const StrategyJWT = require(`passport-jwt`).Strategy; -const ExtractJWT = require(`passport-jwt`).ExtractJwt; -const userUtils = require(`../controllers/users/utils`); -const db = require(`../db`); - -module.exports = (passport) => { - const options = {}; - options.jwtFromRequest = ExtractJWT.fromAuthHeaderAsBearerToken(); - options.secretOrKey = process.env.tokenSecret; - - passport.use( - new StrategyJWT(options, async (jwtPayload, done) => { - let user; - try { - user = await db.getById(`user`, jwtPayload.id); - } catch (error) { - console.log(error); - return done(error, null); - } - - if (!user) { - return done(null, false); - } - return done(null, userUtils.convertToPublicFormat(user)); - }) - ); -}; diff --git a/api/controllers/base/index.js b/api/controllers/base/index.js deleted file mode 100644 index a8235f6..0000000 --- a/api/controllers/base/index.js +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Controller base actions - * - * This module contains base actions that follow - * a template for CRUD operations on a DB and (optionally) - * do custom things afterward to return a response. - */ - -const validation = require(`../../validation`); -const db = require(`../../db`); - -const createAction = async (req, res, config) => { - validation.validateOrThrow(config.validationSchema, req.body); - - const key = config.getObjectKey(); - let existingObject = await db.getByKey(key); - if (existingObject) { - throw customError( - `An object with key "${key}" already exists in the database.`, - 400 - ); - } - - const dbObject = config.buildDbObject(req.body); - await db.put(config.dbKind, dbObject); - const createdObject = await db.getByKey(key); - - const responseBody = config.buildResponseBody(createdObject); - res.json(responseBody); -}; - -const getByKeyAction = async (req, res, config) => { - validation.validateOrThrow(config.validationSchema, req.body); - const key = config.getObjectKey(); - let existingObject = await db.getByKey(key); - - if (!existingObject) { - return res - .status(404) - .send({ error: config.notFoundMessage }); - } - - const responseBody = config.buildResponseBody(existingObject); - res.json(responseBody); -}; - -/** - * Build a custom error - * @param {string} message Error message - * @param {number} code Error code, should be HTTP status code - */ -const customError = (message = "An error occurred.", code = 500) => { - const error = new Error(message); - error.code = code; - return error; -}; - -module.exports = { - createAction, - getByKeyAction, -}; diff --git a/api/controllers/index.js b/api/controllers/index.js deleted file mode 100644 index ce3f1b6..0000000 --- a/api/controllers/index.js +++ /dev/null @@ -1,5 +0,0 @@ -const users = require(`./users`); - -module.exports = { - users, -}; diff --git a/api/controllers/users/index.js b/api/controllers/users/index.js deleted file mode 100644 index fadd5c1..0000000 --- a/api/controllers/users/index.js +++ /dev/null @@ -1,77 +0,0 @@ -/** - * Controllers: Users - */ - -const schemas = require(`./schemas`); -const base = require(`../base`); -const userUtils = require(`./utils`); - -/** - * Save - * @param {*} req - * @param {*} res - */ -const register = async (req, res) => { - const config = { - validationSchema: schemas.create, - getObjectKey: () => req.body.email, - buildDbObject: () => { - return { - hk: req.body.email, - password: userUtils.hashPassword(req.body.password) - }; - }, - dbKind: `user`, - buildResponseBody: createdUser => { - return { - message: `Authentication successful`, - token: userUtils.getToken(createdUser), - }; - } - }; - await base.createAction(req, res, config); -}; - -/** - * Sign a user in - * @param {*} req - * @param {*} res - */ -const login = async (req, res) => { - const config = { - validationSchema: schemas.login, - getObjectKey: () => req.body.email, - notFoundMessage: `Authentication failed. User not found.`, - buildResponseBody: user => { - const isCorrect = userUtils.comparePassword(req.body.password, user.password); - if (!isCorrect) { - return res - .status(401) - .send({ error: `Authentication failed. Wrong password.` }); - } - - return { - message: `Authentication successful`, - token: userUtils.getToken(user), - }; - } - }; - - await base.getByKeyAction(req, res, config); -}; - -/** - * Get a user - * @param {*} req - * @param {*} res - */ -const get = async (req, res) => { - const user = userUtils.convertToPublicFormat(req.user); - res.json({ user }); -}; - -module.exports = { - register, - login, - get, -}; diff --git a/api/controllers/users/schemas.js b/api/controllers/users/schemas.js deleted file mode 100644 index 8900cf2..0000000 --- a/api/controllers/users/schemas.js +++ /dev/null @@ -1,36 +0,0 @@ -const commonSchemas = require(`../../validation/commonSchemas`); - -const login = { - $schema: "http://json-schema.org/draft-07/schema#", - title: "Login User", - description: "An object to log-in a new user", - type: "object", - properties: { - email: commonSchemas.email, - password: { - type: "string", - }, - }, - required: ["email", "password"], -}; - -const create = { - $schema: "http://json-schema.org/draft-07/schema#", - title: "Create User", - description: "An object to create a new user", - type: "object", - properties: { - email: commonSchemas.email, - password: { - type: "string", - minLength: 10, - maxLength: 50, - }, - }, - required: ["email", "password"], -}; - -module.exports = { - login, - create -}; diff --git a/api/controllers/users/utils.js b/api/controllers/users/utils.js deleted file mode 100644 index 11b29bc..0000000 --- a/api/controllers/users/utils.js +++ /dev/null @@ -1,59 +0,0 @@ -/* - * User utilities - */ - -const bcrypt = require(`bcryptjs`); -const jwt = require(`jsonwebtoken`); - -const getToken = (user) => { - return jwt.sign( - convertToPublicFormat(user), - process.env.tokenSecret, - { - expiresIn: 604800, // 1 week - } - ); -}; - -const convertToPublicFormat = (user = {}) => { - user.email = user.email || user.hk || null; - user.id = user.id || user.sk2 || null; - if (user.hk) { - delete user.hk; - } - if (user.sk) { - delete user.sk; - } - if (user.sk2) { - delete user.sk2; - } - if (user.password) { - delete user.password; - } - return user; -}; - -/** - * Hash password - * @param {string} password Password to hash - */ -const hashPassword = (password) => { - const salt = bcrypt.genSaltSync(10); - return bcrypt.hashSync(password, salt); -}; - -/** - * Compare password - * @param {string} candidatePassword Hashed password supplied by user - * @param {string} trustedPassword Hashed password on record for user - */ -const comparePassword = (candidatePassword, trustedPassword) => { - return bcrypt.compareSync(candidatePassword, trustedPassword); -}; - -module.exports = { - getToken, - convertToPublicFormat, - hashPassword, - comparePassword, -} diff --git a/api/db/index.js b/api/db/index.js deleted file mode 100644 index f639496..0000000 --- a/api/db/index.js +++ /dev/null @@ -1,61 +0,0 @@ -const AWS = require(`aws-sdk`); -const shortid = require(`shortid`); -const commonSchemas = require(`../validation/commonSchemas`); -const validation = require(`../validation`); - -const dynamodb = new AWS.DynamoDB.DocumentClient({ - region: process.env.AWS_REGION, -}); - -const defaultParams = { - TableName: process.env.db, -}; - -const put = async (kind, item) => { - const params = { - ...defaultParams, - Item: { - ...item, - sk: kind, - sk2: shortid.generate(), - createdAt: Date.now(), - updatedAt: Date.now(), - }, - }; - - await dynamodb.put(params).promise(); -}; - -const getByKey = async (key) => { - const params = { - ...defaultParams, - KeyConditionExpression: `hk = :hk`, - ExpressionAttributeValues: { ":hk": key }, - }; - - const obj = await dynamodb.query(params).promise(); - return obj.Items && obj.Items[0] ? obj.Items[0] : null; -}; - -const getById = async (kind, id) => { - validation.validateOrThrow(commonSchemas.id, id); - - const params = { - ...defaultParams, - IndexName: process.env.dbIndex1, - KeyConditionExpression: `sk2 = :sk2 and sk = :sk`, - ExpressionAttributeValues: { - ":sk2": id, - ":sk": kind, - }, - }; - - const obj = await dynamodb.query(params).promise(); - return obj.Items && obj.Items[0] ? obj.Items[0] : null; -}; - -module.exports = { - put, - getByKey, - getById, -}; diff --git a/api/package.json b/api/package.json deleted file mode 100644 index dd9cfa4..0000000 --- a/api/package.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "name": "forgetmenot-api", - "version": "1.0.0", - "description": "", - "main": "app.js", - "dependencies": { - "ajv": "^6.12.6", - "aws-sdk": "^2.792.0", - "bcryptjs": "^2.4.3", - "express": "^4.17.1", - "jsonwebtoken": "^8.5.1", - "passport": "^0.4.1", - "passport-jwt": "^4.0.0", - "pino-http": "^5.3.0", - "shortid": "^2.2.15" - }, - "devDependencies": { - "chai": "^4.2.0", - "chai-http": "^4.3.0", - "eslint": "^7.12.1", - "eslint-config-prettier": "^6.15.0", - "faker": "^5.1.0", - "mocha": "^8.2.1", - "prettier": "^2.1.2" - }, - "scripts": { - "pretest": "eslint --ignore-path ../.gitignore .", - "test": "mocha", - "format": "prettier --write \"**/*.{js,json,md,yml}\"" - }, - "author": "", - "license": "ISC" -} diff --git a/api/serverless.yml b/api/serverless.yml deleted file mode 100644 index 18e9d56..0000000 --- a/api/serverless.yml +++ /dev/null @@ -1,18 +0,0 @@ -component: express -name: api - -inputs: - # Express application source code. - src: ./ - # Permissions required for the AWS Lambda function to interact with other resources - roleName: ${output:permissions.name} - # Enable this when you want to set a custom domain. - # domain: api.${env:domain} - # Environment variables - env: - # AWS DynamoDB Table name. Needed for the code to access it. - db: ${output:database.name} - # 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} # Change to secret via environment variable: ${env:tokenSecret} diff --git a/api/validation/commonSchemas.js b/api/validation/commonSchemas.js deleted file mode 100644 index a4230cc..0000000 --- a/api/validation/commonSchemas.js +++ /dev/null @@ -1,10 +0,0 @@ -module.exports = { - "email": { - "type": "string", - "format": "email" - }, - "id": { - "type": "string", - "minLength": 1 - } -} diff --git a/api/validation/index.js b/api/validation/index.js deleted file mode 100644 index 37eeddc..0000000 --- a/api/validation/index.js +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Validation - */ - -const Ajv = require(`ajv`); - -const validateOrThrow = (schema, data) => { - const ajv = new Ajv(); - const valid = ajv.validate(schema, data); - - if (!valid) { - throw validationError(ajv.errors); - } -}; - -/** - * Build a custom validation error - * @param {array[string]} validationErrors Validation errors - */ -const validationError = (validationErrors = []) => { - let error = new Error("Validation error(s)"); - error.validationErrors = validationErrors; - error.code = 400; - return error; -}; - -module.exports = { - validateOrThrow, -}; diff --git a/database/serverless.yml b/database/serverless.yml deleted file mode 100644 index 1313f81..0000000 --- a/database/serverless.yml +++ /dev/null @@ -1,30 +0,0 @@ -component: aws-dynamodb -name: database - -inputs: - name: ${name}-${stage} - 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 - - AttributeName: sk - AttributeType: S - - AttributeName: sk2 - AttributeType: S - keySchema: - - AttributeName: hk - KeyType: HASH - - AttributeName: sk - KeyType: RANGE - globalSecondaryIndexes: - - IndexName: gsi1 - KeySchema: - - AttributeName: sk2 - KeyType: HASH - - AttributeName: sk - KeyType: RANGE - Projection: - ProjectionType: ALL diff --git a/permissions/serverless.yml b/permissions/serverless.yml deleted file mode 100644 index 19f7b75..0000000 --- a/permissions/serverless.yml +++ /dev/null @@ -1,28 +0,0 @@ -component: aws-iam-role -name: permissions - -inputs: - name: ${name}-${stage} - region: us-east-1 - service: lambda.amazonaws.com - policy: - # AWS Lambda function containing Express Logs and Assume Role access - - Effect: Allow - Action: - - sts:AssumeRole - - logs:CreateLogGroup - - logs:CreateLogStream - - logs:PutLogEvents - Resource: "*" - # AWS DynamoDB Table access - - Effect: Allow - Action: - - dynamodb:DescribeTable - - dynamodb:Query - - dynamodb:GetItem - - dynamodb:PutItem - - dynamodb:UpdateItem - - dynamodb:DeleteItem - Resource: - - ${output:database.arn} - - ${output:database.arn}/index/* diff --git a/serverless.yml b/serverless.yml deleted file mode 100644 index 867daae..0000000 --- a/serverless.yml +++ /dev/null @@ -1,2 +0,0 @@ -app: forget-me-not -org: benjaminramey diff --git a/site/.eslintrc.json b/site/.eslintrc.json deleted file mode 100644 index a134b11..0000000 --- a/site/.eslintrc.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "extends": ["eslint:recommended", "prettier"], - "env": { - "node": false, - "browser": true, - "es6": true - }, - "parserOptions": { - "ecmaVersion": 2018 - } -} diff --git a/site/.gitignore b/site/.gitignore deleted file mode 100644 index f813275..0000000 --- a/site/.gitignore +++ /dev/null @@ -1,69 +0,0 @@ -# Logs -logs -*.log -npm-debug.log* -yarn-debug.log* -yarn-error.log* - -# Runtime data -pids -*.pid -*.seed -*.pid.lock - -# Directory for instrumented libs generated by jscoverage/JSCover -lib-cov - -# Coverage directory used by tools like istanbul -coverage - -# nyc test coverage -.nyc_output - -# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) -.grunt - -# Bower dependency directory (https://bower.io/) -bower_components - -# node-waf configuration -.lock-wscript - -# Compiled binary addons (http://nodejs.org/api/addons.html) -build/Release - -# Dependency directories -node_modules/ -jspm_packages/ - -# Typescript v1 declaration files -typings/ - -# Optional npm cache directory -.npm - -# Optional eslint cache -.eslintcache - -# Optional REPL history -.node_repl_history - -# Output of 'npm pack' -*.tgz - -# dotenv environment variable files -.env* - -# gatsby files -.cache/ -public - -# Mac files -.DS_Store - -# Yarn -yarn-error.log -.pnp/ -.pnp.js -# Yarn Integrity file -.yarn-integrity diff --git a/site/.prettierignore b/site/.prettierignore deleted file mode 100644 index 58d06c3..0000000 --- a/site/.prettierignore +++ /dev/null @@ -1,4 +0,0 @@ -.cache -package.json -package-lock.json -public diff --git a/site/LICENSE b/site/LICENSE deleted file mode 100644 index 7e964c1..0000000 --- a/site/LICENSE +++ /dev/null @@ -1,14 +0,0 @@ -The BSD Zero Clause License (0BSD) - -Copyright (c) 2020 Gatsby Inc. - -Permission to use, copy, modify, and/or distribute this software for any -purpose with or without fee is hereby granted. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH -REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, -INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR -OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -PERFORMANCE OF THIS SOFTWARE. diff --git a/site/README.md b/site/README.md deleted file mode 100644 index b40d274..0000000 --- a/site/README.md +++ /dev/null @@ -1,99 +0,0 @@ - -

- - Gatsby - -

-

- Gatsby's hello-world starter -

- -Kick off your project with this hello-world boilerplate. This starter ships with the main Gatsby configuration files you might need to get up and running blazing fast with the blazing fast app generator for React. - -_Have another more specific idea? You may want to check out our vibrant collection of [official and community-created starters](https://www.gatsbyjs.com/docs/gatsby-starters/)._ - -## πŸš€ Quick start - -1. **Create a Gatsby site.** - - Use the Gatsby CLI to create a new site, specifying the hello-world starter. - - ```shell - # create a new Gatsby site using the hello-world starter - gatsby new my-hello-world-starter https://github.com/gatsbyjs/gatsby-starter-hello-world - ``` - -1. **Start developing.** - - Navigate into your new site’s directory and start it up. - - ```shell - cd my-hello-world-starter/ - gatsby develop - ``` - -1. **Open the source code and start editing!** - - Your site is now running at `http://localhost:8000`! - - _Note: You'll also see a second link: _`http://localhost:8000/___graphql`_. This is a tool you can use to experiment with querying your data. Learn more about using this tool in the [Gatsby tutorial](https://www.gatsbyjs.com/tutorial/part-five/#introducing-graphiql)._ - - Open the `my-hello-world-starter` directory in your code editor of choice and edit `src/pages/index.js`. Save your changes and the browser will update in real time! - -## 🧐 What's inside? - -A quick look at the top-level files and directories you'll see in a Gatsby project. - - . - β”œβ”€β”€ node_modules - β”œβ”€β”€ src - β”œβ”€β”€ .gitignore - β”œβ”€β”€ .prettierrc - β”œβ”€β”€ gatsby-browser.js - β”œβ”€β”€ gatsby-config.js - β”œβ”€β”€ gatsby-node.js - β”œβ”€β”€ gatsby-ssr.js - β”œβ”€β”€ LICENSE - β”œβ”€β”€ package-lock.json - β”œβ”€β”€ package.json - └── README.md - -1. **`/node_modules`**: This directory contains all of the modules of code that your project depends on (npm packages) are automatically installed. - -2. **`/src`**: This directory will contain all of the code related to what you will see on the front-end of your site (what you see in the browser) such as your site header or a page template. `src` is a convention for β€œsource code”. - -3. **`.gitignore`**: This file tells git which files it should not track / not maintain a version history for. - -4. **`.prettierrc`**: This is a configuration file for [Prettier](https://prettier.io/). Prettier is a tool to help keep the formatting of your code consistent. - -5. **`gatsby-browser.js`**: This file is where Gatsby expects to find any usage of the [Gatsby browser APIs](https://www.gatsbyjs.com/docs/browser-apis/) (if any). These allow customization/extension of default Gatsby settings affecting the browser. - -6. **`gatsby-config.js`**: This is the main configuration file for a Gatsby site. This is where you can specify information about your site (metadata) like the site title and description, which Gatsby plugins you’d like to include, etc. (Check out the [config docs](https://www.gatsbyjs.com/docs/gatsby-config/) for more detail). - -7. **`gatsby-node.js`**: This file is where Gatsby expects to find any usage of the [Gatsby Node APIs](https://www.gatsbyjs.com/docs/node-apis/) (if any). These allow customization/extension of default Gatsby settings affecting pieces of the site build process. - -8. **`gatsby-ssr.js`**: This file is where Gatsby expects to find any usage of the [Gatsby server-side rendering APIs](https://www.gatsbyjs.com/docs/ssr-apis/) (if any). These allow customization of default Gatsby settings affecting server-side rendering. - -9. **`LICENSE`**: This Gatsby starter is licensed under the 0BSD license. This means that you can see this file as a placeholder and replace it with your own license. - -10. **`package-lock.json`** (See `package.json` below, first). This is an automatically generated file based on the exact versions of your npm dependencies that were installed for your project. **(You won’t change this file directly).** - -11. **`package.json`**: A manifest file for Node.js projects, which includes things like metadata (the project’s name, author, etc). This manifest is how npm knows which packages to install for your project. - -12. **`README.md`**: A text file containing useful reference information about your project. - -## πŸŽ“ Learning Gatsby - -Looking for more guidance? Full documentation for Gatsby lives [on the website](https://www.gatsbyjs.com/). Here are some places to start: - -- **For most developers, we recommend starting with our [in-depth tutorial for creating a site with Gatsby](https://www.gatsbyjs.com/tutorial/).** It starts with zero assumptions about your level of ability and walks through every step of the process. - -- **To dive straight into code samples, head [to our documentation](https://www.gatsbyjs.com/docs/).** In particular, check out the _Guides_, _API Reference_, and _Advanced Tutorials_ sections in the sidebar. - -## πŸ’« Deploy - -[![Deploy to Netlify](https://www.netlify.com/img/deploy/button.svg)](https://app.netlify.com/start/deploy?repository=https://github.com/gatsbyjs/gatsby-starter-hello-world) - -[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/import/project?template=https://github.com/gatsbyjs/gatsby-starter-hello-world) - - diff --git a/site/config.js b/site/config.js deleted file mode 100644 index c3e57d6..0000000 --- a/site/config.js +++ /dev/null @@ -1,18 +0,0 @@ -/** - * 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 = "https://13gtp0hrak.execute-api.us-east-1.amazonaws.com"; - -export default config; diff --git a/site/gatsby-config.js b/site/gatsby-config.js deleted file mode 100644 index e24936b..0000000 --- a/site/gatsby-config.js +++ /dev/null @@ -1,10 +0,0 @@ -/** - * Configure your Gatsby site with this file. - * - * See: https://www.gatsbyjs.com/docs/gatsby-config/ - */ - -module.exports = { - /* Your site config here */ - plugins: [], -}; diff --git a/site/package.json b/site/package.json deleted file mode 100644 index 27371bc..0000000 --- a/site/package.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "name": "forget-me-not-site", - "private": true, - "description": "Forget Me Not site for saving bookmarks", - "version": "0.1.0", - "license": "0BSD", - "scripts": { - "build": "gatsby build", - "develop": "gatsby develop", - "format": "prettier --write \"**/*.{js,jsx,ts,tsx,json,md,yml}\"", - "start": "npm run develop", - "serve": "gatsby serve", - "clean": "gatsby clean", - "test": "echo \"Write tests! -> https://gatsby.dev/unit-testing\" && exit 1" - }, - "dependencies": { - "gatsby": "^2.25.3", - "js-cookie": "^2.2.1", - "moment": "^2.24.0", - "react": "^16.12.0", - "react-bootstrap": "^1.4.0", - "react-dom": "^16.12.0", - "react-router-dom": "^5.1.2" - }, - "devDependencies": { - "eslint": "^7.12.1", - "eslint-config-prettier": "^6.15.0", - "prettier": "^2.1.2" - }, - "repository": { - "type": "git", - "url": "https://github.com/gatsbyjs/gatsby-starter-hello-world" - }, - "bugs": { - "url": "https://github.com/gatsbyjs/gatsby/issues" - } -} diff --git a/site/public/android-chrome-192x192.png b/site/public/android-chrome-192x192.png deleted file mode 100644 index 050fdbf..0000000 Binary files a/site/public/android-chrome-192x192.png and /dev/null differ diff --git a/site/public/android-chrome-512x512.png b/site/public/android-chrome-512x512.png deleted file mode 100644 index 5e1f8ee..0000000 Binary files a/site/public/android-chrome-512x512.png and /dev/null differ diff --git a/site/public/apple-touch-icon.png b/site/public/apple-touch-icon.png deleted file mode 100644 index eadddf2..0000000 Binary files a/site/public/apple-touch-icon.png and /dev/null differ diff --git a/site/public/favicon-16x16.png b/site/public/favicon-16x16.png deleted file mode 100644 index 8a3c249..0000000 Binary files a/site/public/favicon-16x16.png and /dev/null differ diff --git a/site/public/favicon-32x32.png b/site/public/favicon-32x32.png deleted file mode 100644 index 0624682..0000000 Binary files a/site/public/favicon-32x32.png and /dev/null differ diff --git a/site/public/favicon.ico b/site/public/favicon.ico deleted file mode 100644 index 1a466ba..0000000 Binary files a/site/public/favicon.ico and /dev/null differ diff --git a/site/public/index.html b/site/public/index.html deleted file mode 100644 index 48b0944..0000000 --- a/site/public/index.html +++ /dev/null @@ -1 +0,0 @@ -
\ No newline at end of file diff --git a/site/public/manifest.json b/site/public/manifest.json deleted file mode 100644 index 2ffa886..0000000 --- a/site/public/manifest.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "short_name": "Forget Me Not", - "name": "Forget Me Not", - "icons": [ - { - "src": "favicon.ico", - "sizes": "64x64 32x32 24x24 16x16", - "type": "image/x-icon" - }, - { - "src": "android-chrome-192x192.png", - "type": "image/png", - "sizes": "192x192" - }, - { - "src": "android-chrome-512x512.png", - "type": "image/png", - "sizes": "512x512" - } - ], - "start_url": ".", - "display": "standalone", - "theme_color": "#000000", - "background_color": "#ffffff" -} diff --git a/site/public/robots.txt b/site/public/robots.txt deleted file mode 100644 index e9e57dc..0000000 --- a/site/public/robots.txt +++ /dev/null @@ -1,3 +0,0 @@ -# https://www.robotstxt.org/robotstxt.html -User-agent: * -Disallow: diff --git a/site/serverless.yml b/site/serverless.yml deleted file mode 100644 index 106ae28..0000000 --- a/site/serverless.yml +++ /dev/null @@ -1,11 +0,0 @@ -component: website -name: 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: public - # Enable this when you want to set a custom domain. - # domain: ${env:domain} diff --git a/site/src/pages/index.js b/site/src/pages/index.js deleted file mode 100644 index 23f2a29..0000000 --- a/site/src/pages/index.js +++ /dev/null @@ -1,14 +0,0 @@ -import React from "react"; -import { Container, Row, Col } from "react-bootstrap"; - -export default function Home() { - return ( - - - -

Hello world!

- -
-
- ); -} diff --git a/site/src/utils/api.js b/site/src/utils/api.js deleted file mode 100644 index 6edee91..0000000 --- a/site/src/utils/api.js +++ /dev/null @@ -1,70 +0,0 @@ -/** - * Utils: Back-end - */ - -import config from "../../config"; - -/** - * Register a new user - */ -export const userRegister = async (email, password) => { - return await requestApi("/users/register", "POST", { email, password }); -}; - -/** - * Login a new user - */ -export const userLogin = async (email, password) => { - return await requestApi("/users/login", "POST", { email, password }); -}; - -/** - * userGet - */ -export const userGet = async (token) => { - return await requestApi("/user", "POST", null, { - Authorization: `Bearer ${token}`, - }); -}; - -/** - * API request to call the backend - */ -export const requestApi = async ( - 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 "site" folder, in the "./config.js" file. Instructions are listed there and in the documentation.` - ); - } - - // Prepare URL - if (!path.startsWith("/")) { - path = `/${path}`; - } - const url = `${config.domains.api}${path}`; - - // Set headers - headers = Object.assign({ "Content-Type": "application/json" }, headers); - - // Default options are marked with * - const response = await fetch(url, { - method: method.toUpperCase(), - mode: "cors", - cache: "no-cache", - headers, - body: data ? JSON.stringify(data) : null, - }); - - if (response.status < 200 || response.status >= 300) { - const error = await response.json(); - throw new Error(error.error); - } - - return await response.json(); -}; diff --git a/site/src/utils/helpers.js b/site/src/utils/helpers.js deleted file mode 100644 index df3875e..0000000 --- a/site/src/utils/helpers.js +++ /dev/null @@ -1,81 +0,0 @@ -import Cookies from "js-cookie"; - -/** - * Format Org and Username correctly for the Serverless Platform backend - */ -export const formatOrgAndUsername = (name = "") => { - name = name - .toString() - .toLowerCase() - .replace(/[^a-z\d-]+/gi, "-"); - // Remove multiple instances of hyphens - name = name.replace(/-{2,}/g, "-"); - if (name.length > 40) { - name = name.substring(0, 40); - } - return name; -}; - -/** - * Parse query parameters in a URL - * @param {*} searchString - */ -export const parseQueryParams = (searchString = null) => { - if (!searchString) { - return null; - } - - // Clone string - let clonedParams = (" " + searchString).slice(1); - - return clonedParams - .substr(1) - .split("&") - .filter((el) => el.length) - .map((el) => el.split("=")) - .reduce( - (accumulator, currentValue) => - Object.assign(accumulator, { - [decodeURIComponent( - currentValue.shift() - )]: decodeURIComponent(currentValue.pop()), - }), - {} - ); -}; - -/** - * Parse hash fragment parameters in a URL - */ -export const parseHashFragment = (hashString) => { - const hashData = {}; - let hash = decodeURI(hashString); - hash = hash.split("&"); - hash.forEach((val) => { - val = val.replace("#", ""); - hashData[val.split("=")[0]] = val.split("=")[1]; - }); - return hashData; -}; - -/** - * Save session in browser cookie - */ -export const saveSession = (userId, userEmail, userToken) => { - Cookies.set("serverless", { userId, userEmail, userToken }); -}; - -/** - * Get session in browser cookie - */ -export const getSession = () => { - const data = Cookies.get("serverless"); - return data ? JSON.parse(data) : null; -}; - -/** - * Delete session in browser cookie - */ -export const deleteSession = () => { - Cookies.remove("serverless"); -}; diff --git a/site/src/utils/index.js b/site/src/utils/index.js deleted file mode 100644 index 189da4d..0000000 --- a/site/src/utils/index.js +++ /dev/null @@ -1,2 +0,0 @@ -export * from "./helpers"; -export * from "./api"; diff --git a/site/static/android-chrome-192x192.png b/site/static/android-chrome-192x192.png deleted file mode 100644 index 050fdbf..0000000 Binary files a/site/static/android-chrome-192x192.png and /dev/null differ diff --git a/site/static/android-chrome-512x512.png b/site/static/android-chrome-512x512.png deleted file mode 100644 index 5e1f8ee..0000000 Binary files a/site/static/android-chrome-512x512.png and /dev/null differ diff --git a/site/static/apple-touch-icon.png b/site/static/apple-touch-icon.png deleted file mode 100644 index eadddf2..0000000 Binary files a/site/static/apple-touch-icon.png and /dev/null differ diff --git a/site/static/favicon-16x16.png b/site/static/favicon-16x16.png deleted file mode 100644 index 8a3c249..0000000 Binary files a/site/static/favicon-16x16.png and /dev/null differ diff --git a/site/static/favicon-32x32.png b/site/static/favicon-32x32.png deleted file mode 100644 index 0624682..0000000 Binary files a/site/static/favicon-32x32.png and /dev/null differ diff --git a/site/static/favicon.ico b/site/static/favicon.ico deleted file mode 100644 index 1a466ba..0000000 Binary files a/site/static/favicon.ico and /dev/null differ diff --git a/site/static/manifest.json b/site/static/manifest.json deleted file mode 100644 index 2ffa886..0000000 --- a/site/static/manifest.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "short_name": "Forget Me Not", - "name": "Forget Me Not", - "icons": [ - { - "src": "favicon.ico", - "sizes": "64x64 32x32 24x24 16x16", - "type": "image/x-icon" - }, - { - "src": "android-chrome-192x192.png", - "type": "image/png", - "sizes": "192x192" - }, - { - "src": "android-chrome-512x512.png", - "type": "image/png", - "sizes": "512x512" - } - ], - "start_url": ".", - "display": "standalone", - "theme_color": "#000000", - "background_color": "#ffffff" -} diff --git a/site/static/robots.txt b/site/static/robots.txt deleted file mode 100644 index e9e57dc..0000000 --- a/site/static/robots.txt +++ /dev/null @@ -1,3 +0,0 @@ -# https://www.robotstxt.org/robotstxt.html -User-agent: * -Disallow: