Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
6607636
change populate to deeppopulate
NEDDL Sep 6, 2024
2733902
add debug
NEDDL Sep 6, 2024
9fd886f
change readme and change param to pLevel
NEDDL Sep 6, 2024
50dd466
strapi version added to the default depth
NEDDL Sep 6, 2024
97846ed
version
NEDDL Sep 6, 2024
e9093be
remove console.log
NEDDL Sep 8, 2024
138ad42
remove console.log
NEDDL Sep 8, 2024
be6e10e
fix issue with population of fields with the same names
tooonuch Oct 14, 2024
9462dbf
Merge pull request #1 from tooonuch/main
NEDDL Oct 18, 2024
42e8851
change title and version and add contribution note
NEDDL Oct 18, 2024
fd7231d
fix title
NEDDL Oct 18, 2024
39345a0
adapt nodejs engine requirements to @strapi/strapi
adriankirchner Jan 22, 2025
49a82ea
Merge pull request #2 from adriankirchner/main
NEDDL Feb 24, 2025
e2715e3
4.0.5
NEDDL Feb 24, 2025
b2f32e6
fix self-recursion
sanpezlo Mar 15, 2025
ef5d0ea
chore(package.json): allow node 24
chohner Dec 19, 2025
9c2c72f
Merge pull request #12 from chohner/patch-2
NEDDL Jan 16, 2026
b3efeec
chore: bump version to 4.0.6 and add contributors section
NEDDL Jan 16, 2026
b1195c8
Merge branch 'pr/12'
NEDDL Jan 16, 2026
1427896
fix: support Strapi v5.37.0 strict param validation via pLevel
NEDDL Mar 16, 2026
d57978a
chore: add new version
NEDDL Mar 16, 2026
a45252d
Merge pull request #4 from sanpezlo/main
NEDDL Mar 16, 2026
467c251
feat: deepAssign for dynamic zones, pIgnore param, propagate ignore list
NEDDL Mar 16, 2026
f73aa0f
chore: add publish actions
NEDDL Mar 16, 2026
f6987c7
chore: add publish actions
NEDDL Mar 16, 2026
983dcf0
chore(ci): update publish to be manual
NEDDL Mar 16, 2026
4b44d30
add lodash dep, fix pIgnore to accept comma-separated string
NEDDL Mar 17, 2026
d348eb2
chore: release v4.2.1
github-actions[bot] Mar 17, 2026
3569c4c
fix: support Strapi versions before 5.37 (addQueryParams compat)
NEDDL Mar 17, 2026
8283a84
chore: release v4.2.2
github-actions[bot] Mar 17, 2026
a374766
chore: update documentation
NEDDL Mar 17, 2026
d985cc1
chore: update the badge
NEDDL Mar 17, 2026
8704ac3
chore(ci): fix the action to publish
NEDDL Mar 17, 2026
959b9fc
chore(ci): fix npm-publish
NEDDL Mar 17, 2026
6678a76
chore(ci): fix publish step
NEDDL Mar 17, 2026
aee0049
fix(ci): update node version
NEDDL Mar 17, 2026
226bb37
sync lockfile
chohner Mar 19, 2026
6c44e0f
feat(getFullPopulateObject): pull skipCreatorFields into if clause
chohner Mar 19, 2026
351da57
fix: include scalar-only components in dynamic zone populate
NEDDL Mar 21, 2026
ae11961
chore: release v4.3.0
github-actions[bot] Mar 21, 2026
f6d63cb
fix: guard against true.populate → undefined when pLevel=1
NEDDL Mar 21, 2026
0a69996
chore: release v4.3.1
github-actions[bot] Mar 21, 2026
1a34ae8
refactor: replace lodash isEmpty with native JS, remove dependency
Frank3K Mar 22, 2026
749bcea
fix(helpers): copy ignore array at each recursive call to prevent cro…
Frank3K Mar 23, 2026
56f8c1d
Merge pull request #20 from Frank3K/remove-lodash-dependency
chohner Mar 26, 2026
235dc39
Merge pull request #22 from Frank3K/fix/ignore-list-shared-mutation
NEDDL Mar 27, 2026
22f168d
fix: always populate localizations field regardless of ignore list
NEDDL Mar 27, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions .github/workflows/npm-publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
name: Publish to npm

on:
workflow_dispatch:

permissions:
contents: read
id-token: write

jobs:
publish:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: 22
registry-url: https://registry.npmjs.org/

- name: Upgrade npm
run: npm install -g npm@latest

- name: Check if version already on npm
id: check
run: |
VERSION=$(node -p "require('./package.json').version")
if npm view strapi-v5-plugin-populate-deep@$VERSION version 2>/dev/null; then
echo "exists=true" >> $GITHUB_OUTPUT
else
echo "exists=false" >> $GITHUB_OUTPUT
fi

- name: Publish
if: steps.check.outputs.exists == 'false'
run: npm publish --provenance --access public
52 changes: 52 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
name: Create Release

