Compare commits
57 Commits
| Author | SHA1 | Date |
|---|---|---|
|
|
9e5c27c509 | |
|
|
601c2f03f4 | |
|
|
4e085dc7b2 | |
|
|
1e6b9212d3 | |
|
|
4d8e37177b | |
|
|
eec4b91091 | |
|
|
8e65081539 | |
|
|
7ee48c4f2c | |
|
|
e9dc7e0c4a | |
|
|
9875e90dae | |
|
|
9a1050792b | |
|
|
df9cb700a9 | |
|
|
123dc61fac | |
|
|
251af9461b | |
|
|
b906288c58 | |
|
|
11d028277e | |
|
|
509c246e88 | |
|
|
aaa45204b6 | |
|
|
7349e3633c | |
|
|
892af670a4 | |
|
|
bc12ca0f8e | |
|
|
0f37c3e9d4 | |
|
|
6c1530a3d5 | |
|
|
92f20dc9e9 | |
|
|
bbc969a5b0 | |
|
|
0d06f26b12 | |
|
|
e901bebd51 | |
|
|
87a82a28b1 | |
|
|
3de7f399c6 | |
|
|
45b9d5a926 | |
|
|
b92545fe4f | |
|
|
4d035019a4 | |
|
|
9ec3442539 | |
|
|
c0e55b53b4 | |
|
|
a7c26ba587 | |
|
|
703d5595da | |
|
|
02015ede84 | |
|
|
2934d6d38c | |
|
|
5e3b837ec0 | |
|
|
b24d132d38 | |
|
|
e5658cadba | |
|
|
333dfb8757 | |
|
|
02a73b5d74 | |
|
|
7e744aa0d3 | |
|
|
e65b5a7952 | |
|
|
d4c6260774 | |
|
|
6de1cb6917 | |
|
|
555ae79ded | |
|
|
a003ff074f | |
|
|
855a482c54 | |
|
|
266f1a82ce | |
|
|
380ed9d4ca | |
|
|
5984ee122e | |
|
|
a914cc33d1 | |
|
|
03b5ffd24a | |
|
|
4531519e6c | |
|
|
8e0ce1b4a1 |
|
|
@ -4,26 +4,24 @@ on:
|
|||
- pull_request
|
||||
|
||||
jobs:
|
||||
graphql-14:
|
||||
graphql-15:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 12.x
|
||||
node-version: 14.x
|
||||
- name: Install Dependencies
|
||||
run: yarn --frozen-lockfile || yarn --frozen-lockfile
|
||||
- name: Check Formatting
|
||||
run: yarn format:ci
|
||||
- name: Install GraphQL@14.x
|
||||
run: yarn add graphql@^14.5.8
|
||||
run: yarn --frozen-lockfile && yarn format:ci
|
||||
- name: Install GraphQL@15.x
|
||||
run: yarn add graphql@^15
|
||||
- name: Test
|
||||
run: yarn -s test:ci --testPathIgnorePatterns v15
|
||||
run: yarn -s test:ci
|
||||
|
||||
test:
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [12.x, 14.x]
|
||||
node-version: [14.x, 16.x]
|
||||
os: [macos-latest, ubuntu-latest, windows-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
|
|
@ -40,7 +38,7 @@ jobs:
|
|||
run: yarn -s test:ci
|
||||
- name: Upload coverage to Codecov
|
||||
uses: codecov/codecov-action@v1
|
||||
if: matrix.os == 'ubuntu-latest' && matrix.node-version == '10.x'
|
||||
if: matrix.os == 'ubuntu-latest' && matrix.node-version == '14.x'
|
||||
with:
|
||||
directory: ./coverage
|
||||
|
||||
|
|
@ -58,7 +56,7 @@ jobs:
|
|||
# rm examples/star-wars/star-wars-schema.graphql
|
||||
# node examples/star-wars/dist/schema.js
|
||||
# git diff --exit-code
|
||||
node-version: [12.x]
|
||||
node-version: [14.x]
|
||||
os: [macos-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
|
|
|
|||
|
|
@ -5,24 +5,24 @@ on:
|
|||
branches: [main]
|
||||
|
||||
jobs:
|
||||
graphql-14:
|
||||
graphql-15:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: 12.x
|
||||
node-version: 14.x
|
||||
- name: Install Dependencies
|
||||
run: yarn --frozen-lockfile || yarn --frozen-lockfile
|
||||
- name: Install GraphQL@14.x
|
||||
run: yarn add graphql@^14.5.8
|
||||
run: yarn --frozen-lockfile && yarn format:ci
|
||||
- name: Install GraphQL@15.x
|
||||
run: yarn add graphql@^15
|
||||
- name: Test
|
||||
run: yarn -s test:ci --testPathIgnorePatterns v15
|
||||
run: yarn -s test:ci
|
||||
|
||||
test:
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [12.x, 14.x]
|
||||
node-version: [14.x, 16.x]
|
||||
os: [macos-latest, ubuntu-latest, windows-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
|
|
@ -38,7 +38,7 @@ jobs:
|
|||
- name: Test
|
||||
run: yarn -s test:ci
|
||||
- name: Upload coverage to Codecov
|
||||
if: matrix.os == 'ubuntu-latest' && matrix.node-version == '10.x'
|
||||
if: matrix.os == 'ubuntu-latest' && matrix.node-version == '14.x'
|
||||
uses: codecov/codecov-action@v1
|
||||
with:
|
||||
directory: ./coverage
|
||||
|
|
@ -57,7 +57,7 @@ jobs:
|
|||
# rm examples/star-wars/star-wars-schema.graphql
|
||||
# node examples/star-wars/dist/schema.js
|
||||
# git diff --exit-code
|
||||
node-version: [12.x]
|
||||
node-version: [14.x]
|
||||
os: [macos-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
|
|
|
|||
|
|
@ -5,3 +5,4 @@ examples/*/dist
|
|||
website/static/playground-dist
|
||||
yarn-error.log
|
||||
coverage/*
|
||||
tests/esm/out/
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
(c) 2018-2019 Tim Griesser
|
||||
(c) 2018-2022 Tim Griesser
|
||||
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
obtaining a copy of this software and associated documentation
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
# Nexus
|
||||
|
||||
[](https://github.com/graphql-nexus/nexus/actions/workflows/trunk.yml)
|
||||
[](https://badge.fury.io/js/%40nexus%2Fschema)
|
||||
[](https://badge.fury.io/js/nexus)
|
||||
|
||||
Declarative, code-first and strongly typed GraphQL schema construction for TypeScript & JavaScript.
|
||||
|
||||
|
|
@ -74,4 +74,4 @@ You can find the docs for Nexus [here](http://nexusjs.org/).
|
|||
|
||||
## Migrate from SDL
|
||||
|
||||
If you've been following an [SDL-first](https://www.prisma.io/blog/the-problems-of-schema-first-graphql-development-x1mn4cb0tyl3/) approach to build your GraphQL server and want to see what your code looks like when written with GraphQL Nexus, you can use the [**SDL converter**](https://nexus.js.org/converter).
|
||||
If you've been following an [SDL-first](https://www.prisma.io/blog/the-problems-of-schema-first-graphql-development-x1mn4cb0tyl3/) approach to build your GraphQL server and want to see what your code looks like when written with GraphQL Nexus, you can use the [**SDL converter**](https://nexusjs.org/converter).
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ Start by creating your project directory, initializing your `package.json`, and
|
|||
```bash-symbol copy
|
||||
mkdir nexus-tutorial && cd nexus-tutorial
|
||||
npm init -y
|
||||
npm add nexus graphql apollo-server
|
||||
npm install nexus graphql apollo-server
|
||||
```
|
||||
|
||||
> Note: `nexus` works with any GraphQL compliant server. We'll use `apollo-server` in this tutorial, but you're free to use whichever fits your use-case best.
|
||||
|
|
@ -26,7 +26,7 @@ npm add nexus graphql apollo-server
|
|||
We'll also need `typescript` and `ts-node-dev` as dev dependencies. `ts-node-dev` will enable you to transpile your TS files on the fly and restart your API on changes.
|
||||
|
||||
```bash-symbol copy
|
||||
npm add --save-dev typescript ts-node-dev
|
||||
npm install --save-dev typescript ts-node-dev
|
||||
```
|
||||
|
||||
To properly get full advantage of TypeScript, we'll need a `tsconfig.json` file. Create one at the root of your project and copy paste the following
|
||||
|
|
@ -118,7 +118,7 @@ export const server = new ApolloServer({ schema })
|
|||
|
||||
```ts copy
|
||||
// api/index.ts
|
||||
import { server } from './server.ts'
|
||||
import { server } from './server'
|
||||
|
||||
server.listen().then(({ url }) => {
|
||||
console.log(`🚀 Server ready at ${url}`)
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ During this tutorial, you'll use the [Jest testing framework](https://jestjs.io/
|
|||
First, install `jest` and accompanying tools.
|
||||
|
||||
```bash-symbol copy
|
||||
npm add --save-dev jest @types/jest ts-jest graphql-request get-port
|
||||
npm install --save-dev jest @types/jest ts-jest graphql-request get-port@5.1.1
|
||||
```
|
||||
|
||||
Then, configure jest and npm scripts in your `package.json`
|
||||
|
|
@ -88,7 +88,7 @@ mkdir tests && touch tests/Post.test.ts
|
|||
|
||||
To ease testing, we'll create a small utility that we'll call `createTestContext`, which is designed for running integration tests.
|
||||
|
||||
When run, it will boot your app in the same process as the test suite and expose an interface for your tests to interact with it. Jest runs each test suite in its own process, so if you have have say eight test suites running in parallel that means you'll have eight app processes running too.
|
||||
When run, it will boot your app in the same process as the test suite and expose an interface for your tests to interact with it. Jest runs each test suite in its own process, so if you have say eight test suites running in parallel that means you'll have eight app processes running too.
|
||||
|
||||
Create a `tests/__helpers.ts` module with the following contents.
|
||||
|
||||
|
|
|
|||
|
|
@ -35,8 +35,8 @@ Now that you know a bit about Prisma, let's get going! Do the following:
|
|||
like so:
|
||||
|
||||
```bash-symbol copy
|
||||
npm add @prisma/client
|
||||
npm add --save-dev prisma
|
||||
npm install @prisma/client
|
||||
npm install --save-dev prisma
|
||||
```
|
||||
|
||||
Next, add Prisma to your project by creating your [Prisma schema](https://www.prisma.io/docs/concepts/components/prisma-schema/) file with the following command:
|
||||
|
|
@ -135,7 +135,7 @@ Now let's finally ditch our in-memory data! Let's replace it with the Prisma Cli
|
|||
// api/db.ts
|
||||
+import { PrismaClient } from '@prisma/client'
|
||||
|
||||
export const db = new PrismaClient()
|
||||
+export const db = new PrismaClient()
|
||||
|
||||
-export interface Post {
|
||||
- id: number
|
||||
|
|
@ -266,15 +266,15 @@ export const PostMutation = extendType({
|
|||
draftId: nonNull(intArg()),
|
||||
},
|
||||
resolve(_root, args, ctx) {
|
||||
- let postToPublish = ctx.db.posts.find((p) => p.id === args.draftId)
|
||||
- let draftToPublish = ctx.db.posts.find((p) => p.id === args.draftId)
|
||||
|
||||
- if (!postToPublish) {
|
||||
- if (!draftToPublish) {
|
||||
- throw new Error('Could not find draft with id ' + args.draftId)
|
||||
- }
|
||||
|
||||
- postToPublish.published = true
|
||||
- draftToPublish.published = true
|
||||
|
||||
- return postToPublish
|
||||
- return draftToPublish
|
||||
|
||||
+ return ctx.db.post.update({
|
||||
+ where: { id: args.draftId },
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ To achieve some of the steps described above, we'll tweak our test context.
|
|||
First, install the `sqlite3` and `nanoid` packages
|
||||
|
||||
```bash copy
|
||||
npm add --save-dev sqlite3 @types/sqlite3
|
||||
npm install --save-dev sqlite3 @types/sqlite3
|
||||
```
|
||||
|
||||
Then, head to your `tests/__helpers.ts` file to add the following imports and code
|
||||
|
|
@ -220,7 +220,7 @@ function prismaTestContext() {
|
|||
The `prismaTestContext` is in charge of a couple of things:
|
||||
|
||||
1. Connect to an in-memory instance of the SQLite database
|
||||
2. Pushes the Prisma Schema to the adatabase
|
||||
2. Pushes the Prisma Schema to the database
|
||||
3. Generates a new Prisma Client
|
||||
4. Add an instance of a Prisma Client connected to the schema specifically for the test
|
||||
|
||||
|
|
|
|||
|
|
@ -63,6 +63,7 @@ const Post = objectType({
|
|||
const Query = queryType({
|
||||
definition(t) {
|
||||
t.list.field('posts', {
|
||||
type: "Post",
|
||||
resolve: () => [
|
||||
{
|
||||
id: '1',
|
||||
|
|
@ -93,7 +94,7 @@ There are numerous benefits to taking a code-first approach with Nexus:
|
|||
|
||||
When building a schema-first GraphQL API, it is common to start out by placing all type definitions and resolvers in a single file. When both the schema and the resolvers live next to one another, it's fairly straightforward to work in both at the same time.
|
||||
|
||||
As the application grows, however, it is most often desired to move parts of the schema into their own separate modules and files. It's at this point that working on a GraphQL API becomes a bit more tedious. With this modularization comes the need to switch back and forth between the Schema Definition Language and JavaScript/TypeScript to write the resolvers. Not only does one need to constantly switch between files, they also need to do a context switch mentally to work between the two langauges.
|
||||
As the application grows, however, it is most often desired to move parts of the schema into their own separate modules and files. It's at this point that working on a GraphQL API becomes a bit more tedious. With this modularization comes the need to switch back and forth between the Schema Definition Language and JavaScript/TypeScript to write the resolvers. Not only does one need to constantly switch between files, they also need to do a context switch mentally to work between the two languages.
|
||||
|
||||
With Nexus, our schema and its resolvers are always defined together. Nexus also allows us to write everything in a common language. This allows us to side-step the co-location/context switching issue altogether and helps us to be more productive, even as our applications grow to be quite large.
|
||||
|
||||
|
|
@ -133,7 +134,7 @@ A downside of the schema-first approach is the need to repeat yourself in schema
|
|||
|
||||
### Defining enums
|
||||
|
||||
When defining an enum using the schema-first approach, the enum must first be defined in the schema definition languange:
|
||||
When defining an enum using the schema-first approach, the enum must first be defined in the schema definition language:
|
||||
|
||||
```graphql
|
||||
enum UserRole {
|
||||
|
|
|
|||
|
|
@ -28,18 +28,3 @@ Each public API is documented below, feel free to open a PR with more examples/c
|
|||
- [extendType / extendInputType](/api/extend-type)
|
||||
- [mutationField](/api/mutation-field)
|
||||
- [queryField](/api/query-field)
|
||||
|
||||
## Resolving: Inline Function
|
||||
|
||||
One common idiom in GraphQL is exposing fields that mask or rename the property name on the backing object. GraphQL Nexus makes this simple by allowing a function as the second parameter to any built-in scalar resolver function.
|
||||
|
||||
```ts
|
||||
const User = objectType({
|
||||
name: 'User',
|
||||
definition(t) {
|
||||
t.id('id', o => o.user_id)
|
||||
t.string('name', o => o.user_name)
|
||||
t.string('description', o => o.user_description)
|
||||
},
|
||||
})
|
||||
```
|
||||
|
|
|
|||
|
|
@ -65,3 +65,14 @@ const SomeObject = objectType({
|
|||
```
|
||||
|
||||
Check the type-definitions or [the examples](https://github.com/graphql-nexus/nexus/tree/main/examples) for a full illustration of the various options for `scalarType`, or feel free to open a PR on the docs to help document!
|
||||
|
||||
|
||||
## Pass scalar to schema generation
|
||||
It's important to list the scalar in the `types` attribute of `makeSchema`
|
||||
|
||||
```ts
|
||||
const schema = makeSchema({
|
||||
types: [GQLDate] // Add Scalar to Array
|
||||
})
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -10,11 +10,31 @@ codeStyle: true
|
|||
Defines a complex object which can be passed as an input value.
|
||||
|
||||
```ts
|
||||
export const InputType = inputObjectType({
|
||||
name: 'InputType',
|
||||
import { extendType, inputObjectType } from 'nexus'
|
||||
|
||||
export const CommentInputType = inputObjectType({
|
||||
name: 'CommentInputType',
|
||||
definition(t) {
|
||||
t.nonNull.string('key')
|
||||
t.int('answer')
|
||||
t.nonNull.int('userId')
|
||||
t.nonNull.string('body')
|
||||
}
|
||||
})
|
||||
|
||||
export const CommentMutation = extendType({
|
||||
type: 'Mutation',
|
||||
definition(t) {
|
||||
t.field('createComment', {
|
||||
type: 'Comment',
|
||||
args: { data: CommentInputType },
|
||||
resolve(_root, args, ctx) {
|
||||
return ctx.prisma.comment.create({
|
||||
data: {
|
||||
user_id: args.userId,
|
||||
body: args.body,
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
})
|
||||
```
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ import { queryType, stringArg, list } from 'nexus'
|
|||
queryType({
|
||||
definition(t) {
|
||||
t.field('tags', {
|
||||
type: list('String') // -> [String]
|
||||
type: list('String'), // -> [String]
|
||||
args: {
|
||||
ids: list(stringArg()) // or list('String') -> [String]
|
||||
},
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ title: Relay Connection
|
|||
|
||||
## Connection Plugin
|
||||
|
||||
The connection plugin provides a new method on the object definition builder, enabling paginated associations between types, following the [Relay Connection Specification](https://facebook.github.io/relay/graphql/connections.htm#sec-Node). It provides simple ways to customize fields available on the `Connection`, `Edges`, or `PageInfo` types.
|
||||
The connection plugin provides a new method on the object definition builder, enabling paginated associations between types, following the [Relay Connection Specification](https://relay.dev/graphql/connections.htm#sec-Node). It provides simple ways to customize fields available on the `Connection`, `Edges`, or `PageInfo` types.
|
||||
|
||||
To install, add the `connectionPlugin` to the `makeSchema.plugins` array, along with any other plugins
|
||||
you'd like to include:
|
||||
|
|
|
|||
|
|
@ -6,13 +6,13 @@ title: Overview
|
|||
|
||||
This plugin integrates [Prisma](https://www.prisma.io/) into [Nexus](https://nexusjs.org/). It gives you an API to project fields from models defined in your Prisma schema into your GraphQL API. It also gives you an API to build GraphQL root fields that allow your API clients to query and mutate data.
|
||||
|
||||
> **Note**: The Prisma team is currently [rewriting](https://github.com/graphql-nexus/nexus-plugin-prisma/issues/1039) the plugin to make it maintainable longterm.
|
||||
**Note**: You may also use [`nexus-prisma`](https://github.com/graphql-nexus/nexus-prisma), a newer API for integrating Nexus and Prisma.
|
||||
|
||||
## Installation
|
||||
|
||||
```bash-symbol
|
||||
npm add nexus-plugin-prisma @prisma/client
|
||||
npm add -D prisma
|
||||
npm install nexus-plugin-prisma @prisma/client
|
||||
npm install -D prisma
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
|
|
|||
|
|
@ -1586,7 +1586,7 @@ queryType({
|
|||
|
||||
type Query {
|
||||
user(where: UserWhereUniqueInput!): User
|
||||
users(orderBy: UserOrderByInput): [User!]!
|
||||
users(orderBy: [UserOrderByInput!]): [User!]!
|
||||
}
|
||||
|
||||
type Post {
|
||||
|
|
@ -1598,7 +1598,7 @@ type Post {
|
|||
type User {
|
||||
id: Int!
|
||||
name: String!
|
||||
posts(orderBy: UserPostsOrderByInput): [Post!]!
|
||||
posts(orderBy: [UserPostsOrderByInput!]): [Post!]!
|
||||
}
|
||||
|
||||
input UserOrderByInput {
|
||||
|
|
@ -1625,7 +1625,7 @@ enum OrderByArg {
|
|||
|
||||
```graphql
|
||||
query entrypointOrdering {
|
||||
users(orderBy: { name: asc }) {
|
||||
users(orderBy: [{ name: asc }]) {
|
||||
id
|
||||
name
|
||||
}
|
||||
|
|
@ -1633,7 +1633,7 @@ query entrypointOrdering {
|
|||
|
||||
query relationOrdering {
|
||||
user(where: { id: 1643 }) {
|
||||
posts(orderBy: { title: dsc }) {
|
||||
posts(orderBy: [{ title: desc }]) {
|
||||
title
|
||||
body
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ You will need to manage the TypeScript toolchain yourself.
|
|||
1. Install `typescript`, `ts-node`, and `ts-node-dev`.
|
||||
|
||||
```bash-symbol
|
||||
npm add -D typescript ts-node ts-node-dev
|
||||
npm install -D typescript ts-node ts-node-dev
|
||||
```
|
||||
|
||||
2. The following applies to VSCode but something like it might apply to other editors as well. You must also make sure your editor is set to use the local version of TypeScript rather than the one the editor ships with. Summon the command pallet `command+shift+p` and then enter and select `typescript: select TypeScript Version...`. Then select `Workspace Version`.
|
||||
|
|
@ -205,13 +205,13 @@ Nexus framework comes bundled with Apollo Server and runs it for you. You will n
|
|||
1. Install new dependencies
|
||||
|
||||
```tsx
|
||||
npm add express apollo-server-express
|
||||
npm install express apollo-server-express
|
||||
```
|
||||
|
||||
2. If using TypeScript then Install typings for Express
|
||||
|
||||
```tsx
|
||||
npm add -D @types/express
|
||||
npm install -D @types/express
|
||||
```
|
||||
|
||||
3. If using TypeScript then you [need to](https://github.com/apollographql/apollo-server/issues/1977#issuecomment-662946590) enable `esModuleInterop` to be able to use Apollo Server
|
||||
|
|
@ -337,7 +337,7 @@ Nexus Framework has some builtin logging functionality. You can approximate it a
|
|||
1. Install your logger
|
||||
|
||||
```tsx
|
||||
npm add floggy
|
||||
npm install floggy
|
||||
```
|
||||
|
||||
2. Create your application logger. The logger you export here should be used across your codebase.
|
||||
|
|
@ -386,7 +386,7 @@ You need to explicitly setup all custom scalars yourself. To match what Nexus Fr
|
|||
1. Install the `graphql-scalars` package
|
||||
|
||||
```json
|
||||
npm add graphql-scalars
|
||||
npm install graphql-scalars
|
||||
```
|
||||
|
||||
2. Setup the `Json` and `DateTime` scalars
|
||||
|
|
@ -448,7 +448,7 @@ import * as Path from 'path'
|
|||
|
||||
Nexus.makeSchema({
|
||||
contextType: {
|
||||
module: Path.join(__dirname, './path/to/contextModule'),
|
||||
module: Path.join(__dirname, './path/to/contextModule.ts'),
|
||||
alias: 'ContextModule',
|
||||
export: 'Context'
|
||||
},
|
||||
|
|
@ -536,13 +536,13 @@ In Nexus Framework there was a testing module for system testing your app. You n
|
|||
1. Install your test framework
|
||||
|
||||
```tsx
|
||||
npm add jest
|
||||
npm install jest
|
||||
```
|
||||
|
||||
2. If you are a TypeScript user then install and configure `ts-jest`
|
||||
|
||||
```bash
|
||||
npm add ts-jest
|
||||
npm install ts-jest
|
||||
```
|
||||
|
||||
We will configure using a `jest.config.js` module in your project root. Do not use a JSON based configuration unless you know that you won't need the dynamic code used in some later steps here.
|
||||
|
|
@ -639,7 +639,7 @@ In Nexus Framework there was a testing module for system testing your app. You n
|
|||
6. You will need a way to run your app in tests. Here is one way [adapted from the tutorial](https://todo.com).
|
||||
|
||||
```tsx
|
||||
npm add -D graphql-request
|
||||
npm install -D graphql-request
|
||||
```
|
||||
|
||||
```tsx
|
||||
|
|
@ -688,7 +688,7 @@ Nexus Framework had a CLI for scaffolding new projects. You can approximate this
|
|||
Nexus Framework has a gradual settings API with features such as automatic mapping of environment variables to settings. You can use the [`setset`](https://github.com/jasonkuhrt/setset) package manually to gain back this functionality.
|
||||
|
||||
```tsx
|
||||
npm add setset
|
||||
npm install setset
|
||||
```
|
||||
|
||||
```tsx
|
||||
|
|
|
|||
|
|
@ -13,8 +13,8 @@ If you're looking to migrate from the Nexus Framework over to Nexus and you're u
|
|||
You will need to install the Prisma dependencies yourself now.
|
||||
|
||||
```
|
||||
npm add -D @prisma/cli
|
||||
npm add @prisma/client
|
||||
npm install -D @prisma/cli
|
||||
npm install @prisma/client
|
||||
```
|
||||
|
||||
You must also make sure that you are using the version `0.20` or later of `nexus-plugin-prisma`.
|
||||
|
|
@ -82,7 +82,7 @@ export const schema = makeSchema({
|
|||
|
||||
### Configuring Context Type
|
||||
|
||||
The framework used to automatically inject and type your context so that an instance of the client would be there for you. We know need to configure that manually. To do so, we'll first create a `context.ts` file where we'll export a type containing the Prisma Client.
|
||||
The framework used to automatically inject and type your context so that an instance of the client would be there for you. We now need to configure that manually. To do so, we'll first create a `context.ts` file where we'll export a type containing the Prisma Client.
|
||||
|
||||
```tsx
|
||||
// context.ts
|
||||
|
|
@ -128,7 +128,7 @@ If your Prisma Schema is using either the `Json` or `DateTime` type, the framewo
|
|||
|
||||
```bash
|
||||
npm install graphql-scalars
|
||||
```
|
||||
```xf
|
||||
|
||||
2. Then, add the following configuration property to the Prisma plugin
|
||||
|
||||
|
|
|
|||
|
|
@ -22,8 +22,8 @@ Check out the [example projects](https://github.com/graphql-nexus/nexus/tree/mai
|
|||
## Installation
|
||||
|
||||
```sh
|
||||
npm add nexus
|
||||
npm add graphql # required as a peer dependency
|
||||
npm install nexus
|
||||
npm install graphql # required as a peer dependency
|
||||
```
|
||||
|
||||
If you are using TypeScript version `4.1` is suggested. Nexus doesn't have a hard requirement for it yet but may in a future non-breaking release.
|
||||
|
|
|
|||
|
|
@ -214,8 +214,7 @@ const Footer = ({ footerProps }: FooterViewProps) => {
|
|||
}
|
||||
</div>
|
||||
|
||||
<p className="social-text">Prisma © 2018-2020</p>
|
||||
<p>Made with ❤️ in Berlin</p>
|
||||
<p className="social-text">Tim Griesser © 2018-2022</p>
|
||||
</div>
|
||||
</SocialWrapper>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@
|
|||
"apollo-server-testing": "^2.18.1",
|
||||
"dedent": "^0.7.0",
|
||||
"fullstack-tutorial": "apollographql/fullstack-tutorial.git",
|
||||
"graphql": "^15.3.0",
|
||||
"graphql": "^16.3.0",
|
||||
"graphql-tools": "^4.0.7",
|
||||
"isemail": "^3.2.0",
|
||||
"nexus": "^1.0.0",
|
||||
|
|
@ -39,6 +39,6 @@
|
|||
"node-fetch": "^2.2.1",
|
||||
"prettier": "^1.19.1",
|
||||
"ts-node-dev": "^1.0.0-pre.30",
|
||||
"typescript": "^3.9"
|
||||
"typescript": "^4.5.5"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { idArg, list, nonNull, nullable, objectType, stringArg } from 'nexus'
|
||||
import { idArg, list, nonNull, objectType, stringArg } from 'nexus'
|
||||
|
||||
export const Mutation = objectType({
|
||||
name: 'Mutation',
|
||||
|
|
|
|||
|
|
@ -3169,6 +3169,11 @@ graphql@^15.3.0:
|
|||
resolved "https://registry.yarnpkg.com/graphql/-/graphql-15.3.0.tgz#3ad2b0caab0d110e3be4a5a9b2aa281e362b5278"
|
||||
integrity sha512-GTCJtzJmkFLWRfFJuoo9RWWa/FfamUHgiFosxi/X1Ani4AVWbeyBenZTNX6dM+7WSbbFfTo/25eh0LLkwHMw2w==
|
||||
|
||||
graphql@^16.3.0:
|
||||
version "16.3.0"
|
||||
resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.3.0.tgz#a91e24d10babf9e60c706919bb182b53ccdffc05"
|
||||
integrity sha512-xm+ANmA16BzCT5pLjuXySbQVFwH3oJctUVdy81w1sV0vBU0KgDdBGtxQOUd5zqOBk/JayAFeG8Dlmeq74rjm/A==
|
||||
|
||||
growly@^1.2.0, growly@^1.3.0:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081"
|
||||
|
|
@ -6799,10 +6804,10 @@ type-is@~1.6.17, type-is@~1.6.18:
|
|||
media-typer "0.3.0"
|
||||
mime-types "~2.1.24"
|
||||
|
||||
typescript@^3.9:
|
||||
version "3.9.7"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.7.tgz#98d600a5ebdc38f40cb277522f12dc800e9e25fa"
|
||||
integrity sha512-BLbiRkiBzAwsjut4x/dsibSTB6yWpwT5qWmC2OfuCg3GgVQCSgMs4vEctYPhsaGtd0AeuuHMkjZ2h2WG8MSzRw==
|
||||
typescript@^4.5.5:
|
||||
version "4.5.5"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.5.5.tgz#d8c953832d28924a9e3d37c73d729c846c5896f3"
|
||||
integrity sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA==
|
||||
|
||||
uglify-js@^3.1.4:
|
||||
version "3.4.9"
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
"dataloader": "tgriesser/dataloader.git#ts-types",
|
||||
"express": "^4.16.4",
|
||||
"ghost": "^3.35.3",
|
||||
"graphql": "^15.3.0",
|
||||
"graphql": "^16.3.0",
|
||||
"graphql-scalars": "^1.2.6",
|
||||
"graphql-tools": "^4.0.7",
|
||||
"knex": "^0.19.5",
|
||||
|
|
@ -27,6 +27,6 @@
|
|||
"prettier": "^1.19.1",
|
||||
"ts-node": "^8.0.2",
|
||||
"ts-node-dev": "^1.0.0-pre.30",
|
||||
"typescript": "^3.9"
|
||||
"typescript": "^4.5.5"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -6,7 +6,7 @@
|
|||
"dependencies": {
|
||||
"apollo-server": "^2.18.1",
|
||||
"githunt-api": "peggyrayzis/GitHunt-API",
|
||||
"graphql": "^14.5.8",
|
||||
"graphql": "^16.3.0",
|
||||
"graphql-tools": "^4.0.7",
|
||||
"nexus": "^1.0.0"
|
||||
},
|
||||
|
|
@ -14,6 +14,6 @@
|
|||
"nodemon": "^1.18.6",
|
||||
"prettier": "^1.19.1",
|
||||
"sqlite3": "^4.1.0",
|
||||
"typescript": "^3.9"
|
||||
"typescript": "^4.5.5"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2962,18 +2962,16 @@ graphql-upload@^8.0.2:
|
|||
dependencies:
|
||||
iterall "^1.1.0"
|
||||
|
||||
graphql@^14.5.8:
|
||||
version "14.5.8"
|
||||
resolved "https://registry.yarnpkg.com/graphql/-/graphql-14.5.8.tgz#504f3d3114cb9a0a3f359bbbcf38d9e5bf6a6b3c"
|
||||
integrity sha512-MMwmi0zlVLQKLdGiMfWkgQD7dY/TUKt4L+zgJ/aR0Howebod3aNgP5JkgvAULiR2HPVZaP2VEElqtdidHweLkg==
|
||||
dependencies:
|
||||
iterall "^1.2.2"
|
||||
|
||||
graphql@^15.3.0:
|
||||
version "15.3.0"
|
||||
resolved "https://registry.yarnpkg.com/graphql/-/graphql-15.3.0.tgz#3ad2b0caab0d110e3be4a5a9b2aa281e362b5278"
|
||||
integrity sha512-GTCJtzJmkFLWRfFJuoo9RWWa/FfamUHgiFosxi/X1Ani4AVWbeyBenZTNX6dM+7WSbbFfTo/25eh0LLkwHMw2w==
|
||||
|
||||
graphql@^16.3.0:
|
||||
version "16.3.0"
|
||||
resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.3.0.tgz#a91e24d10babf9e60c706919bb182b53ccdffc05"
|
||||
integrity sha512-xm+ANmA16BzCT5pLjuXySbQVFwH3oJctUVdy81w1sV0vBU0KgDdBGtxQOUd5zqOBk/JayAFeG8Dlmeq74rjm/A==
|
||||
|
||||
har-schema@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92"
|
||||
|
|
@ -3516,7 +3514,7 @@ isstream@~0.1.2:
|
|||
resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a"
|
||||
integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=
|
||||
|
||||
iterall@^1.1.0, iterall@^1.1.3, iterall@^1.2.1, iterall@^1.2.2:
|
||||
iterall@^1.1.0, iterall@^1.1.3, iterall@^1.2.1:
|
||||
version "1.2.2"
|
||||
resolved "https://registry.yarnpkg.com/iterall/-/iterall-1.2.2.tgz#92d70deb8028e0c39ff3164fdbf4d8b088130cd7"
|
||||
integrity sha512-yynBb1g+RFUPY64fTrFv7nsjRrENBQJaX2UL+2Szc9REFrSNm1rpSXHGzhmAy7a9uv3vlvgBlXnf9RqmPH1/DA==
|
||||
|
|
@ -5588,10 +5586,10 @@ type-is@~1.6.14, type-is@~1.6.17, type-is@~1.6.18:
|
|||
media-typer "0.3.0"
|
||||
mime-types "~2.1.24"
|
||||
|
||||
typescript@^3.9:
|
||||
version "3.9.7"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.7.tgz#98d600a5ebdc38f40cb277522f12dc800e9e25fa"
|
||||
integrity sha512-BLbiRkiBzAwsjut4x/dsibSTB6yWpwT5qWmC2OfuCg3GgVQCSgMs4vEctYPhsaGtd0AeuuHMkjZ2h2WG8MSzRw==
|
||||
typescript@^4.5.5:
|
||||
version "4.5.5"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.5.5.tgz#d8c953832d28924a9e3d37c73d729c846c5896f3"
|
||||
integrity sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA==
|
||||
|
||||
uid-safe@~2.1.4:
|
||||
version "2.1.5"
|
||||
|
|
|
|||
|
|
@ -19,24 +19,24 @@ interface Baz {
|
|||
|
||||
type BooleanConnection {
|
||||
"""
|
||||
https://facebook.github.io/relay/graphql/connections.htm#sec-Edge-Types
|
||||
https://relay.dev/graphql/connections.htm#sec-Edge-Types
|
||||
"""
|
||||
edges: [BooleanEdge]
|
||||
|
||||
"""
|
||||
https://facebook.github.io/relay/graphql/connections.htm#sec-undefined.PageInfo
|
||||
https://relay.dev/graphql/connections.htm#sec-undefined.PageInfo
|
||||
"""
|
||||
pageInfo: PageInfo!
|
||||
}
|
||||
|
||||
type BooleanEdge {
|
||||
"""
|
||||
https://facebook.github.io/relay/graphql/connections.htm#sec-Cursor
|
||||
https://relay.dev/graphql/connections.htm#sec-Cursor
|
||||
"""
|
||||
cursor: String!
|
||||
|
||||
"""
|
||||
https://facebook.github.io/relay/graphql/connections.htm#sec-Node
|
||||
https://relay.dev/graphql/connections.htm#sec-Node
|
||||
"""
|
||||
node: Boolean
|
||||
}
|
||||
|
|
@ -49,24 +49,24 @@ scalar Date
|
|||
|
||||
type DateConnection {
|
||||
"""
|
||||
https://facebook.github.io/relay/graphql/connections.htm#sec-Edge-Types
|
||||
https://relay.dev/graphql/connections.htm#sec-Edge-Types
|
||||
"""
|
||||
edges: [DateEdge]
|
||||
|
||||
"""
|
||||
https://facebook.github.io/relay/graphql/connections.htm#sec-undefined.PageInfo
|
||||
https://relay.dev/graphql/connections.htm#sec-undefined.PageInfo
|
||||
"""
|
||||
pageInfo: PageInfo!
|
||||
}
|
||||
|
||||
type DateEdge {
|
||||
"""
|
||||
https://facebook.github.io/relay/graphql/connections.htm#sec-Cursor
|
||||
https://relay.dev/graphql/connections.htm#sec-Cursor
|
||||
"""
|
||||
cursor: String!
|
||||
|
||||
"""
|
||||
https://facebook.github.io/relay/graphql/connections.htm#sec-Node
|
||||
https://relay.dev/graphql/connections.htm#sec-Node
|
||||
"""
|
||||
node: Date
|
||||
}
|
||||
|
|
@ -104,7 +104,7 @@ interface Node {
|
|||
}
|
||||
|
||||
"""
|
||||
PageInfo cursor, as defined in https://facebook.github.io/relay/graphql/connections.htm#sec-undefined.PageInfo
|
||||
PageInfo cursor, as defined in https://relay.dev/graphql/connections.htm#sec-undefined.PageInfo
|
||||
"""
|
||||
type PageInfo {
|
||||
"""
|
||||
|
|
@ -306,24 +306,24 @@ type User {
|
|||
|
||||
type UserConnection {
|
||||
"""
|
||||
https://facebook.github.io/relay/graphql/connections.htm#sec-Edge-Types
|
||||
https://relay.dev/graphql/connections.htm#sec-Edge-Types
|
||||
"""
|
||||
edges: [UserEdge]
|
||||
|
||||
"""
|
||||
https://facebook.github.io/relay/graphql/connections.htm#sec-undefined.PageInfo
|
||||
https://relay.dev/graphql/connections.htm#sec-undefined.PageInfo
|
||||
"""
|
||||
pageInfo: PageInfo!
|
||||
}
|
||||
|
||||
type UserEdge {
|
||||
"""
|
||||
https://facebook.github.io/relay/graphql/connections.htm#sec-Cursor
|
||||
https://relay.dev/graphql/connections.htm#sec-Cursor
|
||||
"""
|
||||
cursor: String!
|
||||
|
||||
"""
|
||||
https://facebook.github.io/relay/graphql/connections.htm#sec-Node
|
||||
https://relay.dev/graphql/connections.htm#sec-Node
|
||||
"""
|
||||
node: User
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"apollo-server": "^2.18.1",
|
||||
"graphql": "^15.3.0",
|
||||
"graphql": "^16.3.0",
|
||||
"graphql-query-complexity": "^0.4.1",
|
||||
"graphql-relay": "^0.6.0",
|
||||
"graphql-subscriptions": "^1.0.0",
|
||||
|
|
@ -19,7 +19,7 @@
|
|||
"nexus": "^1.0.0",
|
||||
"subscriptions-transport-ws": "^0.9.15",
|
||||
"ts-node": "^8.5.4",
|
||||
"typescript": "^3.9"
|
||||
"typescript": "^4.5.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/graphql-relay": "^0.4.11",
|
||||
|
|
|
|||
|
|
@ -21,7 +21,11 @@ const schema = makeSchema({
|
|||
types,
|
||||
outputs: {
|
||||
schema: path.join(__dirname, '../kitchen-sink-schema.graphql'),
|
||||
typegen: path.join(__dirname, './kitchen-sink.gen.ts'),
|
||||
typegen: {
|
||||
outputPath: path.join(__dirname, './kitchen-sink.gen.ts'),
|
||||
globalsPath: path.join(__dirname, './kitchen-sink-globals.gen.ts'),
|
||||
declareInputs: true,
|
||||
},
|
||||
},
|
||||
plugins: [
|
||||
NodePlugin,
|
||||
|
|
|
|||
|
|
@ -391,9 +391,17 @@ export const MoreQueryFields = extendType({
|
|||
|
||||
export const DateScalar = scalarType({
|
||||
name: 'Date',
|
||||
serialize: (value) => value.getTime(),
|
||||
parseValue: (value) => new Date(value),
|
||||
parseLiteral: (ast) => (ast.kind === 'IntValue' ? new Date(ast.value) : null),
|
||||
serialize: (value) => (value as Date).toISOString(),
|
||||
parseValue: (value) => new Date(value as string | number),
|
||||
parseLiteral: (ast) => {
|
||||
if (ast.kind === 'IntValue' || ast.kind === 'StringValue') {
|
||||
const d = new Date(ast.value)
|
||||
if (!isNaN(d.valueOf())) {
|
||||
return d
|
||||
}
|
||||
}
|
||||
throw new Error('Invalid date')
|
||||
},
|
||||
asNexusMethod: 'date',
|
||||
sourceType: 'Date',
|
||||
})
|
||||
|
|
|
|||
|
|
@ -0,0 +1,65 @@
|
|||
/** This file was generated by Nexus Schema Do not make changes to this file directly */
|
||||
|
||||
import type { NexusGenTypes } from './kitchen-sink.gen'
|
||||
declare global {
|
||||
interface NexusGenCustomInputMethods<TypeName extends string> {
|
||||
date<FieldName extends string>(
|
||||
fieldName: FieldName,
|
||||
opts?: core.CommonInputFieldConfig<TypeName, FieldName>
|
||||
): void // "Date";
|
||||
}
|
||||
}
|
||||
declare global {
|
||||
interface NexusGenCustomOutputMethods<TypeName extends string> {
|
||||
date<FieldName extends string>(
|
||||
fieldName: FieldName,
|
||||
...opts: core.ScalarOutSpread<TypeName, FieldName>
|
||||
): void // "Date";
|
||||
/**
|
||||
* Adds a Relay-style connection to the type, with numerous options for configuration
|
||||
*
|
||||
* @see https://nexusjs.org/docs/plugins/connection
|
||||
*/
|
||||
connectionField<FieldName extends string>(
|
||||
fieldName: FieldName,
|
||||
config: connectionPluginCore.ConnectionFieldConfig<TypeName, FieldName>
|
||||
): void
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface NexusGen extends NexusGenTypes {}
|
||||
}
|
||||
|
||||
import type { core, connectionPluginCore } from 'nexus'
|
||||
import type { QueryComplexity } from 'nexus/dist/plugins/queryComplexityPlugin'
|
||||
import type { FieldAuthorizeResolver } from 'nexus/dist/plugins/fieldAuthorizePlugin'
|
||||
|
||||
declare global {
|
||||
interface NexusGenPluginTypeConfig<TypeName extends string> {
|
||||
node?: string | core.FieldResolver<TypeName, any>
|
||||
}
|
||||
interface NexusGenPluginInputTypeConfig<TypeName extends string> {}
|
||||
interface NexusGenPluginFieldConfig<TypeName extends string, FieldName extends string> {
|
||||
/**
|
||||
* The complexity for an individual field. Return a number or a function that returns a number to specify
|
||||
* the complexity for this field.
|
||||
*/
|
||||
complexity?: QueryComplexity<TypeName, FieldName>
|
||||
/**
|
||||
* Authorization for an individual field. Returning "true" or "Promise<true>" means the field can be
|
||||
* accessed. Returning "false" or "Promise<false>" will respond with a "Not Authorized" error for the
|
||||
* field. Returning or throwing an error will also prevent the resolver from executing.
|
||||
*/
|
||||
authorize?: FieldAuthorizeResolver<TypeName, FieldName>
|
||||
/**
|
||||
* The nullability guard can be helpful, but is also a potentially expensive operation for lists. We need
|
||||
* to iterate the entire list to check for null items to guard against. Set this to true to skip the null
|
||||
* guard on a specific field if you know there's no potential for unsafe types.
|
||||
*/
|
||||
skipNullGuard?: boolean
|
||||
}
|
||||
interface NexusGenPluginInputFieldConfig<TypeName extends string, FieldName extends string> {}
|
||||
interface NexusGenPluginSchemaConfig {}
|
||||
interface NexusGenPluginArgConfig {}
|
||||
}
|
||||
|
|
@ -1,61 +1,34 @@
|
|||
/** This file was generated by Nexus Schema Do not make changes to this file directly */
|
||||
|
||||
import { UnusedInterfaceTypeDef } from './kitchen-sink-definitions'
|
||||
import { core, connectionPluginCore } from 'nexus'
|
||||
import { QueryComplexity } from 'nexus/dist/plugins/queryComplexityPlugin'
|
||||
import { FieldAuthorizeResolver } from 'nexus/dist/plugins/fieldAuthorizePlugin'
|
||||
declare global {
|
||||
interface NexusGenCustomInputMethods<TypeName extends string> {
|
||||
date<FieldName extends string>(
|
||||
fieldName: FieldName,
|
||||
opts?: core.CommonInputFieldConfig<TypeName, FieldName>
|
||||
): void // "Date";
|
||||
}
|
||||
}
|
||||
declare global {
|
||||
interface NexusGenCustomOutputMethods<TypeName extends string> {
|
||||
date<FieldName extends string>(
|
||||
fieldName: FieldName,
|
||||
...opts: core.ScalarOutSpread<TypeName, FieldName>
|
||||
): void // "Date";
|
||||
/**
|
||||
* Adds a Relay-style connection to the type, with numerous options for configuration
|
||||
*
|
||||
* @see https://nexusjs.org/docs/plugins/connection
|
||||
*/
|
||||
connectionField<FieldName extends string>(
|
||||
fieldName: FieldName,
|
||||
config: connectionPluginCore.ConnectionFieldConfig<TypeName, FieldName>
|
||||
): void
|
||||
}
|
||||
import type { UnusedInterfaceTypeDef } from './kitchen-sink-definitions'
|
||||
import type { core } from 'nexus'
|
||||
|
||||
export interface InputType {
|
||||
answer?: number | null // Int
|
||||
key: string // String!
|
||||
nestedInput?: InputType2 | null // InputType2
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface NexusGen extends NexusGenTypes {}
|
||||
export interface InputType2 {
|
||||
answer?: number | null // Int
|
||||
key: string // String!
|
||||
someDate: NexusGenScalars['Date'] // Date!
|
||||
}
|
||||
|
||||
export interface NestedType {
|
||||
veryNested?: string | null // String
|
||||
}
|
||||
|
||||
export interface SomeArg {
|
||||
arg?: NestedType | null // NestedType
|
||||
someField?: string | null // String
|
||||
}
|
||||
|
||||
export interface NexusGenInputs {
|
||||
InputType: {
|
||||
// input type
|
||||
answer?: number | null // Int
|
||||
key: string // String!
|
||||
nestedInput?: NexusGenInputs['InputType2'] | null // InputType2
|
||||
}
|
||||
InputType2: {
|
||||
// input type
|
||||
answer?: number | null // Int
|
||||
key: string // String!
|
||||
someDate: NexusGenScalars['Date'] // Date!
|
||||
}
|
||||
NestedType: {
|
||||
// input type
|
||||
veryNested?: string | null // String
|
||||
}
|
||||
SomeArg: {
|
||||
// input type
|
||||
arg?: NexusGenInputs['NestedType'] | null // NestedType
|
||||
someField?: string | null // String
|
||||
}
|
||||
InputType: InputType
|
||||
InputType2: InputType2
|
||||
NestedType: NestedType
|
||||
SomeArg: SomeArg
|
||||
}
|
||||
|
||||
export interface NexusGenEnums {}
|
||||
|
|
@ -390,100 +363,117 @@ export interface NexusGenFieldTypeNames {
|
|||
}
|
||||
}
|
||||
|
||||
export interface FooArgsTestArgs {
|
||||
a: InputType | null // InputType
|
||||
}
|
||||
|
||||
export interface MutationSomeMutationFieldArgs {
|
||||
id: string // ID!
|
||||
}
|
||||
|
||||
export interface QueryAsArgExampleArgs {
|
||||
testAsArg: InputType // InputType!
|
||||
}
|
||||
|
||||
export interface QueryBooleanConnectionArgs {
|
||||
after?: string | null // String
|
||||
first: number // Int!
|
||||
}
|
||||
|
||||
export interface QueryComplexQueryArgs {
|
||||
count: number // Int!
|
||||
}
|
||||
|
||||
export interface QueryDeprecatedConnectionArgs {
|
||||
after?: string | null // String
|
||||
before?: string | null // String
|
||||
first?: number | null // Int
|
||||
last?: number | null // Int
|
||||
}
|
||||
|
||||
export interface QueryGetNumberOrNullArgs {
|
||||
a: number // Int!
|
||||
}
|
||||
|
||||
export interface QueryGuardedConnectionArgs {
|
||||
after?: string | null // String
|
||||
first: number // Int!
|
||||
}
|
||||
|
||||
export interface QueryInlineArgsArgs {
|
||||
someArg?: SomeArg | null // SomeArg
|
||||
}
|
||||
|
||||
export interface QueryInputAsArgExampleArgs {
|
||||
testInput?: InputType | null // InputType
|
||||
testScalar?: string | null // String
|
||||
}
|
||||
|
||||
export interface QueryUserConnectionAdditionalArgsArgs {
|
||||
after?: string | null // String
|
||||
first: number // Int!
|
||||
isEven?: boolean | null // Boolean
|
||||
}
|
||||
|
||||
export interface QueryUserConnectionBackwardOnlyArgs {
|
||||
before?: string | null // String
|
||||
last: number // Int!
|
||||
}
|
||||
|
||||
export interface QueryUserConnectionForwardOnlyArgs {
|
||||
after?: string | null // String
|
||||
first: number // Int!
|
||||
}
|
||||
|
||||
export interface QueryUsersConnectionNodesArgs {
|
||||
after?: string | null // String
|
||||
before?: string | null // String
|
||||
first?: number | null // Int
|
||||
last?: number | null // Int
|
||||
}
|
||||
|
||||
export interface QueryUsersConnectionResolveArgs {
|
||||
after?: string | null // String
|
||||
before?: string | null // String
|
||||
first?: number | null // Int
|
||||
last?: number | null // Int
|
||||
}
|
||||
|
||||
export interface TestObjArgsTestArgs {
|
||||
a: InputType | null // InputType
|
||||
}
|
||||
|
||||
export interface BarArgsTestArgs {
|
||||
a: InputType | null // InputType
|
||||
}
|
||||
|
||||
export interface NexusGenArgTypes {
|
||||
Foo: {
|
||||
argsTest: {
|
||||
// args
|
||||
a: NexusGenInputs['InputType'] | null // InputType
|
||||
}
|
||||
argsTest: FooArgsTestArgs
|
||||
}
|
||||
Mutation: {
|
||||
someMutationField: {
|
||||
// args
|
||||
id: string // ID!
|
||||
}
|
||||
someMutationField: MutationSomeMutationFieldArgs
|
||||
}
|
||||
Query: {
|
||||
asArgExample: {
|
||||
// args
|
||||
testAsArg: NexusGenInputs['InputType'] // InputType!
|
||||
}
|
||||
booleanConnection: {
|
||||
// args
|
||||
after?: string | null // String
|
||||
first: number // Int!
|
||||
}
|
||||
complexQuery: {
|
||||
// args
|
||||
count: number // Int!
|
||||
}
|
||||
deprecatedConnection: {
|
||||
// args
|
||||
after?: string | null // String
|
||||
before?: string | null // String
|
||||
first?: number | null // Int
|
||||
last?: number | null // Int
|
||||
}
|
||||
getNumberOrNull: {
|
||||
// args
|
||||
a: number // Int!
|
||||
}
|
||||
guardedConnection: {
|
||||
// args
|
||||
after?: string | null // String
|
||||
first: number // Int!
|
||||
}
|
||||
inlineArgs: {
|
||||
// args
|
||||
someArg?: NexusGenInputs['SomeArg'] | null // SomeArg
|
||||
}
|
||||
inputAsArgExample: {
|
||||
// args
|
||||
testInput?: NexusGenInputs['InputType'] | null // InputType
|
||||
testScalar?: string | null // String
|
||||
}
|
||||
userConnectionAdditionalArgs: {
|
||||
// args
|
||||
after?: string | null // String
|
||||
first: number // Int!
|
||||
isEven?: boolean | null // Boolean
|
||||
}
|
||||
userConnectionBackwardOnly: {
|
||||
// args
|
||||
before?: string | null // String
|
||||
last: number // Int!
|
||||
}
|
||||
userConnectionForwardOnly: {
|
||||
// args
|
||||
after?: string | null // String
|
||||
first: number // Int!
|
||||
}
|
||||
usersConnectionNodes: {
|
||||
// args
|
||||
after?: string | null // String
|
||||
before?: string | null // String
|
||||
first?: number | null // Int
|
||||
last?: number | null // Int
|
||||
}
|
||||
usersConnectionResolve: {
|
||||
// args
|
||||
after?: string | null // String
|
||||
before?: string | null // String
|
||||
first?: number | null // Int
|
||||
last?: number | null // Int
|
||||
}
|
||||
asArgExample: QueryAsArgExampleArgs
|
||||
booleanConnection: QueryBooleanConnectionArgs
|
||||
complexQuery: QueryComplexQueryArgs
|
||||
deprecatedConnection: QueryDeprecatedConnectionArgs
|
||||
getNumberOrNull: QueryGetNumberOrNullArgs
|
||||
guardedConnection: QueryGuardedConnectionArgs
|
||||
inlineArgs: QueryInlineArgsArgs
|
||||
inputAsArgExample: QueryInputAsArgExampleArgs
|
||||
userConnectionAdditionalArgs: QueryUserConnectionAdditionalArgsArgs
|
||||
userConnectionBackwardOnly: QueryUserConnectionBackwardOnlyArgs
|
||||
userConnectionForwardOnly: QueryUserConnectionForwardOnlyArgs
|
||||
usersConnectionNodes: QueryUsersConnectionNodesArgs
|
||||
usersConnectionResolve: QueryUsersConnectionResolveArgs
|
||||
}
|
||||
TestObj: {
|
||||
argsTest: {
|
||||
// args
|
||||
a: NexusGenInputs['InputType'] | null // InputType
|
||||
}
|
||||
argsTest: TestObjArgsTestArgs
|
||||
}
|
||||
Bar: {
|
||||
argsTest: {
|
||||
// args
|
||||
a: NexusGenInputs['InputType'] | null // InputType
|
||||
}
|
||||
argsTest: BarArgsTestArgs
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -554,99 +544,3 @@ export interface NexusGenTypes {
|
|||
abstractsUsingStrategyResolveType: NexusGenAbstractsUsingStrategyResolveType
|
||||
features: NexusGenFeaturesConfig
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface NexusGenPluginTypeConfig<TypeName extends string> {
|
||||
node?: string | core.FieldResolver<TypeName, any>
|
||||
}
|
||||
interface NexusGenPluginFieldConfig<TypeName extends string, FieldName extends string> {
|
||||
/**
|
||||
* The complexity for an individual field. Return a number or a function that returns a number to specify
|
||||
* the complexity for this field.
|
||||
*/
|
||||
complexity?: QueryComplexity<TypeName, FieldName>
|
||||
/**
|
||||
* Authorization for an individual field. Returning "true" or "Promise<true>" means the field can be
|
||||
* accessed. Returning "false" or "Promise<false>" will respond with a "Not Authorized" error for the
|
||||
* field. Returning or throwing an error will also prevent the resolver from executing.
|
||||
*/
|
||||
authorize?: FieldAuthorizeResolver<TypeName, FieldName>
|
||||
/**
|
||||
* The nullability guard can be helpful, but is also a potentially expensive operation for lists. We need
|
||||
* to iterate the entire list to check for null items to guard against. Set this to true to skip the null
|
||||
* guard on a specific field if you know there's no potential for unsafe types.
|
||||
*/
|
||||
skipNullGuard?: boolean
|
||||
/**
|
||||
* Whether the type can be null
|
||||
*
|
||||
* @default (depends on whether nullability is configured in type or schema)
|
||||
* @see declarativeWrappingPlugin
|
||||
*/
|
||||
nullable?: boolean
|
||||
/**
|
||||
* Whether the type is list of values, or just a single value. If list is true, we assume the type is a
|
||||
* list. If list is an array, we'll assume that it's a list with the depth. The boolean indicates whether
|
||||
* the type is required (non-null), where true = nonNull, false = nullable.
|
||||
*
|
||||
* @see declarativeWrappingPlugin
|
||||
*/
|
||||
list?: true | boolean[]
|
||||
/**
|
||||
* Whether the type should be non null, `required: true` = `nullable: false`
|
||||
*
|
||||
* @default (depends on whether nullability is configured in type or schema)
|
||||
* @see declarativeWrappingPlugin
|
||||
*/
|
||||
required?: boolean
|
||||
}
|
||||
interface NexusGenPluginInputFieldConfig<TypeName extends string, FieldName extends string> {
|
||||
/**
|
||||
* Whether the type can be null
|
||||
*
|
||||
* @default (depends on whether nullability is configured in type or schema)
|
||||
* @see declarativeWrappingPlugin
|
||||
*/
|
||||
nullable?: boolean
|
||||
/**
|
||||
* Whether the type is list of values, or just a single value. If list is true, we assume the type is a
|
||||
* list. If list is an array, we'll assume that it's a list with the depth. The boolean indicates whether
|
||||
* the type is required (non-null), where true = nonNull, false = nullable.
|
||||
*
|
||||
* @see declarativeWrappingPlugin
|
||||
*/
|
||||
list?: true | boolean[]
|
||||
/**
|
||||
* Whether the type should be non null, `required: true` = `nullable: false`
|
||||
*
|
||||
* @default (depends on whether nullability is configured in type or schema)
|
||||
* @see declarativeWrappingPlugin
|
||||
*/
|
||||
required?: boolean
|
||||
}
|
||||
interface NexusGenPluginSchemaConfig {}
|
||||
interface NexusGenPluginArgConfig {
|
||||
/**
|
||||
* Whether the type can be null
|
||||
*
|
||||
* @default (depends on whether nullability is configured in type or schema)
|
||||
* @see declarativeWrappingPlugin
|
||||
*/
|
||||
nullable?: boolean
|
||||
/**
|
||||
* Whether the type is list of values, or just a single value. If list is true, we assume the type is a
|
||||
* list. If list is an array, we'll assume that it's a list with the depth. The boolean indicates whether
|
||||
* the type is required (non-null), where true = nonNull, false = nullable.
|
||||
*
|
||||
* @see declarativeWrappingPlugin
|
||||
*/
|
||||
list?: true | boolean[]
|
||||
/**
|
||||
* Whether the type should be non null, `required: true` = `nullable: false`
|
||||
*
|
||||
* @default (depends on whether nullability is configured in type or schema)
|
||||
* @see declarativeWrappingPlugin
|
||||
*/
|
||||
required?: boolean
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2140,6 +2140,11 @@ graphql@^15.3.0:
|
|||
resolved "https://registry.yarnpkg.com/graphql/-/graphql-15.3.0.tgz#3ad2b0caab0d110e3be4a5a9b2aa281e362b5278"
|
||||
integrity sha512-GTCJtzJmkFLWRfFJuoo9RWWa/FfamUHgiFosxi/X1Ani4AVWbeyBenZTNX6dM+7WSbbFfTo/25eh0LLkwHMw2w==
|
||||
|
||||
graphql@^16.3.0:
|
||||
version "16.3.0"
|
||||
resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.3.0.tgz#a91e24d10babf9e60c706919bb182b53ccdffc05"
|
||||
integrity sha512-xm+ANmA16BzCT5pLjuXySbQVFwH3oJctUVdy81w1sV0vBU0KgDdBGtxQOUd5zqOBk/JayAFeG8Dlmeq74rjm/A==
|
||||
|
||||
growly@^1.2.0, growly@^1.3.0:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081"
|
||||
|
|
@ -5070,10 +5075,10 @@ type-is@~1.6.16:
|
|||
media-typer "0.3.0"
|
||||
mime-types "~2.1.18"
|
||||
|
||||
typescript@^3.9:
|
||||
version "3.9.7"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.7.tgz#98d600a5ebdc38f40cb277522f12dc800e9e25fa"
|
||||
integrity sha512-BLbiRkiBzAwsjut4x/dsibSTB6yWpwT5qWmC2OfuCg3GgVQCSgMs4vEctYPhsaGtd0AeuuHMkjZ2h2WG8MSzRw==
|
||||
typescript@^4.5.5:
|
||||
version "4.5.5"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.5.5.tgz#d8c953832d28924a9e3d37c73d729c846c5896f3"
|
||||
integrity sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA==
|
||||
|
||||
uglify-js@^3.1.4:
|
||||
version "3.4.9"
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"apollo-server": "^2.18.1",
|
||||
"graphql": "^15.3.0",
|
||||
"graphql": "^16.3.0",
|
||||
"graphql-tools": "^4.0.7",
|
||||
"nexus": "^1.0.0",
|
||||
"ts-node-dev": "^1.0.0-pre.30"
|
||||
|
|
@ -15,6 +15,6 @@
|
|||
"jest": "^23.6.0",
|
||||
"prettier": "^1.19.1",
|
||||
"ts-jest": "^24.1.0",
|
||||
"typescript": "^3.9"
|
||||
"typescript": "^4.5.5"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2097,6 +2097,11 @@ graphql@^15.3.0:
|
|||
resolved "https://registry.yarnpkg.com/graphql/-/graphql-15.3.0.tgz#3ad2b0caab0d110e3be4a5a9b2aa281e362b5278"
|
||||
integrity sha512-GTCJtzJmkFLWRfFJuoo9RWWa/FfamUHgiFosxi/X1Ani4AVWbeyBenZTNX6dM+7WSbbFfTo/25eh0LLkwHMw2w==
|
||||
|
||||
graphql@^16.3.0:
|
||||
version "16.3.0"
|
||||
resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.3.0.tgz#a91e24d10babf9e60c706919bb182b53ccdffc05"
|
||||
integrity sha512-xm+ANmA16BzCT5pLjuXySbQVFwH3oJctUVdy81w1sV0vBU0KgDdBGtxQOUd5zqOBk/JayAFeG8Dlmeq74rjm/A==
|
||||
|
||||
growly@^1.2.0, growly@^1.3.0:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081"
|
||||
|
|
@ -5006,10 +5011,10 @@ type-is@~1.6.16:
|
|||
media-typer "0.3.0"
|
||||
mime-types "~2.1.18"
|
||||
|
||||
typescript@^3.9:
|
||||
version "3.9.7"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.7.tgz#98d600a5ebdc38f40cb277522f12dc800e9e25fa"
|
||||
integrity sha512-BLbiRkiBzAwsjut4x/dsibSTB6yWpwT5qWmC2OfuCg3GgVQCSgMs4vEctYPhsaGtd0AeuuHMkjZ2h2WG8MSzRw==
|
||||
typescript@^4.5.5:
|
||||
version "4.5.5"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.5.5.tgz#d8c953832d28924a9e3d37c73d729c846c5896f3"
|
||||
integrity sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA==
|
||||
|
||||
uglify-js@^3.1.4:
|
||||
version "3.4.9"
|
||||
|
|
|
|||
|
|
@ -8,11 +8,11 @@
|
|||
"dependencies": {
|
||||
"apollo-server": "^2.18.1",
|
||||
"fs-extra": "^7.0.1",
|
||||
"graphql": "^15.3.0",
|
||||
"graphql": "^16.3.0",
|
||||
"graphql-tools": "^4.0.7",
|
||||
"nexus": "^1.0.0",
|
||||
"ts-node-dev": "1.0.0-pre.31",
|
||||
"typescript": "^3.9"
|
||||
"typescript": "^4.5.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/fs-extra": "^5.0.4"
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { objectType, arg, list, nullable } from 'nexus'
|
||||
import { objectType, arg, list, nullable, core } from 'nexus'
|
||||
import ts from 'typescript'
|
||||
import { nodeType, functionLikeDeclaration, hasTypeParameters } from './mixins'
|
||||
import { filteredNodesList } from './utils'
|
||||
|
||||
|
|
@ -21,7 +22,7 @@ export const SourceFile = objectType({
|
|||
t.list.field('statements', {
|
||||
type: 'Node',
|
||||
args: nodeSkipSyntax,
|
||||
resolve: (root, args) => filteredNodesList(args, Array.from(root.statements)),
|
||||
resolve: (root, args) => filteredNodesList<ts.Statement>(args, Array.from(root.statements)),
|
||||
})
|
||||
},
|
||||
})
|
||||
|
|
@ -156,7 +157,7 @@ export const ClassDeclaration = objectType({
|
|||
t.list.field('members', {
|
||||
type: 'Node',
|
||||
args: nodeSkipSyntax,
|
||||
resolve: (root, args) => filteredNodesList(args, Array.from(root.members)),
|
||||
resolve: (root, args) => filteredNodesList<ts.ClassElement>(args, Array.from(root.members)),
|
||||
})
|
||||
},
|
||||
})
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { arg, interfaceType, list, nullable } from 'nexus'
|
||||
import { JSDoc, SyntaxKind } from 'typescript'
|
||||
import ts, { JSDoc, SyntaxKind } from 'typescript'
|
||||
import { allKnownNodes, syntaxKindFilter } from './utils'
|
||||
|
||||
const syntaxKindArgs = {
|
||||
|
|
@ -50,7 +50,7 @@ export const Node = interfaceType({
|
|||
if (!root.modifiers) {
|
||||
return null
|
||||
}
|
||||
return syntaxKindFilter(args, Array.from(root.modifiers))
|
||||
return syntaxKindFilter<ts.Modifier>(args, Array.from(root.modifiers))
|
||||
},
|
||||
})
|
||||
t.field('parent', { type: 'Node' })
|
||||
|
|
@ -78,7 +78,7 @@ export const JSDocInterface = interfaceType({
|
|||
resolve(root) {
|
||||
if ('jsDoc' in root) {
|
||||
// https://github.com/Microsoft/TypeScript/issues/19856
|
||||
return ((root as unknown) as { jsDoc: JSDoc[] }).jsDoc
|
||||
return (root as unknown as { jsDoc: JSDoc[] }).jsDoc
|
||||
}
|
||||
return null
|
||||
},
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ export const TupleTypeNode = objectType({
|
|||
name: 'TupleTypeNode',
|
||||
definition(t) {
|
||||
nodeType(t)
|
||||
t.list.field('elementTypes', { type: 'Node' })
|
||||
t.list.field('elements', { type: 'Node' })
|
||||
},
|
||||
})
|
||||
|
||||
|
|
|
|||
|
|
@ -1,72 +1,69 @@
|
|||
import { GraphQLSchema, isObjectType, GraphQLResolveInfo } from "graphql";
|
||||
import ts from "typescript";
|
||||
import { NexusGenArgTypes } from "../ts-ast-reader-typegen";
|
||||
import { GraphQLSchema, isObjectType, GraphQLResolveInfo } from 'graphql'
|
||||
import ts from 'typescript'
|
||||
import { NexusGenArgTypes } from '../ts-ast-reader-typegen'
|
||||
|
||||
export function convertTsEnum(toConvert: any) {
|
||||
const converted: { [key: string]: number } = {};
|
||||
const converted: { [key: string]: number } = {}
|
||||
Object.keys(toConvert).forEach((key) => {
|
||||
if (/^[_a-zA-Z][_a-zA-Z0-9]*$/.test(key)) {
|
||||
converted[key] = toConvert[key];
|
||||
converted[key] = toConvert[key]
|
||||
}
|
||||
});
|
||||
return converted;
|
||||
})
|
||||
return converted
|
||||
}
|
||||
|
||||
const knownNodesMap = new WeakMap<GraphQLSchema, Set<string>>();
|
||||
const knownNodesMap = new WeakMap<GraphQLSchema, Set<string>>()
|
||||
|
||||
export function allKnownNodes(schema: GraphQLSchema) {
|
||||
let knownNodes = knownNodesMap.get(schema);
|
||||
let knownNodes = knownNodesMap.get(schema)
|
||||
if (!knownNodes) {
|
||||
const fields = schema.getTypeMap();
|
||||
knownNodes = new Set();
|
||||
const fields = schema.getTypeMap()
|
||||
knownNodes = new Set()
|
||||
Object.keys(fields).forEach((key) => {
|
||||
const field = fields[key];
|
||||
if (
|
||||
isObjectType(field) &&
|
||||
Boolean(field.getInterfaces().find((i) => i.name === "Node"))
|
||||
) {
|
||||
knownNodes!.add(field.name);
|
||||
const field = fields[key]
|
||||
if (isObjectType(field) && Boolean(field.getInterfaces().find((i) => i.name === 'Node'))) {
|
||||
knownNodes!.add(field.name)
|
||||
}
|
||||
});
|
||||
knownNodesMap.set(schema, knownNodes);
|
||||
})
|
||||
knownNodesMap.set(schema, knownNodes)
|
||||
}
|
||||
return knownNodes!;
|
||||
return knownNodes!
|
||||
}
|
||||
|
||||
export const filteredNodesList = <T extends ts.Node>(
|
||||
args: NexusGenArgTypes["SourceFile"]["statements"],
|
||||
args: NexusGenArgTypes['SourceFile']['statements'],
|
||||
nodes: T[]
|
||||
) => {
|
||||
const { skip, only } = args;
|
||||
): T[] => {
|
||||
const { skip, only } = args
|
||||
if ((skip && skip.length) || (only && only.length)) {
|
||||
return nodes.filter((node: ts.Node) => {
|
||||
if (skip && skip.length > 0 && skip.indexOf(node.kind) !== -1) {
|
||||
return;
|
||||
return
|
||||
}
|
||||
if (only && only.length > 0 && only.indexOf(node.kind) === -1) {
|
||||
return;
|
||||
return
|
||||
}
|
||||
return node;
|
||||
});
|
||||
return node
|
||||
})
|
||||
}
|
||||
return nodes;
|
||||
};
|
||||
return nodes
|
||||
}
|
||||
|
||||
export const syntaxKindFilter = <T extends { kind: ts.SyntaxKind }>(
|
||||
args: NexusGenArgTypes["Node"]["modifiers"],
|
||||
args: NexusGenArgTypes['Node']['modifiers'],
|
||||
items: T[]
|
||||
) => {
|
||||
const { skip, only } = args;
|
||||
const { skip, only } = args
|
||||
if ((only && only.length) || (skip && skip.length)) {
|
||||
return items.filter((item) => {
|
||||
if (only && only.length && only.indexOf(item.kind) === -1) {
|
||||
return null;
|
||||
return null
|
||||
}
|
||||
if (skip && skip.length && skip.indexOf(item.kind) !== -1) {
|
||||
return null;
|
||||
return null
|
||||
}
|
||||
return item;
|
||||
});
|
||||
return item
|
||||
})
|
||||
}
|
||||
return items;
|
||||
};
|
||||
return items
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1113,6 +1113,11 @@ graphql@^15.3.0:
|
|||
resolved "https://registry.yarnpkg.com/graphql/-/graphql-15.3.0.tgz#3ad2b0caab0d110e3be4a5a9b2aa281e362b5278"
|
||||
integrity sha512-GTCJtzJmkFLWRfFJuoo9RWWa/FfamUHgiFosxi/X1Ani4AVWbeyBenZTNX6dM+7WSbbFfTo/25eh0LLkwHMw2w==
|
||||
|
||||
graphql@^16.3.0:
|
||||
version "16.3.0"
|
||||
resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.3.0.tgz#a91e24d10babf9e60c706919bb182b53ccdffc05"
|
||||
integrity sha512-xm+ANmA16BzCT5pLjuXySbQVFwH3oJctUVdy81w1sV0vBU0KgDdBGtxQOUd5zqOBk/JayAFeG8Dlmeq74rjm/A==
|
||||
|
||||
growly@^1.2.0:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081"
|
||||
|
|
@ -2164,10 +2169,10 @@ type-is@~1.6.16:
|
|||
media-typer "0.3.0"
|
||||
mime-types "~2.1.18"
|
||||
|
||||
typescript@^3.9:
|
||||
version "3.9.7"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.7.tgz#98d600a5ebdc38f40cb277522f12dc800e9e25fa"
|
||||
integrity sha512-BLbiRkiBzAwsjut4x/dsibSTB6yWpwT5qWmC2OfuCg3GgVQCSgMs4vEctYPhsaGtd0AeuuHMkjZ2h2WG8MSzRw==
|
||||
typescript@^4.5.5:
|
||||
version "4.5.5"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.5.5.tgz#d8c953832d28924a9e3d37c73d729c846c5896f3"
|
||||
integrity sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA==
|
||||
|
||||
universalify@^0.1.0:
|
||||
version "0.1.2"
|
||||
|
|
|
|||
|
|
@ -20,13 +20,13 @@
|
|||
"@prisma/client": "2.14.0",
|
||||
"apollo-server-express": "^2.19.1",
|
||||
"express": "^4.17.1",
|
||||
"graphql": "^15.3.0",
|
||||
"graphql": "^16.3.0",
|
||||
"nexus": "^1.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@prisma/cli": "^2.14.0",
|
||||
"prettier": "2.2.1",
|
||||
"ts-node-dev": "^1.0.0-pre.62",
|
||||
"typescript": "^4.0.2"
|
||||
"typescript": "^4.5.5"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1015,6 +1015,11 @@ graphql@^15.3.0:
|
|||
resolved "https://registry.yarnpkg.com/graphql/-/graphql-15.4.0.tgz#e459dea1150da5a106486ba7276518b5295a4347"
|
||||
integrity sha512-EB3zgGchcabbsU9cFe1j+yxdzKQKAbGUWRb13DsrsMN1yyfmmIq+2+L5MqVWcDCE4V89R5AyUOi7sMOGxdsYtA==
|
||||
|
||||
graphql@^16.3.0:
|
||||
version "16.3.0"
|
||||
resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.3.0.tgz#a91e24d10babf9e60c706919bb182b53ccdffc05"
|
||||
integrity sha512-xm+ANmA16BzCT5pLjuXySbQVFwH3oJctUVdy81w1sV0vBU0KgDdBGtxQOUd5zqOBk/JayAFeG8Dlmeq74rjm/A==
|
||||
|
||||
has-symbols@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8"
|
||||
|
|
@ -1814,10 +1819,10 @@ type-is@^1.6.16, type-is@~1.6.17, type-is@~1.6.18:
|
|||
media-typer "0.3.0"
|
||||
mime-types "~2.1.24"
|
||||
|
||||
typescript@^4.0.2:
|
||||
version "4.1.3"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.1.3.tgz#519d582bd94cba0cf8934c7d8e8467e473f53bb7"
|
||||
integrity sha512-B3ZIOf1IKeH2ixgHhj6la6xdwR9QrLC5d1VKeCSY4tvkqhF2eqd9O7txNlS0PO3GrBAFIdr3L1ndNwteUbZLYg==
|
||||
typescript@^4.5.5:
|
||||
version "4.5.5"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.5.5.tgz#d8c953832d28924a9e3d37c73d729c846c5896f3"
|
||||
integrity sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA==
|
||||
|
||||
unpipe@1.0.0, unpipe@~1.0.0:
|
||||
version "1.0.0"
|
||||
|
|
|
|||
|
|
@ -13,13 +13,13 @@
|
|||
"trailingComma": "all"
|
||||
},
|
||||
"dependencies": {
|
||||
"graphql": "^15.3.0",
|
||||
"graphql": "^16.3.0",
|
||||
"nexus": "^1.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@now/node": "^1.0.1",
|
||||
"@types/node": "^12.11.1",
|
||||
"ts-node": "^8.4.1",
|
||||
"typescript": "^3.9"
|
||||
"typescript": "^4.5.5"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,10 +29,10 @@ diff@^4.0.1:
|
|||
resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.1.tgz#0c667cb467ebbb5cea7f14f135cc2dba7780a8ff"
|
||||
integrity sha512-s2+XdvhPCOF01LRQBC8hf4vhbVmI2CGS5aZnxLJlT5FtdhPCDFq80q++zK2KlrVorVDdL5BOGZ/VfLrVtYNF+Q==
|
||||
|
||||
graphql@^15.3.0:
|
||||
version "15.3.0"
|
||||
resolved "https://registry.yarnpkg.com/graphql/-/graphql-15.3.0.tgz#3ad2b0caab0d110e3be4a5a9b2aa281e362b5278"
|
||||
integrity sha512-GTCJtzJmkFLWRfFJuoo9RWWa/FfamUHgiFosxi/X1Ani4AVWbeyBenZTNX6dM+7WSbbFfTo/25eh0LLkwHMw2w==
|
||||
graphql@^16.3.0:
|
||||
version "16.3.0"
|
||||
resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.3.0.tgz#a91e24d10babf9e60c706919bb182b53ccdffc05"
|
||||
integrity sha512-xm+ANmA16BzCT5pLjuXySbQVFwH3oJctUVdy81w1sV0vBU0KgDdBGtxQOUd5zqOBk/JayAFeG8Dlmeq74rjm/A==
|
||||
|
||||
iterall@^1.3.0:
|
||||
version "1.3.0"
|
||||
|
|
@ -81,10 +81,10 @@ tslib@^2.0.3:
|
|||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.0.3.tgz#8e0741ac45fc0c226e58a17bfc3e64b9bc6ca61c"
|
||||
integrity sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ==
|
||||
|
||||
typescript@^3.9:
|
||||
version "3.9.7"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.7.tgz#98d600a5ebdc38f40cb277522f12dc800e9e25fa"
|
||||
integrity sha512-BLbiRkiBzAwsjut4x/dsibSTB6yWpwT5qWmC2OfuCg3GgVQCSgMs4vEctYPhsaGtd0AeuuHMkjZ2h2WG8MSzRw==
|
||||
typescript@^4.5.5:
|
||||
version "4.5.5"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.5.5.tgz#d8c953832d28924a9e3d37c73d729c846c5896f3"
|
||||
integrity sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA==
|
||||
|
||||
yn@^3.0.0:
|
||||
version "3.1.1"
|
||||
|
|
|
|||
28
package.json
28
package.json
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "nexus",
|
||||
"version": "0.0.0-dripip",
|
||||
"version": "1.3.0",
|
||||
"description": "Scalable, strongly typed GraphQL schema development",
|
||||
"keywords": [
|
||||
"graphql",
|
||||
|
|
@ -46,7 +46,6 @@
|
|||
"release:pr": "dripip pr",
|
||||
"release:preview": "dripip preview",
|
||||
"release:stable": "dripip stable",
|
||||
"pretest": "yarn patch-package",
|
||||
"test": "yarn test:types && jest --testTimeout 10000",
|
||||
"test:ci": "yarn test:types && jest --maxWorkers 2 --coverage --testTimeout 10000",
|
||||
"test:debug": "node --inspect-brk $(yarn bin)/jest -i --watch",
|
||||
|
|
@ -62,12 +61,10 @@
|
|||
},
|
||||
"lint-staged": {
|
||||
"*.{ts,js,graphql,json,css,md}": [
|
||||
"prettier --write",
|
||||
"git add"
|
||||
"prettier --write"
|
||||
],
|
||||
"*package.json": [
|
||||
"sort-package-json",
|
||||
"git add"
|
||||
"sort-package-json"
|
||||
]
|
||||
},
|
||||
"dependencies": {
|
||||
|
|
@ -82,29 +79,28 @@
|
|||
"@types/prettier": "^1.18.3",
|
||||
"@typescript-eslint/eslint-plugin": "2.7.0",
|
||||
"dripip": "^0.10.0",
|
||||
"esbuild": "^0.14.48",
|
||||
"eslint": "^6.6.0",
|
||||
"get-port": "^5.1.1",
|
||||
"graphql": "^15.3.0",
|
||||
"graphql-relay": "^0.6.0",
|
||||
"graphql-scalars": "^1.2.6",
|
||||
"graphql": "^16.3.0",
|
||||
"graphql-relay": "^0.10.0",
|
||||
"graphql-scalars": "^1.14.1",
|
||||
"gulp": "4.0.2",
|
||||
"husky": "^1.1.2",
|
||||
"jest": "^26.6.3",
|
||||
"jest-watch-typeahead": "^0.6.1",
|
||||
"lint-staged": "^7.3.0",
|
||||
"patch-package": "6.2.2",
|
||||
"prettier": "^2.3.1",
|
||||
"prettier-plugin-jsdoc": "^0.3.23",
|
||||
"lint-staged": "^12.4.1",
|
||||
"prettier": "^2.5.1",
|
||||
"sort-package-json": "^1.22.1",
|
||||
"ts-jest": "^26.4.4",
|
||||
"ts-morph": "^8.2.0",
|
||||
"ts-morph": "^13.0.3",
|
||||
"ts-node": "^9.0.0",
|
||||
"tsd": "^0.13.1",
|
||||
"tslint": "^5.11.0",
|
||||
"tslint-config-prettier": "^1.15.0",
|
||||
"typescript": "^4.1.2"
|
||||
"typescript": "^4.5.5"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"graphql": "^14.5.8 || 15.x"
|
||||
"graphql": "15.x || 16.x"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,13 +0,0 @@
|
|||
diff --git a/node_modules/prettier-plugin-jsdoc/lib/parser.js b/node_modules/prettier-plugin-jsdoc/lib/parser.js
|
||||
index 85b9e5d..3b98730 100644
|
||||
--- a/node_modules/prettier-plugin-jsdoc/lib/parser.js
|
||||
+++ b/node_modules/prettier-plugin-jsdoc/lib/parser.js
|
||||
@@ -12,7 +12,7 @@ const stringify_1 = require("./stringify");
|
||||
/** @link https://prettier.io/docs/en/api.html#custom-parser-api} */
|
||||
exports.getParser = (parser) => function jsdocParser(text, parsers, options) {
|
||||
const ast = parser(text, parsers, options);
|
||||
- if (!options.jsdocParser) {
|
||||
+ if (!options || !options.jsdocParser) {
|
||||
return ast;
|
||||
}
|
||||
/**
|
||||
762
src/builder.ts
762
src/builder.ts
File diff suppressed because it is too large
Load Diff
|
|
@ -3,6 +3,7 @@
|
|||
export * from './builder'
|
||||
export * from './makeSchema'
|
||||
export * from './definitions/args'
|
||||
export * from './definitions/directive'
|
||||
export * from './definitions/decorateType'
|
||||
export * from './definitions/definitionBlocks'
|
||||
export * from './definitions/enumType'
|
||||
|
|
@ -28,6 +29,7 @@ export * from './definitions/_types'
|
|||
export * from './dynamicMethod'
|
||||
export * from './plugin'
|
||||
export * from './plugins'
|
||||
export * from './rebuildType'
|
||||
export * from './sdlConverter'
|
||||
export * from './typegenAutoConfig'
|
||||
export * from './typegenFormatPrettier'
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import type {
|
|||
GraphQLSchema,
|
||||
GraphQLUnionType,
|
||||
} from 'graphql'
|
||||
import type { NexusDirectiveConfig } from '../core'
|
||||
import type {
|
||||
NexusFieldExtension,
|
||||
NexusInputObjectTypeExtension,
|
||||
|
|
@ -25,7 +26,8 @@ import type { RequiredDeeply } from '../typeHelpersInternal'
|
|||
|
||||
export type { AbstractTypes }
|
||||
|
||||
export type Maybe<T> = T | null
|
||||
/** Conveniently represents flow's "Maybe" type https://flow.org/en/docs/types/maybe/ */
|
||||
export type Maybe<T> = null | undefined | T
|
||||
|
||||
export type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>
|
||||
|
||||
|
|
@ -52,6 +54,8 @@ export enum NexusTypes {
|
|||
PrintedGenTypingImport = 'PrintedGenTypingImport',
|
||||
Scalar = 'Scalar',
|
||||
Union = 'Union',
|
||||
Directive = 'Directive',
|
||||
DirectiveUse = 'DirectiveUse',
|
||||
}
|
||||
|
||||
export interface DeprecationInfo {
|
||||
|
|
@ -154,8 +158,13 @@ export type NexusGraphQLInterfaceTypeConfig = WithExt<
|
|||
NexusInterfaceTypeExtension
|
||||
> & { interfaces: () => GraphQLInterfaceType[] }
|
||||
|
||||
export type NexusGraphQLSchema = Omit<GraphQLSchema, 'extensions'> & {
|
||||
extensions: { nexus: NexusSchemaExtension }
|
||||
export type NexusGraphQLDirectiveConfig = WithExt<NexusDirectiveConfig, NexusInputObjectTypeExtension>
|
||||
|
||||
export interface NexusGraphQLSchema extends GraphQLSchema {
|
||||
extensions: {
|
||||
nexus: NexusSchemaExtension
|
||||
[attributeName: string]: unknown
|
||||
}
|
||||
}
|
||||
|
||||
export type NexusFeaturesInput = {
|
||||
|
|
@ -175,8 +184,8 @@ export type NexusFeaturesInput = {
|
|||
* types guide](https://nxs.li/guides/abstract-types).
|
||||
*
|
||||
* If you plan on enabling multiple strategies and you've never done so then please [read the guide about
|
||||
* using multiple strategies](https://nxs.li/guides/abstract-types/using-multiple-strategies) as there are a
|
||||
* few quirks to be aware of.
|
||||
* using multiple strategies](https://nxs.li/guides/abstract-types/using-multiple-strategies) as there are
|
||||
* a few quirks to be aware of.
|
||||
*
|
||||
* @default {resolveType: true,
|
||||
* __typename: false
|
||||
|
|
@ -203,16 +212,16 @@ export type NexusFeaturesInput = {
|
|||
* the [Discriminant Model Field Strategy](https://nxs.li/guides/abstract-types/discriminant-model-field-strategy).
|
||||
*
|
||||
* Warning :: When this strategy is enabled in conjunction with other strategies the
|
||||
* "abstractTypeRuntimeChecks" feature will automatically be disabled. This is because it is not practical
|
||||
* at runtime to find out if resolvers will return objects that include the "__typename" field. This
|
||||
* trade-off can be acceptable since the runtime checks are a redundant safety measure over the static
|
||||
* typing. So as long as you are not ignoring static errors related to Nexus' abstract type type checks
|
||||
* then you then you should still have a safe implementation.
|
||||
* "abstractTypeRuntimeChecks" feature will automatically be disabled. This is because it is not
|
||||
* practical at runtime to find out if resolvers will return objects that include the "__typename" field.
|
||||
* This trade-off can be acceptable since the runtime checks are a redundant safety measure over the
|
||||
* static typing. So as long as you are not ignoring static errors related to Nexus' abstract type type
|
||||
* checks then you then you should still have a safe implementation.
|
||||
*
|
||||
* Furthermore another effect is that statically the other strategies will not appear to be *required*,
|
||||
* but instead *optional*, while only this one will appear required. However, upon implementing any of the
|
||||
* other strategies, this one will not longer be required. This quirk is explained in the guide section
|
||||
* about [using multiple strategies](https://nxs.li/guides/abstract-types/using-multiple-strategies).
|
||||
* but instead *optional*, while only this one will appear required. However, upon implementing any of
|
||||
* the other strategies, this one will not longer be required. This quirk is explained in the guide
|
||||
* section about [using multiple strategies](https://nxs.li/guides/abstract-types/using-multiple-strategies).
|
||||
*/
|
||||
__typename?: boolean
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
import type { GraphQLScalarTypeConfig } from 'graphql'
|
||||
import type { AllInputTypes, GetGen2 } from '../typegenTypeHelpers'
|
||||
import type { Directives } from './directive'
|
||||
import type { AllNexusArgsDefs, AllNexusInputTypeDefs } from './wrapping'
|
||||
import { NexusTypes, withNexusSymbol } from './_types'
|
||||
import { Maybe, NexusTypes, withNexusSymbol } from './_types'
|
||||
|
||||
export type ArgsRecord = Record<string, AllNexusArgsDefs>
|
||||
|
||||
|
|
@ -39,7 +40,7 @@ export type CommonArgConfig = {
|
|||
* // ): [Int]
|
||||
* // }
|
||||
*/
|
||||
description?: string
|
||||
description?: Maybe<string>
|
||||
|
||||
/**
|
||||
* Data that will be added to the arg-level [extensions field on the graphql-js type def
|
||||
|
|
@ -47,6 +48,13 @@ export type CommonArgConfig = {
|
|||
* graphql-js based tools which rely on looking for special data here.
|
||||
*/
|
||||
extensions?: GraphQLScalarTypeConfig<any, any>['extensions']
|
||||
/**
|
||||
* A list of directives / directive uses (with args) for the arg definition
|
||||
*
|
||||
* @example
|
||||
* directives: [addDirective('ExampleDirective', { arg: true })]
|
||||
*/
|
||||
directives?: Directives
|
||||
} & NexusGenPluginArgConfig
|
||||
|
||||
export interface ScalarArgConfig<T> extends CommonArgConfig {
|
||||
|
|
@ -86,10 +94,10 @@ export interface NexusArgConfig<T extends string> extends NexusAsArgConfig<T> {
|
|||
*
|
||||
* Types may be expressed in one of three ways:
|
||||
*
|
||||
* 1. As string literals matching the name of a builtin scalar.
|
||||
* 2. As string literals matching the name of another type. Thanks to [Nexus' reflection
|
||||
* system](https://nxs.li/guides/reflection) this is typesafe and autocompletable.
|
||||
* 3. As references to other enums or input object type definitions.
|
||||
* 1. As string literals matching the name of a builtin scalar. 2. As string literals matching the name of
|
||||
* another type. Thanks to [Nexus' reflection
|
||||
* system](https://nxs.li/guides/reflection) this is typesafe and autocompletable. 3. As references to other
|
||||
* enums or input object type definitions.
|
||||
*
|
||||
* Type modifier helpers like list() may also be used and in turn accept one of the three methods listed above.
|
||||
*
|
||||
|
|
@ -157,7 +165,7 @@ withNexusSymbol(NexusArgDef, NexusTypes.Arg)
|
|||
* })
|
||||
*
|
||||
* @param config Configuration for the argument like its type and description. See jsdoc on each config field
|
||||
* for details.
|
||||
* for details.
|
||||
*/
|
||||
export function arg<T extends string>(config: NexusArgConfig<T>) {
|
||||
if (!config.type) {
|
||||
|
|
|
|||
|
|
@ -6,17 +6,13 @@ export interface TypeExtensionConfig {
|
|||
sourceType?: SourceTypingDef
|
||||
}
|
||||
|
||||
export type NexusTypeExtensions = {
|
||||
nexus: TypeExtensionConfig
|
||||
}
|
||||
|
||||
export function decorateType<T extends GraphQLNamedType>(type: T, config: TypeExtensionConfig): T {
|
||||
type.extensions = {
|
||||
...type.extensions,
|
||||
nexus: {
|
||||
asNexusMethod: config.asNexusMethod,
|
||||
sourceType: config.sourceType,
|
||||
...Object(type.extensions?.nexus),
|
||||
...config,
|
||||
},
|
||||
}
|
||||
return type as any
|
||||
return type
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,20 +9,19 @@ import type {
|
|||
NeedsResolver,
|
||||
} from '../typegenTypeHelpers'
|
||||
import type { ArgsRecord } from './args'
|
||||
import type { Directives } from './directive'
|
||||
import type { NexusMetaType } from './nexusMeta'
|
||||
import type { AllNexusInputTypeDefs, AllNexusOutputTypeDefs, NexusWrapKind } from './wrapping'
|
||||
import type { BaseScalars } from './_types'
|
||||
import type { BaseScalars, Maybe } from './_types'
|
||||
|
||||
export interface CommonFieldConfig {
|
||||
//todo
|
||||
/** The description to annotate the GraphQL SDL */
|
||||
description?: string
|
||||
//todo
|
||||
description?: Maybe<string>
|
||||
/**
|
||||
* Info about a field deprecation. Formatted as a string and provided with the deprecated directive on
|
||||
* field/enum types and as a comment on input fields.
|
||||
*/
|
||||
deprecation?: string // | DeprecationInfo;
|
||||
deprecation?: Maybe<string> // | DeprecationInfo;
|
||||
}
|
||||
|
||||
export type CommonOutputFieldConfig<TypeName extends string, FieldName extends string> = CommonFieldConfig & {
|
||||
|
|
@ -75,7 +74,7 @@ export type CommonOutputFieldConfig<TypeName extends string, FieldName extends s
|
|||
* },
|
||||
* })
|
||||
*/
|
||||
args?: ArgsRecord
|
||||
args?: Maybe<ArgsRecord>
|
||||
/**
|
||||
* Data that will be added to the field-level [extensions field on the graphql-js type def
|
||||
* instances](https://github.com/graphql/graphql-js/issues/1527) resulting from makeSchema. Useful for some
|
||||
|
|
@ -105,8 +104,43 @@ export type CommonOutputFieldConfig<TypeName extends string, FieldName extends s
|
|||
* })
|
||||
*/
|
||||
extensions?: GraphQLFieldConfig<any, any>['extensions']
|
||||
/**
|
||||
* A list of directives / directive uses (with args) for the output field definition
|
||||
*
|
||||
* @example
|
||||
* directives: [addDirective('ExampleDirective', { arg: true })]
|
||||
*/
|
||||
directives?: Directives
|
||||
/**
|
||||
* Defines a typing for the field, overriding the default behavior to default to the scalar,
|
||||
* and omit the field if a resolver exists. Most useful in situations where we have a resolver
|
||||
* but we still want the field defined on the output type.
|
||||
*
|
||||
* @example
|
||||
* sourceType: 'string | number'
|
||||
*/
|
||||
sourceType?: string | FieldSourceType | NamedFieldSourceType[]
|
||||
} & NexusGenPluginFieldConfig<TypeName, FieldName>
|
||||
|
||||
export interface FieldSourceType {
|
||||
/**
|
||||
* String representing the TypeScript type output as the value
|
||||
*/
|
||||
type: string
|
||||
/**
|
||||
* If true, marks the field as optional `?:`
|
||||
* @default false
|
||||
*/
|
||||
optional?: boolean
|
||||
}
|
||||
|
||||
export interface NamedFieldSourceType extends FieldSourceType {
|
||||
/**
|
||||
* Property name in the output TypeScript field
|
||||
*/
|
||||
name: string
|
||||
}
|
||||
|
||||
export type CommonInputFieldConfig<TypeName extends string, FieldName extends string> = CommonFieldConfig & {
|
||||
/** The default value for the field, if any */
|
||||
default?: GetGen3<'inputTypes', TypeName, FieldName>
|
||||
|
|
@ -116,7 +150,16 @@ export type CommonInputFieldConfig<TypeName extends string, FieldName extends st
|
|||
* graphql-js based tools which rely on looking for special data here.
|
||||
*/
|
||||
extensions?: GraphQLInputFieldConfig['extensions']
|
||||
} & NexusGenPluginFieldConfig<TypeName, FieldName>
|
||||
/**
|
||||
* A list of directives / directive uses (with args) for the input field definition
|
||||
*
|
||||
* @example
|
||||
* directives: [addDirective('ExampleDirective', { arg: true })]
|
||||
*/
|
||||
directives?: Directives
|
||||
} & NexusGenPluginFieldConfig<TypeName, FieldName> &
|
||||
NexusGenPluginInputFieldConfig<TypeName, FieldName>
|
||||
|
||||
export interface OutputScalarConfig<TypeName extends string, FieldName extends string>
|
||||
extends CommonOutputFieldConfig<TypeName, FieldName> {
|
||||
/**
|
||||
|
|
@ -127,9 +170,7 @@ export interface OutputScalarConfig<TypeName extends string, FieldName extends s
|
|||
* Every field has a resolver and they are the basis for resolving queries at runtime. You do not need to
|
||||
* explicitly implement every resolver however. If the [source typing](https://nxs.li/guides/backing-types) includes:
|
||||
*
|
||||
* 1. A field whose name matches this one
|
||||
* 2. And whose type is compatible
|
||||
* 3. And is a scalar
|
||||
* 1. A field whose name matches this one 2. And whose type is compatible 3. And is a scalar
|
||||
*
|
||||
* ...then the default resolver will be available, whose behaviour is to simply return that field from the
|
||||
* received source type.
|
||||
|
|
@ -147,29 +188,29 @@ export interface OutputScalarConfig<TypeName extends string, FieldName extends s
|
|||
* })
|
||||
*
|
||||
* @param source The [source data](https://nxs.li/guides/source-types) for the GraphQL object that this
|
||||
* field belongs to, unless this is a root field (any field on a [root operation
|
||||
* type](https://spec.graphql.org/June2018/#sec-Root-Operation-Types): Query, Mutation, Subscription), in
|
||||
* which case there is no source data and this will be undefined.
|
||||
* field belongs to, unless this is a root field (any field on a [root operation
|
||||
* type](https://spec.graphql.org/June2018/#sec-Root-Operation-Types): Query, Mutation, Subscription),
|
||||
* in which case there is no source data and this will be undefined.
|
||||
* @param args If you have defined arguments on this field then this parameter will contain any arguments
|
||||
* passed by the client. If you specified default values for any arguments and the client did not
|
||||
* explicitly pass *any* value (including null) for those arguments then you will see the defaults here.
|
||||
* passed by the client. If you specified default values for any arguments and the client did not
|
||||
* explicitly pass *any* value (including null) for those arguments then you will see the defaults here.
|
||||
*
|
||||
* Note that thanks to [Nexus' reflection system](https://nxs.li/guides/reflection) this parameter's type
|
||||
* will always be type safe.
|
||||
* Note that thanks to [Nexus' reflection system](https://nxs.li/guides/reflection) this parameter's type
|
||||
* will always be type safe.
|
||||
* @param context The context data for this request.
|
||||
*
|
||||
* The context data is typically a singleton scoped to the lifecycle of the request. This means created at
|
||||
* the beginning of a request and then passed to all the resolvers that execute while resolving the
|
||||
* request. It is often used to store information like the current user making the request. Nexus is not
|
||||
* responsible for this however. That is typically something you'll do with e.g.
|
||||
* [Mercurius](https://mercurius.dev) or [Apollo
|
||||
* Server](https://apollographql.com/docs/apollo-server/api/apollo-server).
|
||||
* The context data is typically a singleton scoped to the lifecycle of the request. This means created at
|
||||
* the beginning of a request and then passed to all the resolvers that execute while resolving the
|
||||
* request. It is often used to store information like the current user making the request. Nexus is
|
||||
* not responsible for this however. That is typically something you'll do with e.g.
|
||||
* [Mercurius](https://mercurius.dev) or [Apollo
|
||||
* Server](https://apollographql.com/docs/apollo-server/api/apollo-server).
|
||||
*
|
||||
* Note that the type here will be whatever you have specified for "contextType" in your makeSchema configuration.
|
||||
* Note that the type here will be whatever you have specified for "contextType" in your makeSchema configuration.
|
||||
* @param info The GraphQL resolve info.
|
||||
*
|
||||
* This is an advanced parameter seldom used. It includes things like the AST of the [GraphQL
|
||||
* document](https://spec.graphql.org/June2018/#sec-Language.Document) sent by the client.
|
||||
* This is an advanced parameter seldom used. It includes things like the AST of the [GraphQL
|
||||
* document](https://spec.graphql.org/June2018/#sec-Language.Document) sent by the client.
|
||||
*/
|
||||
resolve?: FieldResolver<TypeName, FieldName>
|
||||
}
|
||||
|
|
@ -487,17 +528,15 @@ export class OutputDefinitionBlock<TypeName extends string> {
|
|||
*
|
||||
* @param name The name of this field. Must conform to the regex pattern: [_A-Za-z][_0-9A-Za-z]*
|
||||
* @param config The configuration for things like the field's type, its description, its arguments, its
|
||||
* resolver, and more. See jsdoc on each field within for details.
|
||||
* resolver, and more. See jsdoc on each field within for details.
|
||||
*
|
||||
* This parameter is optional if no resolver is required. No resolver is required if the [source
|
||||
* typing](https://nxs.li/guides/backing-types):
|
||||
* This parameter is optional if no resolver is required. No resolver is required if the [source
|
||||
* typing](https://nxs.li/guides/backing-types):
|
||||
*
|
||||
* 1. Has a field whose name matches this one
|
||||
* 2. And whose type is compatible
|
||||
* 3. And is a scalar
|
||||
* 1. Has a field whose name matches this one 2. And whose type is compatible 3. And is a scalar
|
||||
*
|
||||
* ...in which case the default resolver will be available whose behaviour is to simply return that field
|
||||
* from the received source type.
|
||||
* ...in which case the default resolver will be available whose behaviour is to simply return that field
|
||||
* from the received source type.
|
||||
*/
|
||||
boolean<FieldName extends string>(name: FieldName, ...config: ScalarOutSpread<TypeName, FieldName>) {
|
||||
this.addScalarField(name, 'Boolean', config)
|
||||
|
|
@ -527,17 +566,15 @@ export class OutputDefinitionBlock<TypeName extends string> {
|
|||
*
|
||||
* @param name The name of this field. Must conform to the regex pattern: [_A-Za-z][_0-9A-Za-z]*
|
||||
* @param config The configuration for things like the field's type, its description, its arguments, its
|
||||
* resolver, and more. See jsdoc on each field within for details.
|
||||
* resolver, and more. See jsdoc on each field within for details.
|
||||
*
|
||||
* This parameter is optional if no resolver is required. No resolver is required if the [source
|
||||
* typing](https://nxs.li/guides/backing-types):
|
||||
* This parameter is optional if no resolver is required. No resolver is required if the [source
|
||||
* typing](https://nxs.li/guides/backing-types):
|
||||
*
|
||||
* 1. Has a field whose name matches this one
|
||||
* 2. And whose type is compatible
|
||||
* 3. And is a scalar
|
||||
* 1. Has a field whose name matches this one 2. And whose type is compatible 3. And is a scalar
|
||||
*
|
||||
* ...in which case the default resolver will be available whose behaviour is to simply return that field
|
||||
* from the received source type.
|
||||
* ...in which case the default resolver will be available whose behaviour is to simply return that field
|
||||
* from the received source type.
|
||||
*/
|
||||
string<FieldName extends string>(name: FieldName, ...config: ScalarOutSpread<TypeName, FieldName>) {
|
||||
this.addScalarField(name, 'String', config)
|
||||
|
|
@ -568,17 +605,15 @@ export class OutputDefinitionBlock<TypeName extends string> {
|
|||
*
|
||||
* @param name The name of this field. Must conform to the regex pattern: [_A-Za-z][_0-9A-Za-z]*
|
||||
* @param config The configuration for things like the field's type, its description, its arguments, its
|
||||
* resolver, and more. See jsdoc on each field within for details.
|
||||
* resolver, and more. See jsdoc on each field within for details.
|
||||
*
|
||||
* This parameter is optional if no resolver is required. No resolver is required if the [source
|
||||
* typing](https://nxs.li/guides/backing-types):
|
||||
* This parameter is optional if no resolver is required. No resolver is required if the [source
|
||||
* typing](https://nxs.li/guides/backing-types):
|
||||
*
|
||||
* 1. Has a field whose name matches this one
|
||||
* 2. And whose type is compatible
|
||||
* 3. And is a scalar
|
||||
* 1. Has a field whose name matches this one 2. And whose type is compatible 3. And is a scalar
|
||||
*
|
||||
* ...in which case the default resolver will be available whose behaviour is to simply return that field
|
||||
* from the received source type.
|
||||
* ...in which case the default resolver will be available whose behaviour is to simply return that field
|
||||
* from the received source type.
|
||||
*/
|
||||
id<FieldName extends string>(name: FieldName, ...config: ScalarOutSpread<TypeName, FieldName>) {
|
||||
this.addScalarField(name, 'ID', config)
|
||||
|
|
@ -607,17 +642,15 @@ export class OutputDefinitionBlock<TypeName extends string> {
|
|||
*
|
||||
* @param name The name of this field. Must conform to the regex pattern: [_A-Za-z][_0-9A-Za-z]*
|
||||
* @param config The configuration for things like the field's type, its description, its arguments, its
|
||||
* resolver, and more. See jsdoc on each field within for details.
|
||||
* resolver, and more. See jsdoc on each field within for details.
|
||||
*
|
||||
* This parameter is optional if no resolver is required. No resolver is required if the [source
|
||||
* typing](https://nxs.li/guides/backing-types):
|
||||
* This parameter is optional if no resolver is required. No resolver is required if the [source
|
||||
* typing](https://nxs.li/guides/backing-types):
|
||||
*
|
||||
* 1. Has a field whose name matches this one
|
||||
* 2. And whose type is compatible
|
||||
* 3. And is a scalar
|
||||
* 1. Has a field whose name matches this one 2. And whose type is compatible 3. And is a scalar
|
||||
*
|
||||
* ...in which case the default resolver will be available whose behaviour is to simply return that field
|
||||
* from the received source type.
|
||||
* ...in which case the default resolver will be available whose behaviour is to simply return that field
|
||||
* from the received source type.
|
||||
*/
|
||||
int<FieldName extends string>(name: FieldName, ...config: ScalarOutSpread<TypeName, FieldName>) {
|
||||
this.addScalarField(name, 'Int', config)
|
||||
|
|
@ -629,8 +662,9 @@ export class OutputDefinitionBlock<TypeName extends string> {
|
|||
* Define a field whose type is Float.
|
||||
*
|
||||
* Float types are [scalars](https://spec.graphql.org/June2018/#sec-Scalars) representing signed
|
||||
* double‐precision fractional values as specified by IEEE 754. They are represented in JavaScript using the
|
||||
* [number primitive type](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number).
|
||||
* double‐precision fractional values as specified by IEEE 754. They are represented in JavaScript using
|
||||
* the [number primitive
|
||||
* type](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number).
|
||||
*
|
||||
* This is a shorthand, equivalent to:
|
||||
*
|
||||
|
|
@ -646,17 +680,15 @@ export class OutputDefinitionBlock<TypeName extends string> {
|
|||
*
|
||||
* @param name The name of this field. Must conform to the regex pattern: [_A-Za-z][_0-9A-Za-z]*
|
||||
* @param config The configuration for things like the field's type, its description, its arguments, its
|
||||
* resolver, and more. See jsdoc on each field within for details.
|
||||
* resolver, and more. See jsdoc on each field within for details.
|
||||
*
|
||||
* This parameter is optional if no resolver is required. No resolver is required if the [source
|
||||
* typing](https://nxs.li/guides/backing-types):
|
||||
* This parameter is optional if no resolver is required. No resolver is required if the [source
|
||||
* typing](https://nxs.li/guides/backing-types):
|
||||
*
|
||||
* 1. Has a field whose name matches this one
|
||||
* 2. And whose type is compatible
|
||||
* 3. And is a scalar
|
||||
* 1. Has a field whose name matches this one 2. And whose type is compatible 3. And is a scalar
|
||||
*
|
||||
* ...in which case the default resolver will be available whose behaviour is to simply return that field
|
||||
* from the received source type.
|
||||
* ...in which case the default resolver will be available whose behaviour is to simply return that field
|
||||
* from the received source type.
|
||||
*/
|
||||
float<FieldName extends string>(name: FieldName, ...config: ScalarOutSpread<TypeName, FieldName>) {
|
||||
this.addScalarField(name, 'Float', config)
|
||||
|
|
@ -685,7 +717,7 @@ export class OutputDefinitionBlock<TypeName extends string> {
|
|||
*
|
||||
* @param name The name of this field. Must conform to the regex pattern: [_A-Za-z][_0-9A-Za-z]*
|
||||
* @param config The configuration for things like the field's type, its description, its arguments, its
|
||||
* resolver, and more. See jsdoc on each field within for details.
|
||||
* resolver, and more. See jsdoc on each field within for details.
|
||||
*/
|
||||
field<FieldName extends string>(name: FieldName, config: FieldOutConfig<TypeName, FieldName>): void
|
||||
/**
|
||||
|
|
@ -711,7 +743,7 @@ export class OutputDefinitionBlock<TypeName extends string> {
|
|||
* })
|
||||
*
|
||||
* @param config The configuration for things like the field's type, its description, its arguments, its
|
||||
* resolver, and more. See jsdoc on each field within for details.
|
||||
* resolver, and more. See jsdoc on each field within for details.
|
||||
*/
|
||||
field<FieldName extends string>(config: FieldOutConfigWithName<TypeName, FieldName>): void
|
||||
field<FieldName extends string>(
|
||||
|
|
|
|||
|
|
@ -0,0 +1,230 @@
|
|||
import {
|
||||
ArgumentNode,
|
||||
assertValidName,
|
||||
astFromValue,
|
||||
ASTKindToNode,
|
||||
DirectiveNode,
|
||||
GraphQLDirective,
|
||||
GraphQLDirectiveConfig,
|
||||
Kind,
|
||||
} from 'graphql'
|
||||
import { GetGen, GetGen2, NexusWrappedSymbol } from '../core'
|
||||
import type { MaybeReadonlyArray } from '../typeHelpersInternal'
|
||||
import { mapObj } from '../utils'
|
||||
import type { ArgsRecord } from './args'
|
||||
import { isNexusDirective, isNexusDirectiveUse } from './wrapping'
|
||||
import { Maybe, NexusTypes, withNexusSymbol } from './_types'
|
||||
|
||||
export type Directives = MaybeReadonlyArray<NexusDirectiveDef | GraphQLDirective | NexusDirectiveUse>
|
||||
|
||||
export const RequestDirectiveLocation = [
|
||||
/** Request Definitions */
|
||||
'QUERY',
|
||||
'MUTATION',
|
||||
'SUBSCRIPTION',
|
||||
'FIELD',
|
||||
'FRAGMENT_DEFINITION',
|
||||
'FRAGMENT_SPREAD',
|
||||
'INLINE_FRAGMENT',
|
||||
'VARIABLE_DEFINITION',
|
||||
] as const
|
||||
|
||||
export const SchemaDirectiveLocation = [
|
||||
/** Type System Definitions */
|
||||
'SCHEMA',
|
||||
'SCALAR',
|
||||
'OBJECT',
|
||||
'FIELD_DEFINITION',
|
||||
'ARGUMENT_DEFINITION',
|
||||
'INTERFACE',
|
||||
'UNION',
|
||||
'ENUM',
|
||||
'ENUM_VALUE',
|
||||
'INPUT_OBJECT',
|
||||
'INPUT_FIELD_DEFINITION',
|
||||
] as const
|
||||
|
||||
export type SchemaDirectiveLocationEnum = typeof SchemaDirectiveLocation[number]
|
||||
|
||||
export type RequestDirectiveLocationEnum = typeof RequestDirectiveLocation[number]
|
||||
|
||||
export interface NexusDirectiveConfig<DirectiveName extends string = string> {
|
||||
/** Name of the directive */
|
||||
name: DirectiveName
|
||||
/** The description to annotate the GraphQL SDL */
|
||||
description?: string
|
||||
/** Valid locations that this directive may be used */
|
||||
locations: MaybeReadonlyArray<SchemaDirectiveLocationEnum | RequestDirectiveLocationEnum>
|
||||
/** Whether the directive can be repeated */
|
||||
isRepeatable?: Maybe<boolean> | undefined
|
||||
/**
|
||||
* [GraphQL.org Docs](https://graphql.github.io/learn/schema/#arguments) | [GraphQL 2018
|
||||
* Spec](https://spec.graphql.org/June2018/#sec-Language.Arguments)
|
||||
*
|
||||
* Define arguments for this directive.
|
||||
*
|
||||
* All directives in GraphQL can have arguments defined for them. Nexus provides a number of helpers for
|
||||
* defining arguments. All builtin GraphQL scalar types have helpers named "{scalarName}Arg" such as
|
||||
* "stringArg" and "intArg". You can also use type modifier helpers "[list](https://nxs.li/docs/api/list)"
|
||||
* "[nullable](https://nxs.li/docs/api/nullable)" and "[nonNull](https://nxs.li/docs/api/nonNull)". For
|
||||
* details about nonNull/nullable refer to the [nullability guide](https://nxs.li/guides/nullability).
|
||||
*
|
||||
* @example
|
||||
* export const TestValue = directive({
|
||||
* name: 'TestValue',
|
||||
* description: 'Denotes the value used when testing this type',
|
||||
* args: {
|
||||
* type: enumType({
|
||||
* name: 'TestValueType',
|
||||
* members: ['String', 'Int', 'Float', 'JSON'],
|
||||
* }),
|
||||
* value: stringArg(),
|
||||
* listLength: intArg(),
|
||||
* },
|
||||
* locations: ['FIELD_DEFINITION'],
|
||||
* })
|
||||
*/
|
||||
args?: ArgsRecord
|
||||
/** Data that will be added to the directive extensions field on the graphql-js type def instances */
|
||||
extensions?: GraphQLDirectiveConfig['extensions']
|
||||
}
|
||||
|
||||
export interface NexusDirectiveDef<DirectiveName extends string = string> {
|
||||
(...args: MaybeArgsFor<DirectiveName>): NexusDirectiveUse<DirectiveName>
|
||||
value: NexusDirectiveConfig
|
||||
[NexusWrappedSymbol]: 'Directive'
|
||||
}
|
||||
|
||||
export class NexusDirectiveUse<DirectiveName extends string = string> {
|
||||
constructor(
|
||||
readonly name: DirectiveName,
|
||||
readonly args: MaybeArgsFor<DirectiveName>[0] | undefined,
|
||||
readonly config?: NexusDirectiveConfig<DirectiveName>
|
||||
) {}
|
||||
}
|
||||
|
||||
withNexusSymbol(NexusDirectiveUse, NexusTypes.DirectiveUse)
|
||||
|
||||
/** Defines a directive, which can be used positionally when generating the SDL */
|
||||
export function directive<DirectiveName extends string>(
|
||||
config: NexusDirectiveConfig<DirectiveName>
|
||||
): NexusDirectiveDef<DirectiveName> {
|
||||
assertValidName(config.name)
|
||||
|
||||
config = Object.freeze(config)
|
||||
|
||||
function addDirective(...args: MaybeArgsFor<DirectiveName>) {
|
||||
return new NexusDirectiveUse(config.name, args[0], config)
|
||||
}
|
||||
|
||||
addDirective[NexusWrappedSymbol] = NexusTypes.Directive as 'Directive'
|
||||
|
||||
addDirective.value = config
|
||||
|
||||
return addDirective
|
||||
}
|
||||
|
||||
type MaybeArgsFor<DirectiveName extends string> = GetGen2<'directiveArgs', DirectiveName> extends object
|
||||
? [GetGen2<'directiveArgs', DirectiveName>]
|
||||
: []
|
||||
|
||||
export function addDirective<DirectiveName extends GetGen<'directives', string>>(
|
||||
directiveName: DirectiveName,
|
||||
...args: MaybeArgsFor<DirectiveName>
|
||||
) {
|
||||
return new NexusDirectiveUse<DirectiveName>(directiveName, args[0])
|
||||
}
|
||||
|
||||
const DirectiveASTKindMapping = {
|
||||
SCALAR: Kind.SCALAR_TYPE_DEFINITION, // 'ScalarTypeDefinition',
|
||||
SCHEMA: Kind.SCHEMA_DEFINITION, // 'SchemaDefinition',
|
||||
OBJECT: Kind.OBJECT_TYPE_DEFINITION, // 'ObjectTypeDefinition',
|
||||
FIELD_DEFINITION: Kind.FIELD_DEFINITION, // 'FieldDefinition',
|
||||
ARGUMENT_DEFINITION: Kind.INPUT_VALUE_DEFINITION, // 'InputValueDefinition',
|
||||
INTERFACE: Kind.INTERFACE_TYPE_DEFINITION, // 'InterfaceTypeDefinition',
|
||||
UNION: Kind.UNION_TYPE_DEFINITION, // 'UnionTypeDefinition',
|
||||
ENUM: Kind.ENUM_TYPE_DEFINITION, // 'EnumTypeDefinition',
|
||||
ENUM_VALUE: Kind.ENUM_VALUE_DEFINITION, // 'EnumValueDefinition',
|
||||
INPUT_OBJECT: Kind.INPUT_OBJECT_TYPE_DEFINITION, // 'InputObjectTypeDefinition',
|
||||
INPUT_FIELD_DEFINITION: Kind.INPUT_VALUE_DEFINITION, // 'InputValueDefinition',
|
||||
} as const
|
||||
|
||||
type DirectiveASTKindMapping = typeof DirectiveASTKindMapping
|
||||
export type DirectiveASTKinds = keyof DirectiveASTKindMapping
|
||||
|
||||
/**
|
||||
* Creates the ASTNode with the directives
|
||||
*
|
||||
* @param
|
||||
*/
|
||||
export function maybeAddDirectiveUses<
|
||||
Kind extends DirectiveASTKinds,
|
||||
Result extends { astNode: ASTKindToNode[DirectiveASTKindMapping[Kind]] }
|
||||
>(
|
||||
kind: Kind,
|
||||
directiveUses: Directives | undefined,
|
||||
customDirectives: Record<string, GraphQLDirective>
|
||||
): Result | undefined {
|
||||
if (!directiveUses?.length) {
|
||||
return undefined
|
||||
}
|
||||
const seenDirectives = new Set<string>()
|
||||
return {
|
||||
astNode: {
|
||||
kind: DirectiveASTKindMapping[kind],
|
||||
directives: Array.from(directiveUses).map((d): DirectiveNode => {
|
||||
const directiveName = isNexusDirective(d) ? d.value.name : d.name
|
||||
const directiveDef = customDirectives[directiveName]
|
||||
if (seenDirectives.has(directiveName) && !directiveDef.isRepeatable) {
|
||||
throw new Error(`Cannot use directive ${directiveName} more than once in a row`)
|
||||
}
|
||||
assertValidDirectiveFor(kind, directiveDef)
|
||||
seenDirectives.add(directiveName)
|
||||
|
||||
const args = isNexusDirectiveUse(d) ? directiveArgs(d, directiveDef) : undefined
|
||||
|
||||
return {
|
||||
kind: Kind.DIRECTIVE,
|
||||
name: {
|
||||
kind: Kind.NAME,
|
||||
value: directiveName,
|
||||
},
|
||||
arguments: args,
|
||||
}
|
||||
}),
|
||||
},
|
||||
} as any
|
||||
}
|
||||
|
||||
function assertValidDirectiveFor(
|
||||
kind: DirectiveASTKinds,
|
||||
directiveDef: GraphQLDirective & { locations: readonly any[] } // any is a hack to make this work w/ v15 & 16
|
||||
) {
|
||||
if (!directiveDef.locations.includes(kind)) {
|
||||
throw new Error(`Directive ${directiveDef.name} cannot be applied to ${kind}`)
|
||||
}
|
||||
}
|
||||
|
||||
function directiveArgs(
|
||||
directiveUse: NexusDirectiveUse,
|
||||
directiveDef: GraphQLDirective
|
||||
): ReadonlyArray<ArgumentNode> {
|
||||
return mapObj(directiveUse.args ?? {}, (val, key) => {
|
||||
const arg = directiveDef.args.find((a) => a.name === key)
|
||||
if (!arg) {
|
||||
throw new Error(`Unknown directive arg ${key}, expected one of ${directiveDef.args.map((a) => a.name)}`)
|
||||
}
|
||||
const value = astFromValue(val, arg.type)
|
||||
if (!value) {
|
||||
throw new Error(`Unable to get ast for ${key}`)
|
||||
}
|
||||
return {
|
||||
kind: Kind.ARGUMENT,
|
||||
name: {
|
||||
kind: Kind.NAME,
|
||||
value: key,
|
||||
},
|
||||
value,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
import { assertValidName, GraphQLEnumTypeConfig, GraphQLEnumValueConfig } from 'graphql'
|
||||
import { arg, NexusArgDef, NexusAsArgConfig } from './args'
|
||||
import { NexusTypes, SourceTypingDef, withNexusSymbol } from './_types'
|
||||
import type { Directives } from './directive'
|
||||
import { Maybe, NexusTypes, SourceTypingDef, withNexusSymbol } from './_types'
|
||||
|
||||
type TypeScriptEnumLike = {
|
||||
[key: number]: string
|
||||
|
|
@ -12,24 +13,31 @@ export interface EnumMemberInfo {
|
|||
/** The internal representation of the enum */
|
||||
value?: string | number | object | boolean
|
||||
/** The description to annotate the GraphQL SDL */
|
||||
description?: string
|
||||
description?: Maybe<string>
|
||||
/**
|
||||
* Info about a field deprecation. Formatted as a string and provided with the deprecated directive on
|
||||
* field/enum types and as a comment on input fields.
|
||||
*/
|
||||
deprecation?: string // | DeprecationInfo;
|
||||
deprecation?: Maybe<string> // | DeprecationInfo;
|
||||
/**
|
||||
* Custom extensions, as supported in graphql-js
|
||||
*
|
||||
* @see https://github.com/graphql/graphql-js/issues/1527
|
||||
*/
|
||||
extensions?: GraphQLEnumValueConfig['extensions']
|
||||
/**
|
||||
* A list of directives / directive uses (with args) for the enum member definition
|
||||
*
|
||||
* @example
|
||||
* directives: [addDirective('ExampleDirective', { arg: true })]
|
||||
*/
|
||||
directives?: Directives
|
||||
}
|
||||
|
||||
export interface NexusEnumTypeConfig<TypeName extends string> {
|
||||
name: TypeName
|
||||
/** The description to annotate the GraphQL SDL */
|
||||
description?: string
|
||||
description?: Maybe<string>
|
||||
/** Source type information for this type */
|
||||
sourceType?: SourceTypingDef
|
||||
/** All members of the enum, either as an array of strings/definition objects, as an object, or as a TypeScript enum */
|
||||
|
|
@ -43,6 +51,15 @@ export interface NexusEnumTypeConfig<TypeName extends string> {
|
|||
* @see https://github.com/graphql/graphql-js/issues/1527
|
||||
*/
|
||||
extensions?: GraphQLEnumTypeConfig['extensions']
|
||||
/**
|
||||
* A list of directives / directive uses (with args) for the enum type definition
|
||||
*
|
||||
* @example
|
||||
* directives: [addDirective('ExampleDirective', { arg: true })]
|
||||
*/
|
||||
directives?: Directives
|
||||
/** Adds this type as a method on the Object/Interface definition blocks */
|
||||
asNexusMethod?: string
|
||||
}
|
||||
|
||||
export class NexusEnumTypeDef<TypeName extends string> {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
import { assertValidName, GraphQLInputObjectTypeConfig } from 'graphql'
|
||||
import { arg, NexusArgDef, NexusAsArgConfig } from './args'
|
||||
import type { InputDefinitionBlock } from './definitionBlocks'
|
||||
import { NexusTypes, NonNullConfig, withNexusSymbol } from './_types'
|
||||
import type { Directives } from './directive'
|
||||
import { Maybe, NexusTypes, NonNullConfig, withNexusSymbol } from './_types'
|
||||
|
||||
export type NexusInputObjectTypeConfig<TypeName extends string> = {
|
||||
/** Name of the input object type */
|
||||
|
|
@ -9,7 +10,7 @@ export type NexusInputObjectTypeConfig<TypeName extends string> = {
|
|||
/** Definition block for the input type */
|
||||
definition(t: InputDefinitionBlock<TypeName>): void
|
||||
/** The description to annotate the GraphQL SDL */
|
||||
description?: string
|
||||
description?: Maybe<string>
|
||||
/**
|
||||
* Configures the nullability for the type, check the documentation's "Getting Started" section to learn
|
||||
* more about GraphQL Nexus's assumptions and configuration on nullability.
|
||||
|
|
@ -21,6 +22,15 @@ export type NexusInputObjectTypeConfig<TypeName extends string> = {
|
|||
* @see https://github.com/graphql/graphql-js/issues/1527
|
||||
*/
|
||||
extensions?: GraphQLInputObjectTypeConfig['extensions']
|
||||
/**
|
||||
* A list of directives / directive uses (with args) for the input object type definition
|
||||
*
|
||||
* @example
|
||||
* directives: [addDirective('ExampleDirective', { arg: true })]
|
||||
*/
|
||||
directives?: Directives
|
||||
/** Adds this type as a method on the Object/Interface definition blocks */
|
||||
asNexusMethod?: string
|
||||
} & NexusGenPluginInputTypeConfig<TypeName>
|
||||
|
||||
export class NexusInputObjectTypeDef<TypeName extends string> {
|
||||
|
|
|
|||
|
|
@ -2,18 +2,19 @@ import { assertValidName, GraphQLInterfaceTypeConfig } from 'graphql'
|
|||
import type { FieldResolver, GetGen, InterfaceFieldsFor, ModificationType } from '../typegenTypeHelpers'
|
||||
import type { ArgsRecord } from './args'
|
||||
import { OutputDefinitionBlock, OutputDefinitionBuilder } from './definitionBlocks'
|
||||
import { AbstractTypes, NexusTypes, NonNullConfig, SourceTypingDef, withNexusSymbol } from './_types'
|
||||
import type { Directives } from './directive'
|
||||
import { AbstractTypes, Maybe, NexusTypes, NonNullConfig, SourceTypingDef, withNexusSymbol } from './_types'
|
||||
|
||||
export type Implemented = GetGen<'interfaceNames'> | NexusInterfaceTypeDef<any>
|
||||
|
||||
export interface FieldModification<TypeName extends string, FieldName extends string> {
|
||||
type?: ModificationType<TypeName, FieldName>
|
||||
/** The description to annotate the GraphQL SDL */
|
||||
description?: string
|
||||
description?: Maybe<string>
|
||||
/** The resolve method we should be resolving the field with */
|
||||
resolve?: FieldResolver<TypeName, FieldName>
|
||||
/** You are allowed to add non-required args when modifying a field */
|
||||
args?: ArgsRecord
|
||||
args?: Maybe<ArgsRecord>
|
||||
/**
|
||||
* Custom extensions, as supported in graphql-js
|
||||
*
|
||||
|
|
@ -44,7 +45,7 @@ export type NexusInterfaceTypeConfig<TypeName extends string> = {
|
|||
*/
|
||||
nonNullDefaults?: NonNullConfig
|
||||
/** The description to annotate the GraphQL SDL */
|
||||
description?: string
|
||||
description?: Maybe<string>
|
||||
/** Source type information for this type */
|
||||
sourceType?: SourceTypingDef
|
||||
/**
|
||||
|
|
@ -53,6 +54,15 @@ export type NexusInterfaceTypeConfig<TypeName extends string> = {
|
|||
* @see https://github.com/graphql/graphql-js/issues/1527
|
||||
*/
|
||||
extensions?: GraphQLInterfaceTypeConfig<any, any>['extensions']
|
||||
/**
|
||||
* A list of directives / directive uses (with args) for the output field definition
|
||||
*
|
||||
* @example
|
||||
* directives: [addDirective('ExampleDirective', { arg: true })]
|
||||
*/
|
||||
directives?: Directives
|
||||
/** Adds this type as a method on the Object/Interface definition blocks */
|
||||
asNexusMethod?: string
|
||||
} & AbstractTypes.MaybeTypeDefConfigFieldResolveType<TypeName>
|
||||
|
||||
export interface InterfaceDefinitionBuilder<TypeName extends string> extends OutputDefinitionBuilder {
|
||||
|
|
|
|||
|
|
@ -1,11 +1,7 @@
|
|||
import { isType } from 'graphql'
|
||||
import { isNexusMeta } from './nexusMeta'
|
||||
import { AllNamedTypeDefs, isNexusStruct, NexusListableTypes } from './wrapping'
|
||||
import { isNexusStruct, NexusListableTypes } from './wrapping'
|
||||
import { NexusTypes, withNexusSymbol } from './_types'
|
||||
/** List() */
|
||||
export type NexusListDefConfig<TypeName extends AllNamedTypeDefs> = {
|
||||
type: TypeName
|
||||
}
|
||||
|
||||
export class NexusListDef<TypeName extends NexusListableTypes> {
|
||||
// @ts-ignore
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import type { FieldOutConfig, OutputDefinitionBlock } from '../core'
|
||||
import type { FieldOutConfig, OutputDefinitionBlock } from './definitionBlocks'
|
||||
import { extendType, NexusExtendTypeDef } from './extendType'
|
||||
|
||||
export type MutationFieldConfig<FieldName extends string> =
|
||||
|
|
@ -115,7 +115,7 @@ export function mutationField(
|
|||
* })
|
||||
*
|
||||
* @param name The name of the field on the Mutation type. Names are case‐sensitive and must conform to
|
||||
* pattern: `[_A-Za-z][_0-9A-Za-z]*`
|
||||
* pattern: `[_A-Za-z][_0-9A-Za-z]*`
|
||||
* @param config The same type of configuration you would pass to t.field("...", config)
|
||||
*/
|
||||
export function mutationField<FieldName extends string>(
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ export type NexusMetaBuild = {
|
|||
export type NexusMeta = NexusMetaType | NexusMetaBuild
|
||||
|
||||
export function isNexusMetaBuild(obj: any): obj is NexusMetaBuild {
|
||||
return obj && typeof ownProp.get(obj, NEXUS_BUILD) === 'function'
|
||||
return Boolean(obj && typeof ownProp.get(obj, NEXUS_BUILD) === 'function')
|
||||
}
|
||||
|
||||
export function isNexusMetaType(obj: any): obj is NexusMetaType {
|
||||
|
|
@ -36,11 +36,11 @@ export function isNexusMetaType(obj: any): obj is NexusMetaType {
|
|||
}
|
||||
|
||||
export function isNexusMetaTypeProp(obj: any): obj is NexusMetaTypeProp {
|
||||
return ownProp.has(obj, NEXUS_TYPE) && isNexusStruct(ownProp.get(obj, NEXUS_TYPE))
|
||||
return Boolean(obj && ownProp.has(obj, NEXUS_TYPE) && isNexusStruct(ownProp.get(obj, NEXUS_TYPE)))
|
||||
}
|
||||
|
||||
export function isNexusMetaTypeFn(obj: any): obj is NexusMetaTypeFn {
|
||||
return ownProp.has(obj, NEXUS_TYPE) && typeof ownProp.get(obj, NEXUS_TYPE) === 'function'
|
||||
return Boolean(obj && ownProp.has(obj, NEXUS_TYPE) && typeof ownProp.get(obj, NEXUS_TYPE) === 'function')
|
||||
}
|
||||
|
||||
export function isNexusMeta(obj: any): obj is NexusMetaBuild | NexusMetaTypeFn | NexusMetaType {
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
import { assertValidName, GraphQLObjectType } from 'graphql'
|
||||
import type { InterfaceFieldsFor } from '../typegenTypeHelpers'
|
||||
import { OutputDefinitionBlock, OutputDefinitionBuilder } from './definitionBlocks'
|
||||
import type { Directives } from './directive'
|
||||
import type { FieldModification, FieldModificationDef, Implemented } from './interfaceType'
|
||||
import { AbstractTypes, NexusTypes, NonNullConfig, SourceTypingDef, withNexusSymbol } from './_types'
|
||||
import { AbstractTypes, Maybe, NexusTypes, NonNullConfig, SourceTypingDef, withNexusSymbol } from './_types'
|
||||
|
||||
export interface ObjectDefinitionBuilder extends OutputDefinitionBuilder {
|
||||
addInterfaces(toAdd: Implemented[]): void
|
||||
|
|
@ -102,7 +103,7 @@ export type NexusObjectTypeConfig<TypeName extends string> = {
|
|||
* // # ...
|
||||
* // }
|
||||
*/
|
||||
description?: string
|
||||
description?: Maybe<string>
|
||||
/**
|
||||
* [Source Types Guide](https://nxs.li/guides/backing-types)
|
||||
*
|
||||
|
|
@ -118,8 +119,8 @@ export type NexusObjectTypeConfig<TypeName extends string> = {
|
|||
*
|
||||
* @example
|
||||
* {
|
||||
* "module": "some-package",
|
||||
* "export": "User"
|
||||
* "module": "some-package",
|
||||
* "export": "User"
|
||||
* }
|
||||
*
|
||||
* @example
|
||||
|
|
@ -162,12 +163,12 @@ export type NexusObjectTypeConfig<TypeName extends string> = {
|
|||
* Define the fields of your object type.
|
||||
*
|
||||
* This method receives a type builder api that you will use to define the fields of your object type
|
||||
* within. You can leverage conditionals, loops, other functions (that take the builder api as an argument),
|
||||
* pull in variables from higher scopes, and so on, to help define your fields. However avoid two things:
|
||||
* within. You can leverage conditionals, loops, other functions (that take the builder api as an
|
||||
* argument), pull in variables from higher scopes, and so on, to help define your fields. However avoid two things:
|
||||
*
|
||||
* 1. Doing asynchronous work when defining fields.
|
||||
* 2. Triggering side-effects that you would NOT want run at *build* time––as this code will run during build
|
||||
* to support [Nexus' reflection system](https://nxs.li/guides/reflection).
|
||||
* 1. Doing asynchronous work when defining fields. 2. Triggering side-effects that you would NOT want run
|
||||
* at *build* time––as this code will run during build
|
||||
* to support [Nexus' reflection system](https://nxs.li/guides/reflection).
|
||||
*
|
||||
* @example
|
||||
* objectType({
|
||||
|
|
@ -185,10 +186,19 @@ export type NexusObjectTypeConfig<TypeName extends string> = {
|
|||
* })
|
||||
*
|
||||
* @param t The type builder API for object types. The primary method you'll find is "t.field" but there are
|
||||
* many convenient shorthands available as well, plus anything plugins have added. Explore each one's
|
||||
* jsDoc for more detail.
|
||||
* many convenient shorthands available as well, plus anything plugins have added. Explore each one's
|
||||
* jsDoc for more detail.
|
||||
*/
|
||||
definition(t: ObjectDefinitionBlock<TypeName>): void
|
||||
/**
|
||||
* A list of directives / directive uses (with args) for the object type definition
|
||||
*
|
||||
* @example
|
||||
* directives: [addDirective('ExampleDirective', { arg: true })]
|
||||
*/
|
||||
directives?: Directives
|
||||
/** Adds this type as a method on the Object/Interface definition blocks */
|
||||
asNexusMethod?: string
|
||||
} & AbstractTypes.MaybeTypeDefConfigFieldIsTypeOf<TypeName> &
|
||||
NexusGenPluginTypeConfig<TypeName>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import type { FieldOutConfig, OutputDefinitionBlock } from '../core'
|
||||
import type { FieldOutConfig, OutputDefinitionBlock } from './definitionBlocks'
|
||||
import { extendType, NexusExtendTypeDef } from './extendType'
|
||||
|
||||
export type QueryFieldConfig<FieldName extends string> =
|
||||
|
|
@ -101,7 +101,7 @@ export function queryField(
|
|||
* })
|
||||
*
|
||||
* @param name The name of the field on the Query type. Names are case‐sensitive and must conform to pattern:
|
||||
* `[_A-Za-z][_0-9A-Za-z]*`
|
||||
* `[_A-Za-z][_0-9A-Za-z]*`
|
||||
* @param config The same type of configuration you would pass to t.field("...", config)
|
||||
*/
|
||||
export function queryField<FieldName extends string>(
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
import { assertValidName, GraphQLScalarType, GraphQLScalarTypeConfig } from 'graphql'
|
||||
import { assertValidName, GraphQLNamedType, GraphQLScalarTypeConfig } from 'graphql'
|
||||
import type { AllNexusInputTypeDefs, AllNexusOutputTypeDefs } from '../core'
|
||||
import { decorateType } from './decorateType'
|
||||
import { NexusTypes, SourceTypingDef, withNexusSymbol } from './_types'
|
||||
import type { Directives } from './directive'
|
||||
import { GraphQLNamedOutputType, Maybe, NexusTypes, SourceTypingDef, withNexusSymbol } from './_types'
|
||||
|
||||
export interface ScalarBase
|
||||
extends Pick<
|
||||
|
|
@ -10,7 +12,7 @@ export interface ScalarBase
|
|||
|
||||
export interface ScalarConfig {
|
||||
/** Any deprecation info for this scalar type */
|
||||
deprecation?: string // | DeprecationInfo;
|
||||
deprecation?: Maybe<string> // | DeprecationInfo;
|
||||
/** Adds this type as a method on the Object/Interface definition blocks */
|
||||
asNexusMethod?: string
|
||||
/** Source type information for this type */
|
||||
|
|
@ -21,6 +23,13 @@ export interface ScalarConfig {
|
|||
* @see https://github.com/graphql/graphql-js/issues/1527
|
||||
*/
|
||||
extensions?: GraphQLScalarTypeConfig<any, any>['extensions']
|
||||
/**
|
||||
* A list of directives / directive uses (with args) for the scalar type definition
|
||||
*
|
||||
* @example
|
||||
* directives: [addDirective('ExampleDirective', { arg: true })]
|
||||
*/
|
||||
directives?: Directives
|
||||
}
|
||||
|
||||
export interface NexusScalarTypeConfig<T extends string> extends ScalarBase, ScalarConfig {
|
||||
|
|
@ -43,13 +52,13 @@ export function scalarType<TypeName extends string>(options: NexusScalarTypeConf
|
|||
return new NexusScalarTypeDef(options.name, options)
|
||||
}
|
||||
|
||||
export function asNexusMethod<T extends GraphQLScalarType>(
|
||||
scalar: T,
|
||||
export function asNexusMethod<T extends GraphQLNamedType>(
|
||||
namedType: T,
|
||||
methodName: string,
|
||||
sourceType?: SourceTypingDef
|
||||
): T {
|
||||
return decorateType(scalar, {
|
||||
): T extends GraphQLNamedOutputType ? AllNexusOutputTypeDefs : AllNexusInputTypeDefs {
|
||||
return decorateType(namedType, {
|
||||
asNexusMethod: methodName,
|
||||
sourceType,
|
||||
})
|
||||
}) as any
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
import { assertValidName, GraphQLUnionTypeConfig } from 'graphql'
|
||||
import type { Directives } from '../core'
|
||||
import type { GetGen } from '../typegenTypeHelpers'
|
||||
import type { NexusObjectTypeDef } from './objectType'
|
||||
import { AbstractTypes, NexusTypes, SourceTypingDef, withNexusSymbol } from './_types'
|
||||
import { AbstractTypes, Maybe, NexusTypes, SourceTypingDef, withNexusSymbol } from './_types'
|
||||
|
||||
export interface UnionDefinitionBuilder {
|
||||
typeName: string
|
||||
|
|
@ -27,12 +28,12 @@ export type NexusUnionTypeConfig<TypeName extends string> = {
|
|||
/** Builds the definition for the union */
|
||||
definition(t: UnionDefinitionBlock): void
|
||||
/** The description to annotate the GraphQL SDL */
|
||||
description?: string
|
||||
description?: Maybe<string>
|
||||
/**
|
||||
* Info about a field deprecation. Formatted as a string and provided with the deprecated directive on
|
||||
* field/enum types and as a comment on input fields.
|
||||
*/
|
||||
deprecation?: string // | DeprecationInfo;
|
||||
deprecation?: Maybe<string> // | DeprecationInfo;
|
||||
/** Source type information for this type */
|
||||
sourceType?: SourceTypingDef
|
||||
/**
|
||||
|
|
@ -41,6 +42,15 @@ export type NexusUnionTypeConfig<TypeName extends string> = {
|
|||
* @see https://github.com/graphql/graphql-js/issues/1527
|
||||
*/
|
||||
extensions?: GraphQLUnionTypeConfig<any, any>['extensions']
|
||||
/**
|
||||
* A list of directives / directive uses (with args) for the union type definition
|
||||
*
|
||||
* @example
|
||||
* directives: [addDirective('ExampleDirective', { arg: true })]
|
||||
*/
|
||||
directives?: Directives
|
||||
/** Adds this type as a method on the Object/Interface definition blocks */
|
||||
asNexusMethod?: string
|
||||
} & AbstractTypes.MaybeTypeDefConfigFieldResolveType<TypeName>
|
||||
|
||||
export class NexusUnionTypeDef<TypeName extends string> {
|
||||
|
|
|
|||
|
|
@ -27,21 +27,30 @@ import type { NexusScalarTypeDef } from './scalarType'
|
|||
import { isNexusMetaType, NexusMetaType, resolveNexusMetaType } from './nexusMeta'
|
||||
import type { NexusUnionTypeDef } from './unionType'
|
||||
import { NexusTypes, NexusWrappedSymbol } from './_types'
|
||||
import type { NexusDirectiveDef } from './directive'
|
||||
import type { NexusDirectiveUse } from '../core'
|
||||
|
||||
/** Input(named): Nexus only */
|
||||
export type AllNexusNamedInputTypeDefs<T extends string = any> =
|
||||
| NexusInputObjectTypeDef<T>
|
||||
| NexusEnumTypeDef<T>
|
||||
| NexusScalarTypeDef<T>
|
||||
|
||||
/** Input(named): Nexus + GraphQLInput */
|
||||
export type AllNamedInputTypeDefs<T extends string = any> =
|
||||
| AllNexusNamedInputTypeDefs<T>
|
||||
| Exclude<GraphQLInputType, GraphQLList<any> | GraphQLNonNull<any>>
|
||||
|
||||
/** Input(all): Nexus + GraphQL */
|
||||
export type AllNexusInputTypeDefs<T extends string = any> =
|
||||
| AllNexusNamedInputTypeDefs<T>
|
||||
| AllNamedInputTypeDefs<T>
|
||||
| NexusListDef<any>
|
||||
| NexusNonNullDef<any>
|
||||
| NexusNullDef<any>
|
||||
| GraphQLList<any>
|
||||
| GraphQLNonNull<any>
|
||||
|
||||
/** Output(named): Nexus only */
|
||||
export type AllNexusNamedOutputTypeDefs =
|
||||
| NexusObjectTypeDef<any>
|
||||
| NexusInterfaceTypeDef<any>
|
||||
|
|
@ -49,17 +58,25 @@ export type AllNexusNamedOutputTypeDefs =
|
|||
| NexusEnumTypeDef<any>
|
||||
| NexusScalarTypeDef<any>
|
||||
|
||||
/** Output(all): Nexus only */
|
||||
export type AllNexusOutputTypeDefs =
|
||||
| AllNexusNamedOutputTypeDefs
|
||||
| NexusListDef<any>
|
||||
| NexusNonNullDef<any>
|
||||
| NexusNullDef<any>
|
||||
|
||||
/** Input + output(named): Nexus only */
|
||||
export type AllNexusNamedTypeDefs = AllNexusNamedInputTypeDefs | AllNexusNamedOutputTypeDefs
|
||||
|
||||
/** Input + output(all): Nexus only */
|
||||
export type AllNexusTypeDefs = AllNexusOutputTypeDefs | AllNexusInputTypeDefs
|
||||
|
||||
/** Input + output(all): Nexus only + Name */
|
||||
export type AllNamedTypeDefs = AllNexusNamedTypeDefs | GraphQLNamedType
|
||||
|
||||
/** All inputs to list(...) */
|
||||
export type NexusListableTypes =
|
||||
| GetGen<'allNamedTypes', string>
|
||||
| AllNamedTypeDefs
|
||||
| NexusArgDef<any>
|
||||
| NexusListDef<NexusListableTypes>
|
||||
|
|
@ -68,24 +85,26 @@ export type NexusListableTypes =
|
|||
| GraphQLType
|
||||
| NexusMetaType
|
||||
|
||||
/** All inputs to nonNull(...) */
|
||||
export type NexusNonNullableTypes =
|
||||
| GetGen<'allNamedTypes', string>
|
||||
| AllNamedTypeDefs
|
||||
| NexusListDef<NexusListableTypes>
|
||||
| NexusArgDef<any>
|
||||
| NexusMetaType
|
||||
|
||||
/** All inputs to nullable(...) */
|
||||
export type NexusNullableTypes =
|
||||
| GetGen<'allNamedTypes', string>
|
||||
| AllNamedTypeDefs
|
||||
| NexusListDef<NexusListableTypes>
|
||||
| NexusArgDef<any>
|
||||
| NexusMetaType
|
||||
|
||||
export type AllNamedTypeDefs = GetGen<'allNamedTypes', string> | AllNexusNamedTypeDefs
|
||||
|
||||
export type AllNexusNamedArgsDefs<T extends AllInputTypes = AllInputTypes> =
|
||||
| T
|
||||
| NexusArgDef<T>
|
||||
| AllNexusNamedInputTypeDefs<T>
|
||||
| AllNamedInputTypeDefs<T>
|
||||
| GraphQLInputType
|
||||
|
||||
export type AllNexusArgsDefs =
|
||||
|
|
@ -162,6 +181,13 @@ export function isNexusArgDef(obj: any): obj is NexusArgDef<AllInputTypes> {
|
|||
return isNexusStruct(obj) && obj[NexusWrappedSymbol] === NexusTypes.Arg
|
||||
}
|
||||
|
||||
export function isNexusNamedOuputTypeDef(obj: any): obj is AllNexusNamedOutputTypeDefs {
|
||||
return isNexusNamedTypeDef(obj) && !isNexusInputObjectTypeDef(obj)
|
||||
}
|
||||
export function isNexusNamedInputTypeDef(obj: any): obj is AllNexusNamedInputTypeDefs {
|
||||
return isNexusNamedTypeDef(obj) && !isNexusObjectTypeDef(obj) && !isNexusInterfaceTypeDef(obj)
|
||||
}
|
||||
|
||||
export function isNexusDynamicOutputProperty<T extends string>(obj: any): obj is DynamicOutputPropertyDef<T> {
|
||||
return isNexusStruct(obj) && obj[NexusWrappedSymbol] === NexusTypes.DynamicOutputProperty
|
||||
}
|
||||
|
|
@ -182,6 +208,13 @@ export function isNexusPlugin(obj: any): obj is NexusPlugin {
|
|||
return isNexusStruct(obj) && obj[NexusWrappedSymbol] === NexusTypes.Plugin
|
||||
}
|
||||
|
||||
export function isNexusDirective(obj: any): obj is NexusDirectiveDef {
|
||||
return isNexusStruct(obj) && obj[NexusWrappedSymbol] === NexusTypes.Directive
|
||||
}
|
||||
export function isNexusDirectiveUse(obj: any): obj is NexusDirectiveUse {
|
||||
return isNexusStruct(obj) && obj[NexusWrappedSymbol] === NexusTypes.DirectiveUse
|
||||
}
|
||||
|
||||
export type NexusWrapKind = 'NonNull' | 'Null' | 'List'
|
||||
export type NexusFinalWrapKind = 'NonNull' | 'List'
|
||||
|
||||
|
|
@ -246,10 +279,10 @@ export function rewrapAsGraphQLType(baseType: GraphQLNamedType, wrapping: NexusF
|
|||
let finalType: GraphQLType = baseType
|
||||
wrapping.forEach((wrap) => {
|
||||
if (wrap === 'List') {
|
||||
finalType = GraphQLList(finalType)
|
||||
finalType = new GraphQLList(finalType)
|
||||
} else if (wrap === 'NonNull') {
|
||||
if (!isNonNullType(finalType)) {
|
||||
finalType = GraphQLNonNull(finalType)
|
||||
finalType = new GraphQLNonNull(finalType)
|
||||
}
|
||||
} else {
|
||||
throw new Unreachable(wrap)
|
||||
|
|
|
|||
|
|
@ -1,10 +1,20 @@
|
|||
import { defaultFieldResolver, GraphQLNamedType } from 'graphql'
|
||||
import type { DynamicFieldDefs, SchemaConfig } from './builder'
|
||||
import type { SourceTypingDef, SourceTypings } from './definitions/_types'
|
||||
import type { SourceTypings } from './definitions/_types'
|
||||
import type { NexusOutputFieldConfig } from './definitions/definitionBlocks'
|
||||
import type { NexusInputObjectTypeConfig } from './definitions/inputObjectType'
|
||||
import type { NexusInterfaceTypeConfig } from './definitions/interfaceType'
|
||||
import type { NexusObjectTypeConfig } from './definitions/objectType'
|
||||
import type { Directives, FieldSourceType, NamedFieldSourceType } from './core'
|
||||
|
||||
/** @internal */
|
||||
export function hasNexusExtension(val: any): val is any {
|
||||
return Boolean(val)
|
||||
}
|
||||
|
||||
export function isNexusFieldExtension(val: any): val is NexusFieldExtension {
|
||||
return Boolean(val?._type === 'NexusFieldExtension')
|
||||
}
|
||||
|
||||
export type NexusGraphQLNamedType = GraphQLNamedType & {
|
||||
extensions?: {
|
||||
|
|
@ -18,13 +28,17 @@ export type NexusTypeExtensions = NexusObjectTypeExtension | NexusInterfaceTypeE
|
|||
|
||||
/** Container object living on `fieldDefinition.extensions.nexus` */
|
||||
export class NexusFieldExtension<TypeName extends string = any, FieldName extends string = any> {
|
||||
readonly _type = 'NexusFieldExtension' as const
|
||||
readonly config: Omit<NexusOutputFieldConfig<TypeName, FieldName>, 'resolve'>
|
||||
/** Whether the user has provided a custom "resolve" function, or whether we're using GraphQL's defaultResolver */
|
||||
readonly hasDefinedResolver: boolean
|
||||
readonly sourceType: string | FieldSourceType | NamedFieldSourceType[] | undefined
|
||||
|
||||
constructor(config: NexusOutputFieldConfig<TypeName, FieldName>) {
|
||||
const { resolve, ...rest } = config
|
||||
this.config = rest
|
||||
this.hasDefinedResolver = Boolean(resolve && resolve !== defaultFieldResolver)
|
||||
this.sourceType = rest.sourceType
|
||||
}
|
||||
/** Called when there are modifications on the interface fields */
|
||||
modify(modifications: Partial<NexusOutputFieldConfig<any, any>>) {
|
||||
|
|
@ -34,6 +48,7 @@ export class NexusFieldExtension<TypeName extends string = any, FieldName extend
|
|||
|
||||
/** Container object living on `inputObjectType.extensions.nexus` */
|
||||
export class NexusInputObjectTypeExtension<TypeName extends string = any> {
|
||||
readonly _type = 'NexusInputObjectTypeExtension' as const
|
||||
readonly config: Omit<NexusInputObjectTypeConfig<TypeName>, 'definition'>
|
||||
constructor(config: NexusInputObjectTypeConfig<TypeName>) {
|
||||
const { definition, ...rest } = config
|
||||
|
|
@ -43,6 +58,7 @@ export class NexusInputObjectTypeExtension<TypeName extends string = any> {
|
|||
|
||||
/** Container object living on `objectType.extensions.nexus` */
|
||||
export class NexusObjectTypeExtension<TypeName extends string = any> {
|
||||
readonly _type = 'NexusObjectTypeExtension' as const
|
||||
readonly config: Omit<NexusObjectTypeConfig<TypeName>, 'definition' | 'isTypeOf'>
|
||||
constructor(config: NexusObjectTypeConfig<TypeName>) {
|
||||
const { definition, ...rest } = config
|
||||
|
|
@ -52,6 +68,7 @@ export class NexusObjectTypeExtension<TypeName extends string = any> {
|
|||
|
||||
/** Container object living on `interfaceType.extensions.nexus` */
|
||||
export class NexusInterfaceTypeExtension<TypeName extends string = any> {
|
||||
readonly _type = 'NexusInterfaceTypeExtension' as const
|
||||
readonly config: Omit<NexusInterfaceTypeConfig<TypeName>, 'definition' | 'resolveType'>
|
||||
constructor(config: NexusInterfaceTypeConfig<TypeName>) {
|
||||
const { definition, ...rest } = config
|
||||
|
|
@ -61,7 +78,8 @@ export class NexusInterfaceTypeExtension<TypeName extends string = any> {
|
|||
|
||||
export interface NexusSchemaExtensionConfig extends Omit<SchemaConfig, 'types'> {
|
||||
dynamicFields: DynamicFieldDefs
|
||||
rootTypings: SourceTypings
|
||||
sourceTypings: SourceTypings
|
||||
schemaDirectives?: Directives
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -71,10 +89,3 @@ export interface NexusSchemaExtensionConfig extends Omit<SchemaConfig, 'types'>
|
|||
export class NexusSchemaExtension {
|
||||
constructor(readonly config: NexusSchemaExtensionConfig) {}
|
||||
}
|
||||
|
||||
export type NexusScalarExtensions = {
|
||||
nexus: {
|
||||
asNexusMethod?: string
|
||||
sourceType?: SourceTypingDef
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,219 @@
|
|||
const MAX_ARRAY_LENGTH = 10
|
||||
const MAX_RECURSIVE_DEPTH = 2
|
||||
|
||||
/** Used to print values in error messages. */
|
||||
export function inspect(value: unknown): string {
|
||||
return formatValue(value, [])
|
||||
}
|
||||
|
||||
function formatValue(value: unknown, seenValues: ReadonlyArray<unknown>): string {
|
||||
switch (typeof value) {
|
||||
case 'string':
|
||||
return JSON.stringify(value)
|
||||
case 'function':
|
||||
return value.name ? `[function ${value.name}]` : '[function]'
|
||||
case 'object':
|
||||
return formatObjectValue(value, seenValues)
|
||||
default:
|
||||
return String(value)
|
||||
}
|
||||
}
|
||||
|
||||
function formatObjectValue(value: object | null, previouslySeenValues: ReadonlyArray<unknown>): string {
|
||||
if (value === null) {
|
||||
return 'null'
|
||||
}
|
||||
|
||||
if (previouslySeenValues.includes(value)) {
|
||||
return '[Circular]'
|
||||
}
|
||||
|
||||
const seenValues = [...previouslySeenValues, value]
|
||||
|
||||
if (isJSONable(value)) {
|
||||
const jsonValue = value.toJSON()
|
||||
|
||||
// check for infinite recursion
|
||||
if (jsonValue !== value) {
|
||||
return typeof jsonValue === 'string' ? jsonValue : formatValue(jsonValue, seenValues)
|
||||
}
|
||||
} else if (Array.isArray(value)) {
|
||||
return formatArray(value, seenValues)
|
||||
}
|
||||
|
||||
return formatObject(value, seenValues)
|
||||
}
|
||||
|
||||
function isJSONable(value: any): value is { toJSON: () => unknown } {
|
||||
return typeof value.toJSON === 'function'
|
||||
}
|
||||
|
||||
function formatObject(object: object, seenValues: ReadonlyArray<unknown>): string {
|
||||
const entries = Object.entries(object)
|
||||
if (entries.length === 0) {
|
||||
return '{}'
|
||||
}
|
||||
|
||||
if (seenValues.length > MAX_RECURSIVE_DEPTH) {
|
||||
return '[' + getObjectTag(object) + ']'
|
||||
}
|
||||
|
||||
const properties = entries.map(([key, value]) => key + ': ' + formatValue(value, seenValues))
|
||||
return '{ ' + properties.join(', ') + ' }'
|
||||
}
|
||||
|
||||
function formatArray(array: ReadonlyArray<unknown>, seenValues: ReadonlyArray<unknown>): string {
|
||||
if (array.length === 0) {
|
||||
return '[]'
|
||||
}
|
||||
|
||||
if (seenValues.length > MAX_RECURSIVE_DEPTH) {
|
||||
return '[Array]'
|
||||
}
|
||||
|
||||
const len = Math.min(MAX_ARRAY_LENGTH, array.length)
|
||||
const remaining = array.length - len
|
||||
const items = []
|
||||
|
||||
for (let i = 0; i < len; ++i) {
|
||||
items.push(formatValue(array[i], seenValues))
|
||||
}
|
||||
|
||||
if (remaining === 1) {
|
||||
items.push('... 1 more item')
|
||||
} else if (remaining > 1) {
|
||||
items.push(`... ${remaining} more items`)
|
||||
}
|
||||
|
||||
return '[' + items.join(', ') + ']'
|
||||
}
|
||||
|
||||
function getObjectTag(object: object): string {
|
||||
const tag = Object.prototype.toString
|
||||
.call(object)
|
||||
.replace(/^\[object /, '')
|
||||
.replace(/]$/, '')
|
||||
|
||||
if (tag === 'Object' && typeof object.constructor === 'function') {
|
||||
const name = object.constructor.name
|
||||
if (typeof name === 'string' && name !== '') {
|
||||
return name
|
||||
}
|
||||
}
|
||||
|
||||
return tag
|
||||
}
|
||||
|
||||
export function invariant(condition: unknown, message?: string): asserts condition {
|
||||
const booleanCondition = Boolean(condition)
|
||||
// istanbul ignore else (See transformation done in './resources/inlineInvariant.js')
|
||||
if (!booleanCondition) {
|
||||
throw new Error(message != null ? message : 'Unexpected invariant triggered.')
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Produces the value of a block string from its parsed raw value, similar to CoffeeScript's block string,
|
||||
* Python's docstring trim or Ruby's strip_heredoc.
|
||||
*
|
||||
* This implements the GraphQL spec's BlockStringValue() static algorithm.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
export function dedentBlockStringValue(rawString: string): string {
|
||||
// Expand a block string's raw value into independent lines.
|
||||
const lines = rawString.split(/\r\n|[\n\r]/g)
|
||||
|
||||
// Remove common indentation from all lines but first.
|
||||
const commonIndent = getBlockStringIndentation(rawString)
|
||||
|
||||
if (commonIndent !== 0) {
|
||||
for (let i = 1; i < lines.length; i++) {
|
||||
lines[i] = lines[i].slice(commonIndent)
|
||||
}
|
||||
}
|
||||
|
||||
// Remove leading and trailing blank lines.
|
||||
let startLine = 0
|
||||
while (startLine < lines.length && isBlank(lines[startLine])) {
|
||||
++startLine
|
||||
}
|
||||
|
||||
let endLine = lines.length
|
||||
while (endLine > startLine && isBlank(lines[endLine - 1])) {
|
||||
--endLine
|
||||
}
|
||||
|
||||
// Return a string of the lines joined with U+000A.
|
||||
return lines.slice(startLine, endLine).join('\n')
|
||||
}
|
||||
|
||||
function isBlank(str: string): boolean {
|
||||
for (let i = 0; i < str.length; ++i) {
|
||||
if (str[i] !== ' ' && str[i] !== '\t') {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function getBlockStringIndentation(value: string): number {
|
||||
let isFirstLine = true
|
||||
let isEmptyLine = true
|
||||
let indent = 0
|
||||
let commonIndent = null
|
||||
|
||||
for (let i = 0; i < value.length; ++i) {
|
||||
switch (value.charCodeAt(i)) {
|
||||
case 13: // \r
|
||||
if (value.charCodeAt(i + 1) === 10) {
|
||||
++i // skip \r\n as one symbol
|
||||
}
|
||||
// falls through
|
||||
case 10: // \n
|
||||
isFirstLine = false
|
||||
isEmptyLine = true
|
||||
indent = 0
|
||||
break
|
||||
case 9: // \t
|
||||
case 32: // <space>
|
||||
++indent
|
||||
break
|
||||
default:
|
||||
if (isEmptyLine && !isFirstLine && (commonIndent === null || indent < commonIndent)) {
|
||||
commonIndent = indent
|
||||
}
|
||||
isEmptyLine = false
|
||||
}
|
||||
}
|
||||
|
||||
return commonIndent ?? 0
|
||||
}
|
||||
|
||||
/**
|
||||
* Print a block string in the indented block form by adding a leading and trailing blank line. However, if a
|
||||
* block string starts with whitespace and is a single-line, adding a leading blank line would strip that whitespace.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
export function printBlockString(value: string, preferMultipleLines: boolean = false): string {
|
||||
const isSingleLine = !value.includes('\n')
|
||||
const hasLeadingSpace = value[0] === ' ' || value[0] === '\t'
|
||||
const hasTrailingQuote = value[value.length - 1] === '"'
|
||||
const hasTrailingSlash = value[value.length - 1] === '\\'
|
||||
const printAsMultipleLines = !isSingleLine || hasTrailingQuote || hasTrailingSlash || preferMultipleLines
|
||||
|
||||
let result = ''
|
||||
// Format a multi-line block quote to account for leading space.
|
||||
if (printAsMultipleLines && !(isSingleLine && hasLeadingSpace)) {
|
||||
result += '\n'
|
||||
}
|
||||
result += value
|
||||
if (printAsMultipleLines) {
|
||||
result += '\n'
|
||||
}
|
||||
|
||||
return '"""' + result.replace(/"""/g, '\\"""') + '"""'
|
||||
}
|
||||
|
|
@ -4,6 +4,7 @@ import * as core from './core'
|
|||
// All of the Public API definitions
|
||||
export { makeSchema } from './makeSchema'
|
||||
export { arg, booleanArg, floatArg, idArg, intArg, stringArg } from './definitions/args'
|
||||
export { directive, addDirective } from './definitions/directive'
|
||||
export { decorateType } from './definitions/decorateType'
|
||||
export { enumType } from './definitions/enumType'
|
||||
export { extendInputType } from './definitions/extendInputType'
|
||||
|
|
|
|||
|
|
@ -1,8 +1,16 @@
|
|||
import { makeSchemaInternal, SchemaConfig } from './builder'
|
||||
import { GraphQLNamedType, GraphQLSchema, isObjectType, specifiedDirectives } from 'graphql'
|
||||
import { isNexusObjectTypeDef } from './definitions/wrapping'
|
||||
import {
|
||||
AdditionalGraphQLSchemaConfigOptions,
|
||||
ConfiguredTypegen,
|
||||
MakeSchemaOptions,
|
||||
SchemaBuilder,
|
||||
SchemaConfig,
|
||||
} from './builder'
|
||||
import type { NexusGraphQLSchema } from './definitions/_types'
|
||||
import { TypegenMetadata } from './typegenMetadata'
|
||||
import { resolveTypegenConfig } from './typegenUtils'
|
||||
import { assertNoMissingTypes, runAbstractTypeRuntimeChecks } from './utils'
|
||||
import { assertNoMissingTypes, objValues, runAbstractTypeRuntimeChecks } from './utils'
|
||||
|
||||
/**
|
||||
* Defines the GraphQL schema, by combining the GraphQL types defined by the GraphQL Nexus layer or any
|
||||
|
|
@ -20,10 +28,17 @@ export function makeSchema(config: SchemaConfig): NexusGraphQLSchema {
|
|||
// in the optional thunk for the typegen config
|
||||
const typegenPromise = new TypegenMetadata(typegenConfig).generateArtifacts(schema)
|
||||
if (config.shouldExitAfterGenerateArtifacts) {
|
||||
let typegenPath = '(not enabled)'
|
||||
if (typegenConfig.outputs.typegen) {
|
||||
typegenPath = typegenConfig.outputs.typegen.outputPath
|
||||
if (typegenConfig.outputs.typegen.globalsPath) {
|
||||
typegenPath += ` / ${typegenConfig.outputs.typegen.globalsPath}`
|
||||
}
|
||||
}
|
||||
typegenPromise
|
||||
.then(() => {
|
||||
console.log(`Generated Artifacts:
|
||||
TypeScript Types ==> ${typegenConfig.outputs.typegen || '(not enabled)'}
|
||||
TypeScript Types ==> ${typegenPath}
|
||||
GraphQL Schema ==> ${typegenConfig.outputs.schema || '(not enabled)'}`)
|
||||
process.exit(0)
|
||||
})
|
||||
|
|
@ -58,19 +73,99 @@ export async function generateSchema(config: SchemaConfig): Promise<NexusGraphQL
|
|||
*/
|
||||
generateSchema.withArtifacts = async (
|
||||
config: SchemaConfig,
|
||||
typeFilePath: string | null = null
|
||||
typegen: string | null | ConfiguredTypegen = null
|
||||
): Promise<{
|
||||
schema: NexusGraphQLSchema
|
||||
schemaTypes: string
|
||||
tsTypes: string
|
||||
globalTypes: string | null
|
||||
}> => {
|
||||
const { schema, missingTypes, finalConfig } = makeSchemaInternal(config)
|
||||
const typegenConfig = resolveTypegenConfig(finalConfig)
|
||||
const { schemaTypes, tsTypes } = await new TypegenMetadata(typegenConfig).generateArtifactContents(
|
||||
schema,
|
||||
typeFilePath
|
||||
)
|
||||
const { schemaTypes, tsTypes, globalTypes } = await new TypegenMetadata(
|
||||
typegenConfig
|
||||
).generateArtifactContents(schema, typegen)
|
||||
assertNoMissingTypes(schema, missingTypes)
|
||||
runAbstractTypeRuntimeChecks(schema, finalConfig.features)
|
||||
return { schema, schemaTypes, tsTypes }
|
||||
return { schema, schemaTypes, tsTypes, globalTypes }
|
||||
}
|
||||
|
||||
/** Builds the schema, we may return more than just the schema from this one day. */
|
||||
export function makeSchemaInternal(config: SchemaConfig) {
|
||||
const builder = new SchemaBuilder(config)
|
||||
builder.addTypes(config.types)
|
||||
builder.addTypes(config.directives)
|
||||
if (config.schemaRoots) {
|
||||
builder.addTypes(config.schemaRoots)
|
||||
}
|
||||
|
||||
function getRootType(rootType: 'query' | 'mutation' | 'subscription', defaultType: string) {
|
||||
const rootTypeVal = config.schemaRoots?.[rootType] ?? defaultType
|
||||
let returnVal: null | GraphQLNamedType = null
|
||||
if (typeof rootTypeVal === 'string') {
|
||||
returnVal = typeMap[rootTypeVal]
|
||||
} else if (rootTypeVal) {
|
||||
if (isNexusObjectTypeDef(rootTypeVal)) {
|
||||
returnVal = typeMap[rootTypeVal.name]
|
||||
} else if (isObjectType(rootTypeVal)) {
|
||||
returnVal = typeMap[rootTypeVal.name]
|
||||
}
|
||||
}
|
||||
if (returnVal && !isObjectType(returnVal)) {
|
||||
throw new Error(`Expected ${rootType} to be a objectType, saw ${returnVal.constructor.name}`)
|
||||
}
|
||||
return returnVal
|
||||
}
|
||||
|
||||
const {
|
||||
finalConfig,
|
||||
typeMap,
|
||||
missingTypes,
|
||||
schemaExtension,
|
||||
onAfterBuildFns,
|
||||
customDirectives,
|
||||
schemaDirectives,
|
||||
} = builder.getFinalTypeMap()
|
||||
|
||||
const schema = new GraphQLSchema({
|
||||
...extractGraphQLSchemaOptions(config),
|
||||
query: getRootType('query', 'Query'),
|
||||
mutation: getRootType('mutation', 'Mutation'),
|
||||
subscription: getRootType('subscription', 'Subscription'),
|
||||
types: objValues(typeMap),
|
||||
extensions: {
|
||||
...config.extensions,
|
||||
nexus: schemaExtension,
|
||||
},
|
||||
directives: [...specifiedDirectives, ...Object.values(customDirectives)],
|
||||
...schemaDirectives,
|
||||
}) as NexusGraphQLSchema
|
||||
|
||||
onAfterBuildFns.forEach((fn) => fn(schema))
|
||||
|
||||
return { schema, missingTypes, finalConfig }
|
||||
}
|
||||
|
||||
type OmittedVals = Partial<{ [K in keyof MakeSchemaOptions]: never }>
|
||||
|
||||
function extractGraphQLSchemaOptions(
|
||||
config: SchemaConfig
|
||||
): Partial<AdditionalGraphQLSchemaConfigOptions & OmittedVals> {
|
||||
const {
|
||||
formatTypegen,
|
||||
nonNullDefaults,
|
||||
mergeSchema,
|
||||
outputs,
|
||||
shouldExitAfterGenerateArtifacts,
|
||||
shouldGenerateArtifacts,
|
||||
schemaRoots,
|
||||
sourceTypes,
|
||||
prettierConfig,
|
||||
plugins,
|
||||
customPrintSchemaFn,
|
||||
features,
|
||||
contextType,
|
||||
...graphqlConfigOpts
|
||||
} = config
|
||||
return graphqlConfigOpts
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,8 @@
|
|||
export function nodeImports() {
|
||||
const fs = require('fs') as typeof import('fs')
|
||||
const path = require('path') as typeof import('path')
|
||||
return {
|
||||
fs,
|
||||
path,
|
||||
}
|
||||
}
|
||||
|
|
@ -34,7 +34,7 @@ export type CreateFieldResolverInfo<FieldExt = any, TypeExt = any> = {
|
|||
parentTypeConfig: (
|
||||
| Omit<NexusGraphQLObjectTypeConfig, 'fields' | 'extensions'>
|
||||
| (Omit<NexusGraphQLInterfaceTypeConfig, 'fields' | 'extensions'> & {
|
||||
interfaces: GraphQLInterfaceType[]
|
||||
interfaces: readonly GraphQLInterfaceType[]
|
||||
})
|
||||
) & {
|
||||
extensions?: Maybe<{ nexus?: { config: TypeExt } }>
|
||||
|
|
@ -51,7 +51,7 @@ export interface PluginConfig {
|
|||
/** A name for the plugin, useful for errors, etc. */
|
||||
name: string
|
||||
/** A description for the plugin */
|
||||
description?: string
|
||||
description?: Maybe<string>
|
||||
/** Any type definitions we want to add to output field definitions */
|
||||
fieldDefTypes?: StringLike | StringLike[]
|
||||
/** Any type definitions we want to add to input field definitions */
|
||||
|
|
|
|||
|
|
@ -494,11 +494,11 @@ export const connectionPlugin = (connectionPluginConfig?: ConnectionPluginConfig
|
|||
definition(t2) {
|
||||
t2.list.field('edges', {
|
||||
type: edgeName as any,
|
||||
description: `https://facebook.github.io/relay/graphql/connections.htm#sec-Edge-Types`,
|
||||
description: `https://relay.dev/graphql/connections.htm#sec-Edge-Types`,
|
||||
})
|
||||
t2.nonNull.field('pageInfo', {
|
||||
type: 'PageInfo' as any,
|
||||
description: `https://facebook.github.io/relay/graphql/connections.htm#sec-undefined.PageInfo`,
|
||||
description: `https://relay.dev/graphql/connections.htm#sec-undefined.PageInfo`,
|
||||
})
|
||||
if (includeNodesField) {
|
||||
t2.list.field('nodes', {
|
||||
|
|
@ -530,11 +530,11 @@ export const connectionPlugin = (connectionPluginConfig?: ConnectionPluginConfig
|
|||
definition(t2) {
|
||||
t2.field('cursor', {
|
||||
type: cursorType ?? nonNull('String'),
|
||||
description: 'https://facebook.github.io/relay/graphql/connections.htm#sec-Cursor',
|
||||
description: 'https://relay.dev/graphql/connections.htm#sec-Cursor',
|
||||
})
|
||||
t2.field('node', {
|
||||
type: targetType,
|
||||
description: 'https://facebook.github.io/relay/graphql/connections.htm#sec-Node',
|
||||
description: 'https://relay.dev/graphql/connections.htm#sec-Node',
|
||||
})
|
||||
if (pluginExtendEdge) {
|
||||
eachObj(pluginExtendEdge, (val, key) => {
|
||||
|
|
@ -558,7 +558,7 @@ export const connectionPlugin = (connectionPluginConfig?: ConnectionPluginConfig
|
|||
objectType({
|
||||
name: 'PageInfo',
|
||||
description:
|
||||
'PageInfo cursor, as defined in https://facebook.github.io/relay/graphql/connections.htm#sec-undefined.PageInfo',
|
||||
'PageInfo cursor, as defined in https://relay.dev/graphql/connections.htm#sec-undefined.PageInfo',
|
||||
definition(t2) {
|
||||
t2.nonNull.field('hasNextPage', {
|
||||
type: 'Boolean',
|
||||
|
|
@ -724,10 +724,6 @@ export function makeResolveFn(
|
|||
formattedArgs.after = decodeCursor(args.after).replace(CURSOR_PREFIX, '')
|
||||
}
|
||||
|
||||
if (args.last && !args.before && cursorFromNode === defaultCursorFromNode) {
|
||||
throw new Error(`Cannot paginate backward without a "before" cursor by default.`)
|
||||
}
|
||||
|
||||
// Local variable to cache the execution of fetching the nodes,
|
||||
// which is needed for all fields.
|
||||
let cachedNodes: MaybePromiseLike<Array<any>>
|
||||
|
|
@ -978,8 +974,10 @@ function iterateNodes(nodes: any[], args: PaginationArgs, cb: (node: any, i: num
|
|||
}
|
||||
} else if (typeof args.last === 'number') {
|
||||
const len = Math.min(args.last, nodes.length)
|
||||
const startOffset = Math.max(nodes.length - args.last, 0)
|
||||
|
||||
for (let i = 0; i < len; i++) {
|
||||
cb(nodes[i], i)
|
||||
cb(nodes[i + startOffset], i)
|
||||
}
|
||||
} else {
|
||||
// Only happens if we have a custom validateArgs that ignores first/last
|
||||
|
|
@ -1063,14 +1061,9 @@ function defaultCursorFromNode(
|
|||
// If we're paginating backward, assume we're working backward from the assumed length
|
||||
// e.g. [0...20] (last: 5, before: "cursor:20") -> [cursor:15, cursor:16, cursor:17, cursor:18, cursor:19]
|
||||
if (typeof args.last === 'number') {
|
||||
if (args.before) {
|
||||
const offset = parseInt(args.before, 10)
|
||||
const len = Math.min(nodes.length, args.last)
|
||||
cursorIndex = offset - len + index
|
||||
} else {
|
||||
/* istanbul ignore next */
|
||||
throw new Error('Unreachable')
|
||||
}
|
||||
const offset = args.before ? parseInt(args.before, 10) : nodes.length
|
||||
const len = Math.min(nodes.length, args.last)
|
||||
cursorIndex = offset - len + index
|
||||
}
|
||||
return `${CURSOR_PREFIX}${cursorIndex}`
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,11 +31,9 @@ export interface NullabilityPluginOnGuardedConfig {
|
|||
type: GraphQLNullableType
|
||||
}
|
||||
|
||||
export type NullFallbackValues = Partial<
|
||||
{
|
||||
[K in AllOutputTypes]: (obj: NullabilityPluginFallbackFn) => GetGen2<'rootTypes', K>
|
||||
}
|
||||
>
|
||||
export type NullFallbackValues = Partial<{
|
||||
[K in AllOutputTypes]: (obj: NullabilityPluginFallbackFn) => GetGen2<'rootTypes', K>
|
||||
}>
|
||||
|
||||
export type NullabilityGuardConfig = {
|
||||
/** Whether we should guard against non-null values. Defaults to "true" if NODE_ENV === "production", false otherwise. */
|
||||
|
|
|
|||
|
|
@ -0,0 +1,323 @@
|
|||
/** Conveniently represents flow's "Maybe" type https://flow.org/en/docs/types/maybe/ */
|
||||
type Maybe<T> = null | undefined | T
|
||||
|
||||
import { DirectiveNode, Kind, print } from 'graphql'
|
||||
import { printBlockString, invariant, inspect } from './graphqlInternal'
|
||||
|
||||
import type { GraphQLSchema } from 'graphql'
|
||||
import type { GraphQLDirective } from 'graphql'
|
||||
import type {
|
||||
GraphQLNamedType,
|
||||
GraphQLArgument,
|
||||
GraphQLInputField,
|
||||
GraphQLScalarType,
|
||||
GraphQLEnumType,
|
||||
GraphQLObjectType,
|
||||
GraphQLInterfaceType,
|
||||
GraphQLUnionType,
|
||||
GraphQLInputObjectType,
|
||||
} from 'graphql'
|
||||
import { isIntrospectionType } from 'graphql'
|
||||
import { isSpecifiedScalarType } from 'graphql'
|
||||
import { DEFAULT_DEPRECATION_REASON, isSpecifiedDirective } from 'graphql'
|
||||
import {
|
||||
isScalarType,
|
||||
isObjectType,
|
||||
isInterfaceType,
|
||||
isUnionType,
|
||||
isEnumType,
|
||||
isInputObjectType,
|
||||
} from 'graphql'
|
||||
|
||||
import { astFromValue } from 'graphql'
|
||||
|
||||
export function printSchemaWithDirectives(schema: GraphQLSchema): string {
|
||||
return printFilteredSchemaWithDirectives(schema, (n) => !isSpecifiedDirective(n), isDefinedType)
|
||||
}
|
||||
|
||||
function isDefinedType(type: GraphQLNamedType): boolean {
|
||||
return !isSpecifiedScalarType(type) && !isIntrospectionType(type)
|
||||
}
|
||||
|
||||
function printFilteredSchemaWithDirectives(
|
||||
schema: GraphQLSchema,
|
||||
directiveFilter: (type: GraphQLDirective) => boolean,
|
||||
typeFilter: (type: GraphQLNamedType) => boolean
|
||||
): string {
|
||||
const directives = schema.getDirectives().filter(directiveFilter)
|
||||
const types = Object.values(schema.getTypeMap()).filter(typeFilter)
|
||||
|
||||
return [
|
||||
printSchemaDefinition(schema),
|
||||
...directives.map((directive) => printDirective(directive)),
|
||||
...types.map((type) => printType(type)),
|
||||
]
|
||||
.filter(Boolean)
|
||||
.join('\n\n')
|
||||
}
|
||||
|
||||
function printSchemaDefinition(
|
||||
// & description for GraphQL 14 types
|
||||
schema: GraphQLSchema & { description?: Maybe<string> }
|
||||
): Maybe<string> {
|
||||
if (schema.description == null && isSchemaOfCommonNames(schema)) {
|
||||
return
|
||||
}
|
||||
|
||||
const operationTypes = []
|
||||
|
||||
const queryType = schema.getQueryType()
|
||||
if (queryType) {
|
||||
operationTypes.push(` query: ${queryType.name}`)
|
||||
}
|
||||
|
||||
const mutationType = schema.getMutationType()
|
||||
if (mutationType) {
|
||||
operationTypes.push(` mutation: ${mutationType.name}`)
|
||||
}
|
||||
|
||||
const subscriptionType = schema.getSubscriptionType()
|
||||
if (subscriptionType) {
|
||||
operationTypes.push(` subscription: ${subscriptionType.name}`)
|
||||
}
|
||||
|
||||
return printDescription(schema) + `schema {\n${operationTypes.join('\n')}\n}`
|
||||
}
|
||||
|
||||
/**
|
||||
* GraphQL schema define root types for each type of operation. These types are the same as any other type and
|
||||
* can be named in any manner, however there is a common naming convention:
|
||||
*
|
||||
* ```graphql
|
||||
* query: Query
|
||||
* mutation: Mutation
|
||||
* subscription: Subscription } ```
|
||||
*
|
||||
* When using this naming convention, the schema description can be omitted.
|
||||
* ```
|
||||
*/
|
||||
function isSchemaOfCommonNames(schema: GraphQLSchema): boolean {
|
||||
const queryType = schema.getQueryType()
|
||||
if (queryType && queryType.name !== 'Query') {
|
||||
return false
|
||||
}
|
||||
|
||||
const mutationType = schema.getMutationType()
|
||||
if (mutationType && mutationType.name !== 'Mutation') {
|
||||
return false
|
||||
}
|
||||
|
||||
const subscriptionType = schema.getSubscriptionType()
|
||||
if (subscriptionType && subscriptionType.name !== 'Subscription') {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
export function printType(type: GraphQLNamedType): string {
|
||||
if (isScalarType(type)) {
|
||||
return printScalar(type)
|
||||
}
|
||||
if (isObjectType(type)) {
|
||||
return printObject(type)
|
||||
}
|
||||
if (isInterfaceType(type)) {
|
||||
return printInterface(type)
|
||||
}
|
||||
if (isUnionType(type)) {
|
||||
return printUnion(type)
|
||||
}
|
||||
if (isEnumType(type)) {
|
||||
return printEnum(type)
|
||||
}
|
||||
// istanbul ignore else (See: 'https://github.com/graphql/graphql-js/issues/2618')
|
||||
if (isInputObjectType(type)) {
|
||||
return printInputObject(type)
|
||||
}
|
||||
|
||||
// istanbul ignore next (Not reachable. All possible types have been considered)
|
||||
invariant(false, 'Unexpected type: ' + inspect(type))
|
||||
}
|
||||
|
||||
function printScalar(type: GraphQLScalarType): string {
|
||||
return printDescription(type) + `scalar ${type.name}` + printSpecifiedByURL(type) + printDirectives(type)
|
||||
}
|
||||
|
||||
function printImplementedInterfaces(
|
||||
// & getInterfaces added for GraphQL 14 types
|
||||
type: (GraphQLObjectType | GraphQLInterfaceType) & { getInterfaces?: () => readonly GraphQLInterfaceType[] }
|
||||
): string {
|
||||
const interfaces = type.getInterfaces?.()
|
||||
return interfaces?.length ? ' implements ' + interfaces.map((i) => i.name).join(' & ') : ''
|
||||
}
|
||||
|
||||
function printObject(type: GraphQLObjectType): string {
|
||||
return (
|
||||
printDescription(type) +
|
||||
`type ${type.name}` +
|
||||
printImplementedInterfaces(type) +
|
||||
printDirectives(type) +
|
||||
printFields(type)
|
||||
)
|
||||
}
|
||||
|
||||
function printInterface(type: GraphQLInterfaceType): string {
|
||||
return (
|
||||
printDescription(type) +
|
||||
`interface ${type.name}` +
|
||||
printImplementedInterfaces(type) +
|
||||
printDirectives(type) +
|
||||
printFields(type)
|
||||
)
|
||||
}
|
||||
|
||||
function printUnion(type: GraphQLUnionType): string {
|
||||
const types = type.getTypes()
|
||||
const possibleTypes = types.length ? ' = ' + types.join(' | ') : ''
|
||||
return printDescription(type) + 'union ' + type.name + printDirectives(type) + possibleTypes
|
||||
}
|
||||
|
||||
function printEnum(type: GraphQLEnumType): string {
|
||||
const values = type
|
||||
.getValues()
|
||||
.map(
|
||||
(value, i) =>
|
||||
printDescription(value, ' ', !i) +
|
||||
' ' +
|
||||
value.name +
|
||||
printDeprecated(value.deprecationReason) +
|
||||
printDirectives(value)
|
||||
)
|
||||
|
||||
return printDescription(type) + `enum ${type.name}` + printDirectives(type) + printBlock(values)
|
||||
}
|
||||
|
||||
function printInputObject(type: GraphQLInputObjectType): string {
|
||||
const fields = Object.values(type.getFields()).map(
|
||||
(f, i) => printDescription(f, ' ', !i) + ' ' + printInputValue(f)
|
||||
)
|
||||
return printDescription(type) + `input ${type.name}` + printDirectives(type) + printBlock(fields)
|
||||
}
|
||||
|
||||
function printFields(type: GraphQLObjectType | GraphQLInterfaceType): string {
|
||||
const fields = Object.values(type.getFields()).map(
|
||||
(f, i) =>
|
||||
printDescription(f, ' ', !i) +
|
||||
' ' +
|
||||
f.name +
|
||||
printArgs(f.args, ' ') +
|
||||
': ' +
|
||||
String(f.type) +
|
||||
printDeprecated(f.deprecationReason) +
|
||||
printDirectives(f)
|
||||
)
|
||||
return printBlock(fields)
|
||||
}
|
||||
|
||||
function printBlock(items: ReadonlyArray<string>): string {
|
||||
return items.length !== 0 ? ' {\n' + items.join('\n') + '\n}' : ''
|
||||
}
|
||||
|
||||
function printArgs(args: ReadonlyArray<GraphQLArgument>, indentation: string = ''): string {
|
||||
if (args.length === 0) {
|
||||
return ''
|
||||
}
|
||||
|
||||
// If every arg does not have a description, print them on one line.
|
||||
if (args.every((arg) => !arg.description)) {
|
||||
return '(' + args.map(printInputValue).join(', ') + ')'
|
||||
}
|
||||
|
||||
return (
|
||||
'(\n' +
|
||||
args
|
||||
.map(
|
||||
(arg, i) => printDescription(arg, ' ' + indentation, !i) + ' ' + indentation + printInputValue(arg)
|
||||
)
|
||||
.join('\n') +
|
||||
'\n' +
|
||||
indentation +
|
||||
')'
|
||||
)
|
||||
}
|
||||
|
||||
function printInputValue(arg: GraphQLInputField & { deprecationReason?: Maybe<string> }): string {
|
||||
const defaultAST = astFromValue(arg.defaultValue, arg.type)
|
||||
let argDecl = arg.name + ': ' + String(arg.type)
|
||||
if (defaultAST) {
|
||||
argDecl += ` = ${print(defaultAST)}`
|
||||
}
|
||||
return argDecl + printDeprecated(arg.deprecationReason) + printDirectives(arg)
|
||||
}
|
||||
|
||||
function printDirective(directive: GraphQLDirective): string {
|
||||
return (
|
||||
printDescription(directive) +
|
||||
'directive @' +
|
||||
directive.name +
|
||||
printArgs(directive.args) +
|
||||
(directive.isRepeatable ? ' repeatable' : '') +
|
||||
' on ' +
|
||||
directive.locations.join(' | ')
|
||||
)
|
||||
}
|
||||
|
||||
function printDeprecated(reason: Maybe<string>): string {
|
||||
if (reason == null) {
|
||||
return ''
|
||||
}
|
||||
if (reason !== DEFAULT_DEPRECATION_REASON) {
|
||||
const astValue = print({ kind: Kind.STRING, value: reason })
|
||||
return ` @deprecated(reason: ${astValue})`
|
||||
}
|
||||
return ' @deprecated'
|
||||
}
|
||||
|
||||
function printSpecifiedByURL(
|
||||
// https://github.com/graphql/graphql-js/issues/3156
|
||||
scalar: GraphQLScalarType & { specifiedByURL?: Maybe<string>; specifiedByUrl?: Maybe<string> }
|
||||
): string {
|
||||
const specifiedByURL = scalar.specifiedByURL ?? scalar.specifiedByUrl
|
||||
if (specifiedByURL == null) {
|
||||
return ''
|
||||
}
|
||||
const astValue = print({ kind: Kind.STRING, value: specifiedByURL })
|
||||
return ` @specifiedBy(url: ${astValue})`
|
||||
}
|
||||
|
||||
function printDescription(
|
||||
def: { readonly description?: Maybe<string> },
|
||||
indentation: string = '',
|
||||
firstInBlock: boolean = true
|
||||
): string {
|
||||
const { description } = def
|
||||
if (description == null) {
|
||||
return ''
|
||||
}
|
||||
|
||||
const preferMultipleLines = description.length > 70
|
||||
const blockString = printBlockString(description, preferMultipleLines)
|
||||
const prefix = indentation && !firstInBlock ? '\n' + indentation : indentation
|
||||
|
||||
return prefix + blockString.replace(/\n/g, '\n' + indentation) + '\n'
|
||||
}
|
||||
|
||||
function printDirectives(value: { astNode?: Maybe<{ readonly directives?: ReadonlyArray<DirectiveNode> }> }) {
|
||||
const directives = value.astNode?.directives
|
||||
if (!directives?.length) {
|
||||
return ''
|
||||
}
|
||||
return ' ' + directives.map(printDirectiveUse).join(' ')
|
||||
}
|
||||
|
||||
function printDirectiveUse(node: DirectiveNode) {
|
||||
return `@${node.name.value}` + printDirectiveArgs(node)
|
||||
}
|
||||
|
||||
function printDirectiveArgs(node: DirectiveNode) {
|
||||
if (!node.arguments?.length) {
|
||||
return ''
|
||||
}
|
||||
return `(${node.arguments.map((a) => `${a.name.value}: ${print(a.value)}`).join(', ')})`
|
||||
}
|
||||
|
|
@ -0,0 +1,232 @@
|
|||
import {
|
||||
GraphQLEnumType,
|
||||
GraphQLFieldConfigArgumentMap,
|
||||
GraphQLFieldConfigMap,
|
||||
GraphQLInputFieldConfigMap,
|
||||
GraphQLInputObjectType,
|
||||
GraphQLInterfaceType,
|
||||
GraphQLNamedType,
|
||||
GraphQLObjectType,
|
||||
GraphQLScalarType,
|
||||
GraphQLUnionType,
|
||||
isEnumType,
|
||||
isInputObjectType,
|
||||
isInterfaceType,
|
||||
isObjectType,
|
||||
isScalarType,
|
||||
isUnionType,
|
||||
defaultTypeResolver,
|
||||
} from 'graphql'
|
||||
import type { MergeSchemaConfig } from './builder'
|
||||
import { arg, ArgsRecord } from './definitions/args'
|
||||
import type { InputDefinitionBlock } from './definitions/definitionBlocks'
|
||||
import { enumType } from './definitions/enumType'
|
||||
import { inputObjectType } from './definitions/inputObjectType'
|
||||
import { InterfaceDefinitionBlock, interfaceType } from './definitions/interfaceType'
|
||||
import { ObjectDefinitionBlock, objectType } from './definitions/objectType'
|
||||
import { scalarType } from './definitions/scalarType'
|
||||
import { unionType } from './definitions/unionType'
|
||||
import { AllNexusArgsDefs, applyNexusWrapping, unwrapGraphQLDef } from './definitions/wrapping'
|
||||
import type { Maybe, SourceTypingDef } from './definitions/_types'
|
||||
import type { GetGen } from './typegenTypeHelpers'
|
||||
import { graphql15InterfaceConfig, Unreachable } from './utils'
|
||||
|
||||
export interface RebuildConfig extends Omit<MergeSchemaConfig, 'schema'> {
|
||||
captureLeafType?: (type: GraphQLNamedType) => void
|
||||
asNexusMethod?: string
|
||||
sourceType?: SourceTypingDef
|
||||
}
|
||||
|
||||
export function rebuildNamedType(type: GraphQLNamedType, config: RebuildConfig) {
|
||||
if (isObjectType(type)) {
|
||||
return rebuildObjectType(type, config)
|
||||
} else if (isInputObjectType(type)) {
|
||||
return rebuildInputObjectType(type, config)
|
||||
} else if (isInterfaceType(type)) {
|
||||
return rebuildInterfaceType(type, config)
|
||||
} else if (isUnionType(type)) {
|
||||
return rebuildUnionType(type, config)
|
||||
} else if (isScalarType(type)) {
|
||||
return rebuildScalarType(type, config)
|
||||
} else if (isEnumType(type)) {
|
||||
return rebuildEnumType(type, config)
|
||||
}
|
||||
throw new Unreachable(type)
|
||||
}
|
||||
|
||||
export function rebuildInputObjectType(type: GraphQLInputObjectType, config: RebuildConfig) {
|
||||
const { name, fields, description, extensions } = type.toConfig()
|
||||
return inputObjectType({
|
||||
name,
|
||||
description,
|
||||
definition: (t) => {
|
||||
rebuildInputDefinition(name, t, fields, config)
|
||||
},
|
||||
extensions,
|
||||
nonNullDefaults: {
|
||||
output: false,
|
||||
input: false,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
export function rebuildUnionType(type: GraphQLUnionType, config: RebuildConfig) {
|
||||
const { name, types, description, resolveType, extensions } = type.toConfig()
|
||||
return unionType({
|
||||
name,
|
||||
description,
|
||||
// @ts-ignore - todo, see why this is the case
|
||||
resolveType: resolveType ?? defaultTypeResolver,
|
||||
definition(t) {
|
||||
t.members(
|
||||
...types.map((o) => {
|
||||
config.captureLeafType?.(o)
|
||||
return o.name as GetGen<'objectNames'>
|
||||
})
|
||||
)
|
||||
},
|
||||
extensions,
|
||||
})
|
||||
}
|
||||
|
||||
export function rebuildScalarType(type: GraphQLScalarType, config: RebuildConfig) {
|
||||
return scalarType({
|
||||
...type.toConfig(),
|
||||
sourceType: config.sourceType,
|
||||
asNexusMethod: config.asNexusMethod,
|
||||
})
|
||||
}
|
||||
|
||||
export function rebuildEnumType(type: GraphQLEnumType, { sourceType, asNexusMethod }: RebuildConfig) {
|
||||
const { name, values, ...config } = type.toConfig()
|
||||
return enumType({
|
||||
name,
|
||||
...config,
|
||||
members: Object.entries(values).map(([valueName, config]) => {
|
||||
return {
|
||||
name: valueName,
|
||||
deprecation: config.deprecationReason,
|
||||
...config,
|
||||
}
|
||||
}),
|
||||
sourceType,
|
||||
asNexusMethod,
|
||||
})
|
||||
}
|
||||
|
||||
export function rebuildInterfaceType(type: GraphQLInterfaceType, config: RebuildConfig) {
|
||||
const { name, fields, description, interfaces, extensions, resolveType } = graphql15InterfaceConfig(
|
||||
type.toConfig()
|
||||
)
|
||||
return interfaceType({
|
||||
name,
|
||||
description,
|
||||
// @ts-ignore - todo, see why this is the case
|
||||
resolveType: resolveType ?? defaultTypeResolver,
|
||||
definition: (t) => {
|
||||
rebuildOutputDefinition(name, t, fields, interfaces, config)
|
||||
},
|
||||
nonNullDefaults: {
|
||||
output: false,
|
||||
input: false,
|
||||
},
|
||||
extensions,
|
||||
sourceType: config.sourceType,
|
||||
asNexusMethod: config.asNexusMethod,
|
||||
})
|
||||
}
|
||||
|
||||
export function rebuildObjectType(type: GraphQLObjectType, config: RebuildConfig) {
|
||||
const { name, fields, interfaces, description, extensions } = type.toConfig()
|
||||
return objectType({
|
||||
name,
|
||||
description,
|
||||
definition: (t) => {
|
||||
rebuildOutputDefinition(name, t, fields, interfaces, config)
|
||||
},
|
||||
nonNullDefaults: {
|
||||
output: false,
|
||||
input: false,
|
||||
},
|
||||
extensions,
|
||||
sourceType: config.sourceType,
|
||||
asNexusMethod: config.asNexusMethod,
|
||||
})
|
||||
}
|
||||
|
||||
export function rebuildOutputDefinition(
|
||||
typeName: string,
|
||||
t: ObjectDefinitionBlock<string> | InterfaceDefinitionBlock<string>,
|
||||
fields: GraphQLFieldConfigMap<any, any>,
|
||||
interfaces: ReadonlyArray<GraphQLInterfaceType>,
|
||||
config: RebuildConfig
|
||||
) {
|
||||
t.implements(
|
||||
...interfaces.map((i) => {
|
||||
config.captureLeafType?.(i)
|
||||
return i.name as GetGen<'interfaceNames'>
|
||||
})
|
||||
)
|
||||
for (const [fieldName, fieldConfig] of Object.entries(fields)) {
|
||||
if (config.skipFields?.[typeName] && config.skipFields?.[typeName].includes(fieldName)) {
|
||||
continue
|
||||
}
|
||||
const { namedType, wrapping } = unwrapGraphQLDef(fieldConfig.type)
|
||||
config.captureLeafType?.(namedType)
|
||||
t.field(fieldName, {
|
||||
type: applyNexusWrapping(namedType.name, wrapping),
|
||||
description: fieldConfig.description,
|
||||
deprecation: fieldConfig.deprecationReason,
|
||||
extensions: fieldConfig.extensions,
|
||||
args: rebuildArgs(typeName, fieldName, fieldConfig.args ?? {}, config),
|
||||
resolve: fieldConfig.resolve,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export function rebuildInputDefinition(
|
||||
typeName: string,
|
||||
t: InputDefinitionBlock<string>,
|
||||
fields: GraphQLInputFieldConfigMap,
|
||||
config: RebuildConfig
|
||||
) {
|
||||
for (const [fieldName, fieldConfig] of Object.entries(fields)) {
|
||||
if (config.skipFields?.[typeName] && config.skipFields?.[typeName].includes(fieldName)) {
|
||||
continue
|
||||
}
|
||||
const { namedType, wrapping } = unwrapGraphQLDef(fieldConfig.type)
|
||||
config.captureLeafType?.(namedType)
|
||||
t.field(fieldName, {
|
||||
type: applyNexusWrapping(namedType.name, wrapping),
|
||||
description: fieldConfig.description,
|
||||
default: fieldConfig.defaultValue,
|
||||
extensions: fieldConfig.extensions,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export function rebuildArgs(
|
||||
typeName: string,
|
||||
fieldName: string,
|
||||
argMap: Maybe<GraphQLFieldConfigArgumentMap>,
|
||||
config: RebuildConfig
|
||||
): Maybe<ArgsRecord> {
|
||||
if (!argMap) {
|
||||
return null
|
||||
}
|
||||
const rebuiltArgs: Record<string, AllNexusArgsDefs> = {}
|
||||
for (const [argName, argConfig] of Object.entries(argMap)) {
|
||||
if (config.skipArgs?.[typeName]?.[fieldName]) {
|
||||
continue
|
||||
}
|
||||
const { namedType, wrapping } = unwrapGraphQLDef(argConfig.type)
|
||||
config.captureLeafType?.(namedType)
|
||||
rebuiltArgs[argName] = arg({
|
||||
type: applyNexusWrapping(namedType.name, wrapping),
|
||||
default: argConfig.defaultValue,
|
||||
description: argConfig.description,
|
||||
extensions: argConfig.extensions,
|
||||
})
|
||||
}
|
||||
return rebuiltArgs
|
||||
}
|
||||
|
|
@ -56,3 +56,5 @@ type DoRequireDeeply<T> = {
|
|||
export type MaybePromiseLike<T> = T | PromiseLike<T>
|
||||
|
||||
export type UnwrapPromise<R> = R extends PromiseLike<infer U> ? U : R
|
||||
|
||||
export type MaybeReadonlyArray<T> = Array<T> | ReadonlyArray<T>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import type { GraphQLResolveInfo } from 'graphql'
|
||||
import type { Maybe } from './definitions/_types'
|
||||
import type {
|
||||
AbstractTypeResolver,
|
||||
GetGen,
|
||||
|
|
@ -63,7 +64,7 @@ export type IsTypeOfHandler<TypeName extends string> = (
|
|||
* Get an object with the `isTypeOf` field if applicable for the given object Type.
|
||||
*
|
||||
* @remarks
|
||||
* Intersect the result of this with other things to build up the final options for a type def.
|
||||
* Intersect the result of this with other things to build up the final options for a type def.
|
||||
*/
|
||||
export type MaybeTypeDefConfigFieldIsTypeOf<TypeName extends string> =
|
||||
// is isTypeOf strategy disabled ?
|
||||
|
|
@ -121,24 +122,24 @@ export type MaybeTypeDefConfigFieldIsTypeOf<TypeName extends string> =
|
|||
* })
|
||||
*
|
||||
* @param source The [source data](https://nxs.li/guides/source-types) for the GraphQL objects that
|
||||
* are members of the abstract types that this type is a member of. For example for some type A in
|
||||
* two union types whose members are A,B.C and A,D,E respectively then isTypeOf method for A would
|
||||
* receive source data from A, B, C, D, & E at runtime.
|
||||
* are members of the abstract types that this type is a member of. For example for some type A
|
||||
* in two union types whose members are A,B.C and A,D,E respectively then isTypeOf method for A
|
||||
* would receive source data from A, B, C, D, & E at runtime.
|
||||
* @param context The context data for this request.
|
||||
*
|
||||
* The context data is typically a singleton scoped to the lifecycle of the request. This means
|
||||
* created at the beginning of a request and then passed to all the resolvers that execute while
|
||||
* resolving the request. It is often used to store information like the current user making the
|
||||
* request. Nexus is not responsible for this however. That is typically something you'll do with
|
||||
* e.g. [Mercurius](https://mercurius.dev) or [Apollo
|
||||
* Server](https://apollographql.com/docs/apollo-server/api/apollo-server).
|
||||
* The context data is typically a singleton scoped to the lifecycle of the request. This means
|
||||
* created at the beginning of a request and then passed to all the resolvers that execute while
|
||||
* resolving the request. It is often used to store information like the current user making the
|
||||
* request. Nexus is not responsible for this however. That is typically something you'll do with
|
||||
* e.g. [Mercurius](https://mercurius.dev) or [Apollo
|
||||
* Server](https://apollographql.com/docs/apollo-server/api/apollo-server).
|
||||
*
|
||||
* Note that the type here will be whatever you have specified for "contextType" in your makeSchema
|
||||
* configuration.
|
||||
* Note that the type here will be whatever you have specified for "contextType" in your makeSchema
|
||||
* configuration.
|
||||
* @param info The GraphQL resolve info.
|
||||
*
|
||||
* This is an advanced parameter seldom used. It includes things like the AST of the [GraphQL
|
||||
* document](https://spec.graphql.org/June2018/#sec-Language.Document) sent by the client.
|
||||
* This is an advanced parameter seldom used. It includes things like the AST of the [GraphQL
|
||||
* document](https://spec.graphql.org/June2018/#sec-Language.Document) sent by the client.
|
||||
* @returns A boolean indicating if the received source data is of this type or not.
|
||||
*/
|
||||
isTypeOf?: IsTypeOfHandler<TypeName>
|
||||
|
|
@ -200,24 +201,24 @@ export type MaybeTypeDefConfigFieldIsTypeOf<TypeName extends string> =
|
|||
* })
|
||||
*
|
||||
* @param source The [source data](https://nxs.li/guides/source-types) for the GraphQL objects that
|
||||
* are members of the abstract types that this type is a member of. For example for some type A in
|
||||
* two union types whose members are A,B.C and A,D,E respectively then isTypeOf method for A would
|
||||
* receive source data from A, B, C, D, & E at runtime.
|
||||
* are members of the abstract types that this type is a member of. For example for some type A
|
||||
* in two union types whose members are A,B.C and A,D,E respectively then isTypeOf method for A
|
||||
* would receive source data from A, B, C, D, & E at runtime.
|
||||
* @param context The context data for this request.
|
||||
*
|
||||
* The context data is typically a singleton scoped to the lifecycle of the request. This means
|
||||
* created at the beginning of a request and then passed to all the resolvers that execute while
|
||||
* resolving the request. It is often used to store information like the current user making the
|
||||
* request. Nexus is not responsible for this however. That is typically something you'll do with
|
||||
* e.g. [Mercurius](https://mercurius.dev) or [Apollo
|
||||
* Server](https://apollographql.com/docs/apollo-server/api/apollo-server).
|
||||
* The context data is typically a singleton scoped to the lifecycle of the request. This means
|
||||
* created at the beginning of a request and then passed to all the resolvers that execute while
|
||||
* resolving the request. It is often used to store information like the current user making the
|
||||
* request. Nexus is not responsible for this however. That is typically something you'll do with
|
||||
* e.g. [Mercurius](https://mercurius.dev) or [Apollo
|
||||
* Server](https://apollographql.com/docs/apollo-server/api/apollo-server).
|
||||
*
|
||||
* Note that the type here will be whatever you have specified for "contextType" in your makeSchema
|
||||
* configuration.
|
||||
* Note that the type here will be whatever you have specified for "contextType" in your makeSchema
|
||||
* configuration.
|
||||
* @param info The GraphQL resolve info.
|
||||
*
|
||||
* This is an advanced parameter seldom used. It includes things like the AST of the [GraphQL
|
||||
* document](https://spec.graphql.org/June2018/#sec-Language.Document) sent by the client.
|
||||
* This is an advanced parameter seldom used. It includes things like the AST of the [GraphQL
|
||||
* document](https://spec.graphql.org/June2018/#sec-Language.Document) sent by the client.
|
||||
* @returns A boolean indicating if the received source data is of this type or not.
|
||||
*/
|
||||
isTypeOf?: IsTypeOfHandler<TypeName>
|
||||
|
|
@ -278,24 +279,24 @@ export type MaybeTypeDefConfigFieldIsTypeOf<TypeName extends string> =
|
|||
* })
|
||||
*
|
||||
* @param source The [source data](https://nxs.li/guides/source-types) for the GraphQL objects that
|
||||
* are members of the abstract types that this type is a member of. For example for some type A in
|
||||
* two union types whose members are A,B.C and A,D,E respectively then isTypeOf method for A would
|
||||
* receive source data from A, B, C, D, & E at runtime.
|
||||
* are members of the abstract types that this type is a member of. For example for some type A
|
||||
* in two union types whose members are A,B.C and A,D,E respectively then isTypeOf method for A
|
||||
* would receive source data from A, B, C, D, & E at runtime.
|
||||
* @param context The context data for this request.
|
||||
*
|
||||
* The context data is typically a singleton scoped to the lifecycle of the request. This means
|
||||
* created at the beginning of a request and then passed to all the resolvers that execute while
|
||||
* resolving the request. It is often used to store information like the current user making the
|
||||
* request. Nexus is not responsible for this however. That is typically something you'll do with
|
||||
* e.g. [Mercurius](https://mercurius.dev) or [Apollo
|
||||
* Server](https://apollographql.com/docs/apollo-server/api/apollo-server).
|
||||
* The context data is typically a singleton scoped to the lifecycle of the request. This means
|
||||
* created at the beginning of a request and then passed to all the resolvers that execute while
|
||||
* resolving the request. It is often used to store information like the current user making the
|
||||
* request. Nexus is not responsible for this however. That is typically something you'll do with
|
||||
* e.g. [Mercurius](https://mercurius.dev) or [Apollo
|
||||
* Server](https://apollographql.com/docs/apollo-server/api/apollo-server).
|
||||
*
|
||||
* Note that the type here will be whatever you have specified for "contextType" in your makeSchema
|
||||
* configuration.
|
||||
* Note that the type here will be whatever you have specified for "contextType" in your makeSchema
|
||||
* configuration.
|
||||
* @param info The GraphQL resolve info.
|
||||
*
|
||||
* This is an advanced parameter seldom used. It includes things like the AST of the [GraphQL
|
||||
* document](https://spec.graphql.org/June2018/#sec-Language.Document) sent by the client.
|
||||
* This is an advanced parameter seldom used. It includes things like the AST of the [GraphQL
|
||||
* document](https://spec.graphql.org/June2018/#sec-Language.Document) sent by the client.
|
||||
* @returns A boolean indicating if the received source data is of this type or not.
|
||||
*/
|
||||
isTypeOf?: IsTypeOfHandler<TypeName>
|
||||
|
|
@ -346,24 +347,24 @@ export type MaybeTypeDefConfigFieldIsTypeOf<TypeName extends string> =
|
|||
* })
|
||||
*
|
||||
* @param source The [source data](https://nxs.li/guides/source-types) for the GraphQL objects that
|
||||
* are members of the abstract types that this type is a member of. For example for some type A in
|
||||
* two union types whose members are A,B.C and A,D,E respectively then isTypeOf method for A would
|
||||
* receive source data from A, B, C, D, & E at runtime.
|
||||
* are members of the abstract types that this type is a member of. For example for some type A
|
||||
* in two union types whose members are A,B.C and A,D,E respectively then isTypeOf method for A
|
||||
* would receive source data from A, B, C, D, & E at runtime.
|
||||
* @param context The context data for this request.
|
||||
*
|
||||
* The context data is typically a singleton scoped to the lifecycle of the request. This means
|
||||
* created at the beginning of a request and then passed to all the resolvers that execute while
|
||||
* resolving the request. It is often used to store information like the current user making the
|
||||
* request. Nexus is not responsible for this however. That is typically something you'll do with
|
||||
* e.g. [Mercurius](https://mercurius.dev) or [Apollo
|
||||
* Server](https://apollographql.com/docs/apollo-server/api/apollo-server).
|
||||
* The context data is typically a singleton scoped to the lifecycle of the request. This means
|
||||
* created at the beginning of a request and then passed to all the resolvers that execute while
|
||||
* resolving the request. It is often used to store information like the current user making the
|
||||
* request. Nexus is not responsible for this however. That is typically something you'll do with
|
||||
* e.g. [Mercurius](https://mercurius.dev) or [Apollo
|
||||
* Server](https://apollographql.com/docs/apollo-server/api/apollo-server).
|
||||
*
|
||||
* Note that the type here will be whatever you have specified for "contextType" in your makeSchema
|
||||
* configuration.
|
||||
* Note that the type here will be whatever you have specified for "contextType" in your makeSchema
|
||||
* configuration.
|
||||
* @param info The GraphQL resolve info.
|
||||
*
|
||||
* This is an advanced parameter seldom used. It includes things like the AST of the [GraphQL
|
||||
* document](https://spec.graphql.org/June2018/#sec-Language.Document) sent by the client.
|
||||
* This is an advanced parameter seldom used. It includes things like the AST of the [GraphQL
|
||||
* document](https://spec.graphql.org/June2018/#sec-Language.Document) sent by the client.
|
||||
* @returns A boolean indicating if the received source data is of this type or not.
|
||||
*/
|
||||
isTypeOf: IsTypeOfHandler<TypeName>
|
||||
|
|
@ -373,7 +374,7 @@ export type MaybeTypeDefConfigFieldIsTypeOf<TypeName extends string> =
|
|||
* Get an object with the `resolveType` field if applicable for the given abstract Type.
|
||||
*
|
||||
* @remarks
|
||||
* Intersect the result of this with other things to build up the final options for a type def.
|
||||
* Intersect the result of this with other things to build up the final options for a type def.
|
||||
*/
|
||||
export type MaybeTypeDefConfigFieldResolveType<TypeName extends string> = IsFeatureEnabled2<
|
||||
'abstractTypeStrategies',
|
||||
|
|
@ -389,7 +390,7 @@ export type MaybeTypeDefConfigFieldResolveType<TypeName extends string> = IsFeat
|
|||
* implementation will first look for __typename, then fallback to calling `isTypeOf` on each
|
||||
* implementing Object type.
|
||||
*/
|
||||
resolveType?: AbstractTypeResolver<TypeName>
|
||||
resolveType?: Maybe<AbstractTypeResolver<TypeName>>
|
||||
} // Make resolveType optional when __typename strategy is enabled
|
||||
: IsFeatureEnabled2<'abstractTypeStrategies', '__typename'> extends true
|
||||
? {
|
||||
|
|
@ -400,7 +401,7 @@ export type MaybeTypeDefConfigFieldResolveType<TypeName extends string> = IsFeat
|
|||
* implementation will first look for __typename, then fallback to calling `isTypeOf` on each
|
||||
* implementing Object type.
|
||||
*/
|
||||
resolveType?: AbstractTypeResolver<TypeName>
|
||||
resolveType?: Maybe<AbstractTypeResolver<TypeName>>
|
||||
}
|
||||
: {
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import { GraphQLNamedType, GraphQLSchema, isOutputType } from 'graphql'
|
||||
import * as path from 'path'
|
||||
import type { TypegenInfo } from './builder'
|
||||
import type { TypingImport } from './definitions/_types'
|
||||
import { TYPEGEN_HEADER } from './lang'
|
||||
import { nodeImports } from './node'
|
||||
import { getOwnPackage, log, objValues, relativePathTo, typeScriptFileExtension } from './utils'
|
||||
|
||||
/** Any common types / constants that would otherwise be circular-imported */
|
||||
|
|
@ -129,16 +129,12 @@ export function typegenAutoConfig(options: SourceTypesConfigOptions, contextType
|
|||
}
|
||||
})
|
||||
|
||||
const path = nodeImports().path
|
||||
const typeSources = await Promise.all(
|
||||
options.modules.map(async (source) => {
|
||||
// Keeping all of this in here so if we don't have any sources
|
||||
// e.g. in the Playground, it doesn't break things.
|
||||
|
||||
// Yeah, this doesn't exist in Node 6, but since this is a new
|
||||
// lib and Node 6 is close to EOL so if you really need it, open a PR :)
|
||||
const fs = require('fs') as typeof import('fs')
|
||||
const util = require('util') as typeof import('util')
|
||||
const readFile = util.promisify(fs.readFile)
|
||||
const { module: pathOrModule, glob = true, onlyTypes, alias, typeMatch } = source
|
||||
if (path.isAbsolute(pathOrModule) && path.extname(pathOrModule) !== '.ts') {
|
||||
return console.warn(
|
||||
|
|
@ -154,7 +150,7 @@ export function typegenAutoConfig(options: SourceTypesConfigOptions, contextType
|
|||
if (path.extname(resolvedPath) !== '.ts') {
|
||||
resolvedPath = findTypingForFile(resolvedPath, pathOrModule)
|
||||
}
|
||||
fileContents = await readFile(resolvedPath, 'utf-8')
|
||||
fileContents = String(await nodeImports().fs.promises.readFile(resolvedPath, 'utf-8'))
|
||||
} catch (e) {
|
||||
if (e instanceof Error && e.message.indexOf('Cannot find module') !== -1) {
|
||||
console.error(`GraphQL Nexus: Unable to find file or module ${pathOrModule}, skipping`)
|
||||
|
|
@ -194,7 +190,7 @@ export function typegenAutoConfig(options: SourceTypesConfigOptions, contextType
|
|||
const builtinScalars = new Set(Object.keys(SCALAR_TYPES))
|
||||
|
||||
Object.keys(typeMap).forEach((typeName) => {
|
||||
if (typeName.indexOf('__') === 0) {
|
||||
if (typeName.startsWith('__')) {
|
||||
return
|
||||
}
|
||||
if (typesToIgnore.has(typeName)) {
|
||||
|
|
@ -277,7 +273,7 @@ export function typegenAutoConfig(options: SourceTypesConfigOptions, contextType
|
|||
function findTypingForFile(absolutePath: string, pathOrModule: string) {
|
||||
// First try to find the "d.ts" adjacent to the file
|
||||
try {
|
||||
const typeDefPath = absolutePath.replace(path.extname(absolutePath), '.d.ts')
|
||||
const typeDefPath = absolutePath.replace(nodeImports().path.extname(absolutePath), '.d.ts')
|
||||
require.resolve(typeDefPath)
|
||||
return typeDefPath
|
||||
} catch (e) {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import * as path from 'path'
|
||||
import type * as Prettier from 'prettier'
|
||||
import { nodeImports } from './node'
|
||||
|
||||
export type TypegenFormatFn = (content: string, type: 'types' | 'schema') => string | Promise<string>
|
||||
|
||||
|
|
@ -22,6 +22,8 @@ export function typegenFormatPrettier(prettierConfig: string | object): TypegenF
|
|||
|
||||
let prettierConfigResolved: Prettier.Options
|
||||
|
||||
const path = nodeImports().path
|
||||
|
||||
if (typeof prettierConfig === 'string') {
|
||||
/* istanbul ignore if */
|
||||
if (!path.isAbsolute(prettierConfig)) {
|
||||
|
|
|
|||
|
|
@ -1,10 +1,12 @@
|
|||
import { GraphQLSchema, lexicographicSortSchema, printSchema } from 'graphql'
|
||||
import * as path from 'path'
|
||||
import { GraphQLSchema, lexicographicSortSchema } from 'graphql'
|
||||
import type { BuilderConfigInput, TypegenInfo } from './builder'
|
||||
import type { ConfiguredTypegen } from './core'
|
||||
import type { NexusGraphQLSchema } from './definitions/_types'
|
||||
import { SDL_HEADER, TYPEGEN_HEADER } from './lang'
|
||||
import { nodeImports } from './node'
|
||||
import { printSchemaWithDirectives } from './printSchemaWithDirectives'
|
||||
import { typegenAutoConfig } from './typegenAutoConfig'
|
||||
import { TypegenFormatFn, typegenFormatPrettier } from './typegenFormatPrettier'
|
||||
import { typegenFormatPrettier } from './typegenFormatPrettier'
|
||||
import { TypegenPrinter } from './typegenPrinter'
|
||||
|
||||
export interface TypegenMetadataConfig
|
||||
|
|
@ -12,7 +14,7 @@ export interface TypegenMetadataConfig
|
|||
nexusSchemaImportId?: string
|
||||
outputs: {
|
||||
schema: null | string
|
||||
typegen: null | string
|
||||
typegen: null | ConfiguredTypegen
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -26,26 +28,42 @@ export class TypegenMetadata {
|
|||
/** Generates the artifacts of the build based on what we know about the schema and how it was defined. */
|
||||
async generateArtifacts(schema: NexusGraphQLSchema) {
|
||||
const sortedSchema = this.sortSchema(schema)
|
||||
if (this.config.outputs.schema || this.config.outputs.typegen) {
|
||||
const { schemaTypes, tsTypes } = await this.generateArtifactContents(
|
||||
sortedSchema,
|
||||
this.config.outputs.typegen
|
||||
)
|
||||
const { typegen } = this.config.outputs
|
||||
if (this.config.outputs.schema || typegen) {
|
||||
const { schemaTypes, tsTypes, globalTypes } = await this.generateArtifactContents(sortedSchema, typegen)
|
||||
if (this.config.outputs.schema) {
|
||||
await this.writeFile('schema', schemaTypes, this.config.outputs.schema)
|
||||
}
|
||||
if (this.config.outputs.typegen) {
|
||||
await this.writeFile('types', tsTypes, this.config.outputs.typegen)
|
||||
if (typegen) {
|
||||
if (typeof typegen === 'string') {
|
||||
await this.writeFile('types', tsTypes, typegen)
|
||||
} else {
|
||||
await this.writeFile('types', tsTypes, typegen.outputPath)
|
||||
if (typeof typegen.globalsPath === 'string') {
|
||||
await this.writeFile('types', globalTypes ?? '', typegen.globalsPath)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async generateArtifactContents(schema: NexusGraphQLSchema, typeFilePath: string | null) {
|
||||
const [schemaTypes, tsTypes] = await Promise.all([
|
||||
this.generateSchemaFile(schema),
|
||||
typeFilePath ? this.generateTypesFile(schema, typeFilePath) : '',
|
||||
])
|
||||
return { schemaTypes, tsTypes }
|
||||
async generateArtifactContents(schema: NexusGraphQLSchema, typegen: string | null | ConfiguredTypegen) {
|
||||
const result = {
|
||||
schemaTypes: this.generateSchemaFile(schema),
|
||||
tsTypes: '',
|
||||
globalTypes: null as null | string,
|
||||
}
|
||||
if (!typegen) {
|
||||
return result
|
||||
}
|
||||
if (typeof typegen === 'string') {
|
||||
result.tsTypes = await this.generateTypesFile(schema, typegen)
|
||||
} else {
|
||||
const generateResult = await this.generateConfiguredTypes(schema, typegen)
|
||||
result.tsTypes = generateResult.tsTypes
|
||||
result.globalTypes = generateResult.globalTypes
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
sortSchema(schema: NexusGraphQLSchema) {
|
||||
|
|
@ -57,31 +75,26 @@ export class TypegenMetadata {
|
|||
}
|
||||
|
||||
async writeFile(type: 'schema' | 'types', output: string, filePath: string) {
|
||||
if (typeof filePath !== 'string' || !path.isAbsolute(filePath)) {
|
||||
if (typeof filePath !== 'string' || !nodeImports().path.isAbsolute(filePath)) {
|
||||
return Promise.reject(
|
||||
new Error(`Expected an absolute path to output the Nexus ${type}, saw ${filePath}`)
|
||||
)
|
||||
}
|
||||
const fs = require('fs') as typeof import('fs')
|
||||
const util = require('util') as typeof import('util')
|
||||
const [readFile, writeFile, removeFile, mkdir] = [
|
||||
util.promisify(fs.readFile),
|
||||
util.promisify(fs.writeFile),
|
||||
util.promisify(fs.unlink),
|
||||
util.promisify(fs.mkdir),
|
||||
]
|
||||
let formatTypegen: TypegenFormatFn | null = null
|
||||
if (typeof this.config.formatTypegen === 'function') {
|
||||
formatTypegen = this.config.formatTypegen
|
||||
} else if (this.config.prettierConfig) {
|
||||
formatTypegen = typegenFormatPrettier(this.config.prettierConfig)
|
||||
}
|
||||
const content = typeof formatTypegen === 'function' ? await formatTypegen(output, type) : output
|
||||
const [toSave, existing] = await Promise.all([content, readFile(filePath, 'utf8').catch(() => '')])
|
||||
const fs = nodeImports().fs
|
||||
const formattedOutput =
|
||||
typeof this.config.formatTypegen === 'function' ? await this.config.formatTypegen(output, type) : output
|
||||
const content = this.config.prettierConfig
|
||||
? await typegenFormatPrettier(this.config.prettierConfig)(formattedOutput, type)
|
||||
: formattedOutput
|
||||
|
||||
const [toSave, existing] = await Promise.all([
|
||||
content,
|
||||
fs.promises.readFile(filePath, 'utf8').catch(() => ''),
|
||||
])
|
||||
if (toSave !== existing) {
|
||||
const dirPath = path.dirname(filePath)
|
||||
const dirPath = nodeImports().path.dirname(filePath)
|
||||
try {
|
||||
await mkdir(dirPath, { recursive: true })
|
||||
await fs.promises.mkdir(dirPath, { recursive: true })
|
||||
} catch (e) {
|
||||
if (e.code !== 'EEXIST') {
|
||||
throw e
|
||||
|
|
@ -91,14 +104,14 @@ export class TypegenMetadata {
|
|||
// apparently. See issue motivating this logic here:
|
||||
// https://github.com/graphql-nexus/schema/issues/247.
|
||||
try {
|
||||
await removeFile(filePath)
|
||||
await fs.promises.unlink(filePath)
|
||||
} catch (e) {
|
||||
/* istanbul ignore next */
|
||||
if (e.code !== 'ENOENT' && e.code !== 'ENOTDIR') {
|
||||
throw e
|
||||
}
|
||||
}
|
||||
return writeFile(filePath, toSave)
|
||||
return fs.promises.writeFile(filePath, toSave)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -106,7 +119,7 @@ export class TypegenMetadata {
|
|||
generateSchemaFile(schema: GraphQLSchema): string {
|
||||
let printedSchema = this.config.customPrintSchemaFn
|
||||
? this.config.customPrintSchemaFn(schema)
|
||||
: printSchema(schema)
|
||||
: printSchemaWithDirectives(schema)
|
||||
return [SDL_HEADER, printedSchema].join('\n\n')
|
||||
}
|
||||
|
||||
|
|
@ -115,11 +128,34 @@ export class TypegenMetadata {
|
|||
const typegenInfo = await this.getTypegenInfo(schema, typegenPath)
|
||||
|
||||
return new TypegenPrinter(schema, {
|
||||
declareInputs: false,
|
||||
useReadonlyArrayForInputs: false,
|
||||
...typegenInfo,
|
||||
typegenPath,
|
||||
}).print()
|
||||
}
|
||||
|
||||
/** Generates the type definitions */
|
||||
async generateConfiguredTypes(schema: NexusGraphQLSchema, typegen: ConfiguredTypegen) {
|
||||
const {
|
||||
outputPath: typegenPath,
|
||||
globalsPath,
|
||||
globalsHeaders,
|
||||
declareInputs = false,
|
||||
useReadonlyArrayForInputs = false,
|
||||
} = typegen
|
||||
const typegenInfo = await this.getTypegenInfo(schema, typegenPath)
|
||||
|
||||
return new TypegenPrinter(schema, {
|
||||
...typegenInfo,
|
||||
typegenPath,
|
||||
globalsPath,
|
||||
globalsHeaders,
|
||||
declareInputs,
|
||||
useReadonlyArrayForInputs,
|
||||
}).printConfigured()
|
||||
}
|
||||
|
||||
async getTypegenInfo(schema: GraphQLSchema, typegenPath?: string): Promise<TypegenInfo> {
|
||||
if ('typegenConfig' in this.config) {
|
||||
throw new Error(
|
||||
|
|
@ -130,7 +166,7 @@ export class TypegenMetadata {
|
|||
if (this.config.sourceTypes) {
|
||||
return typegenAutoConfig(this.config.sourceTypes, this.config.contextType)(
|
||||
schema,
|
||||
typegenPath || this.config.outputs.typegen || ''
|
||||
typegenPath || this.config.outputs.typegen?.outputPath || ''
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -18,13 +18,17 @@ import {
|
|||
isNonNullType,
|
||||
isObjectType,
|
||||
isScalarType,
|
||||
isSpecifiedDirective,
|
||||
isSpecifiedScalarType,
|
||||
isUnionType,
|
||||
} from 'graphql'
|
||||
import type { TypegenInfo } from './builder'
|
||||
import { SchemaDirectiveLocation } from './definitions/directive'
|
||||
import { isNexusPrintedGenTyping, isNexusPrintedGenTypingImport } from './definitions/wrapping'
|
||||
import type { NexusGraphQLSchema } from './definitions/_types'
|
||||
import { TYPEGEN_HEADER } from './lang'
|
||||
import type { StringLike } from './plugin'
|
||||
import { hasNexusExtension, isNexusFieldExtension } from './extensions'
|
||||
import {
|
||||
eachObj,
|
||||
getOwnPackage,
|
||||
|
|
@ -34,6 +38,7 @@ import {
|
|||
mapObj,
|
||||
mapValues,
|
||||
PrintedGenTypingImport,
|
||||
relativePathTo,
|
||||
resolveImportPath,
|
||||
} from './utils'
|
||||
|
||||
|
|
@ -52,23 +57,26 @@ type RootTypeMapping = Record<string, string | Record<string, [string, string]>>
|
|||
|
||||
interface TypegenInfoWithFile extends TypegenInfo {
|
||||
typegenPath: string
|
||||
globalsPath?: string
|
||||
globalsHeaders?: string[]
|
||||
declareInputs?: boolean
|
||||
useReadonlyArrayForInputs?: boolean
|
||||
}
|
||||
|
||||
/**
|
||||
* We track and output a few main things:
|
||||
*
|
||||
* 1. "root" types, or the values that fill the first argument for a given object type
|
||||
* 2. "arg" types, the values that are arguments to output fields.
|
||||
* 3. "return" types, the values returned from the resolvers... usually just list/nullable variations on the
|
||||
* "root" types for other types
|
||||
* 4. The names of all types, grouped by type.
|
||||
* 1. "root" types, or the values that fill the first argument for a given object type 2. "arg" types, the
|
||||
* values that are arguments to output fields. 3. "return" types, the values returned from the resolvers...
|
||||
* usually just list/nullable variations on the
|
||||
* "root" types for other types 4. The names of all types, grouped by type.
|
||||
*
|
||||
* - Non-scalar types will get a dedicated "Root" type associated with it
|
||||
*/
|
||||
export class TypegenPrinter {
|
||||
groupedTypes: GroupedTypes
|
||||
printImports: Record<string, Record<string, boolean | string>>
|
||||
hasDiscriminatedTypes: boolean
|
||||
private groupedTypes: GroupedTypes
|
||||
private printImports: Record<string, Record<string, boolean | string>>
|
||||
private hasDiscriminatedTypes: boolean
|
||||
|
||||
constructor(protected schema: NexusGraphQLSchema, protected typegenInfo: TypegenInfoWithFile) {
|
||||
this.groupedTypes = groupTypes(schema)
|
||||
|
|
@ -77,7 +85,33 @@ export class TypegenPrinter {
|
|||
}
|
||||
|
||||
print() {
|
||||
const body = [
|
||||
const body = [this.printCommon(), this.printPlugins()].join('\n\n')
|
||||
return [this.printHeaders(), body].join('\n\n')
|
||||
}
|
||||
|
||||
printConfigured() {
|
||||
if (this.typegenInfo.globalsPath) {
|
||||
const plugins = this.printPlugins()
|
||||
const globalTypes = [this.printHeadersGlobal(), this.printDynamicImport(true), plugins].join('\n\n')
|
||||
|
||||
// Reset printImports for the imports needed in the types
|
||||
this.printImports = {}
|
||||
|
||||
const common = this.printCommon()
|
||||
const tsTypes = [this.printHeadersCommon(), common].join('\n\n')
|
||||
return {
|
||||
tsTypes,
|
||||
globalTypes,
|
||||
}
|
||||
}
|
||||
return {
|
||||
tsTypes: this.print(),
|
||||
globalTypes: null,
|
||||
}
|
||||
}
|
||||
|
||||
private printCommon() {
|
||||
return [
|
||||
this.printInputTypeMap(),
|
||||
this.printEnumTypeMap(),
|
||||
this.printScalarTypeMap(),
|
||||
|
|
@ -97,35 +131,98 @@ export class TypegenPrinter {
|
|||
this.printTypeNames('interface', 'NexusGenInterfaceNames', 'NexusGenInterfaces'),
|
||||
this.printTypeNames('scalar', 'NexusGenScalarNames', 'NexusGenScalars'),
|
||||
this.printTypeNames('union', 'NexusGenUnionNames', 'NexusGenUnions'),
|
||||
this.printDirectives(),
|
||||
this.printIsTypeOfObjectTypeNames('NexusGenObjectsUsingAbstractStrategyIsTypeOf'),
|
||||
this.printResolveTypeAbstractTypes('NexusGenAbstractsUsingStrategyResolveType'),
|
||||
this.printFeaturesConfig('NexusGenFeaturesConfig'),
|
||||
this.printGenTypeMap(),
|
||||
this.printPlugins(),
|
||||
].join('\n\n')
|
||||
return [this.printHeaders(), body].join('\n\n')
|
||||
}
|
||||
|
||||
printHeaders() {
|
||||
const fieldDefs = [
|
||||
this.printDynamicInputFieldDefinitions(),
|
||||
this.printDynamicOutputFieldDefinitions(),
|
||||
this.printDynamicOutputPropertyDefinitions(),
|
||||
]
|
||||
private printHeaders() {
|
||||
return [this.printHeadersCommon(), this.printHeadersGlobal()].join('\n')
|
||||
}
|
||||
|
||||
private printHeadersCommon() {
|
||||
return [
|
||||
this.typegenInfo.headers.join('\n'),
|
||||
this.typegenInfo.imports.join('\n'),
|
||||
this.printDynamicImport(),
|
||||
...fieldDefs,
|
||||
GLOBAL_DECLARATION,
|
||||
].join('\n')
|
||||
}
|
||||
|
||||
printGenTypeMap() {
|
||||
private printDirectives() {
|
||||
const customDirectives = this.schema.getDirectives().filter((d) => !isSpecifiedDirective(d))
|
||||
const schemaDirectiveArgs: Record<string, readonly GraphQLArgument[] | undefined> = {}
|
||||
|
||||
// Gather the mappings between directives, locations, etc.
|
||||
customDirectives.forEach((d) => {
|
||||
d.locations.forEach((l) => {
|
||||
if (SchemaDirectiveLocation.includes(l as any)) {
|
||||
schemaDirectiveArgs[d.name] = d.args ?? undefined
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
const directiveNames = Object.keys(schemaDirectiveArgs)
|
||||
.map((i) => JSON.stringify(i))
|
||||
.join(' | ')
|
||||
|
||||
const toPrint: string[] = [`export type NexusGenDirectives = ${directiveNames || 'never'}`]
|
||||
|
||||
// Print the mappings of the directive names -> args
|
||||
// NexusGenDirectiveArgs
|
||||
let directiveArgs = [`export interface NexusGenDirectiveArgs {`]
|
||||
|
||||
eachObj(schemaDirectiveArgs, (val, key) => {
|
||||
if (val) {
|
||||
directiveArgs.push(` ${key}: {`)
|
||||
val.forEach((arg) => {
|
||||
const [sep, rep] = this.normalizeArg(arg)
|
||||
directiveArgs.push(` ${arg.name}${sep}${rep}`)
|
||||
})
|
||||
directiveArgs.push(` }`)
|
||||
} else {
|
||||
directiveArgs.push(` ${key}: never`)
|
||||
}
|
||||
})
|
||||
|
||||
directiveArgs.push('}')
|
||||
|
||||
toPrint.push(directiveArgs.join('\n'))
|
||||
|
||||
return toPrint.join('\n\n')
|
||||
}
|
||||
|
||||
private printHeadersGlobal() {
|
||||
const headers = [
|
||||
this.printDynamicInputFieldDefinitions(),
|
||||
this.printDynamicOutputFieldDefinitions(),
|
||||
this.printDynamicOutputPropertyDefinitions(),
|
||||
GLOBAL_DECLARATION,
|
||||
]
|
||||
|
||||
if (this.typegenInfo.globalsPath) {
|
||||
headers.unshift(
|
||||
`import type { NexusGenTypes } from '${relativePathTo(
|
||||
this.typegenInfo.typegenPath,
|
||||
this.typegenInfo.globalsPath ?? ''
|
||||
)}'`
|
||||
)
|
||||
headers.unshift(...(this.typegenInfo.globalsHeaders ?? []))
|
||||
headers.unshift(TYPEGEN_HEADER)
|
||||
}
|
||||
|
||||
return headers.join('\n')
|
||||
}
|
||||
|
||||
private printGenTypeMap() {
|
||||
return [`export interface NexusGenTypes {`]
|
||||
.concat([
|
||||
` context: ${this.printContext()};`,
|
||||
` inputTypes: NexusGenInputs;`,
|
||||
` directives: NexusGenDirectives;`,
|
||||
` directiveArgs: NexusGenDirectiveArgs;`,
|
||||
` rootTypes: NexusGenRootTypes;`,
|
||||
` inputTypeShapes: NexusGenInputs & NexusGenEnums & NexusGenScalars;`,
|
||||
` argTypes: NexusGenArgTypes;`,
|
||||
|
|
@ -152,11 +249,8 @@ export class TypegenPrinter {
|
|||
.join('\n')
|
||||
}
|
||||
|
||||
printDynamicImport() {
|
||||
const {
|
||||
rootTypings,
|
||||
dynamicFields: { dynamicInputFields, dynamicOutputFields },
|
||||
} = this.schema.extensions.nexus.config
|
||||
private printDynamicImport(forGlobal = false) {
|
||||
const { sourceTypings } = this.schema.extensions.nexus.config
|
||||
const { contextTypeImport } = this.typegenInfo
|
||||
const imports: string[] = []
|
||||
const importMap: Record<string, Set<string>> = {}
|
||||
|
|
@ -164,38 +258,33 @@ export class TypegenPrinter {
|
|||
const nexusSchemaImportId = this.typegenInfo.nexusSchemaImportId ?? getOwnPackage().name
|
||||
|
||||
if (!this.printImports[nexusSchemaImportId]) {
|
||||
if (
|
||||
[dynamicInputFields, dynamicOutputFields].some((o) => Object.keys(o).length > 0) ||
|
||||
this.hasDiscriminatedTypes === true
|
||||
) {
|
||||
this.printImports[nexusSchemaImportId] = {
|
||||
core: true,
|
||||
}
|
||||
}
|
||||
this.maybeAddCoreImport(forGlobal)
|
||||
}
|
||||
|
||||
if (contextTypeImport) {
|
||||
const importPath = resolveImportPath(contextTypeImport, 'context', outputPath)
|
||||
importMap[importPath] = importMap[importPath] || new Set()
|
||||
importMap[importPath].add(
|
||||
contextTypeImport.alias
|
||||
? `${contextTypeImport.export} as ${contextTypeImport.alias}`
|
||||
: contextTypeImport.export
|
||||
)
|
||||
}
|
||||
|
||||
eachObj(rootTypings, (rootType, typeName) => {
|
||||
if (typeof rootType !== 'string') {
|
||||
const importPath = resolveImportPath(rootType, typeName, outputPath)
|
||||
if (!forGlobal) {
|
||||
if (contextTypeImport) {
|
||||
const importPath = resolveImportPath(contextTypeImport, 'context', outputPath)
|
||||
importMap[importPath] = importMap[importPath] || new Set()
|
||||
importMap[importPath].add(
|
||||
rootType.alias ? `${rootType.export} as ${rootType.alias}` : rootType.export
|
||||
contextTypeImport.alias
|
||||
? `${contextTypeImport.export} as ${contextTypeImport.alias}`
|
||||
: contextTypeImport.export
|
||||
)
|
||||
}
|
||||
})
|
||||
eachObj(importMap, (val, key) => {
|
||||
imports.push(`import type { ${Array.from(val).join(', ')} } from ${JSON.stringify(key)}`)
|
||||
})
|
||||
eachObj(sourceTypings, (rootType, typeName) => {
|
||||
if (typeof rootType !== 'string') {
|
||||
const importPath = resolveImportPath(rootType, typeName, outputPath)
|
||||
importMap[importPath] = importMap[importPath] || new Set()
|
||||
importMap[importPath].add(
|
||||
rootType.alias ? `${rootType.export} as ${rootType.alias}` : rootType.export
|
||||
)
|
||||
}
|
||||
})
|
||||
eachObj(importMap, (val, key) => {
|
||||
imports.push(`import type { ${Array.from(val).join(', ')} } from ${JSON.stringify(key)}`)
|
||||
})
|
||||
}
|
||||
|
||||
eachObj(this.printImports, (val, key) => {
|
||||
const { default: def, ...rest } = val
|
||||
const idents = []
|
||||
|
|
@ -214,7 +303,29 @@ export class TypegenPrinter {
|
|||
return imports.join('\n')
|
||||
}
|
||||
|
||||
printDynamicInputFieldDefinitions() {
|
||||
private maybeAddCoreImport(forGlobal = false) {
|
||||
const nexusSchemaImportId = this.typegenInfo.nexusSchemaImportId ?? getOwnPackage().name
|
||||
const {
|
||||
dynamicFields: { dynamicInputFields, dynamicOutputFields },
|
||||
} = this.schema.extensions.nexus.config
|
||||
|
||||
let shouldAdd = false
|
||||
const hasDynamicFields = [dynamicInputFields, dynamicOutputFields].some((o) => Object.keys(o).length > 0)
|
||||
|
||||
if (!this.typegenInfo.globalsPath) {
|
||||
shouldAdd = hasDynamicFields || this.hasDiscriminatedTypes
|
||||
} else {
|
||||
shouldAdd = forGlobal ? hasDynamicFields : this.hasDiscriminatedTypes
|
||||
}
|
||||
|
||||
if (shouldAdd) {
|
||||
this.printImports[nexusSchemaImportId] = {
|
||||
core: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private printDynamicInputFieldDefinitions() {
|
||||
const { dynamicInputFields } = this.schema.extensions.nexus.config.dynamicFields
|
||||
// If there is nothing custom... exit
|
||||
if (!Object.keys(dynamicInputFields).length) {
|
||||
|
|
@ -242,7 +353,7 @@ export class TypegenPrinter {
|
|||
.join('\n')
|
||||
}
|
||||
|
||||
printDynamicOutputFieldDefinitions() {
|
||||
private printDynamicOutputFieldDefinitions() {
|
||||
const { dynamicOutputFields } = this.schema.extensions.nexus.config.dynamicFields
|
||||
// If there is nothing custom... exit
|
||||
if (!Object.keys(dynamicOutputFields).length) {
|
||||
|
|
@ -270,7 +381,7 @@ export class TypegenPrinter {
|
|||
.join('\n')
|
||||
}
|
||||
|
||||
prependDoc(typeDef: string, typeDescription?: string | null) {
|
||||
private prependDoc(typeDef: string, typeDescription?: string | null) {
|
||||
let outStr = ''
|
||||
if (typeDescription) {
|
||||
let parts = typeDescription.split('\n').map((f) => f.trimLeft())
|
||||
|
|
@ -285,7 +396,7 @@ export class TypegenPrinter {
|
|||
return `${outStr}${typeDef}`
|
||||
}
|
||||
|
||||
printDynamicOutputPropertyDefinitions() {
|
||||
private printDynamicOutputPropertyDefinitions() {
|
||||
const { dynamicOutputProperties } = this.schema.extensions.nexus.config.dynamicFields
|
||||
// If there is nothing custom... exit
|
||||
if (!Object.keys(dynamicOutputProperties).length) {
|
||||
|
|
@ -304,9 +415,9 @@ export class TypegenPrinter {
|
|||
.join('\n')
|
||||
}
|
||||
|
||||
printInheritedFieldMap() {
|
||||
private printInheritedFieldMap() {
|
||||
const hasInterfaces: (
|
||||
| (GraphQLInterfaceType & { getInterfaces(): GraphQLInterfaceType[] })
|
||||
| (GraphQLInterfaceType & { getInterfaces(): ReadonlyArray<GraphQLInterfaceType> })
|
||||
| GraphQLObjectType
|
||||
)[] = []
|
||||
const withInterfaces = hasInterfaces
|
||||
|
|
@ -329,37 +440,15 @@ export class TypegenPrinter {
|
|||
.join('\n')
|
||||
}
|
||||
|
||||
printContext() {
|
||||
private printContext() {
|
||||
return this.typegenInfo.contextTypeImport?.alias || this.typegenInfo.contextTypeImport?.export || 'any'
|
||||
}
|
||||
|
||||
buildResolveSourceTypeMap() {
|
||||
const sourceMap: TypeMapping = {}
|
||||
const abstractTypes: (GraphQLInterfaceType | GraphQLUnionType)[] = []
|
||||
abstractTypes
|
||||
.concat(this.groupedTypes.union)
|
||||
.concat(this.groupedTypes.interface)
|
||||
.forEach((type) => {
|
||||
if (isInterfaceType(type)) {
|
||||
const possibleNames = this.schema.getPossibleTypes(type).map((t) => t.name)
|
||||
if (possibleNames.length > 0) {
|
||||
sourceMap[type.name] = possibleNames.map((val) => `NexusGenRootTypes['${val}']`).join(' | ')
|
||||
}
|
||||
} else {
|
||||
sourceMap[type.name] = type
|
||||
.getTypes()
|
||||
.map((t) => `NexusGenRootTypes['${t.name}']`)
|
||||
.join(' | ')
|
||||
}
|
||||
})
|
||||
return sourceMap
|
||||
}
|
||||
|
||||
printAbstractTypeMembers() {
|
||||
private printAbstractTypeMembers() {
|
||||
return this.printTypeInterface('NexusGenAbstractTypeMembers', this.buildAbstractTypeMembers())
|
||||
}
|
||||
|
||||
buildAbstractTypeMembers() {
|
||||
private buildAbstractTypeMembers() {
|
||||
const sourceMap: TypeMapping = {}
|
||||
const abstractTypes: (GraphQLInterfaceType | GraphQLUnionType)[] = []
|
||||
abstractTypes
|
||||
|
|
@ -381,13 +470,13 @@ export class TypegenPrinter {
|
|||
return sourceMap
|
||||
}
|
||||
|
||||
printTypeNames(name: keyof GroupedTypes, exportName: string, source: string) {
|
||||
private printTypeNames(name: keyof GroupedTypes, exportName: string, source: string) {
|
||||
const obj = this.groupedTypes[name] as GraphQLNamedType[]
|
||||
const typeDef = obj.length === 0 ? 'never' : `keyof ${source}`
|
||||
return `export type ${exportName} = ${typeDef};`
|
||||
}
|
||||
|
||||
printIsTypeOfObjectTypeNames(exportName: string) {
|
||||
private printIsTypeOfObjectTypeNames(exportName: string) {
|
||||
const objectTypes = this.groupedTypes.object.filter((o) => o.isTypeOf !== undefined)
|
||||
const typeDef =
|
||||
objectTypes.length === 0
|
||||
|
|
@ -399,7 +488,7 @@ export class TypegenPrinter {
|
|||
return `export type ${exportName} = ${typeDef};`
|
||||
}
|
||||
|
||||
printResolveTypeAbstractTypes(exportName: string) {
|
||||
private printResolveTypeAbstractTypes(exportName: string) {
|
||||
const abstractTypes = [...this.groupedTypes.interface, ...this.groupedTypes.union].filter(
|
||||
(o) => o.resolveType !== undefined
|
||||
)
|
||||
|
|
@ -414,7 +503,7 @@ export class TypegenPrinter {
|
|||
return `export type ${exportName} = ${typeDef};`
|
||||
}
|
||||
|
||||
printFeaturesConfig(exportName: string) {
|
||||
private printFeaturesConfig(exportName: string) {
|
||||
const abstractTypes = this.schema.extensions.nexus.config.features?.abstractTypeStrategies ?? {}
|
||||
const unionProps = renderObject(mapValues(abstractTypes, (val) => val ?? false))
|
||||
|
||||
|
|
@ -424,7 +513,7 @@ export class TypegenPrinter {
|
|||
.join('\n')
|
||||
}
|
||||
|
||||
buildEnumTypeMap() {
|
||||
private buildEnumTypeMap() {
|
||||
const enumMap: TypeMapping = {}
|
||||
this.groupedTypes.enum.forEach((e) => {
|
||||
const sourceType = this.resolveSourceType(e.name)
|
||||
|
|
@ -438,7 +527,7 @@ export class TypegenPrinter {
|
|||
return enumMap
|
||||
}
|
||||
|
||||
buildInputTypeMap() {
|
||||
private buildInputTypeMap() {
|
||||
const inputObjMap: TypeFieldMapping = {}
|
||||
this.groupedTypes.input.forEach((input) => {
|
||||
eachObj(input.getFields(), (field) => {
|
||||
|
|
@ -449,7 +538,7 @@ export class TypegenPrinter {
|
|||
return inputObjMap
|
||||
}
|
||||
|
||||
buildScalarTypeMap() {
|
||||
private buildScalarTypeMap() {
|
||||
const scalarMap: TypeMapping = {}
|
||||
this.groupedTypes.scalar.forEach((e) => {
|
||||
if (isSpecifiedScalarType(e)) {
|
||||
|
|
@ -466,19 +555,37 @@ export class TypegenPrinter {
|
|||
return scalarMap
|
||||
}
|
||||
|
||||
printInputTypeMap() {
|
||||
return this.printTypeFieldInterface('NexusGenInputs', this.buildInputTypeMap(), 'input type')
|
||||
private printInputTypeMap() {
|
||||
const inputTypeMap = this.buildInputTypeMap()
|
||||
|
||||
if (this.typegenInfo.declareInputs) {
|
||||
const declaredInputs: string[] = mapObj(inputTypeMap, (fields, inputName) =>
|
||||
this.printNamedObj(inputName, fields)
|
||||
)
|
||||
return [...declaredInputs, this.printNamedMap('NexusGenInputs', inputTypeMap)].join('\n\n')
|
||||
}
|
||||
|
||||
return this.printTypeFieldInterface('NexusGenInputs', inputTypeMap, 'input type')
|
||||
}
|
||||
|
||||
printEnumTypeMap() {
|
||||
return this.printTypeInterface('NexusGenEnums', this.buildEnumTypeMap())
|
||||
private printEnumTypeMap() {
|
||||
const enumTypeMap = this.buildEnumTypeMap()
|
||||
|
||||
if (this.typegenInfo.declareInputs) {
|
||||
return [
|
||||
...mapObj(enumTypeMap, (val, name) => `export type ${name} = ${val}`),
|
||||
this.printNamedMap('NexusGenEnums', enumTypeMap),
|
||||
].join('\n\n')
|
||||
}
|
||||
|
||||
return this.printTypeInterface('NexusGenEnums', enumTypeMap)
|
||||
}
|
||||
|
||||
printScalarTypeMap() {
|
||||
private printScalarTypeMap() {
|
||||
return this.printTypeInterface('NexusGenScalars', this.buildScalarTypeMap())
|
||||
}
|
||||
|
||||
shouldDiscriminateType(
|
||||
private shouldDiscriminateType(
|
||||
abstractType: GraphQLAbstractType,
|
||||
objectType: GraphQLObjectType
|
||||
): 'required' | 'optional' | false {
|
||||
|
|
@ -497,7 +604,7 @@ export class TypegenPrinter {
|
|||
return 'required'
|
||||
}
|
||||
|
||||
maybeDiscriminate(abstractType: GraphQLAbstractType, objectType: GraphQLObjectType) {
|
||||
private maybeDiscriminate(abstractType: GraphQLAbstractType, objectType: GraphQLObjectType) {
|
||||
const requiredOrOptional = this.shouldDiscriminateType(abstractType, objectType)
|
||||
|
||||
if (requiredOrOptional === false) {
|
||||
|
|
@ -509,7 +616,7 @@ export class TypegenPrinter {
|
|||
return `core.Discriminate<'${objectType.name}', '${requiredOrOptional}'>`
|
||||
}
|
||||
|
||||
buildRootTypeMap(hasFields: Array<GraphQLInterfaceType | GraphQLObjectType | GraphQLUnionType>) {
|
||||
private buildRootTypeMap(hasFields: Array<GraphQLInterfaceType | GraphQLObjectType | GraphQLUnionType>) {
|
||||
const rootTypeMap: RootTypeMapping = {}
|
||||
hasFields.forEach((type) => {
|
||||
const rootTyping = this.resolveSourceType(type.name)
|
||||
|
|
@ -534,8 +641,17 @@ export class TypegenPrinter {
|
|||
} else {
|
||||
eachObj(type.getFields(), (field) => {
|
||||
const obj = (rootTypeMap[type.name] = rootTypeMap[type.name] || {})
|
||||
if (!this.hasResolver(field, type)) {
|
||||
if (typeof obj !== 'string') {
|
||||
const fieldSourceType = this.fieldSourceType(field, type)
|
||||
if (typeof obj !== 'string') {
|
||||
if (Array.isArray(fieldSourceType)) {
|
||||
for (const field of fieldSourceType) {
|
||||
obj[field.name] = [field.optional ? '?:' : ':', field.type]
|
||||
}
|
||||
} else if (typeof fieldSourceType === 'object') {
|
||||
obj[field.name] = [fieldSourceType.optional ? '?:' : ':', fieldSourceType.type]
|
||||
} else if (fieldSourceType) {
|
||||
obj[field.name] = [':', fieldSourceType]
|
||||
} else if (!this.hasResolver(field, type)) {
|
||||
obj[field.name] = [
|
||||
this.argSeparator(field.type as GraphQLInputType, false),
|
||||
this.printOutputType(field.type),
|
||||
|
|
@ -548,44 +664,55 @@ export class TypegenPrinter {
|
|||
return rootTypeMap
|
||||
}
|
||||
|
||||
resolveSourceType(typeName: string): string | undefined {
|
||||
const rootTyping = this.schema.extensions.nexus.config.rootTypings[typeName]
|
||||
private resolveSourceType(typeName: string): string | undefined {
|
||||
const rootTyping = this.schema.extensions.nexus.config.sourceTypings[typeName]
|
||||
if (rootTyping) {
|
||||
return typeof rootTyping === 'string' ? rootTyping : rootTyping.export
|
||||
}
|
||||
return (this.typegenInfo.sourceTypeMap as any)[typeName]
|
||||
}
|
||||
|
||||
hasResolver(
|
||||
private fieldSourceType(
|
||||
field: GraphQLField<any, any>,
|
||||
// Used in test mocking
|
||||
_type: GraphQLObjectType
|
||||
) {
|
||||
if (field.extensions && field.extensions.nexus) {
|
||||
if (field.extensions && isNexusFieldExtension(field.extensions.nexus)) {
|
||||
return field.extensions.nexus.sourceType
|
||||
}
|
||||
return undefined
|
||||
}
|
||||
|
||||
private hasResolver(
|
||||
field: GraphQLField<any, any>,
|
||||
// Used in test mocking
|
||||
_type: GraphQLObjectType
|
||||
) {
|
||||
if (field.extensions && hasNexusExtension(field.extensions.nexus)) {
|
||||
return field.extensions.nexus.hasDefinedResolver
|
||||
}
|
||||
return Boolean(field.resolve)
|
||||
}
|
||||
|
||||
printObjectTypeMap() {
|
||||
private printObjectTypeMap() {
|
||||
return this.printRootTypeFieldInterface(
|
||||
'NexusGenObjects',
|
||||
this.buildRootTypeMap(this.groupedTypes.object)
|
||||
)
|
||||
}
|
||||
|
||||
printInterfaceTypeMap() {
|
||||
private printInterfaceTypeMap() {
|
||||
return this.printRootTypeFieldInterface(
|
||||
'NexusGenInterfaces',
|
||||
this.buildRootTypeMap(this.groupedTypes.interface)
|
||||
)
|
||||
}
|
||||
|
||||
printUnionTypeMap() {
|
||||
private printUnionTypeMap() {
|
||||
return this.printRootTypeFieldInterface('NexusGenUnions', this.buildRootTypeMap(this.groupedTypes.union))
|
||||
}
|
||||
|
||||
printRootTypeDef() {
|
||||
private printRootTypeDef() {
|
||||
const toJoin: string[] = []
|
||||
if (this.groupedTypes.interface.length) {
|
||||
toJoin.push('NexusGenInterfaces')
|
||||
|
|
@ -599,7 +726,7 @@ export class TypegenPrinter {
|
|||
return `export type NexusGenRootTypes = ${toJoin.join(' & ')}`
|
||||
}
|
||||
|
||||
printAllTypesMap() {
|
||||
private printAllTypesMap() {
|
||||
const toJoin: string[] = ['NexusGenRootTypes']
|
||||
if (this.groupedTypes.scalar.length) {
|
||||
toJoin.push('NexusGenScalars')
|
||||
|
|
@ -610,7 +737,7 @@ export class TypegenPrinter {
|
|||
return `export type NexusGenAllTypes = ${toJoin.join(' & ')}`
|
||||
}
|
||||
|
||||
buildArgTypeMap() {
|
||||
private buildArgTypeMap() {
|
||||
const argTypeMap: Record<string, TypeFieldMapping> = {}
|
||||
const hasFields: (GraphQLInterfaceType | GraphQLObjectType)[] = []
|
||||
hasFields
|
||||
|
|
@ -630,11 +757,38 @@ export class TypegenPrinter {
|
|||
return argTypeMap
|
||||
}
|
||||
|
||||
printArgTypeMap() {
|
||||
return this.printArgTypeFieldInterface(this.buildArgTypeMap())
|
||||
private printArgTypeMap() {
|
||||
const argTypeMap = this.buildArgTypeMap()
|
||||
if (this.typegenInfo.declareInputs) {
|
||||
const declaredArgs: string[] = []
|
||||
eachObj(argTypeMap, (fields, typeName) => {
|
||||
eachObj(fields, (args, fieldName) => {
|
||||
declaredArgs.push(this.printNamedObj(this.getArgsName(typeName, fieldName), args))
|
||||
})
|
||||
})
|
||||
return [...declaredArgs, this.printArgTypeFieldInterface(argTypeMap)].join('\n\n')
|
||||
}
|
||||
|
||||
return this.printArgTypeFieldInterface(argTypeMap)
|
||||
}
|
||||
|
||||
buildReturnTypeMap() {
|
||||
private getArgsName(typeName: string, fieldName: string) {
|
||||
return `${typeName}${fieldName.slice(0, 1).toUpperCase().concat(fieldName.slice(1))}Args`
|
||||
}
|
||||
|
||||
private printNamedObj(name: string, obj: Record<string, [string, string]>) {
|
||||
return [
|
||||
`export interface ${name} {`,
|
||||
...mapObj(obj, (val, key) => ` ${key}${val[0]} ${val[1]}`),
|
||||
`}`,
|
||||
].join('\n')
|
||||
}
|
||||
|
||||
private printNamedMap(name: string, obj: Record<string, any>) {
|
||||
return [`export interface ${name} {`, ...mapObj(obj, (val, key) => ` ${key}: ${key}`), `}`].join('\n')
|
||||
}
|
||||
|
||||
private buildReturnTypeMap() {
|
||||
const returnTypeMap: TypeFieldMapping = {}
|
||||
const hasFields: (GraphQLInterfaceType | GraphQLObjectType)[] = []
|
||||
hasFields
|
||||
|
|
@ -649,7 +803,7 @@ export class TypegenPrinter {
|
|||
return returnTypeMap
|
||||
}
|
||||
|
||||
buildReturnTypeNamesMap() {
|
||||
private buildReturnTypeNamesMap() {
|
||||
const returnTypeMap: TypeFieldMapping = {}
|
||||
const hasFields: (GraphQLInterfaceType | GraphQLObjectType)[] = []
|
||||
hasFields
|
||||
|
|
@ -664,26 +818,26 @@ export class TypegenPrinter {
|
|||
return returnTypeMap
|
||||
}
|
||||
|
||||
printOutputType(type: GraphQLOutputType) {
|
||||
private printOutputType(type: GraphQLOutputType) {
|
||||
const returnType = this.typeToArr(type)
|
||||
function combine(item: any[]): string {
|
||||
if (item.length === 1) {
|
||||
if (Array.isArray(item[0])) {
|
||||
const toPrint = combine(item[0])
|
||||
return toPrint.indexOf('null') === -1 ? `${toPrint}[]` : `Array<${toPrint}>`
|
||||
return `ReadonlyArray<${toPrint}>`
|
||||
}
|
||||
return item[0]
|
||||
}
|
||||
if (Array.isArray(item[1])) {
|
||||
const toPrint = combine(item[1])
|
||||
return toPrint.indexOf('null') === -1 ? `${toPrint}[] | null` : `Array<${toPrint}> | null`
|
||||
return `ReadonlyArray<${toPrint}> | null`
|
||||
}
|
||||
return `${item[1]} | null`
|
||||
}
|
||||
return `${combine(returnType)}; // ${type}`
|
||||
}
|
||||
|
||||
typeToArr(type: GraphQLOutputType): any[] {
|
||||
private typeToArr(type: GraphQLOutputType): any[] {
|
||||
const typing = []
|
||||
if (isNonNullType(type)) {
|
||||
type = type.ofType
|
||||
|
|
@ -695,18 +849,22 @@ export class TypegenPrinter {
|
|||
} else if (isScalarType(type)) {
|
||||
typing.push(this.printScalar(type))
|
||||
} else if (isEnumType(type)) {
|
||||
typing.push(`NexusGenEnums['${type.name}']`)
|
||||
if (this.typegenInfo.declareInputs) {
|
||||
typing.push(type.name)
|
||||
} else {
|
||||
typing.push(`NexusGenEnums['${type.name}']`)
|
||||
}
|
||||
} else if (isObjectType(type) || isInterfaceType(type) || isUnionType(type)) {
|
||||
typing.push(`NexusGenRootTypes['${type.name}']`)
|
||||
}
|
||||
return typing
|
||||
}
|
||||
|
||||
printFieldTypesMap() {
|
||||
private printFieldTypesMap() {
|
||||
return this.printTypeFieldInterface('NexusGenFieldTypes', this.buildReturnTypeMap(), 'field return type')
|
||||
}
|
||||
|
||||
printFieldTypeNamesMap() {
|
||||
private printFieldTypeNamesMap() {
|
||||
return this.printTypeFieldInterface(
|
||||
'NexusGenFieldTypeNames',
|
||||
this.buildReturnTypeNamesMap(),
|
||||
|
|
@ -714,11 +872,11 @@ export class TypegenPrinter {
|
|||
)
|
||||
}
|
||||
|
||||
normalizeArg(arg: GraphQLInputField | GraphQLArgument): [string, string] {
|
||||
private normalizeArg(arg: GraphQLInputField | GraphQLArgument): [string, string] {
|
||||
return [this.argSeparator(arg.type, Boolean(arg.defaultValue)), this.argTypeRepresentation(arg.type)]
|
||||
}
|
||||
|
||||
argSeparator(type: GraphQLInputType, hasDefaultValue: boolean) {
|
||||
private argSeparator(type: GraphQLInputType, hasDefaultValue: boolean) {
|
||||
if (hasDefaultValue || isNonNullType(type)) {
|
||||
return ':'
|
||||
}
|
||||
|
|
@ -726,18 +884,25 @@ export class TypegenPrinter {
|
|||
return '?:'
|
||||
}
|
||||
|
||||
argTypeRepresentation(arg: GraphQLInputType): string {
|
||||
private argTypeRepresentation(arg: GraphQLInputType): string {
|
||||
const argType = this.argTypeArr(arg)
|
||||
const useReadonlyArrayForInputs = !!this.typegenInfo.useReadonlyArrayForInputs
|
||||
function combine(item: any[]): string {
|
||||
if (item.length === 1) {
|
||||
if (Array.isArray(item[0])) {
|
||||
const toPrint = combine(item[0])
|
||||
if (useReadonlyArrayForInputs) {
|
||||
return `ReadonlyArray<${toPrint}>`
|
||||
}
|
||||
return toPrint.indexOf('null') === -1 ? `${toPrint}[]` : `Array<${toPrint}>`
|
||||
}
|
||||
return item[0]
|
||||
}
|
||||
if (Array.isArray(item[1])) {
|
||||
const toPrint = combine(item[1])
|
||||
if (useReadonlyArrayForInputs) {
|
||||
return `ReadonlyArray<${toPrint}> | null`
|
||||
}
|
||||
return toPrint.indexOf('null') === -1 ? `${toPrint}[] | null` : `Array<${toPrint}> | null`
|
||||
}
|
||||
return `${item[1]} | null`
|
||||
|
|
@ -745,7 +910,7 @@ export class TypegenPrinter {
|
|||
return `${combine(argType)}; // ${arg}`
|
||||
}
|
||||
|
||||
argTypeArr(arg: GraphQLInputType): any[] {
|
||||
private argTypeArr(arg: GraphQLInputType): any[] {
|
||||
const typing = []
|
||||
if (isNonNullType(arg)) {
|
||||
arg = arg.ofType
|
||||
|
|
@ -757,21 +922,29 @@ export class TypegenPrinter {
|
|||
} else if (isScalarType(arg)) {
|
||||
typing.push(this.printScalar(arg))
|
||||
} else if (isEnumType(arg)) {
|
||||
typing.push(`NexusGenEnums['${arg.name}']`)
|
||||
if (this.typegenInfo.declareInputs) {
|
||||
typing.push(arg.name)
|
||||
} else {
|
||||
typing.push(`NexusGenEnums['${arg.name}']`)
|
||||
}
|
||||
} else if (isInputObjectType(arg)) {
|
||||
typing.push(`NexusGenInputs['${arg.name}']`)
|
||||
if (this.typegenInfo.declareInputs) {
|
||||
typing.push(arg.name)
|
||||
} else {
|
||||
typing.push(`NexusGenInputs['${arg.name}']`)
|
||||
}
|
||||
}
|
||||
return typing
|
||||
}
|
||||
|
||||
printTypeInterface(interfaceName: string, typeMapping: TypeMapping) {
|
||||
private printTypeInterface(interfaceName: string, typeMapping: TypeMapping) {
|
||||
return [`export interface ${interfaceName} {`]
|
||||
.concat(mapObj(typeMapping, (val, key) => ` ${key}: ${val}`))
|
||||
.concat('}')
|
||||
.join('\n')
|
||||
}
|
||||
|
||||
printRootTypeFieldInterface(interfaceName: string, typeMapping: RootTypeMapping) {
|
||||
private printRootTypeFieldInterface(interfaceName: string, typeMapping: RootTypeMapping) {
|
||||
return [`export interface ${interfaceName} {`]
|
||||
.concat(
|
||||
mapObj(typeMapping, (val, key) => {
|
||||
|
|
@ -788,18 +961,26 @@ export class TypegenPrinter {
|
|||
.join('\n')
|
||||
}
|
||||
|
||||
printTypeFieldInterface(interfaceName: string, typeMapping: TypeFieldMapping, source: string) {
|
||||
private printTypeFieldInterface(interfaceName: string, typeMapping: TypeFieldMapping, source: string) {
|
||||
return [`export interface ${interfaceName} {`]
|
||||
.concat(mapObj(typeMapping, this.printObj(' ', source)))
|
||||
.concat('}')
|
||||
.join('\n')
|
||||
}
|
||||
|
||||
printArgTypeFieldInterface(typeMapping: Record<string, TypeFieldMapping>) {
|
||||
private printArgTypeFieldInterface(typeMapping: Record<string, TypeFieldMapping>) {
|
||||
return [`export interface NexusGenArgTypes {`]
|
||||
.concat(
|
||||
mapObj(typeMapping, (val, key) => {
|
||||
return [` ${key}: {`]
|
||||
mapObj(typeMapping, (val, typeName) => {
|
||||
if (this.typegenInfo.declareInputs) {
|
||||
return [` ${typeName}: {`]
|
||||
.concat(
|
||||
mapObj(val, (_, fieldName) => ` ${fieldName}: ${this.getArgsName(typeName, fieldName)}`)
|
||||
)
|
||||
.concat(' }')
|
||||
.join('\n')
|
||||
}
|
||||
return [` ${typeName}: {`]
|
||||
.concat(mapObj(val, this.printObj(' ', 'args')))
|
||||
.concat(' }')
|
||||
.join('\n')
|
||||
|
|
@ -809,25 +990,26 @@ export class TypegenPrinter {
|
|||
.join('\n')
|
||||
}
|
||||
|
||||
printObj = (space: string, source: string) => (val: Record<string, [string, string]>, key: string) => {
|
||||
return [`${space}${key}: { // ${source}`]
|
||||
.concat(
|
||||
mapObj(val, (v2, k2) => {
|
||||
return `${space} ${k2}${v2[0]} ${v2[1]}`
|
||||
})
|
||||
)
|
||||
.concat(`${space}}`)
|
||||
.join('\n')
|
||||
}
|
||||
private printObj =
|
||||
(space: string, source: string) => (val: Record<string, [string, string]>, key: string) => {
|
||||
return [`${space}${key}: { // ${source}`]
|
||||
.concat(
|
||||
mapObj(val, (v2, k2) => {
|
||||
return `${space} ${k2}${v2[0]} ${v2[1]}`
|
||||
})
|
||||
)
|
||||
.concat(`${space}}`)
|
||||
.join('\n')
|
||||
}
|
||||
|
||||
printScalar(type: GraphQLScalarType) {
|
||||
private printScalar(type: GraphQLScalarType) {
|
||||
if (isSpecifiedScalarType(type)) {
|
||||
return this.resolveSourceType(type.name) ?? SpecifiedScalars[type.name as SpecifiedScalarNames]
|
||||
}
|
||||
return `NexusGenScalars['${type.name}']`
|
||||
}
|
||||
|
||||
printPlugins() {
|
||||
private printPlugins() {
|
||||
const pluginFieldExt: string[] = [
|
||||
` interface NexusGenPluginFieldConfig<TypeName extends string, FieldName extends string> {`,
|
||||
]
|
||||
|
|
@ -876,7 +1058,7 @@ export class TypegenPrinter {
|
|||
].join('\n')
|
||||
}
|
||||
|
||||
printType(strLike: StringLike | StringLike[]): string {
|
||||
private printType(strLike: StringLike | StringLike[]): string {
|
||||
if (Array.isArray(strLike)) {
|
||||
return strLike.map((s) => this.printType(s)).join('\n')
|
||||
}
|
||||
|
|
@ -893,7 +1075,7 @@ export class TypegenPrinter {
|
|||
return strLike
|
||||
}
|
||||
|
||||
addImport(i: PrintedGenTypingImport) {
|
||||
private addImport(i: PrintedGenTypingImport) {
|
||||
/* istanbul ignore if */
|
||||
if (!isNexusPrintedGenTypingImport(i)) {
|
||||
console.warn(`Expected printedGenTypingImport, saw ${i}`)
|
||||
|
|
|
|||
|
|
@ -155,6 +155,8 @@ export type GenTypesShapeKeys =
|
|||
| 'inputTypes'
|
||||
| 'rootTypes'
|
||||
| 'inputTypeShapes'
|
||||
| 'directives'
|
||||
| 'directiveArgs'
|
||||
| 'argTypes'
|
||||
| 'fieldTypes'
|
||||
| 'fieldTypeNames'
|
||||
|
|
@ -179,7 +181,7 @@ export type GenTypesShapeKeys =
|
|||
export type GenTypesShape = Record<GenTypesShapeKeys, any>
|
||||
|
||||
export type GetGen<K extends GenTypesShapeKeys, Fallback = any> = NexusGen extends infer GenTypes
|
||||
? GenTypes extends GenTypesShape
|
||||
? K extends keyof GenTypes
|
||||
? GenTypes[K]
|
||||
: Fallback
|
||||
: Fallback
|
||||
|
|
@ -202,10 +204,8 @@ export type GetGen3<
|
|||
: Fallback
|
||||
|
||||
export type HasGen<K extends GenTypesShapeKeys> = NexusGen extends infer GenTypes
|
||||
? GenTypes extends GenTypesShape
|
||||
? K extends keyof GenTypes
|
||||
? true
|
||||
: false
|
||||
? K extends keyof GenTypes
|
||||
? true
|
||||
: false
|
||||
: false
|
||||
|
||||
|
|
@ -213,11 +213,9 @@ export type HasGen2<
|
|||
K extends GenTypesShapeKeys,
|
||||
K2 extends Extract<keyof GenTypesShape[K], string>
|
||||
> = NexusGen extends infer GenTypes
|
||||
? GenTypes extends GenTypesShape
|
||||
? K extends keyof GenTypes
|
||||
? K2 extends keyof GenTypes[K]
|
||||
? true
|
||||
: false
|
||||
? K extends keyof GenTypes
|
||||
? K2 extends keyof GenTypes[K]
|
||||
? true
|
||||
: false
|
||||
: false
|
||||
: false
|
||||
|
|
@ -227,12 +225,10 @@ export type HasGen3<
|
|||
K2 extends Extract<keyof GenTypesShape[K], string>,
|
||||
K3 extends Extract<keyof GenTypesShape[K][K2], string>
|
||||
> = NexusGen extends infer GenTypes
|
||||
? GenTypes extends GenTypesShape
|
||||
? K extends keyof GenTypes
|
||||
? K2 extends keyof GenTypes[K]
|
||||
? K3 extends keyof GenTypes[K][K2]
|
||||
? true
|
||||
: false
|
||||
? K extends keyof GenTypes
|
||||
? K2 extends keyof GenTypes[K]
|
||||
? K3 extends keyof GenTypes[K][K2]
|
||||
? true
|
||||
: false
|
||||
: false
|
||||
: false
|
||||
|
|
|
|||
|
|
@ -1,51 +1,75 @@
|
|||
import * as path from 'path'
|
||||
import type { BuilderConfigInput } from './builder'
|
||||
import type { ConfiguredTypegen } from './core'
|
||||
import { nodeImports } from './node'
|
||||
import type { TypegenMetadataConfig } from './typegenMetadata'
|
||||
import { assertAbsolutePath, getOwnPackage, isProductionStage } from './utils'
|
||||
|
||||
/** Normalizes the builder config into the config we need for typegen */
|
||||
export function resolveTypegenConfig(config: BuilderConfigInput): TypegenMetadataConfig {
|
||||
const {
|
||||
outputs,
|
||||
shouldGenerateArtifacts = Boolean(!process.env.NODE_ENV || process.env.NODE_ENV !== 'production'),
|
||||
...rest
|
||||
} = config
|
||||
const { outputs, shouldGenerateArtifacts = defaultShouldGenerateArtifacts(), ...rest } = config
|
||||
|
||||
const defaultSDLFilePath = path.join(process.cwd(), 'schema.graphql')
|
||||
function getOutputPaths() {
|
||||
const defaultSDLFilePath = nodeImports().path.join(process.cwd(), 'schema.graphql')
|
||||
|
||||
let typegenFilePath: string | null = null
|
||||
let sdlFilePath: string | null = null
|
||||
let typegenFilePath: ConfiguredTypegen | null = null
|
||||
let sdlFilePath: string | null = null
|
||||
|
||||
if (outputs === undefined) {
|
||||
if (isProductionStage()) {
|
||||
if (outputs === undefined) {
|
||||
if (isProductionStage()) {
|
||||
sdlFilePath = defaultSDLFilePath
|
||||
}
|
||||
} else if (outputs === true) {
|
||||
sdlFilePath = defaultSDLFilePath
|
||||
} else if (typeof outputs === 'object') {
|
||||
if (outputs.schema === true) {
|
||||
sdlFilePath = defaultSDLFilePath
|
||||
} else if (typeof outputs.schema === 'string') {
|
||||
sdlFilePath = assertAbsolutePath(outputs.schema, 'outputs.schema')
|
||||
} else if (outputs.schema === undefined && isProductionStage()) {
|
||||
}
|
||||
// handle typegen configuration
|
||||
if (typeof outputs.typegen === 'string') {
|
||||
typegenFilePath = {
|
||||
outputPath: assertAbsolutePath(outputs.typegen, 'outputs.typegen'),
|
||||
}
|
||||
} else if (typeof outputs.typegen === 'object') {
|
||||
typegenFilePath = {
|
||||
...outputs.typegen,
|
||||
outputPath: assertAbsolutePath(outputs.typegen.outputPath, 'outputs.typegen.outputPath'),
|
||||
} as ConfiguredTypegen
|
||||
if (outputs.typegen.globalsPath) {
|
||||
typegenFilePath.globalsPath = assertAbsolutePath(
|
||||
outputs.typegen.globalsPath,
|
||||
'outputs.typegen.globalsPath'
|
||||
)
|
||||
}
|
||||
}
|
||||
} else if (outputs !== false) {
|
||||
console.warn(
|
||||
`You should specify a configuration value for outputs in Nexus' makeSchema. ` +
|
||||
`Provide one to remove this warning.`
|
||||
)
|
||||
}
|
||||
} else if (outputs === true) {
|
||||
sdlFilePath = defaultSDLFilePath
|
||||
} else if (typeof outputs === 'object') {
|
||||
if (outputs.schema === true) {
|
||||
sdlFilePath = defaultSDLFilePath
|
||||
} else if (typeof outputs.schema === 'string') {
|
||||
sdlFilePath = assertAbsolutePath(outputs.schema, 'outputs.schema')
|
||||
} else if (outputs.schema === undefined && isProductionStage()) {
|
||||
return {
|
||||
typegenFilePath,
|
||||
sdlFilePath,
|
||||
}
|
||||
// handle typegen configuration
|
||||
if (typeof outputs.typegen === 'string') {
|
||||
typegenFilePath = assertAbsolutePath(outputs.typegen, 'outputs.typegen')
|
||||
}
|
||||
} else if (outputs !== false) {
|
||||
console.warn(
|
||||
`You should specify a configuration value for outputs in Nexus' makeSchema. ` +
|
||||
`Provide one to remove this warning.`
|
||||
)
|
||||
}
|
||||
|
||||
return {
|
||||
...rest,
|
||||
nexusSchemaImportId: getOwnPackage().name,
|
||||
outputs: {
|
||||
typegen: shouldGenerateArtifacts ? typegenFilePath : null,
|
||||
schema: shouldGenerateArtifacts ? sdlFilePath : null,
|
||||
typegen: shouldGenerateArtifacts ? getOutputPaths().typegenFilePath : null,
|
||||
schema: shouldGenerateArtifacts ? getOutputPaths().sdlFilePath : null,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
function defaultShouldGenerateArtifacts() {
|
||||
return Boolean(
|
||||
typeof process === 'object' &&
|
||||
typeof process.cwd === 'function' &&
|
||||
(!process.env.NODE_ENV || process.env.NODE_ENV !== 'production')
|
||||
)
|
||||
}
|
||||
|
|
|
|||
58
src/utils.ts
58
src/utils.ts
|
|
@ -1,4 +1,3 @@
|
|||
import * as fs from 'fs'
|
||||
import {
|
||||
GraphQLEnumType,
|
||||
GraphQLInputObjectType,
|
||||
|
|
@ -22,7 +21,6 @@ import {
|
|||
isWrappingType,
|
||||
specifiedScalarTypes,
|
||||
} from 'graphql'
|
||||
import * as Path from 'path'
|
||||
import { decorateType } from './definitions/decorateType'
|
||||
import { isNexusMetaType, NexusMetaType, resolveNexusMetaType } from './definitions/nexusMeta'
|
||||
import {
|
||||
|
|
@ -31,9 +29,10 @@ import {
|
|||
AllNexusTypeDefs,
|
||||
isNexusWrappingType,
|
||||
isNexusArgDef,
|
||||
AllNexusNamedInputTypeDefs,
|
||||
AllNamedInputTypeDefs,
|
||||
} from './definitions/wrapping'
|
||||
import {
|
||||
Maybe,
|
||||
MissingType,
|
||||
NexusFeatures,
|
||||
NexusGraphQLSchema,
|
||||
|
|
@ -41,6 +40,7 @@ import {
|
|||
TypingImport,
|
||||
withNexusSymbol,
|
||||
} from './definitions/_types'
|
||||
import { nodeImports } from './node'
|
||||
|
||||
export const isInterfaceField = (type: GraphQLObjectType, fieldName: string) => {
|
||||
return type.getInterfaces().some((i) => Boolean(i.getFields()[fieldName]))
|
||||
|
|
@ -149,7 +149,7 @@ export function eachObj<T>(obj: Record<string, T>, iter: (val: T, key: string, i
|
|||
export const isObject = (obj: any): boolean => obj !== null && typeof obj === 'object'
|
||||
|
||||
export const assertAbsolutePath = (pathName: string, property: string) => {
|
||||
if (!Path.isAbsolute(pathName)) {
|
||||
if (!nodeImports().path.isAbsolute(pathName)) {
|
||||
throw new Error(`Expected path for "${property}" to be an absolute path, saw "${pathName}"`)
|
||||
}
|
||||
return pathName
|
||||
|
|
@ -177,7 +177,7 @@ export function groupTypes(schema: GraphQLSchema) {
|
|||
Object.keys(schemaTypeMap)
|
||||
.sort()
|
||||
.forEach((typeName) => {
|
||||
if (typeName.indexOf('__') === 0) {
|
||||
if (typeName.startsWith('__')) {
|
||||
return
|
||||
}
|
||||
const type = schema.getType(typeName)
|
||||
|
|
@ -220,7 +220,7 @@ export function isPromiseLike(value: any): value is PromiseLike<any> {
|
|||
export const typeScriptFileExtension = /(\.d)?\.ts$/
|
||||
|
||||
function makeRelativePathExplicitlyRelative(path: string) {
|
||||
if (Path.isAbsolute(path)) return path
|
||||
if (nodeImports().path.isAbsolute(path)) return path
|
||||
if (path.startsWith('./')) return path
|
||||
return `./${path}`
|
||||
}
|
||||
|
|
@ -233,7 +233,7 @@ function nixifyPathSlashes(path: string): string {
|
|||
* Format a path so it is suitable to be used as a module import.
|
||||
*
|
||||
* - Implicitly relative is made explicitly relative - TypeScript file extension is stripped - Windows slashes
|
||||
* converted into *nix slashes
|
||||
* converted into *nix slashes
|
||||
*
|
||||
* Do not pass Node module IDs here as they will be treated as relative paths e.g. "react" "@types/react" etc.
|
||||
*/
|
||||
|
|
@ -242,6 +242,7 @@ export function formatPathForModuleImport(path: string) {
|
|||
}
|
||||
|
||||
export function relativePathTo(absolutePath: string, fromPath: string): string {
|
||||
const Path = nodeImports().path
|
||||
const filename = Path.basename(absolutePath)
|
||||
const relative = Path.relative(Path.dirname(fromPath), Path.dirname(absolutePath))
|
||||
return formatPathForModuleImport(Path.join(relative, filename))
|
||||
|
|
@ -266,7 +267,7 @@ export interface PrintedGenTypingConfig {
|
|||
name: string
|
||||
optional: boolean
|
||||
type: string
|
||||
description?: string
|
||||
description?: Maybe<string>
|
||||
imports?: PrintedGenTypingImport[]
|
||||
}
|
||||
|
||||
|
|
@ -476,20 +477,18 @@ export function casesHandled(x: never): never {
|
|||
throw new Error(`A case was not handled for value: "${x}"`)
|
||||
}
|
||||
|
||||
/** Quickly log objects */
|
||||
export function dump(x: any) {
|
||||
console.log(require('util').inspect(x, { depth: null }))
|
||||
}
|
||||
|
||||
function isNodeModule(path: string) {
|
||||
// Avoid treating absolute windows paths as Node packages e.g. D:/a/b/c
|
||||
return !Path.isAbsolute(path) && /^([A-z0-9@])/.test(path)
|
||||
return !nodeImports().path.isAbsolute(path) && /^([A-z0-9@])/.test(path)
|
||||
}
|
||||
|
||||
export function resolveImportPath(rootType: TypingImport, typeName: string, outputPath: string) {
|
||||
const rootTypePath = rootType.module
|
||||
|
||||
if (typeof rootTypePath !== 'string' || (!Path.isAbsolute(rootTypePath) && !isNodeModule(rootTypePath))) {
|
||||
if (
|
||||
typeof rootTypePath !== 'string' ||
|
||||
(!nodeImports().path.isAbsolute(rootTypePath) && !isNodeModule(rootTypePath))
|
||||
) {
|
||||
throw new Error(
|
||||
`Expected an absolute path or Node package for the root typing path of the type "${typeName}", saw "${rootTypePath}"`
|
||||
)
|
||||
|
|
@ -501,7 +500,7 @@ export function resolveImportPath(rootType: TypingImport, typeName: string, outp
|
|||
} catch (e) {
|
||||
throw new Error(`Module "${rootTypePath}" for the type "${typeName}" does not exist`)
|
||||
}
|
||||
} else if (!fs.existsSync(rootTypePath)) {
|
||||
} else if (!nodeImports().fs.existsSync(rootTypePath)) {
|
||||
throw new Error(`Root typing path "${rootTypePath}" for the type "${typeName}" does not exist`)
|
||||
}
|
||||
|
||||
|
|
@ -509,7 +508,7 @@ export function resolveImportPath(rootType: TypingImport, typeName: string, outp
|
|||
return rootTypePath
|
||||
}
|
||||
|
||||
if (Path.isAbsolute(rootTypePath)) {
|
||||
if (nodeImports().path.isAbsolute(rootTypePath)) {
|
||||
return relativePathTo(rootTypePath, outputPath)
|
||||
}
|
||||
|
||||
|
|
@ -517,7 +516,7 @@ export function resolveImportPath(rootType: TypingImport, typeName: string, outp
|
|||
}
|
||||
|
||||
/** Given the right hand side of an arg definition, returns the underlying "named type" for us to add to the builder */
|
||||
export function getArgNamedType(argDef: AllNexusArgsDefs | string): AllNexusNamedInputTypeDefs | string {
|
||||
export function getArgNamedType(argDef: AllNexusArgsDefs | string): AllNamedInputTypeDefs | string {
|
||||
let finalValue = argDef
|
||||
if (typeof finalValue === 'string') {
|
||||
return finalValue
|
||||
|
|
@ -552,7 +551,7 @@ export function getNexusNamedType(
|
|||
namedType = resolveNexusMetaType(namedType)
|
||||
}
|
||||
}
|
||||
return namedType
|
||||
return namedType as AllNexusNamedTypeDefs | GraphQLNamedType | string
|
||||
}
|
||||
|
||||
/** Assertion utility with nexus-aware feedback for users. */
|
||||
|
|
@ -597,12 +596,20 @@ export function graphql15InterfaceConfig<T extends GraphQLInterfaceTypeConfig<an
|
|||
}
|
||||
|
||||
export function graphql15InterfaceType<T extends GraphQLInterfaceType>(
|
||||
type: T & { getInterfaces?: () => GraphQLInterfaceType[] }
|
||||
): T & { getInterfaces(): GraphQLInterfaceType[] } {
|
||||
type: T & { getInterfaces?: () => ReadonlyArray<GraphQLInterfaceType> }
|
||||
): T & { getInterfaces(): ReadonlyArray<GraphQLInterfaceType> } {
|
||||
if (typeof type.getInterfaces !== 'function') {
|
||||
type.getInterfaces = () => []
|
||||
}
|
||||
return type as T & { getInterfaces(): GraphQLInterfaceType[] }
|
||||
return type as T & { getInterfaces(): ReadonlyArray<GraphQLInterfaceType> }
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function unpack<T extends object>(val: T | (() => T)): T {
|
||||
if (val instanceof Function) {
|
||||
return val()
|
||||
}
|
||||
return val
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -627,3 +634,10 @@ export const ownProp = {
|
|||
return Object.getOwnPropertyDescriptor(obj, key)?.value
|
||||
},
|
||||
}
|
||||
|
||||
export function result<T>(val: T | (() => T)): T {
|
||||
if (val instanceof Function) {
|
||||
return val()
|
||||
}
|
||||
return val as T
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import { join, relative } from 'path'
|
|||
import { core } from '../../src'
|
||||
import type { BuilderConfigInput } from '../../src/core'
|
||||
|
||||
const { generateSchema, typegenFormatPrettier } = core
|
||||
const { generateSchema } = core
|
||||
|
||||
type HookSettings = {
|
||||
rootDir: string
|
||||
|
|
@ -29,12 +29,8 @@ export async function generateTypegen(settings: HookSettings) {
|
|||
},
|
||||
shouldGenerateArtifacts: true,
|
||||
plugins: plugins || [],
|
||||
async formatTypegen(source, type) {
|
||||
const prettierConfigPath = require.resolve('../../.prettierrc')
|
||||
const content = await typegenFormatPrettier(prettierConfigPath)(source, type)
|
||||
|
||||
return content.replace("'nexus'", `'${importPath}'`)
|
||||
},
|
||||
prettierConfig: require.resolve('../../.prettierrc'),
|
||||
formatTypegen: (content) => content.replace('from "nexus"', `from '${importPath}'`),
|
||||
features: {
|
||||
abstractTypeStrategies: {
|
||||
resolveType: true,
|
||||
|
|
|
|||
|
|
@ -90,6 +90,11 @@ export type NexusGenScalarNames = keyof NexusGenScalars;
|
|||
|
||||
export type NexusGenUnionNames = never;
|
||||
|
||||
export type NexusGenDirectives = never
|
||||
|
||||
export interface NexusGenDirectiveArgs {
|
||||
}
|
||||
|
||||
export type NexusGenObjectsUsingAbstractStrategyIsTypeOf = never;
|
||||
|
||||
export type NexusGenAbstractsUsingStrategyResolveType = never;
|
||||
|
|
@ -105,6 +110,8 @@ export type NexusGenFeaturesConfig = {
|
|||
export interface NexusGenTypes {
|
||||
context: any;
|
||||
inputTypes: NexusGenInputs;
|
||||
directives: NexusGenDirectives;
|
||||
directiveArgs: NexusGenDirectiveArgs;
|
||||
rootTypes: NexusGenRootTypes;
|
||||
inputTypeShapes: NexusGenInputs & NexusGenEnums & NexusGenScalars;
|
||||
argTypes: NexusGenArgTypes;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,155 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`builder can replace the Mutation root type with an alternate type 1`] = `
|
||||
"schema {
|
||||
query: Query
|
||||
mutation: RootMutation
|
||||
}
|
||||
|
||||
type Mutation {
|
||||
ok: String
|
||||
}
|
||||
|
||||
type Query {
|
||||
ok: Boolean!
|
||||
}
|
||||
|
||||
type RootMutation {
|
||||
name: String
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`builder can replace the Query root type with an alternate type 1`] = `
|
||||
"schema {
|
||||
query: RootQuery
|
||||
}
|
||||
|
||||
type Query {
|
||||
ok: String
|
||||
}
|
||||
|
||||
type RootQuery {
|
||||
name: String
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`builder can replace the Subscription root type with an alternate type 1`] = `
|
||||
"schema {
|
||||
query: Query
|
||||
subscription: RootSubscription
|
||||
}
|
||||
|
||||
type Query {
|
||||
ok: Boolean!
|
||||
}
|
||||
|
||||
type RootSubscription {
|
||||
name: String
|
||||
}
|
||||
|
||||
type Subscription {
|
||||
ok: String
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`builder does not add a placeholder Query type when an alternate queryRoot has been defined 1`] = `
|
||||
"schema {
|
||||
query: RootQuery
|
||||
}
|
||||
|
||||
type RootQuery {
|
||||
name: String
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`builder.mergeSchema Merges Mutation & Query types by default: merged mutation 1`] = `
|
||||
"type Mutation {
|
||||
externalMutation(a: String): String
|
||||
localMutation: String
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`builder.mergeSchema Merges Mutation & Query types by default: merged query 1`] = `
|
||||
"type Query {
|
||||
externalFn(a: String): String
|
||||
localFn: String
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`builder.mergeSchema Merges Mutation & Query types by default: unmerged mutation 1`] = `
|
||||
"type Mutation {
|
||||
localMutation: String
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`builder.mergeSchema Merges Mutation & Query types by default: unmerged query 1`] = `
|
||||
"type Query {
|
||||
localFn: String
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`builder.mergeSchema can merge with an externally created schema 1`] = `
|
||||
"type Author implements Node {
|
||||
books: [Book]
|
||||
|
||||
\\"\\"\\"A Node ID is globally unique\\"\\"\\"
|
||||
id: ID!
|
||||
}
|
||||
|
||||
type Book implements Node {
|
||||
id: ID!
|
||||
name: String
|
||||
}
|
||||
|
||||
interface ExternalNode {
|
||||
id: ID!
|
||||
}
|
||||
|
||||
type InternalType {
|
||||
fieldName: String
|
||||
}
|
||||
|
||||
interface Node {
|
||||
\\"\\"\\"A Node ID is globally unique\\"\\"\\"
|
||||
id: ID!
|
||||
}
|
||||
|
||||
type Query {
|
||||
internalNodesByIds(ids: [ID!]!, internal: String!): [Node]!
|
||||
node(id: ID!): Node
|
||||
someBook: Book
|
||||
userByUuids(uuid: UUID): User
|
||||
}
|
||||
|
||||
scalar UUID
|
||||
|
||||
type User implements ExternalNode & Node {
|
||||
id: ID!
|
||||
name: String
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`builder.mergeSchema can merge with local types: merged 1`] = `
|
||||
"type User implements Node & ExternalNode {
|
||||
id: ID!
|
||||
name: String
|
||||
localName: String
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`builder.mergeSchema can merge with local types: unmerged 1`] = `
|
||||
"type User {
|
||||
localName: String
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`graphql-js interop extend types works with GraphQLNamedType (#88) 1`] = `
|
||||
"type Query {
|
||||
viewer: Viewer
|
||||
}
|
||||
|
||||
type Viewer {
|
||||
name: String
|
||||
age: Int
|
||||
}"
|
||||
`;
|
||||
|
|
@ -1,5 +1,25 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`enumType can alias as a nexus method 1`] = `
|
||||
"enum ABC {
|
||||
one
|
||||
three
|
||||
two
|
||||
}
|
||||
|
||||
input Input {
|
||||
inAbc: ABC
|
||||
}
|
||||
|
||||
type Out {
|
||||
outAbc: ABC
|
||||
}
|
||||
|
||||
type Query {
|
||||
ok: Boolean!
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`extendInputType should allow extending input objects 1`] = `
|
||||
"input InputTest {
|
||||
hello: String
|
||||
|
|
|
|||
|
|
@ -1,13 +1,20 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`makeSchema directives can specify custom directives 1`] = `
|
||||
"directive @customDirective(code: Int = 42) on FRAGMENT_DEFINITION
|
||||
|
||||
type Query {
|
||||
ok: Boolean!
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`makeSchema shouldExitAfterGenerateArtifacts accepts a customPrintSchemaFn 1`] = `
|
||||
"### This file was generated by Nexus Schema
|
||||
### Do not make changes to this file directly
|
||||
|
||||
|
||||
type Query {
|
||||
# Example boolean field
|
||||
\\"\\"\\"Example boolean field\\"\\"\\"
|
||||
ok: Boolean
|
||||
}
|
||||
"
|
||||
}"
|
||||
`;
|
||||
|
|
|
|||
|
|
@ -4,30 +4,26 @@ exports[`nonNullDefaults false/false on schema 1`] = `
|
|||
"type Query {
|
||||
stringList: [String]
|
||||
test(test: Int): Boolean
|
||||
}
|
||||
"
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`nonNullDefaults false/false on type 1`] = `
|
||||
"type Query {
|
||||
stringList: [String]
|
||||
test(test: Int): Boolean
|
||||
}
|
||||
"
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`nonNullDefaults true/true on schema 1`] = `
|
||||
"type Query {
|
||||
stringList: [String!]!
|
||||
test(test: Int!): Boolean!
|
||||
}
|
||||
"
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`nonNullDefaults true/true on type 1`] = `
|
||||
"type Query {
|
||||
stringList: [String!]!
|
||||
test(test: Int!): Boolean!
|
||||
}
|
||||
"
|
||||
}"
|
||||
`;
|
||||
|
|
|
|||
|
|
@ -31,8 +31,7 @@ exports[`plugin has an onAddOutputField / onAddInputField / onAddArg option, whi
|
|||
|
||||
input SomeType {
|
||||
inputField: [Boolean]
|
||||
}
|
||||
"
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`plugin has an onMissingType, which will be called in order when we encounter a missing type 1`] = `
|
||||
|
|
@ -57,8 +56,7 @@ type UserConnection {
|
|||
type UserEdge {
|
||||
cursor: String
|
||||
node: User
|
||||
}
|
||||
"
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`plugin is applied to the resolver for every field in the schema 1`] = `
|
||||
|
|
|
|||
|
|
@ -7,33 +7,29 @@ exports[`onInstall plugins does not have access to inline types 1`] = `
|
|||
|
||||
type Query {
|
||||
bar(inline: Inline): String
|
||||
}
|
||||
"
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`onInstall plugins does not see fallback ok-query 1`] = `
|
||||
"type Query {
|
||||
ok: Boolean!
|
||||
}
|
||||
"
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`onInstall plugins has access to top-level types 1`] = `
|
||||
"type foo {
|
||||
bar: String
|
||||
}
|
||||
|
||||
type Query {
|
||||
"type Query {
|
||||
ok: Boolean!
|
||||
}
|
||||
"
|
||||
|
||||
type foo {
|
||||
bar: String
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`onInstall plugins may contribute types 1`] = `
|
||||
"type Query {
|
||||
something: String
|
||||
}
|
||||
"
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`runtime config validation checks name is not empty 1`] = `"Plugin \\"\\" is giving an invalid value for property name: empty string"`;
|
||||
|
|
|
|||
|
|
@ -55,9 +55,9 @@ exports[`typegenPrinter should not print roots for fields with resolvers 1`] = `
|
|||
Mutation: {};
|
||||
Post: { // root type
|
||||
author: NexusGenRootTypes['User']; // User!
|
||||
geo: number[][]; // [[Float!]!]!
|
||||
geo: ReadonlyArray<ReadonlyArray<number>>; // [[Float!]!]!
|
||||
id: string; // ID!
|
||||
messyGeo?: Array<number[] | null> | null; // [[Float!]]
|
||||
messyGeo?: ReadonlyArray<ReadonlyArray<number> | null> | null; // [[Float!]]
|
||||
uuid: NexusGenScalars['UUID']; // UUID!
|
||||
}
|
||||
Query: {};
|
||||
|
|
@ -75,7 +75,7 @@ exports[`typegenPrinter should not print roots for fields with resolvers 2`] = `
|
|||
|
||||
exports[`typegenPrinter should print a interface type map 1`] = `
|
||||
"export interface NexusGenInterfaces {
|
||||
Node: core.Discriminate<'Post', 'required'> | core.Discriminate<'User', 'required'>;
|
||||
Node: core.Discriminate<'Post', 'optional'> | core.Discriminate<'User', 'optional'>;
|
||||
}"
|
||||
`;
|
||||
|
||||
|
|
@ -84,9 +84,9 @@ exports[`typegenPrinter should print a object type map 1`] = `
|
|||
Mutation: {};
|
||||
Post: { // root type
|
||||
author: NexusGenRootTypes['User']; // User!
|
||||
geo: number[][]; // [[Float!]!]!
|
||||
geo: ReadonlyArray<ReadonlyArray<number>>; // [[Float!]!]!
|
||||
id: string; // ID!
|
||||
messyGeo?: Array<number[] | null> | null; // [[Float!]]
|
||||
messyGeo?: ReadonlyArray<ReadonlyArray<number> | null> | null; // [[Float!]]
|
||||
uuid: NexusGenScalars['UUID']; // UUID!
|
||||
}
|
||||
Query: {};
|
||||
|
|
@ -96,7 +96,7 @@ exports[`typegenPrinter should print a object type map 1`] = `
|
|||
name: string; // String!
|
||||
outEnum?: NexusGenEnums['SomeEnum'] | null; // SomeEnum
|
||||
phone?: string | null; // String
|
||||
posts: NexusGenRootTypes['Post'][]; // [Post!]!
|
||||
posts: ReadonlyArray<NexusGenRootTypes['Post']>; // [Post!]!
|
||||
}
|
||||
}"
|
||||
`;
|
||||
|
|
@ -106,17 +106,17 @@ exports[`typegenPrinter should print a return type map 1`] = `
|
|||
Mutation: { // field return type
|
||||
createPost: NexusGenRootTypes['Post']; // Post!
|
||||
registerClick: NexusGenRootTypes['Query']; // Query!
|
||||
someList: Array<string | null>; // [String]!
|
||||
someList: ReadonlyArray<string | null>; // [String]!
|
||||
}
|
||||
Post: { // field return type
|
||||
author: NexusGenRootTypes['User']; // User!
|
||||
geo: number[][]; // [[Float!]!]!
|
||||
geo: ReadonlyArray<ReadonlyArray<number>>; // [[Float!]!]!
|
||||
id: string; // ID!
|
||||
messyGeo: Array<number[] | null> | null; // [[Float!]]
|
||||
messyGeo: ReadonlyArray<ReadonlyArray<number> | null> | null; // [[Float!]]
|
||||
uuid: NexusGenScalars['UUID']; // UUID!
|
||||
}
|
||||
Query: { // field return type
|
||||
posts: NexusGenRootTypes['Post'][]; // [Post!]!
|
||||
posts: ReadonlyArray<NexusGenRootTypes['Post']>; // [Post!]!
|
||||
unionField: NexusGenRootTypes['ExampleUnion']; // ExampleUnion!
|
||||
user: NexusGenRootTypes['User']; // User!
|
||||
}
|
||||
|
|
@ -126,7 +126,7 @@ exports[`typegenPrinter should print a return type map 1`] = `
|
|||
name: string; // String!
|
||||
outEnum: NexusGenEnums['SomeEnum'] | null; // SomeEnum
|
||||
phone: string | null; // String
|
||||
posts: NexusGenRootTypes['Post'][]; // [Post!]!
|
||||
posts: ReadonlyArray<NexusGenRootTypes['Post']>; // [Post!]!
|
||||
}
|
||||
Node: { // field return type
|
||||
id: string; // ID!
|
||||
|
|
@ -138,7 +138,7 @@ exports[`typegenPrinter should print a root type map 1`] = `"export type NexusGe
|
|||
|
||||
exports[`typegenPrinter should print a union type map 1`] = `
|
||||
"export interface NexusGenUnions {
|
||||
ExampleUnion: core.Discriminate<'Post', 'required'> | core.Discriminate<'User', 'required'>;
|
||||
ExampleUnion: core.Discriminate<'Post', 'optional'> | core.Discriminate<'User', 'optional'>;
|
||||
}"
|
||||
`;
|
||||
|
||||
|
|
@ -189,9 +189,9 @@ export interface NexusGenObjects {
|
|||
Mutation: {};
|
||||
Post: { // root type
|
||||
author: NexusGenRootTypes['User']; // User!
|
||||
geo: number[][]; // [[Float!]!]!
|
||||
geo: ReadonlyArray<ReadonlyArray<number>>; // [[Float!]!]!
|
||||
id: string; // ID!
|
||||
messyGeo?: Array<number[] | null> | null; // [[Float!]]
|
||||
messyGeo?: ReadonlyArray<ReadonlyArray<number> | null> | null; // [[Float!]]
|
||||
uuid: NexusGenScalars['UUID']; // UUID!
|
||||
}
|
||||
Query: {};
|
||||
|
|
@ -201,16 +201,16 @@ export interface NexusGenObjects {
|
|||
name: string; // String!
|
||||
outEnum?: NexusGenEnums['SomeEnum'] | null; // SomeEnum
|
||||
phone?: string | null; // String
|
||||
posts: NexusGenRootTypes['Post'][]; // [Post!]!
|
||||
posts: ReadonlyArray<NexusGenRootTypes['Post']>; // [Post!]!
|
||||
}
|
||||
}
|
||||
|
||||
export interface NexusGenInterfaces {
|
||||
Node: core.Discriminate<'Post', 'required'> | core.Discriminate<'User', 'required'>;
|
||||
Node: core.Discriminate<'Post', 'optional'> | core.Discriminate<'User', 'optional'>;
|
||||
}
|
||||
|
||||
export interface NexusGenUnions {
|
||||
ExampleUnion: core.Discriminate<'Post', 'required'> | core.Discriminate<'User', 'required'>;
|
||||
ExampleUnion: core.Discriminate<'Post', 'optional'> | core.Discriminate<'User', 'optional'>;
|
||||
}
|
||||
|
||||
export type NexusGenRootTypes = NexusGenInterfaces & NexusGenObjects & NexusGenUnions
|
||||
|
|
@ -221,17 +221,17 @@ export interface NexusGenFieldTypes {
|
|||
Mutation: { // field return type
|
||||
createPost: NexusGenRootTypes['Post']; // Post!
|
||||
registerClick: NexusGenRootTypes['Query']; // Query!
|
||||
someList: Array<string | null>; // [String]!
|
||||
someList: ReadonlyArray<string | null>; // [String]!
|
||||
}
|
||||
Post: { // field return type
|
||||
author: NexusGenRootTypes['User']; // User!
|
||||
geo: number[][]; // [[Float!]!]!
|
||||
geo: ReadonlyArray<ReadonlyArray<number>>; // [[Float!]!]!
|
||||
id: string; // ID!
|
||||
messyGeo: Array<number[] | null> | null; // [[Float!]]
|
||||
messyGeo: ReadonlyArray<ReadonlyArray<number> | null> | null; // [[Float!]]
|
||||
uuid: NexusGenScalars['UUID']; // UUID!
|
||||
}
|
||||
Query: { // field return type
|
||||
posts: NexusGenRootTypes['Post'][]; // [Post!]!
|
||||
posts: ReadonlyArray<NexusGenRootTypes['Post']>; // [Post!]!
|
||||
unionField: NexusGenRootTypes['ExampleUnion']; // ExampleUnion!
|
||||
user: NexusGenRootTypes['User']; // User!
|
||||
}
|
||||
|
|
@ -241,7 +241,7 @@ export interface NexusGenFieldTypes {
|
|||
name: string; // String!
|
||||
outEnum: NexusGenEnums['SomeEnum'] | null; // SomeEnum
|
||||
phone: string | null; // String
|
||||
posts: NexusGenRootTypes['Post'][]; // [Post!]!
|
||||
posts: ReadonlyArray<NexusGenRootTypes['Post']>; // [Post!]!
|
||||
}
|
||||
Node: { // field return type
|
||||
id: string; // ID!
|
||||
|
|
@ -328,9 +328,16 @@ export type NexusGenScalarNames = keyof NexusGenScalars;
|
|||
|
||||
export type NexusGenUnionNames = keyof NexusGenUnions;
|
||||
|
||||
export type NexusGenDirectives = \\"TestFieldDirective\\"
|
||||
|
||||
export interface NexusGenDirectiveArgs {
|
||||
TestFieldDirective: {
|
||||
}
|
||||
}
|
||||
|
||||
export type NexusGenObjectsUsingAbstractStrategyIsTypeOf = never;
|
||||
|
||||
export type NexusGenAbstractsUsingStrategyResolveType = never;
|
||||
export type NexusGenAbstractsUsingStrategyResolveType = \\"ExampleUnion\\" | \\"Node\\";
|
||||
|
||||
export type NexusGenFeaturesConfig = {
|
||||
abstractTypeStrategies: {
|
||||
|
|
@ -343,6 +350,8 @@ export type NexusGenFeaturesConfig = {
|
|||
export interface NexusGenTypes {
|
||||
context: TestContext;
|
||||
inputTypes: NexusGenInputs;
|
||||
directives: NexusGenDirectives;
|
||||
directiveArgs: NexusGenDirectiveArgs;
|
||||
rootTypes: NexusGenRootTypes;
|
||||
inputTypeShapes: NexusGenInputs & NexusGenEnums & NexusGenScalars;
|
||||
argTypes: NexusGenArgTypes;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,801 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`typegenPrinter: globals should print the full output 1`] = `
|
||||
Object {
|
||||
"globalTypes": "/**
|
||||
* This file was generated by Nexus Schema
|
||||
* Do not make changes to this file directly
|
||||
*/
|
||||
|
||||
import type { NexusGenTypes } from './types.gen'
|
||||
|
||||
|
||||
|
||||
|
||||
declare global {
|
||||
interface NexusGen extends NexusGenTypes {}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
declare global {
|
||||
interface NexusGenPluginTypeConfig<TypeName extends string> {
|
||||
}
|
||||
interface NexusGenPluginInputTypeConfig<TypeName extends string> {
|
||||
}
|
||||
interface NexusGenPluginFieldConfig<TypeName extends string, FieldName extends string> {
|
||||
}
|
||||
interface NexusGenPluginInputFieldConfig<TypeName extends string, FieldName extends string> {
|
||||
}
|
||||
interface NexusGenPluginSchemaConfig {
|
||||
}
|
||||
interface NexusGenPluginArgConfig {
|
||||
}
|
||||
}",
|
||||
"tsTypes": "/**
|
||||
* This file was generated by Nexus Schema
|
||||
* Do not make changes to this file directly
|
||||
*/
|
||||
|
||||
|
||||
import type { TestContext } from \\"./../__helpers/index\\"
|
||||
import type { core } from \\"nexus\\"
|
||||
|
||||
export interface CreatePostInput {
|
||||
author: string; // ID!
|
||||
geo: Array<Array<number | null>>; // [[Float]!]!
|
||||
name: string; // String!
|
||||
}
|
||||
|
||||
export interface PostFilters {
|
||||
order: OrderEnum; // OrderEnum!
|
||||
search: string | null; // String
|
||||
}
|
||||
|
||||
export interface NexusGenInputs {
|
||||
CreatePostInput: CreatePostInput
|
||||
PostFilters: PostFilters
|
||||
}
|
||||
|
||||
export type OrderEnum = \\"ASC\\" | \\"DESC\\"
|
||||
|
||||
export type SomeEnum = \\"A\\" | \\"B\\"
|
||||
|
||||
export interface NexusGenEnums {
|
||||
OrderEnum: OrderEnum
|
||||
SomeEnum: SomeEnum
|
||||
}
|
||||
|
||||
export interface NexusGenScalars {
|
||||
String: string
|
||||
Int: number
|
||||
Float: number
|
||||
Boolean: boolean
|
||||
ID: string
|
||||
UUID: string
|
||||
}
|
||||
|
||||
export interface NexusGenObjects {
|
||||
Mutation: {};
|
||||
Post: { // root type
|
||||
author: NexusGenRootTypes['User']; // User!
|
||||
geo: ReadonlyArray<ReadonlyArray<number>>; // [[Float!]!]!
|
||||
id: string; // ID!
|
||||
messyGeo?: ReadonlyArray<ReadonlyArray<number> | null> | null; // [[Float!]]
|
||||
uuid: NexusGenScalars['UUID']; // UUID!
|
||||
}
|
||||
Query: {};
|
||||
User: { // root type
|
||||
email: string; // String!
|
||||
id: string; // ID!
|
||||
name: string; // String!
|
||||
outEnum?: SomeEnum | null; // SomeEnum
|
||||
phone?: string | null; // String
|
||||
posts: ReadonlyArray<NexusGenRootTypes['Post']>; // [Post!]!
|
||||
}
|
||||
}
|
||||
|
||||
export interface NexusGenInterfaces {
|
||||
Node: core.Discriminate<'Post', 'optional'> | core.Discriminate<'User', 'optional'>;
|
||||
}
|
||||
|
||||
export interface NexusGenUnions {
|
||||
ExampleUnion: core.Discriminate<'Post', 'optional'> | core.Discriminate<'User', 'optional'>;
|
||||
}
|
||||
|
||||
export type NexusGenRootTypes = NexusGenInterfaces & NexusGenObjects & NexusGenUnions
|
||||
|
||||
export type NexusGenAllTypes = NexusGenRootTypes & NexusGenScalars & NexusGenEnums
|
||||
|
||||
export interface NexusGenFieldTypes {
|
||||
Mutation: { // field return type
|
||||
createPost: NexusGenRootTypes['Post']; // Post!
|
||||
registerClick: NexusGenRootTypes['Query']; // Query!
|
||||
someList: ReadonlyArray<string | null>; // [String]!
|
||||
}
|
||||
Post: { // field return type
|
||||
author: NexusGenRootTypes['User']; // User!
|
||||
geo: ReadonlyArray<ReadonlyArray<number>>; // [[Float!]!]!
|
||||
id: string; // ID!
|
||||
messyGeo: ReadonlyArray<ReadonlyArray<number> | null> | null; // [[Float!]]
|
||||
uuid: NexusGenScalars['UUID']; // UUID!
|
||||
}
|
||||
Query: { // field return type
|
||||
posts: ReadonlyArray<NexusGenRootTypes['Post']>; // [Post!]!
|
||||
unionField: NexusGenRootTypes['ExampleUnion']; // ExampleUnion!
|
||||
user: NexusGenRootTypes['User']; // User!
|
||||
}
|
||||
User: { // field return type
|
||||
email: string; // String!
|
||||
id: string; // ID!
|
||||
name: string; // String!
|
||||
outEnum: SomeEnum | null; // SomeEnum
|
||||
phone: string | null; // String
|
||||
posts: ReadonlyArray<NexusGenRootTypes['Post']>; // [Post!]!
|
||||
}
|
||||
Node: { // field return type
|
||||
id: string; // ID!
|
||||
}
|
||||
}
|
||||
|
||||
export interface NexusGenFieldTypeNames {
|
||||
Mutation: { // field return type name
|
||||
createPost: 'Post'
|
||||
registerClick: 'Query'
|
||||
someList: 'String'
|
||||
}
|
||||
Post: { // field return type name
|
||||
author: 'User'
|
||||
geo: 'Float'
|
||||
id: 'ID'
|
||||
messyGeo: 'Float'
|
||||
uuid: 'UUID'
|
||||
}
|
||||
Query: { // field return type name
|
||||
posts: 'Post'
|
||||
unionField: 'ExampleUnion'
|
||||
user: 'User'
|
||||
}
|
||||
User: { // field return type name
|
||||
email: 'String'
|
||||
id: 'ID'
|
||||
name: 'String'
|
||||
outEnum: 'SomeEnum'
|
||||
phone: 'String'
|
||||
posts: 'Post'
|
||||
}
|
||||
Node: { // field return type name
|
||||
id: 'ID'
|
||||
}
|
||||
}
|
||||
|
||||
export interface MutationCreatePostArgs {
|
||||
input: CreatePostInput; // CreatePostInput!
|
||||
}
|
||||
|
||||
export interface MutationRegisterClickArgs {
|
||||
uuid?: NexusGenScalars['UUID'] | null; // UUID
|
||||
}
|
||||
|
||||
export interface MutationSomeListArgs {
|
||||
items: Array<string | null>; // [String]!
|
||||
}
|
||||
|
||||
export interface QueryPostsArgs {
|
||||
filters: PostFilters; // PostFilters!
|
||||
}
|
||||
|
||||
export interface UserNameArgs {
|
||||
prefix?: string | null; // String
|
||||
}
|
||||
|
||||
export interface UserPostsArgs {
|
||||
filters?: PostFilters | null; // PostFilters
|
||||
}
|
||||
|
||||
export interface NexusGenArgTypes {
|
||||
Mutation: {
|
||||
createPost: MutationCreatePostArgs
|
||||
registerClick: MutationRegisterClickArgs
|
||||
someList: MutationSomeListArgs
|
||||
}
|
||||
Query: {
|
||||
posts: QueryPostsArgs
|
||||
}
|
||||
User: {
|
||||
name: UserNameArgs
|
||||
posts: UserPostsArgs
|
||||
}
|
||||
}
|
||||
|
||||
export interface NexusGenAbstractTypeMembers {
|
||||
ExampleUnion: \\"Post\\" | \\"User\\"
|
||||
Node: \\"Post\\" | \\"User\\"
|
||||
}
|
||||
|
||||
export interface NexusGenTypeInterfaces {
|
||||
Post: \\"Node\\"
|
||||
User: \\"Node\\"
|
||||
}
|
||||
|
||||
export type NexusGenObjectNames = keyof NexusGenObjects;
|
||||
|
||||
export type NexusGenInputNames = keyof NexusGenInputs;
|
||||
|
||||
export type NexusGenEnumNames = keyof NexusGenEnums;
|
||||
|
||||
export type NexusGenInterfaceNames = keyof NexusGenInterfaces;
|
||||
|
||||
export type NexusGenScalarNames = keyof NexusGenScalars;
|
||||
|
||||
export type NexusGenUnionNames = keyof NexusGenUnions;
|
||||
|
||||
export type NexusGenDirectives = \\"TestFieldDirective\\"
|
||||
|
||||
export interface NexusGenDirectiveArgs {
|
||||
TestFieldDirective: {
|
||||
}
|
||||
}
|
||||
|
||||
export type NexusGenObjectsUsingAbstractStrategyIsTypeOf = never;
|
||||
|
||||
export type NexusGenAbstractsUsingStrategyResolveType = \\"ExampleUnion\\" | \\"Node\\";
|
||||
|
||||
export type NexusGenFeaturesConfig = {
|
||||
abstractTypeStrategies: {
|
||||
__typename: true
|
||||
isTypeOf: false
|
||||
resolveType: false
|
||||
}
|
||||
}
|
||||
|
||||
export interface NexusGenTypes {
|
||||
context: TestContext;
|
||||
inputTypes: NexusGenInputs;
|
||||
directives: NexusGenDirectives;
|
||||
directiveArgs: NexusGenDirectiveArgs;
|
||||
rootTypes: NexusGenRootTypes;
|
||||
inputTypeShapes: NexusGenInputs & NexusGenEnums & NexusGenScalars;
|
||||
argTypes: NexusGenArgTypes;
|
||||
fieldTypes: NexusGenFieldTypes;
|
||||
fieldTypeNames: NexusGenFieldTypeNames;
|
||||
allTypes: NexusGenAllTypes;
|
||||
typeInterfaces: NexusGenTypeInterfaces;
|
||||
objectNames: NexusGenObjectNames;
|
||||
inputNames: NexusGenInputNames;
|
||||
enumNames: NexusGenEnumNames;
|
||||
interfaceNames: NexusGenInterfaceNames;
|
||||
scalarNames: NexusGenScalarNames;
|
||||
unionNames: NexusGenUnionNames;
|
||||
allInputTypes: NexusGenTypes['inputNames'] | NexusGenTypes['enumNames'] | NexusGenTypes['scalarNames'];
|
||||
allOutputTypes: NexusGenTypes['objectNames'] | NexusGenTypes['enumNames'] | NexusGenTypes['unionNames'] | NexusGenTypes['interfaceNames'] | NexusGenTypes['scalarNames'];
|
||||
allNamedTypes: NexusGenTypes['allInputTypes'] | NexusGenTypes['allOutputTypes']
|
||||
abstractTypes: NexusGenTypes['interfaceNames'] | NexusGenTypes['unionNames'];
|
||||
abstractTypeMembers: NexusGenAbstractTypeMembers;
|
||||
objectsUsingAbstractStrategyIsTypeOf: NexusGenObjectsUsingAbstractStrategyIsTypeOf;
|
||||
abstractsUsingStrategyResolveType: NexusGenAbstractsUsingStrategyResolveType;
|
||||
features: NexusGenFeaturesConfig;
|
||||
}",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`typegenPrinter: no input changes should print the full output, with inputs 1`] = `
|
||||
"/**
|
||||
* This file was generated by Nexus Schema
|
||||
* Do not make changes to this file directly
|
||||
*/
|
||||
|
||||
|
||||
import type { core } from \\"nexus\\"
|
||||
|
||||
export interface NexusGenInputs {
|
||||
CreatePostInput: { // input type
|
||||
name: string; // String!
|
||||
author: string; // ID!
|
||||
geo: Array<Array<number | null>>; // [[Float]!]!
|
||||
}
|
||||
PostFilters: { // input type
|
||||
order: NexusGenEnums['OrderEnum']; // OrderEnum!
|
||||
search: string | null; // String
|
||||
}
|
||||
}
|
||||
|
||||
export interface NexusGenEnums {
|
||||
OrderEnum: \\"ASC\\" | \\"DESC\\"
|
||||
SomeEnum: \\"A\\" | \\"B\\"
|
||||
}
|
||||
|
||||
export interface NexusGenScalars {
|
||||
String: string
|
||||
Int: number
|
||||
Float: number
|
||||
Boolean: boolean
|
||||
ID: string
|
||||
UUID: any
|
||||
}
|
||||
|
||||
export interface NexusGenObjects {
|
||||
Mutation: {};
|
||||
Post: { // root type
|
||||
id: string; // ID!
|
||||
uuid: NexusGenScalars['UUID']; // UUID!
|
||||
author: NexusGenRootTypes['User']; // User!
|
||||
geo: ReadonlyArray<ReadonlyArray<number>>; // [[Float!]!]!
|
||||
messyGeo?: ReadonlyArray<ReadonlyArray<number> | null> | null; // [[Float!]]
|
||||
}
|
||||
Query: {};
|
||||
User: { // root type
|
||||
id: string; // ID!
|
||||
name: string; // String!
|
||||
email: string; // String!
|
||||
phone?: string | null; // String
|
||||
posts: ReadonlyArray<NexusGenRootTypes['Post']>; // [Post!]!
|
||||
outEnum?: NexusGenEnums['SomeEnum'] | null; // SomeEnum
|
||||
}
|
||||
}
|
||||
|
||||
export interface NexusGenInterfaces {
|
||||
Node: core.Discriminate<'User', 'optional'> | core.Discriminate<'Post', 'optional'>;
|
||||
}
|
||||
|
||||
export interface NexusGenUnions {
|
||||
ExampleUnion: core.Discriminate<'Post', 'optional'> | core.Discriminate<'User', 'optional'>;
|
||||
}
|
||||
|
||||
export type NexusGenRootTypes = NexusGenInterfaces & NexusGenObjects & NexusGenUnions
|
||||
|
||||
export type NexusGenAllTypes = NexusGenRootTypes & NexusGenScalars & NexusGenEnums
|
||||
|
||||
export interface NexusGenFieldTypes {
|
||||
Mutation: { // field return type
|
||||
someList: ReadonlyArray<string | null>; // [String]!
|
||||
createPost: NexusGenRootTypes['Post']; // Post!
|
||||
registerClick: NexusGenRootTypes['Query']; // Query!
|
||||
}
|
||||
Post: { // field return type
|
||||
id: string; // ID!
|
||||
uuid: NexusGenScalars['UUID']; // UUID!
|
||||
author: NexusGenRootTypes['User']; // User!
|
||||
geo: ReadonlyArray<ReadonlyArray<number>>; // [[Float!]!]!
|
||||
messyGeo: ReadonlyArray<ReadonlyArray<number> | null> | null; // [[Float!]]
|
||||
}
|
||||
Query: { // field return type
|
||||
user: NexusGenRootTypes['User']; // User!
|
||||
posts: ReadonlyArray<NexusGenRootTypes['Post']>; // [Post!]!
|
||||
unionField: NexusGenRootTypes['ExampleUnion']; // ExampleUnion!
|
||||
}
|
||||
User: { // field return type
|
||||
id: string; // ID!
|
||||
name: string; // String!
|
||||
email: string; // String!
|
||||
phone: string | null; // String
|
||||
posts: ReadonlyArray<NexusGenRootTypes['Post']>; // [Post!]!
|
||||
outEnum: NexusGenEnums['SomeEnum'] | null; // SomeEnum
|
||||
}
|
||||
Node: { // field return type
|
||||
id: string; // ID!
|
||||
}
|
||||
}
|
||||
|
||||
export interface NexusGenFieldTypeNames {
|
||||
Mutation: { // field return type name
|
||||
someList: 'String'
|
||||
createPost: 'Post'
|
||||
registerClick: 'Query'
|
||||
}
|
||||
Post: { // field return type name
|
||||
id: 'ID'
|
||||
uuid: 'UUID'
|
||||
author: 'User'
|
||||
geo: 'Float'
|
||||
messyGeo: 'Float'
|
||||
}
|
||||
Query: { // field return type name
|
||||
user: 'User'
|
||||
posts: 'Post'
|
||||
unionField: 'ExampleUnion'
|
||||
}
|
||||
User: { // field return type name
|
||||
id: 'ID'
|
||||
name: 'String'
|
||||
email: 'String'
|
||||
phone: 'String'
|
||||
posts: 'Post'
|
||||
outEnum: 'SomeEnum'
|
||||
}
|
||||
Node: { // field return type name
|
||||
id: 'ID'
|
||||
}
|
||||
}
|
||||
|
||||
export interface NexusGenArgTypes {
|
||||
Mutation: {
|
||||
someList: { // args
|
||||
items: Array<string | null>; // [String]!
|
||||
}
|
||||
createPost: { // args
|
||||
input: NexusGenInputs['CreatePostInput']; // CreatePostInput!
|
||||
}
|
||||
registerClick: { // args
|
||||
uuid?: NexusGenScalars['UUID'] | null; // UUID
|
||||
}
|
||||
}
|
||||
Query: {
|
||||
posts: { // args
|
||||
filters: NexusGenInputs['PostFilters']; // PostFilters!
|
||||
}
|
||||
}
|
||||
User: {
|
||||
name: { // args
|
||||
prefix?: string | null; // String
|
||||
}
|
||||
posts: { // args
|
||||
filters?: NexusGenInputs['PostFilters'] | null; // PostFilters
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export interface NexusGenAbstractTypeMembers {
|
||||
ExampleUnion: \\"Post\\" | \\"User\\"
|
||||
Node: \\"User\\" | \\"Post\\"
|
||||
}
|
||||
|
||||
export interface NexusGenTypeInterfaces {
|
||||
Post: \\"Node\\"
|
||||
User: \\"Node\\"
|
||||
}
|
||||
|
||||
export type NexusGenObjectNames = keyof NexusGenObjects;
|
||||
|
||||
export type NexusGenInputNames = keyof NexusGenInputs;
|
||||
|
||||
export type NexusGenEnumNames = keyof NexusGenEnums;
|
||||
|
||||
export type NexusGenInterfaceNames = keyof NexusGenInterfaces;
|
||||
|
||||
export type NexusGenScalarNames = keyof NexusGenScalars;
|
||||
|
||||
export type NexusGenUnionNames = keyof NexusGenUnions;
|
||||
|
||||
export type NexusGenDirectives = \\"TestFieldDirective\\"
|
||||
|
||||
export interface NexusGenDirectiveArgs {
|
||||
TestFieldDirective: {
|
||||
}
|
||||
}
|
||||
|
||||
export type NexusGenObjectsUsingAbstractStrategyIsTypeOf = never;
|
||||
|
||||
export type NexusGenAbstractsUsingStrategyResolveType = \\"ExampleUnion\\" | \\"Node\\";
|
||||
|
||||
export type NexusGenFeaturesConfig = {
|
||||
abstractTypeStrategies: {
|
||||
__typename: true
|
||||
isTypeOf: false
|
||||
resolveType: false
|
||||
}
|
||||
}
|
||||
|
||||
export interface NexusGenTypes {
|
||||
context: any;
|
||||
inputTypes: NexusGenInputs;
|
||||
directives: NexusGenDirectives;
|
||||
directiveArgs: NexusGenDirectiveArgs;
|
||||
rootTypes: NexusGenRootTypes;
|
||||
inputTypeShapes: NexusGenInputs & NexusGenEnums & NexusGenScalars;
|
||||
argTypes: NexusGenArgTypes;
|
||||
fieldTypes: NexusGenFieldTypes;
|
||||
fieldTypeNames: NexusGenFieldTypeNames;
|
||||
allTypes: NexusGenAllTypes;
|
||||
typeInterfaces: NexusGenTypeInterfaces;
|
||||
objectNames: NexusGenObjectNames;
|
||||
inputNames: NexusGenInputNames;
|
||||
enumNames: NexusGenEnumNames;
|
||||
interfaceNames: NexusGenInterfaceNames;
|
||||
scalarNames: NexusGenScalarNames;
|
||||
unionNames: NexusGenUnionNames;
|
||||
allInputTypes: NexusGenTypes['inputNames'] | NexusGenTypes['enumNames'] | NexusGenTypes['scalarNames'];
|
||||
allOutputTypes: NexusGenTypes['objectNames'] | NexusGenTypes['enumNames'] | NexusGenTypes['unionNames'] | NexusGenTypes['interfaceNames'] | NexusGenTypes['scalarNames'];
|
||||
allNamedTypes: NexusGenTypes['allInputTypes'] | NexusGenTypes['allOutputTypes']
|
||||
abstractTypes: NexusGenTypes['interfaceNames'] | NexusGenTypes['unionNames'];
|
||||
abstractTypeMembers: NexusGenAbstractTypeMembers;
|
||||
objectsUsingAbstractStrategyIsTypeOf: NexusGenObjectsUsingAbstractStrategyIsTypeOf;
|
||||
abstractsUsingStrategyResolveType: NexusGenAbstractsUsingStrategyResolveType;
|
||||
features: NexusGenFeaturesConfig;
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`typegenPrinter: no input changes should print the full output, with inputs 2`] = `
|
||||
"/**
|
||||
* This file was generated by Nexus Schema
|
||||
* Do not make changes to this file directly
|
||||
*/
|
||||
|
||||
import type { NexusGenTypes } from './types.gen'
|
||||
|
||||
|
||||
|
||||
|
||||
declare global {
|
||||
interface NexusGen extends NexusGenTypes {}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
declare global {
|
||||
interface NexusGenPluginTypeConfig<TypeName extends string> {
|
||||
}
|
||||
interface NexusGenPluginInputTypeConfig<TypeName extends string> {
|
||||
}
|
||||
interface NexusGenPluginFieldConfig<TypeName extends string, FieldName extends string> {
|
||||
}
|
||||
interface NexusGenPluginInputFieldConfig<TypeName extends string, FieldName extends string> {
|
||||
}
|
||||
interface NexusGenPluginSchemaConfig {
|
||||
}
|
||||
interface NexusGenPluginArgConfig {
|
||||
}
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`typegenPrinter: useReadonlyArrayForInputs should print the full output using ReadonlyArray in input types 1`] = `
|
||||
Object {
|
||||
"globalTypes": "/**
|
||||
* This file was generated by Nexus Schema
|
||||
* Do not make changes to this file directly
|
||||
*/
|
||||
|
||||
import type { NexusGenTypes } from './types-useReadonlyArrayForInputs.gen'
|
||||
|
||||
|
||||
|
||||
|
||||
declare global {
|
||||
interface NexusGen extends NexusGenTypes {}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
declare global {
|
||||
interface NexusGenPluginTypeConfig<TypeName extends string> {
|
||||
}
|
||||
interface NexusGenPluginInputTypeConfig<TypeName extends string> {
|
||||
}
|
||||
interface NexusGenPluginFieldConfig<TypeName extends string, FieldName extends string> {
|
||||
}
|
||||
interface NexusGenPluginInputFieldConfig<TypeName extends string, FieldName extends string> {
|
||||
}
|
||||
interface NexusGenPluginSchemaConfig {
|
||||
}
|
||||
interface NexusGenPluginArgConfig {
|
||||
}
|
||||
}",
|
||||
"tsTypes": "/**
|
||||
* This file was generated by Nexus Schema
|
||||
* Do not make changes to this file directly
|
||||
*/
|
||||
|
||||
|
||||
import type { TestContext } from \\"./../__helpers/index\\"
|
||||
import type { core } from \\"nexus\\"
|
||||
|
||||
export interface NexusGenInputs {
|
||||
CreatePostInput: { // input type
|
||||
author: string; // ID!
|
||||
geo: ReadonlyArray<ReadonlyArray<number | null>>; // [[Float]!]!
|
||||
name: string; // String!
|
||||
}
|
||||
PostFilters: { // input type
|
||||
order: NexusGenEnums['OrderEnum']; // OrderEnum!
|
||||
search: string | null; // String
|
||||
}
|
||||
}
|
||||
|
||||
export interface NexusGenEnums {
|
||||
OrderEnum: \\"ASC\\" | \\"DESC\\"
|
||||
SomeEnum: \\"A\\" | \\"B\\"
|
||||
}
|
||||
|
||||
export interface NexusGenScalars {
|
||||
String: string
|
||||
Int: number
|
||||
Float: number
|
||||
Boolean: boolean
|
||||
ID: string
|
||||
UUID: string
|
||||
}
|
||||
|
||||
export interface NexusGenObjects {
|
||||
Mutation: {};
|
||||
Post: { // root type
|
||||
author: NexusGenRootTypes['User']; // User!
|
||||
geo: ReadonlyArray<ReadonlyArray<number>>; // [[Float!]!]!
|
||||
id: string; // ID!
|
||||
messyGeo?: ReadonlyArray<ReadonlyArray<number> | null> | null; // [[Float!]]
|
||||
uuid: NexusGenScalars['UUID']; // UUID!
|
||||
}
|
||||
Query: {};
|
||||
User: { // root type
|
||||
email: string; // String!
|
||||
id: string; // ID!
|
||||
name: string; // String!
|
||||
outEnum?: NexusGenEnums['SomeEnum'] | null; // SomeEnum
|
||||
phone?: string | null; // String
|
||||
posts: ReadonlyArray<NexusGenRootTypes['Post']>; // [Post!]!
|
||||
}
|
||||
}
|
||||
|
||||
export interface NexusGenInterfaces {
|
||||
Node: core.Discriminate<'Post', 'optional'> | core.Discriminate<'User', 'optional'>;
|
||||
}
|
||||
|
||||
export interface NexusGenUnions {
|
||||
ExampleUnion: core.Discriminate<'Post', 'optional'> | core.Discriminate<'User', 'optional'>;
|
||||
}
|
||||
|
||||
export type NexusGenRootTypes = NexusGenInterfaces & NexusGenObjects & NexusGenUnions
|
||||
|
||||
export type NexusGenAllTypes = NexusGenRootTypes & NexusGenScalars & NexusGenEnums
|
||||
|
||||
export interface NexusGenFieldTypes {
|
||||
Mutation: { // field return type
|
||||
createPost: NexusGenRootTypes['Post']; // Post!
|
||||
registerClick: NexusGenRootTypes['Query']; // Query!
|
||||
someList: ReadonlyArray<string | null>; // [String]!
|
||||
}
|
||||
Post: { // field return type
|
||||
author: NexusGenRootTypes['User']; // User!
|
||||
geo: ReadonlyArray<ReadonlyArray<number>>; // [[Float!]!]!
|
||||
id: string; // ID!
|
||||
messyGeo: ReadonlyArray<ReadonlyArray<number> | null> | null; // [[Float!]]
|
||||
uuid: NexusGenScalars['UUID']; // UUID!
|
||||
}
|
||||
Query: { // field return type
|
||||
posts: ReadonlyArray<NexusGenRootTypes['Post']>; // [Post!]!
|
||||
unionField: NexusGenRootTypes['ExampleUnion']; // ExampleUnion!
|
||||
user: NexusGenRootTypes['User']; // User!
|
||||
}
|
||||
User: { // field return type
|
||||
email: string; // String!
|
||||
id: string; // ID!
|
||||
name: string; // String!
|
||||
outEnum: NexusGenEnums['SomeEnum'] | null; // SomeEnum
|
||||
phone: string | null; // String
|
||||
posts: ReadonlyArray<NexusGenRootTypes['Post']>; // [Post!]!
|
||||
}
|
||||
Node: { // field return type
|
||||
id: string; // ID!
|
||||
}
|
||||
}
|
||||
|
||||
export interface NexusGenFieldTypeNames {
|
||||
Mutation: { // field return type name
|
||||
createPost: 'Post'
|
||||
registerClick: 'Query'
|
||||
someList: 'String'
|
||||
}
|
||||
Post: { // field return type name
|
||||
author: 'User'
|
||||
geo: 'Float'
|
||||
id: 'ID'
|
||||
messyGeo: 'Float'
|
||||
uuid: 'UUID'
|
||||
}
|
||||
Query: { // field return type name
|
||||
posts: 'Post'
|
||||
unionField: 'ExampleUnion'
|
||||
user: 'User'
|
||||
}
|
||||
User: { // field return type name
|
||||
email: 'String'
|
||||
id: 'ID'
|
||||
name: 'String'
|
||||
outEnum: 'SomeEnum'
|
||||
phone: 'String'
|
||||
posts: 'Post'
|
||||
}
|
||||
Node: { // field return type name
|
||||
id: 'ID'
|
||||
}
|
||||
}
|
||||
|
||||
export interface NexusGenArgTypes {
|
||||
Mutation: {
|
||||
createPost: { // args
|
||||
input: NexusGenInputs['CreatePostInput']; // CreatePostInput!
|
||||
}
|
||||
registerClick: { // args
|
||||
uuid?: NexusGenScalars['UUID'] | null; // UUID
|
||||
}
|
||||
someList: { // args
|
||||
items: ReadonlyArray<string | null>; // [String]!
|
||||
}
|
||||
}
|
||||
Query: {
|
||||
posts: { // args
|
||||
filters: NexusGenInputs['PostFilters']; // PostFilters!
|
||||
}
|
||||
}
|
||||
User: {
|
||||
name: { // args
|
||||
prefix?: string | null; // String
|
||||
}
|
||||
posts: { // args
|
||||
filters?: NexusGenInputs['PostFilters'] | null; // PostFilters
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export interface NexusGenAbstractTypeMembers {
|
||||
ExampleUnion: \\"Post\\" | \\"User\\"
|
||||
Node: \\"Post\\" | \\"User\\"
|
||||
}
|
||||
|
||||
export interface NexusGenTypeInterfaces {
|
||||
Post: \\"Node\\"
|
||||
User: \\"Node\\"
|
||||
}
|
||||
|
||||
export type NexusGenObjectNames = keyof NexusGenObjects;
|
||||
|
||||
export type NexusGenInputNames = keyof NexusGenInputs;
|
||||
|
||||
export type NexusGenEnumNames = keyof NexusGenEnums;
|
||||
|
||||
export type NexusGenInterfaceNames = keyof NexusGenInterfaces;
|
||||
|
||||
export type NexusGenScalarNames = keyof NexusGenScalars;
|
||||
|
||||
export type NexusGenUnionNames = keyof NexusGenUnions;
|
||||
|
||||
export type NexusGenDirectives = \\"TestFieldDirective\\"
|
||||
|
||||
export interface NexusGenDirectiveArgs {
|
||||
TestFieldDirective: {
|
||||
}
|
||||
}
|
||||
|
||||
export type NexusGenObjectsUsingAbstractStrategyIsTypeOf = never;
|
||||
|
||||
export type NexusGenAbstractsUsingStrategyResolveType = \\"ExampleUnion\\" | \\"Node\\";
|
||||
|
||||
export type NexusGenFeaturesConfig = {
|
||||
abstractTypeStrategies: {
|
||||
__typename: true
|
||||
isTypeOf: false
|
||||
resolveType: false
|
||||
}
|
||||
}
|
||||
|
||||
export interface NexusGenTypes {
|
||||
context: TestContext;
|
||||
inputTypes: NexusGenInputs;
|
||||
directives: NexusGenDirectives;
|
||||
directiveArgs: NexusGenDirectiveArgs;
|
||||
rootTypes: NexusGenRootTypes;
|
||||
inputTypeShapes: NexusGenInputs & NexusGenEnums & NexusGenScalars;
|
||||
argTypes: NexusGenArgTypes;
|
||||
fieldTypes: NexusGenFieldTypes;
|
||||
fieldTypeNames: NexusGenFieldTypeNames;
|
||||
allTypes: NexusGenAllTypes;
|
||||
typeInterfaces: NexusGenTypeInterfaces;
|
||||
objectNames: NexusGenObjectNames;
|
||||
inputNames: NexusGenInputNames;
|
||||
enumNames: NexusGenEnumNames;
|
||||
interfaceNames: NexusGenInterfaceNames;
|
||||
scalarNames: NexusGenScalarNames;
|
||||
unionNames: NexusGenUnionNames;
|
||||
allInputTypes: NexusGenTypes['inputNames'] | NexusGenTypes['enumNames'] | NexusGenTypes['scalarNames'];
|
||||
allOutputTypes: NexusGenTypes['objectNames'] | NexusGenTypes['enumNames'] | NexusGenTypes['unionNames'] | NexusGenTypes['interfaceNames'] | NexusGenTypes['scalarNames'];
|
||||
allNamedTypes: NexusGenTypes['allInputTypes'] | NexusGenTypes['allOutputTypes']
|
||||
abstractTypes: NexusGenTypes['interfaceNames'] | NexusGenTypes['unionNames'];
|
||||
abstractTypeMembers: NexusGenAbstractTypeMembers;
|
||||
objectsUsingAbstractStrategyIsTypeOf: NexusGenObjectsUsingAbstractStrategyIsTypeOf;
|
||||
abstractsUsingStrategyResolveType: NexusGenAbstractsUsingStrategyResolveType;
|
||||
features: NexusGenFeaturesConfig;
|
||||
}",
|
||||
}
|
||||
`;
|
||||
|
|
@ -1,8 +1,10 @@
|
|||
export const EXAMPLE_SDL = `
|
||||
directive @TestFieldDirective on FIELD_DEFINITION
|
||||
|
||||
scalar UUID
|
||||
|
||||
type Query {
|
||||
user: User!
|
||||
user: User! @TestFieldDirective
|
||||
posts(filters: PostFilters!): [Post!]!
|
||||
unionField: ExampleUnion!
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,8 +27,10 @@ export function typeCheck(
|
|||
|
||||
const project = new tsm.Project({
|
||||
tsConfigFilePath,
|
||||
compilerOptions,
|
||||
addFilesFromTsConfig: true,
|
||||
compilerOptions: {
|
||||
...compilerOptions,
|
||||
useUnknownInCatchVariables: false,
|
||||
},
|
||||
})
|
||||
|
||||
if (fileNames.length) {
|
||||
|
|
|
|||
|
|
@ -44,17 +44,17 @@ beforeAll(() => {
|
|||
|
||||
it('can be implemented by object types', async () => {
|
||||
expect(
|
||||
await graphql(
|
||||
await graphql({
|
||||
schema,
|
||||
`
|
||||
source: `
|
||||
{
|
||||
user(int: 1, bool: true, float: 123.45, str: "Test") {
|
||||
id
|
||||
name
|
||||
}
|
||||
}
|
||||
`
|
||||
)
|
||||
`,
|
||||
})
|
||||
).toMatchSnapshot()
|
||||
})
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import * as path from 'path'
|
||||
import { core, enumType, makeSchema, objectType, queryType } from '../src'
|
||||
import type { NexusGraphQLSchema } from '../src/core'
|
||||
import { A, B } from './_types'
|
||||
|
||||
const { TypegenPrinter, TypegenMetadata } = core
|
||||
|
|
@ -31,7 +32,10 @@ function getSchemaWithConstEnums() {
|
|||
types: [
|
||||
enumType({
|
||||
name: 'B',
|
||||
members: [B.NINE, B.TEN],
|
||||
members: {
|
||||
NINE: B.NINE,
|
||||
TEN: B.TEN,
|
||||
},
|
||||
}),
|
||||
queryType({
|
||||
definition(t) {
|
||||
|
|
@ -49,7 +53,9 @@ describe('sourceTypes', () => {
|
|||
beforeEach(async () => {
|
||||
metadata = new TypegenMetadata({
|
||||
outputs: {
|
||||
typegen: path.join(__dirname, 'test-gen.ts'),
|
||||
typegen: {
|
||||
outputPath: path.join(__dirname, 'test-gen.ts'),
|
||||
},
|
||||
schema: path.join(__dirname, 'test-gen.graphql'),
|
||||
},
|
||||
sourceTypes: {
|
||||
|
|
@ -70,22 +76,24 @@ describe('sourceTypes', () => {
|
|||
it('can match source types to regular enums', async () => {
|
||||
const schema = getSchemaWithNormalEnums()
|
||||
const typegenInfo = await metadata.getTypegenInfo(schema)
|
||||
const typegen = new TypegenPrinter(schema, {
|
||||
const typegen = new TypegenPrinter(schema as NexusGraphQLSchema, {
|
||||
...typegenInfo,
|
||||
typegenPath: '',
|
||||
})
|
||||
|
||||
// @ts-expect-error
|
||||
expect(typegen.printEnumTypeMap()).toMatchSnapshot()
|
||||
})
|
||||
|
||||
it('can match source types for const enums', async () => {
|
||||
const schema = getSchemaWithConstEnums()
|
||||
const typegenInfo = await metadata.getTypegenInfo(schema)
|
||||
const typegen = new TypegenPrinter(schema, {
|
||||
const typegen = new TypegenPrinter(schema as NexusGraphQLSchema, {
|
||||
...typegenInfo,
|
||||
typegenPath: '',
|
||||
})
|
||||
|
||||
// @ts-expect-error
|
||||
expect(typegen.printEnumTypeMap()).toMatchSnapshot()
|
||||
})
|
||||
})
|
||||
|
|
@ -109,7 +117,7 @@ describe('sourceTypings', () => {
|
|||
outputs: false,
|
||||
})
|
||||
const typegenInfo = await metadata.getTypegenInfo(schema)
|
||||
const typegen = new TypegenPrinter(schema, {
|
||||
const typegen = new TypegenPrinter(schema as NexusGraphQLSchema, {
|
||||
...typegenInfo,
|
||||
typegenPath: '',
|
||||
})
|
||||
|
|
@ -137,7 +145,7 @@ describe('sourceTypings', () => {
|
|||
})
|
||||
|
||||
const typegenInfo = await metadata.getTypegenInfo(schema)
|
||||
const typegen = new TypegenPrinter(schema, {
|
||||
const typegen = new TypegenPrinter(schema as NexusGraphQLSchema, {
|
||||
...typegenInfo,
|
||||
typegenPath: '',
|
||||
})
|
||||
|
|
@ -168,7 +176,7 @@ describe('sourceTypings', () => {
|
|||
})
|
||||
|
||||
const typegenInfo = await metadata.getTypegenInfo(schema)
|
||||
const typegen = new TypegenPrinter(schema, {
|
||||
const typegen = new TypegenPrinter(schema as NexusGraphQLSchema, {
|
||||
...typegenInfo,
|
||||
typegenPath: '',
|
||||
})
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue