Skip to content

Commit

Permalink
remove types for deprecated hooks
Browse files Browse the repository at this point in the history
  • Loading branch information
gautamsi committed Dec 8, 2024
1 parent 6616cd1 commit ee3fcc7
Show file tree
Hide file tree
Showing 34 changed files with 596 additions and 510 deletions.
6 changes: 6 additions & 0 deletions .changeset/chilled-moons-walk.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@keystone-6/core": major
---

Removed deprecated list and field hooks.
Fixed field hooks of all the in built types
21 changes: 15 additions & 6 deletions examples/custom-field/2-stars-field/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,22 @@ export const stars =
...config.hooks,
// We use the `validateInput` hook to ensure that the user doesn't set an out of range value.
// This hook is the key difference on the backend between the stars field type and the integer field type.
async validateInput (args) {
const val = args.resolvedData[meta.fieldKey]
if (!(val == null || (val >= 0 && val <= maxStars))) {
args.addValidationError(`The value must be within the range of 0-${maxStars}`)
validate: {
async create (args) {
const val = args.resolvedData[meta.fieldKey]
if (!(val == null || (val >= 0 && val <= maxStars))) {
args.addValidationError(`The value must be within the range of 0-${maxStars}`)
}
await config.hooks?.validate?.create?.(args)
},
async update (args) {
const val = args.resolvedData[meta.fieldKey]
if (!(val == null || (val >= 0 && val <= maxStars))) {
args.addValidationError(`The value must be within the range of 0-${maxStars}`)
}
await config.hooks?.validate?.update?.(args)
}
await config.hooks?.validateInput?.(args)
},
}
},
// all of these inputs are optional if they don't make sense for a particular field type
input: {
Expand Down
82 changes: 59 additions & 23 deletions examples/custom-field/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,31 +20,58 @@ export const lists = {
},

hooks: {
resolveInput: async ({ resolvedData, operation, inputData, item, fieldKey }) => {
console.log('Post.content.hooks.resolveInput', {
resolveInput: {
create: async ({ resolvedData, operation, inputData, item, fieldKey }) => {
console.log('Post.content.hooks.resolveInput.create', {
resolvedData,
operation,
inputData,
item,
fieldKey,
})
return resolvedData[fieldKey]
},
update: async ({ resolvedData, operation, inputData, item, fieldKey }) => {
console.log('Post.content.hooks.resolveInput.update', {
resolvedData,
operation,
inputData,
item,
fieldKey,
})
return resolvedData[fieldKey]
},
},
validate: {
create: async ({
resolvedData,
operation,
inputData,
item,
addValidationError,
fieldKey,
})
return resolvedData[fieldKey]
},

validateInput: async ({
resolvedData,
inputData,
item,
addValidationError,
fieldKey,
}) => {
console.log('Post.content.hooks.validateInput', {
}) => {
console.log('Post.content.hooks.validateInput.create', {
resolvedData,
inputData,
item,
fieldKey,
})
},
update: async ({
resolvedData,
inputData,
item,
addValidationError,
fieldKey,
})
},
}) => {
console.log('Post.content.hooks.validateInput.update', {
resolvedData,
inputData,
item,
fieldKey,
})
},
}
},
}),
rating: stars({
Expand Down Expand Up @@ -100,13 +127,22 @@ export const lists = {
},
},

validateInput: async ({ resolvedData, operation, inputData, item, addValidationError }) => {
console.log('Post.hooks.validateInput', { resolvedData, operation, inputData, item })
validate: {
create: async ({ resolvedData, operation, inputData, item, addValidationError }) => {
console.log('Post.hooks.validateInput.create', { resolvedData, operation, inputData, item })

if (Math.random() > 0.95) {
addValidationError('oh oh, try again, this is part of the example')
}
},
if (Math.random() > 0.95) {
addValidationError('oh oh, try again, this is part of the example')
}
},
update: async ({ resolvedData, operation, inputData, item, addValidationError }) => {
console.log('Post.hooks.validateInput.update', { resolvedData, operation, inputData, item })

if (Math.random() > 0.95) {
addValidationError('oh oh, try again, this is part of the example')
}
},
}
},
}),
} satisfies Lists
59 changes: 40 additions & 19 deletions examples/custom-output-paths/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,25 +13,46 @@ export const lists = {
},

