Skip to content

Commit 921201f

Browse files
authored
fix(loop): add check to prevent infinite loops (#8)
* fix(loop): add check to prevent infinite loops * ci(test): build plugin for testing
1 parent 2b14d94 commit 921201f

3 files changed

Lines changed: 45 additions & 8 deletions

File tree

.github/workflows/test.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@ jobs:
2929
registry-url: 'https://registry.npmjs.org/'
3030
cache: 'npm'
3131

32+
- name: Prepare plugin
33+
run: npm ci && npm run build
34+
working-directory: ./
35+
3236
- name: dotenv
3337
run: echo "${{ secrets.ENV_FILE }}" >> .env
3438

sandbox/tests/populate-all.test.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,23 @@ import { describe, expect, test } from "@jest/globals";
22
import { strapiRequest } from "./strapi";
33

44
describe("strapi-plugin-populate-all", () => {
5-
test.skip("if everything is populated", async () => {
5+
test("if everything is populated", async () => {
66
const response = await strapiRequest.get(
77
"/api/articles?status=draft&populate=all"
88
);
9+
10+
// request succeeds
911
expect(response.statusCode).toBe(200);
12+
13+
// has first level of population
14+
expect(response.body.data[0]).toHaveProperty("cover");
15+
expect(response.body.data[0]).toHaveProperty("author");
16+
expect(response.body.data[0]).toHaveProperty("category");
17+
expect(response.body.data[0]).toHaveProperty("blocks");
18+
19+
// doesn't loop
20+
expect(response.body.data[0].category.articles[0]).not.toHaveProperty(
21+
"category"
22+
);
1023
});
1124
});

server/src/utils/getPopulateQuery.ts

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ import type { UID } from "@strapi/strapi";
44
const queryCache: Partial<Record<UID.Schema, any>> = {};
55

66
export const getPopulateQuery = (
7-
modelUid: UID.Schema
7+
modelUid: UID.Schema,
8+
parentsModelUids: UID.Schema[] = []
89
): { populate: object | true } | undefined => {
910
try {
1011
// return cached query
@@ -13,6 +14,16 @@ export const getPopulateQuery = (
1314
return queryCache[modelUid];
1415
}
1516

17+
// prevent infinite loop
18+
if (parentsModelUids.includes(modelUid)) {
19+
strapi.log.debug(
20+
`[populate-all] loop detected skipping population: ${modelUid}`
21+
);
22+
return { populate: {} };
23+
} else {
24+
parentsModelUids.push(modelUid);
25+
}
26+
1627
// build query
1728
const query = { populate: {} };
1829
const model = strapi.getModel(modelUid);
@@ -31,7 +42,7 @@ export const getPopulateQuery = (
3142
const components = Object.fromEntries(
3243
attribute.components.map((component) => [
3344
component,
34-
getPopulateQuery(component),
45+
getPopulateQuery(component, parentsModelUids),
3546
])
3647
);
3748
query.populate[fieldName] = { on: components };
@@ -40,7 +51,10 @@ export const getPopulateQuery = (
4051

4152
// component
4253
if (attribute.type === "component") {
43-
query.populate[fieldName] = getPopulateQuery(attribute.component);
54+
query.populate[fieldName] = getPopulateQuery(
55+
attribute.component,
56+
parentsModelUids
57+
);
4458
continue;
4559
}
4660

@@ -57,14 +71,20 @@ export const getPopulateQuery = (
5771
.config<boolean | string[]>("relations");
5872

5973
if (relations === true) {
60-
// @ts-expect-error target actually exists on attribute
61-
query.populate[fieldName] = getPopulateQuery(attribute.target);
74+
query.populate[fieldName] = getPopulateQuery(
75+
// @ts-expect-error target actually exists on attribute
76+
attribute.target,
77+
parentsModelUids
78+
);
6279
continue;
6380
}
6481
// @ts-expect-error target actually exists on attribute
6582
if (Array.isArray(relations) && relations.includes(attribute.target)) {
66-
// @ts-expect-error target actually exists on attribute
67-
query.populate[fieldName] = getPopulateQuery(attribute.target);
83+
query.populate[fieldName] = getPopulateQuery(
84+
// @ts-expect-error target actually exists on attribute
85+
attribute.target,
86+
parentsModelUids
87+
);
6888
continue;
6989
}
7090
}

0 commit comments

Comments
 (0)