Releases: keystonejs/keystone
🔒 10th January 2022
This patch release is related to security advisory CVE-2022-0087.
"@keystone-6/auth": "1.0.2"Security Advisory 🔒
This patch is relating to a security advisory that removes the capability for an attacker to exploit a reflected cross-site scripting vulnerability when using a previous version of the @keystone-6/auth package. The original security advisory is located here.
Impact
The vulnerability can impact users of the administration user interface when following an untrusted link to the signin or init page.
This is a targeted attack and may present itself in the form of phishing and or chained in conjunction with some other vulnerability.
Mitigation
Please upgrade to @keystone-6/auth >= 1.0.2 (this patch), where this vulnerability has been closed.
If you are using @keystone-next/auth, we strongly recommend you upgrade to @keystone-6.
Workarounds
If for some reason you cannot upgrade the dependencies in software, you could alternatively
- disable the administration user interface, or
- if using a reverse-proxy, strip query parameters when accessing the administration interface
References
https://owasp.org/www-community/attacks/xss/
Credits
Thanks to Shivansh Khari (@Shivansh-Khari) for discovering and reporting this vulnerability.
Enjoying Keystone?
Star this repo 🌟 ☝️ or connect to Keystone on Twitter and in Slack.
Changelog
You can also view the verbose changelog in the related PR (#7156) for this release.
⚙️ 22nd December 2021
Patch release.
"@keystone-6/auth": "1.0.1",
"@keystone-6/core": "1.0.1",Miscellaneous Fixes ⚙️
- Page titles now reflect the page you are on:
itemview shows the item's label,listview shows the list name, other pages showKeystone - Refactoring of TypeScript type generation
- Fixed the inferred type of a field
resolveInputhook to support returningundefined - Explicitly disable caching for redirect responses in the Admin UI
- Fixed error
You must await server.start() before calling server.createHandler()when using thegenerateNextGraphqlAPIexperimental option - Fixed setting
db.enableLoggingtofalseerroring - Removed redundant
fast-globdependency - Updated Prisma monorepo to v3.6.0
- Fixed Lists import in artifacts types, thanks @SerWonka!
Enjoying Keystone?
Star this repo 🌟 ☝️ or connect to Keystone on Twitter and in Slack.
Changelog
You can also view the verbose changelog in the related PR (#7044) for this release.
✨ 1st December 2021
This release marks the achievement of General Availability status for Keystone 6! 🚀
We've also included a range of improvements to Keystone's TypeScript DX since shipping last week's release candidate.
Keystone 6 ⚡️
With this major release, the project has moved to the @keystone-6 namespace on npm, and our version numbers have been reset.
We highly recommend you upgrade your existing Keystone Next projects to Keystone 6 with the packages below:
"@keystone-6/auth": "1.0.0",
"@keystone-6/cloudinary": "1.0.0",
"@keystone-6/document-renderer": "1.0.0",
"@keystone-6/fields-document": "1.0.0",
"@keystone-6/core": "1.0.0",
"@keystone-6/session-store-redis": "1.0.0",Note:
@keystone-next/keystonehas been changed to@keystone-6/core
Among other internal naming changes, our CLI commands have switched from keystone-next to simply keystone, please ensure you update your startup scripts to suit!
Note: To learn more about this major release and what's in store for the road ahead, checkout our official general availability announcement and updated roadmap.
Type Enhancements ✨
We've shipped a significant update to our generated TypeScript types.
The types for your schema are stricter when your lists are contextually typed by the newly provided Lists types from .keystone/types.
This results in a smoother, type-safe auto-complete experience and stricter types for your access control, hooks, and any other code that uses a Keystone context.
For example, if you write all your lists in one object:
import { Lists } from '.keystone/types'
export const lists: Lists = {
Blah: list({...})
}If you're defining your lists separately, you can do this:
import { Lists } from '.keystone/types'
export const Blah: Lists.Blah = list({
...
})For a more in-depth view of what TypeScript types have been changed, see below:
- The following types have been renamed:
BaseGeneratedListTypes→BaseListTypeInfoItemRootValue→BaseItemListInfo→ListGraphQLTypesTypesForList→GraphQLTypesForListFieldTypeFuncnow has a required type parameter which must satisfyBaseListTypeInfo
- The following types now have a required type parameter which must satisfy
BaseKeystoneTypeInfo:ServerConfigCreateRequestContextAdminUIConfigDatabaseConfigListOperationAccessControlMaybeSessionFunctionMaybeItemFunction
GraphQLResolverandGraphQLSchemaExtensionnow have a required type parameter which must satisfyKeystoneContextKeystoneGraphQLAPIno longer has a type parameter- The first parameter to the resolver in a
virtualfield will be typed as the item type if the list is typed withKeystone.ListsorKeystone.Lists.ListKey, otherwise it will be typed asunknown - The
item/originalItemarguments in hooks/access control will now receive theItemtype if the list is typed withKeystone.ListsorKeystone.Lists.ListKey, otherwise it will be typed asBaseItem argshas been removed fromBaseListTypeInfoinputs.orderByandallhas been added toBaseListTypeInfo- In
.keystone/types:ListKeyListTypeInfohas been moved toLists.ListKey.TypeInfoKeystoneContexthas been renamed toContext
Credits 💫
This release would not have been possible without the support and feedback of such an awesome developer community.
We're grateful for the ideas you bring, the help you give others, and the code contributions the you've made to get Keystone to where it is today.
Like this release? Give us a star on GitHub!
Changelog
You can view the verbose changelog in the related PR (#7018) for this release.
✨ 24th November 2021
The Release Candidate for Keystone 6 General Availability has arrived! Within you'll find numerous improvements across the project. ⭐️
After this release, we will be moving Keystone 6 to General Availability and promoting the project to the @keystone-6 namespace on npm.
We highly recommend you upgrade to this release:
"@keystone-next/auth": "37.0.0",
"@keystone-next/cloudinary": "12.0.0",
"@keystone-next/document-renderer": "5.0.0",
"@keystone-next/fields-document": "14.0.0",
"@keystone-next/keystone": "29.0.0",
"@keystone-next/session-store-redis": "9.0.0",Shorter Relationship Names 🤏
Warning:
⚠️ Breaking change! Please follow the guidance below to avoid losing data.
The names of one-sided and two-sided, many-many relationships has been shortened. Two-sided many-many relationship names contain only the left-hand side names now; and the _many suffix has been dropped from one-sided many-many relationships.
This reduces the probability that you will exceed PostgreSQL's 63 character limit for identifiers with typical usage.
There are two different ways you can update your schema:
-
Explicitly set the
db.relationNameon many-to-many relations, allowing your database to remain unchanged. -
Rename your many-to-many relations and tables using a migration, changing your database.
Set db.relationName on many to many relations
Rather than doing a migration, you can set the new field property db.relationName, for either side of a many-to-many relationship field.
If set to the existing relation name, your database will remain unchanged.
For example, given a schema like this:
Post: list({
fields: {
tags: relationship({ ref: 'Tag.posts', many: true }),
},
}),
Tag: list({
fields: {
posts: relationship({ ref: 'Post.tags', many: true }),
},
}),Before this release, the generated Prisma schema looked like this:
// This file is automatically generated by Keystone, do not modify it manually.
// Modify your Keystone config when you want to change this.
datasource postgresql {
url = env("DATABASE_URL")
provider = "postgresql"
}
generator client {
provider = "prisma-client-js"
output = "node_modules/.prisma/client"
engineType = "binary"
}
model Post {
id String @id @default(cuid())
tags Tag[] @relation("Post_tags_Tag_posts")
}
model Tag {
id String @id @default(cuid())
posts Post[] @relation("Post_tags_Tag_posts")
}By adding db: { relationName: 'Post_tags_Tag_posts' } to one side of the many-to-many relationship; you can preclude yourself from a migration.
Note: It doesn't matter which side of the relationship you put this property, but it should be only on one side; otherwise you will receive an error.
Post: list({
fields: {
tags: relationship({ ref: 'Tag.posts', many: true, db: { relationName: 'Post_tags_Tag_posts' } }),
},
}),
Tag: list({
fields: {
posts: relationship({ ref: 'Post.tags', many: true }),
},
}),Rename your many relation tables using a migration
For example, given a schema like this:
Post: list({
fields: {
tags: relationship({ ref: 'Tag.posts', many: true }),
},
}),
Tag: list({
fields: {
posts: relationship({ ref: 'Post.tags', many: true }),
},
}),When updating to this change, and running yarn dev, Keystone will prompt you to update your schema.
Warning:
⚠️ Warning: DO NOT APPLY THE AUTOMATICALLY GENERATED MIGRATION!
You will lose your data. Only apply the migration if you want toDROPyour data.
If using useMigrations: true, Keystone will follow the typical migration flow and offer to apply an automatically generated migration.
If using useMigrations: false, Keystone will follow the typical flow and offer to automatically migrate your schema.
On PostgreSQL, Prisma will generate a migration that looks something like this:
/*
Warnings:
- You are about to drop the `_Post_tags_Tag_posts` table. If the table is not empty, all the data it contains will be lost.
*/
-- DropForeignKey
ALTER TABLE "_Post_tags_Tag_posts" DROP CONSTRAINT "_Post_tags_Tag_posts_A_fkey";
-- DropForeignKey
ALTER TABLE "_Post_tags_Tag_posts" DROP CONSTRAINT "_Post_tags_Tag_posts_B_fkey";
-- DropTable
DROP TABLE "_Post_tags_Tag_posts";
-- CreateTable
CREATE TABLE "_Post_tags" (
"A" TEXT NOT NULL,
"B" TEXT NOT NULL
);
-- CreateIndex
CREATE UNIQUE INDEX "_Post_tags_AB_unique" ON "_Post_tags"("A", "B");
-- CreateIndex
CREATE INDEX "_Post_tags_B_index" ON "_Post_tags"("B");
-- AddForeignKey
ALTER TABLE "_Post_tags" ADD FOREIGN KEY ("A") REFERENCES "Post"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "_Post_tags" ADD FOREIGN KEY ("B") REFERENCES "Tag"("id") ON DELETE CASCADE ON UPDATE CASCADE;You need to modify it so that it looks like this with the old and new table names for your schema substituted:
ALTER TABLE "_Post_tags_Tag_posts" RENAME TO "_Post_tags";
ALTER INDEX "_Post_tags_Tag_posts_AB_unique" RENAME TO "_Post_tags_AB_unique";
ALTER INDEX "_Post_tags_Tag_posts_B_index" RENAME TO "_Post_tags_B_index";
ALTER TABLE "_Post_tags" RENAME CONSTRAINT "_Post_tags_Tag_posts_A_fkey" TO "_Post_tags_A_fkey";
ALTER TABLE "_Post_tags" RENAME CONSTRAINT "_Post_tags_Tag_posts_B_fkey" TO "_Post_tags_B_fkey";On SQLite, Prisma will generate a migration that looks something like this:
/*
Warnings:
- You are about to drop the `_Post_tags_Tag_posts` table. If the table is not empty, all the data it contains will be lost.
*/
-- DropTable
PRAGMA foreign_keys=off;
DROP TABLE "_Post_tags_Tag_posts";
PRAGMA foreign_keys=on;
-- CreateTable
CREATE TABLE "_Post_tags" (
"A" TEXT NOT NULL,
"B" TEXT NOT NULL,
FOREIGN KEY ("A") REFERENCES "Post" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
FOREIGN KEY ("B") REFERENCES "Tag" ("id") ON DELETE CASCADE ON UPDATE CASCADE
);
-- CreateIndex
CREATE UNIQUE INDEX "_Post_tags_AB_unique" ON "_Post_tags"("A", "B");
-- CreateIndex
CREATE INDEX "_Post_tags_B_index" ON "_Post_tags"("B");You need to modify it so that it looks like this with the old and new table names for your schema substituted:
ALTER TABLE "_Post_tags_Tag_posts" RENAME TO "_Post_tags";
DROP INDEX "_Post_tags_Tag_posts_AB_unique";
DROP INDEX "_Post_tags_Tag_posts_B_index";
CREATE UNIQUE INDEX "_Post_tags_AB_unique" ON "_Post_tags"("A", "B");
CREATE INDEX "_Post_tags_B_index" ON "_Post_tags"("B");Query Engine Switch 🚂
Keystone now uses Prisma's Node-API Query Engine instead of the Binary Query Engine. This should improve the performance of operations using Prisma.
From our initial testing, performance has increased significantly when getting large amounts of data and is marginally better for smaller amounts.
See the Prisma docs for more details.
Node Engines 💽
Keystone officially supports running on LTS versions of Node.js - this is currently version 14 and 16. We've updated our engine values throughout the project to reflect this.
Note: We recommend you run Node.js
^14.15or^16.13for the best Keystone experience.
Miscellaneous Fixes ⚙️
-
Fixed the init/sign in page showing for a short amount of time after submitting on the init/sign in page and seeing a loading spinner.
-
Fixed clear button not removing inline relationships when used in the document field.
-
Relationship field now respects
ui.displayMode: 'cards'in the create view. -
The
Set as Authenticated Item/Add Authenticated Itembutton is now hidden if the relationship field already has the authenticated item. -
Fixed
ui.isAccessAllowednot being respected in the admin meta query when no session strategy was defined. -
The item page in the Admin UI no longer crashes when failing to fetch an item.
-
The admin meta query now bypasses
ui.isAccessAllowedfor sudo contexts. -
Fixed doing multiple writes at the same time on SQLite causing an timeout immediately.
Credits 💫
-
Thanks to gregpalaci, vicaia, jakegiri davebeauchemin, Temkit, and bkbooth for reporting bugs that were fixed in this release!
-
Fixed default renderer of
layoutblock in<DocumentRenderer />. Thanks @datner!
Like this release? Give us a star on GitHub!
Changelog
You can view the verbose changelog in the related PR (#6943) for this release.
✨ 15th November 2021
Expanded unique filters, customisable table and column names support and a new example featuring Nexus as we continue to finalise our GA release. 🪢
"@keystone-next/auth": "36.0.0",
"@keystone-next/cloudinary": "11.0.0",
"@keystone-next/fields-document": "13.0.0",
"@keystone-next/keystone": "28.0.0",
"@keystone-next/session-store-redis": "8.0.0",Like this release? Give us a star on GitHub!
Expanded Unique Filters 🔎
select, timestamp, float and decimal fields with isIndexed: 'unique' now have unique filters via ListWhereUniqueInput which text, integer and the id field already support.
For example, if you added isIndexed: 'unique' to a select field in a theoretical Settings list, you can now run the following query:
query {
setting ( where: { provider: "github" } ) {
id
token
}
}This is instead of running a settings query where you would have received a list back, and have had to check for results and get the first element:
query {
settings ( where: { provider: { equals: "github" } } ) {
id
token
}
}Customisable Table and Column Names 📇
You may now use different table and column names to those automatically chosen by Keystone for your list and field keys. This is powered by Prisma's @map and @@map attributes. You can read more about this concept in Prisma's documentation.
This is useful if you do not want to modify your existing database (such as a read-only database) and use it with Keystone.
For example if you wanted to refer to a table named stories but you refer to it in Keystone as Posts provide config.db.map to a list or field key such as:
Post: list({
db: {
map: 'stories',
},
fields: {
...
}
})
Nexus Example 🪢
We've got a new example using Nexus, a declarative, code-first and strongly typed GraphQL schema construction for TypeScript & JavaScript.
Using Nexus you can extend the GraphQL API provided by Keystone with custom queries and mutations.
In the example below we expose a mutation called nexusPosts which pulls out items from our Posts list that have been published within the past 7 days (by default), with an optional author filter.
export const PostQuery = extendType({
type: "Query",
definition(t) {
t.field("nexusPosts", {
type: nonNull(list("NexusPost")),
args: {
authorId: stringArg(),
days: nonNull(intArg({ default: 7 })),
},
async resolve(root, { authorId, days }, context) {
const cutoff = new Date(
new Date().setUTCDate(new Date().getUTCDate() - days)
).toISOString();
return await context.prisma.post.findMany({
where: {
...(authorId ? { author: { id: authorId } } : null),
publishDate: { gt: cutoff },
},
});
},
});
},
});Check out the example in Keystone's examples directory.
Miscellaneous Fixes ⚙️
- The format of the date shown in the
DatePickernow uses the user's locale. - When the
sessionDataoption is invalid, the error will now be thrown on startup instead of silently ignored.
Changelog
You can also the verbose changelog in the related PR (#6914) for this release.
⚙️ 10th November 2021
Patch release.
"@keystone-next/keystone": "27.0.2",Miscellaneous Fixes ⚙️
- Fixed importing packages that provide Node ESM
- Local images and files are no longer restricted behind
ui.isAccessAllowed - Updated Prisma monorepo to v3.4.0
Enjoying Keystone?
Star this repo 🌟 ☝️ or connect to Keystone on Twitter and in Slack.
Changelog
You can also view the verbose changelog in the related PR (#6892) for this release.
⚙️ 3rd November 2021
Patch release.
"@keystone-next/keystone": "27.0.1",Miscellaneous Fixes ⚙️
- Fixed files with names including things like [...rest] created using ui.getAdditionalFiles being deleted after being written in dev.
- Runtime type errors from Prisma are now actually returned instead of being returned as Prisma error:
- Fixed Schema must contain uniquely named types but contains multiple types named "OrderDirection". error when running keystone-next build.
Enjoying Keystone?
Star this repo 🌟 ☝️ or connect to Keystone on Twitter and in Slack.
Changelog
You can also view the verbose changelog in the related PR (#6871) for this release.
✨ 2nd November 2021
Server-side Live Reloading is here! 🚀 Plus more updates as we finalise the Keystone 6 GA release.
"keystone-next/auth": "35.0.0",
"keystone-next/cloudinary": "10.0.0",
"keystone-next/fields-document": "12.0.0",
"keystone-next/keystone": "27.0.0",
"keystone-next/session-store-redis": "7.0.0",Like this release? Give us a star on GitHub!
Warning:
⚠️ This release contains breaking changes, please see below!
Server-side Live Reloading 🚀
Keystone now supports live reloading with keystone-next dev.
You can now update your GraphQL schema, change your hooks and access control, log errors and see how your data returns, then immediately use the playground to test it and iterate.
This is in addition to the current support for live reloading changes to custom views in the Admin UI.
How it works
When you run keystone-next dev now, it will start watching for changes to your config and schema. When changes are detected, Keystone will reload your config and schema and hot-swap the GraphQL endpoint.
To balance performance and predictability, Keystone does not do a complete restart when changes are made. The things to know are:
Prisma Schema Changes
The Prisma Client is not reloaded as you make changes to the Keystone Schema. If you make changes that affect your Prisma schema, Keystone will exit the process and wait for you to run keystone-next dev again.
This is because making database schema changes involves generating database migrations, and can result in data loss if those migrations are automatically run against your current database.
When adding or removing lists and fields (except virtual fields), we recommend you finish making your changes then start the dev process again. This will generate a single migration for all the changes you’ve made, and interactively prompt you to resolve any migrations that can't be run safely.
onConnect is not hot reloaded
The db.onConnect function (if specified) will only be run once when Keystone is started, and not when your config is hot reloaded.
This is because onConnect is typically used to run data seeding and other once-off processes that should be executed once before the Keystone server comes online. Re-running it whenever a file is changed could result in a heavy database load, harming overall dev performance and introducing unpredictable behaviour.
If you make changes to the onConnect function, you need to manually stop the dev process and start it again for your changes to take effect.
GraphQL Playground and Apollo Sandbox 🏝
In the last release we upgraded to Apollo Server 3 which brought Apollo Sandbox as the default development UI for testing your GraphQL queries.
This surfaced a number of issues as Apollo Sandbox is hosted remotely rather than locally, including CORS issues and security concerns, making it a bad default.
With this in mind, Keystone will now go back to using the GraphQL Playground by default instead of Apollo Sandbox as it did prior to updating to Apollo Server 3.
We have now introduced the graphql.playground config option, with three possible settings:
truewill configure Apollo Server plugins to enable the GraphQL Playgroundfalsewill configure Apollo Server plugins to disable anyGETrequests to the GraphQL endpoint'apollo'will add no plugins to Apollo Server, enabling the new Apollo Sandbox behaviour
graphql.playground defaults to process.env.NODE_ENV !== 'production' which matches the previous Keystone 6 behaviour before the October update and Apollo Server 3.
Next.js Update ✨
We've updated our Next.js dependency from 11.x to 12.x! This latest release of Next.js includes a new Rust powered compiler with faster refresh and build rates, making your Keystone dev experience even faster.
Check out the Next.js blog for more details.
Relationship Filtering ❤️
If you have hundreds of items in your relationship fields, the Admin UI was sometimes displaying duplicate entries and/or missing entries.
We've made a series of improvements to fetching data resulting in a performance boost, as well as filtering fixes. We also changed the way we detect when an ID is pasted into the field allowing you to select a related item quickly.
CORS Configuration 🌐
We've removed the graphql.cors option, we had one too many ways to configure CORS and it was proving to be confusing.
You should now exclusively configure cors with the server.cors option.
Renamed src in Image and File Fields 🗄️
The src field on the output of image and file fields has been renamed to url.
Subsequently the getSrc function on ImagesContext and FilesContext has been renamed to getUrl.
Removed resolveFields 🚧
The deprecated resolveFields from context.query has been removed.
If you were still using it, you should switch to providing the query option to context.query or use context.db if you were providing false.
The context.query functions will now also throw an error if an empty string is passed to query rather than silently returning what the context.db functions return, you must select at least one field or omit the query option to default to selecting the id.
Internal Types Renamed ✏️
We have updated @graphql-ts/schema to 0.5.0.
The __rootVal properties on ObjectType, InterfaceType and UnionType have been renamed to __source, this is intended to be internal but you may have depended on it, if you were using it, rename __rootVal to __source.
In addition the fields property on InterfaceType has been renamed to __fields and it will no longer exist at runtime like the other types.
GraphQL Schema Reorder 🛗
We've made internal changes to the endSession field on the Mutation type and the keystone field on the Query type. This may result in re-ordering in your generated schema.graphql file.
Miscellaneous Fixes ⚙️
- The
sessionSchemaexport of@keystone-next/keystone/sessionhas been removed. context.sessionno longer has a value if the session is invalid.text,integer,floatanddecimalon the item view now render correctly when usingui.itemView.fieldMode: 'read'.- Admin UI home page now respects
ui.hideCreateand won't show a plus button when create is disabled. - Read-only arrays are now accepted where previously mutable arrays were required. Using
as constwhen writing an array and then passing it to various APIs in Keystone will now work. - Fixed bug in
LinkToRelatedItemsbutton for double sided relationships. - Updated minor typos in GraphQL errors.
Prisma Update 🗃
We've updated our Prisma dependency from 3.1.1 to 3.3.0!
Check out the Prisma releases page for more details.
Credits 💫
-
Added a short plain-text display to
documentfields in theListview as well as a rendered document view inCardValue. Thanks @oplik0! -
We now support extensions with numerical characters when generating safe filenames. Thanks @Zlitus!
Changelog
You can view the verbose change log in the related PR (#6762) for this release.
✨ 5th October 2021
We're nearly at Gold Master status for the Keystone 6 GA release! Here's what's new:
- Fields Overhaul with lots of tweaks and additions 🚀
- Hook Updates bringing consolidation and clearer naming 🪝
- Removal of unused return types and unused values 🚫
- Renaming of options for consistency 📛
- Apollo Server Upgrade to version 3 👩🚀
- Improved Error Messaging 📟
- Performance updates for a faster Admin UI 🏃♀️
- REST API Example using the new
createContextinsideextendExpressApp👩🏫 - Other Notable Changes to be aware of 🛎️
- Prisma Update from 2.x to 3.x 🗃
We've got further improvements to error messaging and performance to come in the next release!
Warning: This release contains breaking changes, please see below!
"@keystone-next/auth": "33.0.0",
"@keystone-next/cloudinary": "8.0.0",
"@keystone-next/fields-document": "10.0.0",
"@keystone-next/keystone": "26.0.1",
"@keystone-next/session-store-redis": "5.0.0",Upgrade Guide 👇
Be sure to read the entire release notes below for everything you need to know about this new release.
The main things to keep in mind are:
defaultValueconfig is now static, if you have dynamic defaults, use theresolveInputhookisRequiredfor fields is nowvalidation: { isRequired }and we have new validation options such asminandmaxfor some fields- We've made it clearer which fields are nullable in the database and tweaked the defaults, you now have more control but may need to migrate your database (more details below)
- The
hooksAPI has new arguments, and we've consolidated update and delete events intobeforeOperationandafterOperation context.listshas been renamed tocontext.query
Fields Overhaul 🚀
Keystone's field types have been given a big overhaul - including several breaking changes, read on to understand what has changed.
Warning: Some of these API changes are breaking and you will be required to update your project.
text
defaultValueis now a static valueisRequiredhas moved tovalidation.isRequired- Now requires that the value has a length of at least one
- New
validation.length.min,validation.length.maxandvalidation.matchoptions
float
defaultValueis now a static numberisRequiredhas moved tovalidation.isRequired- New
validation.minandvalidation.maxoptions
integer
defaultValueis now a static number or{ kind: 'autoincrement' }isRequiredhas moved tovalidation.isRequired- New
validation.minandvalidation.maxoptions
The autoIncrement field has also been removed, use the integer field with a defaultValue of { kind: 'autoincrement' }.
decimal
defaultValueis now a static number written as a stringisRequiredhas moved tovalidation.isRequired- Now requires the input isn't
NaN - New
validation.minandvalidation.maxoptions
timestamp
defaultValueis now a static date time value in an ISO8601 string or{ kind: 'now' }isRequiredhas moved tovalidation.isRequired
The field can also be automatically set to the current time on a create/update by setting db.updatedAt: true, this will add Prisma's @updatedAt attribute to the field.
The timestamp field also now uses a custom GraphQL scalar type named DateTime which requires inputs as full ISO8601 date-time strings such as "2021-01-30T00:00:00.000Z". Using new Date().toISOString() will give you a string in the correct format.
select
dataTypehas been renamed totypedefaultValueis now a static valueisRequiredhas moved tovalidation.isRequired
The select can now also be cleared in the Admin UI when ui.displayMode is segmented-control.
password
defaultValuehas been removedisRequiredhas moved tovalidation.isRequiredrejectCommonhas moved tovalidation.rejectCommonminLengthhas moved tovalidation.length.min- New
validation.length.maxandvalidation.matchoptions
validation.length.min also must be 1 or above, though it still defaults to 8.
If workFactor is outside of the range of 6 to 31, an error will now be thrown instead of the previous behaviour of clamping the value to 4 to 31 and warning if it's below 6.
image
- Removed
isRequired - Removed
defaultValue
If you were using these options, the same behaviour can be re-created with the validateInput and resolveInput hooks respectively.
file
- Removed
isRequired - Removed
defaultValue
If you were using these options, the same behaviour can be re-created with the validateInput and resolveInput hooks respectively.
cloudinaryImage
- Removed
isRequired - Removed
defaultValue
If you were using these options, the same behaviour can be re-created with the validateInput and resolveInput hooks respectively.
json
- Removed
isRequired defaultValuecan no longer be dynamic in thejsonfield
If you were using isRequired, the same behaviour can be re-created with the validateInput hook.
relationship
- Removed
defaultValue - Removed undocumented
withMetaoption
To re-create defaultValue, you can use resolveInput though note that if you're using autoincrement ids, you need to return the id as number, not a string like you would provide to GraphQL, e.g. { connect: { id: 1 } } rather than { connect: { id: "1" } }.
If you were using withMeta: false, please open an issue with your use case.
checkbox
The checkbox field is now non-nullable in the database, if you need three states, you should use the select field.
The field no longer accepts dynamic default values and it will default to false unless a different defaultValue is specified.
If you're using SQLite, Prisma will generate a migration that makes the column non-nullable and sets any rows that have null values to the defaultValue.
If you're using PostgreSQL, Prisma will generate a migration but you'll need to modify it if you have nulls in a checkbox field. Keystone will say that the migration cannot be executed:
✨ Starting Keystone
⭐️ Dev Server Ready on http://localhost:3000
✨ Generating GraphQL and Prisma schemas
✨ There has been a change to your Keystone schema that requires a migration
⚠️ We found changes that cannot be executed:
• Made the column `isAdmin` on table `User` required, but there are 1 existing NULL values.
✔ Name of migration … make-is-admin-non-null
✨ A migration has been created at migrations/20210906053141_make_is_admin_non_null
Please edit the migration and run keystone-next dev again to apply the migration
The generated migration will look like this:
/*
Warnings:
- Made the column `isAdmin` on table `User` required. This step will fail if there are existing NULL values in that column.
*/
-- AlterTable
ALTER TABLE "User" ALTER COLUMN "isAdmin" SET NOT NULL,
ALTER COLUMN "isAdmin" SET DEFAULT false;To make it set any null values to false in your database, you need to modify it so that it looks like this but with the table and column names replaced.
ALTER TABLE "User" ALTER COLUMN "isAdmin" SET DEFAULT false;
UPDATE "User" SET "isAdmin" = DEFAULT WHERE "isAdmin" IS NULL;
ALTER TABLE "User" ALTER COLUMN "isAdmin" SET NOT NULL;document
The document field is now non-nullable in the database. The field no longer has defaultValue or isRequired options.
The same behaviour can be re-created with the validateInput and resolveInput hooks respectively.
The field will default to [{ "type": "paragraph", "children": [{ "text": "" }] }]. The output type has also been renamed to ListKey_fieldKey_Document
If you're using SQLite, Prisma will generate a migration that makes the column non-nullable and sets any rows that have null values to an empty paragraph.
If you're using PostgreSQL, Prisma will generate a migration but you'll need to modify it if you have nulls in a document field.
Keystone will say that the migration cannot be executed:
✨ Starting Keystone
⭐️ Dev Server Ready on http://localhost:3000
✨ Generating GraphQL and Prisma schemas
✨ There has been a change to your Keystone schema that requires a migration
⚠️ We found changes that cannot be executed:
• Made the column `content` on table `Post` required, but there are 1 existing NULL values.
✔ Name of migration … make_document_field_non_null
✨ A migration has been created at migrations/20210915050920_make_document_field_non_null
Please edit the migration and run keystone-next dev again to apply the migration
The generated migration will look like this:
/*
Warnings:
- Made the column `content` on table `Post` required. This step will fail if there are existing NULL values in that column.
*/
-- AlterTable
ALTER TABLE "Post" ALTER COLUMN "content" SET NOT NULL,
ALTER COLUMN "content" SET DEFAULT E'[{"type":"paragraph","children":[{"text":""}]}]';To make it set any null values to an empty paragraph in your database, you need to modify it so that it looks like this but with the table and column names replaced.
ALTER TABLE "Post" ALTER COLUMN "content" SET DEFAULT E'[{"type":"paragraph","children":[{"text":""}]}]';
UPDATE "Post" SET "content" = DEFAULT WHERE "content" IS NULL;
ALTER TABLE "Post" ALTER COLUMN "content" SET NOT NULL;general
text, float, integer, decimal, timestamp, select, password can be made non-nullable at the database-level with the isNullable option which defaults to true, except for text which defaults to false.
All fields above except password can also have:
graphql.read.isNonNullset if the field has `...
✨ 6th September 2021
What's New
Big strides towards our General Availability release for Keystone 6 in the very near future⌛ this release includes:
- New & Improved Access Control API ✨
- Customisable Express App 🗺️
- Customisable GraphQL Paths 🚏
- Faster GraphQL API startups in local dev 🚀
- Next.js 11 upgrade for Admin UI ⚙️
- Apollo Server Introspection 🔎
- Omit GraphQL Operations 🚦
- And more...
"@keystone-next/admin-ui-utils": "6.0.0",
"@keystone-next/auth": "32.0.0",
"@keystone-next/cloudinary": "7.0.0",
"@keystone-next/fields": "15.0.0",
"@keystone-next/fields-document": "9.0.0",
"@keystone-next/keystone": "25.0.1",
"@keystone-next/session-store-redis": "4.0.0",
"@keystone-next/testing": "2.0.0",
"@keystone-next/types": "25.0.0",
"@keystone-next/utils": "2.0.0",New & Improved Access Control API ✨
Access Control is now easier to program, and makes it harder to introduce security gaps in your system:
- The static approach to access control has been replaced. Now access control never effects the operations in your GraphQL API.
- Keystone used to return an
access deniederror from a query if an item couldn't be found, or explicitly had access denied. The improved API never returns that error type on a query. - Access rules are now more explicit, and support fewer variations so you're less likely to introduce security gaps. They're also easier to read, write, and maintain.
How to upgrade
- Follow the instructions in our Access Control upgrade guide.
- Review our updated Access Control API docs.
💡 If you get stuck or have questions, reach out to us in the Keystone community slack to get the help you need.
Faster Startup 🚀
The GraphQL API endpoint now starts up significantly faster in development!
Often when you're working with the GraphQL API you'll be waiting around for it to start up, now you don't need to wait for the Admin UI to be ready before hitting the server. The process of creating of the Express Server + GraphQL API has been split from the Admin UI, which significantly speeds up boot time for the GraphQL API in development! 🎉
💡 To facilitate this,
createExpressServerno longer includes the step of creating the Admin UI Middleware, which changes its signature.createAdminUIMiddlewareis now also exported from@keystone-next/keystone/system.
Next.js 11 ⚙️
We've updated the underlying Next.js server that Keystone uses under the hood from version 10 to 11, which includes optimisations to improve cold startup time.
💡 If you've been using a custom Babel config, you'll need to remove this as it’s no longer supported in Next.js 11.
Omit GraphQL Operations 🚦
You can now add graphql.omit to list and field level configuration to control which types and operations are excluded from the GraphQL API. This option accepts either true, or an array of the values read, create, or update. If you specify true then the field will be excluded from all input and output types in the GraphQL API. If you provide an array of read, create, or update the field will be omitted from the corresponding input and output types in the GraphQL API.
User: list({
fields: {
name: text({
graphql: {
omit: ['read', 'create', 'update'],
}
}),
},
})
Customisable Express App 🗺️
A long awaited feature, the Express App that Keystone creates is now customisable with the new extendExpressApp option!
- Add your own custom server routes
- Host two apps on separate ports
- And more...
Check out the Server Config docs for more information.
Package Shuffle 💃
We've moved some packages around to make it easier for you to keep your project in sync with Keystone releases, in order to prevent mismatching versions of Keystone packages. The exports from the following packages now reside inside the @keystone-next/keystone/* package:
@keystone-next/admin-ui-utils
@keystone-next/fields
@keystone-next/testing
@keystone-next/types
@keystone-next/utils
For example if you had:
import {
relationship,
} from '@keystone-next/fields';
This is now:
import {
relationship,
} from '@keystone-next/keystone/fields';
💡 For any affected package, you'll need to change your import references and remove deprecated packages from your
package.jsonas they will no longer be updated.
Key Changes 🔑
isUnique now isIndex for unique fields 🗂
Unique fields marked as isUnique: true are now represented as isIndexed: 'unique'. This ensures that regular indexes and unique indexes aren't enabled at the same time.
isIndexed accepts the following options as per the Fields API docs -
- If
truethen the field will be indexed by the database. - If
'unique'then all values of the field must be unique.
fieldPath now fieldKey for field hooks 🪝
The fieldPath argument to field hooks has been renamed to fieldKey. This makes the naming consistent with the Access Control APIs.
schema now graphql for virtual and custom fields 🥽
If you've using Virtual fields or custom field types, or if constructing GraphQL types, we used to export schema, this has been changed to graphql.
Disabled filtering and ordering (by default) 🙅♀️
Filtering and ordering is no longer enabled by default, as they have the potential to expose data which would otherwise be protected by access control. To enable filtering and ordering you can set isFilterable: true and isOrderable: true on specific fields, or set defaultIsFilterable: true and defaultIsOrderable: true at the list level.
Check out our Fields API docs for all field level options.
Introspection 🔎
You can now enable introspection in the Apollo Server config. Introspection enables you to query a GraphQL server for information about the underlying schema. Check out the GraphQL Config docs for more information.
GraphQL Path Customisation 🚏
The GraphQL endpoint accessible by default at /api/graphql can now be customised with the new option config.graphql.path. You can find this and all other options in our GraphQL API docs.
Admin UI Improvements 🛠️
The Navigation component has been updated to show docs and playground links irrespective of authentication. The triple-dot menu is now available in the Admin UI even if authentication isn't being used.
Additionally, performance has been improved of the create item modal when many fields are configured. Thanks to Sam Lam for the heads up!
Prisma Update ⬆️
Updated Prisma dependencies from 2.29.0 to 2.30.2, check out the Prisma releases page for more details.
Credits 💫
- Fixed an issue in the Relationship field when using display mode
count, thanks to @gautamsi! - Sam Lam for alerting us to performance issues with Admin UI create item modal.
Enjoying Keystone?
Star this repo 🌟 ☝️ or connect to Keystone on Twitter and in Slack.
View verbose release notes
Releases
@keystone-next/[email protected]
Major Changes
- #6367
4f36a81afThanks @mitchellhamilton! - Moved@keystone-next/admin-ui-utilsto@keystone-next/keystone/admin-ui/utils
@keystone-next/[email protected]
Major Changes
-
#6371
44f2ef60eThanks @mitchellhamilton! - Moved@keystone-next/typesto@keystone-next/keystone/types -
#6367
4f36a81afThanks @mitchellhamilton! - Moved@keystone-next/admin-ui-utilsto@keystone-next/keystone/admin-ui/utils
Patch Changes
-
#6414
32f024738Thanks @mitchellhamilton! - Updated usages ofjsxfrom@keystone-ui/coreto explicitly use/** @jsxRuntime classic */ -
#6437
af5e59bf4Thanks @mitchellhamilton! - ChangedisUnique: trueconfig in fields toisIndexed: 'unique' -
#6414 [
32f024738](https://github.com/keystonejs/keystone/commit...