hooks: {
afterOperation: async ({ context }) => {
const posts = (await context.db.Post.findMany({
where: {
title: { equals: 'Home' },
},

// we use Typescript's satisfies here as way to ensure that
// this is the contextualised type - you don't need this
//
// it is helpful for us to check that the example is not
// broken by code changes
//

// TODO: FIXME, babel and pnpm issues
})) as readonly { title: string, content: string }[]
// })) satisfies readonly { title: string; content: string }[];

console.log(posts)
},
afterOperation: {
create: async ({ context }) => {
const posts = (await context.db.Post.findMany({
where: {
title: { equals: 'Home' },
},

// we use Typescript's satisfies here as way to ensure that
// this is the contextualised type - you don't need this
//
// it is helpful for us to check that the example is not
// broken by code changes
//

// TODO: FIXME, babel and pnpm issues
})) as readonly { title: string, content: string }[]
// })) satisfies readonly { title: string; content: string }[];

console.log(posts)
},
update: async ({ context }) => {
const posts = (await context.db.Post.findMany({
where: {
title: { equals: 'Home' },
},

// we use Typescript's satisfies here as way to ensure that
// this is the contextualised type - you don't need this
//
// it is helpful for us to check that the example is not
// broken by code changes
//

// TODO: FIXME, babel and pnpm issues
})) as readonly { title: string, content: string }[]
// })) satisfies readonly { title: string; content: string }[];

console.log(posts)
},
}
},
}),
} satisfies Lists
18 changes: 13 additions & 5 deletions examples/custom-session-invalidation/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,19 @@ We add one new field, `passwordChangedAt`, to the `Person` list. Setting the `pa
passwordChangedAt: timestamp({
access: () => false,
hooks: {
resolveInput: ({ resolvedData }) => {
if (resolvedData.password) {
return new Date();
}
return;
resolveInput: {
create: ({ resolvedData }) => {
if (resolvedData.password) {
return new Date();
}
return;
},
update: ({ resolvedData }) => {
if (resolvedData.password) {
return new Date();
}
return;
},
},
},
ui: {
Expand Down
98 changes: 68 additions & 30 deletions examples/default-values/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,30 @@ export const lists = {
{ label: 'High', value: 'high' },
],
hooks: {
resolveInput ({ resolvedData, inputData }) {
if (inputData.priority === null) {
// default to high if "urgent" is in the label
if (inputData.label && inputData.label.toLowerCase().includes('urgent')) {
return 'high'
} else {
return 'low'
resolveInput: {
create ({ resolvedData, inputData }) {
if (inputData.priority === null) {
// default to high if "urgent" is in the label
if (inputData.label && inputData.label.toLowerCase().includes('urgent')) {
return 'high'
} else {
return 'low'
}
}
}
return resolvedData.priority
},
return resolvedData.priority
},
update ({ resolvedData, inputData }) {
if (inputData.priority === null) {
// default to high if "urgent" is in the label
if (inputData.label && inputData.label.toLowerCase().includes('urgent')) {
return 'high'
} else {
return 'low'
}
}
return resolvedData.priority
},
}
},
}),

Expand All @@ -39,33 +52,58 @@ export const lists = {
many: false,
hooks: {
// dynamic default: if unassigned, find an anonymous user and assign the task to them
async resolveInput ({ context, operation, resolvedData }) {
if (resolvedData.assignedTo === null) {
const [user] = await context.db.Person.findMany({
where: { name: { equals: 'Anonymous' } },
})

if (user) {
return { connect: { id: user.id } }
resolveInput: {
async create ({ context, operation, resolvedData }) {
if (resolvedData.assignedTo === null) {
const [user] = await context.db.Person.findMany({
where: { name: { equals: 'Anonymous' } },
})

if (user) {
return { connect: { id: user.id } }
}
}
}

return resolvedData.assignedTo
},

return resolvedData.assignedTo
},
async update ({ context, operation, resolvedData }) {
if (resolvedData.assignedTo === null) {
const [user] = await context.db.Person.findMany({
where: { name: { equals: 'Anonymous' } },
})

if (user) {
return { connect: { id: user.id } }
}
}

return resolvedData.assignedTo
},
}
},
}),

// dynamic default: we set the due date to be 7 days in the future
finishBy: timestamp({
hooks: {
resolveInput ({ resolvedData, inputData, operation }) {
if (inputData.finishBy == null) {
const date = new Date()
date.setUTCDate(new Date().getUTCDate() + 7)
return date
}
return resolvedData.finishBy
},
resolveInput: {
create ({ resolvedData, inputData, operation }) {
if (inputData.finishBy == null) {
const date = new Date()
date.setUTCDate(new Date().getUTCDate() + 7)
return date
}
return resolvedData.finishBy
},
update ({ resolvedData, inputData, operation }) {
if (inputData.finishBy == null) {
const date = new Date()
date.setUTCDate(new Date().getUTCDate() + 7)
return date
}
return resolvedData.finishBy
},
}
},
}),

Expand Down
35 changes: 24 additions & 11 deletions examples/extend-graphql-subscriptions/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,30 @@ export const lists = {
access: allowAll,
hooks: {
// this hook publishes posts to the 'POST_UPDATED' channel when a post mutated
afterOperation: async ({ item }) => {
// WARNING: passing this item directly to pubSub bypasses any contextual access control
// if you want access control, you need to use a different architecture
//
// tl;dr Keystone access filters are not respected in this scenario
console.log('POST_UPDATED', { id: item?.id })

pubSub.publish('POST_UPDATED', {
postUpdated: item,
})
},
afterOperation: {
create: async ({ item }) => {
// WARNING: passing this item directly to pubSub bypasses any contextual access control
// if you want access control, you need to use a different architecture
//
// tl;dr Keystone access filters are not respected in this scenario
console.log('POST_UPDATED', { id: item?.id })

pubSub.publish('POST_UPDATED', {
postUpdated: item,
})
},
update: async ({ item }) => {
// WARNING: passing this item directly to pubSub bypasses any contextual access control
// if you want access control, you need to use a different architecture
//
// tl;dr Keystone access filters are not respected in this scenario
console.log('POST_UPDATED', { id: item?.id })

pubSub.publish('POST_UPDATED', {
postUpdated: item,
})
},
}
},
fields: {
title: text({ validation: { isRequired: true } }),
Expand Down
Loading

0 comments on commit ee3fcc7

Please sign in to comment.