npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@fourlights/strapi-plugin-deep-populate

v1.13.0

Published

This plugin provides a simple way of retrieving all nested objects in a single request.

Readme

Strapi v5 Deep Populate Plugin

npm version

A Strapi v5 plugin that automatically populates all nested relations in a single request using populate: '*'. It does not impose a limit on the level of nesting and can cache the populate object for improved performance.

Features

  • Automatically resolves and populates all nested relations
  • Supports all relation types including dynamic zones
  • Handles circular references and edge cases
  • Includes caching for improved performance
  • Honors populateCreatorFields setting
  • Supports optional allow/deny lists for specific relations or components during population

Installation

npm install @fourlights/strapi-plugin-deep-populate

Usage

Enable deep population in your Strapi config:

// config/plugins.js
module.exports = ({ env }) => ({
  'deep-populate': {
    enabled: true,
    config: {
      useCache: true, // default
      replaceWildcard: true, // default
    }
  }
});

Basic Usage

// Get fully populated document
const document = await strapi.documents("api.page.page").findOne({
  documentId: 'xyz',
  populate: '*'
});

Advanced Usage

// Get populate object for custom usage
const populate = await strapi.plugin("deep-populate")
  .service("populate")
  .get({
    documentId: 'xyz',
    contentType: 'api::page.page',
    omitEmpty: true // optional
  });

const document = await strapi.documents('api::page.page').findOne({
  documentId: 'xyz',
  populate
});

omitEmpty and localizations

The plugin provides fine-grained control over which attributes are included in the populate object through omitEmpty and localizations options.

Global Configuration

Set default behavior for all content types:

// config/plugins.js
module.exports = ({ env }) => ({
  'deep-populate': {
    enabled: true,
    config: {
      useCache: true,
      replaceWildcard: true,
      omitEmpty: true, // Omit empty attributes by default
      localizations: false, // Exclude localizations by default
    }
  }
});

Content-Type Specific Configuration

Override global settings for specific content types:

// config/plugins.js
module.exports = ({ env }) => ({
  'deep-populate': {
    enabled: true,
    config: {
      useCache: true,
      replaceWildcard: true,
      omitEmpty: true,
      localizations: false,
      
      contentTypes: {
        'api::page.page': {
          omitEmpty: false, // Include all attributes for pages
          localizations: true, // Always include localizations for pages
        },
        'api::blog-post.blog-post': {
          omitEmpty: true, // Explicitly omit empty attributes
          localizations: true, // But include localizations for blog posts
        }
      }
    }
  }
});

Function Parameter Configuration

Override both global and content-type settings per request:

// Get populate object with custom settings
const populate = await strapi.plugin("deep-populate")
  .service("populate")
  .get({
    documentId: 'xyz',
    contentType: 'api::page.page',
    omitEmpty: true, // Override content-type setting
    localizations: false // Override content-type setting
  });

Override Priority

Settings are applied in the following priority order (highest to lowest):

  1. Function parameters - Passed directly to the get() method
  2. Content-type configuration - Specific to the content type
  3. Global configuration - Default plugin settings

Special Behavior

  • When localizations: true, the localizations field will be included even if omitEmpty: true
  • When localizations: false, localizations are excluded regardless of the omitEmpty setting
  • The localizations option only affects content types that have i18n enabled

Caching

The plugin caches populate objects to improve performance. Cache can be disabled via the useCache setting.

Creator Fields

The plugin automatically populates createdBy and updatedBy fields when populateCreatorFields is enabled in the content-type configuration.

Allow / Deny Lists

Sometimes you may want to restrict the nested population of certain relations or components. For example if you have a Page contentType where a deeply nested Link component has a relation to another Page. In those situations you can use the allow or deny lists to control where the plugin should stop resolving nested relations.

// config/plugins.js
module.exports = ({ env }) => ({
  'deep-populate': {
    enabled: true,
    config: {
      useCache: true,
      replaceWildcard: true,
      
      contentTypes: {
        // '*' would apply to all content types
        'api::page.page': {
          deny: {
            relations: ['api::page.page']  // prevent resolving nested pages when populating a page
            // alternatively we could have denied the link component in this case
            // components: ['shared.link']
          }
        }
      }
    }
  }
});

How The Plugin Works

The plugin recursively:

  1. Traverses the content-type schema
  2. Retrieves documents with one-level deep populate
  3. Resolves all nested relations
  4. Returns a complete populate object

This process handles all relation types including dynamic zones and circular references.