Skip to content

Commit 2146bb8

Browse files
committed
Experiment with easier context binding
1 parent b101d93 commit 2146bb8

File tree

9 files changed

+104
-96
lines changed

9 files changed

+104
-96
lines changed

examples/extend-graphql-schema-graphql-ts/schema.ts

+15-8
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,14 @@
1-
import { g, list } from '@keystone-6/core'
1+
import { initG, list } from '@keystone-6/core'
22
import { allowAll } from '@keystone-6/core/access'
33
import { select, relationship, text, timestamp } from '@keystone-6/core/fields'
4-
import { type Context, type Lists } from '.keystone/types'
4+
import type { TypeInfo, Lists } from '.keystone/types'
5+
6+
const g = initG<TypeInfo>()
7+
type g<
8+
K extends initG.Key,
9+
FirstArg extends initG.Arg[K],
10+
SecondArg extends initG.OtherArg[K] = initG.OtherArgDefaults<FirstArg>[K],
11+
> = initG<TypeInfo, K, FirstArg, SecondArg>
512

613
export const lists = {
714
Post: list({
@@ -37,23 +44,23 @@ export const extendGraphqlSchema = g.extend(base => {
3744
fields: {
3845
draft: g.field({
3946
type: g.Int,
40-
resolve({ authorId }, args, context: Context) {
47+
resolve({ authorId }, args, context) {
4148
return context.query.Post.count({
4249
where: { author: { id: { equals: authorId } }, status: { equals: 'draft' } },
4350
})
4451
},
4552
}),
4653
published: g.field({
4754
type: g.Int,
48-
resolve({ authorId }, args, context: Context) {
55+
resolve({ authorId }, args, context) {
4956
return context.query.Post.count({
5057
where: { author: { id: { equals: authorId } }, status: { equals: 'published' } },
5158
})
5259
},
5360
}),
5461
latest: g.field({
5562
type: base.object('Post'),
56-
async resolve({ authorId }, args, context: Context) {
63+
async resolve({ authorId }, args, context) {
5764
const [post] = await context.db.Post.findMany({
5865
take: 1,
5966
orderBy: { publishDate: 'desc' },
@@ -72,7 +79,7 @@ export const extendGraphqlSchema = g.extend(base => {
7279
// with the name provided or throw if it doesn't exist
7380
type: base.object('Post'),
7481
args: { id: g.arg({ type: g.nonNull(g.ID) }) },
75-
resolve(source, { id }, context: Context) {
82+
resolve(source, { id }, context) {
7683
// Note we use `context.db.Post` here as we have a return type
7784
// of Post, and this API provides results in the correct format.
7885
// If you accidentally use `context.query.Post` here you can expect problems
@@ -90,7 +97,7 @@ export const extendGraphqlSchema = g.extend(base => {
9097
banPost: g.field({
9198
type: base.object('Post'),
9299
args: { id: g.arg({ type: g.nonNull(g.ID) }) },
93-
resolve(source, { id }, context: Context) {
100+
resolve(source, { id }, context) {
94101
return context.db.Post.updateOne({
95102
where: { id },
96103
data: { status: 'banned' },
@@ -107,7 +114,7 @@ export const extendGraphqlSchema = g.extend(base => {
107114
id: g.arg({ type: g.nonNull(g.ID) }),
108115
seconds: g.arg({ type: g.nonNull(g.Int), defaultValue: 600 }),
109116
},
110-
resolve(source, { id, seconds }, context: Context) {
117+
resolve(source, { id, seconds }, context) {
111118
const cutoff = new Date(Date.now() - seconds * 1000)
112119

113120
// Note we use `context.db.Post` here as we have a return type

examples/graphql-codegen/schema.ts

+9-2
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,17 @@
11
/* eslint-disable @typescript-eslint/consistent-type-imports */
2-
import { list, g } from '@keystone-6/core'
2+
import { list, initG } from '@keystone-6/core'
33
import { relationship, text, timestamp, virtual } from '@keystone-6/core/fields'
44
import { allowAll } from '@keystone-6/core/access'
55
import { graphql } from './gql'
66

7-
import type { Lists } from '.keystone/types'
7+
import type { Lists, TypeInfo } from '.keystone/types'
8+
9+
const g = initG<TypeInfo>()
10+
type g<
11+
K extends initG.Key,
12+
FirstArg extends initG.Arg[K],
13+
SecondArg extends initG.OtherArg[K] = initG.OtherArgDefaults<FirstArg>[K],
14+
> = initG<TypeInfo, K, FirstArg, SecondArg>
815

916
const LatestPostQuery = graphql(/* GraphQL */ `
1017
query LastestPostQuery($id: ID!) {

examples/virtual-field/schema.ts

+9-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,15 @@
1-
import { list, g } from '@keystone-6/core'
1+
import { list, initG } from '@keystone-6/core'
22
import { text, checkbox, virtual } from '@keystone-6/core/fields'
33
import { allowAll } from '@keystone-6/core/access'
44

5-
import type { Lists } from '.keystone/types'
5+
import type { Lists, TypeInfo } from '.keystone/types'
6+
7+
const g = initG<TypeInfo>()
8+
type g<
9+
K extends initG.Key,
10+
FirstArg extends initG.Arg[K],
11+
SecondArg extends initG.OtherArg[K] = initG.OtherArgDefaults<FirstArg>[K],
12+
> = initG<TypeInfo, K, FirstArg, SecondArg>
613

714
export const lists = {
815
Post: list({

packages/core/package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -235,8 +235,8 @@
235235
"@aws-sdk/lib-storage": "^3.83.0",
236236
"@aws-sdk/s3-request-presigner": "^3.83.0",
237237
"@babel/runtime": "^7.24.7",
238-
"@graphql-ts/extend": "https://pkg.pr.new/Thinkmill/graphql-ts/@graphql-ts/extend@6e84a1c",
239-
"@graphql-ts/schema": "https://pkg.pr.new/Thinkmill/graphql-ts/@graphql-ts/schema@6e84a1c",
238+
"@graphql-ts/extend": "https://pkg.pr.new/Thinkmill/graphql-ts/@graphql-ts/extend@f4bafbe",
239+
"@graphql-ts/schema": "https://pkg.pr.new/Thinkmill/graphql-ts/@graphql-ts/schema@f4bafbe",
240240
"@graphql-typed-document-node/core": "^3.1.2",
241241
"@hapi/iron": "^7.0.0",
242242
"@internationalized/date": "^3.5.5",

packages/core/src/index.ts

+2
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,5 @@ export type { ListConfig, BaseFields } from './types'
77
// if this was an explicit list, it would change the re-export here
88
// rather than the usage in their project
99
export * from './types/schema'
10+
11+
export { initG } from './types/schema/graphql-ts-schema'

packages/core/src/types/schema/graphql-ts-schema.ts

+46-69
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,10 @@ import type { ReadStream } from 'node:fs'
22
import * as graphqlTsSchema from '@graphql-ts/schema'
33
// @ts-expect-error
44
import GraphQLUpload from 'graphql-upload/GraphQLUpload.js'
5-
import type { GraphQLFieldExtensions, GraphQLResolveInfo } from 'graphql'
65
import { GraphQLError, GraphQLScalarType } from 'graphql'
76
import { Decimal as DecimalValue } from 'decimal.js'
87
import type { KeystoneContext } from '../context'
98
import type { JSONValue } from '../utils'
10-
import { field as fieldd } from './schema-api-with-context'
119

1210
export {
1311
Boolean,
@@ -37,79 +35,58 @@ export type {
3735
NullableInputType,
3836
ScalarType,
3937
} from '@graphql-ts/schema/api-without-context'
40-
export { bindGraphQLSchemaAPIToContext } from '@graphql-ts/schema'
4138
export type { BaseSchemaMeta, Extension } from '@graphql-ts/extend'
4239
export { extend } from '@graphql-ts/extend'
43-
export { fields, interface, interfaceField, object, union } from './schema-api-with-context'
40+
export { fields, interface, interfaceField, object, union, field } from './schema-api-with-context'
41+
import { initG as baseInitG } from '@graphql-ts/schema'
42+
import type { BaseKeystoneTypeInfo } from '../type-info'
43+
import type { BaseSchemaMeta, Extension } from '@graphql-ts/extend'
44+
import { extend } from '@graphql-ts/extend'
4445

45-
// TODO: remove when we use { graphql } from '.keystone'
46-
type SomeTypeThatIsntARecordOfArgs = string
46+
export function initG<TypeInfo extends BaseKeystoneTypeInfo>() {
47+
return {
48+
extend,
49+
...baseInitG<KeystoneContext<TypeInfo>>(),
50+
}
51+
}
4752

48-
type ImpliedResolver<
49-
Args extends { [Key in keyof Args]: graphqlTsSchema.Arg<graphqlTsSchema.InputType> },
50-
Type extends OutputType<Context>,
51-
Context extends KeystoneContext<any>,
52-
> =
53-
| graphqlTsSchema.InferValueFromOutputType<Type>
54-
| ((
55-
args: graphqlTsSchema.InferValueFromArgs<Args>,
56-
context: Context,
57-
info: GraphQLResolveInfo
58-
) => graphqlTsSchema.InferValueFromOutputType<Type>)
53+
export declare namespace initG {
54+
export type Arg = {
55+
baseSchemaMeta: never
56+
extension: never
57+
} & baseInitG.Arg
5958

60-
export const field: <
61-
Source,
62-
Type extends OutputType<Context>,
63-
Resolve extends
64-
| undefined
65-
| ((
66-
source: Source,
67-
args: graphqlTsSchema.InferValueFromArgs<
68-
SomeTypeThatIsntARecordOfArgs extends Args ? {} : Args
69-
>,
70-
context: Context,
71-
info: GraphQLResolveInfo
72-
) => graphqlTsSchema.InferValueFromOutputType<Type>),
73-
Context extends KeystoneContext<any>,
74-
Args extends { [Key in keyof Args]: graphqlTsSchema.Arg<graphqlTsSchema.InputType> } = {},
75-
>(
76-
field: {
77-
args?: Args
78-
type: Type
79-
deprecationReason?: string
80-
description?: string
81-
extensions?: Readonly<GraphQLFieldExtensions<Source, unknown>>
82-
} & (Resolve extends {}
59+
// the definition of ArgDefaults may change in the future so you should use `ArgDefaults` as the default
60+
// not `Arg`
61+
export type ArgDefaults = Arg
62+
63+
export type OtherArg = {
64+
baseSchemaMeta: never
65+
extension: never
66+
} & baseInitG.OtherArg
67+
68+
export type OtherArgDefaults<FirstArg> = {
69+
baseSchemaMeta: never
70+
extension: never
71+
} & baseInitG.OtherArgDefaults<FirstArg>
72+
73+
export type Key = keyof Arg
74+
export {}
75+
}
76+
77+
export type initG<
78+
TypeInfo extends BaseKeystoneTypeInfo,
79+
K extends initG.Key,
80+
FirstArg extends initG.Arg[K],
81+
SecondArg extends initG.OtherArg[K] = initG.OtherArgDefaults<FirstArg>[K],
82+
> = K extends baseInitG.Key
83+
? baseInitG<KeystoneContext<TypeInfo>, K, FirstArg, SecondArg>
84+
: K extends 'baseSchemaMeta' | 'extension'
8385
? {
84-
resolve: ((
85-
source: Source,
86-
args: graphqlTsSchema.InferValueFromArgs<
87-
SomeTypeThatIsntARecordOfArgs extends Args ? {} : Args
88-
>,
89-
context: Context,
90-
info: GraphQLResolveInfo
91-
) => graphqlTsSchema.InferValueFromOutputType<Type>) &
92-
Resolve
93-
}
94-
: {
95-
resolve?: ((
96-
source: Source,
97-
args: graphqlTsSchema.InferValueFromArgs<
98-
SomeTypeThatIsntARecordOfArgs extends Args ? {} : Args
99-
>,
100-
context: Context,
101-
info: GraphQLResolveInfo
102-
) => graphqlTsSchema.InferValueFromOutputType<Type>) &
103-
Resolve
104-
})
105-
) => Field<
106-
Source,
107-
Args,
108-
Type,
109-
undefined extends Resolve ? ImpliedResolver<Args, Type, Context> : unknown,
110-
Context
111-
> = fieldd as any
112-
// TODO: remove when we use { graphql } from '.keystone'
86+
baseSchemaMeta: BaseSchemaMeta
87+
extension: Extension
88+
}[K]
89+
: never
11390

11491
export const JSON = graphqlTsSchema.g.scalar<JSONValue>(
11592
new GraphQLScalarType({
+8
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,10 @@
1+
import type { BaseKeystoneTypeInfo } from '../type-info'
2+
import type { initG } from './graphql-ts-schema'
3+
14
export * as g from './graphql-ts-schema'
5+
export type g<
6+
K extends initG.Key,
7+
FirstArg extends initG.Arg[K],
8+
SecondArg extends initG.OtherArg[K] = initG.OtherArgDefaults<FirstArg>[K],
9+
> = initG<BaseKeystoneTypeInfo, K, FirstArg, SecondArg>
210
export * from './legacy-alias'
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import { type GraphQLSchemaAPIWithContext } from '@graphql-ts/schema'
1+
import type { GWithContext } from '@graphql-ts/schema'
22

3-
declare const __graphql: GraphQLSchemaAPIWithContext<any>
3+
declare const __graphql: GWithContext<any>
44

55
export = __graphql

pnpm-lock.yaml

+11-11
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)