Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(ts): support input object in selection set #736

Merged
merged 5 commits into from
Mar 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@
"graphql": "14 - 16"
},
"devDependencies": {
"@tsconfig/node16": "^16.1.1",
"@tsconfig/node16": "^16.1.2",
"@types/body-parser": "^1.19.5",
"@types/express": "^4.17.21",
"@types/json-bigint": "^1.0.4",
Expand All @@ -104,10 +104,10 @@
"get-port": "^7.1.0",
"graphql": "^16.8.1",
"graphql-tag": "^2.12.6",
"happy-dom": "^14.3.1",
"happy-dom": "^14.3.6",
"json-bigint": "^1.0.0",
"tsx": "^4.7.1",
"type-fest": "^4.13.1",
"type-fest": "^4.14.0",
"typescript": "^5.4.3",
"vitest": "^1.4.0"
}
Expand Down
40 changes: 20 additions & 20 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

22 changes: 11 additions & 11 deletions src/ResultSet/ResultSet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export type Object<$SelectionSet, $Node extends Schema.Named.Object, $Index exte
*/
?
{
[$Key in keyof $Node['fields'] as $Node['fields'][$Key] extends Schema.Field.Field<Schema.Field.Type.__typename> | {'typeUnwrapped':{kind:'Scalar'}} ? $Key : never]:
[$Key in keyof $Node['fields'] as $Node['fields'][$Key] extends Schema.Field.Field<Schema.Field.Type.Output.__typename> | {'typeUnwrapped':{kind:'Scalar'}} ? $Key : never]:
// eslint-disable-next-line
// @ts-ignore infinite depth issue, can this be fixed?
Field<$SelectionSet, Schema.Field.As<$Node['fields'][$Key]>, $Index>
Expand Down Expand Up @@ -74,18 +74,18 @@ type Field<$SelectionSet, $Field extends Schema.Field.Field, $Index extends Sche
// dprint-ignore
type FieldType<
$SelectionSet,
$Type extends Schema.Field.Type.Any,
$Type extends Schema.Field.Type.Output.Any,
$Index extends Schema.Index
> =Simplify<
$Type extends Schema.Field.Type.__typename<infer $Value> ? $Value :
$Type extends Schema.Field.Type.Nullable<infer $InnerType> ? null | FieldType<$SelectionSet, $InnerType, $Index> :
$Type extends Schema.Field.Type.List<infer $InnerType> ? Array<FieldType<$SelectionSet, $InnerType, $Index>> :
$Type extends Schema.Named.Enum<infer _, infer $Members> ? $Members[number] :
$Type extends Schema.Named.Scalar.Any ? ReturnType<$Type['constructor']> :
$Type extends Schema.Named.Object ? Object<$SelectionSet,$Type,$Index> :
$Type extends Schema.Named.Interface ? Interface<$SelectionSet,$Type,$Index> :
$Type extends Schema.Named.Union ? Union<$SelectionSet,$Type,$Index> :
TSError<'FieldType', `Unknown type`, { $Type: $Type }>
$Type extends Schema.Field.Type.Output.__typename<infer $Value> ? $Value :
$Type extends Schema.Field.Type.Output.Nullable<infer $InnerType> ? null | FieldType<$SelectionSet, $InnerType, $Index> :
$Type extends Schema.Field.Type.Output.List<infer $InnerType> ? Array<FieldType<$SelectionSet, $InnerType, $Index>> :
$Type extends Schema.Named.Enum<infer _, infer $Members> ? $Members[number] :
$Type extends Schema.Named.Scalar.Any ? ReturnType<$Type['constructor']> :
$Type extends Schema.Named.Object ? Object<$SelectionSet,$Type,$Index> :
$Type extends Schema.Named.Interface ? Interface<$SelectionSet,$Type,$Index> :
$Type extends Schema.Named.Union ? Union<$SelectionSet,$Type,$Index> :
TSError<'FieldType', `Unknown type`, { $Type: $Type }>
>

// dprint-ignore
Expand Down
17 changes: 5 additions & 12 deletions src/Schema/Field/Field.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import type { NamedType } from '../NamedType/__.js'
import type { Scalar } from '../NamedType/Scalar/_.js'
import type * as Type from './Type.js'
import { unwrap } from './Type.js'
import * as Type from './Type.js'

export type * as Type from './Type.js'

Expand All @@ -17,33 +16,27 @@ export type Number<$Args extends Args | null = null> = Field<Scalar.Int, $Args>

export type Boolean<$Args extends Args | null = null> = Field<Scalar.Boolean, $Args>

export namespace Input {
export type Nullable = Type.Nullable<any>
export type List = Type.List<any>
export type Any = Scalar.Any | List | Nullable
}

// export interface Args<$Fields extends Record<keyof $Fields, InputFieldType> = Record<string, InputFieldType>> {
export interface Args<$Fields extends any = any> {
allOptional: Exclude<$Fields[keyof $Fields], Type.Nullable<any>> extends never ? true : false
allOptional: Exclude<$Fields[keyof $Fields], Type.Output.Nullable<any>> extends never ? true : false
fields: $Fields
}

export const field = <$Type extends Type.Any, $Args extends null | Args = null>(
export const field = <$Type extends Type.Output.Any, $Args extends null | Args = null>(
type: $Type,
args: $Args = null as $Args,
): Field<$Type, $Args> => {
return {
// eslint-disable-next-line
// @ts-ignore infinite depth issue, can this be fixed?
typeUnwrapped: unwrap(type),
typeUnwrapped: Type.Output.unwrap(type),
type,
args,
}
}

export type Field<$Type extends any = any, $Args extends Args | null = Args | null> = {
typeUnwrapped: Type.Unwrap<$Type>
typeUnwrapped: Type.Output.Unwrap<$Type>
type: $Type
args: $Args
}
63 changes: 38 additions & 25 deletions src/Schema/Field/Type.ts
Original file line number Diff line number Diff line change
@@ -1,38 +1,51 @@
import type { TSError } from '../../lib/TSError.js'
import type { NamedType } from '../NamedType/__.js'

export interface __typename<$Type extends string = string> {
kind: 'typename'
type: $Type
}
export interface Nullable<$Type extends Any> {
kind: 'nullable'
type: $Type
}
export interface List<$Type extends Any> {
kind: 'list'
type: $Type
export namespace Base {
export interface Nullable<$Type> {
kind: 'nullable'
type: $Type
}
export interface List<$Type> {
kind: 'list'
type: $Type
}
}

export type Any = List<any> | __typename<any> | Nullable<any> | NamedType.Any
export namespace Output {
export interface __typename<$Type extends string = string> {
kind: 'typename'
type: $Type
}
export type Nullable<$Type extends Any> = Base.Nullable<$Type>
export type List<$Type extends Any> = Base.List<$Type>

export type Any = Output.List<any> | __typename<any> | Base.Nullable<any> | NamedType.AnyOutput

export const __typename = <$Type extends string>(type: $Type): __typename<$Type> => ({ kind: `typename`, type })
export const nullable = <$Type extends __typename<any> | List<any>>(type: $Type): Nullable<$Type> => ({
kind: `nullable`,
type,
})
export const list = <$Type extends Any>(type: $Type): List<$Type> => ({ kind: `list`, type })
export const __typename = <$Type extends string>(type: $Type): __typename<$Type> => ({ kind: `typename`, type })
export const nullable = <$Type extends __typename<any> | List<any>>(type: $Type): Nullable<$Type> => ({
kind: `nullable`,
type,
})
export const list = <$Type extends Any>(type: $Type): List<$Type> => ({ kind: `list`, type })

// todo extends any because of infinite depth issue in generated schema types
// dprint-ignore
export type Unwrap<$Type extends any> =
// todo extends any because of infinite depth issue in generated schema types
// dprint-ignore
export type Unwrap<$Type extends any> =
$Type extends List<infer $innerType> ? Unwrap<$innerType> :
$Type extends Nullable<infer $innerType> ? Unwrap<$innerType> :
$Type extends __typename ? $Type['type'] :
$Type extends NamedType.Any ? $Type :
$Type extends NamedType.AnyOutput ? $Type :
TSError<'Unwrap', 'Unknown $Type', { $Type: $Type }>

export const unwrap = <$Type extends Any>(type: $Type): Unwrap<$Type> => {
// @ts-expect-error fixme
return type.kind === `named` ? type.type : unwrap(type.type)
export const unwrap = <$Type extends Any>(type: $Type): Unwrap<$Type> => {
// @ts-expect-error fixme
return type.kind === `named` ? type.type : unwrap(type.type)
}
}

export namespace Input {
export type Nullable<$InnerType extends Any = Any> = Base.Nullable<$InnerType>
export type List<$InnerType extends Any = Any> = Base.List<$InnerType>
export type Any = List<any> | Nullable<any> | NamedType.AnyInput
}
2 changes: 0 additions & 2 deletions src/Schema/NamedType/Enum.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import type { __typename } from '../__.js'

export interface Enum<
$Name extends string = string,
$Members extends [string, ...string[]] = [string, ...string[]],
Expand Down
23 changes: 23 additions & 0 deletions src/Schema/NamedType/InputObjet.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/* eslint-disable @typescript-eslint/ban-types */

type Fields = Record<string, any>

export interface InputObject<
$Name extends string = string,
$Fields extends Fields = Fields,
> {
kind: 'InputObject'
name: $Name
fields: $Fields
}

export const InputObject = <$Name extends string, $Fields extends Record<keyof $Fields, any>>(
name: $Name,
fields: $Fields,
): InputObject<$Name, $Fields> => ({
kind: `InputObject`,
name: name,
fields: {
...fields,
},
})
1 change: 0 additions & 1 deletion src/Schema/NamedType/Interface.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
/* eslint-disable @typescript-eslint/ban-types */

import type { __typename } from '../__.js'
import type { Field } from '../Field/Field.js'
import type { Object } from './Object.js'

Expand Down
5 changes: 4 additions & 1 deletion src/Schema/NamedType/NamedType.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,15 @@

import type { Digit, Letter } from '../../lib/prelude.js'
import type { Enum } from './Enum.js'
import type { InputObject } from './InputObjet.js'
import type { Interface } from './Interface.js'
import type { Object } from './Object.js'
import type { Scalar } from './Scalar/_.js'
import type { Union } from './Union.js'

export type Any = Interface | Enum | Object | Scalar.Any | Union
export type AnyOutput = Interface | Enum | Object | Scalar.Any | Union
export type AnyInput = Enum | Scalar.Any | InputObject
export type Any = AnyOutput | AnyInput

/**
* @see http://spec.graphql.org/draft/#sec-Names
Expand Down
8 changes: 4 additions & 4 deletions src/Schema/NamedType/Object.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@

import type { Field } from '../Field/Field.js'
import { field } from '../Field/Field.js'
import { __typename } from '../Field/Type.js'
import { Output } from '../Field/Type.js'

export type Fields = Record<string, Field<any>>

export type ObjectFields = {
__typename: Field<__typename>
__typename: Field<Output.__typename>
} & Fields

export interface Object<
Expand All @@ -16,7 +16,7 @@ export interface Object<
> {
kind: 'Object'
fields: {
__typename: Field<__typename<$Name>>
__typename: Field<Output.__typename<$Name>>
} & $Fields
}

Expand All @@ -26,7 +26,7 @@ export const Object = <$Name extends string, $Fields extends Record<keyof $Field
): Object<$Name, $Fields> => ({
kind: `Object`,
fields: {
__typename: field(__typename(name)),
__typename: field(Output.__typename(name)),
...fields,
},
})
Loading