diff --git a/examples/typescript-node/package.json b/examples/typescript-node/package.json index 81d18815..34db4e0f 100644 --- a/examples/typescript-node/package.json +++ b/examples/typescript-node/package.json @@ -1,6 +1,6 @@ { "name": "typescript-node", - "version": "2.0.0", + "version": "3.0.0", "description": "", "private": true, "main": "index.js", diff --git a/examples/typescript-node/src/zeus/index.ts b/examples/typescript-node/src/zeus/index.ts index 5ba0f668..6834a502 100644 --- a/examples/typescript-node/src/zeus/index.ts +++ b/examples/typescript-node/src/zeus/index.ts @@ -1107,15 +1107,15 @@ export type ModelTypes = { ["Nameable"]: ModelTypes["CardStack"] | ModelTypes["Card"] | ModelTypes["SpecialCard"] | ModelTypes["EffectCard"]; ["SpecialSkills"]:SpecialSkills; ["Query"]: { - cardById?: ModelTypes["Card"] | undefined, + cardById?: ModelTypes["Card"] | undefined | null, /** Draw a card
*/ drawCard: ModelTypes["Card"], drawChangeCard: ModelTypes["ChangeCard"], /** list All Cards availble
*/ listCards: Array, - myStacks?: Array | undefined, + myStacks?: Array | undefined | null, nameables: Array, - public?: ModelTypes["Public"] | undefined + public?: ModelTypes["Public"] | undefined | null }; /** create card inputs
*/ ["createCard"]: { @@ -1124,17 +1124,17 @@ export type ModelTypes = { /** Description of a card
*/ description: string, /**
How many children the greek god had
*/ - Children?: number | undefined, + Children?: number | undefined | null, /** The attack power
*/ Attack: number, /** The defense power
*/ Defense: number, /** input skills */ - skills?: Array | undefined + skills?: Array | undefined | null }; /** Stack of cards */ ["CardStack"]: { - cards?: Array | undefined, + cards?: Array | undefined | null, name: string }; /** Card used in card game
*/ @@ -1142,13 +1142,13 @@ export type ModelTypes = { /** The attack power
*/ Attack: number, /**
How many children the greek god had
*/ - Children?: number | undefined, + Children?: number | undefined | null, /** The defense power
*/ Defense: number, /** Attack other cards on the table , returns Cards after attack
*/ - attack?: Array | undefined, + attack?: Array | undefined | null, /** Put your description here */ - cardImage?: ModelTypes["S3Object"] | undefined, + cardImage?: ModelTypes["S3Object"] | undefined | null, /** Description of a card
*/ description: string, id: string, @@ -1156,7 +1156,7 @@ export type ModelTypes = { info: ModelTypes["JSON"], /** The name of a card
*/ name: string, - skills?: Array | undefined + skills?: Array | undefined | null }; ["SpecialCard"]: { effect: string, @@ -1178,19 +1178,19 @@ export type ModelTypes = { region: string }; ["Public"]: { - powerups?: Array | undefined + powerups?: Array | undefined | null }; ["Powerup"]: { - name?: string | undefined + name?: string | undefined | null }; ["ChangeCard"]:ModelTypes["SpecialCard"] | ModelTypes["EffectCard"]; ["Subscription"]: { - deck?: Array | undefined + deck?: Array | undefined | null }; ["schema"]: { - query?: ModelTypes["Query"] | undefined, - mutation?: ModelTypes["Mutation"] | undefined, - subscription?: ModelTypes["Subscription"] | undefined + query?: ModelTypes["Query"] | undefined | null, + mutation?: ModelTypes["Mutation"] | undefined | null, + subscription?: ModelTypes["Subscription"] | undefined | null } } @@ -1206,15 +1206,15 @@ export type GraphQLTypes = { ["SpecialSkills"]: SpecialSkills; ["Query"]: { __typename: "Query", - cardById?: GraphQLTypes["Card"] | undefined, + cardById?: GraphQLTypes["Card"] | undefined | null, /** Draw a card
*/ drawCard: GraphQLTypes["Card"], drawChangeCard: GraphQLTypes["ChangeCard"], /** list All Cards availble
*/ listCards: Array, - myStacks?: Array | undefined, + myStacks?: Array | undefined | null, nameables: Array, - public?: GraphQLTypes["Public"] | undefined + public?: GraphQLTypes["Public"] | undefined | null }; /** create card inputs
*/ ["createCard"]: { @@ -1223,18 +1223,18 @@ export type GraphQLTypes = { /** Description of a card
*/ description: string, /**
How many children the greek god had
*/ - Children?: number | undefined, + Children?: number | undefined | null, /** The attack power
*/ Attack: number, /** The defense power
*/ Defense: number, /** input skills */ - skills?: Array | undefined + skills?: Array | undefined | null }; /** Stack of cards */ ["CardStack"]: { __typename: "CardStack", - cards?: Array | undefined, + cards?: Array | undefined | null, name: string }; /** Card used in card game
*/ @@ -1243,13 +1243,13 @@ export type GraphQLTypes = { /** The attack power
*/ Attack: number, /**
How many children the greek god had
*/ - Children?: number | undefined, + Children?: number | undefined | null, /** The defense power
*/ Defense: number, /** Attack other cards on the table , returns Cards after attack
*/ - attack?: Array | undefined, + attack?: Array | undefined | null, /** Put your description here */ - cardImage?: GraphQLTypes["S3Object"] | undefined, + cardImage?: GraphQLTypes["S3Object"] | undefined | null, /** Description of a card
*/ description: string, id: string, @@ -1257,7 +1257,7 @@ export type GraphQLTypes = { info: GraphQLTypes["JSON"], /** The name of a card
*/ name: string, - skills?: Array | undefined + skills?: Array | undefined | null }; ["SpecialCard"]: { __typename: "SpecialCard", @@ -1284,11 +1284,11 @@ export type GraphQLTypes = { }; ["Public"]: { __typename: "Public", - powerups?: Array | undefined + powerups?: Array | undefined | null }; ["Powerup"]: { __typename: "Powerup", - name?: string | undefined + name?: string | undefined | null }; ["ChangeCard"]:{ __typename:"SpecialCard" | "EffectCard" @@ -1297,10 +1297,10 @@ export type GraphQLTypes = { }; ["Subscription"]: { __typename: "Subscription", - deck?: Array | undefined + deck?: Array | undefined | null } } -export const enum SpecialSkills { +export enum SpecialSkills { THUNDER = "THUNDER", RAIN = "RAIN", FIRE = "FIRE" diff --git a/packages/graphql-zeus-core/TranslateGraphQL/index.ts b/packages/graphql-zeus-core/TranslateGraphQL/index.ts index 19240ea2..59bd0816 100644 --- a/packages/graphql-zeus-core/TranslateGraphQL/index.ts +++ b/packages/graphql-zeus-core/TranslateGraphQL/index.ts @@ -8,12 +8,13 @@ export interface TranslateOptions { host?: string; esModule?: boolean; subscriptions?: 'legacy' | 'graphql-ws'; + constEnums?: boolean; } export class TranslateGraphQL { - static typescript = ({ schema, env = 'browser', host, subscriptions = 'legacy' }: TranslateOptions) => { + static typescript = ({ schema, env = 'browser', host, subscriptions = 'legacy', constEnums }: TranslateOptions) => { const tree = Parser.parseAddExtensions(schema); - const ts = TreeToTS.resolveTree({ tree, env, host, subscriptions }); + const ts = TreeToTS.resolveTree({ tree, env, host, subscriptions, constEnums }); return ts; }; @@ -23,9 +24,10 @@ export class TranslateGraphQL { host, esModule, subscriptions = 'legacy', + constEnums, }: TranslateOptions) => { const tree = Parser.parseAddExtensions(schema); - const ts = TreeToTS.resolveTreeSplit({ tree, env, host, esModule, subscriptions }); + const ts = TreeToTS.resolveTreeSplit({ tree, env, host, esModule, subscriptions, constEnums }); return { const: TreeToTS.resolveBasisHeader().concat(ts.const), index: TreeToTS.resolveBasisHeader().concat(ts.indexImports).concat('\n').concat(ts.index), diff --git a/packages/graphql-zeus-core/TreeToTS/index.ts b/packages/graphql-zeus-core/TreeToTS/index.ts index 663cd0ed..99ae68ef 100644 --- a/packages/graphql-zeus-core/TreeToTS/index.ts +++ b/packages/graphql-zeus-core/TreeToTS/index.ts @@ -36,6 +36,7 @@ export interface ResolveOptions { headers?: Record; esModule?: boolean; subscriptions?: 'legacy' | 'graphql-ws'; + constEnums?: boolean; } const disableLintersComments = ['eslint-disable']; @@ -67,8 +68,8 @@ export class TreeToTS { return propTypes.concat('\n\n').concat(returnTypes).concat('\n\n').concat(opsString); } - static resolveBasisTypes(tree: ParserTree): string { - const rootTypes = resolveTypes(tree.nodes); + static resolveBasisTypes(tree: ParserTree, options?: { constEnums?: boolean }): string { + const rootTypes = resolveTypes(tree.nodes, options); const valueTypes = resolveValueTypes(tree.nodes); const inputTypes = resolveInputTypes(tree.nodes); const modelTypes = resolveModelTypes(tree.nodes); @@ -103,6 +104,7 @@ export class TreeToTS { esModule, headers, subscriptions = 'legacy', + constEnums, }: ResolveOptions) { return { indexImports: `import { AllTypesProps, ReturnTypes, Ops } from './const${ @@ -124,7 +126,11 @@ import WebSocket from 'ws';` .concat('\n') .concat(typescriptFunctions) .concat('\n') - .concat(TreeToTS.resolveBasisTypes(tree)), + .concat( + TreeToTS.resolveBasisTypes(tree, { + constEnums, + }), + ), }; } diff --git a/packages/graphql-zeus-core/TreeToTS/templates/returnedTypes/enum.spec.ts b/packages/graphql-zeus-core/TreeToTS/templates/returnedTypes/enum.spec.ts index 285bd0be..f5f6fc23 100644 --- a/packages/graphql-zeus-core/TreeToTS/templates/returnedTypes/enum.spec.ts +++ b/packages/graphql-zeus-core/TreeToTS/templates/returnedTypes/enum.spec.ts @@ -1,57 +1,62 @@ import { resolveEnum } from '@/TreeToTS/templates/returnedTypes/enum'; import { createParserField, Options, TypeDefinition, ValueDefinition } from 'graphql-js-tree'; -describe('It creates correct TypeScript const enums', () => { - test('Simple enum with 2 fields', () => { - const enumString = resolveEnum( - createParserField({ - args: [ - createParserField({ - type: { - fieldType: { - name: ValueDefinition.EnumValueDefinition, - type: Options.name, - }, - }, - args: [], - directives: [], - interfaces: [], - name: 'CREATED', - data: { - type: ValueDefinition.EnumValueDefinition, - }, - }), - createParserField({ - type: { - fieldType: { - name: ValueDefinition.EnumValueDefinition, - type: Options.name, - }, - }, - args: [], - directives: [], - interfaces: [], - name: 'DELETED', - data: { - type: ValueDefinition.EnumValueDefinition, - }, - }), - ], - data: { - type: TypeDefinition.EnumTypeDefinition, +const mockEnum = createParserField({ + args: [ + createParserField({ + type: { + fieldType: { + name: ValueDefinition.EnumValueDefinition, + type: Options.name, }, - directives: [], - interfaces: [], - name: 'Status', - type: { - fieldType: { - name: 'enum', - type: Options.name, - }, + }, + args: [], + directives: [], + interfaces: [], + name: 'CREATED', + data: { + type: ValueDefinition.EnumValueDefinition, + }, + }), + createParserField({ + type: { + fieldType: { + name: ValueDefinition.EnumValueDefinition, + type: Options.name, }, - }), - ); - expect(enumString).toEqual(`export const enum Status { + }, + args: [], + directives: [], + interfaces: [], + name: 'DELETED', + data: { + type: ValueDefinition.EnumValueDefinition, + }, + }), + ], + data: { + type: TypeDefinition.EnumTypeDefinition, + }, + directives: [], + interfaces: [], + name: 'Status', + type: { + fieldType: { + name: 'enum', + type: Options.name, + }, + }, +}); + +describe('It creates correct TypeScript const enums', () => { + test('Simple enum with 2 fields', () => { + const enumString = resolveEnum(mockEnum); + const enumConstString = resolveEnum(mockEnum, true); + expect(enumString).toEqual(`export enum Status { +\tCREATED = "CREATED", +\tDELETED = "DELETED" +}`); + expect(enumConstString).toEqual(`export const enum Status { \tCREATED = "CREATED", \tDELETED = "DELETED" }`); diff --git a/packages/graphql-zeus-core/TreeToTS/templates/returnedTypes/enum.ts b/packages/graphql-zeus-core/TreeToTS/templates/returnedTypes/enum.ts index cfe17ed9..48762bc6 100644 --- a/packages/graphql-zeus-core/TreeToTS/templates/returnedTypes/enum.ts +++ b/packages/graphql-zeus-core/TreeToTS/templates/returnedTypes/enum.ts @@ -1,11 +1,11 @@ import { plusDescription } from '@/TreeToTS/templates/shared/description'; import { ParserField } from 'graphql-js-tree'; -export const resolveEnum = (i: ParserField): string => { +export const resolveEnum = (i: ParserField, constEnum?: boolean): string => { if (!i.args) { throw new Error('Empty enum error'); } - return `${plusDescription(i.description)}export const enum ${i.name} {\n${i.args + return `${plusDescription(i.description)}export ${constEnum ? 'const ' : ''}enum ${i.name} {\n${i.args .map((f) => `\t${f.name} = "${f.name}"`) .join(',\n')}\n}`; }; diff --git a/packages/graphql-zeus-core/TreeToTS/templates/returnedTypes/index.ts b/packages/graphql-zeus-core/TreeToTS/templates/returnedTypes/index.ts index 99a5219f..a5301e27 100644 --- a/packages/graphql-zeus-core/TreeToTS/templates/returnedTypes/index.ts +++ b/packages/graphql-zeus-core/TreeToTS/templates/returnedTypes/index.ts @@ -42,7 +42,7 @@ export const resolveTypeFromRoot = (i: ParserField, rootNodes: ParserField[]): s return `${plusDescription(i.description)}${resolveType(i, rootNodes)}`; }; -export const resolveTypes = (rootNodes: ParserField[]): string => { +export const resolveTypes = (rootNodes: ParserField[], options?: { constEnums?: boolean }): string => { return `export type ${TYPES} = { ${rootNodes .map((f) => resolveTypeFromRoot(f, rootNodes)) @@ -53,7 +53,7 @@ export const resolveTypes = (rootNodes: ParserField[]): string => { .concat( rootNodes .filter((rn) => rn.data.type === TypeDefinition.EnumTypeDefinition) - .map(resolveEnum) + .map((f) => resolveEnum(f, options?.constEnums)) .join('\n'), ); }; diff --git a/packages/graphql-zeus-core/TreeToTS/templates/shared/field.spec.ts b/packages/graphql-zeus-core/TreeToTS/templates/shared/field.spec.ts index 8e706ab8..8e886b34 100644 --- a/packages/graphql-zeus-core/TreeToTS/templates/shared/field.spec.ts +++ b/packages/graphql-zeus-core/TreeToTS/templates/shared/field.spec.ts @@ -17,7 +17,7 @@ describe('Test type field generation', () => { type: Options.name, name: 'Person', }); - expect(resolvedString).toEqual(`Person | undefined`); + expect(resolvedString).toEqual(`Person | undefined | null`); }); test('Optional Array Optional Field generation', () => { const resolvedString = resolveFieldType('Person', { @@ -27,7 +27,7 @@ describe('Test type field generation', () => { name: 'Person', }, }); - expect(resolvedString).toEqual(`Array | undefined`); + expect(resolvedString).toEqual(`Array | undefined | null`); }); test('Required Array Optional Field generation', () => { const resolvedString = resolveFieldType('Person', { @@ -40,7 +40,7 @@ describe('Test type field generation', () => { }, }, }); - expect(resolvedString).toEqual(`Array`); + expect(resolvedString).toEqual(`Array`); }); test('Required Array Required Field generation', () => { const resolvedString = resolveFieldType('Person', { diff --git a/packages/graphql-zeus-core/TreeToTS/templates/shared/field.ts b/packages/graphql-zeus-core/TreeToTS/templates/shared/field.ts index f473b696..0537d9e0 100644 --- a/packages/graphql-zeus-core/TreeToTS/templates/shared/field.ts +++ b/packages/graphql-zeus-core/TreeToTS/templates/shared/field.ts @@ -10,13 +10,13 @@ export const resolveFieldType = ( isRequired = false, ): string => { if (fType.type === Options.name) { - return fn(isRequired ? name : `${name} | undefined`); + return fn(isRequired ? name : `${name} | undefined | null`); } if (fType.type === Options.array) { return resolveFieldType( name, fType.nest, - isRequired ? (x) => `Array<${fn(x)}>` : (x) => `Array<${fn(x)}> | undefined`, + isRequired ? (x) => `Array<${fn(x)}>` : (x) => `Array<${fn(x)}> | undefined | null`, false, ); } diff --git a/packages/graphql-zeus-core/package.json b/packages/graphql-zeus-core/package.json index 4442bc9e..178cdbfc 100644 --- a/packages/graphql-zeus-core/package.json +++ b/packages/graphql-zeus-core/package.json @@ -1,6 +1,6 @@ { "name": "graphql-zeus-core", - "version": "6.0.0", + "version": "7.0.0", "private": false, "main": "./lib/index.js", "author": "GraphQL Editor, Artur Czemiel", diff --git a/packages/graphql-zeus-jsonschema/package.json b/packages/graphql-zeus-jsonschema/package.json index 9ca13451..3f760c1f 100644 --- a/packages/graphql-zeus-jsonschema/package.json +++ b/packages/graphql-zeus-jsonschema/package.json @@ -1,6 +1,6 @@ { "name": "graphql-zeus-jsonschema", - "version": "6.0.0", + "version": "7.0.0", "private": false, "main": "./lib/index.js", "author": "GraphQL Editor, Artur Czemiel", diff --git a/packages/graphql-zeus/CLIClass.ts b/packages/graphql-zeus/CLIClass.ts index 772780e7..4da2bbb4 100644 --- a/packages/graphql-zeus/CLIClass.ts +++ b/packages/graphql-zeus/CLIClass.ts @@ -25,6 +25,7 @@ interface CliArgs extends Yargs { graphql?: string; jsonSchema?: string; apollo?: boolean; + constEnums?: boolean; reactQuery?: boolean; typedDocumentNode?: boolean; subscriptions?: string; @@ -80,6 +81,7 @@ export class CLI { env, host, esModule: !!args.esModule, + constEnums: !!args.constEnums, subscriptions: args.subscriptions === 'graphql-ws' ? 'graphql-ws' : 'legacy', }); Object.keys(typeScriptDefinition).forEach((k) => diff --git a/packages/graphql-zeus/package.json b/packages/graphql-zeus/package.json index f86f70df..0c8c3d3d 100644 --- a/packages/graphql-zeus/package.json +++ b/packages/graphql-zeus/package.json @@ -1,6 +1,6 @@ { "name": "graphql-zeus", - "version": "6.0.0", + "version": "7.0.0", "private": false, "scripts": { "start": "ttsc --watch",