<commit_before>[![Commitizen friendly](https://img.shields.io/badge/commitizen-friendly-brightgreen.svg)](http://commitizen.github.io/cz-cli/)

# nap
[WIP] NextJS/ApolloJS/PassportJS
Build in Next JS for SSR, Apollo Client for GraphQL, Passport JS for authentication, Docker for development and production.

![](https://raw.githubusercontent.com/rabbotio/nap/master/art/nap-logo.png)

## Overview
```
○ Docker
├─ ○ Docker Compose 3.1
│  ├─ Docker Swarm Stack
│  └─ Docker Flow Proxy
│
├─ ○ Nginx
│  ├─ ./nginx/certs   : /etc/nginx/certs
│  ├─ ./nginx/conf.d  : /etc/nginx/conf.d
│  ├─ ./nginx/log     : /var/log/nginx
│  └─ ./nginx/www     : /var/www
│
├─ ○ NodeJS 7.6, nodemon
│  ├─ ○ NextJS 2
│  │  ├─ ./pages      : /usr/app/pages
│  │  ├─ ./components : /usr/app/components
│  │  ├─ ./lib        : /usr/app/lib
│  │  ├─ ./routes     : /usr/app/routes
│  │  └─ ./server     : /usr/app/server
│  │
│  ├─ ○ Apollo GraphQL
│  │  └─ ./graphql    : /usr/app/graphql
│  │
│  └─ ○ PassportJS, Redis
│     └─ ./providers  : /usr/app/providers
│
├─ ○ Redis : redis://redis
│  └─ data            : /data
│
└─ ○ MongoDB : mongodb://mongo/graphql
   └─ data            : /data/db
```

## Stacks
- [x] [next](https://github.com/zeit/next.js/) for SSR `React`.
- [x] [apollo](https://github.com/apollographql) for `GraphQL` client.
- [x] [passport](https://github.com/jaredhanson/passport) for `Express` authentication.

## Extras
- [x] [express](https://github.com/expressjs/express) for web framework.
- [x] [express-session](https://github.com/expressjs/session) for persist session via `Redis`.
- [x] [graphql-compose](https://github.com/nodkz/graphql-compose) for build `GraphQL` types from `Mongoose` with resolvers.
- [x] [mongoose-role](https://github.com/ksmithut/mongoose-role) for manage user roles and user access levels
- [x] [nextjs-starter](https://github.com/iaincollins/nextjs-starter) for basic authentication.
- [x] [modclean](https://www.npmjs.com/package/modclean) for smaller `node_modules`.
- [x] [mailgun](http://www.mailgun.com/) for send email.
- [x] [passport-facebook-token](https://github.com/drudge/passport-facebook-token) for authenticating with Facebook access tokens.
- [x] [lusca](https://github.com/krakenjs/lusca) for web application security middleware.
- [x] [platform](https://github.com/bestiejs/platform.js) for detect client platform.
- [x] [commitizen](https://github.com/commitizen/cz-cli) for commit formatting
- [ ] [nginx](https://github.com/nginxinc) for proxy.
- [ ] [certbot](https://github.com/rabbotio/nginx-certbot) for `TLS`.

- - -

## Configurations
> Copy from `.env.example` template and `.env` as you wish
```shell
cp .env.example .env
```

## Develop
```shell
# To build and run docker compose (it take sometime for first build)
npm run up

# Try modify files and see the HMR result
open http://localhost:3000

# Try modify file in ./graphql and see the result via GraphiQL
open http://localhost:3000/graphql
```

## Debug
- Server side : Use `VSCode` and press F5 to `attach` with nodejs
- Client side : Use `Chrome Dev Tool`

## Addition
```shell
# To kill all and tear down
npm run down

# To dive in container
npm run in
```

## Test
```
# Will need to run server for integration test (WIP)
npm run up

# To test all with Jest
npm run test

# To see coverage
npm run cover
```

- - -

## GraphQL extend default fields
```js
// Just modify ./graphql/custom.js
// To add `score` field as `Number` to `User` collection
exports.extraUserSchema = {
  score: Number
}

// To add `badge` field as `String` to `Installation` collection
exports.extraInstallationSchema = {
  badge: String
}

// To add `isVerified` field as `Boolean` to `Installation` collection
exports.extraInstallationSchema = {
  isVerified: Boolean
}
```

## GraphQL examples
```shell
# For original graphql-compose examples
cp -r ./examples/schema-graphql-compose/ ./graphql/
open http://localhost:3000/graphql/user

# For Apollo style with graphql-tools
cp -r ./examples/schema-graphql-tools/ ./graphql/
open http://localhost:3000/graphql/apollo

# For original style
cp -r ./examples/schema-original/ ./graphql/
open http://localhost:3000/graphql/original
```
- - -

## Passport (cookie)
> Will need test after refactoring

- [x] Facebook : http://localhost:3000/auth/facebook/
- [x] Github : http://localhost:3000/auth/github/
- [x] Twitter : http://localhost:3000/auth/twitter/
- [x] Google : http://localhost:3000/auth/google/
- [x] Email : http://localhost:3000/auth/signin/
- [x] Sign Out : http://localhost:3000/auth/signout/

## Passport (token via GraphQL)
- [x] Facebook
  > Use with `Ract Native` after get `access_token` form `Facebook`, See [nap-react-native](https://github.com/rabbotio/nap-react-native)
  ```shell
  # Login with Facebook access_token and device's info
  mutation loginWithFacebook($deviceInfo: String!, $accessToken: String!) {
    loginWithFacebook(deviceInfo: $deviceInfo, accessToken: $accessToken) {
      sessionToken
      user {
        _id
        name
      }
    }
    errors {
      code
      message
    }
  }

  # To get user profile
  {
    user {
      name
    }
    errors {
      code
      message
    }
  }

  # Logout with current bearer session token
  mutation {
    logout {
      isLoggedIn
    }
  }
  ```
- [ ] Log in with email
  > Will to setup `MailGun` bofore use.
  ```shell
  MAILGUN_API_KEY=key-SOME_RANDOM_NUMBER_HERE
  MAILGUN_DOMAIN=foo.bar
  ```
  > Then log in with `GraphQL`  
  > Status should return as `WAIT_FOR_EMAIL_VERIFICATION` and `VERIFIED_BY_EMAIL` after visit verified link.
  ```
  mutation loginWithEmail($deviceInfo: String!, $email: String!) {
    loginWithEmail(deviceInfo: $deviceInfo, email: $email) {
      sessionToken
      user {
        _id
        status
      }
    }
    errors {
      code
      message<commit_msg>docs(Authen): Mark as done<commit_after>[![Commitizen friendly](https://img.shields.io/badge/commitizen-friendly-brightgreen.svg)](http://commitizen.github.io/cz-cli/)

# nap
[WIP] NextJS/ApolloJS/PassportJS
Build in Next JS for SSR, Apollo Client for GraphQL, Passport JS for authentication, Docker for development and production.

![](https://raw.githubusercontent.com/rabbotio/nap/master/art/nap-logo.png)

## Overview
```
○ Docker
├─ ○ Docker Compose 3.1
│  ├─ Docker Swarm Stack
│  └─ Docker Flow Proxy
│
├─ ○ Nginx
│  ├─ ./nginx/certs   : /etc/nginx/certs
│  ├─ ./nginx/conf.d  : /etc/nginx/conf.d
│  ├─ ./nginx/log     : /var/log/nginx
│  └─ ./nginx/www     : /var/www
│
├─ ○ NodeJS 7.6, nodemon
│  ├─ ○ NextJS 2
│  │  ├─ ./pages      : /usr/app/pages
│  │  ├─ ./components : /usr/app/components
│  │  ├─ ./lib        : /usr/app/lib
│  │  ├─ ./routes     : /usr/app/routes
│  │  └─ ./server     : /usr/app/server
│  │
│  ├─ ○ Apollo GraphQL
│  │  └─ ./graphql    : /usr/app/graphql
│  │
│  └─ ○ PassportJS, Redis
│     └─ ./providers  : /usr/app/providers
│
├─ ○ Redis : redis://redis
│  └─ data            : /data
│
└─ ○ MongoDB : mongodb://mongo/graphql
   └─ data            : /data/db
```

## Stacks
- [x] [next](https://github.com/zeit/next.js/) for SSR `React`.
- [x] [apollo](https://github.com/apollographql) for `GraphQL` client.
- [x] [passport](https://github.com/jaredhanson/passport) for `Express` authentication.

## Extras
- [x] [express](https://github.com/expressjs/express) for web framework.
- [x] [express-session](https://github.com/expressjs/session) for persist session via `Redis`.
- [x] [graphql-compose](https://github.com/nodkz/graphql-compose) for build `GraphQL` types from `Mongoose` with resolvers.
- [x] [mongoose-role](https://github.com/ksmithut/mongoose-role) for manage user roles and user access levels
- [x] [nextjs-starter](https://github.com/iaincollins/nextjs-starter) for basic authentication.
- [x] [modclean](https://www.npmjs.com/package/modclean) for smaller `node_modules`.
- [x] [mailgun](http://www.mailgun.com/) for send email.
- [x] [passport-facebook-token](https://github.com/drudge/passport-facebook-token) for authenticating with Facebook access tokens.
- [x] [lusca](https://github.com/krakenjs/lusca) for web application security middleware.
- [x] [platform](https://github.com/bestiejs/platform.js) for detect client platform.
- [x] [commitizen](https://github.com/commitizen/cz-cli) for commit formatting
- [ ] [nginx](https://github.com/nginxinc) for proxy.
- [ ] [certbot](https://github.com/rabbotio/nginx-certbot) for `TLS`.

- - -

## Configurations
> Copy from `.env.example` template and `.env` as you wish
```shell
cp .env.example .env
```

## Develop
```shell
# To build and run docker compose (it take sometime for first build)
npm run up

# Try modify files and see the HMR result
open http://localhost:3000

# Try modify file in ./graphql and see the result via GraphiQL
open http://localhost:3000/graphql
```

## Debug
- Server side : Use `VSCode` and press F5 to `attach` with nodejs
- Client side : Use `Chrome Dev Tool`

## Addition
```shell
# To kill all and tear down
npm run down

# To dive in container
npm run in
```

## Test
```
# Will need to run server for integration test (WIP)
npm run up

# To test all with Jest
npm run test

# To see coverage
npm run cover
```

- - -

## GraphQL extend default fields
```js
// Just modify ./graphql/custom.js
// To add `score` field as `Number` to `User` collection
exports.extraUserSchema = {
  score: Number
}

// To add `badge` field as `String` to `Installation` collection
exports.extraInstallationSchema = {
  badge: String
}

// To add `isVerified` field as `Boolean` to `Installation` collection
exports.extraInstallationSchema = {
  isVerified: Boolean
}
```

## GraphQL examples
```shell
# For original graphql-compose examples
cp -r ./examples/schema-graphql-compose/ ./graphql/
open http://localhost:3000/graphql/user

# For Apollo style with graphql-tools
cp -r ./examples/schema-graphql-tools/ ./graphql/
open http://localhost:3000/graphql/apollo

# For original style
cp -r ./examples/schema-original/ ./graphql/
open http://localhost:3000/graphql/original
```
- - -

## Passport (cookie)
> Will need test after refactoring

- [x] Facebook : http://localhost:3000/auth/facebook/
- [x] Github : http://localhost:3000/auth/github/
- [x] Twitter : http://localhost:3000/auth/twitter/
- [x] Google : http://localhost:3000/auth/google/
- [x] Email : http://localhost:3000/auth/signin/
- [x] Sign Out : http://localhost:3000/auth/signout/

## Passport (token via GraphQL)
- [x] Facebook
  > Use with `Ract Native` after get `access_token` form `Facebook`, See [nap-react-native](https://github.com/rabbotio/nap-react-native)
  ```shell
  # Login with Facebook access_token and device's info
  mutation loginWithFacebook($deviceInfo: String!, $accessToken: String!) {
    loginWithFacebook(deviceInfo: $deviceInfo, accessToken: $accessToken) {
      sessionToken
      user {
        _id
        name
      }
    }
    errors {
      code
      message
    }
  }

  # To get user profile
  {
    user {
      name
    }
    errors {
      code
      message
    }
  }

  # Logout with current bearer session token
  mutation {
    logout {
      isLoggedIn
    }
  }
  ```
- [x] Log in with email
  > Will to setup `MailGun` bofore use.
  ```shell
  MAILGUN_API_KEY=key-SOME_RANDOM_NUMBER_HERE
  MAILGUN_DOMAIN=foo.bar
  ```
  > Then log in with `GraphQL`  
  > Status should return as `WAIT_FOR_EMAIL_VERIFICATION` and `VERIFIED_BY_EMAIL` after visit verified link.
  ```
  mutation loginWithEmail($deviceInfo: String!, $email: String!) {
    loginWithEmail(deviceInfo: $deviceInfo, email: $email) {
      sessionToken
      user {
        _id
        status
      }
    }
    errors {
      code
      message
{'fraction_non_alphanumeric': 0.15278609946075494, 'fraction_numerical': 0.008559445347941454, 'mean_word_length': 3.1803220035778175, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 15, 'https://': 36, 'lorem ipsum': 0, 'www.': 6, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 16, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6753413', 'n_tokens_mistral': 4211, 'n_tokens_neox': 4146, 'n_words': 1121}