feat: allow asNexusMethod to specify TS type (#473)
Co-authored-by: Jason Kuhrt <jasonkuhrt@me.com> - Create a new `NexusGenScalars` for all scalar types - Remove scalars from `NexusGenRootTypes` (might be a breaking change, need review) - Use the `NexusGenScalars` for all non specified (base GraphQL) scalars in `input` and `output` types - Add `rootTyping` parameter to `asNexusMethod` to allow the user to specify it, otherwise it will fallback to the `backingTypeMap` BREAKING CHANGE: The global TS type `NexusGenRootTypes` no longer contains scalars. All scalars now live under a new global TS type named `NexusGenScalars`. ```ts // before let foo: NexusGenRootTypes['String'] ``` ```ts // after let foo: NexusGenScalars['String'] ```
This commit is contained in:
parent
61eccca200
commit
1d97b788b5
|
@ -52,8 +52,13 @@ export function scalarType<TypeName extends string>(options: NexusScalarTypeConf
|
|||
return new NexusScalarTypeDef(options.name, options)
|
||||
}
|
||||
|
||||
export function asNexusMethod<T extends GraphQLScalarType>(scalar: T, methodName: string): T {
|
||||
export function asNexusMethod<T extends GraphQLScalarType>(
|
||||
scalar: T,
|
||||
methodName: string,
|
||||
rootTyping?: RootTypingDef
|
||||
): T {
|
||||
return decorateType(scalar, {
|
||||
asNexusMethod: methodName,
|
||||
rootTyping: rootTyping,
|
||||
})
|
||||
}
|
||||
|
|
|
@ -81,6 +81,7 @@ export class TypegenPrinter {
|
|||
const body = [
|
||||
this.printInputTypeMap(),
|
||||
this.printEnumTypeMap(),
|
||||
this.printScalarTypeMap(),
|
||||
this.printRootTypeMap(),
|
||||
this.printAllTypesMap(),
|
||||
this.printReturnTypeMap(),
|
||||
|
@ -340,6 +341,23 @@ export class TypegenPrinter {
|
|||
return inputObjMap
|
||||
}
|
||||
|
||||
buildScalarTypeMap() {
|
||||
const scalarMap: TypeMapping = {}
|
||||
this.groupedTypes.scalar.forEach((e) => {
|
||||
if (isSpecifiedScalarType(e)) {
|
||||
scalarMap[e.name] = SpecifiedScalars[e.name as SpecifiedScalarNames]
|
||||
return
|
||||
}
|
||||
const backingType = this.resolveBackingType(e.name)
|
||||
if (backingType) {
|
||||
scalarMap[e.name] = backingType
|
||||
} else {
|
||||
scalarMap[e.name] = 'any'
|
||||
}
|
||||
})
|
||||
return scalarMap
|
||||
}
|
||||
|
||||
printInputTypeMap() {
|
||||
return this.printTypeFieldInterface('NexusGenInputs', this.buildInputTypeMap(), 'input type')
|
||||
}
|
||||
|
@ -348,13 +366,16 @@ export class TypegenPrinter {
|
|||
return this.printTypeInterface('NexusGenEnums', this.buildEnumTypeMap())
|
||||
}
|
||||
|
||||
printScalarTypeMap() {
|
||||
return this.printTypeInterface('NexusGenScalars', this.buildScalarTypeMap())
|
||||
}
|
||||
|
||||
buildRootTypeMap() {
|
||||
const rootTypeMap: RootTypeMapping = {}
|
||||
const hasFields: (GraphQLInterfaceType | GraphQLObjectType | GraphQLScalarType | GraphQLUnionType)[] = []
|
||||
const hasFields: (GraphQLInterfaceType | GraphQLObjectType | GraphQLUnionType)[] = []
|
||||
hasFields
|
||||
.concat(this.groupedTypes.object)
|
||||
.concat(this.groupedTypes.interface)
|
||||
.concat(this.groupedTypes.scalar)
|
||||
.concat(this.groupedTypes.union)
|
||||
.forEach((type) => {
|
||||
const rootTyping = this.resolveBackingType(type.name)
|
||||
|
@ -362,13 +383,7 @@ export class TypegenPrinter {
|
|||
rootTypeMap[type.name] = rootTyping
|
||||
return
|
||||
}
|
||||
if (isScalarType(type)) {
|
||||
if (isSpecifiedScalarType(type)) {
|
||||
rootTypeMap[type.name] = SpecifiedScalars[type.name as SpecifiedScalarNames]
|
||||
} else {
|
||||
rootTypeMap[type.name] = 'any'
|
||||
}
|
||||
} else if (isUnionType(type)) {
|
||||
if (isUnionType(type)) {
|
||||
rootTypeMap[type.name] = type
|
||||
.getTypes()
|
||||
.map((t) => `NexusGenRootTypes['${t.name}']`)
|
||||
|
@ -411,15 +426,18 @@ export class TypegenPrinter {
|
|||
|
||||
buildAllTypesMap() {
|
||||
const typeMap: TypeMapping = {}
|
||||
const toCheck: (GraphQLInputObjectType | GraphQLEnumType)[] = []
|
||||
const toCheck: (GraphQLInputObjectType | GraphQLEnumType | GraphQLScalarType)[] = []
|
||||
toCheck
|
||||
.concat(this.groupedTypes.input)
|
||||
.concat(this.groupedTypes.enum)
|
||||
.concat(this.groupedTypes.scalar)
|
||||
.forEach((type) => {
|
||||
if (isInputObjectType(type)) {
|
||||
typeMap[type.name] = `NexusGenInputs['${type.name}']`
|
||||
} else if (isEnumType(type)) {
|
||||
typeMap[type.name] = `NexusGenEnums['${type.name}']`
|
||||
} else if (isScalarType(type)) {
|
||||
typeMap[type.name] = `NexusGenScalars['${type.name}']`
|
||||
}
|
||||
})
|
||||
return typeMap
|
||||
|
@ -642,12 +660,7 @@ export class TypegenPrinter {
|
|||
if (isSpecifiedScalarType(type)) {
|
||||
return SpecifiedScalars[type.name as SpecifiedScalarNames]
|
||||
}
|
||||
const backingType = (this.typegenInfo.backingTypeMap as any)[type.name]
|
||||
if (typeof backingType === 'string') {
|
||||
return backingType
|
||||
} else {
|
||||
return 'any'
|
||||
}
|
||||
return `NexusGenScalars['${type.name}']`
|
||||
}
|
||||
|
||||
printPlugins() {
|
||||
|
|
|
@ -35,17 +35,25 @@ export interface NexusGenEnums {
|
|||
TestEnumType: TestEnum
|
||||
}
|
||||
|
||||
export interface NexusGenScalars {
|
||||
String: string
|
||||
Int: number
|
||||
Float: number
|
||||
Boolean: boolean
|
||||
ID: string
|
||||
}
|
||||
|
||||
export interface NexusGenRootTypes {
|
||||
Query: {};
|
||||
String: string;
|
||||
Int: number;
|
||||
Float: number;
|
||||
Boolean: boolean;
|
||||
ID: string;
|
||||
}
|
||||
|
||||
export interface NexusGenAllTypes extends NexusGenRootTypes {
|
||||
TestEnumType: NexusGenEnums['TestEnumType'];
|
||||
String: NexusGenScalars['String'];
|
||||
Int: NexusGenScalars['Int'];
|
||||
Float: NexusGenScalars['Float'];
|
||||
Boolean: NexusGenScalars['Boolean'];
|
||||
ID: NexusGenScalars['ID'];
|
||||
}
|
||||
|
||||
export interface NexusGenFieldTypes {
|
||||
|
|
|
@ -28,7 +28,7 @@ exports[`typegenPrinter should build an argument type map 1`] = `
|
|||
input: NexusGenInputs['CreatePostInput']; // CreatePostInput!
|
||||
}
|
||||
registerClick: { // args
|
||||
uuid?: string | null; // UUID
|
||||
uuid?: NexusGenScalars['UUID'] | null; // UUID
|
||||
}
|
||||
someList: { // args
|
||||
items: Array<string | null>; // [String]!
|
||||
|
@ -58,7 +58,7 @@ exports[`typegenPrinter should not print roots for fields with resolvers 1`] = `
|
|||
geo: number[][]; // [[Float!]!]!
|
||||
id: string; // ID!
|
||||
messyGeo?: Array<number[] | null> | null; // [[Float!]]
|
||||
uuid: string; // UUID!
|
||||
uuid: NexusGenScalars['UUID']; // UUID!
|
||||
}
|
||||
Query: {};
|
||||
User: { // root type
|
||||
|
@ -69,12 +69,6 @@ exports[`typegenPrinter should not print roots for fields with resolvers 1`] = `
|
|||
phone?: string | null; // String
|
||||
}
|
||||
Node: NexusGenRootTypes['Post'] | NexusGenRootTypes['User'];
|
||||
String: string;
|
||||
Int: number;
|
||||
Float: number;
|
||||
Boolean: boolean;
|
||||
ID: string;
|
||||
UUID: string;
|
||||
ExampleUnion: NexusGenRootTypes['Post'] | NexusGenRootTypes['User'];
|
||||
}"
|
||||
`;
|
||||
|
@ -91,7 +85,7 @@ exports[`typegenPrinter should print a return type map 1`] = `
|
|||
geo: number[][]; // [[Float!]!]!
|
||||
id: string; // ID!
|
||||
messyGeo: Array<number[] | null> | null; // [[Float!]]
|
||||
uuid: string; // UUID!
|
||||
uuid: NexusGenScalars['UUID']; // UUID!
|
||||
}
|
||||
Query: { // field return type
|
||||
posts: NexusGenRootTypes['Post'][]; // [Post!]!
|
||||
|
@ -120,7 +114,7 @@ exports[`typegenPrinter should print a root type map 1`] = `
|
|||
geo: number[][]; // [[Float!]!]!
|
||||
id: string; // ID!
|
||||
messyGeo?: Array<number[] | null> | null; // [[Float!]]
|
||||
uuid: string; // UUID!
|
||||
uuid: NexusGenScalars['UUID']; // UUID!
|
||||
}
|
||||
Query: {};
|
||||
User: { // root type
|
||||
|
@ -132,12 +126,6 @@ exports[`typegenPrinter should print a root type map 1`] = `
|
|||
posts: NexusGenRootTypes['Post'][]; // [Post!]!
|
||||
}
|
||||
Node: NexusGenRootTypes['Post'] | NexusGenRootTypes['User'];
|
||||
String: string;
|
||||
Int: number;
|
||||
Float: number;
|
||||
Boolean: boolean;
|
||||
ID: string;
|
||||
UUID: string;
|
||||
ExampleUnion: NexusGenRootTypes['Post'] | NexusGenRootTypes['User'];
|
||||
}"
|
||||
`;
|
||||
|
@ -175,6 +163,15 @@ export interface NexusGenEnums {
|
|||
SomeEnum: \\"A\\" | \\"B\\"
|
||||
}
|
||||
|
||||
export interface NexusGenScalars {
|
||||
String: string
|
||||
Int: number
|
||||
Float: number
|
||||
Boolean: boolean
|
||||
ID: string
|
||||
UUID: string
|
||||
}
|
||||
|
||||
export interface NexusGenRootTypes {
|
||||
Mutation: {};
|
||||
Post: { // root type
|
||||
|
@ -182,7 +179,7 @@ export interface NexusGenRootTypes {
|
|||
geo: number[][]; // [[Float!]!]!
|
||||
id: string; // ID!
|
||||
messyGeo?: Array<number[] | null> | null; // [[Float!]]
|
||||
uuid: string; // UUID!
|
||||
uuid: NexusGenScalars['UUID']; // UUID!
|
||||
}
|
||||
Query: {};
|
||||
User: { // root type
|
||||
|
@ -194,12 +191,6 @@ export interface NexusGenRootTypes {
|
|||
posts: NexusGenRootTypes['Post'][]; // [Post!]!
|
||||
}
|
||||
Node: NexusGenRootTypes['Post'] | NexusGenRootTypes['User'];
|
||||
String: string;
|
||||
Int: number;
|
||||
Float: number;
|
||||
Boolean: boolean;
|
||||
ID: string;
|
||||
UUID: string;
|
||||
ExampleUnion: NexusGenRootTypes['Post'] | NexusGenRootTypes['User'];
|
||||
}
|
||||
|
||||
|
@ -208,6 +199,12 @@ export interface NexusGenAllTypes extends NexusGenRootTypes {
|
|||
PostFilters: NexusGenInputs['PostFilters'];
|
||||
OrderEnum: NexusGenEnums['OrderEnum'];
|
||||
SomeEnum: NexusGenEnums['SomeEnum'];
|
||||
String: NexusGenScalars['String'];
|
||||
Int: NexusGenScalars['Int'];
|
||||
Float: NexusGenScalars['Float'];
|
||||
Boolean: NexusGenScalars['Boolean'];
|
||||
ID: NexusGenScalars['ID'];
|
||||
UUID: NexusGenScalars['UUID'];
|
||||
}
|
||||
|
||||
export interface NexusGenFieldTypes {
|
||||
|
@ -221,7 +218,7 @@ export interface NexusGenFieldTypes {
|
|||
geo: number[][]; // [[Float!]!]!
|
||||
id: string; // ID!
|
||||
messyGeo: Array<number[] | null> | null; // [[Float!]]
|
||||
uuid: string; // UUID!
|
||||
uuid: NexusGenScalars['UUID']; // UUID!
|
||||
}
|
||||
Query: { // field return type
|
||||
posts: NexusGenRootTypes['Post'][]; // [Post!]!
|
||||
|
@ -247,7 +244,7 @@ export interface NexusGenArgTypes {
|
|||
input: NexusGenInputs['CreatePostInput']; // CreatePostInput!
|
||||
}
|
||||
registerClick: { // args
|
||||
uuid?: string | null; // UUID
|
||||
uuid?: NexusGenScalars['UUID'] | null; // UUID
|
||||
}
|
||||
someList: { // args
|
||||
items: Array<string | null>; // [String]!
|
||||
|
|
|
@ -34,6 +34,14 @@ export interface NexusGenInputs {
|
|||
|
||||
export interface NexusGenEnums {}
|
||||
|
||||
export interface NexusGenScalars {
|
||||
String: string;
|
||||
Int: number;
|
||||
Float: number;
|
||||
Boolean: boolean;
|
||||
ID: string;
|
||||
}
|
||||
|
||||
export interface NexusGenRootTypes {
|
||||
Mutation: {};
|
||||
Post: {
|
||||
|
@ -43,15 +51,15 @@ export interface NexusGenRootTypes {
|
|||
};
|
||||
Query: {};
|
||||
User: { firstName: string; lastName: string };
|
||||
String: string;
|
||||
Int: number;
|
||||
Float: number;
|
||||
Boolean: boolean;
|
||||
ID: string;
|
||||
}
|
||||
|
||||
export interface NexusGenAllTypes extends NexusGenRootTypes {
|
||||
PostSearchInput: NexusGenInputs["PostSearchInput"];
|
||||
String: NexusGenScalars["String"];
|
||||
Int: NexusGenScalars["Int"];
|
||||
Float: NexusGenScalars["Float"];
|
||||
Boolean: NexusGenScalars["Boolean"];
|
||||
ID: NexusGenScalars["ID"];
|
||||
}
|
||||
|
||||
export interface NexusGenFieldTypes {
|
||||
|
|
|
@ -64,16 +64,24 @@ export interface NexusGenInputs {
|
|||
export interface NexusGenEnums {
|
||||
}
|
||||
|
||||
export interface NexusGenScalars {
|
||||
String: string
|
||||
Int: number
|
||||
Float: number
|
||||
Boolean: boolean
|
||||
ID: string
|
||||
}
|
||||
|
||||
export interface NexusGenRootTypes {
|
||||
Query: {};
|
||||
String: string;
|
||||
Int: number;
|
||||
Float: number;
|
||||
Boolean: boolean;
|
||||
ID: string;
|
||||
}
|
||||
|
||||
export interface NexusGenAllTypes extends NexusGenRootTypes {
|
||||
String: NexusGenScalars['String'];
|
||||
Int: NexusGenScalars['Int'];
|
||||
Float: NexusGenScalars['Float'];
|
||||
Boolean: NexusGenScalars['Boolean'];
|
||||
ID: NexusGenScalars['ID'];
|
||||
}
|
||||
|
||||
export interface NexusGenFieldTypes {
|
||||
|
|
|
@ -22,16 +22,24 @@ export interface NexusGenInputs {
|
|||
export interface NexusGenEnums {
|
||||
}
|
||||
|
||||
export interface NexusGenScalars {
|
||||
String: string
|
||||
Int: number
|
||||
Float: number
|
||||
Boolean: boolean
|
||||
ID: string
|
||||
}
|
||||
|
||||
export interface NexusGenRootTypes {
|
||||
Query: {};
|
||||
String: string;
|
||||
Int: number;
|
||||
Float: number;
|
||||
Boolean: boolean;
|
||||
ID: string;
|
||||
}
|
||||
|
||||
export interface NexusGenAllTypes extends NexusGenRootTypes {
|
||||
String: NexusGenScalars['String'];
|
||||
Int: NexusGenScalars['Int'];
|
||||
Float: NexusGenScalars['Float'];
|
||||
Boolean: NexusGenScalars['Boolean'];
|
||||
ID: NexusGenScalars['ID'];
|
||||
}
|
||||
|
||||
export interface NexusGenFieldTypes {
|
||||
|
|
|
@ -1,8 +1,27 @@
|
|||
import { graphql } from 'graphql'
|
||||
import { GraphQLDate, GraphQLDateTime } from 'graphql-iso-date'
|
||||
import { asNexusMethod, inputObjectType, makeSchema, objectType, queryField } from '../src/core'
|
||||
import {
|
||||
asNexusMethod,
|
||||
inputObjectType,
|
||||
makeSchema,
|
||||
makeSchemaInternal,
|
||||
objectType,
|
||||
queryField,
|
||||
resolveTypegenConfig,
|
||||
} from '../src/core'
|
||||
import { TypegenMetadata } from '../src/typegenMetadata'
|
||||
|
||||
describe('scalarType', () => {
|
||||
it('asNexusMethod: may specify the TS type of the scalar', async () => {
|
||||
const schema = makeSchemaInternal({
|
||||
types: [asNexusMethod(GraphQLDate, 'date', 'Int')],
|
||||
outputs: false,
|
||||
shouldExitAfterGenerateArtifacts: false,
|
||||
})
|
||||
const generator = new TypegenMetadata(resolveTypegenConfig(schema.finalConfig))
|
||||
const typegen = await generator.generateTypesFile(schema.schema, 'foo.ts')
|
||||
expect(typegen).toMatch(/Date: Int/)
|
||||
})
|
||||
it('asNexusMethod: should wrap a scalar and make it available on the builder', async () => {
|
||||
const schema = makeSchema({
|
||||
types: [
|
||||
|
|
|
@ -26,18 +26,21 @@ export interface NexusGenEnums {
|
|||
SomeEnum: 'A' | 'B'
|
||||
}
|
||||
|
||||
export interface NexusGenRootTypes {
|
||||
Mutation: {}
|
||||
Post: {}
|
||||
Query: {}
|
||||
User: {}
|
||||
Node: NexusGenRootTypes['Post'] | NexusGenRootTypes['User']
|
||||
export interface NexusGenScalars {
|
||||
String: string
|
||||
Int: number
|
||||
Float: number
|
||||
Boolean: boolean
|
||||
ID: string
|
||||
UUID: any
|
||||
}
|
||||
|
||||
export interface NexusGenRootTypes {
|
||||
Mutation: {}
|
||||
Post: {}
|
||||
Query: {}
|
||||
User: {}
|
||||
Node: NexusGenRootTypes['Post'] | NexusGenRootTypes['User']
|
||||
ExampleUnion: NexusGenRootTypes['Post'] | NexusGenRootTypes['User']
|
||||
}
|
||||
|
||||
|
@ -46,6 +49,12 @@ export interface NexusGenAllTypes extends NexusGenRootTypes {
|
|||
PostFilters: NexusGenInputs['PostFilters']
|
||||
OrderEnum: NexusGenEnums['OrderEnum']
|
||||
SomeEnum: NexusGenEnums['SomeEnum']
|
||||
String: NexusGenScalars['String']
|
||||
Int: NexusGenScalars['Int']
|
||||
Float: NexusGenScalars['Float']
|
||||
Boolean: NexusGenScalars['Boolean']
|
||||
ID: NexusGenScalars['ID']
|
||||
UUID: NexusGenScalars['UUID']
|
||||
}
|
||||
|
||||
export interface NexusGenFieldTypes {
|
||||
|
@ -61,7 +70,7 @@ export interface NexusGenFieldTypes {
|
|||
geo: number[][] // [[Float!]!]!
|
||||
id: string // ID!
|
||||
messyGeo: Array<number[] | null> | null // [[Float!]]
|
||||
uuid: any // UUID!
|
||||
uuid: NexusGenScalars['UUID'] // UUID!
|
||||
}
|
||||
Query: {
|
||||
// field return type
|
||||
|
@ -92,7 +101,7 @@ export interface NexusGenArgTypes {
|
|||
}
|
||||
registerClick: {
|
||||
// args
|
||||
uuid?: any | null // UUID
|
||||
uuid?: NexusGenScalars['UUID'] | null // UUID
|
||||
}
|
||||
someList: {
|
||||
// args
|
||||
|
|
Loading…
Reference in New Issue