UNPKG

30.1 kBMarkdownView Raw
1<p align="center">
2 <a href="http://warthog.dev/"><img src="./img/warthog-logo.png" width="400" alt="Warthog Logo"></a>
3</p>
4
5 <p align="center">
6 Node.js <a href="https://graphql.org" target="_blank">GraphQL</a> Framework for building APIs with strong conventions through auto-generated code. With Warthog, set up your data models and resolvers, and it does the rest.
7</p>
8
9<p align="center">
10 <a href="https://blacklivesmatter.com/"><img src="https://img.shields.io/badge/branch-main-fce21b?labelColor=black" alt="Black Lives Matter"/></a>
11 <a href="https://www.npmjs.org/package/warthog"><img src="https://img.shields.io/npm/v/warthog.svg" alt="npm version"></a>
12 <a href="https://circleci.com/gh/goldcaddy77/warthog/tree/main"><img src="https://circleci.com/gh/goldcaddy77/warthog/tree/main.svg?style=shield" alt="CircleCI"></a>
13 <a href="https://codecov.io/gh/goldcaddy77/warthog"><img src="https://codecov.io/gh/goldcaddy77/warthog/branch/master/graph/badge.svg" alt="styled with prettier"></a>
14 <a href="#badge"><img src="https://img.shields.io/badge/styled_with-prettier-ff69b4.svg" alt="styled with prettier"></a>
15 <a href="https://github.com/semantic-release/semantic-release"><img src="https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg" alt="semantic-release"></a>
16 <a href="https://gitter.im/warthog-graphql/community?utm_source=badge&amp;utm_medium=badge&amp;utm_campaign=pr-badge&amp;utm_content=badge"><img src="https://badges.gitter.im/warthog-graphql/community.svg" alt="Join the chat at https://gitter.im/warthog-graphql/community"></a>
17</p>
18
19## Summary
20
21Warthog is a [Node.js](http://nodejs.org) GraphQL API framework for quickly building consistent GraphQL APIs that have sorting, filtering and pagination out of the box. It is written in [TypeScript](http://www.typescriptlang.org) and makes heavy use of decorators for concise, declarative code.
22
23## Note: Upgrading from 1.0 to 2.0
24
25Warthog is now on version 2.0! There were a few breaking changes that you should consider while upgrading. Also, we tried to keep all new features development on v1, but did end up adding JSON filtering directly to 2.0 as it was much easier given some foundation refactors.
26
27<details>
28<summary>Expand for Breaking change details</summary>
29<p>
30
31### More specific scalars
32
33A few fields have been updated to use more specific GraphQL scalars:
34
35- ID fields: previously these were represented by type `String`. Dates now use type `ID`
36- Date fields: previously these were represented by type `String`. Dates now use type `DateTime`
37
38Since your GraphQL schema has changed and so have the associated TypeScript types in `classes.ts`, there might be changes in your server code and even perhaps some associated client code if you use these generated classes in your client code.
39
40### `mockDBConnection` has been removed
41
42The old codegen pipeline used TypeORM's metadata in order to generate the GraphQL schema since Warthog didn't also capture this metadata. Warthog now captures the necessary metadata, so we no longer need to lean on TypeORM and therefore we don't need the `mockDBConnection` we previously used during codegen. Searching your codebase for `mockDBConnection` and `WARTHOG_MOCK_DATABASE`/`MOCK_DATABASE` should do it. If you've been using the Warthog CLI for codegen, you shouldn't have anything to do here.
43
44### Project Dependencies Updated
45
46Staying on the latest versions of libraries is good for security, performance and new features. We've bumped to the latest stable versions of each of Warthog's dependencies. This might require some changes to your package.json.
47
48### Troubleshooting
49
50#### Cannot get connection "default" from the connection manager
51
52If you get an error like:
53
54```txt
55Cannot get connection "default" from the connection manager. Make sure you have created such connection. Also make sure you have called useContainer(Container) in your application before you established a connection and importing any entity.
56```
57
58It could be caused by 2 things:
59
60##### Remove explicit `Container` injection
61
62In V1 of Warthog, the README suggested that you should explicitly create your DI containers and pass them into your `App` instance like so:
63
64```typescript
65import { Container } from 'typedi'; // REMOVE this
66import { useContainer } from 'typeorm'; // REMOVE this
67
68import { App } from 'warthog';
69
70async function run() {
71 useContainer(Container); // REMOVE this
72
73 const app = new App({ container: Container }); // REMOVE the container option here
74 await app.start();
75}
76```
77
78In V2, it is recommended that you no longer do this unless you explicitly need access to the Container.
79
80##### Remove references to Warthog's dependencies
81
82It can sometimes cause problems to explicitly require Warthog's depdendencies (ie `type-graphql`, `typedi`, `typeorm` and `typeorm-typedi-extensions`). In future versions, remove these explicit dependencies from `package.json`:
83
84```txt
85- "type-graphql": "...",
86- "typedi": "...",
87- "typeorm": "...",
88- "typeorm-typedi-extensions": "...",
89```
90
91</p>
92</details>
93
94## Philosophy
95
96This library is intentionally opinionated and generates as much code as possible. When teams build products quickly, even if they have strong conventions and good linters, the GraphQL can quickly become inconsistent, making it difficult for clients to consume the APIs in a reusable way.
97
98To do this, Warthog automatically generates the following:
99
100- Database schema - generated by [TypeORM](https://github.com/typeorm/typeorm)
101- Your entire GraphQL Schema including:
102 - types to match your entities - generated by [TypeGraphQL](https://github.com/19majkel94/type-graphql)
103 - GraphQL inputs for consistent creates, updates, filtering, and pagination
104 inspired by [Prisma](https://github.com/prisma/prisma)'s conventions
105- A [graphql-binding](https://github.com/graphql-binding/graphql-binding) for
106 type-safe programmatic access to your APIs.
107- TypeScript classes for the generated GraphQL schema for type-safety while developing.
108
109Further, it covers the following concerns by hooking into best-in-class open source libraries:
110
111- Validation: Automatic validation before data is saved using any of the decorators available in the [class-validator](https://github.com/typestack/class-validator#validation-decorators) library.
112
113## Prerequisites
114
115Warthog currently only supports PostgreSQL as a DB engine, so you must have Postgres installed before getting Warthog set up. (Note: Postgres 12 is not currently supported)
116
117<details>
118<summary>Expand for Postgres installation options</summary>
119<p>
120
121### Homebrew (OSX)
122
123If you're on OSX and have [homebrew](http://brew.sh/) and [homebrew-cask](https://github.com/caskroom/homebrew-cask) installed, you can simply run:
124
125```bash
126brew cask install postgres
127```
128
129Or you can install Homebrew's official version:
130
131```bash
132brew install postgresql
133`brew --prefix`/opt/postgres/bin/createuser -s postgres
134```
135
136### Postgres.app (OSX)
137
138Otherwise, you can install [Postgres.app](https://postgresapp.com/) manually.
139
140### Docker
141
142See the [warthog-starter](https://github.com/goldcaddy77/warthog-starter/pull/6/files) project for how to use Docker to run Postgres.
143
144</p>
145</details>
146
147## Getting Started
148
149Warthog comes with a CLI that makes it easy to get started.
150
151### Create new project with the CLI
152
153To install in an existing project, you'll need to create several files in place and then you'll need to call a few Warthog CLI commands that:
154
155- Generate a new resource
156- Create a database
157- Create a DB migration and run it
158- Run the server
159
160The following code will get you bootstrapped. You should read through this before running:
161
162```bash
163# Add warthog so that we can use the CLI
164yarn add warthog
165
166# Bootstrap a new application using Warthog CLI
167yarn warthog new
168
169# Install dependencies from generated package.json
170yarn
171
172# Generate a resource (model, resolver and service)
173yarn warthog generate user name! nickname age:int! verified:bool!
174
175# Generate typescript classes and GraphQL schema
176yarn warthog codegen
177
178# Create your DB
179yarn warthog db:create
180
181# Generate the DB migration for your newly generated model
182yarn warthog db:migrate:generate --name=create-user-table
183
184# Run the DB migration
185yarn warthog db:migrate
186
187# Start the server
188yarn start:dev
189```
190
191Here's what this looks like in action:
192
193![warthog-quickstart](https://user-images.githubusercontent.com/573625/69854217-8967f380-1256-11ea-8492-dee07334501d.gif)
194
195This will open up GraphQL Playground, where you can execute queries and mutations against your API.
196
197First, add a user by entering the following in the window:
198
199```graphql
200mutation {
201 createUser(data: { name: "Test User", age: 25, verified: false }) {
202 id
203 name
204 createdAt
205 }
206}
207```
208
209Then, query for this user:
210
211```graphql
212query {
213 users {
214 id
215 name
216 createdAt
217 }
218}
219```
220
221See [introducing-graphql-playground](https://www.prisma.io/blog/introducing-graphql-playground-f1e0a018f05d) for more info about GraphQL Playground.
222
223<details>
224<summary>Expand for other options for how to play with Warthog</summary>
225<p>
226
227### Cloning the `warthog-starter` project
228
229Another way to start playing with Warthog is to clone the [warthog-starter](https://github.com/goldcaddy77/warthog-starter) repo. To get the starter project up and running, do the following:
230
231```bash
232git clone git@github.com:goldcaddy77/warthog-starter.git
233cd warthog-starter
234yarn bootstrap
235WARTHOG_AUTO_OPEN_PLAYGROUND=true yarn start:dev
236```
237
238### Running the examples in the Warthog repo
239
240You can also clone the Warthog repo and run the examples in the [examples](./examples/README.md) folder.
241
242```bash
243git clone git@github.com:goldcaddy77/warthog.git
244cd warthog/examples/01-simple-model
245yarn bootstrap
246yarn db:seed:dev
247yarn start
248```
249
250This has a simple example in place to get you started. There are also a bunch of examples in the folder for more advanced use cases.
251
252Note that the examples in the [examples](./examples/README.md) folder use relative import paths to call into Warthog. In your projects, you won't need to set this config value as it's only set to deal with the fact that it's using the Warthog core files without consuming the package from NPM. In your projects, you can omit this as I do in [warthog-starter](https://github.com/goldcaddy77/warthog-starter).
253
254</p>
255</details>
256
257### Warthog Constructs Explained
258
259#### Models
260
261A model represents both a GraphQL type and a DB table. Warthog exposes a [BaseModel](https://github.com/goldcaddy77/warthog/blob/master/src/core/BaseModel.ts) class that provides the following columns for free: `id`, `createdAt`, `createdById`, `updatedAt`, `updatedById`, `deletedAt`, `deletedById`, `version`. If you use BaseModel in conjunction with BaseService (see below), all of these columns will be updated as you'd expect. The Warthog server will find all models that match the following glob - `'/**/*.model.ts'`. Ex: `user.model.ts`
262
263Custom [TypeORM](https://github.com/typeorm/typeorm/blob/master/docs/decorator-reference.md#entity) and [TypeGraphQL](https://typegraphql.ml/docs/types-and-fields.html) options may be passed into the `Model` decorator using the following signature.
264
265```javascript
266@Model({ api: { description: 'Custom description' }, db: { name: 'customtablename' } })
267```
268
269#### Resolvers
270
271A Warthog resolver exposes queries (reading data) and mutations (writing data). They interact with the DB through `services` (described below) and typically make use of a bunch of auto-generated TypeScript types in the `generated` folder for things like sorting and filtering. Warthog will find all resolvers that match the following glob - `'/**/*.resolver.ts'`. Ex: `user.resolver.ts`
272
273#### Services
274
275Services are the glue between resolvers and models. Warthog exposes a class called [BaseService](https://github.com/goldcaddy77/warthog/blob/master/src/core/BaseService.ts) that exposes the following methods: `find`, `findOne`, `create`, `update`, `delete`. For the `find` operator, it also maps the auto-generated `WhereInput` attributes to the appropriate TypeORM Query Builders. Warthog's convention is to name services `<model-name>.service.ts`. Ex: `user.service.ts`
276
277#### Generated Folder
278
279When you start your server, there will be a new `generated` folder that Warthog creates automatically. The folder contains:
280
281- classes.ts: Warthog auto-generates this file from the metadata it collects (from decorators like `Model`, `Query`, `Resolver`, `StringField`, etc...). Resolvers will import items from here instead of having to manually create them.
282- schema.graphql: This is auto-generated from our resolvers, models and `classes.ts` above. Check out [this example's schema.graphql](https://github.com/goldcaddy77/warthog/blob/master/examples/01-simple-model/generated/schema.graphql) to show the additional GraphQL schema Warthog autogenerates.
283- ormconfig.ts: a TypeORM [ormconfig](https://github.com/typeorm/typeorm/blob/master/docs/using-ormconfig.md) file.
284- binding.ts - a [graphql-binding](https://www.prisma.io/docs/1.10/graphql-ecosystem/graphql-binding/graphql-binding-quaidah9ph) for type-safe programmatic access to your API (making real API calls)
285
286## Server API (appOptions)
287
288Most of the config in Warthog is done via environment variables (see `Config - Environment Variables` below). However, more complex/dynamic objects should be passed via the server config.
289
290| attribute | description | default |
291| ------------------------- | --------------------------------------------------------------------------------------------------------- | --------------------------------------------- |
292| container | TypeDI container. Warthog uses dependency injection under the hood. | empty container |
293| authChecker | An instance of an [AuthChecker](https://typegraphql.ml/docs/authorization.html) to secure your resolvers. | |
294| context | Context getter of form `(request: Request) => Promise<object>` | empty |
295| logger | Logger | [debug](https://github.com/visionmedia/debug) |
296| middlewares | [TypeGraphQL](https://typegraphql.ml/docs/middlewares.html) middlewares to add to your server | none |
297| onBeforeGraphQLMiddleware | Callback executed just before the Graphql server is started. The Express app is passed. | none |
298| onAfterGraphQLMiddleware | Callback executed just after the Graphql server is started. The Express app is passed. | none |
299
300## Config - Environment Variables
301
302Almost all config in Warthog is driven by environment variables. The following items are available:
303
304| variable | value | default |
305| ----------------------------- | -------------------------------------------------------- | ------------------------- |
306| WARTHOG_APP_HOST | App server host | _none_ |
307| WARTHOG_APP_PORT | App server port | 4000 |
308| WARTHOG_APP_PROTOCOL | App server protocol | DEV: http, PROD: https |
309| WARTHOG_AUTO_GENERATE_FILES | Auto-generate files | DEV: true, PROD: false |
310| WARTHOG_AUTO_OPEN_PLAYGROUND | Open playground on server start | DEV: true, PROD: false |
311| WARTHOG_CLI_GENERATE_PATH | Where should CLI generate files | ./src |
312| WARTHOG_DB_DATABASE | DB name | _none_ |
313| WARTHOG_DB_ENTITIES | Where should warthog look for models | src\/\*\*\/\*.model.ts |
314| WARTHOG_DB_MIGRATIONS | What DB migrations should TypeORM run | db/migrations/\*\*\/\*.ts |
315| WARTHOG_DB_MIGRATIONS_DIR | Where should generated migrations be placed | db/migrations |
316| WARTHOG_DB_PORT | DB port | 5432 |
317| WARTHOG_DB_USERNAME | DB username | _none_ |
318| WARTHOG_DB_LOGGER | TypeORM logger | advanced-console |
319| WARTHOG_DB_PASSWORD | DB password | _none_ |
320| WARTHOG_DB_SYNCHRONIZE | DB automatically migrated | false |
321| WARTHOG_FILTER_BY_DEFAULT | Should all filters and sorts be generated by default? | true |
322| WARTHOG_GENERATED_FOLDER | Where should generated code be placed | ./generated |
323| WARTHOG_HEADERS_TIMEOUT_MS | See [Node server.headersTimeout][1] | 60000 |
324| WARTHOG_INTROSPECTION | Allow server to be introspected | true |
325| WARTHOG_KEEP_ALIVE_TIMEOUT_MS | See [Node server.keepAliveTimeout][2] | 30000 |
326| WARTHOG_RESOLVERS_PATH | Where should Warthog look for resolvers | src/\*\*\/\*.resolver.ts |
327| WARTHOG_SUBSCRIPTIONS | Should we enable subscriptions and open a websocket port | false |
328| WARTHOG_VALIDATE_RESOLVERS | TypeGraphQL validation enabled? | false |
329
330## Field/Column Decorators
331
332All of the auto-generation magic comes from the decorators added to the attributes on your models. Warthog decorators are convenient wrappers around TypeORM decorators (to create DB schema) and TypeGraphQL (to create GraphQL schema). You can find a list of decorators available in the [src/decorators](./src/decorators) folder. Most of these are also used in the [examples](./examples) folder in this project.
333
334## Transactions
335
336There are a few ways to handle transactions in the framework, depending if you want to use `BaseService` or use your repositories directly.
337
338### Using BaseService
339
340To wrap BaseService operations in a transaction, you do 3 things:
341
3421. Create a function decorated with the `@Transaction` method decorator
3432. Inject `@TransactionManager` as a function parameter
3443. Pass the `@TransactionManager` into calls to `BaseService`
345
346#### @Transaction method decorator
347
348The `@Transaction` decorator opens up a new transaction that is then available via the `@TransactionManager`. It will automatically close the transaction when the function returns, so it is important to `await` your service calls and not return a promise in this function.
349
350```typescript
351 @Transaction()
352 async createTwoItems() {
353 // ...
354 }
355```
356
357#### @TransactionManager decorator
358
359The `@TransactionManager` is essentially the same as a TypeORM EntityManger, except it wraps everything inside of it's transaction.
360
361```typescript
362 @Transaction()
363 async createTwoItems(
364 @TransactionManager() manager?: EntityManager
365 ) {
366 // ...
367 }
368```
369
370#### Pass manager to BaseService
371
372You can pass the entity manager into any of the `BaseService` methods to ensure they're part of the transaction.
373
374```typescript
375 @Transaction()
376 async createTwoItems(
377 @TransactionManager() manager?: EntityManager
378 ) {
379 this.create(data, userId, { manager })
380 }
381```
382
383#### Example
384
385```typescript
386@Service('UserService')
387export class UserService extends BaseService<User> {
388 constructor(@InjectRepository(User) protected readonly repository: Repository<User>) {
389 super(User, repository);
390 }
391
392 // GOOD: successful transaction
393 @Transaction()
394 async successfulTransaction(
395 data: DeepPartial<User>,
396 userId: string,
397 @TransactionManager() manager?: EntityManager
398 ): Promise<User[]> {
399 return Promise.all([
400 this.create(data, userId, { manager }),
401 this.create(data, userId, { manager })
402 ]);
403 }
404
405 // GOOD: successful rollback when something errors
406 @Transaction()
407 async failedTransaction(
408 data: DeepPartial<User>,
409 userId: string,
410 @TransactionManager() manager?: EntityManager
411 ): Promise<User[]> {
412 const invalidUserData = {};
413
414 const users = await Promise.all([
415 this.create(data, userId, { manager }),
416 this.create(invalidUserData, userId, { manager }) // This one fails
417 ]);
418
419 return users;
420 }
421
422 // BAD: you can't return a promise here. The function will return and the first
423 // user will be saved even though the 2nd one fails
424 @Transaction()
425 async failedTransaction(
426 data: DeepPartial<User>,
427 userId: string,
428 @TransactionManager() manager?: EntityManager
429 ): Promise<User[]> {
430 return await Promise.all([
431 this.create(data, userId, { manager }),
432 this.create(invalidUserData, userId, { manager })
433 ]);
434 }
435}
436```
437
438See the [TypeORM Transaction Docs](https://github.com/typeorm/typeorm/blob/master/docs/transactions.md#transaction-decorators) for more info.
439
440## Complex use cases
441
442Warthog makes building simple CRUD endpoints incredibly easy. In addition, since it is built on top of TypeORM and TypeGraphQL it is flexible enough to handle complex use cases as well. If you need a field to be exposed to either the DB or API, but not both, do the following:
443
444### DB-only
445
446If you need to add a column to the DB that does not need to be exposed via the API, you should pass the `dbOnly` option to your decorator:
447
448```typescript
449 @StringField({ dbOnly: true })
450 dbOnlyField!: string;
451```
452
453Note that you could also just use the [TypeORM Column Decorator](https://github.com/typeorm/typeorm/blob/master/docs/decorator-reference.md) as well. However, if Warthog adds additional capabilities in this space, we would not have this column metadata, so it is recommended you use the `dbOnly` option.
454
455### API-only
456
457If you need to add a field that is exposed via the API that is not database-backed, use the `apiOnly` option:
458
459```typescript
460 @StringField({ apiOnly: true })
461 apiOnlyField!: string;
462```
463
464### Custom Query
465
466See the [feature-flag example](./examples/07-feature-flags/) for an example of where we'd want to build something beyond the standard CRUD actions. In this example we want to add a custom query that makes a complex DB call.
467
468- First add the query to the resolver - [link to code](https://github.com/goldcaddy77/warthog/blob/master/examples/07-feature-flags/src/feature-flag/feature-flag.resolver.ts#L75-L79)
469- Then add the custom query input in the resolver - [link to code](https://github.com/goldcaddy77/warthog/blob/master/examples/07-feature-flags/src/feature-flag/feature-flag.resolver.ts#L31-L41)
470- Then add the custom service method that fetches the data [link to code](https://github.com/goldcaddy77/warthog/blob/master/examples/07-feature-flags/src/feature-flag/feature-flag.service.ts#L28-L48)
471
472Warthog will generate the correct GraphQL query and InputType automatically.
473
474## CLI
475
476Warthog ships with the following commands that can be accessed by running `yarn warthog <command>`.
477
478See the [warthog-starter](https://github.com/goldcaddy77/warthog-starter/blob/master/package.json) project's package.json for example usage.
479
480| Command | Args | Description |
481| ----------------- | --------- | --------------------------------------------------------------------------------------- |
482| codegen | none | autogenerates code from decorated models and resolvers and places in `generated` folder |
483| db:create | none | creates DB based on DB specified in config file |
484| db:drop | none | drops DB based on DB specified in config file |
485| generate | See below | generates a model, service and resolver |
486| db:migrate | none | migrates DB (proxies through TypeORM CLI) |
487| db:migrate:create | none | auto-generates DB migration based on new code additions (proxies through TypeORM CLI) |
488
489### `generate` Command in depth
490
491The `generate` command will create a new resolver, service and model for a given resource. Let's start with a complex example and we'll break it down:
492
493```bash
494yarn warthog generate user name! nickname numLogins:int! verified:bool! registeredAt:date balance:float! --folder my_generated_folder
495```
496
497- `user` - this is the name of the new resource (required)
498- ...args - each of the remaining args until `--folder` is a field on the resource
499- `name!` - the name field is of type string by default since no data type is specified. The `!` states that it's required
500- `numLogins:int!` - numLogins states that it is of type int - also required
501- `registeredAt:date` - registeredAt is of type date (which correlates to an ISO8601 datetime). The absence of the `!` means it is optional.
502- ...the rest of the args are self-explanatory. Possible types are `bool`, `date`, `int`, `float` and `string`. If you need to use other types, just add them as strings and update the models manually.
503- `--folder` - this allows you to explicitly set the folder where the generated files should go. This is not recommended and instead you should use the .rc file (see below)
504
505## `warthogrc` config file
506
507Warthog uses [cosmiconfig](https://github.com/davidtheclark/cosmiconfig) for config that shouldn't change between environments (so typically file paths). This means you can put any of the following config files in your project root:
508
509- .warthogrc.json
510- .warthogrc.yaml
511- .warthogrc.js
512- warthog.config.js file (exporting a JS object)
513
514The following config options are currently available:
515
516| Config Key | Description | Equivalent Environment Variable |
517| --------------- | ---------------------------------------------------------------------------- | ------------------------------- |
518| generatedFolder | Relative location to generated folder (relative path from the config file) | WARTHOG_GENERATED_FOLDER |
519| cliGeneratePath | Where should CLI place generated files? (relative path from the config file) | WARTHOG_CLI_GENERATE_PATH |
520| resolversPath | Where should Warthog look for resolvers? (comma-delimited list of regexes) | WARTHOG_RESOLVERS_PATH |
521
522Note that for `cliGeneratePath`, you can interpolate in the following strings to generate dynamic paths:
523
524- `className` (pascal case)
525- `camelName` (camel case)
526- `kebabName` (kebab case)
527
528Example:
529
530```json
531{
532 "cliGeneratePath": "./src/${kebabName}"
533}
534```
535
536Running `yarn warthog generate featureFlag` would create 3 files in the `./src/feature-flag/` folder. See [feature-flag example](./examples/7-feature-flags/warthog.config.js) for a live example.
537
538## Usage in Production
539
540It is recommended that you not run Warthog's TypeScript files via `ts-node` in Production as we do in development as `ts-node` has been known to cause issues in some smaller AWS instances. Instead, compile down to JS and run in `node`. For a full project example (using [dotenvi](https://github.com/b3ross/dotenvi) for config management), see [warthog-starter](https://github.com/goldcaddy77/warthog-starter)
541
542## Contributing
543
544PRs accepted, fire away! Or add issues if you have use cases Warthog doesn't cover.
545
546Before contributing, make sure you have Postgres installed and running with a user named `postgres` with an empty password. If you don't have this local Postgres user, you'll need to update the `.env` files in the `examples` folders to point to a user that can run DB migrations.
547
548Once you have this user set up, you can build a specific example by navigating to that folder and running `yarn bootstrap`.
549
550If you want to build all examples, you can run `yarn bootstrap` from the Warthog root folder.
551
552It's helpful to add a new feature to the Warthog and make use of it in one of the examples folders until you've determined how it's going to work. Once you have it working, you can add tests.
553
554## Intentionally Opinionated
555
556Warthog is intentionally opinionated to accelerate development and make use of technology-specific features:
557
558- Postgres - currently the only database supported. This could be changed, but choosing Postgres allows adding a docker container and other goodies easily.
559- Jest - other harnesses will work, but if you use Jest, we will not open the GraphQL playground when the server starts, for example.
560- Soft deletes - no records are ever deleted, only "soft deleted". The base service used in resolvers filters out the deleted records by default.
561
562## Thanks
563
564Special thanks to:
565
566- [TypeORM](https://github.com/typeorm/typeorm) - DB generation
567- [TypeGraphQL](https://github.com/19majkel94/type-graphql) - GraphQL generation
568- [Prisma](https://github.com/prisma/prisma) - [OpenCrud](https://github.com/opencrud/opencrud) conventions
569- [richardbmx](https://github.com/richardbmx) - Logo design
570
571Warthog is essentially a really opinionated composition of TypeORM and TypeGraphQL that uses similar GraphQL conventions to the Prisma project.
572
573## License
574
575MIT © Dan Caddigan
576
577[1]: https://nodejs.org/api/http.html#http_server_headerstimeout
578[2]: https://nodejs.org/api/http.html#http_server_keepalivetimeout