I’m currently learning strapi and digging through a lot of tutorial material. I encountered the same issue with this.transformResponse, and also with this.santizeOutput (this at v 4.2.7). When I look at how I had created the custom controller, it looks like a problem with “this”.
The first way I tried, via copy paste from several tutorials and applying workarounds found on SO to deal with the problem functions.
'use strict';
const utils = require("@strapi/utils");
const {sanitize} = utils;
const sanitizeOutput = (data, ctx) => {
const schema = strapi.getModel('api::event.event');
const {auth} = ctx.state;
return sanitize.contentAPI.output(data, schema ,{auth});
};
/**
* event controller
*/
const {createCoreController} = require('@strapi/strapi').factories;
module.exports = createCoreController('api::event.event', ({strapi}) => ({
me: async (ctx, next) => {
const user = ctx.state.user
console.log(this)
if (!user) {
return ctx.badRequest(null, [{messages: [{id: "No auth header found"}]}])
}
const data = await strapi.entityService.findMany("api::event.event", {
populate: 'image',
filters: {
"users_permissions_user": {
"id": user.id
}
},
});
if (!data) {
return ctx.notFound();
}
const sanitizedEvents = sanitizeOutput(data, ctx);
return (sanitizedEvents);
}
}));
Note how the object is returned via me: property. Within the above if you log “this” its an empty object. Also even though you get your data, and can santize it, it’s not in the same shape as you get from the standard collection controllers. no data or meta, just an array of your data.
After a bit more digging and some experiments if I rewrite the above to return the object in a different way we get this as expected, and can access transformResponse and santizeOutput as shown in lots of reference code.
The way that works as expected. Left the above in but commented out in case it’s useful to compare.
'use strict';
// const utils = require("@strapi/utils");
// const {sanitize} = utils;
//
// const sanitizeOutput = (data, ctx) => {
// const schema = strapi.getModel('api::event.event');
// const {auth} = ctx.state;
// return sanitize.contentAPI.output(data, schema ,{auth});
// };
/**
* event controller
*/
const {createCoreController} = require('@strapi/strapi').factories;
// module.exports = createCoreController('api::event.event', ({strapi}) => ({
// me: async (ctx, next) => {
// const user = ctx.state.user
// console.log(this)
// if (!user) {
// return ctx.badRequest(null, [{messages: [{id: "No auth header found"}]}])
// }
//
// const data = await strapi.entityService.findMany("api::event.event", {
// populate: 'image',
// filters: {
// "users_permissions_user": {
// "id": user.id
// }
// },
//
// });
//
// if (!data) {
// return ctx.notFound();
// }
//
// const sanitizedEvents = sanitizeOutput(data, ctx);
//
// return (sanitizedEvents);
// }
// }));
module.exports = createCoreController("api::event.event", ({strapi}) => ({
async me(ctx, next) {
const user = ctx.state.user
console.log(this)
if (!user) {
return ctx.badRequest(null, [{messages: [{id: "No auth header found"}]}])
}
const data = await strapi.entityService.findMany("api::event.event", {
populate: 'image',
filters: {
"users_permissions_user": {
"id": user.id
}
},
});
console.log(data);
if (!data) {
return ctx.notFound();
}
const sanitizedEvents = await this.sanitizeOutput(data, ctx);
return this.transformResponse(sanitizedEvents);
}
}));
when doing it the above way this is logged populated rather than an empty object and the issues resolving this.santizeOutput and this.transformResponse go away
{
me: [AsyncFunction: me] { [Symbol(__type__)]: [ 'content-api' ] },
find: [AsyncFunction: find] { [Symbol(__type__)]: [ 'content-api' ] },
findOne: [AsyncFunction: findOne] { [Symbol(__type__)]: [ 'content-api' ] },
create: [AsyncFunction: create] { [Symbol(__type__)]: [ 'content-api' ] },
update: [AsyncFunction: update] { [Symbol(__type__)]: [ 'content-api' ] },
delete: [AsyncFunction: delete] { [Symbol(__type__)]: [ 'content-api' ] }
}
Hopefully that helps someone.