diff --git a/src/definitions/scalarType.ts b/src/definitions/scalarType.ts index 7ea6f61c..190e8922 100644 --- a/src/definitions/scalarType.ts +++ b/src/definitions/scalarType.ts @@ -52,8 +52,13 @@ export function scalarType(options: NexusScalarTypeConf return new NexusScalarTypeDef(options.name, options) } -export function asNexusMethod(scalar: T, methodName: string): T { +export function asNexusMethod( + scalar: T, + methodName: string, + rootTyping?: RootTypingDef +): T { return decorateType(scalar, { asNexusMethod: methodName, + rootTyping: rootTyping, }) } diff --git a/src/typegenPrinter.ts b/src/typegenPrinter.ts index f7a2da88..3d0957b9 100644 --- a/src/typegenPrinter.ts +++ b/src/typegenPrinter.ts @@ -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() { diff --git a/tests/__snapshots__/backingTypes.spec.ts.snap b/tests/__snapshots__/backingTypes.spec.ts.snap index 8fec7a67..3d897ab5 100644 --- a/tests/__snapshots__/backingTypes.spec.ts.snap +++ b/tests/__snapshots__/backingTypes.spec.ts.snap @@ -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 { diff --git a/tests/__snapshots__/typegenPrinter.spec.ts.snap b/tests/__snapshots__/typegenPrinter.spec.ts.snap index cd2d4c28..7f7f101b 100644 --- a/tests/__snapshots__/typegenPrinter.spec.ts.snap +++ b/tests/__snapshots__/typegenPrinter.spec.ts.snap @@ -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]! @@ -58,7 +58,7 @@ exports[`typegenPrinter should not print roots for fields with resolvers 1`] = ` geo: number[][]; // [[Float!]!]! id: string; // ID! messyGeo?: Array | 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 | 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 | 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 | 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 | 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]! diff --git a/tests/integration/_app.typegen.ts b/tests/integration/_app.typegen.ts index 3936f04d..03ad6583 100644 --- a/tests/integration/_app.typegen.ts +++ b/tests/integration/_app.typegen.ts @@ -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 { diff --git a/tests/plugins/__snapshots__/fieldAuthorizePlugin.spec.ts.snap b/tests/plugins/__snapshots__/fieldAuthorizePlugin.spec.ts.snap index f14e58fa..a077b369 100644 --- a/tests/plugins/__snapshots__/fieldAuthorizePlugin.spec.ts.snap +++ b/tests/plugins/__snapshots__/fieldAuthorizePlugin.spec.ts.snap @@ -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 { diff --git a/tests/plugins/__snapshots__/queryComplexityPlugin.spec.ts.snap b/tests/plugins/__snapshots__/queryComplexityPlugin.spec.ts.snap index 5c6354c9..0ff67514 100644 --- a/tests/plugins/__snapshots__/queryComplexityPlugin.spec.ts.snap +++ b/tests/plugins/__snapshots__/queryComplexityPlugin.spec.ts.snap @@ -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 { diff --git a/tests/scalarType.spec.ts b/tests/scalarType.spec.ts index 240e1d3c..e36f57ca 100644 --- a/tests/scalarType.spec.ts +++ b/tests/scalarType.spec.ts @@ -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: [ diff --git a/tests/typegen/types.gen.ts b/tests/typegen/types.gen.ts index 6b424d2b..6369fe72 100644 --- a/tests/typegen/types.gen.ts +++ b/tests/typegen/types.gen.ts @@ -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 | 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