Search code examples
strapihasurasanityheadless-cms

Is there a way to get a structure of a Strapi CMS Content Type?


A content-type "Product" having the following fields:

  • string title
  • int qty
  • string description
  • double price

Is there an API endpoint to retrieve the structure or schema of the "Product" content-type as opposed to getting the values?

For example: On endpoint localhost:1337/products, and response can be like:

[
  {
    field: "title",
    type: "string",
    other: "col-xs-12, col-5"
  },
  {
    field: "qty",
    type: "int"
  }, 
  {
    field: "description",
    type: "string"
  },
  {
    field: "price",
    type: "double"
  }
]

where the structure of the schema or the table is sent instead of the actual values?

If not in Strapi CMS, is this possible on other headless CMS such as Hasura and Sanity?


Solution

  • You need to use Models, from the link:
    Link is dead -> New link

    Models are a representation of the database's structure. They are split into two separate files. A JavaScript file that contains the model options (e.g: lifecycle hooks), and a JSON file that represents the data structure stored in the database.

    This is exactly what you are after.
    The way I GET this info is by adding a custom endpoint - check my answers here for how to do this - https://stackoverflow.com/a/63283807/5064324 & https://stackoverflow.com/a/62634233/5064324.

    For handlers you can do something like:

    async getProductModel(ctx) {
      return strapi.models['product'].allAttributes;
    }
    

    I needed the solution for all Content Types so I made a plugin with /modelStructure/* endpoints where you can supply the model name and then pass to a handler:

    //more generic wrapper
    async getModel(ctx) {
      const { model } = ctx.params;
      let data = strapi.models[model].allAttributes;
      return data;
    },
    async getProductModel(ctx) {
      ctx.params['model'] = "product"
      return  this.getModel(ctx)
    },
    
    //define all endpoints you need, like maybe a Page content type
    async getPageModel(ctx) {
      ctx.params['model'] = "page"
      return  this.getModel(ctx)
    },
    
    //finally I ended up writing a `allModels` handler
    async getAllModels(ctx) {
      Object.keys(strapi.models).forEach(key => {
           //iterate through all models
           //possibly filter some models
           //iterate through all fields
           Object.keys(strapi.models[key].allAttributes).forEach(fieldKey => {
               //build the response - iterate through models and all their fields
           }
       }
       //return your desired custom response
    } 
    

    Comments & questions welcome