Skip to content

Commit 80e050c

Browse files
authored
feat(ts-client): returnMode successData (#804)
1 parent c0127d3 commit 80e050c

26 files changed

Lines changed: 780 additions & 160 deletions

src/Schema/core/Index.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1+
import type { GlobalRegistry } from '../../globalRegistry.js'
12
import type { Output } from '../Output/__.js'
23

34
export interface Index {
5+
name: GlobalRegistry.SchemaNames
46
Root: {
57
Query: null | Output.Object$2
68
Mutation: null | Output.Object$2
@@ -11,5 +13,11 @@ export interface Index {
1113
interfaces: Record<string, Output.Interface>
1214
error: {
1315
objects: Record<string, Output.Object$2>
16+
objectsTypename: Record<string, { __typename: string }>
17+
rootResultFields: {
18+
Query: Record<string, string>
19+
Mutation: Record<string, string>
20+
Subscription: Record<string, string>
21+
}
1422
}
1523
}

src/client/Config.ts

Lines changed: 51 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,24 @@
11
import type { ExecutionResult } from 'graphql'
2+
import type { GlobalRegistry } from '../globalRegistry.js'
23
import type { GraphQLExecutionResultError } from '../lib/graphql.js'
34
import type { SetProperty } from '../lib/prelude.js'
5+
import type { Schema } from '../Schema/__.js'
46

57
export type ReturnModeType =
68
| ReturnModeTypeGraphQL
9+
| ReturnModeTypeSuccessData
710
| ReturnModeTypeData
8-
| ReturnModeTypeDataAndSchemaErrors
9-
| ReturnModeTypeDataAllErrors
11+
| ReturnModeTypeDataAndErrors
1012

11-
export type ReturnModeTypeBase = ReturnModeTypeGraphQL | ReturnModeTypeData | ReturnModeTypeDataAllErrors
13+
export type ReturnModeTypeBase = ReturnModeTypeGraphQL | ReturnModeTypeDataAndErrors | ReturnModeTypeData
1214

1315
export type ReturnModeTypeGraphQL = 'graphql'
1416

1517
export type ReturnModeTypeData = 'data'
1618

17-
export type ReturnModeTypeDataAllErrors = 'dataAndAllErrors'
19+
export type ReturnModeTypeDataAndErrors = 'dataAndErrors'
1820

19-
export type ReturnModeTypeDataAndSchemaErrors = 'dataAndSchemaErrors'
21+
export type ReturnModeTypeSuccessData = 'successData'
2022

2123
export type OptionsInput = {
2224
returnMode: ReturnModeType | undefined
@@ -36,10 +38,52 @@ export type ApplyInputDefaults<Input extends OptionsInput> = {
3638
}
3739

3840
// dprint-ignore
39-
export type ReturnMode<$Config extends Config, $Data, $DataRaw = undefined> =
41+
export type ReturnModeRootType<$Config extends Config, $Index extends Schema.Index, $Data extends object> =
42+
$Config['returnMode'] extends 'graphql' ? ExecutionResult<$Data> :
43+
$Config['returnMode'] extends 'data' ? $Data :
44+
$Config['returnMode'] extends 'successData' ? { [$Key in keyof $Data]: ExcludeSchemaErrors<$Index, $Data[$Key]> } :
45+
$Data | GraphQLExecutionResultError
46+
47+
// dprint-ignore
48+
export type ReturnModeRootField<$Config extends Config, $Index extends Schema.Index, $Data, $DataRaw = undefined> =
4049
$Config['returnMode'] extends 'graphql' ? ExecutionResult<$DataRaw extends undefined ? $Data : $DataRaw> :
4150
$Config['returnMode'] extends 'data' ? $Data :
51+
$Config['returnMode'] extends 'successData' ? ExcludeSchemaErrors<$Index, $Data> :
4252
$Data | GraphQLExecutionResultError
4353

54+
export type ExcludeSchemaErrors<$Index extends Schema.Index, $Data> = Exclude<
55+
$Data,
56+
$Index['error']['objectsTypename'][keyof $Index['error']['objectsTypename']]
57+
>
58+
4459
export type OrThrowifyConfig<$Config extends Config> = $Config['returnMode'] extends 'graphql' ? $Config
45-
: SetProperty<$Config, 'returnMode', 'data'>
60+
: SetProperty<$Config, 'returnMode', 'successData'>
61+
62+
/**
63+
* We inject __typename select when:
64+
* 1. using schema errors
65+
* 2. using return mode successData
66+
*/
67+
68+
type TypenameSelection = { __typename: true }
69+
70+
// dprint-ignore
71+
export type CreateSelectionTypename<$Config extends Config, $Index extends Schema.Index> =
72+
IsNeedSelectionTypename<$Config, $Index> extends true ? TypenameSelection : {} // eslint-disable-line
73+
74+
// dprint-ignore
75+
export type IsNeedSelectionTypename<$Config extends Config, $Index extends Schema.Index> =
76+
$Config['returnMode'] extends 'successData' ? GlobalRegistry.HasSchemaErrors<$Index['name']> extends true ? true :
77+
false :
78+
false
79+
export type AugmentRootTypeSelectionWithTypename<
80+
$Config extends Config,
81+
$Index extends Schema.Index,
82+
$RootTypeName extends Schema.RootTypeName,
83+
$Selection extends object,
84+
> = IsNeedSelectionTypename<$Config, $Index> extends true ? {
85+
[$Key in keyof $Selection]:
86+
& $Selection[$Key]
87+
& ($Key extends keyof $Index['error']['rootResultFields'][$RootTypeName] ? TypenameSelection : {}) // eslint-disable-line
88+
}
89+
: $Selection

src/client/RootTypeMethods.ts

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,14 @@ import type { OperationName } from '../lib/graphql.js'
22
import type { Exact } from '../lib/prelude.js'
33
import type { TSError } from '../lib/TSError.js'
44
import type { InputFieldsAllNullable, Schema } from '../Schema/__.js'
5-
import type { Config, OrThrowifyConfig, ReturnMode } from './Config.js'
5+
import type {
6+
AugmentRootTypeSelectionWithTypename,
7+
Config,
8+
CreateSelectionTypename,
9+
OrThrowifyConfig,
10+
ReturnModeRootField,
11+
ReturnModeRootType,
12+
} from './Config.js'
613
import type { ResultSet } from './ResultSet/__.js'
714
import type { SelectionSet } from './SelectionSet/__.js'
815

@@ -54,10 +61,9 @@ export type RootTypeMethods<$Config extends Config, $Index extends Schema.Index,
5461
// dprint-ignore
5562
type RootMethod<$Config extends Config, $Index extends Schema.Index, $RootTypeName extends Schema.RootTypeName> =
5663
<$SelectionSet extends object>(selectionSet: Exact<$SelectionSet, SelectionSet.Root<$Index, $RootTypeName>>) =>
57-
Promise<ReturnMode<$Config, ResultSet.Root<$SelectionSet, $Index, $RootTypeName>>>
64+
Promise<ReturnModeRootType<$Config, $Index, ResultSet.Root<AugmentRootTypeSelectionWithTypename<$Config,$Index,$RootTypeName,$SelectionSet>, $Index, $RootTypeName>>>
5865

5966
// dprint-ignore
60-
// type RootTypeFieldMethod<$Config extends OptionsInputDefaults, $Index extends Schema.Index, $RootTypeName extends Schema.RootTypeName, $RootTypeFieldName extends string> =
6167
type RootTypeFieldMethod<$Context extends RootTypeFieldContext> =
6268
RootTypeFieldMethod_<$Context, $Context['Field']['type']>
6369

@@ -73,7 +79,7 @@ type RootTypeFieldMethod_<$Context extends RootTypeFieldContext, $Type extends S
7379
// dprint-ignore
7480
type ObjectLikeFieldMethod<$Context extends RootTypeFieldContext> =
7581
<$SelectionSet>(selectionSet: Exact<$SelectionSet, SelectionSet.Field<$Context['Field'], $Context['Index'], { hideDirectives: true }>>) =>
76-
Promise<ReturnModeForFieldMethod<$Context, ResultSet.Field<$SelectionSet, $Context['Field'], $Context['Index']>>>
82+
Promise<ReturnModeForFieldMethod<$Context, ResultSet.Field<$SelectionSet & CreateSelectionTypename<$Context['Config'],$Context['Index']>, $Context['Field'], $Context['Index']>>>
7783

7884
// dprint-ignore
7985
type ScalarFieldMethod<$Context extends RootTypeFieldContext> =
@@ -82,4 +88,4 @@ type ScalarFieldMethod<$Context extends RootTypeFieldContext> =
8288
(() => Promise<ReturnModeForFieldMethod<$Context, ResultSet.Field<true, $Context['Field'], $Context['Index']>>>)
8389
// dprint-ignore
8490
type ReturnModeForFieldMethod<$Context extends RootTypeFieldContext, $Data> =
85-
ReturnMode<$Context['Config'], $Data, { [k in $Context['RootTypeFieldName']] : $Data }>
91+
ReturnModeRootField<$Context['Config'], $Context['Index'], $Data, { [k in $Context['RootTypeFieldName']] : $Data }>

src/client/SelectionSet/_.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
export * from './SelectionSet.js'
2-
export * from './toGraphQLDocumentString.js'
2+
export * as Print from './toGraphQLDocumentString.js'

src/client/SelectionSet/__snapshots__/toGraphQLDocumentString.test.ts.snap

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -669,6 +669,25 @@ exports[`args > Query 4`] = `
669669
"
670670
`;
671671

672+
exports[`enum > Query 1`] = `
673+
"
674+
{
675+
"result": {
676+
"$": {
677+
"case": "Object1"
678+
},
679+
"__typename": true
680+
}
681+
}
682+
--------------
683+
{
684+
result(case: Object1) {
685+
__typename
686+
}
687+
}
688+
"
689+
`;
690+
672691
exports[`other > Query 1`] = `
673692
"
674693
{

src/client/SelectionSet/toGraphQLDocumentString.test.ts

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,18 @@
11
import { parse, print } from 'graphql'
22
import { describe, expect, test } from 'vitest'
33
import type { Index } from '../../../tests/_/schema/generated/Index.js'
4+
import { $Index as schemaIndex } from '../../../tests/_/schema/generated/SchemaRuntime.js'
45
import type { SelectionSet } from './__.js'
5-
import { toGraphQLDocumentSelectionSet } from './toGraphQLDocumentString.js'
6+
import type { Context } from './toGraphQLDocumentString.js'
7+
import { rootTypeSelectionSet } from './toGraphQLDocumentString.js'
68

79
// eslint-disable-next-line
810
// @ts-ignore
911
type Q = SelectionSet.Query<Index>
1012
const s = (selectionSet: Q) => selectionSet
1113
const prepareResult = (ss: Q) => {
12-
const graphqlDocumentString = toGraphQLDocumentSelectionSet(ss as any)
14+
const context: Context = { schemaIndex, config: { returnMode: `data` } }
15+
const graphqlDocumentString = rootTypeSelectionSet(context, schemaIndex[`Root`][`Query`], ss as any)
1316
// Should parse, ensures is syntactically valid graphql document.
1417
const document = parse(graphqlDocumentString)
1518
const graphqlDocumentStringFormatted = print(document)
@@ -21,6 +24,14 @@ const prepareResult = (ss: Q) => {
2124
return beforeAfter
2225
}
2326

27+
describe(`enum`, () => {
28+
test.each([
29+
s({ result: { $: { case: `Object1` }, __typename: true } }),
30+
])(`Query`, (ss) => {
31+
expect(prepareResult(ss)).toMatchSnapshot()
32+
})
33+
})
34+
2435
describe(`union`, () => {
2536
test.each([
2637
s({ unionFooBar: { __typename: true } }),

0 commit comments

Comments
 (0)