diff --git a/src/layers/5_client/client.raw.test.ts b/src/layers/5_client/client.raw.test.ts new file mode 100644 index 000000000..065679143 --- /dev/null +++ b/src/layers/5_client/client.raw.test.ts @@ -0,0 +1,24 @@ +import { expect, test } from 'vitest' +import { $Index } from '../../../tests/_/schema/generated/SchemaRuntime.js' +import { schema } from '../../../tests/_/schema/schema.js' +import { create } from './client.js' + +// todo test with custom scalars + +const client = create({ schema, schemaIndex: $Index }) + +test(`.rawOrThrow() throws if errors array non-empty`, async () => { + await expect(client.rawOrThrow(`query {}`)).rejects.toMatchInlineSnapshot( + `[ContextualAggregateError: One or more errors in the execution result.]`, + ) +}) + +test(`.raw() returns errors in array`, async () => { + await expect(client.raw(`query {}`)).resolves.toMatchInlineSnapshot(` + { + "errors": [ + [GraphQLError: Syntax Error: Expected Name, found "}".], + ], + } + `) +}) diff --git a/src/layers/5_client/client.returnMode.test.ts b/src/layers/5_client/client.returnMode.test.ts index 229cd58a3..7a341cc88 100644 --- a/src/layers/5_client/client.returnMode.test.ts +++ b/src/layers/5_client/client.returnMode.test.ts @@ -16,7 +16,7 @@ describe('default (data)', () => { await expect(client.document({ main: { query: { id: true } } }).runOrThrow()).resolves.toEqual({ id: db.id }) }) test(`document.runOrThrow error`, async () => { - await expect(client.document({ main: { query: { error: true } } }).runOrThrow()).rejects.toEqual(db.error) + await expect(client.document({ main: { query: { error: true } } }).runOrThrow()).rejects.toEqual(db.errorAggregate) }) test('raw', async () => { await expect(client.raw('query main {\nid\n}', {}, 'main')).resolves.toEqual({ data: { id: db.id } }) @@ -25,16 +25,16 @@ describe('default (data)', () => { await expect(client.query.__typename()).resolves.toEqual('Query') }) test('query. error', async () => { - await expect(client.query.error()).rejects.toMatchObject(db.error) + await expect(client.query.error()).rejects.toMatchObject(db.errorAggregate) }) test('query. error orThrow', async () => { - await expect(client.query.errorOrThrow()).rejects.toMatchObject(db.error) + await expect(client.query.errorOrThrow()).rejects.toMatchObject(db.errorAggregate) }) test('query.$batch', async () => { await expect(client.query.$batch({ __typename: true, id: true })).resolves.toEqual({ __typename: 'Query', id: db.id }) }) test('query.$batchOrThrow error', async () => { - await expect(client.query.$batchOrThrow({ error: true })).rejects.toMatchObject(db.error) + await expect(client.query.$batchOrThrow({ error: true })).rejects.toMatchObject(db.errorAggregate) }) test('mutation.', async () => { await expect(client.mutation.__typename()).resolves.toEqual('Mutation') @@ -54,7 +54,7 @@ describe('dataAndErrors', () => { await expect(client.document({ main: { query: { id: true } } }).runOrThrow()).resolves.toEqual({ id: db.id }) }) test(`document.runOrThrow error`, async () => { - await expect(client.document({ main: { query: { error: true } } }).runOrThrow()).rejects.toEqual(db.error) + await expect(client.document({ main: { query: { error: true } } }).runOrThrow()).rejects.toEqual(db.errorAggregate) }) test('raw', async () => { await expect(client.raw('query main {\nid\n}', {}, 'main')).resolves.toEqual({ data: { id: db.id } }) @@ -63,16 +63,16 @@ describe('dataAndErrors', () => { await expect(client.query.__typename()).resolves.toEqual('Query') }) test('query. error', async () => { - await expect(client.query.error()).resolves.toMatchObject(db.error) + await expect(client.query.error()).resolves.toMatchObject(db.errorAggregate) }) test('query. error orThrow', async () => { - await expect(client.query.errorOrThrow()).rejects.toMatchObject(db.error) + await expect(client.query.errorOrThrow()).rejects.toMatchObject(db.errorAggregate) }) test('query.$batch', async () => { await expect(client.query.$batch({ __typename: true, id: true })).resolves.toEqual({ __typename: 'Query', id: db.id }) }) test('query.$batchOrThrow error', async () => { - await expect(client.query.$batchOrThrow({ error: true })).rejects.toMatchObject(db.error) + await expect(client.query.$batchOrThrow({ error: true })).rejects.toMatchObject(db.errorAggregate) }) test('mutation.', async () => { await expect(client.mutation.__typename()).resolves.toEqual('Mutation') @@ -146,7 +146,7 @@ describe('graphql', () => { await expect(client.document({ main: { query: { id: true } } }).runOrThrow()).resolves.toEqual({data:{ id: db.id }}) }) test(`document.runOrThrow error`, async () => { - await expect(client.document({ main: { query: { error: true } } }).runOrThrow()).rejects.toEqual(db.error) + await expect(client.document({ main: { query: { error: true } } }).runOrThrow()).rejects.toEqual(db.errorAggregate) }) test('raw', async () => { await expect(client.raw('query main {\nid\n}', {}, 'main')).resolves.toEqual({ data: { id: db.id } }) @@ -155,16 +155,16 @@ describe('graphql', () => { await expect(client.query.__typename()).resolves.toEqual({ data: { __typename: 'Query' } }) }) test('query. error', async () => { - await expect(client.query.error()).resolves.toMatchObject({ errors:db.error['errors'] }) + await expect(client.query.error()).resolves.toMatchObject({ errors:db.errorAggregate['errors'] }) }) test('query. orThrow error', async () => { - await expect(client.query.errorOrThrow()).rejects.toMatchObject(db.error) + await expect(client.query.errorOrThrow()).rejects.toMatchObject(db.errorAggregate) }) test('query.$batch', async () => { await expect(client.query.$batch({ __typename: true, id: true })).resolves.toEqual({ data: { __typename: 'Query', id: db.id } }) }) test('query.$batchOrThrow error', async () => { - await expect(client.query.$batchOrThrow({ error: true })).rejects.toMatchObject(db.error) + await expect(client.query.$batchOrThrow({ error: true })).rejects.toMatchObject(db.errorAggregate) }) test('mutation.', async () => { await expect(client.mutation.__typename()).resolves.toEqual({ data: { __typename: 'Mutation' } }) diff --git a/src/layers/5_client/client.rootTypeMethods.test.ts b/src/layers/5_client/client.rootTypeMethods.test.ts index a6d45978e..7bf1abf06 100644 --- a/src/layers/5_client/client.rootTypeMethods.test.ts +++ b/src/layers/5_client/client.rootTypeMethods.test.ts @@ -41,7 +41,7 @@ describe(`query`, () => { await expect(client.query.objectWithArgsOrThrow({ $: { id: `x` }, id: true })).resolves.toEqual({ id: `x` }) }) test(`with error`, async () => { - await expect(client.query.errorOrThrow()).rejects.toMatchObject(db.error) + await expect(client.query.errorOrThrow()).rejects.toMatchObject(db.errorAggregate) }) }) describe(`$batch`, () => { @@ -49,14 +49,14 @@ describe(`query`, () => { await expect(client.query.$batch({ id: true })).resolves.toMatchObject({ id:db.id }) }) test(`error`, async () => { - await expect(client.query.$batch({ error: true })).rejects.toMatchObject(db.error) + await expect(client.query.$batch({ error: true })).rejects.toMatchObject(db.errorAggregate) }) describe(`orThrow`, () => { test(`success`, async () => { await expect(client.query.$batchOrThrow({ id: true })).resolves.toMatchObject({ id:db.id }) }) test(`error`, async () => { - await expect(client.query.$batchOrThrow({ error: true })).rejects.toMatchObject(db.error) + await expect(client.query.$batchOrThrow({ error: true })).rejects.toMatchObject(db.errorAggregate) }) }) }) diff --git a/src/layers/5_client/client.ts b/src/layers/5_client/client.ts index 6777e2767..cb936b398 100644 --- a/src/layers/5_client/client.ts +++ b/src/layers/5_client/client.ts @@ -2,6 +2,7 @@ import type { ExecutionResult } from 'graphql' import { type DocumentNode, execute, graphql, type GraphQLSchema } from 'graphql' import request from '../../entrypoints/main.js' import { Errors } from '../../lib/errors/__.js' +import type { SomeExecutionResultWithoutErrors } from '../../lib/graphql.js' import { type RootTypeName, rootTypeNameToOperationName, type Variables } from '../../lib/graphql.js' import { isPlainObject } from '../../lib/prelude.js' import type { Object$2 } from '../1_Schema/__.js' @@ -27,6 +28,7 @@ export type Client<$Index extends Schema.Index, $Config extends Config> = & { // todo test raw raw: (document: string | DocumentNode, variables?:Variables, operationName?:string) => Promise + rawOrThrow: (document: string | DocumentNode, variables?:Variables, operationName?:string) => Promise document: DocumentFn<$Config, $Index> } & GetRootTypeMethods<$Config, $Index> @@ -295,6 +297,18 @@ export const create = <$Input extends Input>( raw: async (document: string | DocumentNode, variables?: Variables, operationName?: string) => { return await executeGraphQLDocument({ document, variables, operationName }) }, + rawOrThrow: async (document: string | DocumentNode, variables?: Variables, operationName?: string) => { + const result = await client.raw(document, variables, operationName) as ExecutionResult // eslint-disable-line + // todo consolidate + if (result.errors && result.errors.length > 0) { + throw new Errors.ContextualAggregateError( + `One or more errors in the execution result.`, + {}, + result.errors, + ) + } + return result + }, document: (documentObject: DocumentObject) => { const run = async (operationName: string) => { // 1. if returnMode is successData OR using orThrow diff --git a/src/lib/graphql.ts b/src/lib/graphql.ts index 166b46120..b6ff397aa 100644 --- a/src/lib/graphql.ts +++ b/src/lib/graphql.ts @@ -11,6 +11,7 @@ import { isListType, isNonNullType, } from 'graphql' +import type { ObjMap } from 'graphql/jsutils/ObjMap.js' import type { Errors } from './errors/__.js' export type TypeMapByKind = @@ -247,3 +248,12 @@ export type Variables = Record // todo export type GraphQLExecutionResultError = Errors.ContextualAggregateError export type OperationName = 'query' | 'mutation' + +export interface SomeExecutionResultWithoutErrors< + TData = ObjMap, + TExtensions = ObjMap, +> { + errors?: readonly [] + data?: TData | null + extensions?: TExtensions +} diff --git a/tests/_/db.ts b/tests/_/db.ts index da1713d8c..16de60b8d 100644 --- a/tests/_/db.ts +++ b/tests/_/db.ts @@ -4,7 +4,7 @@ import { Errors } from '../../src/lib/errors/__.js' const date0 = new Date(0) // const error = { errors: [{ message: `Something went wrong.` }] } -const error = new Errors.ContextualAggregateError(`One or more errors in the execution result.`, {}, [ +const errorAggregate = new Errors.ContextualAggregateError(`One or more errors in the execution result.`, {}, [ new GraphQLError(`Something went wrong.`), ]) @@ -67,5 +67,5 @@ export const db = { DateInterface1: { date1: date0, }, - error, + errorAggregate, } as const