Entity Service API to Document Service API migration reference
In Strapi 5, the Document Service API replaces the Entity Service API from Strapi v4 (see breaking change description).
The present page is intended to give developers an idea of how to migrate away from the Entity Service API, by describing which changes in custom code will be handled by codemods from the upgrade tool and which will have to be handled manually.
Migration using the upgrade tool
When using the upgrade tool, a codemod is run and handles some parts of the entityService
migration.
The codemod is only changing the function calls and some parameters. This can not be considered as a complete migration as the codemod will never be able to convert an entityId
into a documentId
.
Codemod scope
The following list explains what is automatically handled by the codemod (✅), what is not handled by the codemod and must be handled 100% manually (❌) and what will still require manual intervention after the codemod has run (🚧):
Topic | Handled by the codemod? | Manual steps to perform |
---|---|---|
Code structure | ✅ Yes | Nothing. The code structure is automatically migrated. |
publicationState removed in favor of status | ✅ Yes | Nothing. The codemod automatically transforms it. |
Usage of documentId instead of the Strapi v4 unique identifiers | 🚧 Partially:
| 👉 __TODO__ placeholder values need to be manually updated.For instance, you might change documentId: "__TODO__" to something like documentId: "ln1gkzs6ojl9d707xn6v86mw" . |
Update of published_at to trigger publication | ❌ Not handled. | 👉 Update your code to use the new publish() , unpublish() , and discardDraft() methods of the Document Service API instead. |
Examples of function calls migration
The following examples show how the codemod from the upgrade tool updates the code for various function calls.
findOne
Before:
strapi.entityService.findOne(uid, entityId);
After:
strapi.documents(uid).findOne({
documentId: "__TODO__"
});
findMany
Before:
strapi.entityService.findMany(uid, {
fields: ["id", "name", "description"],
populate: ["author", "comments"],
publicationState: "preview",
});
After:
strapi.documents(uid).findMany({
fields: ["id", "name", "description"],
populate: ["author", "comments"],
status: "draft",
});
create
Before:
strapi.entityService.create(uid, {
data: {
name: "John Doe",
age: 30,
},
});
After:
strapi.documents(uid).create({
data: {
name: "John Doe",
age: 30,
},
});
update
Before:
strapi.entityService.update(uid, entityId, {
data: {
name: "John Doe",
age: 30,
}
});
After:
strapi.documents(uid).update({
documentId: "__TODO__",
data: {
name: "John Doe",
age: 30,
}
});
delete
Before:
strapi.entityService.delete(uid, entityId);
After:
strapi.documents(uid).delete({
documentId: "__TODO__"
});
count
Before:
strapi.entityService.count(uid);
After:
strapi.documents(uid).count();
Manual migration
-
Users who prefer to manually migrate can do so by replicating what the codemod does (see codemod scope and function calls examples for reference).
-
Plugin developers who use Entity Service decorators in their code must replace them by Document Service middlewares. The following example gives you an idea of how they work, and additional information can be found in the dedicated Document Service middlewares documentation:
In Strapi v4:
strapi.entityService.decorate((service) => {
return Object.assign(service, {
findOne(entityId, params = {}) {
// e.g., exclude soft deleted content
params.filters = { ...params.filters, deletedAt: { $notNull: true } }
return service.findOne(entityId, params)
}
});
})In Strapi 5
strapi.documents.use((ctx, next) => {
if (ctx.uid !== "api::my-content-type.my-content-type") {
return next();
}
if (ctx.action === 'findOne') {
// customization
ctx.params.filters = { ...params.filters, deletedAt: { $notNull: true