Skip to content

Commit

Permalink
feat: gentime setting for output directory (#166)
Browse files Browse the repository at this point in the history
  • Loading branch information
jasonkuhrt authored Dec 15, 2021
1 parent 3c9991b commit 83889bf
Show file tree
Hide file tree
Showing 33 changed files with 627 additions and 358 deletions.
34 changes: 33 additions & 1 deletion docs/pages/architecture.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,43 @@
# Architecture

Understanding the following information should not be required knowledge for using Nexus Prisma. It is primarily here for internal maintenance and collaboration. But we're happy for whatever benefit you get out of it too.

## System

![nexus-prisma-architecture](https://user-images.githubusercontent.com/284476/118728589-70fce780-b802-11eb-8c8b-4328ef5d6fb5.png)

1. You or a script (CI, programmatic, etc.) run `$ prisma generate`.
2. Prisma generator system reads your Prisma schema file
3. Prisma generator system runs the Nexus Prisma generator passing it the "DMMF", a structured representation of your Prisma schema.
4. Nexus Prisma generator reads your Nexus Prisma generator configuration if present.
5. Nexus Prisma generator writes generated source code into its own package space in your node_modules.
5. Nexus Prisma generator writes generated source code. By default into a special place within the `nexus-prisma` package in your `node_modules`. However, you can configure this location.
6. Later when you run your code it imports `nexus-prisma` which hits the generated entrypoint.
7. The generated runtime is actually thin, making use of a larger static runtime.

## Package Exports

When users choose a custom Nexus Prisma output directory the generated runtime needs to import the static runtime. There are a few things that need to happen in order for this to work:

1. The output's imports needs to specify the package to import from
2. The output's imports needs to specify the subpath to import from

For (1) we import from `'nexus-prisma'`. We just rely on the assumption that the user is outputting into a directory where eventually `node_modules/nexus-prisma` will should up in the CWD path as Node module resolution algorithm executes.

For (2) we look if user is outputting ESM or CJS (gentime config) and based on that access either `/dist-cjs` or `/dist-esm`. In order to support this we need to break the encapsulation provided by package.json `exports` field. We need to configure in it:

```json
"./*": {
"default": "./*.js"
}
```

We cannot do something slightly cleaner either like this:

```json
"./_/*": {
"require": "./dist-cjs/*.js",
"import": "./dist-esm/*.js"
}
```

Because `ncc`, at least, does not support resolving `.../_/...` imports to what is specified in the package exports.
208 changes: 14 additions & 194 deletions docs/pages/features.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

> **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 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 @@ -28,7 +28,7 @@ objectType({
})
```

### Project Enums
## 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.

Expand All @@ -49,7 +49,7 @@ SomeEnum.members // ['foo', 'bar']
enumType(SomeEnum)
```

### Project Scalars
## 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:

Expand Down Expand Up @@ -95,7 +95,7 @@ makeSchema({

There is a [recipe below](#Supply-custom-custom-scalars-to-your-GraphQL-schema) showing how to add your own custom scalars if you want.

### Project Relations
## Project Relations

You can project [relations](https://www.prisma.io/docs/concepts/components/prisma-schema/relations) into your API with Nexus Prisma. Nexus Prisma even includes the resolver you'll need at runtime to fulfill the projection by automating use of your Prisma Client instance.

Expand All @@ -122,7 +122,7 @@ new ApolloServer({
})
```

### Project 1:1 Relation
## Project 1:1 Relation

You can project [1:1 relationships](https://www.prisma.io/docs/concepts/components/prisma-schema/relations#one-to-one-relations) into your API.

Expand Down Expand Up @@ -308,7 +308,7 @@ objectType({
})
```

### Project 1:n Relation
## Project 1:n Relation

You can project [1:n relationships](https://www.prisma.io/docs/concepts/components/prisma-schema/relations#one-to-many-relations) into your API.

Expand Down Expand Up @@ -431,7 +431,7 @@ query {
}
```

### Projecting Nullability
## Projecting Nullability

Currently nullability projection is not configurable. This section describes how Nexus Prisma handles it.

Expand Down Expand Up @@ -479,187 +479,7 @@ If you have a use-case for different behaviour [please open a feature request](h

- [`#98` Always set rejectOnNotFound to false](https://github.com/prisma/nexus-prisma/issues/98)

### Runtime Settings

#### Reference

##### `prismaClientContextField: string`

- **@summary** The name of the GraphQL context field to get an instance of Prisma Client from.
- **@remarks** The instance of Prisma Client found here is accessed in the default resolvers for relational fields.
- **@default** `"prisma"`
- **@example**

```ts
// src/main.ts

import { PrismaClient } from '@prisma/client'
import { ApolloServer } from 'apollo-server'
import { makeSchema } from 'nexus'
import { User, Post, $settings } from 'nexus-prisma'

new ApolloServer({
schema: makeSchema({
types: [],
}),
context() {
return {
db: new PrismaClient(), // <-- You put Prisma client on the "db" context property
}
},
})

$settings({
prismaClientContextField: 'db', // <-- Tell Nexus Prisma
})
```

##### `prismaClientImportId: string`

- **@summary** Where Nexus Prisma will try to import your generated Prisma Client from. You should not need to configure this normally because Nexus Prisma generator automatically reads the Prisma Client generator `output` setting if you have set it. The value here will be used in a dynamic import thus following Node's path resolution rules. You can pass a node_modules package like `foo` `@prisma/client`, `@my/custom/thing` etc. or you can pass an absolute module/file path `/my/custom/thing` / `/my/custom/thing/index.js` or finally a relative path to be resolved relative to the location of Nexus Prisma source files (you probably don't want this).

- **@default** `@prisma/client`

- **@remarks** Nexus Prisma imports Prisma client internally for two reasons: 1) validation wherein a class reference to Prisma Client is needed for some `instanceof` checks and 2) for acquiring the DMMF as Nexus Prisma relies on some post-processing done by Prisma Client generator.

- **@example**

```ts
// src/main.ts
import { PrismaClient } from '@prisma/client'
import { ApolloServer } from 'apollo-server'
import { makeSchema } from 'nexus'
import { User, Post, $settings } from 'nexus-prisma'
new ApolloServer({
schema: makeSchema({
types: [],
}),
})
$settings({
prismaClientImportId: '@my/custom/thing',
})
```

### Gentime Settings

You are able to control certain aspects of the Nexus Prisma code generation.

#### Usage

1. Create a configuration file named any of:

```
nexusPrisma.ts / nexus-prisma.ts / nexus_prisma.ts
```

In one of the following directories:

1. **Project Root**The directory containing your project's package.json. Example:

```
├── nexus-prisma.ts
└── package.json
```

2. **Primsa Directory**The directory containing your Prisma schema. Example:

```
├── prisma/nexus-prisma.ts
└── package.json
```

2. If you have not already, install [`ts-node`](https://github.com/TypeStrong/ts-node) which `nexus-prisma` will use to read your configuration module.

3. Import the settings singleton and make your desired changes. Example:

```ts
import { settings } from 'nexus-prisma/generator'
settings({
projectIdIntToGraphQL: 'ID',
})
```

#### Reference

##### `projectIdIntToGraphQL: 'ID' | 'Int'`

- **`@default`** `Int`
- **`@summary`** Map Prisma model fields of type `Int` with attribute `@id` to `ID` or `Int`.

##### `jsdocPropagationDefault?: 'none' | 'guide'`

- **`@default`** `'guide'`
- **`@summary`**

Nexus Prisma will project your Prisma schema field/model/enum documentation into JSDoc of the generated Nexus Prisma API.

This setting controls what Nexus Prisma should do when you have not written documentation in your Prisma Schema for a field/model/enum.

The following modes are as follows:

1. `'none'`

In this mode, no default JSDoc will be written.

2. `'guide'`

In this mode, guide content into your JSDoc that looks something like the following:

```
* ### ️⚠️ You have not writen documentation for ${thisItem}
* Replace this default advisory JSDoc with your own documentation about ${thisItem}
* by documenting it in your Prisma schema. For example:
* ...
* ...
* ...
```

##### `docPropagation.JSDoc: boolean`

- **`@default`** `true`
- **`@summary`** Should Prisma Schema docs propagate as JSDoc?

##### `docPropagation.GraphQLDocs: boolean`

- **`@default`** `true`
- **`@summary`** Should Prisma Schema docs propagate as GraphQL docs?
- **`@remarks`** When this is disabled it will force `.description` property to be `undefined`. This is for convenience, allowing you to avoid post-generation data manipulation or consumption contortions.

### Prisma String @id fields project as GraphQL ID fields

All `String` fields with `@id` attribute in your Prisma Schema get projected as GraphQL `ID` types rather than `String` types.

```prisma
model User {
id String @id
}
```

```ts
import { User } from 'nexus-prisma'
import { objectType } from 'nexus'
objectType({
name: User.$name
description: User.$description
definition(t) {
t.field(User.id)
}
})
```

```graphql
type User {
id: ID
}
```

### Prisma Schema Docs Propagation
## Prisma Schema Docs Propagation

#### As GraphQL schema doc

Expand Down Expand Up @@ -753,28 +573,28 @@ model Foo {

This formatting logic is conservative. We are open to making it less so, in order to support more expressivity. Please [open an issue](https://github.com/prisma/nexus-prisma/issues/new?assignees=&labels=type%2Ffeat&template=10-feature.md&title=Better%20extraction%20of%20Prisma%20documentation) if you have an idea.

### ESM Support
## ESM Support

Nexus Prisma supports both [ESM](https://nodejs.org/api/esm.html) and CJS. There shouldn't be anything you need to "do", things should "just work". Here's the highlights of how it works though:

- We publish both a CJS and ESM build to npm.
- When the generator runs, it emits CJS code to the CJS build _and_ ESM code to the ESM build.
- Nexus Prisma CLI exists both in the ESM and CJS builds but its built to not matter which is used. That said, the package manifest is setup to run the CJS of the CLI and so that is what ends up being used in practice.

### Refined DX
## Refined DX

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

##### JSDoc
#### JSDoc

- Generated Nexus configuration for fields and models that you _have not_ documented in your PSL get default JSDoc that teaches you how to do so.
- JSDoc for Enums have their members embedded

##### Default Runtime
#### Default 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.

##### Peer-Dependency Validation
#### Peer-Dependency Validation

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

Expand All @@ -785,6 +605,6 @@ NO_PEER_DEPENDENCY_CHECK=true|1
PEER_DEPENDENCY_CHECK=false|0
```

##### Auto-Import Optimized
#### Auto-Import Optimized

- `nexus-prisma/scalars` offers a default export you can easily auto-import by name: `NexusPrismaScalars`.
6 changes: 4 additions & 2 deletions docs/pages/meta.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@
"index": "Introduction",
"usage": "Usage",
"roadmap": "Roadmap",
"architecture": "Architecture",
"features": "Features",
"settings-gentime": "Settings (Gentime)",
"settings-runtime": "Settings (Runtime)",
"recipes": "Recipes",
"notes": "Notes"
"notes": "Notes",
"architecture": "Architecture"
}
Loading

1 comment on commit 83889bf

@vercel
Copy link

@vercel vercel bot commented on 83889bf Dec 15, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.