strapi-plugin-bulk-updater 1.2.13 → 1.3.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 +10 -4
- package/dist/_chunks/{BulkUpdater-CWJYmuGU.js → BulkUpdater-CRvwX326.js} +261 -33
- package/dist/_chunks/BulkUpdater-CRvwX326.js.map +1 -0
- package/dist/_chunks/{BulkUpdater-Cfig2f7d.mjs → BulkUpdater-DowSmA56.mjs} +261 -33
- package/dist/_chunks/BulkUpdater-DowSmA56.mjs.map +1 -0
- package/dist/admin/index.js +1 -1
- package/dist/admin/index.mjs +1 -1
- package/dist/server/index.js +187 -92
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +187 -92
- package/dist/server/index.mjs.map +1 -1
- package/package.json +3 -3
- package/dist/_chunks/BulkUpdater-CWJYmuGU.js.map +0 -1
- package/dist/_chunks/BulkUpdater-Cfig2f7d.mjs.map +0 -1
package/dist/admin/index.js
CHANGED
|
@@ -10,7 +10,7 @@ const index = {
|
|
|
10
10
|
id: `${PLUGIN_ID}.plugin.name`,
|
|
11
11
|
defaultMessage: "Bulk Attribute Updater"
|
|
12
12
|
},
|
|
13
|
-
Component: () => Promise.resolve().then(() => require("../_chunks/BulkUpdater-
|
|
13
|
+
Component: () => Promise.resolve().then(() => require("../_chunks/BulkUpdater-CRvwX326.js")),
|
|
14
14
|
permissions: [],
|
|
15
15
|
position: 3
|
|
16
16
|
});
|
package/dist/admin/index.mjs
CHANGED
|
@@ -9,7 +9,7 @@ const index = {
|
|
|
9
9
|
id: `${PLUGIN_ID}.plugin.name`,
|
|
10
10
|
defaultMessage: "Bulk Attribute Updater"
|
|
11
11
|
},
|
|
12
|
-
Component: () => import("../_chunks/BulkUpdater-
|
|
12
|
+
Component: () => import("../_chunks/BulkUpdater-DowSmA56.mjs"),
|
|
13
13
|
permissions: [],
|
|
14
14
|
position: 3
|
|
15
15
|
});
|
package/dist/server/index.js
CHANGED
|
@@ -328,12 +328,13 @@ const bulkUpdaterController = ({ strapi: strapi2 }) => ({
|
|
|
328
328
|
async getCollectionEntries(ctx) {
|
|
329
329
|
try {
|
|
330
330
|
const { uid } = ctx.params;
|
|
331
|
-
const { page, pageSize, attribute, filterOperator, filterQuery, search, sortField, sortOrder } = ctx.query;
|
|
331
|
+
const { page, pageSize, attribute, searchAttribute, filterOperator, filterQuery, search, sortField, sortOrder } = ctx.query;
|
|
332
332
|
const service = strapi2.plugin("bulk-updater").service("bulkUpdater");
|
|
333
333
|
const data = await service.getCollectionEntries(uid, {
|
|
334
334
|
page: page ? Number(page) : 1,
|
|
335
335
|
pageSize: pageSize ? Number(pageSize) : 10,
|
|
336
336
|
attribute: attribute ? String(attribute) : void 0,
|
|
337
|
+
searchAttribute: searchAttribute ? String(searchAttribute) : void 0,
|
|
337
338
|
filterOperator: filterOperator ? String(filterOperator) : void 0,
|
|
338
339
|
filterQuery: filterQuery !== void 0 ? String(filterQuery) : void 0,
|
|
339
340
|
search: search ? String(search) : void 0,
|
|
@@ -692,6 +693,127 @@ const modelsCache = /* @__PURE__ */ new Map();
|
|
|
692
693
|
const MAX_QUERY_CACHE_SIZE = 500;
|
|
693
694
|
const CACHE_TTL_MS = 60 * 1e3;
|
|
694
695
|
let staticSchemaCache = null;
|
|
696
|
+
function buildDeepPopulate$1(attributes, allComponents, depth2 = 0) {
|
|
697
|
+
if (depth2 > 5) return true;
|
|
698
|
+
const populate2 = {};
|
|
699
|
+
for (const [key, def] of Object.entries(attributes || {})) {
|
|
700
|
+
if (def.type === "component" && def.component) {
|
|
701
|
+
const comp = allComponents[def.component];
|
|
702
|
+
if (comp?.attributes) {
|
|
703
|
+
populate2[key] = {
|
|
704
|
+
populate: buildDeepPopulate$1(comp.attributes, allComponents, depth2 + 1)
|
|
705
|
+
};
|
|
706
|
+
} else {
|
|
707
|
+
populate2[key] = true;
|
|
708
|
+
}
|
|
709
|
+
} else if (def.type === "dynamiczone") {
|
|
710
|
+
populate2[key] = true;
|
|
711
|
+
} else if (def.type === "relation" || def.type === "media") {
|
|
712
|
+
populate2[key] = true;
|
|
713
|
+
}
|
|
714
|
+
}
|
|
715
|
+
return Object.keys(populate2).length > 0 ? populate2 : true;
|
|
716
|
+
}
|
|
717
|
+
function discoverComponentAttributes(strapi2, compUid, prefix, currentDepth, maxDepth, systemFields, allContentTypes, relationsByAttr, allRelationsMeta, attributesMeta) {
|
|
718
|
+
if (currentDepth > maxDepth || !compUid) return [];
|
|
719
|
+
const compSchema = strapi2.components[compUid];
|
|
720
|
+
if (!compSchema?.attributes) return [];
|
|
721
|
+
const discoveredAttrs = [];
|
|
722
|
+
for (const [subKey, subAttr] of Object.entries(compSchema.attributes)) {
|
|
723
|
+
if (systemFields.includes(subKey)) continue;
|
|
724
|
+
if (subAttr.type === "dynamiczone") continue;
|
|
725
|
+
const fullPath = prefix ? `${prefix}.${subKey}` : subKey;
|
|
726
|
+
if (subAttr.type === "component") {
|
|
727
|
+
if (!subAttr.repeatable && subAttr.component) {
|
|
728
|
+
const deeper = discoverComponentAttributes(
|
|
729
|
+
strapi2,
|
|
730
|
+
subAttr.component,
|
|
731
|
+
fullPath,
|
|
732
|
+
currentDepth + 1,
|
|
733
|
+
maxDepth,
|
|
734
|
+
systemFields,
|
|
735
|
+
allContentTypes,
|
|
736
|
+
relationsByAttr,
|
|
737
|
+
allRelationsMeta,
|
|
738
|
+
attributesMeta
|
|
739
|
+
);
|
|
740
|
+
discoveredAttrs.push(...deeper);
|
|
741
|
+
}
|
|
742
|
+
} else if (subAttr.type === "relation") {
|
|
743
|
+
const targetUid = subAttr.target;
|
|
744
|
+
if (targetUid && allContentTypes[targetUid]) {
|
|
745
|
+
const targetInfo = allContentTypes[targetUid]?.info;
|
|
746
|
+
const isMulti = subAttr.relation === "oneToMany" || subAttr.relation === "manyToMany";
|
|
747
|
+
const relMeta = {
|
|
748
|
+
isRelation: true,
|
|
749
|
+
relationType: subAttr.relation,
|
|
750
|
+
targetUid,
|
|
751
|
+
targetDisplayName: targetInfo?.displayName || targetUid,
|
|
752
|
+
isMulti
|
|
753
|
+
};
|
|
754
|
+
relationsByAttr[fullPath] = relMeta;
|
|
755
|
+
allRelationsMeta[fullPath] = relMeta;
|
|
756
|
+
attributesMeta[fullPath] = { depth: currentDepth, type: "relation", component: compUid, isRelation: true };
|
|
757
|
+
discoveredAttrs.push(fullPath);
|
|
758
|
+
}
|
|
759
|
+
} else {
|
|
760
|
+
attributesMeta[fullPath] = { depth: currentDepth, type: subAttr.type, component: compUid };
|
|
761
|
+
discoveredAttrs.push(fullPath);
|
|
762
|
+
}
|
|
763
|
+
}
|
|
764
|
+
return discoveredAttrs;
|
|
765
|
+
}
|
|
766
|
+
function isDeepComponentField(contentType, allComponents, attribute) {
|
|
767
|
+
if (!attribute || !attribute.includes(".")) return false;
|
|
768
|
+
const parts = attribute.split(".");
|
|
769
|
+
let currentSchema = contentType;
|
|
770
|
+
for (let i = 0; i < parts.length - 1; i++) {
|
|
771
|
+
const part = parts[i];
|
|
772
|
+
const attrDef = currentSchema?.attributes?.[part];
|
|
773
|
+
if (!attrDef || attrDef.type !== "component" || !attrDef.component) return false;
|
|
774
|
+
currentSchema = allComponents[attrDef.component];
|
|
775
|
+
if (!currentSchema) return false;
|
|
776
|
+
}
|
|
777
|
+
const leafField = parts[parts.length - 1];
|
|
778
|
+
return Boolean(currentSchema?.attributes?.[leafField]);
|
|
779
|
+
}
|
|
780
|
+
function getLeafAttributeSchema(contentType, allComponents, attribute) {
|
|
781
|
+
if (!attribute) return null;
|
|
782
|
+
if (!attribute.includes(".")) return contentType?.attributes?.[attribute] || null;
|
|
783
|
+
const parts = attribute.split(".");
|
|
784
|
+
let currentSchema = contentType;
|
|
785
|
+
for (let i = 0; i < parts.length - 1; i++) {
|
|
786
|
+
const part = parts[i];
|
|
787
|
+
const attrDef = currentSchema?.attributes?.[part];
|
|
788
|
+
if (!attrDef || attrDef.type !== "component" || !attrDef.component) return null;
|
|
789
|
+
currentSchema = allComponents[attrDef.component];
|
|
790
|
+
if (!currentSchema) return null;
|
|
791
|
+
}
|
|
792
|
+
return currentSchema?.attributes?.[parts[parts.length - 1]] || null;
|
|
793
|
+
}
|
|
794
|
+
function setDeepProperty(obj, pathParts, value) {
|
|
795
|
+
if (pathParts.length === 0) return value;
|
|
796
|
+
const current = { ...obj || {} };
|
|
797
|
+
const [head, ...tail] = pathParts;
|
|
798
|
+
if (tail.length === 0) {
|
|
799
|
+
current[head] = value;
|
|
800
|
+
} else {
|
|
801
|
+
current[head] = setDeepProperty(current[head] || {}, tail, value);
|
|
802
|
+
}
|
|
803
|
+
return current;
|
|
804
|
+
}
|
|
805
|
+
function getDeepProperty(obj, path2) {
|
|
806
|
+
if (!obj || !path2) return void 0;
|
|
807
|
+
if (!path2.includes(".")) return obj[path2];
|
|
808
|
+
return path2.split(".").reduce((acc, part) => acc && typeof acc === "object" ? acc[part] : void 0, obj);
|
|
809
|
+
}
|
|
810
|
+
function buildDeepFilter(pathParts, condition) {
|
|
811
|
+
if (pathParts.length === 0) return condition;
|
|
812
|
+
const [head, ...tail] = pathParts;
|
|
813
|
+
return {
|
|
814
|
+
[head]: buildDeepFilter(tail, condition)
|
|
815
|
+
};
|
|
816
|
+
}
|
|
695
817
|
function getSafeTimezone(timeZone) {
|
|
696
818
|
if (!timeZone || typeof timeZone !== "string") {
|
|
697
819
|
return Intl.DateTimeFormat().resolvedOptions().timeZone || "UTC";
|
|
@@ -900,43 +1022,28 @@ async function executeBatchInternal(strapi2, {
|
|
|
900
1022
|
const currentEntry = await getDocumentDeduplicated(target.uid, target.documentId);
|
|
901
1023
|
const entryLabel = currentEntry?.name || currentEntry?.title || currentEntry?.email || `Entry #${target.documentId}`;
|
|
902
1024
|
const isNested = attribute.includes(".");
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
if (isNested) {
|
|
907
|
-
const parts = attribute.split(".");
|
|
908
|
-
parentKey = parts[0];
|
|
909
|
-
childKey = parts[1];
|
|
910
|
-
const parentAttrDef = contentType?.attributes?.[parentKey];
|
|
911
|
-
if (parentAttrDef?.type === "component" && !parentAttrDef.repeatable && parentAttrDef.component) {
|
|
912
|
-
const compSchema = strapi2.components[parentAttrDef.component];
|
|
913
|
-
if (compSchema?.attributes?.[childKey]) {
|
|
914
|
-
isComponentNested = true;
|
|
915
|
-
}
|
|
916
|
-
}
|
|
917
|
-
}
|
|
1025
|
+
const isComponentNested = isNested && isDeepComponentField(contentType, strapi2.components, attribute);
|
|
1026
|
+
const parts = isNested ? attribute.split(".") : [];
|
|
1027
|
+
const rootKey = isNested ? parts[0] : "";
|
|
918
1028
|
const attrDef = contentType?.attributes?.[attribute];
|
|
919
1029
|
const hasAttribute = Boolean(attrDef) || isComponentNested;
|
|
920
1030
|
if (hasAttribute) {
|
|
921
1031
|
if (isComponentNested) {
|
|
922
1032
|
const currentEntryWithPopulate = await strapi2.documents(target.uid).findOne({
|
|
923
1033
|
documentId: target.documentId,
|
|
924
|
-
populate:
|
|
1034
|
+
populate: buildDeepPopulate$1(contentType.attributes, strapi2.components)
|
|
925
1035
|
});
|
|
926
|
-
const
|
|
927
|
-
const currentVal2 =
|
|
1036
|
+
const existingRoot = currentEntryWithPopulate?.[rootKey] || {};
|
|
1037
|
+
const currentVal2 = getDeepProperty(existingRoot, parts.slice(1).join("."));
|
|
928
1038
|
let newValue2 = value;
|
|
929
1039
|
if (regexObj && typeof currentVal2 === "string") {
|
|
930
1040
|
newValue2 = currentVal2.replace(regexObj, value);
|
|
931
1041
|
}
|
|
932
|
-
const
|
|
933
|
-
...existingParent,
|
|
934
|
-
[childKey]: newValue2
|
|
935
|
-
};
|
|
1042
|
+
const updatedRoot = setDeepProperty(existingRoot, parts.slice(1), newValue2);
|
|
936
1043
|
await strapi2.documents(target.uid).update({
|
|
937
1044
|
documentId: target.documentId,
|
|
938
1045
|
data: {
|
|
939
|
-
[
|
|
1046
|
+
[rootKey]: updatedRoot
|
|
940
1047
|
}
|
|
941
1048
|
});
|
|
942
1049
|
const isDraftAndPublishComp = Boolean(contentType?.options?.draftAndPublish);
|
|
@@ -1371,12 +1478,14 @@ const bulkUpdaterService = ({ strapi: strapi2 }) => {
|
|
|
1371
1478
|
}
|
|
1372
1479
|
const metaByUid = {};
|
|
1373
1480
|
const allRelationsMeta = {};
|
|
1481
|
+
const allAttributesMeta = {};
|
|
1374
1482
|
for (const uid of targetUids) {
|
|
1375
1483
|
const contentType = allContentTypes[uid];
|
|
1376
1484
|
if (!contentType || contentType.kind !== "collectionType" && contentType.kind !== "singleType") continue;
|
|
1377
1485
|
const isSingleType = contentType.kind === "singleType";
|
|
1378
1486
|
const rawAttrs = contentType.attributes || {};
|
|
1379
1487
|
const relationsByAttr = {};
|
|
1488
|
+
const colAttributesMeta = {};
|
|
1380
1489
|
const nestedComponentAttrs = [];
|
|
1381
1490
|
const validAttrs = Object.keys(rawAttrs).filter((attrKey) => {
|
|
1382
1491
|
if (systemFields.includes(attrKey)) return false;
|
|
@@ -1384,14 +1493,19 @@ const bulkUpdaterService = ({ strapi: strapi2 }) => {
|
|
|
1384
1493
|
if (rawAttrs[attrKey].type === "component") {
|
|
1385
1494
|
const compDef = rawAttrs[attrKey];
|
|
1386
1495
|
if (!compDef.repeatable && compDef.component) {
|
|
1387
|
-
const
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1496
|
+
const compAttrs = discoverComponentAttributes(
|
|
1497
|
+
strapi2,
|
|
1498
|
+
compDef.component,
|
|
1499
|
+
attrKey,
|
|
1500
|
+
1,
|
|
1501
|
+
5,
|
|
1502
|
+
systemFields,
|
|
1503
|
+
allContentTypes,
|
|
1504
|
+
relationsByAttr,
|
|
1505
|
+
allRelationsMeta,
|
|
1506
|
+
colAttributesMeta
|
|
1507
|
+
);
|
|
1508
|
+
nestedComponentAttrs.push(...compAttrs);
|
|
1395
1509
|
}
|
|
1396
1510
|
return false;
|
|
1397
1511
|
}
|
|
@@ -1410,12 +1524,19 @@ const bulkUpdaterService = ({ strapi: strapi2 }) => {
|
|
|
1410
1524
|
};
|
|
1411
1525
|
relationsByAttr[attrKey] = relMeta;
|
|
1412
1526
|
allRelationsMeta[attrKey] = relMeta;
|
|
1527
|
+
colAttributesMeta[attrKey] = { depth: 0, type: "relation", isRelation: true };
|
|
1413
1528
|
return true;
|
|
1414
1529
|
}
|
|
1530
|
+
colAttributesMeta[attrKey] = { depth: 0, type: rawAttrs[attrKey].type };
|
|
1415
1531
|
return true;
|
|
1416
1532
|
});
|
|
1417
1533
|
const allColAttrs = [...validAttrs, ...nestedComponentAttrs];
|
|
1418
|
-
allColAttrs.forEach((attr) =>
|
|
1534
|
+
allColAttrs.forEach((attr) => {
|
|
1535
|
+
allAttributesSet.add(attr);
|
|
1536
|
+
if (colAttributesMeta[attr]) {
|
|
1537
|
+
allAttributesMeta[attr] = colAttributesMeta[attr];
|
|
1538
|
+
}
|
|
1539
|
+
});
|
|
1419
1540
|
metaByUid[uid] = {
|
|
1420
1541
|
uid,
|
|
1421
1542
|
kind: contentType.kind,
|
|
@@ -1425,11 +1546,13 @@ const bulkUpdaterService = ({ strapi: strapi2 }) => {
|
|
|
1425
1546
|
pluralName: contentType.info?.pluralName || uid,
|
|
1426
1547
|
displayName: contentType.info?.displayName || uid,
|
|
1427
1548
|
attributes: allColAttrs,
|
|
1549
|
+
attributesMeta: colAttributesMeta,
|
|
1428
1550
|
relations: relationsByAttr
|
|
1429
1551
|
};
|
|
1430
1552
|
}
|
|
1431
1553
|
staticSchemaCache = {
|
|
1432
1554
|
attributes: Array.from(allAttributesSet),
|
|
1555
|
+
attributesMeta: allAttributesMeta,
|
|
1433
1556
|
targetUids: Object.keys(metaByUid),
|
|
1434
1557
|
metaByUid,
|
|
1435
1558
|
relationsMeta: allRelationsMeta
|
|
@@ -1460,17 +1583,7 @@ const bulkUpdaterService = ({ strapi: strapi2 }) => {
|
|
|
1460
1583
|
let entries = [];
|
|
1461
1584
|
let totalCount = 0;
|
|
1462
1585
|
try {
|
|
1463
|
-
const
|
|
1464
|
-
const relKeys = Object.keys(meta.relations || {});
|
|
1465
|
-
const compKeys = Object.keys(ctAttrs).filter((k) => ctAttrs[k].type === "component");
|
|
1466
|
-
const populateOptionObj = {};
|
|
1467
|
-
relKeys.forEach((k) => {
|
|
1468
|
-
populateOptionObj[k] = true;
|
|
1469
|
-
});
|
|
1470
|
-
compKeys.forEach((k) => {
|
|
1471
|
-
populateOptionObj[k] = true;
|
|
1472
|
-
});
|
|
1473
|
-
const populateOption = Object.keys(populateOptionObj).length > 0 ? populateOptionObj : void 0;
|
|
1586
|
+
const populateOption = buildDeepPopulate$1(allContentTypes[uid]?.attributes || {}, strapi2.components);
|
|
1474
1587
|
if (meta.isSingleType) {
|
|
1475
1588
|
const singleDoc = await strapi2.documents(uid).findFirst({
|
|
1476
1589
|
populate: populateOption
|
|
@@ -1529,8 +1642,10 @@ const bulkUpdaterService = ({ strapi: strapi2 }) => {
|
|
|
1529
1642
|
return {
|
|
1530
1643
|
success: true,
|
|
1531
1644
|
attributes: staticSchemaCache.attributes,
|
|
1645
|
+
attributesMeta: staticSchemaCache.attributesMeta,
|
|
1532
1646
|
collections,
|
|
1533
1647
|
relationsMeta: staticSchemaCache.relationsMeta,
|
|
1648
|
+
maxDiscoveredDepth: 5,
|
|
1534
1649
|
executionWindow: {
|
|
1535
1650
|
...executionConfig,
|
|
1536
1651
|
...windowStatus
|
|
@@ -1549,6 +1664,7 @@ const bulkUpdaterService = ({ strapi: strapi2 }) => {
|
|
|
1549
1664
|
page = 1,
|
|
1550
1665
|
pageSize = 10,
|
|
1551
1666
|
attribute,
|
|
1667
|
+
searchAttribute,
|
|
1552
1668
|
filterOperator,
|
|
1553
1669
|
filterQuery,
|
|
1554
1670
|
search,
|
|
@@ -1563,8 +1679,9 @@ const bulkUpdaterService = ({ strapi: strapi2 }) => {
|
|
|
1563
1679
|
const currentPage = Math.max(Number(page) || 1, 1);
|
|
1564
1680
|
const start = (currentPage - 1) * limit;
|
|
1565
1681
|
const isSingleType = contentType.kind === "singleType";
|
|
1682
|
+
const targetFilterAttr = searchAttribute || attribute;
|
|
1566
1683
|
const signature = await getCollectionSignature(strapi2, uid);
|
|
1567
|
-
const cacheKey = `${uid}:${limit}:${start}:${attribute || ""}:${filterOperator || ""}:${filterQuery || ""}:${search || ""}:${sortField || ""}:${sortOrder}`;
|
|
1684
|
+
const cacheKey = `${uid}:${limit}:${start}:${attribute || ""}:${searchAttribute || ""}:${filterOperator || ""}:${filterQuery || ""}:${search || ""}:${sortField || ""}:${sortOrder}`;
|
|
1568
1685
|
const cached = queryCache.get(cacheKey);
|
|
1569
1686
|
const etag = `W/"entry-${crypto__default.default.createHash("md5").update(`${cacheKey}:${signature}`).digest("hex")}"`;
|
|
1570
1687
|
if (cached && cached.signature === signature && Date.now() - cached.timestamp < CACHE_TTL_MS) {
|
|
@@ -1579,19 +1696,15 @@ const bulkUpdaterService = ({ strapi: strapi2 }) => {
|
|
|
1579
1696
|
const attrs = contentType.attributes || {};
|
|
1580
1697
|
let colHasAttribute = false;
|
|
1581
1698
|
let isNestedAttr = false;
|
|
1582
|
-
let
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
if (compSchema?.attributes?.[childKey]) {
|
|
1590
|
-
colHasAttribute = true;
|
|
1591
|
-
isNestedAttr = true;
|
|
1592
|
-
}
|
|
1699
|
+
let parts = [];
|
|
1700
|
+
if (targetFilterAttr) {
|
|
1701
|
+
if (targetFilterAttr.includes(".")) {
|
|
1702
|
+
isNestedAttr = isDeepComponentField(contentType, strapi2.components, targetFilterAttr);
|
|
1703
|
+
if (isNestedAttr) {
|
|
1704
|
+
colHasAttribute = true;
|
|
1705
|
+
parts = targetFilterAttr.split(".");
|
|
1593
1706
|
}
|
|
1594
|
-
} else if (attrs[
|
|
1707
|
+
} else if (attrs[targetFilterAttr]) {
|
|
1595
1708
|
colHasAttribute = true;
|
|
1596
1709
|
}
|
|
1597
1710
|
}
|
|
@@ -1616,7 +1729,7 @@ const bulkUpdaterService = ({ strapi: strapi2 }) => {
|
|
|
1616
1729
|
}
|
|
1617
1730
|
let condition = void 0;
|
|
1618
1731
|
const q = (filterQuery || "").trim();
|
|
1619
|
-
const targetAttrSchema = isNestedAttr ? strapi2.components
|
|
1732
|
+
const targetAttrSchema = isNestedAttr ? getLeafAttributeSchema(contentType, strapi2.components, targetFilterAttr) : attrs[targetFilterAttr];
|
|
1620
1733
|
const isStringLike = ["string", "text", "email", "richtext", "uid"].includes(targetAttrSchema?.type);
|
|
1621
1734
|
if (normOp === "empty") {
|
|
1622
1735
|
condition = isStringLike ? { $or: [{ $null: true }, { $eq: "" }] } : { $null: true };
|
|
@@ -1646,19 +1759,18 @@ const bulkUpdaterService = ({ strapi: strapi2 }) => {
|
|
|
1646
1759
|
}
|
|
1647
1760
|
if (condition !== void 0) {
|
|
1648
1761
|
if (isNestedAttr) {
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
};
|
|
1762
|
+
const deepFilter = buildDeepFilter(parts, condition);
|
|
1763
|
+
Object.assign(filters2, deepFilter);
|
|
1652
1764
|
} else {
|
|
1653
1765
|
if (normOp === "empty" && isStringLike) {
|
|
1654
1766
|
filters2.$or = [
|
|
1655
|
-
{ [
|
|
1656
|
-
{ [
|
|
1767
|
+
{ [targetFilterAttr]: { $null: true } },
|
|
1768
|
+
{ [targetFilterAttr]: { $eq: "" } }
|
|
1657
1769
|
];
|
|
1658
1770
|
} else if (normOp === "notempty" && isStringLike) {
|
|
1659
|
-
filters2[
|
|
1771
|
+
filters2[targetFilterAttr] = { $notNull: true, $ne: "" };
|
|
1660
1772
|
} else {
|
|
1661
|
-
filters2[
|
|
1773
|
+
filters2[targetFilterAttr] = condition;
|
|
1662
1774
|
}
|
|
1663
1775
|
}
|
|
1664
1776
|
}
|
|
@@ -1681,11 +1793,13 @@ const bulkUpdaterService = ({ strapi: strapi2 }) => {
|
|
|
1681
1793
|
}
|
|
1682
1794
|
}
|
|
1683
1795
|
}
|
|
1796
|
+
const populateOption = buildDeepPopulate$1(contentType.attributes, strapi2.components);
|
|
1684
1797
|
if (isSingleType) {
|
|
1685
1798
|
let singleDoc = null;
|
|
1686
1799
|
try {
|
|
1687
1800
|
singleDoc = await strapi2.documents(uid).findFirst({
|
|
1688
|
-
filters: Object.keys(filters2).length > 0 ? filters2 : void 0
|
|
1801
|
+
filters: Object.keys(filters2).length > 0 ? filters2 : void 0,
|
|
1802
|
+
populate: populateOption
|
|
1689
1803
|
});
|
|
1690
1804
|
} catch {
|
|
1691
1805
|
singleDoc = null;
|
|
@@ -1704,11 +1818,11 @@ const bulkUpdaterService = ({ strapi: strapi2 }) => {
|
|
|
1704
1818
|
}
|
|
1705
1819
|
};
|
|
1706
1820
|
} else {
|
|
1707
|
-
|
|
1821
|
+
let sortClause = {};
|
|
1708
1822
|
if (sortField && sortField.includes(".")) {
|
|
1709
|
-
const
|
|
1710
|
-
if (contentType.
|
|
1711
|
-
sortClause
|
|
1823
|
+
const sortParts = sortField.split(".");
|
|
1824
|
+
if (isDeepComponentField(contentType, strapi2.components, sortField)) {
|
|
1825
|
+
sortClause = buildDeepFilter(sortParts, sortOrder);
|
|
1712
1826
|
} else {
|
|
1713
1827
|
sortClause["createdAt"] = "desc";
|
|
1714
1828
|
}
|
|
@@ -1717,10 +1831,6 @@ const bulkUpdaterService = ({ strapi: strapi2 }) => {
|
|
|
1717
1831
|
} else {
|
|
1718
1832
|
sortClause["createdAt"] = "desc";
|
|
1719
1833
|
}
|
|
1720
|
-
const populateAttrs = Object.keys(contentType.attributes || {}).filter(
|
|
1721
|
-
(k) => contentType.attributes[k].type === "relation" || contentType.attributes[k].type === "component"
|
|
1722
|
-
);
|
|
1723
|
-
const populateOption = populateAttrs.length > 0 ? populateAttrs.reduce((acc, k) => ({ ...acc, [k]: true }), {}) : void 0;
|
|
1724
1834
|
const [entries, totalEntries] = await Promise.all([
|
|
1725
1835
|
strapi2.documents(uid).findMany({
|
|
1726
1836
|
start,
|
|
@@ -1842,21 +1952,7 @@ const bulkUpdaterService = ({ strapi: strapi2 }) => {
|
|
|
1842
1952
|
const displayName = contentType?.info?.displayName || target.uid;
|
|
1843
1953
|
try {
|
|
1844
1954
|
const isNested = attribute.includes(".");
|
|
1845
|
-
|
|
1846
|
-
let parentKey = "";
|
|
1847
|
-
let childKey = "";
|
|
1848
|
-
if (isNested) {
|
|
1849
|
-
const parts = attribute.split(".");
|
|
1850
|
-
parentKey = parts[0];
|
|
1851
|
-
childKey = parts[1];
|
|
1852
|
-
const parentAttrDef = contentType?.attributes?.[parentKey];
|
|
1853
|
-
if (parentAttrDef?.type === "component" && !parentAttrDef.repeatable && parentAttrDef.component) {
|
|
1854
|
-
const compSchema = strapi2.components[parentAttrDef.component];
|
|
1855
|
-
if (compSchema?.attributes?.[childKey]) {
|
|
1856
|
-
isComponentNested = true;
|
|
1857
|
-
}
|
|
1858
|
-
}
|
|
1859
|
-
}
|
|
1955
|
+
const isComponentNested = isNested && isDeepComponentField(contentType, strapi2.components, attribute);
|
|
1860
1956
|
const attrDef = contentType?.attributes?.[attribute];
|
|
1861
1957
|
const hasAttribute = Boolean(attrDef) || isComponentNested;
|
|
1862
1958
|
if (!hasAttribute) {
|
|
@@ -1881,7 +1977,7 @@ const bulkUpdaterService = ({ strapi: strapi2 }) => {
|
|
|
1881
1977
|
if (isComponentNested) {
|
|
1882
1978
|
currentEntry = await strapi2.documents(target.uid).findOne({
|
|
1883
1979
|
documentId: target.documentId,
|
|
1884
|
-
populate:
|
|
1980
|
+
populate: buildDeepPopulate$1(contentType.attributes, strapi2.components)
|
|
1885
1981
|
});
|
|
1886
1982
|
} else if (attrDef?.type === "relation") {
|
|
1887
1983
|
currentEntry = await strapi2.documents(target.uid).findOne({
|
|
@@ -1895,8 +1991,7 @@ const bulkUpdaterService = ({ strapi: strapi2 }) => {
|
|
|
1895
1991
|
}
|
|
1896
1992
|
const entryLabel = currentEntry?.name || currentEntry?.title || currentEntry?.email || `Entry #${target.documentId}`;
|
|
1897
1993
|
if (isComponentNested) {
|
|
1898
|
-
const
|
|
1899
|
-
const currentVal2 = existingParent?.[childKey];
|
|
1994
|
+
const currentVal2 = getDeepProperty(currentEntry, attribute);
|
|
1900
1995
|
let newValue2 = value;
|
|
1901
1996
|
if (regexObj && typeof currentVal2 === "string") {
|
|
1902
1997
|
newValue2 = currentVal2.replace(regexObj, value);
|