@fourlights/strapi-plugin-deep-populate 1.0.0-beta.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -3
- package/dist/server/index.js +77 -34
- package/dist/server/index.mjs +77 -34
- package/dist/server/src/index.d.ts +2 -1
- package/dist/server/src/services/deep-populate/index.d.ts +1 -1
- package/dist/server/src/services/index.d.ts +2 -1
- package/dist/server/src/services/populate.d.ts +4 -3
- package/package.json +10 -6
package/README.md
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# @fourlights/strapi-plugin-deep-populate
|
|
2
2
|
|
|
3
|
+
[](https://badge.fury.io/js/@fourlights%2Fstrapi-plugin-deep-populate)
|
|
4
|
+
|
|
3
5
|
This Strapi v5 plugin provides a simple way of retrieving all nested objects in a single request.
|
|
4
6
|
It does this by traversing the schema and comparing that to the actual retrieved document(s).
|
|
5
7
|
Only relations that are actually set will be populated.
|
|
@@ -8,17 +10,25 @@ Only relations that are actually set will be populated.
|
|
|
8
10
|
|
|
9
11
|
```ts
|
|
10
12
|
// Option 1: get the populate object and use where you see fit
|
|
11
|
-
const populate = await strapi.plugin("deep-populate").service("populate").
|
|
13
|
+
const populate = await strapi.plugin("deep-populate").service("populate").get({ documentId: 'xyz', contentType: 'api::page.page' })
|
|
12
14
|
const document = strapi.documents('api::page.page').findOne({ documentId: 'xyz', populate })
|
|
13
15
|
```
|
|
14
16
|
```ts
|
|
15
|
-
// Option 2: use the
|
|
17
|
+
// Option 2: use the `findOne` method that wraps around documentService.findOne
|
|
16
18
|
const { findOne } = strapi.plugin("deep-populate").service("populate").documents("api::page.page")
|
|
17
19
|
const document = await findOne({ documentId: 'xyz' })
|
|
20
|
+
```
|
|
18
21
|
|
|
19
|
-
|
|
22
|
+
```ts
|
|
23
|
+
// Using the wrapped FindOne provides some handy features:
|
|
24
|
+
|
|
25
|
+
// Allow you to override the populate this way:
|
|
20
26
|
const documentWithCreatedBy = findOne({ documentId: 'xyz', populate: ['createdBy']})
|
|
21
27
|
const documentWithoutSection = findOne({ documentId: 'xyz', populate: { section: false }})
|
|
28
|
+
|
|
29
|
+
// And if you supply a `*` as populate, it will return a fully populated document (i.e. non-sparse)
|
|
30
|
+
const sparseDocument = findOne({ documentId: 'xyz' }) // sparse, so only attributes are returned that have a value
|
|
31
|
+
const fullDocument = findOne({ documentId: 'xyz', populate: '*' }) // fully populated, so all attributes are returned
|
|
22
32
|
```
|
|
23
33
|
|
|
24
34
|
### populateCreatorFields
|
package/dist/server/index.js
CHANGED
|
@@ -24584,7 +24584,7 @@ const isPopulateString = (value) => {
|
|
|
24584
24584
|
};
|
|
24585
24585
|
const isStringArray$1 = (value) => fp.isArray(value) && value.every(fp.isString);
|
|
24586
24586
|
const isObj = (value) => fp.isObject(value);
|
|
24587
|
-
const populate = traverseFactory().intercept(isPopulateString, async (visitor2, options, populate2, { recurse }) => {
|
|
24587
|
+
const populate$1 = traverseFactory().intercept(isPopulateString, async (visitor2, options, populate2, { recurse }) => {
|
|
24588
24588
|
const populateObject = pathsToObjectPopulate([populate2]);
|
|
24589
24589
|
const traversedPopulate = await recurse(visitor2, options, populateObject);
|
|
24590
24590
|
const [result] = objectPopulateToPaths(traversedPopulate);
|
|
@@ -24752,7 +24752,7 @@ const populate = traverseFactory().intercept(isPopulateString, async (visitor2,
|
|
|
24752
24752
|
}
|
|
24753
24753
|
}
|
|
24754
24754
|
);
|
|
24755
|
-
const traverseQueryPopulate = fp.curry(populate.traverse);
|
|
24755
|
+
const traverseQueryPopulate = fp.curry(populate$1.traverse);
|
|
24756
24756
|
const objectPopulateToPaths = (input) => {
|
|
24757
24757
|
const paths = [];
|
|
24758
24758
|
function traverse(currentObj, parentPath) {
|
|
@@ -25061,7 +25061,9 @@ const getRelations = (model) => {
|
|
|
25061
25061
|
...contentTypes.getRelationalAttributes(model).filter((attr) => !filteredAttributes.has(attr)),
|
|
25062
25062
|
...contentTypes.getComponentAttributes(model).filter((attr) => !filteredAttributes.has(attr))
|
|
25063
25063
|
]);
|
|
25064
|
-
return Object.entries(model.attributes).filter(
|
|
25064
|
+
return Object.entries(model.attributes).filter(
|
|
25065
|
+
([attrName, attr]) => relationalAttributes.has(attrName) || contentTypes.isMediaAttribute(attr)
|
|
25066
|
+
);
|
|
25065
25067
|
};
|
|
25066
25068
|
const isEmpty = (obj) => {
|
|
25067
25069
|
return obj === void 0 || Object.keys(obj).length === 0;
|
|
@@ -25073,31 +25075,42 @@ async function _populateComponent({
|
|
|
25073
25075
|
mainUid,
|
|
25074
25076
|
mainDocumentId,
|
|
25075
25077
|
schema: schema2,
|
|
25076
|
-
populate: populate2,
|
|
25077
|
-
lookup
|
|
25078
|
+
populate: populate2 = {},
|
|
25079
|
+
lookup,
|
|
25080
|
+
inDynamicZone = false,
|
|
25081
|
+
omitEmpty
|
|
25078
25082
|
}) {
|
|
25079
|
-
const
|
|
25080
|
-
|
|
25083
|
+
const attrName = lookup.pop();
|
|
25084
|
+
const componentLookup = lookup.length === 0 ? [attrName] : [...lookup, inDynamicZone ? "on" : "populate", attrName];
|
|
25085
|
+
const componentPopulate = json$1.klona(populate2);
|
|
25086
|
+
merge$1.dset(componentPopulate, componentLookup, { populate: "*" });
|
|
25087
|
+
const nestedPopulate = await _populate({
|
|
25088
|
+
mainUid,
|
|
25089
|
+
mainDocumentId,
|
|
25090
|
+
schema: schema2,
|
|
25091
|
+
populate: componentPopulate,
|
|
25092
|
+
lookup: componentLookup,
|
|
25093
|
+
omitEmpty
|
|
25094
|
+
});
|
|
25095
|
+
return isEmpty(nestedPopulate) ? true : { populate: nestedPopulate };
|
|
25081
25096
|
}
|
|
25082
25097
|
async function _populateDynamicZone({
|
|
25083
25098
|
mainUid,
|
|
25084
25099
|
mainDocumentId,
|
|
25085
25100
|
components,
|
|
25086
25101
|
populate: populate2,
|
|
25087
|
-
lookup
|
|
25102
|
+
lookup,
|
|
25103
|
+
omitEmpty
|
|
25088
25104
|
}) {
|
|
25089
|
-
const dzLookup = [...lookup, "on"];
|
|
25090
|
-
const dzPopulate = json$1.klona(populate2);
|
|
25091
|
-
merge$1.dset(dzPopulate, dzLookup, {});
|
|
25092
25105
|
const resolvedPopulate = await components.reduce(async (prev, cur) => {
|
|
25093
|
-
const componentPopulate = json$1.klona(dzPopulate);
|
|
25094
|
-
delve__default.default(componentPopulate, dzLookup)[cur] = { populate: "*" };
|
|
25095
25106
|
const curPopulate = await _populateComponent({
|
|
25096
25107
|
mainUid,
|
|
25097
25108
|
mainDocumentId,
|
|
25098
25109
|
schema: cur,
|
|
25099
|
-
populate:
|
|
25100
|
-
lookup: [...
|
|
25110
|
+
populate: populate2,
|
|
25111
|
+
lookup: [...lookup, cur],
|
|
25112
|
+
inDynamicZone: true,
|
|
25113
|
+
omitEmpty
|
|
25101
25114
|
});
|
|
25102
25115
|
const newPop = await prev;
|
|
25103
25116
|
merge$1.dset(newPop, [cur], curPopulate);
|
|
@@ -25107,12 +25120,13 @@ async function _populateDynamicZone({
|
|
|
25107
25120
|
return { on: resolvedPopulate };
|
|
25108
25121
|
}
|
|
25109
25122
|
function _populateMedia() {
|
|
25110
|
-
return
|
|
25123
|
+
return true;
|
|
25111
25124
|
}
|
|
25112
25125
|
async function _populateRelation({
|
|
25113
25126
|
contentType,
|
|
25114
25127
|
relation,
|
|
25115
|
-
resolvedRelations
|
|
25128
|
+
resolvedRelations,
|
|
25129
|
+
omitEmpty
|
|
25116
25130
|
}) {
|
|
25117
25131
|
const isSingleRelation = !Array.isArray(relation);
|
|
25118
25132
|
const relations = isSingleRelation ? [relation] : relation;
|
|
@@ -25122,7 +25136,8 @@ async function _populateRelation({
|
|
|
25122
25136
|
mainUid: contentType,
|
|
25123
25137
|
mainDocumentId: relation2.documentId,
|
|
25124
25138
|
schema: contentType,
|
|
25125
|
-
resolvedRelations
|
|
25139
|
+
resolvedRelations,
|
|
25140
|
+
omitEmpty
|
|
25126
25141
|
});
|
|
25127
25142
|
resolvedRelations.set(relation2.documentId, relationPopulate);
|
|
25128
25143
|
}
|
|
@@ -25131,15 +25146,34 @@ async function _populateRelation({
|
|
|
25131
25146
|
const relationPopulate = resolvedRelations.get(documentId);
|
|
25132
25147
|
Object.keys(relationPopulate).map((r) => merge$1.dset(newPopulate, r, relationPopulate[r]));
|
|
25133
25148
|
}
|
|
25134
|
-
return { populate: newPopulate };
|
|
25149
|
+
return isEmpty(newPopulate) ? true : { populate: newPopulate };
|
|
25135
25150
|
}
|
|
25151
|
+
const _resolveValue = ({ document: document2, lookup, attrName }) => {
|
|
25152
|
+
if (lookup.find((l) => l === "on")) {
|
|
25153
|
+
const attrLookup = lookup.filter((l) => l !== "on");
|
|
25154
|
+
const parentAttr = attrLookup.pop();
|
|
25155
|
+
const parentValue2 = (delve__default.default(document2, attrLookup) ?? []).filter((b) => b.__component === parentAttr) ?? [];
|
|
25156
|
+
return (Array.isArray(parentValue2) ? parentValue2 : [parentValue2]).find((v) => hasValue(v[attrName]))?.[attrName];
|
|
25157
|
+
}
|
|
25158
|
+
if (lookup.find((l) => l === "populate")) {
|
|
25159
|
+
const attrLookup = lookup.filter((l) => l !== "populate");
|
|
25160
|
+
const parentValue2 = delve__default.default(document2, attrLookup) ?? [];
|
|
25161
|
+
return (Array.isArray(parentValue2) ? parentValue2 : [parentValue2]).find((v) => hasValue(v[attrName]))?.[attrName];
|
|
25162
|
+
}
|
|
25163
|
+
const parentValue = delve__default.default(document2, lookup);
|
|
25164
|
+
if (Array.isArray(parentValue)) {
|
|
25165
|
+
return parentValue.map((v) => v[attrName]);
|
|
25166
|
+
}
|
|
25167
|
+
return parentValue?.[attrName];
|
|
25168
|
+
};
|
|
25136
25169
|
async function _populate({
|
|
25137
25170
|
mainUid,
|
|
25138
25171
|
mainDocumentId,
|
|
25139
25172
|
schema: schema2,
|
|
25140
25173
|
populate: populate2 = {},
|
|
25141
25174
|
lookup = [],
|
|
25142
|
-
resolvedRelations = /* @__PURE__ */ new Map()
|
|
25175
|
+
resolvedRelations = /* @__PURE__ */ new Map(),
|
|
25176
|
+
omitEmpty = true
|
|
25143
25177
|
}) {
|
|
25144
25178
|
const newPopulate = {};
|
|
25145
25179
|
const model = strapi.getModel(schema2);
|
|
@@ -25160,10 +25194,9 @@ async function _populate({
|
|
|
25160
25194
|
populate: currentPopulate ? currentPopulate : "*"
|
|
25161
25195
|
});
|
|
25162
25196
|
for (const [attrName, attr] of relations) {
|
|
25163
|
-
const
|
|
25164
|
-
const value = delve__default.default(document2, attrLookup);
|
|
25197
|
+
const value = _resolveValue({ document: document2, attrName, lookup });
|
|
25165
25198
|
if (!hasValue(value)) {
|
|
25166
|
-
newPopulate[attrName] = true;
|
|
25199
|
+
if (!omitEmpty) newPopulate[attrName] = true;
|
|
25167
25200
|
continue;
|
|
25168
25201
|
}
|
|
25169
25202
|
if (contentTypes.isDynamicZoneAttribute(attr)) {
|
|
@@ -25174,8 +25207,8 @@ async function _populate({
|
|
|
25174
25207
|
mainUid,
|
|
25175
25208
|
mainDocumentId,
|
|
25176
25209
|
components: relComponents,
|
|
25177
|
-
|
|
25178
|
-
|
|
25210
|
+
lookup: [...lookup, attrName],
|
|
25211
|
+
omitEmpty
|
|
25179
25212
|
});
|
|
25180
25213
|
}
|
|
25181
25214
|
if (contentTypes.isRelationalAttribute(attr)) {
|
|
@@ -25183,7 +25216,8 @@ async function _populate({
|
|
|
25183
25216
|
newPopulate[attrName] = await _populateRelation({
|
|
25184
25217
|
contentType: relContentType,
|
|
25185
25218
|
relation: value,
|
|
25186
|
-
resolvedRelations
|
|
25219
|
+
resolvedRelations,
|
|
25220
|
+
omitEmpty
|
|
25187
25221
|
});
|
|
25188
25222
|
}
|
|
25189
25223
|
if (contentTypes.isComponentAttribute(attr) && !contentTypes.isDynamicZoneAttribute(attr)) {
|
|
@@ -25191,26 +25225,35 @@ async function _populate({
|
|
|
25191
25225
|
mainUid,
|
|
25192
25226
|
mainDocumentId,
|
|
25193
25227
|
schema: attr.component,
|
|
25194
|
-
|
|
25195
|
-
|
|
25228
|
+
lookup: [...lookup, attrName],
|
|
25229
|
+
omitEmpty
|
|
25196
25230
|
});
|
|
25197
25231
|
}
|
|
25198
25232
|
if (contentTypes.isMediaAttribute(attr)) {
|
|
25199
25233
|
newPopulate[attrName] = _populateMedia();
|
|
25200
25234
|
}
|
|
25201
25235
|
}
|
|
25202
|
-
return
|
|
25236
|
+
return newPopulate;
|
|
25203
25237
|
}
|
|
25204
|
-
const
|
|
25205
|
-
async
|
|
25206
|
-
|
|
25238
|
+
const populate = ({ strapi: strapi2 }) => ({
|
|
25239
|
+
async get({
|
|
25240
|
+
contentType,
|
|
25241
|
+
documentId,
|
|
25242
|
+
omitEmpty = false
|
|
25243
|
+
}) {
|
|
25244
|
+
return await _populate({ mainUid: contentType, mainDocumentId: documentId, schema: contentType, omitEmpty });
|
|
25207
25245
|
},
|
|
25208
25246
|
documents(contentType) {
|
|
25209
25247
|
strapi2.documents(contentType);
|
|
25210
25248
|
const { findOne, ...wrapped } = strapi2.documents(contentType);
|
|
25211
25249
|
const wrappedFindOne = async (params) => {
|
|
25212
25250
|
const { documentId, populate: originalPopulate } = params;
|
|
25213
|
-
const deepPopulate = await _populate({
|
|
25251
|
+
const deepPopulate = await _populate({
|
|
25252
|
+
mainUid: contentType,
|
|
25253
|
+
mainDocumentId: documentId,
|
|
25254
|
+
schema: contentType,
|
|
25255
|
+
omitEmpty: originalPopulate !== "*"
|
|
25256
|
+
});
|
|
25214
25257
|
if (originalPopulate && originalPopulate !== "*") {
|
|
25215
25258
|
strapi2.log.warn(
|
|
25216
25259
|
`passed "populate" will be merged with deepPopulate, which could result in unexpected behavior.`
|
|
@@ -25225,7 +25268,7 @@ const deepPopulateService = ({ strapi: strapi2 }) => ({
|
|
|
25225
25268
|
}
|
|
25226
25269
|
});
|
|
25227
25270
|
const services = {
|
|
25228
|
-
populate
|
|
25271
|
+
populate
|
|
25229
25272
|
};
|
|
25230
25273
|
const index = {
|
|
25231
25274
|
services
|
package/dist/server/index.mjs
CHANGED
|
@@ -24570,7 +24570,7 @@ const isPopulateString = (value) => {
|
|
|
24570
24570
|
};
|
|
24571
24571
|
const isStringArray$1 = (value) => fp.isArray(value) && value.every(fp.isString);
|
|
24572
24572
|
const isObj = (value) => fp.isObject(value);
|
|
24573
|
-
const populate = traverseFactory().intercept(isPopulateString, async (visitor2, options, populate2, { recurse }) => {
|
|
24573
|
+
const populate$1 = traverseFactory().intercept(isPopulateString, async (visitor2, options, populate2, { recurse }) => {
|
|
24574
24574
|
const populateObject = pathsToObjectPopulate([populate2]);
|
|
24575
24575
|
const traversedPopulate = await recurse(visitor2, options, populateObject);
|
|
24576
24576
|
const [result] = objectPopulateToPaths(traversedPopulate);
|
|
@@ -24738,7 +24738,7 @@ const populate = traverseFactory().intercept(isPopulateString, async (visitor2,
|
|
|
24738
24738
|
}
|
|
24739
24739
|
}
|
|
24740
24740
|
);
|
|
24741
|
-
const traverseQueryPopulate = fp.curry(populate.traverse);
|
|
24741
|
+
const traverseQueryPopulate = fp.curry(populate$1.traverse);
|
|
24742
24742
|
const objectPopulateToPaths = (input) => {
|
|
24743
24743
|
const paths = [];
|
|
24744
24744
|
function traverse(currentObj, parentPath) {
|
|
@@ -25047,7 +25047,9 @@ const getRelations = (model) => {
|
|
|
25047
25047
|
...contentTypes.getRelationalAttributes(model).filter((attr) => !filteredAttributes.has(attr)),
|
|
25048
25048
|
...contentTypes.getComponentAttributes(model).filter((attr) => !filteredAttributes.has(attr))
|
|
25049
25049
|
]);
|
|
25050
|
-
return Object.entries(model.attributes).filter(
|
|
25050
|
+
return Object.entries(model.attributes).filter(
|
|
25051
|
+
([attrName, attr]) => relationalAttributes.has(attrName) || contentTypes.isMediaAttribute(attr)
|
|
25052
|
+
);
|
|
25051
25053
|
};
|
|
25052
25054
|
const isEmpty = (obj) => {
|
|
25053
25055
|
return obj === void 0 || Object.keys(obj).length === 0;
|
|
@@ -25059,31 +25061,42 @@ async function _populateComponent({
|
|
|
25059
25061
|
mainUid,
|
|
25060
25062
|
mainDocumentId,
|
|
25061
25063
|
schema: schema2,
|
|
25062
|
-
populate: populate2,
|
|
25063
|
-
lookup
|
|
25064
|
+
populate: populate2 = {},
|
|
25065
|
+
lookup,
|
|
25066
|
+
inDynamicZone = false,
|
|
25067
|
+
omitEmpty
|
|
25064
25068
|
}) {
|
|
25065
|
-
const
|
|
25066
|
-
|
|
25069
|
+
const attrName = lookup.pop();
|
|
25070
|
+
const componentLookup = lookup.length === 0 ? [attrName] : [...lookup, inDynamicZone ? "on" : "populate", attrName];
|
|
25071
|
+
const componentPopulate = klona(populate2);
|
|
25072
|
+
dset(componentPopulate, componentLookup, { populate: "*" });
|
|
25073
|
+
const nestedPopulate = await _populate({
|
|
25074
|
+
mainUid,
|
|
25075
|
+
mainDocumentId,
|
|
25076
|
+
schema: schema2,
|
|
25077
|
+
populate: componentPopulate,
|
|
25078
|
+
lookup: componentLookup,
|
|
25079
|
+
omitEmpty
|
|
25080
|
+
});
|
|
25081
|
+
return isEmpty(nestedPopulate) ? true : { populate: nestedPopulate };
|
|
25067
25082
|
}
|
|
25068
25083
|
async function _populateDynamicZone({
|
|
25069
25084
|
mainUid,
|
|
25070
25085
|
mainDocumentId,
|
|
25071
25086
|
components,
|
|
25072
25087
|
populate: populate2,
|
|
25073
|
-
lookup
|
|
25088
|
+
lookup,
|
|
25089
|
+
omitEmpty
|
|
25074
25090
|
}) {
|
|
25075
|
-
const dzLookup = [...lookup, "on"];
|
|
25076
|
-
const dzPopulate = klona(populate2);
|
|
25077
|
-
dset(dzPopulate, dzLookup, {});
|
|
25078
25091
|
const resolvedPopulate = await components.reduce(async (prev, cur) => {
|
|
25079
|
-
const componentPopulate = klona(dzPopulate);
|
|
25080
|
-
delve(componentPopulate, dzLookup)[cur] = { populate: "*" };
|
|
25081
25092
|
const curPopulate = await _populateComponent({
|
|
25082
25093
|
mainUid,
|
|
25083
25094
|
mainDocumentId,
|
|
25084
25095
|
schema: cur,
|
|
25085
|
-
populate:
|
|
25086
|
-
lookup: [...
|
|
25096
|
+
populate: populate2,
|
|
25097
|
+
lookup: [...lookup, cur],
|
|
25098
|
+
inDynamicZone: true,
|
|
25099
|
+
omitEmpty
|
|
25087
25100
|
});
|
|
25088
25101
|
const newPop = await prev;
|
|
25089
25102
|
dset(newPop, [cur], curPopulate);
|
|
@@ -25093,12 +25106,13 @@ async function _populateDynamicZone({
|
|
|
25093
25106
|
return { on: resolvedPopulate };
|
|
25094
25107
|
}
|
|
25095
25108
|
function _populateMedia() {
|
|
25096
|
-
return
|
|
25109
|
+
return true;
|
|
25097
25110
|
}
|
|
25098
25111
|
async function _populateRelation({
|
|
25099
25112
|
contentType,
|
|
25100
25113
|
relation,
|
|
25101
|
-
resolvedRelations
|
|
25114
|
+
resolvedRelations,
|
|
25115
|
+
omitEmpty
|
|
25102
25116
|
}) {
|
|
25103
25117
|
const isSingleRelation = !Array.isArray(relation);
|
|
25104
25118
|
const relations = isSingleRelation ? [relation] : relation;
|
|
@@ -25108,7 +25122,8 @@ async function _populateRelation({
|
|
|
25108
25122
|
mainUid: contentType,
|
|
25109
25123
|
mainDocumentId: relation2.documentId,
|
|
25110
25124
|
schema: contentType,
|
|
25111
|
-
resolvedRelations
|
|
25125
|
+
resolvedRelations,
|
|
25126
|
+
omitEmpty
|
|
25112
25127
|
});
|
|
25113
25128
|
resolvedRelations.set(relation2.documentId, relationPopulate);
|
|
25114
25129
|
}
|
|
@@ -25117,15 +25132,34 @@ async function _populateRelation({
|
|
|
25117
25132
|
const relationPopulate = resolvedRelations.get(documentId);
|
|
25118
25133
|
Object.keys(relationPopulate).map((r) => dset(newPopulate, r, relationPopulate[r]));
|
|
25119
25134
|
}
|
|
25120
|
-
return { populate: newPopulate };
|
|
25135
|
+
return isEmpty(newPopulate) ? true : { populate: newPopulate };
|
|
25121
25136
|
}
|
|
25137
|
+
const _resolveValue = ({ document: document2, lookup, attrName }) => {
|
|
25138
|
+
if (lookup.find((l) => l === "on")) {
|
|
25139
|
+
const attrLookup = lookup.filter((l) => l !== "on");
|
|
25140
|
+
const parentAttr = attrLookup.pop();
|
|
25141
|
+
const parentValue2 = (delve(document2, attrLookup) ?? []).filter((b) => b.__component === parentAttr) ?? [];
|
|
25142
|
+
return (Array.isArray(parentValue2) ? parentValue2 : [parentValue2]).find((v) => hasValue(v[attrName]))?.[attrName];
|
|
25143
|
+
}
|
|
25144
|
+
if (lookup.find((l) => l === "populate")) {
|
|
25145
|
+
const attrLookup = lookup.filter((l) => l !== "populate");
|
|
25146
|
+
const parentValue2 = delve(document2, attrLookup) ?? [];
|
|
25147
|
+
return (Array.isArray(parentValue2) ? parentValue2 : [parentValue2]).find((v) => hasValue(v[attrName]))?.[attrName];
|
|
25148
|
+
}
|
|
25149
|
+
const parentValue = delve(document2, lookup);
|
|
25150
|
+
if (Array.isArray(parentValue)) {
|
|
25151
|
+
return parentValue.map((v) => v[attrName]);
|
|
25152
|
+
}
|
|
25153
|
+
return parentValue?.[attrName];
|
|
25154
|
+
};
|
|
25122
25155
|
async function _populate({
|
|
25123
25156
|
mainUid,
|
|
25124
25157
|
mainDocumentId,
|
|
25125
25158
|
schema: schema2,
|
|
25126
25159
|
populate: populate2 = {},
|
|
25127
25160
|
lookup = [],
|
|
25128
|
-
resolvedRelations = /* @__PURE__ */ new Map()
|
|
25161
|
+
resolvedRelations = /* @__PURE__ */ new Map(),
|
|
25162
|
+
omitEmpty = true
|
|
25129
25163
|
}) {
|
|
25130
25164
|
const newPopulate = {};
|
|
25131
25165
|
const model = strapi.getModel(schema2);
|
|
@@ -25146,10 +25180,9 @@ async function _populate({
|
|
|
25146
25180
|
populate: currentPopulate ? currentPopulate : "*"
|
|
25147
25181
|
});
|
|
25148
25182
|
for (const [attrName, attr] of relations) {
|
|
25149
|
-
const
|
|
25150
|
-
const value = delve(document2, attrLookup);
|
|
25183
|
+
const value = _resolveValue({ document: document2, attrName, lookup });
|
|
25151
25184
|
if (!hasValue(value)) {
|
|
25152
|
-
newPopulate[attrName] = true;
|
|
25185
|
+
if (!omitEmpty) newPopulate[attrName] = true;
|
|
25153
25186
|
continue;
|
|
25154
25187
|
}
|
|
25155
25188
|
if (contentTypes.isDynamicZoneAttribute(attr)) {
|
|
@@ -25160,8 +25193,8 @@ async function _populate({
|
|
|
25160
25193
|
mainUid,
|
|
25161
25194
|
mainDocumentId,
|
|
25162
25195
|
components: relComponents,
|
|
25163
|
-
|
|
25164
|
-
|
|
25196
|
+
lookup: [...lookup, attrName],
|
|
25197
|
+
omitEmpty
|
|
25165
25198
|
});
|
|
25166
25199
|
}
|
|
25167
25200
|
if (contentTypes.isRelationalAttribute(attr)) {
|
|
@@ -25169,7 +25202,8 @@ async function _populate({
|
|
|
25169
25202
|
newPopulate[attrName] = await _populateRelation({
|
|
25170
25203
|
contentType: relContentType,
|
|
25171
25204
|
relation: value,
|
|
25172
|
-
resolvedRelations
|
|
25205
|
+
resolvedRelations,
|
|
25206
|
+
omitEmpty
|
|
25173
25207
|
});
|
|
25174
25208
|
}
|
|
25175
25209
|
if (contentTypes.isComponentAttribute(attr) && !contentTypes.isDynamicZoneAttribute(attr)) {
|
|
@@ -25177,26 +25211,35 @@ async function _populate({
|
|
|
25177
25211
|
mainUid,
|
|
25178
25212
|
mainDocumentId,
|
|
25179
25213
|
schema: attr.component,
|
|
25180
|
-
|
|
25181
|
-
|
|
25214
|
+
lookup: [...lookup, attrName],
|
|
25215
|
+
omitEmpty
|
|
25182
25216
|
});
|
|
25183
25217
|
}
|
|
25184
25218
|
if (contentTypes.isMediaAttribute(attr)) {
|
|
25185
25219
|
newPopulate[attrName] = _populateMedia();
|
|
25186
25220
|
}
|
|
25187
25221
|
}
|
|
25188
|
-
return
|
|
25222
|
+
return newPopulate;
|
|
25189
25223
|
}
|
|
25190
|
-
const
|
|
25191
|
-
async
|
|
25192
|
-
|
|
25224
|
+
const populate = ({ strapi: strapi2 }) => ({
|
|
25225
|
+
async get({
|
|
25226
|
+
contentType,
|
|
25227
|
+
documentId,
|
|
25228
|
+
omitEmpty = false
|
|
25229
|
+
}) {
|
|
25230
|
+
return await _populate({ mainUid: contentType, mainDocumentId: documentId, schema: contentType, omitEmpty });
|
|
25193
25231
|
},
|
|
25194
25232
|
documents(contentType) {
|
|
25195
25233
|
strapi2.documents(contentType);
|
|
25196
25234
|
const { findOne, ...wrapped } = strapi2.documents(contentType);
|
|
25197
25235
|
const wrappedFindOne = async (params) => {
|
|
25198
25236
|
const { documentId, populate: originalPopulate } = params;
|
|
25199
|
-
const deepPopulate = await _populate({
|
|
25237
|
+
const deepPopulate = await _populate({
|
|
25238
|
+
mainUid: contentType,
|
|
25239
|
+
mainDocumentId: documentId,
|
|
25240
|
+
schema: contentType,
|
|
25241
|
+
omitEmpty: originalPopulate !== "*"
|
|
25242
|
+
});
|
|
25200
25243
|
if (originalPopulate && originalPopulate !== "*") {
|
|
25201
25244
|
strapi2.log.warn(
|
|
25202
25245
|
`passed "populate" will be merged with deepPopulate, which could result in unexpected behavior.`
|
|
@@ -25211,7 +25254,7 @@ const deepPopulateService = ({ strapi: strapi2 }) => ({
|
|
|
25211
25254
|
}
|
|
25212
25255
|
});
|
|
25213
25256
|
const services = {
|
|
25214
|
-
populate
|
|
25257
|
+
populate
|
|
25215
25258
|
};
|
|
25216
25259
|
const index = {
|
|
25217
25260
|
services
|
|
@@ -3,9 +3,10 @@ declare const _default: {
|
|
|
3
3
|
populate: ({ strapi }: {
|
|
4
4
|
strapi: import("@strapi/types/dist/core").Strapi;
|
|
5
5
|
}) => {
|
|
6
|
-
|
|
6
|
+
get({ contentType, documentId, omitEmpty, }: {
|
|
7
7
|
contentType: import("@strapi/types/dist/uid").ContentType;
|
|
8
8
|
documentId: string;
|
|
9
|
+
omitEmpty?: boolean;
|
|
9
10
|
}): Promise<{}>;
|
|
10
11
|
documents(contentType: import("@strapi/types/dist/uid").ContentType): {
|
|
11
12
|
findMany<const TParams extends import("@strapi/types/dist/modules/documents/params/document-engine").FindMany<import("@strapi/types/dist/uid").ContentType>>(params?: TParams): import("@strapi/types/dist/modules/documents/result/document-engine").FindMany<import("@strapi/types/dist/uid").ContentType, TParams>;
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import type { UID } from "@strapi/strapi";
|
|
2
2
|
import type { PopulateProps } from "./types";
|
|
3
|
-
export default function _populate<TContentType extends UID.ContentType, TSchema extends UID.Schema>({ mainUid, mainDocumentId, schema, populate, lookup, resolvedRelations, }: PopulateProps<TContentType, TSchema>): Promise<{}>;
|
|
3
|
+
export default function _populate<TContentType extends UID.ContentType, TSchema extends UID.Schema>({ mainUid, mainDocumentId, schema, populate, lookup, resolvedRelations, omitEmpty, }: PopulateProps<TContentType, TSchema>): Promise<{}>;
|
|
@@ -2,9 +2,10 @@ declare const _default: {
|
|
|
2
2
|
populate: ({ strapi }: {
|
|
3
3
|
strapi: import("@strapi/types/dist/core").Strapi;
|
|
4
4
|
}) => {
|
|
5
|
-
|
|
5
|
+
get({ contentType, documentId, omitEmpty, }: {
|
|
6
6
|
contentType: import("@strapi/types/dist/uid").ContentType;
|
|
7
7
|
documentId: string;
|
|
8
|
+
omitEmpty?: boolean;
|
|
8
9
|
}): Promise<{}>;
|
|
9
10
|
documents(contentType: import("@strapi/types/dist/uid").ContentType): {
|
|
10
11
|
findMany<const TParams extends import("@strapi/types/dist/modules/documents/params/document-engine").FindMany<import("@strapi/types/dist/uid").ContentType>>(params?: TParams): import("@strapi/types/dist/modules/documents/result/document-engine").FindMany<import("@strapi/types/dist/uid").ContentType, TParams>;
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import type { Core, UID } from "@strapi/strapi";
|
|
2
|
-
declare const
|
|
2
|
+
declare const _default: ({ strapi }: {
|
|
3
3
|
strapi: Core.Strapi;
|
|
4
4
|
}) => {
|
|
5
|
-
|
|
5
|
+
get({ contentType, documentId, omitEmpty, }: {
|
|
6
6
|
contentType: UID.ContentType;
|
|
7
7
|
documentId: string;
|
|
8
|
+
omitEmpty?: boolean;
|
|
8
9
|
}): Promise<{}>;
|
|
9
10
|
documents(contentType: UID.ContentType): {
|
|
10
11
|
findMany<const TParams extends import("@strapi/types/dist/modules/documents/params/document-engine").FindMany<UID.ContentType>>(params?: TParams): import("@strapi/types/dist/modules/documents/result/document-engine").FindMany<UID.ContentType, TParams>;
|
|
@@ -17,4 +18,4 @@ declare const deepPopulateService: ({ strapi }: {
|
|
|
17
18
|
clone<const TParams_7 extends import("@strapi/types/dist/modules/documents/params/document-engine").Clone<UID.ContentType>>(params: TParams_7): import("@strapi/types/dist/modules/documents/result/document-engine").Clone<UID.ContentType, TParams_7>;
|
|
18
19
|
} & import("@strapi/types/dist/modules/documents").DraftAndPublishExtension<UID.ContentType> & import("@strapi/types/dist/modules/documents/component-extension").ComponentExtension<UID.ContentType>;
|
|
19
20
|
};
|
|
20
|
-
export default
|
|
21
|
+
export default _default;
|
package/package.json
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "1.
|
|
3
|
-
"keywords": [
|
|
2
|
+
"version": "1.1.0",
|
|
3
|
+
"keywords": [
|
|
4
|
+
"strapi",
|
|
5
|
+
"strapi-plugin",
|
|
6
|
+
"populate",
|
|
7
|
+
"strapi-v5"
|
|
8
|
+
],
|
|
4
9
|
"type": "commonjs",
|
|
5
10
|
"exports": {
|
|
6
11
|
"./package.json": "./package.json",
|
|
@@ -25,7 +30,7 @@
|
|
|
25
30
|
"test:integration": "jest --verbose --forceExit --detectOpenHandles",
|
|
26
31
|
"ci": "biome ci server",
|
|
27
32
|
"release": "release-it",
|
|
28
|
-
"playground:install": "$npm_execpath run playground:yalc-add && cd playground && $npm_execpath install",
|
|
33
|
+
"playground:install": "$npm_execpath run playground:yalc-add && cd playground && $npm_execpath install --loglevel error",
|
|
29
34
|
"playground:yalc-add": "cd playground && yalc add @fourlights/strapi-plugin-deep-populate",
|
|
30
35
|
"playground:yalc-add-link": "cd playground && yalc add --link @fourlights/strapi-plugin-deep-populate"
|
|
31
36
|
},
|
|
@@ -36,7 +41,6 @@
|
|
|
36
41
|
},
|
|
37
42
|
"devDependencies": {
|
|
38
43
|
"@biomejs/biome": "^1.9.4",
|
|
39
|
-
"@release-it/conventional-changelog": "^10.0.0",
|
|
40
44
|
"@strapi/sdk-plugin": "^5.3.0",
|
|
41
45
|
"@strapi/strapi": "^5.8.0",
|
|
42
46
|
"@strapi/typescript-utils": "^5.8.0",
|
|
@@ -53,8 +57,8 @@
|
|
|
53
57
|
"yalc": "^1.0.0-pre.53"
|
|
54
58
|
},
|
|
55
59
|
"peerDependencies": {
|
|
56
|
-
"@strapi/sdk-plugin": "^5
|
|
57
|
-
"@strapi/strapi": "^5
|
|
60
|
+
"@strapi/sdk-plugin": "^5",
|
|
61
|
+
"@strapi/strapi": "^5"
|
|
58
62
|
},
|
|
59
63
|
"strapi": {
|
|
60
64
|
"kind": "plugin",
|