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/server/index.mjs
CHANGED
|
@@ -315,12 +315,13 @@ const bulkUpdaterController = ({ strapi: strapi2 }) => ({
|
|
|
315
315
|
async getCollectionEntries(ctx) {
|
|
316
316
|
try {
|
|
317
317
|
const { uid } = ctx.params;
|
|
318
|
-
const { page, pageSize, attribute, filterOperator, filterQuery, search, sortField, sortOrder } = ctx.query;
|
|
318
|
+
const { page, pageSize, attribute, searchAttribute, filterOperator, filterQuery, search, sortField, sortOrder } = ctx.query;
|
|
319
319
|
const service = strapi2.plugin("bulk-updater").service("bulkUpdater");
|
|
320
320
|
const data = await service.getCollectionEntries(uid, {
|
|
321
321
|
page: page ? Number(page) : 1,
|
|
322
322
|
pageSize: pageSize ? Number(pageSize) : 10,
|
|
323
323
|
attribute: attribute ? String(attribute) : void 0,
|
|
324
|
+
searchAttribute: searchAttribute ? String(searchAttribute) : void 0,
|
|
324
325
|
filterOperator: filterOperator ? String(filterOperator) : void 0,
|
|
325
326
|
filterQuery: filterQuery !== void 0 ? String(filterQuery) : void 0,
|
|
326
327
|
search: search ? String(search) : void 0,
|
|
@@ -679,6 +680,127 @@ const modelsCache = /* @__PURE__ */ new Map();
|
|
|
679
680
|
const MAX_QUERY_CACHE_SIZE = 500;
|
|
680
681
|
const CACHE_TTL_MS = 60 * 1e3;
|
|
681
682
|
let staticSchemaCache = null;
|
|
683
|
+
function buildDeepPopulate$1(attributes, allComponents, depth2 = 0) {
|
|
684
|
+
if (depth2 > 5) return true;
|
|
685
|
+
const populate2 = {};
|
|
686
|
+
for (const [key, def] of Object.entries(attributes || {})) {
|
|
687
|
+
if (def.type === "component" && def.component) {
|
|
688
|
+
const comp = allComponents[def.component];
|
|
689
|
+
if (comp?.attributes) {
|
|
690
|
+
populate2[key] = {
|
|
691
|
+
populate: buildDeepPopulate$1(comp.attributes, allComponents, depth2 + 1)
|
|
692
|
+
};
|
|
693
|
+
} else {
|
|
694
|
+
populate2[key] = true;
|
|
695
|
+
}
|
|
696
|
+
} else if (def.type === "dynamiczone") {
|
|
697
|
+
populate2[key] = true;
|
|
698
|
+
} else if (def.type === "relation" || def.type === "media") {
|
|
699
|
+
populate2[key] = true;
|
|
700
|
+
}
|
|
701
|
+
}
|
|
702
|
+
return Object.keys(populate2).length > 0 ? populate2 : true;
|
|
703
|
+
}
|
|
704
|
+
function discoverComponentAttributes(strapi2, compUid, prefix, currentDepth, maxDepth, systemFields, allContentTypes, relationsByAttr, allRelationsMeta, attributesMeta) {
|
|
705
|
+
if (currentDepth > maxDepth || !compUid) return [];
|
|
706
|
+
const compSchema = strapi2.components[compUid];
|
|
707
|
+
if (!compSchema?.attributes) return [];
|
|
708
|
+
const discoveredAttrs = [];
|
|
709
|
+
for (const [subKey, subAttr] of Object.entries(compSchema.attributes)) {
|
|
710
|
+
if (systemFields.includes(subKey)) continue;
|
|
711
|
+
if (subAttr.type === "dynamiczone") continue;
|
|
712
|
+
const fullPath = prefix ? `${prefix}.${subKey}` : subKey;
|
|
713
|
+
if (subAttr.type === "component") {
|
|
714
|
+
if (!subAttr.repeatable && subAttr.component) {
|
|
715
|
+
const deeper = discoverComponentAttributes(
|
|
716
|
+
strapi2,
|
|
717
|
+
subAttr.component,
|
|
718
|
+
fullPath,
|
|
719
|
+
currentDepth + 1,
|
|
720
|
+
maxDepth,
|
|
721
|
+
systemFields,
|
|
722
|
+
allContentTypes,
|
|
723
|
+
relationsByAttr,
|
|
724
|
+
allRelationsMeta,
|
|
725
|
+
attributesMeta
|
|
726
|
+
);
|
|
727
|
+
discoveredAttrs.push(...deeper);
|
|
728
|
+
}
|
|
729
|
+
} else if (subAttr.type === "relation") {
|
|
730
|
+
const targetUid = subAttr.target;
|
|
731
|
+
if (targetUid && allContentTypes[targetUid]) {
|
|
732
|
+
const targetInfo = allContentTypes[targetUid]?.info;
|
|
733
|
+
const isMulti = subAttr.relation === "oneToMany" || subAttr.relation === "manyToMany";
|
|
734
|
+
const relMeta = {
|
|
735
|
+
isRelation: true,
|
|
736
|
+
relationType: subAttr.relation,
|
|
737
|
+
targetUid,
|
|
738
|
+
targetDisplayName: targetInfo?.displayName || targetUid,
|
|
739
|
+
isMulti
|
|
740
|
+
};
|
|
741
|
+
relationsByAttr[fullPath] = relMeta;
|
|
742
|
+
allRelationsMeta[fullPath] = relMeta;
|
|
743
|
+
attributesMeta[fullPath] = { depth: currentDepth, type: "relation", component: compUid, isRelation: true };
|
|
744
|
+
discoveredAttrs.push(fullPath);
|
|
745
|
+
}
|
|
746
|
+
} else {
|
|
747
|
+
attributesMeta[fullPath] = { depth: currentDepth, type: subAttr.type, component: compUid };
|
|
748
|
+
discoveredAttrs.push(fullPath);
|
|
749
|
+
}
|
|
750
|
+
}
|
|
751
|
+
return discoveredAttrs;
|
|
752
|
+
}
|
|
753
|
+
function isDeepComponentField(contentType, allComponents, attribute) {
|
|
754
|
+
if (!attribute || !attribute.includes(".")) return false;
|
|
755
|
+
const parts = attribute.split(".");
|
|
756
|
+
let currentSchema = contentType;
|
|
757
|
+
for (let i = 0; i < parts.length - 1; i++) {
|
|
758
|
+
const part = parts[i];
|
|
759
|
+
const attrDef = currentSchema?.attributes?.[part];
|
|
760
|
+
if (!attrDef || attrDef.type !== "component" || !attrDef.component) return false;
|
|
761
|
+
currentSchema = allComponents[attrDef.component];
|
|
762
|
+
if (!currentSchema) return false;
|
|
763
|
+
}
|
|
764
|
+
const leafField = parts[parts.length - 1];
|
|
765
|
+
return Boolean(currentSchema?.attributes?.[leafField]);
|
|
766
|
+
}
|
|
767
|
+
function getLeafAttributeSchema(contentType, allComponents, attribute) {
|
|
768
|
+
if (!attribute) return null;
|
|
769
|
+
if (!attribute.includes(".")) return contentType?.attributes?.[attribute] || null;
|
|
770
|
+
const parts = attribute.split(".");
|
|
771
|
+
let currentSchema = contentType;
|
|
772
|
+
for (let i = 0; i < parts.length - 1; i++) {
|
|
773
|
+
const part = parts[i];
|
|
774
|
+
const attrDef = currentSchema?.attributes?.[part];
|
|
775
|
+
if (!attrDef || attrDef.type !== "component" || !attrDef.component) return null;
|
|
776
|
+
currentSchema = allComponents[attrDef.component];
|
|
777
|
+
if (!currentSchema) return null;
|
|
778
|
+
}
|
|
779
|
+
return currentSchema?.attributes?.[parts[parts.length - 1]] || null;
|
|
780
|
+
}
|
|
781
|
+
function setDeepProperty(obj, pathParts, value) {
|
|
782
|
+
if (pathParts.length === 0) return value;
|
|
783
|
+
const current = { ...obj || {} };
|
|
784
|
+
const [head, ...tail] = pathParts;
|
|
785
|
+
if (tail.length === 0) {
|
|
786
|
+
current[head] = value;
|
|
787
|
+
} else {
|
|
788
|
+
current[head] = setDeepProperty(current[head] || {}, tail, value);
|
|
789
|
+
}
|
|
790
|
+
return current;
|
|
791
|
+
}
|
|
792
|
+
function getDeepProperty(obj, path2) {
|
|
793
|
+
if (!obj || !path2) return void 0;
|
|
794
|
+
if (!path2.includes(".")) return obj[path2];
|
|
795
|
+
return path2.split(".").reduce((acc, part) => acc && typeof acc === "object" ? acc[part] : void 0, obj);
|
|
796
|
+
}
|
|
797
|
+
function buildDeepFilter(pathParts, condition) {
|
|
798
|
+
if (pathParts.length === 0) return condition;
|
|
799
|
+
const [head, ...tail] = pathParts;
|
|
800
|
+
return {
|
|
801
|
+
[head]: buildDeepFilter(tail, condition)
|
|
802
|
+
};
|
|
803
|
+
}
|
|
682
804
|
function getSafeTimezone(timeZone) {
|
|
683
805
|
if (!timeZone || typeof timeZone !== "string") {
|
|
684
806
|
return Intl.DateTimeFormat().resolvedOptions().timeZone || "UTC";
|
|
@@ -887,43 +1009,28 @@ async function executeBatchInternal(strapi2, {
|
|
|
887
1009
|
const currentEntry = await getDocumentDeduplicated(target.uid, target.documentId);
|
|
888
1010
|
const entryLabel = currentEntry?.name || currentEntry?.title || currentEntry?.email || `Entry #${target.documentId}`;
|
|
889
1011
|
const isNested = attribute.includes(".");
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
if (isNested) {
|
|
894
|
-
const parts = attribute.split(".");
|
|
895
|
-
parentKey = parts[0];
|
|
896
|
-
childKey = parts[1];
|
|
897
|
-
const parentAttrDef = contentType?.attributes?.[parentKey];
|
|
898
|
-
if (parentAttrDef?.type === "component" && !parentAttrDef.repeatable && parentAttrDef.component) {
|
|
899
|
-
const compSchema = strapi2.components[parentAttrDef.component];
|
|
900
|
-
if (compSchema?.attributes?.[childKey]) {
|
|
901
|
-
isComponentNested = true;
|
|
902
|
-
}
|
|
903
|
-
}
|
|
904
|
-
}
|
|
1012
|
+
const isComponentNested = isNested && isDeepComponentField(contentType, strapi2.components, attribute);
|
|
1013
|
+
const parts = isNested ? attribute.split(".") : [];
|
|
1014
|
+
const rootKey = isNested ? parts[0] : "";
|
|
905
1015
|
const attrDef = contentType?.attributes?.[attribute];
|
|
906
1016
|
const hasAttribute = Boolean(attrDef) || isComponentNested;
|
|
907
1017
|
if (hasAttribute) {
|
|
908
1018
|
if (isComponentNested) {
|
|
909
1019
|
const currentEntryWithPopulate = await strapi2.documents(target.uid).findOne({
|
|
910
1020
|
documentId: target.documentId,
|
|
911
|
-
populate:
|
|
1021
|
+
populate: buildDeepPopulate$1(contentType.attributes, strapi2.components)
|
|
912
1022
|
});
|
|
913
|
-
const
|
|
914
|
-
const currentVal2 =
|
|
1023
|
+
const existingRoot = currentEntryWithPopulate?.[rootKey] || {};
|
|
1024
|
+
const currentVal2 = getDeepProperty(existingRoot, parts.slice(1).join("."));
|
|
915
1025
|
let newValue2 = value;
|
|
916
1026
|
if (regexObj && typeof currentVal2 === "string") {
|
|
917
1027
|
newValue2 = currentVal2.replace(regexObj, value);
|
|
918
1028
|
}
|
|
919
|
-
const
|
|
920
|
-
...existingParent,
|
|
921
|
-
[childKey]: newValue2
|
|
922
|
-
};
|
|
1029
|
+
const updatedRoot = setDeepProperty(existingRoot, parts.slice(1), newValue2);
|
|
923
1030
|
await strapi2.documents(target.uid).update({
|
|
924
1031
|
documentId: target.documentId,
|
|
925
1032
|
data: {
|
|
926
|
-
[
|
|
1033
|
+
[rootKey]: updatedRoot
|
|
927
1034
|
}
|
|
928
1035
|
});
|
|
929
1036
|
const isDraftAndPublishComp = Boolean(contentType?.options?.draftAndPublish);
|
|
@@ -1358,12 +1465,14 @@ const bulkUpdaterService = ({ strapi: strapi2 }) => {
|
|
|
1358
1465
|
}
|
|
1359
1466
|
const metaByUid = {};
|
|
1360
1467
|
const allRelationsMeta = {};
|
|
1468
|
+
const allAttributesMeta = {};
|
|
1361
1469
|
for (const uid of targetUids) {
|
|
1362
1470
|
const contentType = allContentTypes[uid];
|
|
1363
1471
|
if (!contentType || contentType.kind !== "collectionType" && contentType.kind !== "singleType") continue;
|
|
1364
1472
|
const isSingleType = contentType.kind === "singleType";
|
|
1365
1473
|
const rawAttrs = contentType.attributes || {};
|
|
1366
1474
|
const relationsByAttr = {};
|
|
1475
|
+
const colAttributesMeta = {};
|
|
1367
1476
|
const nestedComponentAttrs = [];
|
|
1368
1477
|
const validAttrs = Object.keys(rawAttrs).filter((attrKey) => {
|
|
1369
1478
|
if (systemFields.includes(attrKey)) return false;
|
|
@@ -1371,14 +1480,19 @@ const bulkUpdaterService = ({ strapi: strapi2 }) => {
|
|
|
1371
1480
|
if (rawAttrs[attrKey].type === "component") {
|
|
1372
1481
|
const compDef = rawAttrs[attrKey];
|
|
1373
1482
|
if (!compDef.repeatable && compDef.component) {
|
|
1374
|
-
const
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1483
|
+
const compAttrs = discoverComponentAttributes(
|
|
1484
|
+
strapi2,
|
|
1485
|
+
compDef.component,
|
|
1486
|
+
attrKey,
|
|
1487
|
+
1,
|
|
1488
|
+
5,
|
|
1489
|
+
systemFields,
|
|
1490
|
+
allContentTypes,
|
|
1491
|
+
relationsByAttr,
|
|
1492
|
+
allRelationsMeta,
|
|
1493
|
+
colAttributesMeta
|
|
1494
|
+
);
|
|
1495
|
+
nestedComponentAttrs.push(...compAttrs);
|
|
1382
1496
|
}
|
|
1383
1497
|
return false;
|
|
1384
1498
|
}
|
|
@@ -1397,12 +1511,19 @@ const bulkUpdaterService = ({ strapi: strapi2 }) => {
|
|
|
1397
1511
|
};
|
|
1398
1512
|
relationsByAttr[attrKey] = relMeta;
|
|
1399
1513
|
allRelationsMeta[attrKey] = relMeta;
|
|
1514
|
+
colAttributesMeta[attrKey] = { depth: 0, type: "relation", isRelation: true };
|
|
1400
1515
|
return true;
|
|
1401
1516
|
}
|
|
1517
|
+
colAttributesMeta[attrKey] = { depth: 0, type: rawAttrs[attrKey].type };
|
|
1402
1518
|
return true;
|
|
1403
1519
|
});
|
|
1404
1520
|
const allColAttrs = [...validAttrs, ...nestedComponentAttrs];
|
|
1405
|
-
allColAttrs.forEach((attr) =>
|
|
1521
|
+
allColAttrs.forEach((attr) => {
|
|
1522
|
+
allAttributesSet.add(attr);
|
|
1523
|
+
if (colAttributesMeta[attr]) {
|
|
1524
|
+
allAttributesMeta[attr] = colAttributesMeta[attr];
|
|
1525
|
+
}
|
|
1526
|
+
});
|
|
1406
1527
|
metaByUid[uid] = {
|
|
1407
1528
|
uid,
|
|
1408
1529
|
kind: contentType.kind,
|
|
@@ -1412,11 +1533,13 @@ const bulkUpdaterService = ({ strapi: strapi2 }) => {
|
|
|
1412
1533
|
pluralName: contentType.info?.pluralName || uid,
|
|
1413
1534
|
displayName: contentType.info?.displayName || uid,
|
|
1414
1535
|
attributes: allColAttrs,
|
|
1536
|
+
attributesMeta: colAttributesMeta,
|
|
1415
1537
|
relations: relationsByAttr
|
|
1416
1538
|
};
|
|
1417
1539
|
}
|
|
1418
1540
|
staticSchemaCache = {
|
|
1419
1541
|
attributes: Array.from(allAttributesSet),
|
|
1542
|
+
attributesMeta: allAttributesMeta,
|
|
1420
1543
|
targetUids: Object.keys(metaByUid),
|
|
1421
1544
|
metaByUid,
|
|
1422
1545
|
relationsMeta: allRelationsMeta
|
|
@@ -1447,17 +1570,7 @@ const bulkUpdaterService = ({ strapi: strapi2 }) => {
|
|
|
1447
1570
|
let entries = [];
|
|
1448
1571
|
let totalCount = 0;
|
|
1449
1572
|
try {
|
|
1450
|
-
const
|
|
1451
|
-
const relKeys = Object.keys(meta.relations || {});
|
|
1452
|
-
const compKeys = Object.keys(ctAttrs).filter((k) => ctAttrs[k].type === "component");
|
|
1453
|
-
const populateOptionObj = {};
|
|
1454
|
-
relKeys.forEach((k) => {
|
|
1455
|
-
populateOptionObj[k] = true;
|
|
1456
|
-
});
|
|
1457
|
-
compKeys.forEach((k) => {
|
|
1458
|
-
populateOptionObj[k] = true;
|
|
1459
|
-
});
|
|
1460
|
-
const populateOption = Object.keys(populateOptionObj).length > 0 ? populateOptionObj : void 0;
|
|
1573
|
+
const populateOption = buildDeepPopulate$1(allContentTypes[uid]?.attributes || {}, strapi2.components);
|
|
1461
1574
|
if (meta.isSingleType) {
|
|
1462
1575
|
const singleDoc = await strapi2.documents(uid).findFirst({
|
|
1463
1576
|
populate: populateOption
|
|
@@ -1516,8 +1629,10 @@ const bulkUpdaterService = ({ strapi: strapi2 }) => {
|
|
|
1516
1629
|
return {
|
|
1517
1630
|
success: true,
|
|
1518
1631
|
attributes: staticSchemaCache.attributes,
|
|
1632
|
+
attributesMeta: staticSchemaCache.attributesMeta,
|
|
1519
1633
|
collections,
|
|
1520
1634
|
relationsMeta: staticSchemaCache.relationsMeta,
|
|
1635
|
+
maxDiscoveredDepth: 5,
|
|
1521
1636
|
executionWindow: {
|
|
1522
1637
|
...executionConfig,
|
|
1523
1638
|
...windowStatus
|
|
@@ -1536,6 +1651,7 @@ const bulkUpdaterService = ({ strapi: strapi2 }) => {
|
|
|
1536
1651
|
page = 1,
|
|
1537
1652
|
pageSize = 10,
|
|
1538
1653
|
attribute,
|
|
1654
|
+
searchAttribute,
|
|
1539
1655
|
filterOperator,
|
|
1540
1656
|
filterQuery,
|
|
1541
1657
|
search,
|
|
@@ -1550,8 +1666,9 @@ const bulkUpdaterService = ({ strapi: strapi2 }) => {
|
|
|
1550
1666
|
const currentPage = Math.max(Number(page) || 1, 1);
|
|
1551
1667
|
const start = (currentPage - 1) * limit;
|
|
1552
1668
|
const isSingleType = contentType.kind === "singleType";
|
|
1669
|
+
const targetFilterAttr = searchAttribute || attribute;
|
|
1553
1670
|
const signature = await getCollectionSignature(strapi2, uid);
|
|
1554
|
-
const cacheKey = `${uid}:${limit}:${start}:${attribute || ""}:${filterOperator || ""}:${filterQuery || ""}:${search || ""}:${sortField || ""}:${sortOrder}`;
|
|
1671
|
+
const cacheKey = `${uid}:${limit}:${start}:${attribute || ""}:${searchAttribute || ""}:${filterOperator || ""}:${filterQuery || ""}:${search || ""}:${sortField || ""}:${sortOrder}`;
|
|
1555
1672
|
const cached = queryCache.get(cacheKey);
|
|
1556
1673
|
const etag = `W/"entry-${crypto.createHash("md5").update(`${cacheKey}:${signature}`).digest("hex")}"`;
|
|
1557
1674
|
if (cached && cached.signature === signature && Date.now() - cached.timestamp < CACHE_TTL_MS) {
|
|
@@ -1566,19 +1683,15 @@ const bulkUpdaterService = ({ strapi: strapi2 }) => {
|
|
|
1566
1683
|
const attrs = contentType.attributes || {};
|
|
1567
1684
|
let colHasAttribute = false;
|
|
1568
1685
|
let isNestedAttr = false;
|
|
1569
|
-
let
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
if (compSchema?.attributes?.[childKey]) {
|
|
1577
|
-
colHasAttribute = true;
|
|
1578
|
-
isNestedAttr = true;
|
|
1579
|
-
}
|
|
1686
|
+
let parts = [];
|
|
1687
|
+
if (targetFilterAttr) {
|
|
1688
|
+
if (targetFilterAttr.includes(".")) {
|
|
1689
|
+
isNestedAttr = isDeepComponentField(contentType, strapi2.components, targetFilterAttr);
|
|
1690
|
+
if (isNestedAttr) {
|
|
1691
|
+
colHasAttribute = true;
|
|
1692
|
+
parts = targetFilterAttr.split(".");
|
|
1580
1693
|
}
|
|
1581
|
-
} else if (attrs[
|
|
1694
|
+
} else if (attrs[targetFilterAttr]) {
|
|
1582
1695
|
colHasAttribute = true;
|
|
1583
1696
|
}
|
|
1584
1697
|
}
|
|
@@ -1603,7 +1716,7 @@ const bulkUpdaterService = ({ strapi: strapi2 }) => {
|
|
|
1603
1716
|
}
|
|
1604
1717
|
let condition = void 0;
|
|
1605
1718
|
const q = (filterQuery || "").trim();
|
|
1606
|
-
const targetAttrSchema = isNestedAttr ? strapi2.components
|
|
1719
|
+
const targetAttrSchema = isNestedAttr ? getLeafAttributeSchema(contentType, strapi2.components, targetFilterAttr) : attrs[targetFilterAttr];
|
|
1607
1720
|
const isStringLike = ["string", "text", "email", "richtext", "uid"].includes(targetAttrSchema?.type);
|
|
1608
1721
|
if (normOp === "empty") {
|
|
1609
1722
|
condition = isStringLike ? { $or: [{ $null: true }, { $eq: "" }] } : { $null: true };
|
|
@@ -1633,19 +1746,18 @@ const bulkUpdaterService = ({ strapi: strapi2 }) => {
|
|
|
1633
1746
|
}
|
|
1634
1747
|
if (condition !== void 0) {
|
|
1635
1748
|
if (isNestedAttr) {
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
};
|
|
1749
|
+
const deepFilter = buildDeepFilter(parts, condition);
|
|
1750
|
+
Object.assign(filters2, deepFilter);
|
|
1639
1751
|
} else {
|
|
1640
1752
|
if (normOp === "empty" && isStringLike) {
|
|
1641
1753
|
filters2.$or = [
|
|
1642
|
-
{ [
|
|
1643
|
-
{ [
|
|
1754
|
+
{ [targetFilterAttr]: { $null: true } },
|
|
1755
|
+
{ [targetFilterAttr]: { $eq: "" } }
|
|
1644
1756
|
];
|
|
1645
1757
|
} else if (normOp === "notempty" && isStringLike) {
|
|
1646
|
-
filters2[
|
|
1758
|
+
filters2[targetFilterAttr] = { $notNull: true, $ne: "" };
|
|
1647
1759
|
} else {
|
|
1648
|
-
filters2[
|
|
1760
|
+
filters2[targetFilterAttr] = condition;
|
|
1649
1761
|
}
|
|
1650
1762
|
}
|
|
1651
1763
|
}
|
|
@@ -1668,11 +1780,13 @@ const bulkUpdaterService = ({ strapi: strapi2 }) => {
|
|
|
1668
1780
|
}
|
|
1669
1781
|
}
|
|
1670
1782
|
}
|
|
1783
|
+
const populateOption = buildDeepPopulate$1(contentType.attributes, strapi2.components);
|
|
1671
1784
|
if (isSingleType) {
|
|
1672
1785
|
let singleDoc = null;
|
|
1673
1786
|
try {
|
|
1674
1787
|
singleDoc = await strapi2.documents(uid).findFirst({
|
|
1675
|
-
filters: Object.keys(filters2).length > 0 ? filters2 : void 0
|
|
1788
|
+
filters: Object.keys(filters2).length > 0 ? filters2 : void 0,
|
|
1789
|
+
populate: populateOption
|
|
1676
1790
|
});
|
|
1677
1791
|
} catch {
|
|
1678
1792
|
singleDoc = null;
|
|
@@ -1691,11 +1805,11 @@ const bulkUpdaterService = ({ strapi: strapi2 }) => {
|
|
|
1691
1805
|
}
|
|
1692
1806
|
};
|
|
1693
1807
|
} else {
|
|
1694
|
-
|
|
1808
|
+
let sortClause = {};
|
|
1695
1809
|
if (sortField && sortField.includes(".")) {
|
|
1696
|
-
const
|
|
1697
|
-
if (contentType.
|
|
1698
|
-
sortClause
|
|
1810
|
+
const sortParts = sortField.split(".");
|
|
1811
|
+
if (isDeepComponentField(contentType, strapi2.components, sortField)) {
|
|
1812
|
+
sortClause = buildDeepFilter(sortParts, sortOrder);
|
|
1699
1813
|
} else {
|
|
1700
1814
|
sortClause["createdAt"] = "desc";
|
|
1701
1815
|
}
|
|
@@ -1704,10 +1818,6 @@ const bulkUpdaterService = ({ strapi: strapi2 }) => {
|
|
|
1704
1818
|
} else {
|
|
1705
1819
|
sortClause["createdAt"] = "desc";
|
|
1706
1820
|
}
|
|
1707
|
-
const populateAttrs = Object.keys(contentType.attributes || {}).filter(
|
|
1708
|
-
(k) => contentType.attributes[k].type === "relation" || contentType.attributes[k].type === "component"
|
|
1709
|
-
);
|
|
1710
|
-
const populateOption = populateAttrs.length > 0 ? populateAttrs.reduce((acc, k) => ({ ...acc, [k]: true }), {}) : void 0;
|
|
1711
1821
|
const [entries, totalEntries] = await Promise.all([
|
|
1712
1822
|
strapi2.documents(uid).findMany({
|
|
1713
1823
|
start,
|
|
@@ -1829,21 +1939,7 @@ const bulkUpdaterService = ({ strapi: strapi2 }) => {
|
|
|
1829
1939
|
const displayName = contentType?.info?.displayName || target.uid;
|
|
1830
1940
|
try {
|
|
1831
1941
|
const isNested = attribute.includes(".");
|
|
1832
|
-
|
|
1833
|
-
let parentKey = "";
|
|
1834
|
-
let childKey = "";
|
|
1835
|
-
if (isNested) {
|
|
1836
|
-
const parts = attribute.split(".");
|
|
1837
|
-
parentKey = parts[0];
|
|
1838
|
-
childKey = parts[1];
|
|
1839
|
-
const parentAttrDef = contentType?.attributes?.[parentKey];
|
|
1840
|
-
if (parentAttrDef?.type === "component" && !parentAttrDef.repeatable && parentAttrDef.component) {
|
|
1841
|
-
const compSchema = strapi2.components[parentAttrDef.component];
|
|
1842
|
-
if (compSchema?.attributes?.[childKey]) {
|
|
1843
|
-
isComponentNested = true;
|
|
1844
|
-
}
|
|
1845
|
-
}
|
|
1846
|
-
}
|
|
1942
|
+
const isComponentNested = isNested && isDeepComponentField(contentType, strapi2.components, attribute);
|
|
1847
1943
|
const attrDef = contentType?.attributes?.[attribute];
|
|
1848
1944
|
const hasAttribute = Boolean(attrDef) || isComponentNested;
|
|
1849
1945
|
if (!hasAttribute) {
|
|
@@ -1868,7 +1964,7 @@ const bulkUpdaterService = ({ strapi: strapi2 }) => {
|
|
|
1868
1964
|
if (isComponentNested) {
|
|
1869
1965
|
currentEntry = await strapi2.documents(target.uid).findOne({
|
|
1870
1966
|
documentId: target.documentId,
|
|
1871
|
-
populate:
|
|
1967
|
+
populate: buildDeepPopulate$1(contentType.attributes, strapi2.components)
|
|
1872
1968
|
});
|
|
1873
1969
|
} else if (attrDef?.type === "relation") {
|
|
1874
1970
|
currentEntry = await strapi2.documents(target.uid).findOne({
|
|
@@ -1882,8 +1978,7 @@ const bulkUpdaterService = ({ strapi: strapi2 }) => {
|
|
|
1882
1978
|
}
|
|
1883
1979
|
const entryLabel = currentEntry?.name || currentEntry?.title || currentEntry?.email || `Entry #${target.documentId}`;
|
|
1884
1980
|
if (isComponentNested) {
|
|
1885
|
-
const
|
|
1886
|
-
const currentVal2 = existingParent?.[childKey];
|
|
1981
|
+
const currentVal2 = getDeepProperty(currentEntry, attribute);
|
|
1887
1982
|
let newValue2 = value;
|
|
1888
1983
|
if (regexObj && typeof currentVal2 === "string") {
|
|
1889
1984
|
newValue2 = currentVal2.replace(regexObj, value);
|