From b0b6edcd636aa6f7958c84e36456e2d81cc97422 Mon Sep 17 00:00:00 2001 From: Lenz Weber Date: Sun, 30 May 2021 14:48:47 +0200 Subject: [PATCH 1/3] expose grapql schema via `factory.toSchema` --- src/factory.ts | 13 +++++++++++-- src/glossary.ts | 15 +++++++++++---- src/model/generateGraphQLHandlers.ts | 22 ++++++++++++++++++---- 3 files changed, 40 insertions(+), 10 deletions(-) diff --git a/src/factory.ts b/src/factory.ts index 360482bb..bb145d38 100644 --- a/src/factory.ts +++ b/src/factory.ts @@ -15,7 +15,10 @@ import { updateEntity } from './model/updateEntity' import { OperationError, OperationErrorType } from './errors/OperationError' import { Database } from './db/Database' import { generateRestHandlers } from './model/generateRestHandlers' -import { generateGraphQLHandlers } from './model/generateGraphQLHandlers' +import { + generateGraphQLHandlers, + generateGraphQLSchema, +} from './model/generateGraphQLHandlers' import { sync } from './extensions/sync' import { removeInternalProperties } from './utils/removeInternalProperties' @@ -256,13 +259,19 @@ function createModelApi< return records.map(removeInternalProperties) }, - toHandlers(type, baseUrl): any { + toHandlers(type: 'rest' | 'graphql', baseUrl: string): any { if (type === 'graphql') { return generateGraphQLHandlers(modelName, definition, api, baseUrl) } return generateRestHandlers(modelName, definition, api, baseUrl) }, + toSchema(type: 'graphql') { + if (type === 'graphql') { + return generateGraphQLSchema(modelName, definition, api) + } + throw new Error('This Schema type is not supported at the moment') + }, } return api diff --git a/src/glossary.ts b/src/glossary.ts index e1a8f993..ee7f9996 100644 --- a/src/glossary.ts +++ b/src/glossary.ts @@ -1,3 +1,4 @@ +import { GraphQLSchema } from 'graphql' import { GraphQLHandler, RestHandler } from 'msw' import { BulkQueryOptions, @@ -174,10 +175,16 @@ export interface ModelAPI< /** * Generate request handlers of the given type based on the model. */ - toHandlers( - type: HandlerType, - baseUrl?: string, - ): HandlerType extends 'rest' ? RestHandler[] : GraphQLHandler[] + toHandlers(type: 'rest', baseUrl?: string): RestHandler[] + /** + * Generate request handlers of the given type based on the model. + */ + toHandlers(type: 'graphql', baseUrl?: string): GraphQLHandler[] + + /** + * Generate a schema of the given type based on the model. + */ + toSchema(type: 'graphql'): GraphQLSchema } export type UpdateManyValue< diff --git a/src/model/generateGraphQLHandlers.ts b/src/model/generateGraphQLHandlers.ts index edc89a11..b5a3b490 100644 --- a/src/model/generateGraphQLHandlers.ts +++ b/src/model/generateGraphQLHandlers.ts @@ -132,16 +132,14 @@ export function definitionToFields( ) } -export function generateGraphQLHandlers< +export function generateGraphQLSchema< Dictionary extends ModelDictionary, ModelName extends string >( modelName: ModelName, definition: ModelDefinition, model: ModelAPI, - baseUrl: string = '', -): GraphQLHandler[] { - const target = baseUrl ? graphql.link(baseUrl) : graphql +): GraphQLSchema { const pluralModelName = pluralize(modelName) const capitalModelName = capitalize(modelName) const { fields, inputFields, queryInputFields } = definitionToFields( @@ -268,6 +266,22 @@ export function generateGraphQLHandlers< }), }) + return objectSchema +} + +export function generateGraphQLHandlers< + Dictionary extends ModelDictionary, + ModelName extends string +>( + modelName: ModelName, + definition: ModelDefinition, + model: ModelAPI, + baseUrl: string = '', +): GraphQLHandler[] { + const target = baseUrl ? graphql.link(baseUrl) : graphql + + const objectSchema = generateGraphQLSchema(modelName, definition, model) + return [ target.operation(async (req, res, ctx) => { if (!req.body) { From acc84daacf80e28e4c062f0211d3350e094b266c Mon Sep 17 00:00:00 2001 From: Lenz Weber Date: Tue, 8 Jun 2021 23:40:05 +0200 Subject: [PATCH 2/3] add test --- test/model/toGraphQLSchema.test.ts | 77 ++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 test/model/toGraphQLSchema.test.ts diff --git a/test/model/toGraphQLSchema.test.ts b/test/model/toGraphQLSchema.test.ts new file mode 100644 index 00000000..e9a077ea --- /dev/null +++ b/test/model/toGraphQLSchema.test.ts @@ -0,0 +1,77 @@ +import { datatype } from 'faker' +import { factory, primaryKey } from '@mswjs/data' +import { printSchema } from 'graphql' + +const db = factory({ + user: { + id: primaryKey(datatype.uuid), + firstName: String, + age: Number, + }, +}) + +test('generates a graphql schema', () => { + const schema = db.user.toSchema('graphql') + expect(printSchema(schema)).toMatchInlineSnapshot(` + "type Query { + user(where: UserQueryInput): User + users(take: Int, skip: Int, cursor: ID, where: UserQueryInput): [User] + } + + type User { + id: ID + firstName: String + age: Int + } + + input UserQueryInput { + id: IdQueryType + firstName: StringQueryType + age: IntQueryType + } + + input IdQueryType { + equals: ID + notEquals: ID + contains: ID + notContains: ID + in: ID + notIn: ID + } + + input StringQueryType { + equals: String + notEquals: String + contains: String + notContains: String + in: String + notIn: String + } + + input IntQueryType { + equals: Int + notEquals: Int + between: Int + notBetween: Int + gt: Int + gte: Int + lt: Int + lte: Int + } + + type Mutation { + createUser(data: UserInput): User + updateUser(where: UserQueryInput, data: UserInput): User + updateUsers(where: UserQueryInput, data: UserInput): [User] + deleteUser(where: UserQueryInput): User + deleteUsers(where: UserQueryInput): [User] + } + + input UserInput { + id: ID + firstName: String + age: Int + } + " + `) +}) From 625d5cda43463726c99546ef59bf20518a7a3cef Mon Sep 17 00:00:00 2001 From: Lenz Weber Date: Wed, 9 Jun 2021 21:32:50 +0200 Subject: [PATCH 3/3] rename toSchema('graphq') -> toGraphQLSchema() --- src/factory.ts | 7 ++----- src/glossary.ts | 4 ++-- test/model/toGraphQLSchema.test.ts | 2 +- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/factory.ts b/src/factory.ts index bb145d38..7d0798ad 100644 --- a/src/factory.ts +++ b/src/factory.ts @@ -266,11 +266,8 @@ function createModelApi< return generateRestHandlers(modelName, definition, api, baseUrl) }, - toSchema(type: 'graphql') { - if (type === 'graphql') { - return generateGraphQLSchema(modelName, definition, api) - } - throw new Error('This Schema type is not supported at the moment') + toGraphQLSchema() { + return generateGraphQLSchema(modelName, definition, api) }, } diff --git a/src/glossary.ts b/src/glossary.ts index ee7f9996..26582d63 100644 --- a/src/glossary.ts +++ b/src/glossary.ts @@ -182,9 +182,9 @@ export interface ModelAPI< toHandlers(type: 'graphql', baseUrl?: string): GraphQLHandler[] /** - * Generate a schema of the given type based on the model. + * Generate a graphql schema based on the model. */ - toSchema(type: 'graphql'): GraphQLSchema + toGraphQLSchema(): GraphQLSchema } export type UpdateManyValue< diff --git a/test/model/toGraphQLSchema.test.ts b/test/model/toGraphQLSchema.test.ts index e9a077ea..33ad4b45 100644 --- a/test/model/toGraphQLSchema.test.ts +++ b/test/model/toGraphQLSchema.test.ts @@ -11,7 +11,7 @@ const db = factory({ }) test('generates a graphql schema', () => { - const schema = db.user.toSchema('graphql') + const schema = db.user.toGraphQLSchema() expect(printSchema(schema)).toMatchInlineSnapshot(` "type Query { user(where: UserQueryInput): User