Skip to content

Commit

Permalink
fix(readme): add quickstart info (#262)
Browse files Browse the repository at this point in the history
  • Loading branch information
goldcaddy77 committed Nov 25, 2019
1 parent 8f3adb1 commit 81e2acc
Show file tree
Hide file tree
Showing 3 changed files with 119 additions and 145 deletions.
2 changes: 1 addition & 1 deletion .markdownlint.json
Expand Up @@ -4,7 +4,7 @@
},
"line-length": false,
"no-inline-html": {
"allowed_elements": ["a", "img", "p"]
"allowed_elements": ["a", "img", "p", "details", "summary"]
},
"no-trailing-punctuation": {
"punctuation": ".,;:"
Expand Down
256 changes: 113 additions & 143 deletions README.md
Expand Up @@ -40,203 +40,173 @@ Further, it covers the following concerns by hooking into best-in-class open sou

## Prerequisites

You must have Postgresql installed to use Warthog. If you already have it installed, you can skip this step, otherwise there are 3 options:
Warthog 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)

### Docker
<details>
<summary>Expand for Postgres installation options</summary>
<p>

See the [warthog-starter](https://github.com/goldcaddy77/warthog-starter/pull/6/files) project for how to use Docker to run Postgres.
### Homebrew (OSX)

### Homebrew
If you're on OSX and have [homebrew](http://brew.sh/) and [homebrew-cask](https://github.com/caskroom/homebrew-cask) installed, you can simply run:

If you're on OSX and have [Homebrew](https://brew.sh/) installed, you can simply run:
```bash
brew cask install postgres
```

Or you can install Homebrew's official version:

```bash
brew install postgresql
`brew --prefix`/opt/postgres/bin/createuser -s postgres
```

### Postgres.app
### Postgres.app (OSX)

Otherwise, you can install [Postgres.app](https://postgresapp.com/) or use the Google machine to figure out how to install on your OS.
Otherwise, you can install [Postgres.app](https://postgresapp.com/) manually.

## Usage
### Docker

The easiest way to start using Warthog for a fresh project is to clone the [warthog-starter](https://github.com/goldcaddy77/warthog-starter) repo. This has a simple example in place to get you started. There are also a bunch of examples in the [examples](./examples/README.md) folder for more advanced use cases.
See the [warthog-starter](https://github.com/goldcaddy77/warthog-starter/pull/6/files) project for how to use Docker to run Postgres.

Note 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).
</p>
</details>

### Installing in Existing Project
## Usage

### Cloning the starter project

The easiest way to start using Warthog for a fresh project is to clone the [warthog-starter](https://github.com/goldcaddy77/warthog-starter) repo. To get the starter project up and running, do the following:

```bash
yarn add warthog
git clone git@github.com:goldcaddy77/warthog-starter.git
cd warthog-starter
yarn bootstrap
WARTHOG_AUTO_OPEN_PLAYGROUND=true yarn start:dev
```

### 1. Create a Model
### Installing in Existing Project

The model will auto-generate your database table and graphql types. Warthog will find all models that match the following glob - `'/**/*.model.ts'`. So for this file, you would name it `user.model.ts`
To 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:

```typescript
import { BaseModel, Model, StringField } from "warthog";
- Generate a new resource
- Create a database
- Create a DB migration and run it
- Run the server

@Model()
export class User extends BaseModel {
@StringField()
name?: string;
}
```
The following code will get you bootstrapped. You should read through this before running:

### 2. Create a Resolver
```bash
# Install Warthog
yarn add warthog

The resolver auto-generates queries and mutations in your GraphQL schema. Warthog will find all resolvers that match the following glob - `'/**/*.resolver.ts'`. So for this file, you would name it `user.resolver.ts`
# Pull down several nessesary files from the warthog-starter example
declare -a arr=(".env" "warthog.config.js" "tsconfig.json" "src/config.ts" "src/index.ts" "src/logger.ts" "src/server.ts")
for i in "${arr[@]}"
do
if [ ! -f ./$i ]; then
curl https://raw.githubusercontent.com/goldcaddy77/warthog-starter/master/$i -o $i
fi
done

# Create a .env file with your app and DB settings (modify these as needed)
printf "DEBUG=*
NODE_ENV=development
WARTHOG_AUTO_OPEN_PLAYGROUND=true
WARTHOG_APP_HOST=localhost
WARTHOG_APP_PORT=4100
WARTHOG_DB_DATABASE=warthog-starter
WARTHOG_DB_HOST=localhost
WARTHOG_DB_PASSWORD=
WARTHOG_DB_PORT=5432
WARTHOG_DB_SYNCHRONIZE=true
WARTHOG_DB_USERNAME=postgres" > .env

```typescript
import { User } from "./user.model";
import { UserService } from "./user.service";
# Create your first model (See https://github.com/goldcaddy77/warthog#generate-command-in-depth for more info)
yarn warthog generate user name! nickname age:int! verified:bool!

@Resolver(User)
export class UserResolver {
constructor(@Inject("UserService") readonly service: UserService) {}
# Generate typescript classes and GraphQL schema
yarn warthog codegen

@Query(() => [User])
async users(
@Args() { where, orderBy, limit, offset }: UserWhereArgs
): Promise<User[]> {
return this.service.find<UserWhereInput>(where, orderBy, limit, offset);
}
# Create your DB
yarn warthog db:create

@Mutation(() => User)
async createUser(
@Arg("data") data: UserCreateInput,
@Ctx() ctx: BaseContext
): Promise<User> {
return this.service.create(data, ctx.user.id);
}
}
# Generate the DB migration for your newly generated model
yarn warthog db:migrate:generate --name=create-user-table

# Run the DB migration
yarn warthog db:migrate

# Start the server
yarn ts-node --type-check src/index.ts
```

### 3. Create a Service
This will open up GraphQL Playground, where you can execute queries and mutations against your API.

```typescript
import { User } from "./user.model";
First, add a user by entering the following in the window:

@Service("UserService")
export class UserService extends BaseService<User> {
constructor(
@InjectRepository(User) protected readonly repository: Repository<User>
) {
super(User, repository);
```graphql
mutation {
createUser(data: { name: "Test User", age: 25, verified: false }) {
id
name
createdAt
}
}
```

### 4. Add config to .env file
Then, query for this user:

```env
WARTHOG_APP_HOST=localhost
WARTHOG_APP_PORT=4100
WARTHOG_DB_DATABASE=warthog
WARTHOG_DB_USERNAME=postgres
WARTHOG_DB_PASSWORD=
```graphql
query {
users {
id
name
createdAt
}
}
```

### 5. Run your server
See [introducing-graphql-playground](https://www.prisma.io/blog/introducing-graphql-playground-f1e0a018f05d) for more info about GraphQL Playground.

```typescript
import "reflect-metadata";
import { Server } from "warthog";
### Running the examples in the Warthog repo

async function bootstrap() {
const server = new Server();
return server.start();
}
You can also clone the Warthog repo and run the examples in the [examples](./examples/README.md) folder.

bootstrap();
```bash
git clone git@github.com:goldcaddy77/warthog.git
cd warthog/examples/01-simple-model
yarn bootstrap
yarn db:seed:dev
yarn start
```

When you start your server, there will be a new `generated` folder that has your GraphQL schema in `schema.graphql`. This contains:
This 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.

```graphql
type User implements BaseGraphQLObject {
id: String!
createdAt: DateTime!
createdById: String!
updatedAt: DateTime
updatedById: String
deletedAt: DateTime
deletedById: String
version: Int!
name: String!
}
Note 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).

type Mutation {
createUser(data: UserCreateInput!): User!
}
### Warthog Constructs Explained

type Query {
users(
offset: Int
limit: Int = 50
where: UserWhereInput
orderBy: UserOrderByInput
): [User!]!
}
#### Models

input UserCreateInput {
name: String!
}
A 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`

enum UserOrderByInput {
createdAt_ASC
createdAt_DESC
updatedAt_ASC
updatedAt_DESC
deletedAt_ASC
deletedAt_DESC
name_ASC
name_DESC
}
#### Resolvers

input UserUpdateInput {
name: String
}
A 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`

input UserWhereInput {
id_eq: String
id_in: [String!]
createdAt_eq: String
createdAt_lt: String
createdAt_lte: String
createdAt_gt: String
createdAt_gte: String
createdById_eq: String
updatedAt_eq: String
updatedAt_lt: String
updatedAt_lte: String
updatedAt_gt: String
updatedAt_gte: String
updatedById_eq: String
deletedAt_all: Boolean
deletedAt_eq: String
deletedAt_lt: String
deletedAt_lte: String
deletedAt_gt: String
deletedAt_gte: String
deletedById_eq: String
name_eq: String
name_contains: String
name_startsWith: String
name_endsWith: String
name_in: [String!]
}
#### Services

input UserWhereUniqueInput {
id: String!
}
Services 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`

# ...
```
#### Generated Folder

When you start your server, there will be a new `generated` folder that Warthog creates automatically. The folder contains:

Notice how we've only added a single field on the model and you get pagination, filtering and tracking of who created, updated and deleted records automatically.
- 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.
- 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.
- ormconfig.ts: a TypeORM [ormconfig](https://github.com/typeorm/typeorm/blob/master/docs/using-ormconfig.md) file.
- 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)

## Server API (appOptions)

Expand Down
6 changes: 5 additions & 1 deletion src/schema/SchemaGenerator.ts
Expand Up @@ -29,12 +29,16 @@ export class SchemaGenerator {
// This file has been auto-generated by Warthog. Do not update directly as it
// will be re-written. If you need to change this file, update models or add
// new TypeGraphQL objects
// @ts-ignore
import { GraphQLDateTime as DateTime } from 'graphql-iso-date';
import { GraphQLID as ID } from 'graphql';
// @ts-ignore
import { ArgsType, Field as TypeGraphQLField, Float, InputType as TypeGraphQLInputType, Int } from 'type-graphql';
// @ts-ignore
import { registerEnumType } from 'type-graphql';
// eslint-disable-next-line @typescript-eslint/no-var-requires
// @ts-ignore eslint-disable-next-line @typescript-eslint/no-var-requires
const { GraphQLJSONObject } = require('graphql-type-json');
// @ts-ignore
Expand Down

0 comments on commit 81e2acc

Please sign in to comment.