Code Monkey home page Code Monkey logo

boilerplate-graphql's Introduction

Boilerplate

Built by No Quarter

NOTE: We now recommend using our updated stack.


Typescript + React + React Native + GraphQL + Prisma

Comes with user authentication included

  • React
  • React Native
  • Expo
  • TypeGraphQL
  • Prisma
  • Web, App & API monorepo
  • Next.js
  • TypeScript
  • Postgres
  • Apollo Client
  • Apollo Server
  • Express
  • React hook form
  • Chakra UI
  • Customizable theme & Dark mode
  • Eslint
  • Prettier
  • Graphql Code Generator
  • Sendgrid SMTP
  • Sentry
  • Husky
  • Lint staged

& many more tasty treats


Feel comfortable with this stack?

We are hiring! Contact us here


Get Started

You must have node, yarn, postgres and redis installed and setup locally

  1. Clone the repo

  2. Delete the app folder if you're working on a purely web project.

    rm -rf packages/app
  3. Install dependencies.

    yarn install
  4. Create local postgres database

    createdb boilerplate
  5. Create a .env file and update the DATABASE_URL with your local postgres database url.

    cp packages/api/.env.example  packages/api/.env
    # Replace <user>,<password> and <db-name> with your corresponding username, password, and database name of your postgresql database.
    DATABASE_URL=postgresql://<user>:<password>@localhost:5432/<db-name>
  6. Migrate the database.

    cd packages/api && yarn db:migrate


We use Husky to run a couple of checks each commit (prettier, eslint & commitlint), make sure to add a .huskyrc file to your home directory:

touch ~/.huskyrc

and copy this into the file this in:

export PATH="/usr/local/bin:$PATH"

then run this in the root of the project:

npx husky install

We use AWS S3 for image/file hosting, so you'll need to set up a few things for this to work, process can be found here.



Development

  1. cd packages/api && yarn dev
  2. cd packages/web && yarn dev
  3. cd packages/app && yarn start

An example of creating a simple todo feature can be found here.



Production

Mailers

  • Create a Sendgrid account and set a SENDGRID_API_KEY environment variable in .env
  • Create templates for each email you want to send and use the templateId in the corresponding mailer class

Error tracing

  • Create a Sentry account + project for each package and add the DSN to the web config and the api env variables

Deployment

An example is deployed here

We are using Railway for the API package and Vercel for the WEB package

For railway we have setup preview deploys and that gives a dynamic url that the web can use. The url includes the PR number so on the web we need to grab the PR number from git and dynamically change the API_URL when building the Next.js app. Vercel doesn't include PR numbers in the env variables so we use a package to do that for us.


boilerplate-graphql's People

Contributors

dependabot[bot] avatar jclackett avatar lewisblackburn avatar renovate-bot avatar renovate[bot] avatar rykuno avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

boilerplate-graphql's Issues

Documentation: SSR

Looks like a promising boilerplate... Could you pl. explain to the novice developers like me how SSR is working? The transfer of "state" from server to client side is really a concern, kindly explain that.

Also, it'd be great if you can provide leads how to proceed ahead after an page initial page is rendered.

Thanks

Authentication token in Apollo Studio Explorer

Hi Jack,

What is the format for the Authentication header in the Apollo studio explorer?

I can't seem to find a key value pair that works to recognise the token. All my queries return not authorised (apart from the me query, which returns null data) - even when the login mutation runs.

Is there a specific syntax for JWT in the Apollo Studio Explorer header?

thank you

Husky config

Hi,

thank you for making this demo.

When you say:

We use Husky to run a couple of checks each commit (prettier, eslint & commitlint), make sure to add a .huskyrc file to your home directory ~/.huskyrc, and add this in:

Do you mean that I should add a file at the root level called .huskyrc?

I did that and it has converted the file structure to:

BOILERPLATE/.husky/.huskyrc

The commit message and pre-commit files are now located in the same folder. Is that what should be created?

Thank you!

yarn install failed to run prisma generate

Hey Jack!
Thank you for putting this boilerplate together! I was trying to do the initial setup of this repo and ran into this issue when running yarn install. Is there something with Prisma that I need to install separately or do I need to setup the .env file for api before running yarn install? I tried deleting node_modules and trying it again to no avail. I also do not have Prisma installed globally. Any insight into this issue would be greatly appreciated!

