.github/CONTRIBUTING.md
# Contributing
Guide for contributors
### Setup
You will need [npm](https://github.com/npm/cli) as a package manager and build runner. You should install it and `node` via [nvm](https://github.com/nvm-sh/nvm).
If you choose not to use `nvm`, you'll have to manually make sure that your `node` version matches what's in `.nvmrc`.
If you choose to use `nvm`, you can just run `nvm use`.
Run `./scripts/devEnv.sh` from the top level of the Vaken repository. Note that the variables in
the new `.env` file will need to be changed to valid values.
**Installing MongoDB:**
You will need a MongoDB instance running in order for the application to work correctly. We recommend using [MongoDB Atlas](https://www.mongodb.com/cloud/atlas) to set up a cluster. Another option is to [install MongoDB locally](https://www.mongodb.com/download-center/community) and run it.
In addition, we recommend getting [MongoDB Compass](https://www.mongodb.com/download-center/compass) to view and edit data easily.
### Running the app:
```bash
npm run dev # runs backend + frontend, both reloading on changes
```
Now to go `localhost:8081` to see the page.
NOTE: you can also go to `localhost:8080/graphql` to see an interactive GraphQL IDE to try out queries and mutations (disabled in production env by default).
To create a production build, run `npm build`.
### Testing
We use Jest for testing. Happo screenshot testing is mostly for frontend, while mocking is preferable for backend.
Our local jest tests use the `--only-changed` option, which runs tests only for files that are actually changed, to speed up testing. NOTE: the CI will run all the tests regardless.
Jest configs are split using projects into specific backend and frontend configurations (see [./jest.config.js](./jest.config.js))
Running tests
```bash
npm run check:test # runs only changed tests
npm run check:test:ci # runs all tests
```
### Linting
We use Eslint for linting. The linting tests are cached with the `--cache` option.
NOTE: there are multiple eslint files. The rules are cascaded with the rule in the more specific directory taking priority (see [Eslint cascading hierarchy](https://eslint.org/docs/user-guide/configuring#configuration-cascading-and-hierarchy))
- client-specific config: [./src/client/.eslintrc.js](./src/client/.eslintrc.js)
- common (shared between server+client) config: [./.eslintrc.js](./.eslintrc.js)
```bash
npm run check:lint # runs the linter
npm run check:lint:fix # runs the linter with autofix
```
### Folder Structure
- `/__mocks__` - mocks for testing
- `/__snapshots__` - jest snapshots for frontend testing
- `/.vscode` - vscode workspace settings, recommended plugins, and launch debug config
- `/scripts` - runnable scripts to do certain tasks (install, populate DB, make an organizer, make a volunteer, etc.)
- `/src`
- `/client`
- `/assets` - static assets
- `/routes.js` - all frontend routes mapped to React components
- `/components` - all frontend components
- `/contexts`
- `/generated` - autogenerated files, don't modify
- `/routes`
- `/common`
- `/server`
- `/auth` - authentication
- `/generated` - autogenerated files, don't modify
- `index.ts` - main Express API server and Apollo Server
- `models.ts` - graphql models
- `resolvers.ts` - graphql resolvers
- `/types` - misc. type declaration files
- `// lots of config files here`
NOTE: We use [dotansimha/graphql-code-generator](https://github.com/dotansimha/graphql-code-generator) for automatic code generation. The mappings for schema models to db models are in [./codegen.json](./codegen.json).
### General Architecture
Schemas:
- [./src/common/schema.graphql.ts](./src/common/schema.graphql.ts) - main schema, shared among server and client
- [./src/client/routes/team/teams.graphql.ts](./src/client/routes/team/teams.graphql.ts) - team data
- [./src/client/routes/profile/user.graphql.ts](./src/client/routes/profile/user.graphql.ts) - for a specific user
- [./src/client/routes/manage/hackers.graphql.ts](./src/client/routes/manage/hackers.graphql.ts) - hacker table
- [./src/client/me.graphql.ts](./src/common/schema.graphql.ts) - personal logged in user
Models:
In [./src/server/models.ts](./src/server/models.ts)
Resolvers:
In [./src/server/resolvers.ts](./src/server/resolvers/index.ts)
### Tooling
We use:
- Jest for testing
- Happo for screenshot diff verification
- GitHub Actions
- Eslint (there's a different config for server and client)
- Prettier (can be used with `npm format` but we also use the eslint integration)
- [Ts-node-dev](https://github.com/whitecolor/ts-node-dev) for auto reloading server
- [dotansimha/graphql-code-generator](https://github.com/dotansimha/graphql-code-generator) for automatic code generation
- Webpack Dev Server
- [TypeDoc](https://typedoc.org/) - for documentation
### Bots
- Dependabot Preview - makes PRs for dependency upgrades (set to monthly updates, configure in [Dashboard](https://app.dependabot.com)
- Codecov - creates code coverage report for each PR, works with Circle CI
### Github Actions
In this repo, Github Actions are used for:
- delete merged PR branches
- CI
### FAQ
#### HELP! TypeScript says there's no types for the import.
Go to the terminal and, in the vaken directory, run `npm i -D @types/LIBRARY_NAME_HERE`
#### Is there a way to login with email + password?
No, this was disabled with #261.
#### Is there a way to add hackers to the DB for testing purposes?
Yes, run the scripts/populateDB.ts script.
```
ts-node -r dotenv/config ./scripts/populateDb.ts
```
#### How do I log in as an organizer?
To make yourself an organizer, first log in with the account you'd like to use, then run the following script:
```
ts-node -r dotenv/config ./scripts/makeOrganizer.ts -- YOUR_EMAIL_HERE [github] [google]
```
Where you specify either github or google if you use the same email for both accounts to only update one of them.
Then you may simply log in with the account as usual and you should be an organizer.