Skip to content

Commit

Permalink
feat: support projecting enums (#18)
Browse files Browse the repository at this point in the history
  • Loading branch information
Jason Kuhrt authored Mar 19, 2021
1 parent ae31769 commit 1c1cd13
Show file tree
Hide file tree
Showing 21 changed files with 3,298 additions and 1,838 deletions.
140 changes: 93 additions & 47 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,28 +1,47 @@
**⚠️ Currently in development - _not to be used in Production_.** Follow progress from [here](https://github.com/graphql-nexus/nexus-plugin-prisma/issues/1039).

# nexus-prisma

[![trunk](https://github.com/prisma/nexus-prisma/actions/workflows/trunk.yml/badge.svg)](https://github.com/prisma/nexus-prisma/actions/workflows/trunk.yml)

Official Prisma plugin for Nexus.
**Currently in development - not to be used in Production.** Follow the progress from [here](https://github.com/graphql-nexus/nexus-plugin-prisma/issues/1039).
Official Prisma plugin for Nexus.

## Installation
<!-- toc -->

```
npm add nexus-prisma graphql @prisma/client
npm add --dev prisma
```
- [Usage](#usage)
- [Roadmap](#roadmap)
- [Features](#features)
- [Type-safe seamless generated library code](#type-safe-seamless-generated-library-code)
- [Scalar Mapping & Custom GraphQL Scalars for Native Prisma Scalars](#scalar-mapping--custom-graphql-scalars-for-native-prisma-scalars)
- [Prisma ID field to GraphQL ID scalar type mapping](#prisma-id-field-to-graphql-id-scalar-type-mapping)
- [Prisma Schema model & field documentation re-use](#prisma-schema-model--field-documentation-re-use)
- [GraphQL documentation for your API clients](#graphql-documentation-for-your-api-clients)
- [Internal JSDoc for your team](#internal-jsdoc-for-your-team)
- [Refined DX](#refined-dx)
- [Notes](#notes)

> `graphql` and `@prisma/client` are peer dependencies. `prisma` is for the Prisma CLI which you'll probably want during development.
<!-- tocstop -->

## Usage

1. Install dependencies

```
npm add nexus-prisma graphql @prisma/client
npm add --dev prisma
```

> `graphql` and `@prisma/client` are peer dependencies. `prisma` is for the Prisma CLI which you'll probably want during development.
1. Add a `nexus-prisma` generator block to your Prisma Schema.

> If you are using `prisma@=<2.17.x` then you must use the Nexus Prisma Prisma generator name of `nexus_prisma` instead of `nexus-prisma`. See [notes](#notes) for more detail.
1. Run `prisma generate` in your terminal.
1. Import models from `nexus-prisma` and then pass them to your Nexus type definition and field definition configurations. In this way you will be effectively projecting models from your data layer into GraphQL types in your API layer.

### Example
1. Import models from `nexus-prisma` and then pass them to your Nexus type definition and field definition configurations. In this way you will be effectively projecting models from your data layer into GraphQL types in your API layer.

> **Note:** If you are using Prisma@=<2.17.x then you _must_ use the Nexus Prisma Prisma generator name of `nexus_prisma` instead of `nexus-prisma`. This is because prior to prisma@2.18.x there was a hardcode check for `nexus-prisma` generator name wherein it would give feedback about it no longer being a generator.
##### Example

```prisma
Expand All @@ -43,7 +62,7 @@ model User {
```

```
$ prisma generate
prisma generate
```

```ts
Expand All @@ -65,32 +84,32 @@ export const schema = makeSchema({

## Roadmap

#### Done
##### Done

- [x] ([#4](https://github.com/prisma/nexus-prisma/issues/4)) Support for Prisma Model field types that map to standard GraphQL scalars
- [x] ([#8](https://github.com/prisma/nexus-prisma/issues/8)) Support for Prisma Model field types of `DateTime` & `Json`
- [x] ([#16](https://github.com/prisma/nexus-prisma/issues/16)) Support for Prisma enums

#### Shortterm
##### Shortterm

- [ ] ([#16](https://github.com/prisma/nexus-prisma/issues/16)) Support for Prisma enums
- [ ] Support for Prisma Model field types of remaiming scalars (`Byes`, etc.)

#### Midterm
##### Midterm

- [ ] Support for Prisma Model field types relating to other Models 1:1
- [ ] Support for Prisma Model field types relating to other Models 1:n
- [ ] Support for Prisma Model field types relating to other Models n:n

#### Longterm
##### Longterm

- [ ] Nexus Plugin? `t.model`? `t.crud`?
- [ ] ...

## Features

> **Note**: ⛑ The following use abbreviated examples that skip a complete setup of passing Nexus type definition to Nexus `makeSchema`. If you are new to Nexus, Consider reading the [official Nexus tutorial](https://nxs.li/tutorial) before jumping into Nexus Prisma.
> **Note**: ⛑ The following use abbreviated examples that skip a complete setup of passing Nexus type definition to Nexus' `makeSchema`. If you are new to Nexus, Consider reading the [official Nexus tutorial](https://nxs.li/tutorial) before jumping into Nexus Prisma.
### Type-safe seamless generated library code
### Type-safe Generated Library Code

Following the same philosophy as Prisma Client, Nexus Prisma uses generation to create an API that feels tailor made for your project.

Expand All @@ -116,9 +135,30 @@ objectType({
})
```

### Scalar Mapping & Custom GraphQL Scalars for Native Prisma Scalars
### Project Enums

Every enum defined in your Prisma schema becomes importable as a Nexus enum type definition configuration. This makes it trivial to project enums from your database layer into your API layer.

```prisma
enum SomeEnum {
foo
bar
}
```

Like GraphQL [Prisma has the concept of scalar types](https://www.prisma.io/docs/reference/api-reference/prisma-schema-reference/#model-field-scalar-types). Some of the Prisma scalars can be naturally mapped to standard GraphQL scalars. The mapping is as follows:
```ts
import { SomeEnum } from 'nexus-prisma'
import { enumType } from 'nexus'

SomeEnum.name // 'SomeEnum'
SomeEnum.members // ['foo', 'bar']

enumType(SomeEnum)
```

### Project Scalars

Like GraphQL, [Prisma has the concept of scalar types](https://www.prisma.io/docs/reference/api-reference/prisma-schema-reference/#model-field-scalar-types). Some of the Prisma scalars can be naturally mapped to standard GraphQL scalars. The mapping is as follows:

**Prisma Standard Scalar to GraphQL Standard Scalar Mapping**

Expand Down Expand Up @@ -154,25 +194,7 @@ makeSchema({
})
```

The following is a brief example how you could roll the implementations yourself:

```ts
import { GraphQLScalarType } from 'graphql'
import { JSONObjectResolver, DateTimeResolver } from 'graphql-scalars'
import { asNexusMethod, makeSchema } from 'nexus'

const jsonScalar = new GraphQLScalarType({
...JSONObjectResolver,
// Override the default 'JsonObject' name with one that matches what Nexus Prisma expects.
name: 'Json',
})

const dateTimeScalar = new GraphQLScalarType(DateTimeResolver)

makeSchema({
types: [asNexusMethod(jsonScalar, 'json'), asNexusMethod(dateTimeScalar, 'dateTime')],
})
```
There is a [recipe below](#Supply-custom-custom-scalars-to-your-GraphQL-schema) showing how to add your own custom scalars if you want.

### Prisma ID field to GraphQL ID scalar type mapping

Expand Down Expand Up @@ -203,9 +225,7 @@ type User {
}
```

### Prisma Schema model & field documentation re-use

#### GraphQL documentation for your API clients
### Prisma Schema docs re-used for GraphQL schema doc

```prisma
/// A user.
Expand Down Expand Up @@ -243,7 +263,7 @@ type User {
}
```

#### Internal JSDoc for your team
### Prisma Schema docs re-used for JSDoc

```prisma
/// A user.
Expand All @@ -264,15 +284,15 @@ User.id // JSDoc: A stable identifier to find users by.

These are finer points that aren't perhaps worth a top-level point but none the less add up toward a thoughtful developer experience.

##### Default JSDoc Prompts
##### Default JSDoc

Fields and models that you do not document will result in a helpful default JSDoc that teaches you about this.

##### Runtime Proxy
##### Defualt Runtime

When your project is in a state where the generated Nexus Prisma part is missing (new repo clone, reinstalled deps, etc.) Nexus Prisma gives you a default runtime export named `PleaseRunPrismaGenerate` and will error with a clear message.

##### Opt-outable friendly runtime peer dependency checks
##### Peer-Dependency Validation

When `nexus-prisma` is imported it will validate that your project has peer dependencies setup correctly.

Expand All @@ -287,6 +307,32 @@ PEER_DEPENDENCY_CHECK=false|0

- `nexus-prisma/scalars` offers a default export you can easily auto-import by name: `NexusPrismaScalars`.

## Recipes

### Supply custom custom scalars to your GraphQL schema

The following is a brief example how you could add your own custom GraphQL custom scalars to satisfy Nexus Prisma. Note that most of the time using the defaults exported by `nexus-prisma/scalars` will probably be good enough for you.

```ts
import { GraphQLScalarType } from 'graphql'
import { JSONObjectResolver, DateTimeResolver } from 'graphql-scalars'
import { asNexusMethod, makeSchema } from 'nexus'

const jsonScalar = new GraphQLScalarType({
...JSONObjectResolver,
// Override the default 'JsonObject' name with one that matches what Nexus Prisma expects.
name: 'Json',
})

const dateTimeScalar = new GraphQLScalarType(DateTimeResolver)

makeSchema({
types: [asNexusMethod(jsonScalar, 'json'), asNexusMethod(dateTimeScalar, 'dateTime')],
})
```

## Notes

- Versions of `nexus-prisma` package prior to `0.20` were a completely different version of the API, and had also become deprecated at one point to migrate to `nexus-plugin-prisma` when Nexus Framework was being worked on. All of that is history.

- If you are using `prisma@=<2.17.x` then you must use the Nexus Prisma Prisma generator name of `nexus_prisma` instead of `nexus-prisma`. This is because prior to `prisma@2.18.x` there was a hardcode check for `nexus-prisma` that would fail with an error message about a now-old migration.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
"nexus_prisma": "./dist/cli/nexus-prisma.js"
},
"scripts": {
"reflect:toc": "markdown-toc README.md -i --maxdepth 4",
"format": "prettier --write .",
"format:check": "prettier --check .",
"lint": "eslint . --ext .ts,.tsx --fix",
Expand Down Expand Up @@ -56,6 +57,7 @@
"jest": "26.6.3",
"jest-watch-typeahead": "0.6.1",
"lodash": "^4.17.21",
"markdown-toc": "^1.2.0",
"nexus": "^1.0.0",
"nodemon": "^2.0.7",
"prettier": "2.2.1",
Expand Down
Loading

0 comments on commit 1c1cd13

Please sign in to comment.