[4/4] Building fresh packages...
[-/9] ⠈ waiting...
[-/9] ⠈ waiting...
[9/9] ⠈ @boilerplate/api
[-/9] ⠈ waiting...
error [path]\node_modules\@boilerplate\api: Command failed.
Exit code: 1
Command: prisma generate
Arguments:
Directory: [path]\node_modules\@boilerplate\api
node:internal/modules/cjs/loader:936
  throw err;
  ^

Error: Cannot find module '[path]\node_modules\node_modules\prisma\build\index.js'
    at Function.Module._resolveFilename (node:internal/modules/cjs/loader:933:15)
    at Function.Module._load (node:internal/modules/cjs/loader:778:27)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:81:12)
    at node:internal/main/run_main_module:17:47 {
  code: 'MODULE_NOT_FOUND',
  requireStack: []

Forgot password - missing padding

I just saw your reddit comment and viewed the example webpage on mobile.
Some padding is missing on the forgot password page.
grafik

The other pages look good:
grafik

Cors configuration

Hi Jack,

Thank you for sharing this repo - it's so helpful. You've made it really easy to learn your approach.

When I start this, a cors configuraion error arises when I try to upload the avatar image.

The error says:

> Access to fetch at 'https://s3.ap-southeast-2.amazonaws.com/' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

I can see that the api/src/index/ts applies middleware with cors set to true.

If I make the following changes, will I mess other parts of your code around? I'm not sure how to implement cors within this structure.

apolloServer.applyMiddleware({ app, cors: false })
and then add

app.use(cors(corsOptions))

Suggestion: ormconfig.json production entity/migration glob patterns may need improvement

In the ormconfig.json under "name": "production"

we see originally

    "entities": ["packages/api/dist/modules/**/*.entity.js"],
    "migrations": ["packages/api/dist/db/migrations/*.js"],

What worked for me was this pattern (because I wasn't aware node needed the current working directory to be at the root):

    "entities": ["modules/**/*.entity.js"],
    "migrations": ["db/migrations/*.js"],

Perhaps these can be added to the array of glob paths. I've added debug printout in
the createDbConnection function that shows if any files were loaded:

    const entity_names = connection.entityMetadatas.map(entity => entity.name)
    console.log('connection.entities', entity_names)
    console.log('connection.migrations', connection.migrations

I noticed that running heroku local web it does use the original paths. However node running with current working directory of packages/api/dist instead at the root caused my issue.

tl;dr

I suggest adding debug printout in createDbConnection to show the entities and migration files being loaded, just to double check the paths are correct. I had spent couple hours trying to figure out why my production params didn't populate an empty database. It could save others some time.

Missing page to handle self generated reset-password link

This link this is not handled by the CheckAuth router.

https://.localhost:3000/reset-password?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjNhY2NkNjMwLTcxYjEtNGMxOS1hMjM5LTYxMmY1ODE3Nzk4NSIsImlhdCI6MTU4ODM1MDE4OCwiZXhwIjoxNTkwNzY5Mzg4LCJhdWQiOlsiQGZhbmN5c3RhY2svYXBwIiwiQGZhbmN5c3RhY2svd2ViIl0sImlzcyI6IkBmYW5jeXN0YWNrL2FwaSJ9.I-VV2sgiM8lNFcbaQNBXRFYojdrY7zZy63DaGie8w_0

I see the api exists in user.resolver.ts so maybe this page was forgotten to be added. I could create a PR for my version of this page or you guys can add it.

Apollo SSR: Absolute URL Error

Whenever attempting to make a request from the Apollo Client from the API or SSR, you receive an error detailing

Error: Network error: Only absolute URLs are supported
at new ApolloError

To replicate error on main/develop, just try to make a SSR Apollo query or mutation within the index.tsx or within a /api/... route.

This looks to be due to the fact that the /api/graphql proxy is being executed server side in which sends a request to...well..not an absolute URL.

I issued #1776 so you can see where it's happening.

[Question] Custom Errors by extending ApolloError

I've tried to create my own error to throw when login fails too many times:

import { ApolloError } from "apollo-server-errors/src/index"

export class AuthLockdownError extends ApolloError {
  constructor(message: string, properties?: Record<string, any>) {
    super(message, 'AUTH_LOCKDOWN', properties);

    Object.defineProperty(this, 'name', { value: 'AuthLockdownError' });
  }
}

Usage:

 // Handle a login request to the application.
  async login(requestIP: string, data: { email: string; password: string }): Promise<User> {
    ...

    if (AUTH_THROTTLE && await this.hasTooManyLoginAttempts(throttleKey)) {
      throw new AuthLockdownError("Too many loin attempts have failed")
    }

    const isValidPassword = await bcrypt.compare(data.password, user.password)
    ....
  }

When doing so I get the following error

(node:7284) UnhandledPromiseRejectionWarning: D:\graphql-tests\typescript-boilerplate\node_modules\apollo-server-errors\src\index.ts:1
import { GraphQLError, GraphQLFormattedError } from 'graphql';
^^^^^^

SyntaxError: Cannot use import statement outside a module
at wrapSafe (internal/modules/cjs/loader.js:1070:16)
at Module._compile (internal/modules/cjs/loader.js:1120:27)
at Module._compile (D:\graphql-tests\typescript-boilerplate\node_modules\source-map-support\source-map-support.js:521:25)
at Module.m._compile (C:\Users\Hitech95\AppData\Local\Temp\ts-node-dev-hook-8290200771403802.js:57:25)
at Module._extensions..js (internal/modules/cjs/loader.js:1176:10)
at require.extensions. (C:\Users\Hitech95\AppData\Local\Temp\ts-node-dev-hook-8290200771403802.js:59:14)
at Object.nodeDevHook [as .ts] (D:\graphql-tests\typescript-boilerplate\node_modules\ts-node-dev\lib\hook.js:61:7)
at Module.load (internal/modules/cjs/loader.js:1000:32)
at Function.Module._load (internal/modules/cjs/loader.js:899:14)
at Module.require (internal/modules/cjs/loader.js:1042:19)

(node:7284) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To term

I'm quite new with TS/Node but I don't understand why is giving me this issue on a module instead of on my code. Reading online looks like that it have to do with the tsconfig.ts file.

Any suggestyion on how to solve this using this boilerplate?

Not generating fields on Prisma Relations

There's no docs for this page so I hope its cool to ask this here.

Whenever adding a relation to the User model such as shown below, I'm under the impression the typegraphql-prisma package with the help of the lib/loadResolvers function will automatically include the Relation and Crud resolvers as referenced within the docs here

For graphql's introspection to pickup the relations, I'm having to explicitly define the @FieldResovlers in which case I lose the ability to paginate or set limits within my query.

I'm brand new to prisma, type-graphql, and this pattern so I might be misunderstanding the intended use case or pattern here, but is this an intended result or am I utilizing the stack incorrectly?

Resolver

  @FieldResolver(() => UsersResponse)
  async followedBy(@Root() user: User) {
    const items = user.followedBy || []
    const count = user.followedBy?.length || 0
    return { items, count }
  }

  @FieldResolver(() => UsersResponse)
  following(@Root() user: User) {
    const items = user.following || []
    const count = user.following?.length || 0
    return { items, count }
  }

Model

model User {
id          String   @id @default(uuid())
createdAt   DateTime @default(now())
updatedAt   DateTime @default(now()) @updatedAt

followedBy User[] @relation("UserFollows", references: [id])
following  User[] @relation("UserFollows", references: [id])
}

redirect on login success

Hi Jack,

where is the login route coming from?

I'm trying to change the on success handler on the login page to redirect to a different page, but I can't follow whats happening in the direct flow.

Where can I change the redirect router?

thank you

const onSubmit = (data: LoginInput) => {
    return form.handler(() => login({ variables: { data } }), {
      onSuccess: async (data) => {
        await fetch("/api/login", {
          method: "post",
          body: JSON.stringify({ [LOGIN_TOKEN_KEY]: data.login.token }),
        })
        client.writeQuery<MeQuery>({ query: MeDocument, data: { me: data.login.user } })
        router.replace(redirect || "/")
        // router.replace('/dashboard')

      },
    })
  }

I have try to add Todo module, but error

model User {
  id        String   @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid
  email     String   @unique
  /// @TypeGraphQL.omit(output: true)
  password  String
  firstName String
  lastName  String
  avatar    String?
  role      Role     @default(USER)
  bio       String?
  createdAt DateTime @default(now()) @db.Timestamptz(6)
  updatedAt DateTime @default(now()) @updatedAt @db.Timestamptz(6)
}

model Todo {
  id         String   @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid
  title      String
  user       User     @relation(fields: [userId], references: [id])
  userId     String   @db.Uuid
  isComplete Boolean? @default(false)
  createdAt  DateTime @default(now()) @db.Timestamptz(6)
  updatedAt  DateTime @default(now()) @updatedAt @db.Timestamptz(6)
}

Error from terminal

Environment variables loaded from .env
Prisma schema loaded from src/db/schema.prisma
Datasource "db": PostgreSQL database "boilerplate", schema "public" at "localhost:5432"

Error: Schema parsing
error: Error validating field `user` in model `Todo`: The relation field `user` on Model `Todo` is missing an opposite relation field on the model `User`. Either run `prisma format` or add it manually.
  -->  schema.prisma:38
   |
37 |   title      String
38 |   user       User     @relation(fields: [userId], references: [id])
39 |   userId     String   @db.Uuid
   |

Validation Error Count: 1
error Command failed with exit code 1.

Action Required: Fix Renovate Configuration

There is an error with this repository's Renovate configuration that needs to be fixed. As a precaution, Renovate will stop PRs until it is resolved.

File: renovate.json
Error type: The renovate configuration file contains some invalid settings
Message: Invalid regExp for packageRules[0].packagePatterns: eslint, Invalid regExp for packageRules[1].packagePatterns: @types/``

seed.ts file is missed

If you try to run yarn seed you'll get an error. seed.ts file is missed.
(P.S. probably it should be inside of db directory)

Empty .env.example

.env.example is empty. It's hard to set any key which is needed to run backend API.

Can you share keys?

Thanks

Dependency Dashboard

This issue lists Renovate updates and detected dependencies. Read the Dependency Dashboard docs to learn more.

Warning

These dependencies are deprecated:

Datasource Name Replacement PR?
npm @types/express-jwt Unavailable
npm @types/ioredis Unavailable
npm @types/react-native Unavailable
npm vercel-is-pull-request Unavailable

Rate-Limited

These updates are currently rate-limited. Click on a checkbox below to force their creation now.

  • chore(deps): update dependency @types/node to v16.18.106
  • fix(deps): update dependency dayjs to v1.11.13
  • fix(deps): update react-navigation monorepo (@react-navigation/core, @react-navigation/native, @react-navigation/native-stack, @react-navigation/stack)
  • chore(deps): update dependency @babel/core to v7.25.2
  • chore(deps): update eslint (@babel/eslint-parser, eslint-plugin-react)
  • fix(deps): update apollo graphql packages (@apollo/client, @apollo/server)
  • fix(deps): update dependency aws-sdk to v2.1687.0
  • fix(deps): update dependency react-hook-form to v7.53.0
  • fix(deps): update dependency typegraphql-prisma to v0.28.0
  • fix(deps): update emotion monorepo (@emotion/react, @emotion/styled)
  • fix(deps): update sentry-javascript monorepo to v7.119.0 (@sentry/nextjs, @sentry/node)
  • chore(deps): update dependency lint-staged to v15
  • chore(deps): update dependency prettier to v3
  • chore(deps): update dependency turbo to v2
  • chore(deps): update dependency typescript to v5
  • chore(deps): update graphqlcodegenerator monorepo (major) (@graphql-codegen/add, @graphql-codegen/cli, @graphql-codegen/typescript, @graphql-codegen/typescript-operations, @graphql-codegen/typescript-react-apollo)
  • fix(deps): update dependency @hookform/resolvers to v3
  • fix(deps): update dependency framer-motion to v11
  • fix(deps): update dependency glob to v11
  • fix(deps): update dependency jsonwebtoken to v9
  • fix(deps): update dependency react-icons to v5
  • fix(deps): update dependency react-native-svg to v15
  • fix(deps): update dependency styled-components to v6
  • fix(deps): update dependency yup to v1
  • fix(deps): update sendgrid-nodejs monorepo to v8 (major) (@sendgrid/client, @sendgrid/mail)
  • fix(deps): update sentry-javascript monorepo to v8 (major) (@sentry/nextjs, @sentry/node)
  • 🔐 Create all rate-limited PRs at once 🔐

Open

These updates have all been created already. Click a checkbox below to force a retry/rebase of any.

Detected dependencies

npm
package.json
  • @commitlint/cli 17.8.1
  • @commitlint/config-conventional 17.8.1
  • @typescript-eslint/eslint-plugin 5.62.0
  • @typescript-eslint/parser 5.62.0
  • @babel/eslint-parser 7.24.7
  • eslint 8.57.0
  • eslint-config-prettier 8.10.0
  • eslint-plugin-flowtype 8.0.3
  • eslint-plugin-import 2.29.1
  • eslint-plugin-jsx-a11y 6.9.0
  • eslint-plugin-simple-import-sort 8.0.0
  • husky 8.0.3
  • lint-staged 13.3.0
  • prettier 2.8.8
  • turbo 1.13.4
  • typescript 4.9.5
  • node >=16.0.0
  • prettier 2.8.8
packages/api/package.json
  • @sendgrid/client 7.7.0
  • @sendgrid/mail 7.7.0
  • @sentry/node 7.118.0
  • @sentry/tracing 7.114.0
  • apollo-graphql 0.9.7
  • @apollo/server 4.10.4
  • aws-sdk 2.1206.0
  • bcryptjs 2.4.3
  • chalk 4.1.2
  • class-transformer 0.5.1
  • class-validator 0.14.1
  • dayjs 1.11.11
  • dotenv 16.4.5
  • express 4.19.2
  • express-jwt 6.1.2
  • glob 8.1.0
  • graphql 15.9.0
  • graphql-fields 2.0.3
  • graphql-scalars 1.23.0
  • handlebars 4.7.8
  • ioredis 5.4.1
  • jsonwebtoken 8.5.1
  • morgan 1.10.0
  • nodemailer 6.9.14
  • pg 8.12.0
  • reflect-metadata 0.2.2
  • type-graphql 1.1.1
  • typedi 0.10.0
  • typegraphql-prisma 0.27.2
  • @types/bcryptjs 2.4.6
  • @types/express 4.17.21
  • @types/express-jwt 6.0.4
  • @types/graphql-fields 1.3.9
  • @types/ioredis 4.28.10
  • @types/jsonwebtoken 8.5.9
  • @types/morgan 1.9.9
  • @types/node 16.18.101
  • @types/nodemailer 6.4.15
  • ts-node 10.9.2
  • ts-node-dev 2.0.0
packages/app/package.json
  • @apollo/client 3.10.6
  • @react-navigation/core 6.4.16
  • @react-navigation/native 6.1.17
  • @react-navigation/native-stack 6.9.26
  • @react-navigation/stack 6.3.29
  • expo 45.0.8
  • expo-status-bar 1.12.1
  • graphql 15.9.0
  • graphql-tag 2.12.6
  • native-base 3.4.28
  • polished 4.3.1
  • react 17.0.2
  • react-dom 17.0.2
  • react-native-svg 12.5.1
  • react-native-web 0.19.12
  • styled-components 5.3.11
  • styled-system 5.1.5
  • @babel/core 7.24.7
  • @graphql-codegen/add 3.2.3
  • @graphql-codegen/cli 2.16.5
  • @graphql-codegen/typescript 2.8.8
  • @graphql-codegen/typescript-operations 2.5.13
  • @graphql-codegen/typescript-react-apollo 3.3.7
  • @types/react 17.0.80
  • @types/react-dom 17.0.25
  • @types/react-native 0.73.0
  • eslint-plugin-react 7.34.3
  • eslint-plugin-react-hooks 4.6.2
packages/web/package.json
  • @apollo/client 3.10.6
  • @chakra-ui/react 1.8.9
  • @emotion/react 11.11.4
  • @emotion/styled 11.11.5
  • @hookform/resolvers 2.9.11
  • @sentry/nextjs 7.118.0
  • dayjs 1.11.11
  • framer-motion 6.5.1
  • graphql 15.9.0
  • next 12.3.4
  • react 17.0.2
  • react-dom 17.0.2
  • react-dropzone 14.2.3
  • react-hook-form 7.52.0
  • react-icons 4.12.0
  • vercel-is-pull-request 0.0.8
  • yup 0.32.11
  • @graphql-codegen/add 3.2.3
  • @graphql-codegen/cli 2.16.5
  • @graphql-codegen/typescript 2.8.8
  • @graphql-codegen/typescript-operations 2.5.13
  • @graphql-codegen/typescript-react-apollo 3.3.7
  • @types/cookie 0.6.0
  • @types/react 17.0.80
  • @types/react-dom 17.0.25
  • eslint-config-next 12.3.4

  • Check this box to trigger a request for Renovate to run again on this repository

Can not upload profile picture.

Hi Jack,

Thanks you for sharing this repo, it help me a lot.

I have a problem with upload file to s3. Could you show me how to config that?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.