Hi Riley,
the reason we went with the design decision to not ship with something like createContentTypeIfNotExists
was that we wanted to preserve intent as much as possible
and to make all content model migrations as explicit as possible.
We validate - even before running a single step - for every step of the migration whether it can be done and will not cause any inconsistencies.
This becomes quite difficult once createIfNotExists
is implemented.
For example given a migration like:
const foo = createContentTypeIfNotExists('foo')
foo.description('It is a foo')
foo.name('Foo')
foo.createField('bar').type('Symbol').name('a bar')
What should happen if foo
exists, but its description is not It is a foo
?
We would have to add a createOrUpdateContentType
method too, and the same for the fields.
At that point we might even have to start diffing all the contents to see what we should apply and what not.
It gets very difficult to actually see what the expressed intent of that migration is, and so also as a developer,
you cannot be sure about the outcome.
For that reason, we designed this tool with a workflow in mind where a set of spaces is evolved only via these migrations
and where every migration would be applied in sequence and only once.
If you were to accidentally apply an old migration, it would quickly catch it and inform you about your error.
That is a safety net that you would not have with createOrUpdate
operations, which could basically always be applied.
What we are indeed lacking at the moment is the tooling to automatically keep track of the migrations that have been run already
so that applying the right migrations in sequence to sync up two spaces can be done in a fully automated way,
but we are looking into supporting these sort of workflows.
Lastly, if you still would like to make use of createIfNotExists
and others, there is a way to implement it yourself.
We do not have try/catch available because we first process the migration script into a set of intents,
validate them and only then proceed with building payloads and sending them out to the API, so at the time you write createContentType
,
no actual creation is happening yet.
However, we do support creating the migration script asynchronously and our migration files are actually pure node modules so you could do something like:
const createContentTypeIfNotExists = async function (migration, contentTypeId) {
// Assuming you have the SDK required and set up
const contentType = await contentfulSDK.getContentType(contentTypeId)
if (contentType) {
return migration.editContentType(contentTypeId)
} else {
return migration.createContentType(contentTypeId)
}
}
module.exports = async function (migration) {
const contentType = await createContentTypeIfNotExists(migration, 'foo')
contentType.description('It is a foo')
}
That way you can dynamically build the migration script you need.