improve: remove dynamic output builtins (#590)
closes #581 BREAKING CHANGE: `ext` is no longer exported. The `relayConnectionField` and `collectionField` dynamic output methods have been removed. In their place try the `connection` plugin.
This commit is contained in:
parent
cc12ec16fb
commit
9f01342248
|
|
@ -13,7 +13,7 @@
|
|||
"trailingComma": "all"
|
||||
},
|
||||
"dependencies": {
|
||||
"@nexus/schema": "0.17.0-next.2",
|
||||
"@nexus/schema": "0.17.0",
|
||||
"graphql": "^15.3.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
|
|
|||
|
|
@ -2,10 +2,10 @@
|
|||
# yarn lockfile v1
|
||||
|
||||
|
||||
"@nexus/schema@0.17.0-next.2":
|
||||
version "0.17.0-next.2"
|
||||
resolved "https://registry.yarnpkg.com/@nexus/schema/-/schema-0.17.0-next.2.tgz#b85fcb1cd35d4fd65618404f406d0e1e309ffda7"
|
||||
integrity sha512-EMUYhEvo6DkbZSBC/ErlSN59KWDVrZbuBbRY+QbRn2EsOcOhA3Y6g+/SDYEfJwqJzKjiC9AjqOmOqzmBXBNJQA==
|
||||
"@nexus/schema@0.17.0":
|
||||
version "0.17.0"
|
||||
resolved "https://registry.yarnpkg.com/@nexus/schema/-/schema-0.17.0.tgz#5b6ec9630a9cd17f64a7ffc999378fa9835df3a9"
|
||||
integrity sha512-X/DdvXGDNw2VMi1F2un7JRY17yFbuxXHM+U4ViejAf9jCkhlasdljK3TLTqA5wSFfriFIx0eWtYHkUeOvIjLkg==
|
||||
dependencies:
|
||||
iterall "^1.2.2"
|
||||
tslib "^1.9.3"
|
||||
|
|
|
|||
|
|
@ -1,60 +0,0 @@
|
|||
import { GraphQLFieldResolver } from 'graphql'
|
||||
import { intArg } from '../definitions/args'
|
||||
import { NexusObjectTypeDef, objectType } from '../definitions/objectType'
|
||||
import { dynamicOutputMethod } from '../dynamicMethod'
|
||||
|
||||
const basicCollectionMap = new Map<string, NexusObjectTypeDef<string>>()
|
||||
|
||||
export const CollectionFieldMethod = dynamicOutputMethod({
|
||||
name: 'collectionField',
|
||||
typeDefinition: `<FieldName extends string>(fieldName: FieldName, opts: {
|
||||
type: NexusGenObjectNames | NexusGenInterfaceNames | core.NexusObjectTypeDef<any> | core.NexusInterfaceTypeDef<any>,
|
||||
nodes: core.SubFieldResolver<TypeName, FieldName, "nodes">,
|
||||
totalCount: core.SubFieldResolver<TypeName, FieldName, "totalCount">,
|
||||
args?: core.ArgsRecord,
|
||||
nullable?: boolean,
|
||||
description?: string
|
||||
}): void;`,
|
||||
factory({ typeDef: t, args: [fieldName, config] }) {
|
||||
/* istanbul ignore next */
|
||||
if (!config.type) {
|
||||
throw new Error(`Missing required property "type" from collectionField ${fieldName}`)
|
||||
}
|
||||
const typeName = typeof config.type === 'string' ? config.type : config.type.name
|
||||
/* istanbul ignore next */
|
||||
if (config.list) {
|
||||
throw new Error(`Collection field ${fieldName}.${typeName} cannot be used as a list.`)
|
||||
}
|
||||
if (!basicCollectionMap.has(typeName)) {
|
||||
basicCollectionMap.set(
|
||||
typeName,
|
||||
objectType({
|
||||
name: `${typeName}Collection`,
|
||||
definition(c) {
|
||||
c.int('totalCount')
|
||||
c.list.field('nodes', { type: config.type })
|
||||
},
|
||||
})
|
||||
)
|
||||
}
|
||||
t.field(fieldName, {
|
||||
type: basicCollectionMap.get(typeName)!,
|
||||
args: config.args || {
|
||||
page: intArg(),
|
||||
perPage: intArg(),
|
||||
},
|
||||
nullable: config.nullable,
|
||||
description: config.description,
|
||||
resolve(root, args, ctx, info) {
|
||||
const nodesResolver: GraphQLFieldResolver<any, any> = (...fArgs) =>
|
||||
config.nodes(root, args, ctx, fArgs[3])
|
||||
const totalCountResolver: GraphQLFieldResolver<any, any> = (...fArgs) =>
|
||||
config.totalCount(root, args, ctx, fArgs[3])
|
||||
return {
|
||||
nodes: nodesResolver,
|
||||
totalCount: totalCountResolver,
|
||||
}
|
||||
},
|
||||
})
|
||||
},
|
||||
})
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
export * from './collection'
|
||||
export * from './relayConnection'
|
||||
|
|
@ -1,83 +0,0 @@
|
|||
import { GraphQLFieldResolver } from 'graphql'
|
||||
import { intArg, stringArg } from '../definitions/args'
|
||||
import { NexusObjectTypeDef, objectType } from '../definitions/objectType'
|
||||
import { dynamicOutputMethod } from '../dynamicMethod'
|
||||
|
||||
const relayConnectionMap = new Map<string, NexusObjectTypeDef<string>>()
|
||||
|
||||
let pageInfo: NexusObjectTypeDef<string>
|
||||
|
||||
export const RelayConnectionFieldMethod = dynamicOutputMethod({
|
||||
name: 'relayConnectionField',
|
||||
typeDefinition: `<FieldName extends string>(fieldName: FieldName, opts: {
|
||||
type: NexusGenObjectNames | NexusGenInterfaceNames | core.NexusObjectTypeDef<any> | core.NexusInterfaceTypeDef<any>,
|
||||
edges: core.SubFieldResolver<TypeName, FieldName, "edges">,
|
||||
pageInfo: core.SubFieldResolver<TypeName, FieldName, "pageInfo">,
|
||||
args?: Record<string, core.NexusArgDef<any>>,
|
||||
nullable?: boolean,
|
||||
description?: string
|
||||
}): void
|
||||
`,
|
||||
factory({ typeDef: t, args: [fieldName, config] }) {
|
||||
/* istanbul ignore next */
|
||||
if (!config.type) {
|
||||
throw new Error(`Missing required property "type" from relayConnection field ${fieldName}`)
|
||||
}
|
||||
const typeName = typeof config.type === 'string' ? config.type : config.type.name
|
||||
pageInfo =
|
||||
pageInfo ||
|
||||
objectType({
|
||||
name: `ConnectionPageInfo`,
|
||||
definition(p) {
|
||||
p.boolean('hasNextPage')
|
||||
p.boolean('hasPreviousPage')
|
||||
},
|
||||
})
|
||||
/* istanbul ignore next */
|
||||
if (config.list) {
|
||||
throw new Error(`Collection field ${fieldName}.${typeName} cannot be used as a list.`)
|
||||
}
|
||||
if (!relayConnectionMap.has(typeName)) {
|
||||
relayConnectionMap.set(
|
||||
typeName,
|
||||
objectType({
|
||||
name: `${typeName}RelayConnection`,
|
||||
definition(c) {
|
||||
c.list.field('edges', {
|
||||
type: objectType({
|
||||
name: `${typeName}Edge`,
|
||||
definition(e) {
|
||||
e.id('cursor')
|
||||
e.field('node', { type: config.type })
|
||||
},
|
||||
}),
|
||||
})
|
||||
c.field('pageInfo', { type: pageInfo })
|
||||
},
|
||||
})
|
||||
)
|
||||
}
|
||||
t.field(fieldName, {
|
||||
type: relayConnectionMap.get(typeName)!,
|
||||
args: {
|
||||
first: intArg(),
|
||||
after: stringArg(),
|
||||
last: intArg(),
|
||||
before: stringArg(),
|
||||
...config.args,
|
||||
},
|
||||
nullable: config.nullable,
|
||||
description: config.description,
|
||||
resolve(root, args, ctx, info) {
|
||||
const edgeResolver: GraphQLFieldResolver<any, any> = (...fArgs) =>
|
||||
config.edges(root, args, ctx, fArgs[3])
|
||||
const pageInfoResolver: GraphQLFieldResolver<any, any> = (...fArgs) =>
|
||||
config.pageInfo(root, args, ctx, fArgs[3])
|
||||
return {
|
||||
edges: edgeResolver,
|
||||
pageInfo: pageInfoResolver,
|
||||
}
|
||||
},
|
||||
})
|
||||
},
|
||||
})
|
||||
|
|
@ -1,3 +1,6 @@
|
|||
import * as blocks from './blocks'
|
||||
import * as core from './core'
|
||||
|
||||
// All of the Public API definitions
|
||||
export { makeSchema } from './builder'
|
||||
export { arg, booleanArg, floatArg, idArg, intArg, stringArg } from './definitions/args'
|
||||
|
|
@ -21,7 +24,4 @@ export * from './plugins'
|
|||
export { convertSDL } from './sdlConverter'
|
||||
export { AllInputTypes, AllOutputTypes, FieldResolver, FieldType } from './typegenTypeHelpers'
|
||||
export { groupTypes } from './utils'
|
||||
export { core, blocks, ext }
|
||||
import * as blocks from './blocks'
|
||||
import * as core from './core'
|
||||
import * as ext from './dynamicMethods'
|
||||
export { blocks, core }
|
||||
|
|
|
|||
|
|
@ -1,48 +0,0 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`dynamicOutputMethod CollectionFieldMethod example 1`] = `
|
||||
Object {
|
||||
"data": Object {
|
||||
"cats": Object {
|
||||
"nodes": Array [
|
||||
Object {
|
||||
"id": "Cat:1",
|
||||
"name": "Felix",
|
||||
},
|
||||
Object {
|
||||
"id": "Cat:2",
|
||||
"name": "Booker",
|
||||
},
|
||||
],
|
||||
"totalCount": 2,
|
||||
},
|
||||
},
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`dynamicOutputMethod RelayConnectionFieldMethod example 1`] = `
|
||||
Object {
|
||||
"data": Object {
|
||||
"cats": Object {
|
||||
"edges": Array [
|
||||
Object {
|
||||
"node": Object {
|
||||
"id": "Cat:1",
|
||||
"name": "Felix",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"node": Object {
|
||||
"id": "Cat:2",
|
||||
"name": "Booker",
|
||||
},
|
||||
},
|
||||
],
|
||||
"pageInfo": Object {
|
||||
"hasNextPage": false,
|
||||
"hasPreviousPage": false,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
`;
|
||||
|
|
@ -1,161 +1,44 @@
|
|||
import { graphql } from 'graphql'
|
||||
import { GraphQLDateTime } from 'graphql-scalars'
|
||||
import path from 'path'
|
||||
import {
|
||||
decorateType,
|
||||
dynamicInputMethod,
|
||||
ext,
|
||||
dynamicOutputMethod,
|
||||
inputObjectType,
|
||||
makeSchema,
|
||||
objectType,
|
||||
queryType,
|
||||
} from '../src'
|
||||
import { dynamicOutputProperty } from '../src/dynamicProperty'
|
||||
import { CatListFixture } from './_fixtures'
|
||||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks()
|
||||
})
|
||||
|
||||
describe('dynamicOutputMethod', () => {
|
||||
const Cat = objectType({
|
||||
name: 'Cat',
|
||||
definition(t) {
|
||||
t.id('id')
|
||||
t.string('name')
|
||||
},
|
||||
})
|
||||
|
||||
test('RelayConnectionFieldMethod example', async () => {
|
||||
const Query = queryType({
|
||||
definition(t) {
|
||||
// @ts-ignore
|
||||
t.relayConnectionField('cats', {
|
||||
type: Cat,
|
||||
pageInfo: () => ({
|
||||
hasNextPage: false,
|
||||
hasPreviousPage: false,
|
||||
}),
|
||||
edges: () => CatListFixture.map((c) => ({ cursor: `Cursor: ${c.id}`, node: c })),
|
||||
})
|
||||
},
|
||||
})
|
||||
const schema = makeSchema({
|
||||
types: [Query, ext.RelayConnectionFieldMethod],
|
||||
it('should provide a method on the output type builder', async () => {
|
||||
makeSchema({
|
||||
types: [
|
||||
dynamicOutputMethod({
|
||||
name: 'foo',
|
||||
typeDefinition: 'String',
|
||||
factory({ typeDef }) {
|
||||
typeDef.field('viaFoo', { type: 'Int' })
|
||||
},
|
||||
}),
|
||||
objectType({
|
||||
name: 'Bar',
|
||||
definition(t) {
|
||||
//@ts-expect-error
|
||||
t.foo()
|
||||
},
|
||||
}),
|
||||
],
|
||||
outputs: {
|
||||
typegen: path.join(__dirname, 'test-output.ts'),
|
||||
schema: path.join(__dirname, 'schema.graphql'),
|
||||
},
|
||||
shouldGenerateArtifacts: false,
|
||||
})
|
||||
expect(
|
||||
await graphql(
|
||||
schema,
|
||||
`
|
||||
{
|
||||
cats {
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
name
|
||||
}
|
||||
}
|
||||
pageInfo {
|
||||
hasNextPage
|
||||
hasPreviousPage
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
)
|
||||
).toMatchSnapshot()
|
||||
})
|
||||
|
||||
test('CollectionFieldMethod example', async () => {
|
||||
const dynamicOutputMethod = queryType({
|
||||
definition(t) {
|
||||
// @ts-ignore
|
||||
t.collectionField('cats', {
|
||||
type: Cat,
|
||||
totalCount: () => CatListFixture.length,
|
||||
nodes: () => CatListFixture,
|
||||
})
|
||||
},
|
||||
})
|
||||
|
||||
const schema = makeSchema({
|
||||
types: [dynamicOutputMethod, ext.CollectionFieldMethod],
|
||||
outputs: {
|
||||
typegen: path.join(__dirname, 'test-output'),
|
||||
schema: path.join(__dirname, 'schema.graphql'),
|
||||
},
|
||||
shouldGenerateArtifacts: false,
|
||||
})
|
||||
|
||||
expect(
|
||||
await graphql(
|
||||
schema,
|
||||
`
|
||||
{
|
||||
cats {
|
||||
totalCount
|
||||
nodes {
|
||||
id
|
||||
name
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
)
|
||||
).toMatchSnapshot()
|
||||
})
|
||||
|
||||
test('CollectionFieldMethod example with string type ref', () => {
|
||||
makeSchema({
|
||||
types: [
|
||||
queryType({
|
||||
definition(t) {
|
||||
// @ts-ignore
|
||||
t.collectionField('cats', {
|
||||
type: 'Cat',
|
||||
totalCount: () => CatListFixture.length,
|
||||
nodes: () => CatListFixture,
|
||||
})
|
||||
},
|
||||
}),
|
||||
ext.CollectionFieldMethod,
|
||||
],
|
||||
outputs: false,
|
||||
})
|
||||
})
|
||||
|
||||
test('RelayConnectionFieldMethod example with string type ref', async () => {
|
||||
makeSchema({
|
||||
types: [
|
||||
queryType({
|
||||
definition(t) {
|
||||
// @ts-ignore
|
||||
t.relayConnectionField('cats', {
|
||||
type: 'Cat',
|
||||
nodes(root: any, args: any, ctx: any, info: any) {
|
||||
return CatListFixture
|
||||
},
|
||||
pageInfo: () => ({
|
||||
hasNextPage: false,
|
||||
hasPreviousPage: false,
|
||||
}),
|
||||
edges: () =>
|
||||
CatListFixture.map((c) => ({
|
||||
cursor: `Cursor: ${c.id}`,
|
||||
node: c,
|
||||
})),
|
||||
})
|
||||
},
|
||||
}),
|
||||
ext.RelayConnectionFieldMethod,
|
||||
],
|
||||
outputs: false,
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
|
|
@ -170,7 +53,7 @@ describe('dynamicInputMethod', () => {
|
|||
name: 'SomeInput',
|
||||
definition(t) {
|
||||
t.id('id')
|
||||
// @ts-ignore
|
||||
//@ts-expect-error
|
||||
t.timestamps()
|
||||
},
|
||||
}),
|
||||
|
|
|
|||
Loading…
Reference in New Issue