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

Upgrade to @graphql-ts/schema@1 #9535

Merged
merged 4 commits into from
Mar 12, 2025
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
5 changes: 5 additions & 0 deletions .changeset/eager-cloths-matter.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@keystone-6/core": major
---

`@graphql-ts/schema` has been upgraded to `1.0.0`
2 changes: 1 addition & 1 deletion .changeset/small-kiwis-speak.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
"@keystone-6/core": minor
---

Rename `graphql` export to `g` - `graphql` is still exported but is deprecated and may be removed in a future release
Rename `graphql` export to `g` - `graphql` is still exported but is deprecated and may be removed in a future release. In projects, use `gWithContext` to bind `g` to your specific context type.
9 changes: 6 additions & 3 deletions examples/auth-magic-link/schema.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import { g, list } from '@keystone-6/core'
import { gWithContext, list } from '@keystone-6/core'
import { allowAll, denyAll } from '@keystone-6/core/access'
import { password, text, timestamp } from '@keystone-6/core/fields'
import type { Lists, Context } from '.keystone/types'

import { randomBytes } from 'node:crypto'

const g = gWithContext<Context>()
type g<T> = gWithContext.infer<T>

export type Session = {
itemId: string
}
Expand Down Expand Up @@ -107,7 +110,7 @@ export const extendGraphqlSchema = g.extend(base => {
type: g.nonNull(g.Boolean), // always true
args: { userId: g.arg({ type: g.nonNull(g.String) }) },

async resolve(args, { userId }, context: Context) {
async resolve(args, { userId }, context) {
// run asynchronously to reduce timing attacks
;(async function () {
const ott = randomBytes(16).toString('base64url')
Expand Down Expand Up @@ -141,7 +144,7 @@ export const extendGraphqlSchema = g.extend(base => {
token: g.arg({ type: g.nonNull(g.String) }),
},

async resolve(args, { userId, token }, context: Context) {
async resolve(args, { userId, token }, context) {
if (!context.sessionStrategy)
throw new Error('No session implementation available on context')

Expand Down
19 changes: 11 additions & 8 deletions examples/extend-graphql-schema-graphql-ts/schema.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import { g, list } from '@keystone-6/core'
import { gWithContext, list } from '@keystone-6/core'
import { allowAll } from '@keystone-6/core/access'
import { select, relationship, text, timestamp } from '@keystone-6/core/fields'
import { type Context, type Lists } from '.keystone/types'
import type { Context, Lists } from '.keystone/types'

const g = gWithContext<Context>()
type g<T> = gWithContext.infer<T>

export const lists = {
Post: list({
Expand Down Expand Up @@ -37,23 +40,23 @@ export const extendGraphqlSchema = g.extend(base => {
fields: {
draft: g.field({
type: g.Int,
resolve({ authorId }, args, context: Context) {
resolve({ authorId }, args, context) {
return context.query.Post.count({
where: { author: { id: { equals: authorId } }, status: { equals: 'draft' } },
})
},
}),
published: g.field({
type: g.Int,
resolve({ authorId }, args, context: Context) {
resolve({ authorId }, args, context) {
return context.query.Post.count({
where: { author: { id: { equals: authorId } }, status: { equals: 'published' } },
})
},
}),
latest: g.field({
type: base.object('Post'),
async resolve({ authorId }, args, context: Context) {
async resolve({ authorId }, args, context) {
const [post] = await context.db.Post.findMany({
take: 1,
orderBy: { publishDate: 'desc' },
Expand All @@ -72,7 +75,7 @@ export const extendGraphqlSchema = g.extend(base => {
// with the name provided or throw if it doesn't exist
type: base.object('Post'),
args: { id: g.arg({ type: g.nonNull(g.ID) }) },
resolve(source, { id }, context: Context) {
resolve(source, { id }, context) {
// Note we use `context.db.Post` here as we have a return type
// of Post, and this API provides results in the correct format.
// If you accidentally use `context.query.Post` here you can expect problems
Expand All @@ -90,7 +93,7 @@ export const extendGraphqlSchema = g.extend(base => {
banPost: g.field({
type: base.object('Post'),
args: { id: g.arg({ type: g.nonNull(g.ID) }) },
resolve(source, { id }, context: Context) {
resolve(source, { id }, context) {
return context.db.Post.updateOne({
where: { id },
data: { status: 'banned' },
Expand All @@ -107,7 +110,7 @@ export const extendGraphqlSchema = g.extend(base => {
id: g.arg({ type: g.nonNull(g.ID) }),
seconds: g.arg({ type: g.nonNull(g.Int), defaultValue: 600 }),
},
resolve(source, { id, seconds }, context: Context) {
resolve(source, { id, seconds }, context) {
const cutoff = new Date(Date.now() - seconds * 1000)

// Note we use `context.db.Post` here as we have a return type
Expand Down
7 changes: 5 additions & 2 deletions examples/graphql-codegen/schema.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
/* eslint-disable @typescript-eslint/consistent-type-imports */
import { list, g } from '@keystone-6/core'
import { list, gWithContext } from '@keystone-6/core'
import { relationship, text, timestamp, virtual } from '@keystone-6/core/fields'
import { allowAll } from '@keystone-6/core/access'
import { graphql } from './gql'

import type { Lists } from '.keystone/types'
import type { Lists, Context } from '.keystone/types'

const g = gWithContext<Context>()
type g<T> = gWithContext.infer<T>

const LatestPostQuery = graphql(/* GraphQL */ `
query LastestPostQuery($id: ID!) {
Expand Down
7 changes: 5 additions & 2 deletions examples/graphql-gql.tada/schema.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { list, g } from '@keystone-6/core'
import { list, gWithContext } from '@keystone-6/core'
import { relationship, text, timestamp, virtual } from '@keystone-6/core/fields'
import { allowAll } from '@keystone-6/core/access'
import { graphql } from './tada'
import type { Lists } from '.keystone/types'
import type { Lists, Context } from '.keystone/types'

const LatestPostQuery = graphql(`
query LastestPostQuery($id: ID!) {
Expand All @@ -15,6 +15,9 @@ const LatestPostQuery = graphql(`
}
`)

const g = gWithContext<Context>()
type g<T> = gWithContext.infer<T>

export const lists: Lists = {
Post: list({
access: allowAll,
Expand Down
7 changes: 5 additions & 2 deletions examples/graphql-ts-gql/schema.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
/* eslint-disable @typescript-eslint/consistent-type-imports */
import { list, g } from '@keystone-6/core'
import { list, gWithContext } from '@keystone-6/core'
import { relationship, text, timestamp, virtual } from '@keystone-6/core/fields'
import { allowAll } from '@keystone-6/core/access'
import { gql } from '@ts-gql/tag/no-transform'

import type { Lists } from '.keystone/types'
import type { Lists, Context } from '.keystone/types'

const LatestPostQuery = gql`
query LastestPostQuery($id: ID!) {
Expand All @@ -18,6 +18,9 @@ const LatestPostQuery = gql`
}
` as import('./__generated__/ts-gql/LastestPostQuery').type

const g = gWithContext<Context>()
type g<T> = gWithContext.infer<T>

export const lists = {
Post: list({
access: allowAll,
Expand Down
7 changes: 5 additions & 2 deletions examples/number-fields/schema.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import { list, g } from '@keystone-6/core'
import { list, gWithContext } from '@keystone-6/core'
import { bigInt, float, integer, virtual } from '@keystone-6/core/fields'
import { allowAll } from '@keystone-6/core/access'
import type { Lists } from '.keystone/types'
import type { Lists, Context } from '.keystone/types'

const g = gWithContext<Context>()
type g<T> = gWithContext.infer<T>

export const lists = {
Example: list({
Expand Down
9 changes: 6 additions & 3 deletions examples/transactions/schema.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
import { g, list } from '@keystone-6/core'
import { gWithContext, list } from '@keystone-6/core'
import { allowAll } from '@keystone-6/core/access'
import { text, integer, relationship, timestamp, virtual } from '@keystone-6/core/fields'
import { type Context, type Lists } from '.keystone/types'
import type { Lists, Context } from '.keystone/types'

const g = gWithContext<Context>()
type g<T> = gWithContext.infer<T>

export const extendGraphqlSchema = g.extend(base => {
return {
mutation: {
submitOrder: g.field({
type: base.object('Order'),
args: {},
async resolve(source, {}, context: Context) {
async resolve(source, {}, context) {
// TODO: this should come from GraphQL arguments
const orderInput = [
{ sku: '123', count: 1 },
Expand Down
7 changes: 5 additions & 2 deletions examples/usecase-relationship-union/schema.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { list, group, g } from '@keystone-6/core'
import { list, group, gWithContext } from '@keystone-6/core'
import { allowAll } from '@keystone-6/core/access'
import { text, relationship, virtual } from '@keystone-6/core/fields'
import type { Lists } from '.keystone/types'
import type { Lists, Context } from '.keystone/types'

function ifUnsetHideUI<Key extends string>(field: Key) {
return {
Expand All @@ -15,6 +15,9 @@ function ifUnsetHideUI<Key extends string>(field: Key) {
}
}

const g = gWithContext<Context>()
type g<T> = gWithContext.infer<T>

export const lists: Lists = {
Post: list({
access: allowAll,
Expand Down
7 changes: 5 additions & 2 deletions examples/virtual-field/schema.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import { list, g } from '@keystone-6/core'
import { list, gWithContext } from '@keystone-6/core'
import { text, checkbox, virtual } from '@keystone-6/core/fields'
import { allowAll } from '@keystone-6/core/access'

import type { Lists } from '.keystone/types'
import type { Lists, Context } from '.keystone/types'

const g = gWithContext<Context>()
type g<T> = gWithContext.infer<T>

export const lists = {
Post: list({
Expand Down
3 changes: 2 additions & 1 deletion packages/auth/src/gql/getBaseAuthSchema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import type { BaseItem, KeystoneContext } from '@keystone-6/core/types'
import { g } from '@keystone-6/core'
import { getPasswordFieldKDF } from '@keystone-6/core/fields/types/password'
import type { AuthGqlNames } from '../types'
import type { BaseSchemaMeta } from '@keystone-6/core/graphql-ts'

const AUTHENTICATION_FAILURE = {
code: 'FAILURE',
Expand All @@ -19,7 +20,7 @@ export function getBaseAuthSchema<I extends string, S extends string>({
identityField: I
secretField: S
gqlNames: AuthGqlNames
base: g.BaseSchemaMeta
base: BaseSchemaMeta
}) {
const kdf = getPasswordFieldKDF(base.schema, listKey, secretField)
if (!kdf) {
Expand Down
29 changes: 15 additions & 14 deletions packages/auth/src/gql/getInitFirstItemSchema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import type { BaseItem, KeystoneContext } from '@keystone-6/core/types'
import { g } from '@keystone-6/core'
import { assertInputObjectType, GraphQLInputObjectType, type GraphQLSchema } from 'graphql'
import { type AuthGqlNames, type InitFirstItemConfig } from '../types'
import type { Extension } from '@keystone-6/core/graphql-ts'

const AUTHENTICATION_FAILURE = 'Authentication failed.' as const

Expand All @@ -18,25 +19,25 @@ export function getInitFirstItemSchema({
defaultItemData: InitFirstItemConfig<any>['itemData']
gqlNames: AuthGqlNames
graphQLSchema: GraphQLSchema
ItemAuthenticationWithPasswordSuccess: g.ObjectType<{
item: BaseItem
sessionToken: string
}>
ItemAuthenticationWithPasswordSuccess: g<
typeof g.object<{
item: BaseItem
sessionToken: string
}>
>
// TODO: return type required by pnpm :(
}): g.Extension {
}): Extension {
const createInputConfig = assertInputObjectType(
graphQLSchema.getType(`${listKey}CreateInput`)
).toConfig()
const fieldsSet = new Set(fields)
const initialCreateInput = g.wrap.inputObject(
new GraphQLInputObjectType({
...createInputConfig,
fields: Object.fromEntries(
Object.entries(createInputConfig.fields).filter(([fieldKey]) => fieldsSet.has(fieldKey))
),
name: gqlNames.CreateInitialInput,
})
)
const initialCreateInput = new GraphQLInputObjectType({
...createInputConfig,
fields: Object.fromEntries(
Object.entries(createInputConfig.fields).filter(([fieldKey]) => fieldsSet.has(fieldKey))
),
name: gqlNames.CreateInitialInput,
})

return {
mutation: {
Expand Down
7 changes: 4 additions & 3 deletions packages/cloudinary/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { jsonFieldTypePolyfilledForSQLite } from '@keystone-6/core/types'
import { g } from '@keystone-6/core'
import type Cloudinary from 'cloudinary'
import { v2 as cloudinary } from 'cloudinary'
import type { GArg, InferValueFromArg } from '@keystone-6/core/graphql-ts'

type StoredFile = {
id: string
Expand Down Expand Up @@ -74,7 +75,7 @@ type CloudinaryImage_File = {
encoding: string
publicUrl: string
publicUrlTransformed: (args: {
transformation: g.InferValueFromArg<g.Arg<typeof CloudinaryImageFormat>>
transformation: InferValueFromArg<GArg<typeof CloudinaryImageFormat>>
}) => string
filesize: number
width: number
Expand Down Expand Up @@ -119,7 +120,7 @@ export function cloudinaryImage<ListTypeInfo extends BaseListTypeInfo>({

const inputArg = g.arg({ type: g.Upload })
async function resolveInput(
uploadData: g.InferValueFromArg<typeof inputArg>
uploadData: InferValueFromArg<typeof inputArg>
): Promise<StoredFile | undefined | null> {
if (uploadData === null) return null
if (uploadData === undefined) return
Expand Down Expand Up @@ -181,7 +182,7 @@ export function cloudinaryImage<ListTypeInfo extends BaseListTypeInfo>({
publicUrlTransformed: ({
transformation,
}: {
transformation: g.InferValueFromArg<g.Arg<typeof CloudinaryImageFormat>>
transformation: InferValueFromArg<GArg<typeof CloudinaryImageFormat>>
}) => {
if (!val._meta) return null

Expand Down
4 changes: 4 additions & 0 deletions packages/core/graphql-ts/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"main": "dist/keystone-6-core-graphql-ts.cjs.js",
"module": "dist/keystone-6-core-graphql-ts.esm.js"
}
10 changes: 8 additions & 2 deletions packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@
"module": "./testing/dist/keystone-6-core-testing.esm.js",
"default": "./testing/dist/keystone-6-core-testing.cjs.js"
},
"./graphql-ts": {
"types": "./graphql-ts/dist/keystone-6-core-graphql-ts.cjs.js",
"module": "./graphql-ts/dist/keystone-6-core-graphql-ts.esm.js",
"default": "./graphql-ts/dist/keystone-6-core-graphql-ts.cjs.js"
},
"./scripts/cli": {
"types": "./scripts/cli/dist/keystone-6-core-scripts-cli.cjs.js",
"module": "./scripts/cli/dist/keystone-6-core-scripts-cli.esm.js",
Expand Down Expand Up @@ -235,8 +240,8 @@
"@aws-sdk/lib-storage": "^3.83.0",
"@aws-sdk/s3-request-presigner": "^3.83.0",
"@babel/runtime": "^7.24.7",
"@graphql-ts/extend": "^1.0.3",
"@graphql-ts/schema": "^0.6.4",
"@graphql-ts/extend": "^2.0.0",
"@graphql-ts/schema": "^1.0.0",
"@graphql-typed-document-node/core": "^3.1.2",
"@hapi/iron": "^7.0.0",
"@internationalized/date": "^3.5.5",
Expand Down Expand Up @@ -311,6 +316,7 @@
"context.ts",
"testing.ts",
"session.ts",
"graphql-ts.ts",
"scripts/index.ts",
"scripts/cli.ts",
"admin-ui/components/index.ts",
Expand Down
Loading