# apostrophe-migrations
# Inherits from: apostrophe-module
# apos.migrations
Provide services for database migration. The apostrophe-migrations:migrate
task
carries out all migrations that have been registered with this module. Migrations
are used to make changes to the database at the time of a new code deployment,
typically because we need to represent the data in a different way or correct
errors.
Migrations MUST be idempotent (it must be safe to run them twice). Apostrophe does remember whether they have been run before in a cache but there is NO guarantee that they will not run again when the cache is cleared. If this is difficult to guarantee, you may wish to write a task instead.
# Methods
# add(name, fn, options) [api]
Add a migration function to be invoked when the apostrophe-migrations:migrate task is invoked.
The function is invoked with a callback. If it returns a promise, the promise is awaited, and the function should not also invoke the callback. However for bc this situation is tolerated.
The options argument may be omitted. If options.safe is true, this migration will still be run when the --safe option is passed to the task. ONLY SET THIS OPTION IF THE CALLBACK HAS NO NEGATIVE IMPACT ON A RUNNING, LIVE SITE. But if you can mark a migration safe, do it, because it minimizes downtime when deploying.
# eachDoc(criteria, limit, iterator, callback) [api]
Invoke the iterator function once for each doc in the aposDocs collection.
If only three arguments are given, limit
is assumed to be 1 (only one
doc may be processed at a time).
The iterator is passed a document and a callback. If the iterator returns a promise, it is awaited, and must NOT invoke the callback.
This method will never visit the same doc twice in a single call, even if modifications are made.
THIS API IS FOR MIGRATION AND TASK USE ONLY AND HAS NO SECURITY
This method returns a promise if no callback is supplied.
# each(collection, criteria, limit, iterator, callback) [api]
Invoke the iterator function once for each document in the given collection.
If limit
is omitted, limit
is assumed to be 1 (only one
doc may be processed at a time).
This method will never visit the same document twice in a single call, even if modifications are made.
THIS API IS FOR MIGRATION AND TASK USE ONLY AND HAS NO SECURITY.
The iterator is passed a document and a callback. If the iterator accepts only one parameter, it is assumed to return a promise, which is awaited in lieu of a callback.
If it is determined that node is running in an interactive terminal
and will run for enough time, a simple plaintext progress display
is shown. If this is not desired, the progressDisplay
option
of this module may be set to false
.
# progressStart(options) [api]
Start CLI progress meter. Takes an options
object which must
have a getTotal
callback function that obtains the
total number of steps from you. If that function returns a promise,
its value is awaited, otherwise it must invoke its callback with
(null, total)
. This function only gets called if a progress meter
will actually be displayed. We do it this way to avoid wasting time
calculating totals in contexts where the progress meter would be
nested or there is no TTY to display it on.
Returns a meter object with message
, step
and end
methods. message
displays a message, step
takes an
optional number of steps to update the progress meter (defaults to 1),
and end
terminates the progress meter. You must call end
.
If there is no TTY (such as in a pipeline deployment script), the progress meter object displays nothing. If you create a meter while another meter is already active, the nested progress meter object displays nothing.
If the operation takes less than a second to complete the
progress meter is never shown and getTotal
is never invoked.
If you have messages that should ALWAYS be output, output
them yourself.
# progressAppropriate() [api]
# eachArea(criteria, limit, iterator, callback) [api]
Invoke the iterator function once for each area in each doc in
the aposDocs collection. The iterator
function receives
(doc, area, dotPath, callback)
. criteria
may be used to limit
the docs for which this is done.
If only three arguments are given, limit
is assumed to be 1 (only one
doc may be processed at a time).
This method will never visit the same doc twice in a single call, even if modifications are made.
If callback
is omitted, a promise is returned.
If the iterator accepts only four parameters, it is assumed to return a promise. The promise is awaited, and the iterator must NOT invoke its callback.
THIS API IS FOR MIGRATION AND TASK USE ONLY AND HAS NO SECURITY.
YOUR ITERATOR MUST BE ASYNCHRONOUS.
# eachWidget(criteria, limit, iterator, callback) [api]
Invoke the iterator function once for each widget in each area in each doc in the aposDocs collection.
If only three arguments are given, limit
is assumed to be 1 (only one
doc may be processed at a time).
The iterator
function receives (doc, widget, dotPath, callback)
.
criteria
may be used to limit
the docs for which this is done. If the iterator accepts exactly
three arguments, it is assumed to return a promise, and the iterator
must NOT invoke the callback.
This method will never visit the same doc twice in a single call, even if modifications are made.
Widget loaders are NOT called.
If callback
is omitted, a promise is returned.
THIS API IS FOR MIGRATION AND TASK USE ONLY AND HAS NO SECURITY.
YOUR ITERATOR MUST BE ASYNCHRONOUS.
# addSortify(migrationNamePrefix, criteria, field) [api]
Most of the time, this is called automatically for you. Any
doc type schema field marked with sortify: true
automatically
gets a migration implemented via this method. Don't forget
to run the apostrophe-migration:migrate
task.
Adds a migration that takes the given field, such as lastName
, and
creates a parallel lastNameSortified
field, formatted with
apos.utils.sortify
so that it sorts and compares in a more
intuitive, case-insensitive way.
The migration applies only to documents that match criteria
.
After adding such a migration, you can add sortify: true
to the
schema field declaration for field
, and any calls to
the sort()
cursor filter for lastName
will automatically
use lastNameSortified
. You can also do that explicitly of course.
Note that you want to do both things (add the migration, and
add sortify: true
) because sortify: true
guarantees that
lastNameSortified
gets updated on all saves of the doc.
migrationNamePrefix
just helps uniquely identify this
migration, since different modules might contribute migrations
for fields of the same name.
# enableCache() [implementation]
Legacy cache of migrations performed
# enableCollection(callback) [implementation]
How we now track migrations performed: a mongodb collection (persistent)