From 5f930dad47a16e0e882c24253f61c07e09b02b02 Mon Sep 17 00:00:00 2001 From: jack Date: Wed, 28 Aug 2019 20:22:29 +1000 Subject: [PATCH 1/6] WIP --- README.md | 35 +++++++++++------------------- src/cli.ts | 2 +- src/types.ts | 3 ++- src/typescriptResolverGenerator.ts | 13 +++++++---- 4 files changed, 25 insertions(+), 28 deletions(-) diff --git a/README.md b/README.md index 66cb441..44eb75e 100644 --- a/README.md +++ b/README.md @@ -52,7 +52,7 @@ The file generated will have some types that can make it type-safed when writing * Parent type and resolve result is default to `any`, but could be overwritten in your code For example, if you schema is like this: -``` +```gql schema { query: RootQuery } @@ -129,24 +129,15 @@ export interface RootQueryToUsersResolver`, +// due to an issue with VSCode that not showing auto completion when returns is a mix of `T | Promise` (see [#17](https://github.com/dangcuuson/graphql-schema-typescript/issues/17)) + +// smartTParent: true +// smartTResult: true +// asyncResult: 'always' +export interface RootQueryToUsersResolver { + (parent: TParent, args: RootQueryToUsersArgs, context: any, info: GraphQLResolveInfo): Promise; // the different is here + +``` \ No newline at end of file diff --git a/src/cli.ts b/src/cli.ts index be60623..abb9d2f 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -72,7 +72,7 @@ yargs }) .option(asyncResult, { desc: 'Set return type of resolver to `TResult | Promise`', - boolean: true + choices: [true, 'always'] }) .option(requireResolverTypes, { desc: 'Set resolvers to be required. Useful to ensure no resolvers is missing', diff --git a/src/types.ts b/src/types.ts index 203df17..5c85eae 100644 --- a/src/types.ts +++ b/src/types.ts @@ -81,12 +81,13 @@ export interface GenerateTypescriptOptions { /** * This option is for resolvers * If true, set return type of resolver to `TResult | Promise` + * If 'awalys', set return type of resolver to `Promise` * * e.g: interface QueryToUsersResolver { * (parent: TParent, args: {}, context: any, info): TResult extends Promise ? TResult : TResult | Promise * } */ - asyncResult?: boolean; + asyncResult?: boolean | 'always'; /** * If true, field resolver of each type will be required, instead of optional diff --git a/src/typescriptResolverGenerator.ts b/src/typescriptResolverGenerator.ts index 08a8ea7..8ea309d 100644 --- a/src/typescriptResolverGenerator.ts +++ b/src/typescriptResolverGenerator.ts @@ -116,7 +116,7 @@ export class TSResolverGenerator { private generateTypeResolver(type: IntrospectionUnionType | IntrospectionInterfaceType) { const possbileTypes = type.possibleTypes.map(pt => `'${pt.name}'`); const interfaceName = `${this.options.typePrefix}${type.name}TypeResolver`; - const infoModifier = this.options.optionalResolverInfo ? '?' : ''; + const infoModifier = this.options.optionalResolverInfo ? '?' : ''; this.resolverInterfaces.push(...[ `export interface ${interfaceName} {`, @@ -164,8 +164,13 @@ export class TSResolverGenerator { const TParent = this.guessTParent(objectType.name); const TResult = this.guessTResult(field); const infoModifier = this.options.optionalResolverInfo ? '?' : ''; - const returnType = this.options.asyncResult ? 'TResult | Promise' : 'TResult'; - const subscriptionReturnType = + const returnType = + this.options.asyncResult === 'always' + ? 'Promise' + : !!this.options.asyncResult + ? 'TResult | Promise' + : 'TResult'; + const subscriptionReturnType = this.options.asyncResult ? 'AsyncIterator | Promise>' : 'AsyncIterator'; const fieldResolverTypeDef = !isSubscription ? [ @@ -179,7 +184,7 @@ export class TSResolverGenerator { // tslint:disable-next-line:max-line-length `resolve${this.getModifier()}: (parent: TParent, args: ${argsType}, context: ${this.contextType}, info${infoModifier}: GraphQLResolveInfo) => ${returnType};`, // tslint:disable-next-line:max-line-length - `subscribe: (parent: TParent, args: ${argsType}, context: ${this.contextType}, info${infoModifier}: GraphQLResolveInfo) => ${subscriptionReturnType};`, + `subscribe: (parent: TParent, args: ${argsType}, context: ${this.contextType}, info${infoModifier}: GraphQLResolveInfo) => ${subscriptionReturnType};`, '}', '' ]; From 349838ab7af07b641c9be49b39f6b3dbcd01c23a Mon Sep 17 00:00:00 2001 From: jack Date: Mon, 2 Sep 2019 18:37:54 +1000 Subject: [PATCH 2/6] update README.md - include vscode extension --- README.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 44eb75e..829e9b5 100644 --- a/README.md +++ b/README.md @@ -9,11 +9,10 @@ types to make it type-safed when developing GraphQL server (mainly resolvers) ## Features -### Generate Typescript from Schema Definition -### Support [Typescript string enum](https://github.com/Microsoft/TypeScript/wiki/What's-new-in-TypeScript#typescript-25) with fallback to string union (fallback not tested yet) -### Convert GraphQL description into JSDoc -### Also add deprecated field and reason into JSDoc +### Generate Typescript from Schema Definition (1-1 mapping from GQL type to TypeScript) +### Convert GraphQL description into JSDoc, include deprecated directive ### [Generate TypeScripts to support writing resolvers](#type-resolvers) +### [VSCode extension](#https://github.com/liyikun/vscode-graphql-schema-typescript) (credit to [@liyikun](https://github.com/liyikun)) ## Usage From d4947bc1851451f350cb559800248bc9d33d2f64 Mon Sep 17 00:00:00 2001 From: jack Date: Mon, 16 Sep 2019 18:31:02 +1000 Subject: [PATCH 3/6] close #20 & close #29 --- .../option.customScalarType.test.ts.snap | 4 +- .../option.global_nameSpace.test.ts.snap | 56 ++++++++++++++++--- .../option.importStatements.test.ts.snap | 2 +- .../option.minimizedInterface.test.ts.snap | 2 +- .../option.optionalResolverInfo.test.ts.snap | 2 +- .../option.resolver.test.ts.snap | 8 +-- .../option.strictMode.test.ts.snap | 2 +- .../option.typePrefix.test.ts.snap | 4 +- .../__snapshots__/schemaAsString.test.ts.snap | 2 +- src/__tests__/option.global_nameSpace.test.ts | 6 +- src/index.ts | 3 +- src/typescriptGenerator.ts | 10 +--- 12 files changed, 68 insertions(+), 33 deletions(-) diff --git a/src/__tests__/__snapshots__/option.customScalarType.test.ts.snap b/src/__tests__/__snapshots__/option.customScalarType.test.ts.snap index cb66536..00da0c8 100644 --- a/src/__tests__/__snapshots__/option.customScalarType.test.ts.snap +++ b/src/__tests__/__snapshots__/option.customScalarType.test.ts.snap @@ -57,7 +57,7 @@ export interface GQLUser { * In the future, this will be changed by having User as interface * and implementing multiple User */ -export enum GQLUserRole { +export const enum GQLUserRole { /** * System Administrator @@ -649,7 +649,7 @@ export interface GQLUser { * In the future, this will be changed by having User as interface * and implementing multiple User */ -export enum GQLUserRole { +export const enum GQLUserRole { /** * System Administrator diff --git a/src/__tests__/__snapshots__/option.global_nameSpace.test.ts.snap b/src/__tests__/__snapshots__/option.global_nameSpace.test.ts.snap index 4ffb5ac..7946f02 100644 --- a/src/__tests__/__snapshots__/option.global_nameSpace.test.ts.snap +++ b/src/__tests__/__snapshots__/option.global_nameSpace.test.ts.snap @@ -61,8 +61,29 @@ declare global { * In the future, this will be changed by having User as interface * and implementing multiple User */ - export type GQLUserRole = 'sysAdmin' | 'manager' | 'clerk' | 'employee'; - // NOTE: enum UserRole is generate as string union instead of string enum because the types is generated under global scope + export const enum GQLUserRole { + + /** + * System Administrator + */ + sysAdmin = 'sysAdmin', + + /** + * Manager - Have access to manage functions + */ + manager = 'manager', + + /** + * General Staff + */ + clerk = 'clerk', + + /** + * + * @deprecated Use 'clerk' instead + */ + employee = 'employee' + } export interface GQLIProduct { id: string; @@ -577,7 +598,7 @@ declare global { }" `; -exports[`global + namespace should wrap types in global and use string union if global is configured 1`] = ` +exports[`global + namespace should wrap types in global and use const enum if global is configured 1`] = ` "/* tslint:disable */ /* eslint-disable */ import { GraphQLResolveInfo, GraphQLScalarType } from 'graphql'; @@ -637,8 +658,29 @@ declare global { * In the future, this will be changed by having User as interface * and implementing multiple User */ - export type GQLUserRole = 'sysAdmin' | 'manager' | 'clerk' | 'employee'; - // NOTE: enum UserRole is generate as string union instead of string enum because the types is generated under global scope + export const enum GQLUserRole { + + /** + * System Administrator + */ + sysAdmin = 'sysAdmin', + + /** + * Manager - Have access to manage functions + */ + manager = 'manager', + + /** + * General Staff + */ + clerk = 'clerk', + + /** + * + * @deprecated Use 'clerk' instead + */ + employee = 'employee' + } export interface GQLIProduct { id: string; @@ -1162,7 +1204,7 @@ import { GraphQLResolveInfo, GraphQLScalarType } from 'graphql'; */ -namespace MyNamespace { +declare namespace MyNamespace { /******************************* * * * TYPE DEFS * @@ -1210,7 +1252,7 @@ namespace MyNamespace { * In the future, this will be changed by having User as interface * and implementing multiple User */ - export enum GQLUserRole { + export const enum GQLUserRole { /** * System Administrator diff --git a/src/__tests__/__snapshots__/option.importStatements.test.ts.snap b/src/__tests__/__snapshots__/option.importStatements.test.ts.snap index c7f0d96..3e8b872 100644 --- a/src/__tests__/__snapshots__/option.importStatements.test.ts.snap +++ b/src/__tests__/__snapshots__/option.importStatements.test.ts.snap @@ -59,7 +59,7 @@ export interface GQLUser { * In the future, this will be changed by having User as interface * and implementing multiple User */ -export enum GQLUserRole { +export const enum GQLUserRole { /** * System Administrator diff --git a/src/__tests__/__snapshots__/option.minimizedInterface.test.ts.snap b/src/__tests__/__snapshots__/option.minimizedInterface.test.ts.snap index 353e20f..6517623 100644 --- a/src/__tests__/__snapshots__/option.minimizedInterface.test.ts.snap +++ b/src/__tests__/__snapshots__/option.minimizedInterface.test.ts.snap @@ -57,7 +57,7 @@ export interface GQLUser { * In the future, this will be changed by having User as interface * and implementing multiple User */ -export enum GQLUserRole { +export const enum GQLUserRole { /** * System Administrator diff --git a/src/__tests__/__snapshots__/option.optionalResolverInfo.test.ts.snap b/src/__tests__/__snapshots__/option.optionalResolverInfo.test.ts.snap index b7445c8..630d33c 100644 --- a/src/__tests__/__snapshots__/option.optionalResolverInfo.test.ts.snap +++ b/src/__tests__/__snapshots__/option.optionalResolverInfo.test.ts.snap @@ -57,7 +57,7 @@ export interface GQLUser { * In the future, this will be changed by having User as interface * and implementing multiple User */ -export enum GQLUserRole { +export const enum GQLUserRole { /** * System Administrator diff --git a/src/__tests__/__snapshots__/option.resolver.test.ts.snap b/src/__tests__/__snapshots__/option.resolver.test.ts.snap index 0e8a9da..1a97c9c 100644 --- a/src/__tests__/__snapshots__/option.resolver.test.ts.snap +++ b/src/__tests__/__snapshots__/option.resolver.test.ts.snap @@ -57,7 +57,7 @@ export interface GQLUser { * In the future, this will be changed by having User as interface * and implementing multiple User */ -export enum GQLUserRole { +export const enum GQLUserRole { /** * System Administrator @@ -649,7 +649,7 @@ export interface GQLUser { * In the future, this will be changed by having User as interface * and implementing multiple User */ -export enum GQLUserRole { +export const enum GQLUserRole { /** * System Administrator @@ -1241,7 +1241,7 @@ export interface GQLUser { * In the future, this will be changed by having User as interface * and implementing multiple User */ -export enum GQLUserRole { +export const enum GQLUserRole { /** * System Administrator @@ -1833,7 +1833,7 @@ export interface GQLUser { * In the future, this will be changed by having User as interface * and implementing multiple User */ -export enum GQLUserRole { +export const enum GQLUserRole { /** * System Administrator diff --git a/src/__tests__/__snapshots__/option.strictMode.test.ts.snap b/src/__tests__/__snapshots__/option.strictMode.test.ts.snap index 9c1304e..8bf4938 100644 --- a/src/__tests__/__snapshots__/option.strictMode.test.ts.snap +++ b/src/__tests__/__snapshots__/option.strictMode.test.ts.snap @@ -57,7 +57,7 @@ export interface GQLUser { * In the future, this will be changed by having User as interface * and implementing multiple User */ -export enum GQLUserRole { +export const enum GQLUserRole { /** * System Administrator diff --git a/src/__tests__/__snapshots__/option.typePrefix.test.ts.snap b/src/__tests__/__snapshots__/option.typePrefix.test.ts.snap index 2ba7c99..0415d6f 100644 --- a/src/__tests__/__snapshots__/option.typePrefix.test.ts.snap +++ b/src/__tests__/__snapshots__/option.typePrefix.test.ts.snap @@ -57,7 +57,7 @@ export interface User { * In the future, this will be changed by having User as interface * and implementing multiple User */ -export enum UserRole { +export const enum UserRole { /** * System Administrator @@ -649,7 +649,7 @@ export interface MyCustomPrefixUser { * In the future, this will be changed by having User as interface * and implementing multiple User */ -export enum MyCustomPrefixUserRole { +export const enum MyCustomPrefixUserRole { /** * System Administrator diff --git a/src/__tests__/__snapshots__/schemaAsString.test.ts.snap b/src/__tests__/__snapshots__/schemaAsString.test.ts.snap index cd42efb..362ae12 100644 --- a/src/__tests__/__snapshots__/schemaAsString.test.ts.snap +++ b/src/__tests__/__snapshots__/schemaAsString.test.ts.snap @@ -57,7 +57,7 @@ export interface GQLUser { * In the future, this will be changed by having User as interface * and implementing multiple User */ -export enum GQLUserRole { +export const enum GQLUserRole { /** * System Administrator diff --git a/src/__tests__/option.global_nameSpace.test.ts b/src/__tests__/option.global_nameSpace.test.ts index 468bc3b..60b294e 100644 --- a/src/__tests__/option.global_nameSpace.test.ts +++ b/src/__tests__/option.global_nameSpace.test.ts @@ -1,15 +1,15 @@ import { executeApiTest } from './testUtils'; describe('global + namespace', () => { - it('should wrap types in global and use string union if global is configured', async () => { + it('should wrap types in global and use const enum if global is configured', async () => { const generated = await executeApiTest('global.ts', { global: true }); expect(generated).toContain('declare global {'); - expect(generated).toContain(`export type GQLUserRole = 'sysAdmin' | 'manager' | 'clerk' | 'employee';`); + expect(generated).toContain(`export const enum GQLUserRole {`); }); it('should wrap types in namespace if namespace is configured', async () => { const generated = await executeApiTest('global.ts', { namespace: 'MyNamespace' }); - expect(generated).toContain('namespace MyNamespace {'); + expect(generated).toContain('declare namespace MyNamespace {'); }); it('should have no conflict between global and namespace config', async () => { diff --git a/src/index.ts b/src/index.ts index a095f4e..b76fdb2 100644 --- a/src/index.ts +++ b/src/index.ts @@ -83,7 +83,8 @@ export const generateTSTypesAsString = async (schema: GraphQLSchema | string, op if (mergedOptions.namespace) { body = [ - `namespace ${options.namespace} {`, + // if namespace is under global, it doesn't need to be declared again + `${mergedOptions.global ? '' : 'declare '}namespace ${options.namespace} {`, ...body, '}' ]; diff --git a/src/typescriptGenerator.ts b/src/typescriptGenerator.ts index f235406..fa85f8e 100644 --- a/src/typescriptGenerator.ts +++ b/src/typescriptGenerator.ts @@ -94,14 +94,6 @@ export class TypeScriptGenerator { return this.createUnionType(enumType.name, enumType.enumValues.map(v => `'${v.name}'`)); } - // if generate as global, don't generate string enum as it requires import - if (this.options.global) { - return [ - ...this.createUnionType(enumType.name, enumType.enumValues.map(v => `'${v.name}'`)), - `// NOTE: enum ${enumType.name} is generate as string union instead of string enum because the types is generated under global scope` - ]; - } - let enumBody = enumType.enumValues.reduce( (prevTypescriptDefs, enumValue, index) => { let typescriptDefs: string[] = []; @@ -126,7 +118,7 @@ export class TypeScriptGenerator { ); return [ - `export enum ${this.options.typePrefix}${enumType.name} {`, + `export const enum ${this.options.typePrefix}${enumType.name} {`, ...enumBody, '}' ]; From a2e848df33a9a113ae7dabafadf6b30c5cf914cd Mon Sep 17 00:00:00 2001 From: jack Date: Mon, 16 Sep 2019 18:31:23 +1000 Subject: [PATCH 4/6] 1.3.0 --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index d44d3e6..9e57f28 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "graphql-schema-typescript", - "version": "1.2.10", + "version": "1.3.0", "description": "Generate TypeScript from GraphQL's schema type definitions", "main": "./lib/index.js", "types": "./lib/index.d.ts", @@ -55,4 +55,4 @@ "json" ] } -} \ No newline at end of file +} From d7cb1a3cd02071296c16c5442d83af8acbf43e9f Mon Sep 17 00:00:00 2001 From: jack Date: Mon, 16 Sep 2019 18:58:15 +1000 Subject: [PATCH 5/6] re-close #29 --- .../option.customScalarType.test.ts.snap | 4 ++-- .../option.importStatements.test.ts.snap | 2 +- .../option.minimizedInterface.test.ts.snap | 2 +- .../option.optionalResolverInfo.test.ts.snap | 2 +- .../option.resolver.test.ts.snap | 8 ++++---- .../option.strictMode.test.ts.snap | 2 +- .../option.typePrefix.test.ts.snap | 4 ++-- .../__snapshots__/schemaAsString.test.ts.snap | 2 +- src/index.ts | 10 +++++++--- src/typescriptGenerator.ts | 19 +++++++++++++------ 10 files changed, 33 insertions(+), 22 deletions(-) diff --git a/src/__tests__/__snapshots__/option.customScalarType.test.ts.snap b/src/__tests__/__snapshots__/option.customScalarType.test.ts.snap index 00da0c8..cb66536 100644 --- a/src/__tests__/__snapshots__/option.customScalarType.test.ts.snap +++ b/src/__tests__/__snapshots__/option.customScalarType.test.ts.snap @@ -57,7 +57,7 @@ export interface GQLUser { * In the future, this will be changed by having User as interface * and implementing multiple User */ -export const enum GQLUserRole { +export enum GQLUserRole { /** * System Administrator @@ -649,7 +649,7 @@ export interface GQLUser { * In the future, this will be changed by having User as interface * and implementing multiple User */ -export const enum GQLUserRole { +export enum GQLUserRole { /** * System Administrator diff --git a/src/__tests__/__snapshots__/option.importStatements.test.ts.snap b/src/__tests__/__snapshots__/option.importStatements.test.ts.snap index 3e8b872..c7f0d96 100644 --- a/src/__tests__/__snapshots__/option.importStatements.test.ts.snap +++ b/src/__tests__/__snapshots__/option.importStatements.test.ts.snap @@ -59,7 +59,7 @@ export interface GQLUser { * In the future, this will be changed by having User as interface * and implementing multiple User */ -export const enum GQLUserRole { +export enum GQLUserRole { /** * System Administrator diff --git a/src/__tests__/__snapshots__/option.minimizedInterface.test.ts.snap b/src/__tests__/__snapshots__/option.minimizedInterface.test.ts.snap index 6517623..353e20f 100644 --- a/src/__tests__/__snapshots__/option.minimizedInterface.test.ts.snap +++ b/src/__tests__/__snapshots__/option.minimizedInterface.test.ts.snap @@ -57,7 +57,7 @@ export interface GQLUser { * In the future, this will be changed by having User as interface * and implementing multiple User */ -export const enum GQLUserRole { +export enum GQLUserRole { /** * System Administrator diff --git a/src/__tests__/__snapshots__/option.optionalResolverInfo.test.ts.snap b/src/__tests__/__snapshots__/option.optionalResolverInfo.test.ts.snap index 630d33c..b7445c8 100644 --- a/src/__tests__/__snapshots__/option.optionalResolverInfo.test.ts.snap +++ b/src/__tests__/__snapshots__/option.optionalResolverInfo.test.ts.snap @@ -57,7 +57,7 @@ export interface GQLUser { * In the future, this will be changed by having User as interface * and implementing multiple User */ -export const enum GQLUserRole { +export enum GQLUserRole { /** * System Administrator diff --git a/src/__tests__/__snapshots__/option.resolver.test.ts.snap b/src/__tests__/__snapshots__/option.resolver.test.ts.snap index 1a97c9c..0e8a9da 100644 --- a/src/__tests__/__snapshots__/option.resolver.test.ts.snap +++ b/src/__tests__/__snapshots__/option.resolver.test.ts.snap @@ -57,7 +57,7 @@ export interface GQLUser { * In the future, this will be changed by having User as interface * and implementing multiple User */ -export const enum GQLUserRole { +export enum GQLUserRole { /** * System Administrator @@ -649,7 +649,7 @@ export interface GQLUser { * In the future, this will be changed by having User as interface * and implementing multiple User */ -export const enum GQLUserRole { +export enum GQLUserRole { /** * System Administrator @@ -1241,7 +1241,7 @@ export interface GQLUser { * In the future, this will be changed by having User as interface * and implementing multiple User */ -export const enum GQLUserRole { +export enum GQLUserRole { /** * System Administrator @@ -1833,7 +1833,7 @@ export interface GQLUser { * In the future, this will be changed by having User as interface * and implementing multiple User */ -export const enum GQLUserRole { +export enum GQLUserRole { /** * System Administrator diff --git a/src/__tests__/__snapshots__/option.strictMode.test.ts.snap b/src/__tests__/__snapshots__/option.strictMode.test.ts.snap index 8bf4938..9c1304e 100644 --- a/src/__tests__/__snapshots__/option.strictMode.test.ts.snap +++ b/src/__tests__/__snapshots__/option.strictMode.test.ts.snap @@ -57,7 +57,7 @@ export interface GQLUser { * In the future, this will be changed by having User as interface * and implementing multiple User */ -export const enum GQLUserRole { +export enum GQLUserRole { /** * System Administrator diff --git a/src/__tests__/__snapshots__/option.typePrefix.test.ts.snap b/src/__tests__/__snapshots__/option.typePrefix.test.ts.snap index 0415d6f..2ba7c99 100644 --- a/src/__tests__/__snapshots__/option.typePrefix.test.ts.snap +++ b/src/__tests__/__snapshots__/option.typePrefix.test.ts.snap @@ -57,7 +57,7 @@ export interface User { * In the future, this will be changed by having User as interface * and implementing multiple User */ -export const enum UserRole { +export enum UserRole { /** * System Administrator @@ -649,7 +649,7 @@ export interface MyCustomPrefixUser { * In the future, this will be changed by having User as interface * and implementing multiple User */ -export const enum MyCustomPrefixUserRole { +export enum MyCustomPrefixUserRole { /** * System Administrator diff --git a/src/__tests__/__snapshots__/schemaAsString.test.ts.snap b/src/__tests__/__snapshots__/schemaAsString.test.ts.snap index 362ae12..cd42efb 100644 --- a/src/__tests__/__snapshots__/schemaAsString.test.ts.snap +++ b/src/__tests__/__snapshots__/schemaAsString.test.ts.snap @@ -57,7 +57,7 @@ export interface GQLUser { * In the future, this will be changed by having User as interface * and implementing multiple User */ -export const enum GQLUserRole { +export enum GQLUserRole { /** * System Administrator diff --git a/src/index.ts b/src/index.ts index b76fdb2..b310278 100644 --- a/src/index.ts +++ b/src/index.ts @@ -36,7 +36,11 @@ const typeResolversDecoration = [ ' *********************************/' ]; -export const generateTSTypesAsString = async (schema: GraphQLSchema | string, options: GenerateTypescriptOptions): Promise => { +export const generateTSTypesAsString = async ( + schema: GraphQLSchema | string, + outputPath: string, + options: GenerateTypescriptOptions +): Promise => { const mergedOptions = { ...defaultOptions, ...options }; let introspectResult: IntrospectionQuery; @@ -62,7 +66,7 @@ export const generateTSTypesAsString = async (schema: GraphQLSchema | string, op introspectResult = await introspectSchema(schema); } - const tsGenerator = new TypeScriptGenerator(mergedOptions, introspectResult); + const tsGenerator = new TypeScriptGenerator(mergedOptions, introspectResult, outputPath); const typeDefs = await tsGenerator.generate(); let typeResolvers: GenerateResolversResult = { @@ -109,6 +113,6 @@ export async function generateTypeScriptTypes( outputPath: string, options: GenerateTypescriptOptions = defaultOptions ) { - const content = await generateTSTypesAsString(schema, options); + const content = await generateTSTypesAsString(schema, outputPath, options); fs.writeFileSync(outputPath, content, 'utf-8'); } \ No newline at end of file diff --git a/src/typescriptGenerator.ts b/src/typescriptGenerator.ts index fa85f8e..8bdf9ca 100644 --- a/src/typescriptGenerator.ts +++ b/src/typescriptGenerator.ts @@ -22,7 +22,8 @@ export class TypeScriptGenerator { constructor( protected options: GenerateTypescriptOptions, - protected introspectResult: IntrospectionQuery + protected introspectResult: IntrospectionQuery, + protected outputPath: string ) { } public async generate(): Promise { @@ -117,8 +118,14 @@ export class TypeScriptGenerator { [] ); + // if code is generated as type declaration, better use export const enum instead + // of just export enum + const isGeneratingDeclaration = this.options.global + || !!this.options.namespace + || this.outputPath.endsWith('.d.ts'); + const enumModifier = isGeneratingDeclaration ? ' const ' : ' '; return [ - `export const enum ${this.options.typePrefix}${enumType.name} {`, + `export${enumModifier}enum ${this.options.typePrefix}${enumType.name} {`, ...enumBody, '}' ]; @@ -128,7 +135,7 @@ export class TypeScriptGenerator { objectType: IntrospectionObjectType | IntrospectionInputObjectType | IntrospectionInterfaceType, allGQLTypes: IntrospectionType[] ): string[] { - let fields: (IntrospectionInputValue | IntrospectionField)[] + const fields: (IntrospectionInputValue | IntrospectionField)[] = objectType.kind === 'INPUT_OBJECT' ? objectType.inputFields : objectType.fields; const extendTypes: string[] = objectType.kind === 'OBJECT' @@ -150,7 +157,7 @@ export class TypeScriptGenerator { return prevTypescriptDefs; } - let fieldJsDoc = descriptionToJSDoc(field); + const fieldJsDoc = descriptionToJSDoc(field); const { fieldName, fieldType } = createFieldRef(field, this.options.typePrefix, this.options.strictNulls); const fieldNameAndType = `${fieldName}: ${fieldType};`; let typescriptDefs = [...fieldJsDoc, fieldNameAndType]; @@ -244,12 +251,12 @@ export class TypeScriptGenerator { * | ... */ private createUnionType(typeName: string, possibleTypes: string[]): string[] { - let result = `export type ${this.options.typePrefix}${typeName} = ${possibleTypes.join(' | ')};`; + const result = `export type ${this.options.typePrefix}${typeName} = ${possibleTypes.join(' | ')};`; if (result.length <= 80) { return [result]; } - let [firstLine, rest] = result.split('='); + const [firstLine, rest] = result.split('='); return [ firstLine + '=', From d00c9cad9ece36104f38749d7b8c253c1769f216 Mon Sep 17 00:00:00 2001 From: jack Date: Mon, 16 Sep 2019 18:58:21 +1000 Subject: [PATCH 6/6] 1.3.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 9e57f28..1bfe6cb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "graphql-schema-typescript", - "version": "1.3.0", + "version": "1.3.1", "description": "Generate TypeScript from GraphQL's schema type definitions", "main": "./lib/index.js", "types": "./lib/index.d.ts",