For anyone wishing to populate all attributes (à la Strapi v3) with ?populate=*
, here’s a merge of the solutions provided by @thylo, @JayTee, and myself.
src/helpers/populate.js
/*********************************
* Poplulate All Attributes
*
* https://forum.strapi.io/t/strapi-v4-populate-media-and-dynamiczones-from-components/12670/2
*
*********************************/
const { createCoreController } = require('@strapi/strapi/lib/factories')
const populateAttribute = ({ components }) => {
if (components) {
const populate = components.reduce((currentValue, current) => {
const [componentDir, componentName] = current.split('.')
/* Component attributes needs to be explicitly populated */
const componentAttributes = Object.entries(
require(`../components/${componentDir}/${componentName}.json`)
.attributes
).filter(([, v]) => v.type === 'component')
const attrPopulates = componentAttributes.reduce(
(acc, [curr]) => ({ ...acc, [curr]: { populate: '*' } }),
{}
)
return {
...currentValue,
[current.split('.').pop()]: { populate: '*' },
...attrPopulates,
}
}, {})
return { populate }
}
return { populate: '*' }
}
const getPopulateFromSchema = function (schema) {
// console.log('schema', schema)
return Object.keys(schema.attributes).reduce((currentValue, current) => {
const attribute = schema.attributes[current]
if (!['dynamiczone', 'component'].includes(attribute.type)) {
return { [current]: populateAttribute(attribute) }
}
return {
...currentValue,
[current]: populateAttribute(attribute),
}
}, {})
}
function createPopulatedController(uid, schema) {
return createCoreController(uid, () => {
// console.log(schema.collectionName, getPopulateFromSchema(schema))
return {
async find(ctx) {
// deeply populate all attributes with ?populate=*, else retain vanilla functionality
if (ctx.query.populate === '*') {
ctx.query = {
...ctx.query,
populate: getPopulateFromSchema(schema),
}
}
return await super.find(ctx)
},
async findOne(ctx) {
if (ctx.query.populate === '*') {
ctx.query = {
...ctx.query,
populate: getPopulateFromSchema(schema),
}
}
return await super.findOne(ctx)
},
}
})
}
module.exports = createPopulatedController
src/api/homepage/controllers/homepage.js
"use strict";
/**
* homepage controller
*/
const collectionType = 'homepage'
const schema = require(`../content-types/${collectionType}/schema.json`);
const createPopulatedController = require("../../../helpers/populate");
module.exports = createPopulatedController(`api::${collectionType}.${collectionType}`, schema);