on:
workflow_dispatch:

permissions:
contents: write

jobs:
release:
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: 20

- name: Bump version and create tag
id: tag
uses: mathieudutour/github-tag-action@v6.2
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
default_bump: patch
release_branches: main

- name: Update package.json version
run: |
node -e "
const fs = require('fs');
const pkg = JSON.parse(fs.readFileSync('./package.json', 'utf8'));
pkg.version = '${{ steps.tag.outputs.new_version }}';
fs.writeFileSync('./package.json', JSON.stringify(pkg, null, 2) + '\n');
"
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add package.json
git commit -m "chore: release v${{ steps.tag.outputs.new_version }}"
git push

- name: Create GitHub Release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh release create ${{ steps.tag.outputs.new_tag }} \
--generate-notes \
--title "${{ steps.tag.outputs.new_tag }}"
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
node_modules/
104 changes: 72 additions & 32 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,52 +1,92 @@
# Strapi plugin populate-deep
This plugin allows for easier population of deep content structures using the rest API.

# Installation

`npm install strapi-plugin-populate-deep`

`yarn add strapi-plugin-populate-deep`


# Usages

## Examples
# strapi-v5-plugin-populate-deep

A Strapi v5 plugin that enables deep population of nested content structures via a simple query parameter.

[![npm version](https://img.shields.io/npm/v/strapi-v5-plugin-populate-deep?label=version&color=blue)](https://www.npmjs.com/package/strapi-v5-plugin-populate-deep)
[![npm downloads](https://img.shields.io/npm/dm/strapi-v5-plugin-populate-deep?color=brightgreen)](https://www.npmjs.com/package/strapi-v5-plugin-populate-deep)
[![npm total downloads](https://img.shields.io/npm/dt/strapi-v5-plugin-populate-deep)](https://www.npmjs.com/package/strapi-v5-plugin-populate-deep)
[![license](https://img.shields.io/npm/l/strapi-v5-plugin-populate-deep)](./LICENSE)
[![node](https://img.shields.io/node/v/strapi-v5-plugin-populate-deep)](https://www.npmjs.com/package/strapi-v5-plugin-populate-deep)
[![install size](https://packagephobia.com/badge?p=strapi-v5-plugin-populate-deep)](https://packagephobia.com/result?p=strapi-v5-plugin-populate-deep)
[![GitHub stars](https://img.shields.io/github/stars/NEDDL/strapi-v5-plugin-populate-deep?style=social)](https://github.com/NEDDL/strapi-v5-plugin-populate-deep/stargazers)
[![GitHub forks](https://img.shields.io/github/forks/NEDDL/strapi-v5-plugin-populate-deep?style=social)](https://github.com/NEDDL/strapi-v5-plugin-populate-deep/network/members)
[![GitHub issues](https://img.shields.io/github/issues/NEDDL/strapi-v5-plugin-populate-deep)](https://github.com/NEDDL/strapi-v5-plugin-populate-deep/issues)
[![GitHub last commit](https://img.shields.io/github/last-commit/NEDDL/strapi-v5-plugin-populate-deep)](https://github.com/NEDDL/strapi-v5-plugin-populate-deep/commits/main)
[![GitHub contributors](https://img.shields.io/github/contributors/NEDDL/strapi-v5-plugin-populate-deep)](https://github.com/NEDDL/strapi-v5-plugin-populate-deep/graphs/contributors)
[![Strapi v5](https://img.shields.io/badge/Strapi-v5-8C4BFF?logo=strapi)](https://strapi.io)

## Installation

```bash
npm install strapi-v5-plugin-populate-deep
# or
yarn add strapi-v5-plugin-populate-deep
```

Populate a request with the default max depth.
## Usage

`/api/articles?populate=deep`
Add `pLevel` to any API request to deeply populate the response.

Populate a request with the a custom depth
| Parameter | Type | Description |
|-----------|------|-------------|
| `pLevel` | `number` (optional) | Depth of population. Omit the value to use the default depth. |
| `pIgnore` | `string` or `string[]` (optional) | Fields or collection names to exclude from population. Accepts a comma-separated string or array. |

`/api/articles?populate=deep,10`
### Examples

Populate a request with the a custom depth
```
# Use default depth (5)
GET /api/articles?pLevel

`/api/articles/1?populate=deep,10`
# Use custom depth
GET /api/articles?pLevel=10

## Good to know
# Ignore specific fields (comma-separated string)
GET /api/articles?pLevel=5&pIgnore=author,tags

The default max depth is 5 levels deep.
# Ignore specific fields (array syntax)
GET /api/articles?pLevel=5&pIgnore[0]=author&pIgnore[1]=tags
```

The populate deep option is available for all collections and single types using the findOne and findMany methods.
## Configuration

# Configuration
Customize the default depth globally via `config/plugins.js` (or `.ts`):

The default depth can be customized via the plugin config. To do so create or edit you plugins.js file.
```js
// config/plugins.js
module.exports = ({ env }) => ({
'strapi-v5-plugin-populate-deep': {
config: {
defaultDepth: 3, // default: 5
},
},
});
```

## Example configuration
## Good to Know

`config/plugins.js`
- Default depth is **5** unless configured otherwise.
- Works for all collections and single types (`findOne` and `findMany`).
- `pIgnore` prevents circular population and can significantly reduce response size and query time.
- Increasing depth may result in longer response times — use `pIgnore` to offset this.
- `plugin::upload.file` related field is always excluded to avoid bloated responses.
- `admin::user` (creator fields) can be excluded via `skipCreatorFields` config:

```
```js
module.exports = ({ env }) => ({
'strapi-plugin-populate-deep': {
'strapi-v5-plugin-populate-deep': {
config: {
defaultDepth: 3, // Default is 5
}
defaultDepth: 5,
skipCreatorFields: true,
},
},
});
```

# Contributions
The original idea for getting the populate structure was created by [tomnovotny7](https://github.com/tomnovotny7) and can be found in [this](https://github.com/strapi/strapi/issues/11836) github thread
## Contributors

<a href="https://github.com/NEDDL/strapi-v5-plugin-populate-deep/graphs/contributors">
<img src="https://contrib.rocks/image?repo=NEDDL/strapi-v5-plugin-populate-deep" />
</a>

Based on the original work by [Barelydead](https://github.com/Barelydead/strapi-plugin-populate-deep). Original populate concept by [tomnovotny7](https://github.com/tomnovotny7) ([thread](https://github.com/strapi/strapi/issues/11836)). Dynamic zone fix by [tooonuch](https://github.com/tooonuch).
20 changes: 16 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

26 changes: 15 additions & 11 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,28 +1,32 @@
{
"name": "strapi-plugin-populate-deep",
"version": "3.0.1",
"description": "Strapi plugin that populates nested content.",
"name": "strapi-v5-plugin-populate-deep",
"version": "4.3.1",
"description": "Strapi v5 plugin that populates nested content.",
"strapi": {
"name": "strapi-plugin-populate-deep",
"description": "Api helper to populate deep content structures.",
"name": "strapi-v5-plugin-populate-deep",
"description": "API helper to populate deep content structures for Strapi v5.",
"kind": "plugin"
},
"dependencies": {},
"author": {
"name": "Christofer Jungberg"
"name": "Mustafa ONAL"
},
"contributors": [
"Christofer Jungberg",
"Mustafa ONAL",
"chohner"
],
"maintainers": [
{
"name": "Christofer Jungberg"
"name": "Mustafa ONAL"
}
],
"repository": {
"type": "git",
"url": "https://github.com/Barelydead/strapi-plugin-deep-populate"
"url": "https://github.com/NEDDL/strapi-v5-plugin-populate-deep"
},
"engines": {
"node": ">=14.19.1 <=20.x.x",
"node": ">=18.0.0 <=24.x.x",
"npm": ">=6.0.0"
},
"license": "MIT"
}
}
34 changes: 23 additions & 11 deletions server/bootstrap.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,30 @@
'use strict';
const { getFullPopulateObject } = require('./helpers')
"use strict";
const { getFullPopulateObject } = require("./helpers");

module.exports = ({ strapi }) => {
// Subscribe to the lifecycles that we are intrested in.
const defaultDepth =
strapi.plugin("strapi-v5-plugin-populate-deep")?.config("defaultDepth") ||
5;

strapi.db.lifecycles.subscribe((event) => {
if (event.action === 'beforeFindMany' || event.action === 'beforeFindOne') {
const populate = event.params?.populate;
const defaultDepth = strapi.plugin('strapi-plugin-populate-deep')?.config('defaultDepth') || 5
const { action, model, params } = event;

if (!["beforeFindMany", "beforeFindOne"].includes(action)) return;
if (!model.uid.startsWith("api::")) return;

const ctx = strapi.requestContext.get();
if (!ctx?.request?.url?.startsWith("/api/")) return;

const pLevel = params?.pLevel ?? ctx.query?.pLevel;
if (pLevel === undefined) return;

const pIgnore = params?.pIgnore ?? ctx.query?.pIgnore ?? [];
const ignore = typeof pIgnore === 'string' ? pIgnore.split(',').map(s => s.trim()) : Array.isArray(pIgnore) ? pIgnore : [pIgnore];

if (populate && populate[0] === 'deep') {
const depth = populate[1] ?? defaultDepth
const modelObject = getFullPopulateObject(event.model.uid, depth, []);
event.params.populate = modelObject.populate
}
const depth = pLevel ? parseInt(pLevel, 10) : defaultDepth;
const populateObj = getFullPopulateObject(model.uid, depth, ignore);
if (populateObj && populateObj !== true) {
params.populate = populateObj.populate;
}
});
};
Loading