derelektrischemoench
derelektrischemoench

Reputation: 403

Strapi v5 overriding controller action deletes other default actions

I've got a weird issue here, I overrode the find() action inside of a custom controller in strapi v5 like this:

'use strict';

/**
 * team controller
 */

const {createCoreController} = require('@strapi/strapi').factories;

module.exports = createCoreController('api::team.team', ({strapi}) => ({
  async create(ctx) {
    try {
      const user = ctx.state.user;

      if (!user) {
        return ctx.unauthorized('You must be logged in to create a team');
      }

      const teamData = {
        ...ctx.request.body.data,
        user: user.id
      }

      const team = await strapi.entityService.create('api::team.team', {
        data: teamData,
      });

      return ctx.created(team);
    } catch (error) {
      throw ctx.throw(500, error);
    }
  },

  async findOne(ctx) {
    const {data, meta} = await super.findOne(ctx);
    return {data, meta};
  }
}));

Unfortunately this seems to remove all other controller actions like findOne() from the controller entirely. How can I fix this?

Thanks in advance for any useful input.

Upvotes: 0

Views: 20

Answers (1)

derelektrischemoench
derelektrischemoench

Reputation: 403

Well... after some researching I figured it out. Basically I required the controller and bound routes for all of the instance methods (i.e. create(), update() etc.). The controller looks like this:

const {createCoreController} = require('@strapi/strapi').factories;

module.exports = createCoreController('api::team.team', ({strapi}) => ({
  async create(ctx) {
    try {
      const user = ctx.state.user;

      if (!user) {
        return ctx.unauthorized('You must be logged in to create a team');
      }

      const teamData = {
        ...ctx.request.body.data,
        user: user.id
      }

      const team = await strapi.entityService.create('api::team.team', {
        data: teamData,
      });

      return ctx.created(team);
    } catch (error) {
      throw ctx.throw(500, error);
    }
  }
}));

When this was done I bound the create round in my routes.js file:

module.exports = {
  routes: [
    {
      method: 'POST',
      path: '/create-team/submit',
      handler: 'team.create',
      config: {
        policies: [],
        middlewares: [],
      },
    },
}

Unfortunately overriding just one route deletes all other bound methods (i.e. find(), findOne() etc. This means that they all have to be set manually like this in routes/apiName.js

module.exports = {
  routes: [
    {
      method: 'POST',
      path: '/create-team/submit',
      handler: 'team.create',
      config: {
        policies: [],
        middlewares: [],
      },
    },
    {
      method: 'GET',
      path: '/teams',
      handler: 'team.find',
      config: {
        policies: [],
        middlewares: [],
      },
    },
    {
      method: 'GET',
      path: '/teams/:id',
      handler: 'team.findOne',
      config: {
        policies: [],
        middlewares: [],
      },
    },
    {
      method: 'PUT',
      path: '/teams/:id',
      handler: 'team.update',
      config: {
        policies: [],
        middlewares: [],
      },
    },
    {
      method: 'DELETE',
      path: '/teams/:id',
      handler: 'team.delete',
      config: {
        policies: [],
        middlewares: [],
      },
    },
  ],
};

And that was basically it. All the endpoints for CRUD operations work fine and the custom controller is called for the create() method.

Having to manually set all the bound routes seems kind of fishy to me, but at least it works. If someone finds a more elegant solution to this, I'd be very interested to see what that would look like.

Upvotes: 0

Related Questions