diff --git a/src/__tests__/__testSchema__/mutation.auth/index.ts b/src/__tests__/__testSchema__/mutation.auth/index.ts index d0b9a07..6e0c5cd 100644 --- a/src/__tests__/__testSchema__/mutation.auth/index.ts +++ b/src/__tests__/__testSchema__/mutation.auth/index.ts @@ -1,3 +1,5 @@ +import { NamespaceConfig } from '../../../typeDefs'; + export default { resolve: () => ({}), -}; +} as NamespaceConfig; diff --git a/src/__tests__/__testSchema__/mutation.auth/login.ts b/src/__tests__/__testSchema__/mutation.auth/login.ts index 31f9db6..32f985d 100644 --- a/src/__tests__/__testSchema__/mutation.auth/login.ts +++ b/src/__tests__/__testSchema__/mutation.auth/login.ts @@ -1,6 +1,8 @@ +import { FieldConfig } from '../../../typeDefs'; + export default { type: 'Boolean', description: 'Login operation', args: { email: 'String', password: 'String' }, resolve: () => true, -}; +} as FieldConfig; diff --git a/src/__tests__/__testSchema__/mutation.auth/logout.ts b/src/__tests__/__testSchema__/mutation.auth/logout.ts index 598abfa..9b99175 100644 --- a/src/__tests__/__testSchema__/mutation.auth/logout.ts +++ b/src/__tests__/__testSchema__/mutation.auth/logout.ts @@ -1,4 +1,6 @@ +import { FieldConfig } from '../../../typeDefs'; + export default { type: 'Boolean', resolve: () => true, -}; +} as FieldConfig; diff --git a/src/__tests__/__testSchema__/mutation.auth/nested/method.ts b/src/__tests__/__testSchema__/mutation.auth/nested/method.ts index 598abfa..edd2a78 100644 --- a/src/__tests__/__testSchema__/mutation.auth/nested/method.ts +++ b/src/__tests__/__testSchema__/mutation.auth/nested/method.ts @@ -1,4 +1,6 @@ +import { FieldConfig } from '../../../../typeDefs'; + export default { type: 'Boolean', resolve: () => true, -}; +} as FieldConfig; diff --git a/src/__tests__/__testSchema__/mutation.user/create.ts b/src/__tests__/__testSchema__/mutation.user/create.ts index 598abfa..9b99175 100644 --- a/src/__tests__/__testSchema__/mutation.user/create.ts +++ b/src/__tests__/__testSchema__/mutation.user/create.ts @@ -1,4 +1,6 @@ +import { FieldConfig } from '../../../typeDefs'; + export default { type: 'Boolean', resolve: () => true, -}; +} as FieldConfig; diff --git a/src/__tests__/__testSchema__/mutation.user/update.ts b/src/__tests__/__testSchema__/mutation.user/update.ts index 598abfa..9b99175 100644 --- a/src/__tests__/__testSchema__/mutation.user/update.ts +++ b/src/__tests__/__testSchema__/mutation.user/update.ts @@ -1,4 +1,6 @@ +import { FieldConfig } from '../../../typeDefs'; + export default { type: 'Boolean', resolve: () => true, -}; +} as FieldConfig; diff --git a/src/__tests__/__testSchema__/mutation/logs.nested/list.ts b/src/__tests__/__testSchema__/mutation/logs.nested/list.ts index 598abfa..edd2a78 100644 --- a/src/__tests__/__testSchema__/mutation/logs.nested/list.ts +++ b/src/__tests__/__testSchema__/mutation/logs.nested/list.ts @@ -1,4 +1,6 @@ +import { FieldConfig } from '../../../../typeDefs'; + export default { type: 'Boolean', resolve: () => true, -}; +} as FieldConfig; diff --git a/src/__tests__/__testSchema__/query.auth/index.ts b/src/__tests__/__testSchema__/query.auth/index.ts index d01e64a..3a81907 100644 --- a/src/__tests__/__testSchema__/query.auth/index.ts +++ b/src/__tests__/__testSchema__/query.auth/index.ts @@ -1,3 +1,5 @@ +import { NamespaceConfig } from '../../../typeDefs'; + export default { type: 'NamespaceCustomTypeName', -}; +} as NamespaceConfig; diff --git a/src/__tests__/__testSchema__/query.auth/isLoggedIn.ts b/src/__tests__/__testSchema__/query.auth/isLoggedIn.ts index ed52f3d..87df801 100644 --- a/src/__tests__/__testSchema__/query.auth/isLoggedIn.ts +++ b/src/__tests__/__testSchema__/query.auth/isLoggedIn.ts @@ -1,4 +1,6 @@ +import { FieldConfig } from '../../../typeDefs'; + export default { type: (sc) => sc.get('Boolean'), resolve: () => true, -}; +} as FieldConfig; diff --git a/src/__tests__/__testSchema__/query.auth/nested/method.ts b/src/__tests__/__testSchema__/query.auth/nested/method.ts index 598abfa..edd2a78 100644 --- a/src/__tests__/__testSchema__/query.auth/nested/method.ts +++ b/src/__tests__/__testSchema__/query.auth/nested/method.ts @@ -1,4 +1,6 @@ +import { FieldConfig } from '../../../../typeDefs'; + export default { type: 'Boolean', resolve: () => true, -}; +} as FieldConfig; diff --git a/src/__tests__/__testSchema__/query/__skip/field.ts b/src/__tests__/__testSchema__/query/__skip/field.ts index 7218203..3120700 100644 --- a/src/__tests__/__testSchema__/query/__skip/field.ts +++ b/src/__tests__/__testSchema__/query/__skip/field.ts @@ -1,4 +1,6 @@ +import { FieldConfig } from '../../../../typeDefs'; + export default { type: 'String', resolve: () => 'text', -}; +} as FieldConfig; diff --git a/src/__tests__/__testSchema__/query/field.spec.ts b/src/__tests__/__testSchema__/query/field.spec.ts index 1bdfc66..7b6a5e3 100644 --- a/src/__tests__/__testSchema__/query/field.spec.ts +++ b/src/__tests__/__testSchema__/query/field.spec.ts @@ -1,5 +1,7 @@ +import { FieldConfig } from '../../../typeDefs'; + export default { type: 'String', description: 'This file should be skipped', resolve: () => 'ok', -}; +} as FieldConfig; diff --git a/src/__tests__/__testSchema__/query/field.ts b/src/__tests__/__testSchema__/query/field.ts index 5c618a2..427c8b8 100644 --- a/src/__tests__/__testSchema__/query/field.ts +++ b/src/__tests__/__testSchema__/query/field.ts @@ -1,4 +1,6 @@ +import { FieldConfig } from '../../../typeDefs'; + export default { type: 'String', resolve: () => 'ok', -}; +} as FieldConfig; diff --git a/src/__tests__/__testSchema__/query/index.ts b/src/__tests__/__testSchema__/query/index.ts index d0b9a07..6e0c5cd 100644 --- a/src/__tests__/__testSchema__/query/index.ts +++ b/src/__tests__/__testSchema__/query/index.ts @@ -1,3 +1,5 @@ +import { NamespaceConfig } from '../../../typeDefs'; + export default { resolve: () => ({}), -}; +} as NamespaceConfig; diff --git a/src/__tests__/__testSchema__/query/me/address.city.ts b/src/__tests__/__testSchema__/query/me/address.city.ts index 598abfa..edd2a78 100644 --- a/src/__tests__/__testSchema__/query/me/address.city.ts +++ b/src/__tests__/__testSchema__/query/me/address.city.ts @@ -1,4 +1,6 @@ +import { FieldConfig } from '../../../../typeDefs'; + export default { type: 'Boolean', resolve: () => true, -}; +} as FieldConfig; diff --git a/src/__tests__/__testSchema__/query/me/address.street.ts b/src/__tests__/__testSchema__/query/me/address.street.ts index 598abfa..edd2a78 100644 --- a/src/__tests__/__testSchema__/query/me/address.street.ts +++ b/src/__tests__/__testSchema__/query/me/address.street.ts @@ -1,4 +1,6 @@ +import { FieldConfig } from '../../../../typeDefs'; + export default { type: 'Boolean', resolve: () => true, -}; +} as FieldConfig; diff --git a/src/__tests__/__testSchema__/query/me/index.ts b/src/__tests__/__testSchema__/query/me/index.ts index a8c993b..97a3bc2 100644 --- a/src/__tests__/__testSchema__/query/me/index.ts +++ b/src/__tests__/__testSchema__/query/me/index.ts @@ -1,9 +1,11 @@ +import { NamespaceConfig } from '../../../../typeDefs'; + export default { args: { arg: 'Int', }, - resolve: (_: any, __: any, context: any) => { + resolve: (_, __, context) => { if (!context?.isAdmin) throw new Error('You should be the ADMIN'); return {}; }, -}; +} as NamespaceConfig; diff --git a/src/__tests__/__testSchema__/query/me/name.ts b/src/__tests__/__testSchema__/query/me/name.ts index 0a2421f..199b483 100644 --- a/src/__tests__/__testSchema__/query/me/name.ts +++ b/src/__tests__/__testSchema__/query/me/name.ts @@ -1,4 +1,6 @@ +import { FieldConfig } from '../../../../typeDefs'; + export default { type: 'String', resolve: () => 'nodkz', -}; +} as FieldConfig; diff --git a/src/__tests__/__testSchema__/query/some.index.ts b/src/__tests__/__testSchema__/query/some.index.ts index 8ced91d..df6b980 100644 --- a/src/__tests__/__testSchema__/query/some.index.ts +++ b/src/__tests__/__testSchema__/query/some.index.ts @@ -1,3 +1,5 @@ +import { FieldConfig } from '../../../typeDefs'; + export default { type: ` type SomeIndexFileType { @@ -5,4 +7,4 @@ export default { } `, resolve: () => ({ awesomeValue: 'awesomeValue' }), -}; +} as FieldConfig; diff --git a/src/__tests__/__testSchema__/query/some.nested.ts b/src/__tests__/__testSchema__/query/some.nested.ts index 95140ad..a2b44ba 100644 --- a/src/__tests__/__testSchema__/query/some.nested.ts +++ b/src/__tests__/__testSchema__/query/some.nested.ts @@ -1,4 +1,6 @@ +import { FieldConfig } from '../../../typeDefs'; + export default { type: 'Int', resolve: () => 123, -}; +} as FieldConfig; diff --git a/src/__tests__/__testSchema__/query/user/extendedData.ts b/src/__tests__/__testSchema__/query/user/extendedData.ts index d4064ae..d663bb3 100644 --- a/src/__tests__/__testSchema__/query/user/extendedData.ts +++ b/src/__tests__/__testSchema__/query/user/extendedData.ts @@ -1,3 +1,5 @@ +import { FieldConfig } from '../../../../typeDefs'; + export default { type: ` type UserExtendedData { @@ -5,4 +7,4 @@ export default { } `, resolve: () => ({ starsCount: 10 }), -}; +} as FieldConfig; diff --git a/src/__tests__/__testSchema__/query/user/index.ts b/src/__tests__/__testSchema__/query/user/index.ts index a93b517..282a40e 100644 --- a/src/__tests__/__testSchema__/query/user/index.ts +++ b/src/__tests__/__testSchema__/query/user/index.ts @@ -1,3 +1,5 @@ +import { NamespaceConfig } from '../../../../typeDefs'; + export default { type: ` type UserAwesomeType { @@ -12,4 +14,4 @@ export default { lastName: 'User', }; }, -}; +} as NamespaceConfig; diff --git a/src/__tests__/__testSchema__/query/user/roles.ts b/src/__tests__/__testSchema__/query/user/roles.ts index 1753d30..9863766 100644 --- a/src/__tests__/__testSchema__/query/user/roles.ts +++ b/src/__tests__/__testSchema__/query/user/roles.ts @@ -1,4 +1,6 @@ +import { FieldConfig } from '../../../../typeDefs'; + export default { type: ['String'], resolve: () => ['ADMIN', 'USER'], -}; +} as FieldConfig; diff --git a/src/__tests__/astVisitor-test.ts b/src/__tests__/astVisitor-test.ts index 6673716..43f144e 100644 --- a/src/__tests__/astVisitor-test.ts +++ b/src/__tests__/astVisitor-test.ts @@ -177,10 +177,10 @@ describe('astVisitor', () => { } }, FILE: (node) => { - const currentResolve = node.code.default.resolve; + const currentResolve = node.code.default?.resolve; if (currentResolve) { - const description = node.code.default.description; - node.code.default.resolve = (s: any, a: any, c: any, i: any) => { + const description = node.code.default?.description; + (node.code as any).default.resolve = (s: any, a: any, c: any, i: any) => { logs.push({ description, args: a, diff --git a/src/astToSchema.ts b/src/astToSchema.ts index 01d2c06..2ae9f29 100644 --- a/src/astToSchema.ts +++ b/src/astToSchema.ts @@ -8,10 +8,12 @@ import { isComposeOutputType, isSomeOutputTypeDefinitionString, inspect, + isFunction, } from 'graphql-compose'; import { AstRootNode, AstRootTypeNode, AstDirNode, AstFileNode } from './directoryToAst'; import dedent from 'dedent'; import { GraphQLObjectType } from 'graphql'; +import { FieldConfig, NamespaceConfig } from './typeDefs'; export interface AstToSchemaOptions { schemaComposer?: SchemaComposer; @@ -29,7 +31,7 @@ export function astToSchema( if (!opts.schemaComposer) { throw new Error(dedent` Provided option 'schemaComposer' should be an instance of SchemaComposer class from 'graphql-compose' package. - Recieved: + Received: ${inspect(opts.schemaComposer)} `); } @@ -77,7 +79,7 @@ export function createFields( if (ast.kind === 'file') { parent.addNestedFields({ - [name]: prepareFieldConfig(sc, ast), + [name]: prepareFieldConfig(sc, ast) as FieldConfig, }); return; } @@ -190,8 +192,8 @@ function prepareNamespaceFieldConfig( function prepareFieldConfig( sc: SchemaComposer, ast: AstFileNode -): ObjectTypeComposerFieldConfig { - const fc = ast.code.default as any; +): FieldConfig | NamespaceConfig { + const fc = ast.code.default; if (!fc) { throw new Error(dedent` diff --git a/src/astVisitor.ts b/src/astVisitor.ts index 714be71..671b605 100644 --- a/src/astVisitor.ts +++ b/src/astVisitor.ts @@ -57,7 +57,7 @@ export function visitNode( node: AstDirNode | AstFileNode | AstRootTypeNode, visitor: AstVisitor, info: VisitInfo -) { +): void { let result: VisitorEmptyResult | AstDirNode | AstFileNode | AstRootTypeNode; if (node.kind === 'dir') { if (visitor.DIR) result = visitor.DIR(node, info); diff --git a/src/directoryToAst.ts b/src/directoryToAst.ts index ab23425..11c4070 100644 --- a/src/directoryToAst.ts +++ b/src/directoryToAst.ts @@ -1,5 +1,6 @@ import fs from 'fs'; import { join, resolve, dirname, basename } from 'path'; +import { FieldConfig, NamespaceConfig } from './typeDefs'; export interface DirectoryToAstOptions { relativePath?: string; @@ -35,7 +36,7 @@ export interface AstDirNode extends AstBaseNode { export interface AstFileNode extends AstBaseNode { kind: 'file'; code: { - default?: any; + default?: FieldConfig | NamespaceConfig; }; } diff --git a/src/index.ts b/src/index.ts index fb6e1d3..0a16acc 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,13 +1,18 @@ import { directoryToAst, DirectoryToAstOptions } from './directoryToAst'; import { astToSchema, AstToSchemaOptions } from './astToSchema'; +import { SchemaComposer } from 'graphql-compose'; +import { GraphQLSchema } from 'graphql'; export interface BuildOptions extends DirectoryToAstOptions, AstToSchemaOptions {} -export function buildSchema(module: NodeModule, opts: BuildOptions = {}) { +export function buildSchema(module: NodeModule, opts: BuildOptions = {}): GraphQLSchema { return loadSchemaComposer(module, opts).buildSchema(); } -export function loadSchemaComposer(module: NodeModule, opts: BuildOptions) { +export function loadSchemaComposer( + module: NodeModule, + opts: BuildOptions +): SchemaComposer { const ast = directoryToAst(module, opts); const sc = astToSchema(ast, opts); return sc; @@ -25,6 +30,7 @@ export { } from './directoryToAst'; export { astToSchema, AstToSchemaOptions } from './astToSchema'; export * from './testHelpers'; +export * from './typeDefs'; export { astVisitor, diff --git a/src/testHelpers.ts b/src/testHelpers.ts index 48d8d1e..edf17f3 100644 --- a/src/testHelpers.ts +++ b/src/testHelpers.ts @@ -128,7 +128,7 @@ export function testSDL(opts: { fc: ObjectTypeComposerFieldConfigAsObjectDefinition | Resolver; schemaComposer?: SchemaComposer; deep?: boolean; -}) { +}): string { const sc = opts.schemaComposer || new SchemaComposer(); sc.Query.setField(FIELD, opts.fc); sc.buildSchema(); diff --git a/src/typeDefs.ts b/src/typeDefs.ts new file mode 100644 index 0000000..4d969ab --- /dev/null +++ b/src/typeDefs.ts @@ -0,0 +1,8 @@ +import { ObjectTypeComposerFieldConfigAsObjectDefinition } from 'graphql-compose'; + +export type FieldConfig = + ObjectTypeComposerFieldConfigAsObjectDefinition; + +export type NamespaceConfig = Partial< + ObjectTypeComposerFieldConfigAsObjectDefinition +>;