diff --git a/package.json b/package.json index 4045027fe..2c6543936 100644 --- a/package.json +++ b/package.json @@ -27,12 +27,12 @@ "pluralize": "^8.0.0" }, "peerDependencies": { - "@nexus/schema": "^0.12.0-rc.13", + "@nexus/schema": "^0.13.1", "@prisma/client": "2.0.0-beta.1", "graphql": "^14.5.0" }, "devDependencies": { - "@nexus/schema": "^0.12.0-rc.13", + "@nexus/schema": "^0.13.1", "@prisma/cli": "2.0.0-beta.1", "@prisma/client": "2.0.0-beta.1", "@prisma/fetch-engine": "2.0.0-beta.1", diff --git a/tests/schema/__snapshots__/computedInputs.test.ts.snap b/tests/schema/__snapshots__/computedInputs.test.ts.snap index ea6d409d5..b5b25534a 100644 --- a/tests/schema/__snapshots__/computedInputs.test.ts.snap +++ b/tests/schema/__snapshots__/computedInputs.test.ts.snap @@ -1,5 +1,399 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`removes global computedInputs from all input types: globallyComputedInputs 1`] = ` +Object { + "schema": "type Mutation { + createOneUser(data: UserCreateInput!): User! + createOneNested(data: NestedCreateInput!): Nested! +} + +type Nested { + id: Int! + createdWithBrowser: String! + name: String! +} + +input NestedCreateInput { + name: String! + user: UserCreateOneWithoutNestedInput +} + +input NestedCreateManyWithoutUserInput { + create: [NestedCreateWithoutUserInput!] + connect: [NestedWhereUniqueInput!] +} + +input NestedCreateWithoutUserInput { + name: String! +} + +input NestedWhereUniqueInput { + id: Int +} + +type Query { + user(where: UserWhereUniqueInput!): User +} + +type User { + id: Int! + name: String! + nested(skip: Int, after: NestedWhereUniqueInput, before: NestedWhereUniqueInput, first: Int, last: Int): [Nested!]! + createdWithBrowser: String! +} + +input UserCreateInput { + name: String! + nested: NestedCreateManyWithoutUserInput +} + +input UserCreateOneWithoutNestedInput { + create: UserCreateWithoutNestedInput + connect: UserWhereUniqueInput +} + +input UserCreateWithoutNestedInput { + name: String! +} + +input UserWhereUniqueInput { + id: Int +} +", + "typegen": "import * as prisma from '@prisma/client'; +import { core } from '@nexus/schema'; +import { GraphQLResolveInfo } from 'graphql'; + +// Types helpers + type IsModelNameExistsInGraphQLTypes< + ReturnType extends any +> = ReturnType extends core.GetGen<'objectNames'> ? true : false; + +type NexusPrismaScalarOpts = { + alias?: string; +}; + +type Pagination = { + first?: boolean; + last?: boolean; + before?: boolean; + after?: boolean; + skip?: boolean; +}; + +type RootObjectTypes = Pick< + core.GetGen<'rootTypes'>, + core.GetGen<'objectNames'> +>; + +/** + * Determine if \`B\` is a subset (or equivalent to) of \`A\`. +*/ +type IsSubset = keyof A extends never + ? false + : B extends A + ? true + : false; + +type OmitByValue = Pick< + T, + { [Key in keyof T]: T[Key] extends ValueType ? never : Key }[keyof T] +>; + +type GetSubsetTypes = keyof OmitByValue< + { + [P in keyof RootObjectTypes]: ModelName extends keyof ModelTypes + ? IsSubset extends true + ? RootObjectTypes[P] + : never + : never; + }, + never +>; + +type SubsetTypes = GetSubsetTypes< + ModelName +> extends never + ? \`ERROR: No subset types are available. Please make sure that one of your GraphQL type is a subset of your t.model('')\` + : GetSubsetTypes; + +type DynamicRequiredType = IsModelNameExistsInGraphQLTypes< + ReturnType +> extends true + ? { type?: SubsetTypes } + : { type: SubsetTypes }; + +type GetNexusPrismaInput< + ModelName extends any, + MethodName extends any, + InputName extends 'filtering' | 'ordering' +> = ModelName extends keyof NexusPrismaInputs + ? MethodName extends keyof NexusPrismaInputs[ModelName] + ? NexusPrismaInputs[ModelName][MethodName][InputName] + : never + : never; + +/** + * Represents arguments required by Prisma Client JS that will + * be derived from a request's input (args, context, and info) + * and omitted from the GraphQL API. The object itself maps the + * names of these args to a function that takes an object representing + * the request's input and returns the value to pass to the prisma + * arg of the same name. + */ +export type LocalComputedInputs = Record< + string, + (params: LocalMutationResolverParams) => unknown +> + +export type GlobalComputedInputs = Record< + string, + (params: GlobalMutationResolverParams) => unknown +> + +type BaseMutationResolverParams = { + info: GraphQLResolveInfo + ctx: Context +} + +export type GlobalMutationResolverParams = BaseMutationResolverParams & { + args: Record & { data: unknown } +} + +export type LocalMutationResolverParams< + MethodName extends any +> = BaseMutationResolverParams & { + args: MethodName extends keyof core.GetGen2<'argTypes', 'Mutation'> + ? core.GetGen3<'argTypes', 'Mutation', MethodName> + : any +} + +export type Context = core.GetGen<'context'> + +type NexusPrismaRelationOpts< + ModelName extends any, + MethodName extends any, + ReturnType extends any +> = GetNexusPrismaInput< + // If GetNexusPrismaInput returns never, it means there are no filtering/ordering args for it. + ModelName, + MethodName, + 'filtering' +> extends never + ? { + alias?: string; + computedInputs?: LocalComputedInputs; + } & DynamicRequiredType + : { + alias?: string; + computedInputs?: LocalComputedInputs; + filtering?: + | boolean + | Partial< + Record< + GetNexusPrismaInput, + boolean + > + >; + ordering?: + | boolean + | Partial< + Record< + GetNexusPrismaInput, + boolean + > + >; + pagination?: boolean | Pagination; + } & DynamicRequiredType; + +type IsScalar = TypeName extends core.GetGen<'scalarNames'> + ? true + : false; + +type IsObject = Name extends core.GetGen<'objectNames'> + ? true + : false + +type IsEnum = Name extends core.GetGen<'enumNames'> + ? true + : false + +type IsInputObject = Name extends core.GetGen<'inputNames'> + ? true + : false + +/** + * The kind that a GraphQL type may be. + */ +type Kind = 'Enum' | 'Object' | 'Scalar' | 'InputObject' + +/** + * Helper to safely reference a Kind type. For example instead of the following + * which would admit a typo: + * + * \`\`\`ts + * type Foo = Bar extends 'scalar' ? ... + * \`\`\` + * + * You can do this which guarantees a correct reference: + * + * \`\`\`ts + * type Foo = Bar extends AKind<'Scalar'> ? ... + * \`\`\` + * + */ +type AKind = T + +type GetKind = IsEnum extends true + ? 'Enum' + : IsScalar extends true + ? 'Scalar' + : IsObject extends true + ? 'Object' + : IsInputObject extends true + ? 'InputObject' + // FIXME should be \`never\`, but GQL objects named differently + // than backing type fall into this branch + : 'Object' + +type NexusPrismaFields = { + [MethodName in keyof NexusPrismaTypes[ModelName]]: NexusPrismaMethod< + ModelName, + MethodName, + GetKind // Is the return type a scalar? + >; +}; + +type NexusPrismaMethod< + ModelName extends keyof NexusPrismaTypes, + MethodName extends keyof NexusPrismaTypes[ModelName], + ThisKind extends Kind, + ReturnType extends any = NexusPrismaTypes[ModelName][MethodName] +> = + ThisKind extends AKind<'Enum'> + ? () => NexusPrismaFields + : ThisKind extends AKind<'Scalar'> + ? (opts?: NexusPrismaScalarOpts) => NexusPrismaFields // Return optional scalar opts + : IsModelNameExistsInGraphQLTypes extends true // If model name has a mapped graphql types + ? ( + opts?: NexusPrismaRelationOpts + ) => NexusPrismaFields // Then make opts optional + : ( + opts: NexusPrismaRelationOpts + ) => NexusPrismaFields; // Else force use input the related graphql type -> { type: '...' } + +type GetNexusPrismaMethod< + TypeName extends string +> = TypeName extends keyof NexusPrismaMethods + ? NexusPrismaMethods[TypeName] + : ( + typeName: CustomTypeName + ) => NexusPrismaMethods[CustomTypeName]; + +type GetNexusPrisma< + TypeName extends string, + ModelOrCrud extends 'model' | 'crud' +> = ModelOrCrud extends 'model' + ? TypeName extends 'Mutation' + ? never + : TypeName extends 'Query' + ? never + : GetNexusPrismaMethod + : ModelOrCrud extends 'crud' + ? TypeName extends 'Mutation' + ? GetNexusPrismaMethod + : TypeName extends 'Query' + ? GetNexusPrismaMethod + : never + : never; + + +// Generated +interface ModelTypes { + User: prisma.User + Nested: prisma.Nested +} + +interface NexusPrismaInputs { + Query: { + users: { + filtering: 'id' | 'name' | 'nested' | 'AND' | 'OR' | 'NOT' + ordering: 'id' | 'name' +} + nesteds: { + filtering: 'id' | 'name' | 'AND' | 'OR' | 'NOT' | 'user' + ordering: 'id' | 'name' +} + + }, + User: { + nested: { + filtering: 'id' | 'name' | 'AND' | 'OR' | 'NOT' | 'user' + ordering: 'id' | 'name' +} + + }, Nested: { + + + } +} + +interface NexusPrismaTypes { + Query: { + user: 'User' + users: 'User' + nested: 'Nested' + nesteds: 'Nested' + + }, + Mutation: { + createOneUser: 'User' + updateOneUser: 'User' + updateManyUser: 'BatchPayload' + deleteOneUser: 'User' + deleteManyUser: 'BatchPayload' + upsertOneUser: 'User' + createOneNested: 'Nested' + updateOneNested: 'Nested' + updateManyNested: 'BatchPayload' + deleteOneNested: 'Nested' + deleteManyNested: 'BatchPayload' + upsertOneNested: 'Nested' + + }, + User: { + id: 'Int' + name: 'String' + nested: 'Nested' + createdWithBrowser: 'String' + +}, Nested: { + id: 'Int' + name: 'String' + createdWithBrowser: 'String' + user: 'User' + +} +} + +interface NexusPrismaMethods { + User: NexusPrismaFields<'User'> + Nested: NexusPrismaFields<'Nested'> + Query: NexusPrismaFields<'Query'> + Mutation: NexusPrismaFields<'Mutation'> +} + + +declare global { + type NexusPrisma< + TypeName extends string, + ModelOrCrud extends 'model' | 'crud' + > = GetNexusPrisma; +} + ", +} +`; + exports[`removes resolver-level computedInputs from the corresponding input type: locallyComputedInputs 1`] = ` Object { "schema": "type Mutation { diff --git a/tests/schema/computedInputs.test.ts b/tests/schema/computedInputs.test.ts index ab2b5940c..c98766aa1 100644 --- a/tests/schema/computedInputs.test.ts +++ b/tests/schema/computedInputs.test.ts @@ -82,7 +82,7 @@ const globalTestData = { }), } -it.only('removes resolver-level computedInputs from the corresponding input type', async () => { +it('removes resolver-level computedInputs from the corresponding input type', async () => { const { datamodel, ...resolvers } = resolverTestData const result = await generateSchemaAndTypes( datamodel, diff --git a/yarn.lock b/yarn.lock index 0963c8859..6cc24be9f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -462,10 +462,10 @@ call-me-maybe "^1.0.1" glob-to-regexp "^0.3.0" -"@nexus/schema@^0.12.0-rc.13": - version "0.12.0-rc.13" - resolved "https://registry.yarnpkg.com/@nexus/schema/-/schema-0.12.0-rc.13.tgz#afdc7433030b5d7fffcd2509a771581d6c143cf5" - integrity sha512-q4A5Jfe26wayPHE2qgXF5wJIu2soeUR2koyVCzihR6Zxe6THwONKkntHmznUNy4ofIGTRFsF4d0I7kmjceMhVw== +"@nexus/schema@^0.13.1": + version "0.13.1" + resolved "https://registry.yarnpkg.com/@nexus/schema/-/schema-0.13.1.tgz#02dadf66b121b3c270659479f2410b7023fcc4a6" + integrity sha512-V7fFhkPOcqQ7KwSaAkfSTAV/klY/NlL7aIHTuEZynAUNm2cG8S6QSU+TuVlbpj0L14B9tqgPrVeO+IOe0AV+yA== dependencies: iterall "^1.2.2" tslib "^1.9.3"