Upgrade Guide: 0.3 to 4.0
Changes to express application and mounting
WIP
The mounting process has been rewritten for modularity and clarity. This
may introduce some breaking changes if your app has been attaching the
Keystone Admin UI to a nonstandard express app (i.e. not using
Keystone.start(), but should make things simpler going forward.
Changed
keystone.get('express session')has been replaced bykeystone.expressSession- Session initialisation middleware is now executed before the body parser to allow for the Admin UI to include its own bodyParser implementation
- IP Restrictions middleware is now processed first, which means that static assets will now respect restrictions (previously this only restricted routes)
keystone.routes(fn)has been replaced bykeystone.set('routes', fn)-
the
routesoption supports both:- the legacy
function (app) {}way of adding routes to the root express app - an
express.Routerinstance
- the legacy
Removed
keystone.statichas been removed (replacement TBA, seeadmin/server)keystone.mounthas been removed (replaced by more granular methods, seeadmin/server)keystone.bindEmailTestRoutesandkeystone.set('email tests')support (was this actually being used by anyone? let me know - @jedwatson)keystone.set('email rules')option has been removed; you should just use variables in your templates, rather than globally applied regular expressions.- The
Types.CloudinaryImageoptionpublicID: 'slug'option has been removed. It has been replaced by the generateFilename function. Documentation for the new option can be found infields/types/cloudinaryimage
UpdateHandler Changes
The UpdateHandler functionality has been completely rewritten to use the
new, generic List.updateItem method. While we have tried to preserve
backwards compatibility, there may be minor differences in functionality
and the format of messages returned.
The structure of error detail passed to the callback has changed, and now matches the new API error format (see the API Spec)
If you are using the UpdateHandler please test your application comprehensively when upgrading to 0.4 and report any problems you find in the issues.
Specific changes include:
- The
callbackfunction now receives a single error argument options.validationMethodsis no longer supported, please apply any custom validation before callingupdateHandler.process()options.errorMessagesis no longer supported, as fields may now return different error conditions and replacing specific error detail with a simple string has the potential to be misleading and frustrating for users. If you want to show custom messages, please handle this on a case-by-case basis in your application.
The flashErrors option now supports the following values:
truesend all error messages toreq.flash"validation"only send validation error messages toreq.flash"update"only send update errors toreq.flash
File handling Field Types
New File field type
The new File field type, with the FS, S3 and Azure storage
adapters, replace the following field types (which are removed in 0.4) -
azureFilelocalFilelocalFiless3File
For usage instructions, see:
For the full upgrade guide for File fields, see File-Fields-Upgrade-Guide in the KeystoneJS Wiki.
CloudinaryImage
The _upload suffix is no longer required or supported when uploading
files from an html form. Now simply provide the cloudinary field path as
the name of file upload fields. For example:
<!-- old -->
<input type="file" name="picture_upload" />
<!-- new -->
<input type="file" name="picture" />
CloudinaryImages
When the cloudinary folders keystone option is set, in 0.3.x
CloudinaryImages fields would incorrectly use the cloudinary prefix
option’s value as the first part of the folder path for fields that did
not specify the folder option. This has been fixed; the folder for
uploaded images now defaults to this.list.path + '/' + this.path
Explicit support for actions with paths.action (i.e. submitting a
fieldPath_action value) has been removed. To remove images from the
value, submit the new value for the field without the removed image
present.
The CloudinaryImages field no longer supports deleting removed images from Cloudinary, this may be restored in a subsequent version.
Reordering images with paths.order (i.e. submitting a
fieldPath_order value) has also been removed. To sort images, submit
the full array of values in the correct order.
Field API Changes
-
updateItem is now asynchronous and need to pass a callback:
- Before:
field.updateItem(item, data) - After:
field.updateItem(item, data, function(err) {...})
- Before:
Location fields
The geocodeGoogle option has been renamed to enableImprove.
Mongoose 4
The bundled version of Mongoose has been updated from 3.x to 4.x. Please review the Migration Guide and Release Notes for more information.
Keystone.Email
Keystone.Email was completely rewritten as the standalone, well-tested
keystone-email module, and requires it to be installed to work.
Changed
new Emailnow accepts a second argument as the options (e.g. to set the transport)
new Email('templatepath.ext', { transport: 'mailgun' });
- The template locals are now passed in as the first, the options for
send as the second and the callback as the third argument to
.send
new Email('templatepath.ext', { transport: 'mailgun' })
.send(templateLocals, sendOptions, callback);
Removed
These options, APIs or behaviours were removed with the rewrite to an external module.
- We no longer assume
email.jadeas the default filename, you now have to pass an entire filename to or set theenginein the.Emailcall
Deprecated
All of these deprecations will continue to work throughout v4.x,
though warnings will be added in a future minor release. We highly
encourage moving to the new APIs as soon as possible, your apps will
break in v5 otherwise!
keystone.set('email')has been deprecated in favor of therootoption (passed to the.Emailcall)- The
templateExtoption was deprecated in favor of theengineoption keystone.set('transport')has been deprecated in favor of settingtransportin thenew Email()optionskeystone.set('mailgun api key')andkeystone.set('mailgun domain')have been deprecated in favor of passing theapiKeyanddomainoption to the send options in.send
CSV Download
Keystone 0.3 had a feature where you could specify a custom toCSV
method on a list schema to control which values were included in the
CSV.
As the CSV Export has been completely rewritten and now supports the
same filter and fields options that the List view in the Admin UI does
(including being able to specify which fields are included in the CSV
from the Admin UI), the toCSV method has been replaced by a new
getCSVData method:
User.schema.methods.getCSVData = function (data, options) {
return {
password: undefined,
custom: { complex: true },
};
};
Values returned by this method will be added to the CSV regardless of
the fields specified to be included. You have access to the fields in
options.fields. Additionally, you can set values to undefined to
remove them from the csv if they were included.
The current User, if there is one, is provided in options.user.
New Features
toCSV method on Fields
You can now also specify a per-field toCSV transform. Provide a
function to return a custom value for the field if it is specified in
options.fields:
User.add({
email: { type: Types.Email, toCSV: function (field, options) {
return this.id === options.user.id ? 'Your email address' : this.email;
}}
})
The this scope will be the document being serialised to CSV format.
The field argument is the field definition, and the options argument
contains the options passed to getCSVData (see above).
For field types that store an object, you can instead provide a list or array of keys to include in the CSV data:
User.add({
address: { type: Types.Location, toCSV: 'suburb, postcode' }
})
Automatic flattening of complex values
Objects will be flattened to multiple columns, with each key being appended to the field path using camelCase.
So, for example, the following data from a File field with the path
attachment:
{
id: '56dd3f1a51cb31100cf08457',
attachment: {
filename: 'photo.jpg',
size: 83452
}
}
Will be added to the CSV in two columns:
id,attachmentFilename,attachmentFilesize
56dd3f1a51cb31100cf08457,photo.jpg,83452
Removed Options
The csv expanded keystone option has been deprecated. Relationship
fields will always be expanded into fieldName, fieldId columns by
default.
Changed Dependencies
Breaking Fixes
Relationship Field Updates
Relationship fields had a bug in 0.3.x and 4.0.0 betas pre-beta.6 where undefined values passed to List.updateItem would be persisted to the database for { many: true } fields.
This has been fixed, so that incoming undefined values are ignored, which is consistent with all other field types except Boolean.
Jade
Keystone 3 included jade as a dependency; this meant your project may
have been able to use jade as the view engine without depending on it
explicitly. Jade has now been removed from Keystone, so if you’re using
it you will need to explicitly add it to your package.json.
Underscore
Keystone 3 included underscore as a dependency; this was utilised by
the generator, which should have added an explicit dependency when
generating package.json files. Unfortunately it didn’t, which means
your project may expect underscore to be available and it won’t be.
If you get the following error when starting a project with keystone 4:
Error: Cannot find module 'underscore'
Run the following command in your project’s root folder to resolve it:
npm install --save underscore