From 3531a31f800168a46c99b541661ef568b1d572d8 Mon Sep 17 00:00:00 2001 From: Jason Kuhrt Date: Fri, 11 Dec 2020 14:57:09 -0500 Subject: [PATCH] docs: cover root types with jsdoc --- src/definitions/definitionBlocks.ts | 6 +- src/definitions/mutationField.ts | 114 +++++++++++++- src/definitions/mutationType.ts | 39 +++++ src/definitions/nonNull.ts | 55 ++++++- src/definitions/nullable.ts | 54 ++++++- src/definitions/queryField.ts | 102 +++++++++++- src/definitions/queryType.ts | 39 +++++ src/definitions/subscriptionField.ts | 222 ++++++++++++++++++++++++++- src/definitions/subscriptionType.ts | 121 ++++++++++++++- 9 files changed, 738 insertions(+), 14 deletions(-) diff --git a/src/definitions/definitionBlocks.ts b/src/definitions/definitionBlocks.ts index 53ee8062..97bda285 100644 --- a/src/definitions/definitionBlocks.ts +++ b/src/definitions/definitionBlocks.ts @@ -6,8 +6,10 @@ import { AllNexusInputTypeDefs, AllNexusOutputTypeDefs, NexusWrapKind } from './ import { BaseScalars } from './_types' export interface CommonFieldConfig { + //todo /** The description to annotate the GraphQL SDL */ description?: string + //todo /** * 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. @@ -372,7 +374,7 @@ export class OutputDefinitionBlock { } /** - * [API Docs](https://nxs.li/docs/api/nonNull) | [Nexus Nullability + * [API Docs](https://nxs.li/docs/api/nonNull) | [Nullability * Guide](https://nexusjs.org/docs/guides/nullability) | [GraphQL 2018 * Spec](https://spec.graphql.org/June2018/#sec-Type-System.Non-Null) * @@ -410,7 +412,7 @@ export class OutputDefinitionBlock { } /** - * [API Docs](https://nxs.li/docs/api/null) | [Nexus Nullability + * [API Docs](https://nxs.li/docs/api/null) | [Nullability * Guide](https://nexusjs.org/docs/guides/nullability) | [GraphQL 2018 * Spec](https://spec.graphql.org/June2018/#sec-Type-System.Non-Null) * diff --git a/src/definitions/mutationField.ts b/src/definitions/mutationField.ts index 1bc24b56..819ab6b2 100644 --- a/src/definitions/mutationField.ts +++ b/src/definitions/mutationField.ts @@ -5,12 +5,122 @@ export type MutationFieldConfig = | FieldOutConfig<'Mutation', FieldName> | (() => FieldOutConfig<'Mutation', FieldName>) +/** + * [API Docs](https://nexusjs.org/docs/api/mutation-field) | [2018 GraphQL + * Spec](https://spec.graphql.org/June2018/#sec-Mutation) + * + * Define one or more fields on the Mutation type. + * + * Use this if you are going to modularize your schema and thus be wanting to contribute fields to Mutation + * type from multiple modules. You do not have to have previously defined a Mutatin type before using this. + * If you haven't Nexus will create one automatically for you. + * + * This is shorthand for: + * + * `extendType({ type: 'Mutation' })` + * + * If you need to leverage plugins or define multiple fields then use the typeBuilder overload variant of this + * function. Otherwise you may prefer to the field name/config variant. + * + * @example + * // User.ts + * // Overload 1: Type Builder + * + * mutationField((t) => { + * t.field('signup', { + * type: 'User', + * args: { + * email: stringArg(), + * }, + * // ... + * }) + * t.field('deactivate', { + * type: 'User', + * args: { + * userId: idArg(), + * }, + * // ... + * }) + * }) + * + * @example + * // User.ts + * // Overload 2: Field Name/Config + * + * mutationField('signup', { + * type: 'User', + * args: { + * email: stringArg(), + * }, + * // ... + * }) + * + * @param typeBuilder The same as the "definition" method you define on object type configurations. + */ export function mutationField( - fieldFn: (t: OutputDefinitionBlock<'Mutation'>) => void + typeBuilder: (t: OutputDefinitionBlock<'Mutation'>) => void ): NexusExtendTypeDef<'Mutation'> +/** + * [API Docs](https://nexusjs.org/docs/api/mutation-field) | [2018 GraphQL + * Spec](https://spec.graphql.org/June2018/#sec-Mutation) + * + * Define one or more fields on the mutation type. + * + * The Mutation type is one of three [root types](https://spec.graphql.org/June2018/#sec-Root-Operation-Types) + * in GraphQL and its fields represent API operations your clients can run that may have side-effects. + * + * Use this instead of mutationType if you are going to modularize your schema and thus be wanting to + * contribute fields to Mutation type from multiple modules. You do not have to have previously defined a + * Mutatin type before using this. If you haven't Nexus will create one automatically for you. + * + * This is shorthand for: + * + * `extendType({ type: 'Mutation' })` + * + * If you need to leverage plugins or define multiple fields then use the typeBuilder overload variant of this + * function. Otherwise you may prefer to the field name/config variant. + * + * @example + * // User.ts + * // Overload 1: Type Builder + * + * mutationField((t) => { + * t.field('signup', { + * type: 'User', + * args: { + * email: stringArg(), + * }, + * // ... + * }) + * t.field('deactivate', { + * type: 'User', + * args: { + * userId: idArg(), + * }, + * // ... + * }) + * }) + * + * @example + * // User.ts + * // Overload 2: Field Name/Config + * + * mutationField('signup', { + * type: 'User', + * args: { + * email: stringArg(), + * }, + * // ... + * }) + * + * @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]* + * @param config The same type of configuration you would pass to t.field("...", config) + */ export function mutationField( - fieldName: FieldName, + name: FieldName, config: MutationFieldConfig ): NexusExtendTypeDef<'Mutation'> diff --git a/src/definitions/mutationType.ts b/src/definitions/mutationType.ts index 57e95c31..510914d5 100644 --- a/src/definitions/mutationType.ts +++ b/src/definitions/mutationType.ts @@ -1,5 +1,44 @@ import { NexusObjectTypeConfig, objectType } from './objectType' +/** + * [2018 GraphQL Spec](https://spec.graphql.org/June2018/#sec-Mutation) + * + * Define a Mutation type. + * + * The Mutation type is one of three [root types](https://spec.graphql.org/June2018/#sec-Root-Operation-Types) + * in GraphQL and its fields represent API operations your clients can run that may have side-effects. + * + * You can only have one of these in your schema. If you are going to modularize your schema and thus be + * wanting to contribute fields to Mutation type from multiple modules then use + * [mutationField](https://nxs.li/docs/api/mutation-field) intead. + * + * This is a shorthand for: + * + * `objectType({ name: 'Mutation' })` + * + * @example + * mutationType({ + * definitin(t) { + * t.field('signup', { + * type: 'User', + * args: { + * email: stringArg(), + * }, + * // ... + * }) + * t.field('buy', { + * type: 'Recipet', + * args: { + * productId: idArg(), + * }, + * // ... + * }) + * }, + * }) + * + * @param config Specify your Mutation type's fields, description, and more. See each config property's jsDoc + * for more detail. + */ export function mutationType(config: Omit, 'name'>) { return objectType({ ...config, name: 'Mutation' }) } diff --git a/src/definitions/nonNull.ts b/src/definitions/nonNull.ts index d8d875c6..adfe63fe 100644 --- a/src/definitions/nonNull.ts +++ b/src/definitions/nonNull.ts @@ -1,6 +1,6 @@ +import { isNonNullType, isType } from 'graphql' import { isNexusNonNullTypeDef, isNexusNullTypeDef, isNexusStruct, NexusNonNullableTypes } from './wrapping' import { NexusTypes, withNexusSymbol } from './_types' -import { isNonNullType, isType } from 'graphql' export class NexusNonNullDef { // @ts-ignore @@ -16,6 +16,59 @@ export class NexusNonNullDef { withNexusSymbol(NexusNonNullDef, NexusTypes.NonNull) +/** + * [API Docs](https://nxs.li/docs/api/nonNull) | [Nullability Guide](https://nxs.li/guides/nullability) | + * [2018 GraphQL Spec](https://spec.graphql.org/June2018/#sec-Type-System.Non-Null) + * + * Modify a type to be Non-Null. + * + * In Nexus input postition types are non-null by default so this has no use for them (until you've changed + * the default). On the other hand output postition types are nullable by default so use this to modify them + * (until you've changed the default). + * + * If you find yourself using this a large majority of the time then consider changing your nullability defaults. + * + * @example + * objectType({ + * name: 'User', + * nonNullDefaults: { + * inputs: false, + * }, + * definition(t) { + * t.field('id', { + * type: nonNull('ID'), + * }) + * t.field('bio', { + * args: { + * format: nonNull(booleanArg()), + * maxWords: intArg(), + * }, + * type: 'String', + * }) + * }, + * }) + * + * // GraphQL SDL + * // ----------- + * // + * // type User { + * // id: ID! + * // bio(maxWords: Int, format: Boolean!): String + * // } + * + * @param type The type to wrap in Non-Null. This may be expressed in one of three ways: + * + * 1. As string literals matching the name of a builtin scalar. E.g.: 'ID', 'String', ... + * + * 2. As string literals matching the name of another type. E.g.: 'User', 'Location', ... Thanks to + * [Nexus' reflection + * system](https://nxs.li/guides/reflection) this is typesafe and autocompletable. This is the idiomatic + * approach in Nexus because it avoids excessive importing and circular references. + * + * 3. As references to other enums or object type definitions. E.g.: User, Location + * + * You may also use other type modifier helpers like list() which in turn accept one of the three + */ export function nonNull(type: TypeName) { if (isNexusNonNullTypeDef(type) || isNonNullType(type)) { return type diff --git a/src/definitions/nullable.ts b/src/definitions/nullable.ts index 3bef1529..ebd186a4 100644 --- a/src/definitions/nullable.ts +++ b/src/definitions/nullable.ts @@ -16,7 +16,59 @@ export class NexusNullDef { withNexusSymbol(NexusNullDef, NexusTypes.Null) -/** Null() */ +/** + * [API Docs](https://nxs.li/docs/api/nonNull) | [Nullability Guide](https://nxs.li/guides/nullability) | + * [2018 GraphQL Spec](https://spec.graphql.org/June2018/#sec-Type-System.Non-Null) + * + * Remove the Non-Null wrapper from a type, if present. + * + * In Nexus input postition types are non-null by default so this is useful to modify them (until you've + * changed the default). On the other hand output postition types are nullable by default so this has no use + * for them (until you've changed the default). + * + * If you find yourself using this a large majority of the time then consider changing your nullability defaults. + * + * @example + * objectType({ + * name: 'User', + * nonNullDefaults: { + * outputs: true, + * }, + * definition(t) { + * t.field('id', { + * type: 'ID', + * }) + * t.field('bio', { + * args: { + * format: booleanArg(), + * maxWords: nullable(intArg()), + * }, + * type: nullable('String'), + * }) + * }, + * }) + * + * // GraphQL SDL + * // ----------- + * // + * // type User { + * // id: ID! + * // bio(maxWords: Int, format: Boolean!): String + * // } + * + * @param type The type to wrap in Non-Null. This may be expressed in one of three ways: + * + * 1. As string literals matching the name of a builtin scalar. E.g.: 'ID', 'String', ... + * + * 2. As string literals matching the name of another type. E.g.: 'User', 'Location', ... Thanks to + * [Nexus' reflection + * system](https://nxs.li/guides/reflection) this is typesafe and autocompletable. This is the idiomatic + * approach in Nexus because it avoids excessive importing and circular references. + * + * 3. As references to other enums or object type definitions. E.g.: User, Location + * + * You may also use other type modifier helpers like list() which in turn accept one of the three + */ export function nullable(type: TypeName) { if (isNexusNonNullTypeDef(type)) { return new NexusNullDef(type.ofNexusType) diff --git a/src/definitions/queryField.ts b/src/definitions/queryField.ts index 5784347f..b9ae2757 100644 --- a/src/definitions/queryField.ts +++ b/src/definitions/queryField.ts @@ -5,10 +5,108 @@ export type QueryFieldConfig = | FieldOutConfig<'Query', FieldName> | (() => FieldOutConfig<'Query', FieldName>) -export function queryField(fieldFn: (t: OutputDefinitionBlock<'Query'>) => void): NexusExtendTypeDef<'Query'> +/** + * [API Docs](https://nexusjs.org/docs/api/query-field) | [2018 GraphQL + * Spec](https://spec.graphql.org/June2018/#sec-Query) + * + * Define one or more fields on the Query type. + * + * The Query type is one of three [root types](https://spec.graphql.org/June2018/#sec-Root-Operation-Types) in + * GraphQL and its fields represent API operations your clients can run that must not have side-effects. + * + * Use this instead of queryType if you are going to modularize your schema and thus be wanting to contribute + * fields to Query type from multiple modules. You do not have to have previously defined a Query type before + * using this. If you haven't Nexus will create one automatically for you. + * + * This is shorthand for: + * + * `extendType({ type: 'Query' })` + * + * If you need to leverage plugins or define multiple fields then use the typeBuilder overload variant of this + * function. Otherwise you may prefer to the field name/config variant. + * + * @example + * // User.ts + * // Overload 1: Type Builder + * + * queryField((t) => { + * t.field('user', { + * type: 'User', + * args: { + * id: idArg(), + * }, + * // ... + * }) + * }) + * + * @example + * // User.ts + * // Overload 2: Field Name/Config + * + * queryField('user', { + * type: 'User', + * args: { + * id: idArg(), + * }, + * // ... + * }) + * + * @param typeBuilder The same as the "definition" method you define on object type configurations. + */ +export function queryField( + typeBuilder: (t: OutputDefinitionBlock<'Query'>) => void +): NexusExtendTypeDef<'Query'> +/** + * [API Docs](https://nexusjs.org/docs/api/query-field) | [2018 GraphQL + * Spec](https://spec.graphql.org/June2018/#sec-Query) + * + * Define one or more fields on the Query type. + * + * Use this if you are going to modularize your schema and thus be wanting to contribute fields to Query type + * from multiple modules. You do not have to have previously defined a Query type before using this. If you + * haven't Nexus will create one automatically for you. + * + * This is shorthand for: + * + * `extendType({ type: 'Query' })` + * + * If you need to leverage plugins or define multiple fields then use the typeBuilder overload variant of this + * function. Otherwise you may prefer to the field name/config variant. + * + * @example + * // User.ts + * // Overload 1: Type Builder + * + * queryField((t) => { + * t.field('user', { + * type: 'User', + * args: { + * id: idArg(), + * }, + * // ... + * }) + * }) + * + * @example + * // User.ts + * // Overload 2: Field Name/Config + * + * queryField('user', { + * type: 'User', + * args: { + * id: idArg(), + * }, + * // ... + * }) + * + * @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]* + * @param config The same type of configuration you would pass to t.field("...", config) + */ export function queryField( - fieldName: FieldName, + name: FieldName, config: QueryFieldConfig ): NexusExtendTypeDef<'Query'> diff --git a/src/definitions/queryType.ts b/src/definitions/queryType.ts index d95f065e..70904959 100644 --- a/src/definitions/queryType.ts +++ b/src/definitions/queryType.ts @@ -1,5 +1,44 @@ import { NexusObjectTypeConfig, objectType } from './objectType' +/** + * [2018 GraphQL Spec](https://spec.graphql.org/June2018/#sec-Query) + * + * Define a Query type. + * + * The Query type is one of three [root types](https://spec.graphql.org/June2018/#sec-Root-Operation-Types) in + * GraphQL and its fields represent API operations your clients can run that must not have side-effects. + * + * You can only have one of these in your schema. If you are going to modularize your schema and thus be + * wanting to contribute fields to Query type from multiple modules then use + * [queryField](https://nxs.li/docs/api/query-field) intead. + * + * This is a shorthand for: + * + * `objectType({ name: 'Query' })` + * + * @example + * queryType({ + * definitin(t) { + * t.field('user', { + * type: 'User', + * args: { + * id: idArg(), + * }, + * // ... + * }) + * t.field('search', { + * type: 'SearchResult', + * args: { + * pattern: stringArg(), + * }, + * // ... + * }) + * }, + * }) + * + * @param config Specify your Query type's fields, description, and more. See each config property's jsDoc + * for more detail. + */ export function queryType(config: Omit, 'name'>) { return objectType({ ...config, name: 'Query' }) } diff --git a/src/definitions/subscriptionField.ts b/src/definitions/subscriptionField.ts index 26100df5..505677d3 100644 --- a/src/definitions/subscriptionField.ts +++ b/src/definitions/subscriptionField.ts @@ -5,16 +5,232 @@ export type SubscriptionFieldConfig = | SubscriptionTypeConfig | (() => SubscriptionTypeConfig) +/** + * [2018 GraphQL Spec](https://spec.graphql.org/June2018/#sec-Subscription) + * + * Define one or more fields on the Subscription type. + * + * This is shorthand for: + * + * `extendType({ type: 'Subscription' })` + * + * The Subscription type is one of three [root + * types](https://spec.graphql.org/June2018/#sec-Root-Operation-Types) in GraphQL and its fields represent + * API operations your clients can run to be pushed data changes over time. + * + * Use this instead of subscriptionType if you are going to modularize your schema and thus be wanting to + * contribute fields to the Subscription type from multiple modules. You do not have to have previously + * defined a Query type before using this. If you haven't Nexus will create one automatically for you. + * + * Note that the main difference about Subscription type from other object types is that its field + * configurations require a special "subscribe" method where you can return an asynchronous iterator. + * Promises yielded by that iterator become available to the resolver in its first param, the source data. + * + * If you need to leverage plugins or define multiple fields then use the typeBuilder overload variant of this + * function. Otherwise you may prefer to the field name/config variant. + * + * @example + * // Contrived but simple self-contained example + * + * subscriptionField((t) => { + * t.boolean('truths', { + * subscribe() { + * async function* createTruthsStream() { + * while (true) { + * await new Promise((res) => setTimeout(res, 1000)) + * yield Math.random() > 0.5 + * } + * } + * return createTruthsStream() + * }, + * resolve(truthPromise) { + * return truthPromise + * }, + * }) + * }) + * + * @example + * // A slightly less contrived example + * // See the full working example at + * // https://nxs.li/examples/subscriptions + * + * import { PubSub } from 'apollo-server-express' + * import { makeSchema, mutationType, objectType, stringArg, subscriptionType } from '_AT_nexus/schema' + * import * as path from 'path' + * + * export const pubsub = new PubSub() + * + * type User = { + * email: string + * } + * + * type Event = { + * data: T + * } + * + * makeSchema({ + * types: [ + * subscriptionField('signup', { + * type: 'User', + * subscribe() { + * return pubsub.asyncIterator('signup') + * }, + * async resolve(eventPromise: Promise>) { + * const event = await eventPromise + * return event.data + * }, + * }), + * + * mutationField('signup', { + * type: 'User', + * args: { + * email: stringArg(), + * }, + * async resolve(_, args) { + * const newUser = { + * email: args.email, + * } + * // ... + * await pubsub.publish('signup', { + * data: newUser, + * }) + * return newUser + * }, + * }), + * + * objectType({ + * name: 'User', + * definition(t) { + * t.string('email') + * }, + * }), + * ], + * typegenAutoConfig: { + * sources: [{ source: __filename, alias: 'SourceTypes' }], + * }, + * }) + * + * @param typeBuilder The same as the "definition" method you define on object type configurations. + */ export function subscriptionField( - fieldFn: (t: SubscriptionBuilder) => void + typeBuilder: (t: SubscriptionBuilder) => void ): NexusExtendTypeDef<'Subscription'> +/** + * [2018 GraphQL Spec](https://spec.graphql.org/June2018/#sec-Subscription) + * + * Define one or more fields on the Subscription type. + * + * This is shorthand for: + * + * `extendType({ type: 'Subscription' })` + * + * The Subscription type is one of three [root + * types](https://spec.graphql.org/June2018/#sec-Root-Operation-Types) in GraphQL and its fields represent + * API operations your clients can run to be pushed data changes over time. + * + * Use this instead of subscriptionType if you are going to modularize your schema and thus be wanting to + * contribute fields to the Subscription type from multiple modules. You do not have to have previously + * defined a Query type before using this. If you haven't Nexus will create one automatically for you. + * + * Note that the main difference about Subscription type from other object types is that its field + * configurations require a special "subscribe" method where you can return an asynchronous iterator. + * Promises yielded by that iterator become available to the resolver in its first param, the source data. + * + * If you need to leverage plugins or define multiple fields then use the typeBuilder overload variant of this + * function. Otherwise you may prefer to the field name/config variant. + * + * @example + * // Contrived but simple self-contained example + * + * subscriptionField((t) => { + * t.boolean('truths', { + * subscribe() { + * async function* createTruthsStream() { + * while (true) { + * await new Promise((res) => setTimeout(res, 1000)) + * yield Math.random() > 0.5 + * } + * } + * return createTruthsStream() + * }, + * resolve(truthPromise) { + * return truthPromise + * }, + * }) + * }) + * + * @example + * // A slightly less contrived example + * // See the full working example at + * // https://nxs.li/examples/subscriptions + * + * import { PubSub } from 'apollo-server-express' + * import { makeSchema, mutationType, objectType, stringArg, subscriptionType } from '_AT_nexus/schema' + * import * as path from 'path' + * + * export const pubsub = new PubSub() + * + * type User = { + * email: string + * } + * + * type Event = { + * data: T + * } + * + * makeSchema({ + * types: [ + * subscriptionField('signup', { + * type: 'User', + * subscribe() { + * return pubsub.asyncIterator('signup') + * }, + * async resolve(eventPromise: Promise>) { + * const event = await eventPromise + * return event.data + * }, + * }), + * + * mutationField('signup', { + * type: 'User', + * args: { + * email: stringArg(), + * }, + * async resolve(_, args) { + * const newUser = { + * email: args.email, + * } + * // ... + * await pubsub.publish('signup', { + * data: newUser, + * }) + * return newUser + * }, + * }), + * + * objectType({ + * name: 'User', + * definition(t) { + * t.string('email') + * }, + * }), + * ], + * typegenAutoConfig: { + * sources: [{ source: __filename, alias: 'SourceTypes' }], + * }, + * }) + * + * @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]* + * @param config The same type of configuration you would pass to t.field("...", config) + */ export function subscriptionField( - fieldName: FieldName, + name: FieldName, config: SubscriptionFieldConfig ): NexusExtendTypeDef<'Subscription'> -/** Add one field to the Subscription type */ export function subscriptionField(...args: any[]) { return extendType({ type: 'Subscription', diff --git a/src/definitions/subscriptionType.ts b/src/definitions/subscriptionType.ts index 28f75e37..e1ffcf31 100644 --- a/src/definitions/subscriptionType.ts +++ b/src/definitions/subscriptionType.ts @@ -5,6 +5,8 @@ import { CommonOutputFieldConfig } from './definitionBlocks' import { objectType } from './objectType' import { AllNexusOutputTypeDefs } from './wrapping' +export type IsSubscriptionType = IsEqual + export interface SubscriptionTypeConfigBase { resolve( root: Event, @@ -51,8 +53,121 @@ export type SubscriptionTypeParams = { definition(t: SubscriptionBuilder): void } +/** + * [2018 GraphQL Spec](https://spec.graphql.org/June2018/#sec-Subscription) + * + * Define a Subscription type. + * + * This is a shorthand for: + * + * `objectType({ name: 'Subscription' })` + * + * The Subscription type is one of three [root + * types](https://spec.graphql.org/June2018/#sec-Root-Operation-Types) in GraphQL and its fields represent + * API operations your clients can run to be pushed data changes over time. + * + * You can only have one of these in your schema. If you are going to modularize your schema and thus be + * wanting to contribute fields to the Subscription type from multiple modules then use + * [queryField](https://nxs.li/docs/api/subscription-field) intead. + * + * Note that the main difference about Subscription type from other object types is that its field + * configurations require a special "subscribe" method where you can return an asynchronous iterator. + * Promises yielded by that iterator become available to the resolver in its first param, the source data. + * + * @example + * // Contrived but simple self-contained example + * + * subscriptionType({ + * definition(t) { + * t.boolean('truths', { + * subscribe() { + * async function* createTruthsStream() { + * while (true) { + * await new Promise((res) => setTimeout(res, 1000)) + * yield Math.random() > 0.5 + * } + * } + * return createTruthsStream() + * }, + * resolve(truthPromise) { + * return truthPromise + * }, + * }) + * }, + * }) + * + * @example + * // A slightly less contrived example + * // See the full working example at + * // https://nxs.li/examples/subscriptions + * + * import { PubSub } from 'apollo-server-express' + * import { makeSchema, mutationType, objectType, stringArg, subscriptionType } from '_AT_nexus/schema' + * import * as path from 'path' + * + * export const pubsub = new PubSub() + * + * type User = { + * email: string + * } + * + * type Event = { + * data: T + * } + * + * export const schema = makeSchema({ + * types: [ + * subscriptionType({ + * definition(t) { + * t.field('signup', { + * type: 'User', + * subscribe() { + * return pubsub.asyncIterator('signup') + * }, + * async resolve(eventPromise: Promise>) { + * const event = await eventPromise + * return event.data + * }, + * }) + * }, + * }), + * + * mutationType({ + * definition(t) { + * t.field('signup', { + * type: 'User', + * args: { + * email: stringArg(), + * }, + * async resolve(_, args) { + * const newUser = { + * email: args.email, + * } + * // ... + * await pubsub.publish('signup', { + * data: newUser, + * }) + * return newUser + * }, + * }) + * }, + * }), + * + * objectType({ + * name: 'User', + * definition(t) { + * t.string('email') + * }, + * }), + * ], + * typegenAutoConfig: { + * sources: [{ source: __filename, alias: 'SourceTypes' }], + * }, + * }) + * + * @param config Specify your Subscription type's fields, description, and more. See each config property's jsDoc + * for more detail. + */ export function subscriptionType(config: SubscriptionTypeParams) { - return objectType({ name: 'Subscription', ...config } as any) + return objectType({ ...config, name: 'Subscription' } as any) } - -export type IsSubscriptionType = IsEqual