payload 3.80.0-internal.cdd7ef7 → 3.80.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/dist/admin/elements/Nav.d.ts +0 -13
- package/dist/admin/elements/Nav.d.ts.map +1 -1
- package/dist/admin/elements/Nav.js.map +1 -1
- package/dist/admin/functions/index.d.ts +38 -1
- package/dist/admin/functions/index.d.ts.map +1 -1
- package/dist/admin/functions/index.js.map +1 -1
- package/dist/admin/types.d.ts +4 -5
- package/dist/admin/types.d.ts.map +1 -1
- package/dist/admin/types.js.map +1 -1
- package/dist/admin/views/folderList.d.ts +56 -0
- package/dist/admin/views/folderList.d.ts.map +1 -0
- package/dist/admin/views/folderList.js +3 -0
- package/dist/admin/views/folderList.js.map +1 -0
- package/dist/admin/views/index.d.ts +3 -1
- package/dist/admin/views/index.d.ts.map +1 -1
- package/dist/admin/views/index.js.map +1 -1
- package/dist/admin/views/list.d.ts +2 -43
- package/dist/admin/views/list.d.ts.map +1 -1
- package/dist/admin/views/list.js.map +1 -1
- package/dist/bin/generateImportMap/iterateCollections.d.ts.map +1 -1
- package/dist/bin/generateImportMap/iterateCollections.js +0 -1
- package/dist/bin/generateImportMap/iterateCollections.js.map +1 -1
- package/dist/bin/generateImportMap/iterateConfig.d.ts.map +1 -1
- package/dist/bin/generateImportMap/iterateConfig.js +0 -7
- package/dist/bin/generateImportMap/iterateConfig.js.map +1 -1
- package/dist/collections/config/client.d.ts +1 -3
- package/dist/collections/config/client.d.ts.map +1 -1
- package/dist/collections/config/client.js +0 -11
- package/dist/collections/config/client.js.map +1 -1
- package/dist/collections/config/defaults.js +1 -1
- package/dist/collections/config/defaults.js.map +1 -1
- package/dist/collections/config/sanitize.d.ts.map +1 -1
- package/dist/collections/config/sanitize.js +7 -3
- package/dist/collections/config/sanitize.js.map +1 -1
- package/dist/collections/config/types.d.ts +7 -29
- package/dist/collections/config/types.d.ts.map +1 -1
- package/dist/collections/config/types.js.map +1 -1
- package/dist/collections/operations/create.js +17 -17
- package/dist/collections/operations/create.js.map +1 -1
- package/dist/collections/operations/findByID.js +3 -3
- package/dist/collections/operations/findByID.js.map +1 -1
- package/dist/collections/operations/update.js +1 -1
- package/dist/collections/operations/update.js.map +1 -1
- package/dist/collections/operations/utilities/update.d.ts.map +1 -1
- package/dist/collections/operations/utilities/update.js +6 -6
- package/dist/collections/operations/utilities/update.js.map +1 -1
- package/dist/config/client.d.ts.map +1 -1
- package/dist/config/client.js +10 -0
- package/dist/config/client.js.map +1 -1
- package/dist/config/defaults.d.ts.map +1 -1
- package/dist/config/defaults.js +15 -0
- package/dist/config/defaults.js.map +1 -1
- package/dist/config/sanitize.d.ts.map +1 -1
- package/dist/config/sanitize.js +26 -3
- package/dist/config/sanitize.js.map +1 -1
- package/dist/config/types.d.ts +12 -26
- package/dist/config/types.d.ts.map +1 -1
- package/dist/config/types.js.map +1 -1
- package/dist/exports/shared.d.ts +3 -2
- package/dist/exports/shared.d.ts.map +1 -1
- package/dist/exports/shared.js +2 -1
- package/dist/exports/shared.js.map +1 -1
- package/dist/fields/baseFields/slug/index.d.ts +7 -0
- package/dist/fields/baseFields/slug/index.d.ts.map +1 -1
- package/dist/fields/baseFields/slug/index.js +2 -2
- package/dist/fields/baseFields/slug/index.js.map +1 -1
- package/dist/fields/config/sanitize.d.ts.map +1 -1
- package/dist/fields/config/sanitize.js +0 -4
- package/dist/fields/config/sanitize.js.map +1 -1
- package/dist/fields/config/sanitizeJoinField.d.ts.map +1 -1
- package/dist/fields/config/sanitizeJoinField.js +0 -3
- package/dist/fields/config/sanitizeJoinField.js.map +1 -1
- package/dist/folders/addFolderCollection.d.ts +10 -0
- package/dist/folders/addFolderCollection.d.ts.map +1 -0
- package/dist/folders/addFolderCollection.js +26 -0
- package/dist/folders/addFolderCollection.js.map +1 -0
- package/dist/folders/addFolderFieldToCollection.d.ts +8 -0
- package/dist/folders/addFolderFieldToCollection.d.ts.map +1 -0
- package/dist/folders/addFolderFieldToCollection.js +20 -0
- package/dist/folders/addFolderFieldToCollection.js.map +1 -0
- package/dist/folders/buildFolderField.d.ts +8 -0
- package/dist/folders/buildFolderField.d.ts.map +1 -0
- package/dist/folders/buildFolderField.js +87 -0
- package/dist/folders/buildFolderField.js.map +1 -0
- package/dist/folders/constants.d.ts +3 -0
- package/dist/folders/constants.d.ts.map +1 -0
- package/dist/folders/constants.js +4 -0
- package/dist/folders/constants.js.map +1 -0
- package/dist/folders/createFolderCollection.d.ts +11 -0
- package/dist/folders/createFolderCollection.d.ts.map +1 -0
- package/dist/folders/createFolderCollection.js +115 -0
- package/dist/folders/createFolderCollection.js.map +1 -0
- package/dist/folders/hooks/deleteSubfoldersAfterDelete.d.ts +8 -0
- package/dist/folders/hooks/deleteSubfoldersAfterDelete.d.ts.map +1 -0
- package/dist/folders/hooks/deleteSubfoldersAfterDelete.js +15 -0
- package/dist/folders/hooks/deleteSubfoldersAfterDelete.js.map +1 -0
- package/dist/folders/hooks/dissasociateAfterDelete.d.ts +8 -0
- package/dist/folders/hooks/dissasociateAfterDelete.d.ts.map +1 -0
- package/dist/folders/hooks/dissasociateAfterDelete.js +20 -0
- package/dist/folders/hooks/dissasociateAfterDelete.js.map +1 -0
- package/dist/folders/hooks/ensureSafeCollectionsChange.d.ts +5 -0
- package/dist/folders/hooks/ensureSafeCollectionsChange.d.ts.map +1 -0
- package/dist/folders/hooks/ensureSafeCollectionsChange.js +107 -0
- package/dist/folders/hooks/ensureSafeCollectionsChange.js.map +1 -0
- package/dist/folders/hooks/reparentChildFolder.d.ts +24 -0
- package/dist/folders/hooks/reparentChildFolder.d.ts.map +1 -0
- package/dist/folders/hooks/reparentChildFolder.js +72 -0
- package/dist/folders/hooks/reparentChildFolder.js.map +1 -0
- package/dist/folders/types.d.ts +118 -0
- package/dist/folders/types.d.ts.map +1 -0
- package/dist/folders/types.js +3 -0
- package/dist/folders/types.js.map +1 -0
- package/dist/folders/utils/buildFolderWhereConstraints.d.ts +13 -0
- package/dist/folders/utils/buildFolderWhereConstraints.d.ts.map +1 -0
- package/dist/folders/utils/buildFolderWhereConstraints.js +45 -0
- package/dist/folders/utils/buildFolderWhereConstraints.js.map +1 -0
- package/dist/folders/utils/formatFolderOrDocumentItem.d.ts +12 -0
- package/dist/folders/utils/formatFolderOrDocumentItem.d.ts.map +1 -0
- package/dist/folders/utils/formatFolderOrDocumentItem.js +30 -0
- package/dist/folders/utils/formatFolderOrDocumentItem.js.map +1 -0
- package/dist/folders/utils/getFolderBreadcrumbs.d.ts +14 -0
- package/dist/folders/utils/getFolderBreadcrumbs.d.ts.map +1 -0
- package/dist/folders/utils/getFolderBreadcrumbs.js +45 -0
- package/dist/folders/utils/getFolderBreadcrumbs.js.map +1 -0
- package/dist/folders/utils/getFolderData.d.ts +33 -0
- package/dist/folders/utils/getFolderData.d.ts.map +1 -0
- package/dist/folders/utils/getFolderData.js +88 -0
- package/dist/folders/utils/getFolderData.js.map +1 -0
- package/dist/folders/utils/getFoldersAndDocumentsFromJoin.d.ts +24 -0
- package/dist/folders/utils/getFoldersAndDocumentsFromJoin.d.ts.map +1 -0
- package/dist/folders/utils/getFoldersAndDocumentsFromJoin.js +66 -0
- package/dist/folders/utils/getFoldersAndDocumentsFromJoin.js.map +1 -0
- package/dist/folders/utils/getOrphanedDocs.d.ts +15 -0
- package/dist/folders/utils/getOrphanedDocs.d.ts.map +1 -0
- package/dist/folders/utils/getOrphanedDocs.js +40 -0
- package/dist/folders/utils/getOrphanedDocs.js.map +1 -0
- package/dist/globals/config/types.d.ts +0 -4
- package/dist/globals/config/types.d.ts.map +1 -1
- package/dist/globals/config/types.js.map +1 -1
- package/dist/globals/operations/update.d.ts.map +1 -1
- package/dist/globals/operations/update.js +2 -1
- package/dist/globals/operations/update.js.map +1 -1
- package/dist/index.bundled.d.ts +288 -577
- package/dist/index.d.ts +9 -23
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -13
- package/dist/index.js.map +1 -1
- package/dist/preferences/keys.d.ts +4 -8
- package/dist/preferences/keys.d.ts.map +1 -1
- package/dist/preferences/keys.js +4 -7
- package/dist/preferences/keys.js.map +1 -1
- package/dist/types/index.d.ts +0 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js.map +1 -1
- package/dist/utilities/addDataAndFileToRequest.d.ts.map +1 -1
- package/dist/utilities/addDataAndFileToRequest.js +7 -1
- package/dist/utilities/addDataAndFileToRequest.js.map +1 -1
- package/dist/utilities/extractID.js +1 -1
- package/dist/utilities/extractID.js.map +1 -1
- package/dist/utilities/formatAdminURL.d.ts +2 -13
- package/dist/utilities/formatAdminURL.d.ts.map +1 -1
- package/dist/utilities/formatAdminURL.js.map +1 -1
- package/dist/versions/saveVersion.d.ts +1 -0
- package/dist/versions/saveVersion.d.ts.map +1 -1
- package/dist/versions/saveVersion.js +16 -66
- package/dist/versions/saveVersion.js.map +1 -1
- package/dist/versions/updateLatestVersion.d.ts +24 -0
- package/dist/versions/updateLatestVersion.d.ts.map +1 -0
- package/dist/versions/updateLatestVersion.js +64 -0
- package/dist/versions/updateLatestVersion.js.map +1 -0
- package/package.json +4 -4
- package/dist/admin/views/hierarchyList.d.ts +0 -9
- package/dist/admin/views/hierarchyList.d.ts.map +0 -1
- package/dist/admin/views/hierarchyList.js +0 -3
- package/dist/admin/views/hierarchyList.js.map +0 -1
- package/dist/hierarchy/addHierarchyToCollection.d.ts +0 -8
- package/dist/hierarchy/addHierarchyToCollection.d.ts.map +0 -1
- package/dist/hierarchy/addHierarchyToCollection.js +0 -62
- package/dist/hierarchy/addHierarchyToCollection.js.map +0 -1
- package/dist/hierarchy/buildParentField.d.ts +0 -11
- package/dist/hierarchy/buildParentField.d.ts.map +0 -1
- package/dist/hierarchy/buildParentField.js +0 -42
- package/dist/hierarchy/buildParentField.js.map +0 -1
- package/dist/hierarchy/constants.d.ts +0 -15
- package/dist/hierarchy/constants.d.ts.map +0 -1
- package/dist/hierarchy/constants.js +0 -11
- package/dist/hierarchy/constants.js.map +0 -1
- package/dist/hierarchy/createFolderField.d.ts +0 -39
- package/dist/hierarchy/createFolderField.d.ts.map +0 -1
- package/dist/hierarchy/createFolderField.js +0 -54
- package/dist/hierarchy/createFolderField.js.map +0 -1
- package/dist/hierarchy/createFoldersCollection.d.ts +0 -57
- package/dist/hierarchy/createFoldersCollection.d.ts.map +0 -1
- package/dist/hierarchy/createFoldersCollection.js +0 -63
- package/dist/hierarchy/createFoldersCollection.js.map +0 -1
- package/dist/hierarchy/createTagField.d.ts +0 -44
- package/dist/hierarchy/createTagField.d.ts.map +0 -1
- package/dist/hierarchy/createTagField.js +0 -48
- package/dist/hierarchy/createTagField.js.map +0 -1
- package/dist/hierarchy/createTagsCollection.d.ts +0 -54
- package/dist/hierarchy/createTagsCollection.d.ts.map +0 -1
- package/dist/hierarchy/createTagsCollection.js +0 -56
- package/dist/hierarchy/createTagsCollection.js.map +0 -1
- package/dist/hierarchy/getInitialTreeData.d.ts +0 -27
- package/dist/hierarchy/getInitialTreeData.d.ts.map +0 -1
- package/dist/hierarchy/getInitialTreeData.js +0 -125
- package/dist/hierarchy/getInitialTreeData.js.map +0 -1
- package/dist/hierarchy/hooks/collectionAfterDelete.d.ts +0 -14
- package/dist/hierarchy/hooks/collectionAfterDelete.d.ts.map +0 -1
- package/dist/hierarchy/hooks/collectionAfterDelete.js +0 -21
- package/dist/hierarchy/hooks/collectionAfterDelete.js.map +0 -1
- package/dist/hierarchy/hooks/collectionAfterRead.d.ts +0 -27
- package/dist/hierarchy/hooks/collectionAfterRead.d.ts.map +0 -1
- package/dist/hierarchy/hooks/collectionAfterRead.js +0 -64
- package/dist/hierarchy/hooks/collectionAfterRead.js.map +0 -1
- package/dist/hierarchy/hooks/collectionBeforeChange.d.ts +0 -19
- package/dist/hierarchy/hooks/collectionBeforeChange.d.ts.map +0 -1
- package/dist/hierarchy/hooks/collectionBeforeChange.js +0 -90
- package/dist/hierarchy/hooks/collectionBeforeChange.js.map +0 -1
- package/dist/hierarchy/hooks/collectionBeforeDelete.d.ts +0 -15
- package/dist/hierarchy/hooks/collectionBeforeDelete.d.ts.map +0 -1
- package/dist/hierarchy/hooks/collectionBeforeDelete.js +0 -20
- package/dist/hierarchy/hooks/collectionBeforeDelete.js.map +0 -1
- package/dist/hierarchy/hooks/ensureSafeCollectionsChange.d.ts +0 -8
- package/dist/hierarchy/hooks/ensureSafeCollectionsChange.d.ts.map +0 -1
- package/dist/hierarchy/hooks/ensureSafeCollectionsChange.js +0 -108
- package/dist/hierarchy/hooks/ensureSafeCollectionsChange.js.map +0 -1
- package/dist/hierarchy/injectHierarchyButton.d.ts +0 -14
- package/dist/hierarchy/injectHierarchyButton.d.ts.map +0 -1
- package/dist/hierarchy/injectHierarchyButton.js +0 -37
- package/dist/hierarchy/injectHierarchyButton.js.map +0 -1
- package/dist/hierarchy/resolveHierarchyCollections.d.ts +0 -23
- package/dist/hierarchy/resolveHierarchyCollections.d.ts.map +0 -1
- package/dist/hierarchy/resolveHierarchyCollections.js +0 -312
- package/dist/hierarchy/resolveHierarchyCollections.js.map +0 -1
- package/dist/hierarchy/sanitizeHierarchyCollection.d.ts +0 -14
- package/dist/hierarchy/sanitizeHierarchyCollection.d.ts.map +0 -1
- package/dist/hierarchy/sanitizeHierarchyCollection.js +0 -112
- package/dist/hierarchy/sanitizeHierarchyCollection.js.map +0 -1
- package/dist/hierarchy/types.d.ts +0 -137
- package/dist/hierarchy/types.d.ts.map +0 -1
- package/dist/hierarchy/types.js +0 -6
- package/dist/hierarchy/types.js.map +0 -1
- package/dist/hierarchy/utils/buildLocalizedHierarchyPaths.d.ts +0 -71
- package/dist/hierarchy/utils/buildLocalizedHierarchyPaths.d.ts.map +0 -1
- package/dist/hierarchy/utils/buildLocalizedHierarchyPaths.js +0 -65
- package/dist/hierarchy/utils/buildLocalizedHierarchyPaths.js.map +0 -1
- package/dist/hierarchy/utils/computePaths.d.ts +0 -31
- package/dist/hierarchy/utils/computePaths.d.ts.map +0 -1
- package/dist/hierarchy/utils/computePaths.js +0 -371
- package/dist/hierarchy/utils/computePaths.js.map +0 -1
- package/dist/hierarchy/utils/findUseAsTitle.d.ts +0 -6
- package/dist/hierarchy/utils/findUseAsTitle.d.ts.map +0 -1
- package/dist/hierarchy/utils/findUseAsTitle.js +0 -72
- package/dist/hierarchy/utils/findUseAsTitle.js.map +0 -1
- package/dist/hierarchy/utils/getAncestors.d.ts +0 -34
- package/dist/hierarchy/utils/getAncestors.d.ts.map +0 -1
- package/dist/hierarchy/utils/getAncestors.js +0 -94
- package/dist/hierarchy/utils/getAncestors.js.map +0 -1
- package/dist/hierarchy/utils/getLocalizedValue.d.ts +0 -30
- package/dist/hierarchy/utils/getLocalizedValue.d.ts.map +0 -1
- package/dist/hierarchy/utils/getLocalizedValue.js +0 -46
- package/dist/hierarchy/utils/getLocalizedValue.js.map +0 -1
- package/dist/hierarchy/utils/getLocalizedValue.spec.js +0 -250
- package/dist/hierarchy/utils/getLocalizedValue.spec.js.map +0 -1
|
@@ -1,371 +0,0 @@
|
|
|
1
|
-
import { slugify as payloadSlugify } from '../../utilities/slugify.js';
|
|
2
|
-
import { HIERARCHY_SLUG_PATH_FIELD, HIERARCHY_TITLE_PATH_FIELD } from '../constants.js';
|
|
3
|
-
import { buildLocalizedHierarchyPaths } from './buildLocalizedHierarchyPaths.js';
|
|
4
|
-
import { findUseAsTitleField } from './findUseAsTitle.js';
|
|
5
|
-
import { getLocalizedValue } from './getLocalizedValue.js';
|
|
6
|
-
// Helper to get title value - returns string for single locale, object for 'all' locales
|
|
7
|
-
const getTitleValue = ({ document, isTitleLocalized = false, locale, req, titleFieldName })=>{
|
|
8
|
-
const titleValue = document[titleFieldName];
|
|
9
|
-
if (!titleValue) {
|
|
10
|
-
return document.id?.toString() || 'untitled';
|
|
11
|
-
}
|
|
12
|
-
// If field is localized and we want all locales, return the full object
|
|
13
|
-
if (isTitleLocalized && locale === 'all' && typeof titleValue === 'object') {
|
|
14
|
-
return titleValue;
|
|
15
|
-
}
|
|
16
|
-
// Single locale - use getLocalizedValue to handle fallback
|
|
17
|
-
if (isTitleLocalized && typeof titleValue === 'object') {
|
|
18
|
-
const localizedValue = getLocalizedValue({
|
|
19
|
-
fallbackLocale: req.fallbackLocale,
|
|
20
|
-
fieldType: 'text',
|
|
21
|
-
locale: locale || req.locale || 'en',
|
|
22
|
-
value: titleValue
|
|
23
|
-
});
|
|
24
|
-
return localizedValue || document.id?.toString() || 'untitled';
|
|
25
|
-
}
|
|
26
|
-
return titleValue;
|
|
27
|
-
};
|
|
28
|
-
/**
|
|
29
|
-
* Computes both slug and title breadcrumb paths for a document by walking up the parent chain.
|
|
30
|
-
* More efficient than computing them separately since it only walks the chain once.
|
|
31
|
-
*
|
|
32
|
-
* Note: Ancestor fetches always use `overrideAccess: true` to ensure paths are complete.
|
|
33
|
-
* If a user can read a document, they should see its full breadcrumb path even if they
|
|
34
|
-
* cannot read all ancestor documents. This prevents broken breadcrumbs and provides
|
|
35
|
-
* better UX at the cost of minimal information leakage (ancestor titles in paths).
|
|
36
|
-
*
|
|
37
|
-
* @param args - Configuration for path computation
|
|
38
|
-
* @returns Object with slugPath and titlePath
|
|
39
|
-
*/ export async function computePaths(args) {
|
|
40
|
-
const { collection, doc, draft = false, locale, parentFieldName, req, slugPathFieldName = HIERARCHY_SLUG_PATH_FIELD, titlePathFieldName = HIERARCHY_TITLE_PATH_FIELD } = args;
|
|
41
|
-
const slugify = collection.hierarchy !== false && collection.hierarchy.slugify || ((text)=>payloadSlugify(text) || '');
|
|
42
|
-
const { localized: isTitleLocalized, titleFieldName } = findUseAsTitleField(collection);
|
|
43
|
-
// Initialize cache if it doesn't exist
|
|
44
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
45
|
-
const context = req.context;
|
|
46
|
-
if (!context.hierarchyAncestorCache) {
|
|
47
|
-
context.hierarchyAncestorCache = {};
|
|
48
|
-
}
|
|
49
|
-
if (!context.hierarchyAncestorCache[collection.slug]) {
|
|
50
|
-
context.hierarchyAncestorCache[collection.slug] = {};
|
|
51
|
-
}
|
|
52
|
-
// Initialize cache stats if debug is enabled
|
|
53
|
-
if (req.payload.config.debug && !context.hierarchyCacheStats) {
|
|
54
|
-
context.hierarchyCacheStats = {
|
|
55
|
-
hits: 0,
|
|
56
|
-
misses: 0,
|
|
57
|
-
queries: 0
|
|
58
|
-
};
|
|
59
|
-
}
|
|
60
|
-
const parentValue = doc[parentFieldName];
|
|
61
|
-
let parentID;
|
|
62
|
-
if (!parentValue) {
|
|
63
|
-
// No parent - root document
|
|
64
|
-
parentID = undefined;
|
|
65
|
-
} else {
|
|
66
|
-
// Extract ID from parent value
|
|
67
|
-
// Parent can be:
|
|
68
|
-
// - Plain ID (string/number)
|
|
69
|
-
// - Populated object with { id: ... }
|
|
70
|
-
if (typeof parentValue === 'object' && 'id' in parentValue) {
|
|
71
|
-
parentID = parentValue.id;
|
|
72
|
-
} else {
|
|
73
|
-
parentID = parentValue;
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
if (parentID) {
|
|
77
|
-
// Parent is always from the same collection (self-referential)
|
|
78
|
-
const parentCollectionConfig = collection;
|
|
79
|
-
const parentHierarchyConfig = parentCollectionConfig.hierarchy;
|
|
80
|
-
// If parent collection doesn't have hierarchy, we can't compute paths through it
|
|
81
|
-
if (!parentHierarchyConfig || !parentCollectionConfig) {
|
|
82
|
-
const titleValue = getTitleValue({
|
|
83
|
-
document: doc,
|
|
84
|
-
isTitleLocalized,
|
|
85
|
-
locale,
|
|
86
|
-
req,
|
|
87
|
-
titleFieldName
|
|
88
|
-
});
|
|
89
|
-
if (isTitleLocalized && locale === 'all') {
|
|
90
|
-
return buildLocalizedHierarchyPaths({
|
|
91
|
-
req,
|
|
92
|
-
slugify,
|
|
93
|
-
titleValue: titleValue
|
|
94
|
-
});
|
|
95
|
-
}
|
|
96
|
-
return {
|
|
97
|
-
slugPath: slugify(titleValue),
|
|
98
|
-
titlePath: titleValue
|
|
99
|
-
};
|
|
100
|
-
}
|
|
101
|
-
// Initialize cache for parent collection if needed
|
|
102
|
-
if (!context.hierarchyAncestorCache[collection.slug]) {
|
|
103
|
-
context.hierarchyAncestorCache[collection.slug] = {};
|
|
104
|
-
}
|
|
105
|
-
const cache = context.hierarchyAncestorCache[collection.slug];
|
|
106
|
-
const cacheKey = `${parentID}_${locale || 'default'}`;
|
|
107
|
-
// Check cache first
|
|
108
|
-
let parent = cache[cacheKey];
|
|
109
|
-
if (parent) {
|
|
110
|
-
// Cache hit
|
|
111
|
-
if (context.hierarchyCacheStats) {
|
|
112
|
-
context.hierarchyCacheStats.hits += 1;
|
|
113
|
-
}
|
|
114
|
-
} else {
|
|
115
|
-
// Cache miss - fetch parent
|
|
116
|
-
if (context.hierarchyCacheStats) {
|
|
117
|
-
context.hierarchyCacheStats.misses += 1;
|
|
118
|
-
context.hierarchyCacheStats.queries += 1;
|
|
119
|
-
}
|
|
120
|
-
const parentTitleField = findUseAsTitleField(parentCollectionConfig).titleFieldName;
|
|
121
|
-
// parentID is guaranteed to be defined here (we're inside if (parentID))
|
|
122
|
-
const validParentID = parentID;
|
|
123
|
-
// Create new context with computeHierarchyPaths enabled to trigger recursive path computation
|
|
124
|
-
const parentReq = {
|
|
125
|
-
...req,
|
|
126
|
-
context: {
|
|
127
|
-
...req.context,
|
|
128
|
-
computeHierarchyPaths: true
|
|
129
|
-
}
|
|
130
|
-
};
|
|
131
|
-
// Fetch parent
|
|
132
|
-
// When locale === 'all', we need special handling because Payload doesn't support
|
|
133
|
-
// fetching all locales of a draft document (drafts are stored per-locale).
|
|
134
|
-
// Strategy: Try published first, fallback to fetching each locale separately for drafts.
|
|
135
|
-
const fetchParent = async ()=>{
|
|
136
|
-
if (locale === 'all') {
|
|
137
|
-
try {
|
|
138
|
-
// First try to fetch published version with all locales
|
|
139
|
-
return await req.payload.findByID({
|
|
140
|
-
id: validParentID,
|
|
141
|
-
collection: collection.slug,
|
|
142
|
-
depth: 0,
|
|
143
|
-
locale,
|
|
144
|
-
overrideAccess: true,
|
|
145
|
-
req: parentReq,
|
|
146
|
-
select: {
|
|
147
|
-
[parentHierarchyConfig.parentFieldName]: true,
|
|
148
|
-
[parentHierarchyConfig.slugPathFieldName]: true,
|
|
149
|
-
[parentHierarchyConfig.titlePathFieldName]: true,
|
|
150
|
-
[parentTitleField]: true
|
|
151
|
-
},
|
|
152
|
-
user: req.user
|
|
153
|
-
});
|
|
154
|
-
} catch (_error) {
|
|
155
|
-
// Published version not found, must be a draft
|
|
156
|
-
// Payload doesn't support fetching all locales of a draft with a single query
|
|
157
|
-
// So we need to fetch each locale separately and combine the path data
|
|
158
|
-
const locales = req.payload.config.localization ? req.payload.config.localization.localeCodes : [];
|
|
159
|
-
const parentPathsByLocale = {};
|
|
160
|
-
// Get parent collection's slugify function (may differ from child's)
|
|
161
|
-
const parentSlugify = parentCollectionConfig.hierarchy !== false && parentCollectionConfig.hierarchy.slugify || ((text)=>payloadSlugify(text) || '');
|
|
162
|
-
// Fetch parent for each locale to get paths
|
|
163
|
-
for (const loc of locales){
|
|
164
|
-
// Create a new request with this specific locale but keep computeHierarchyPaths flag
|
|
165
|
-
const localeReq = {
|
|
166
|
-
...req,
|
|
167
|
-
context: {
|
|
168
|
-
...req.context,
|
|
169
|
-
computeHierarchyPaths: true
|
|
170
|
-
},
|
|
171
|
-
locale: loc
|
|
172
|
-
};
|
|
173
|
-
try {
|
|
174
|
-
const parentForLocale = await req.payload.findByID({
|
|
175
|
-
id: validParentID,
|
|
176
|
-
collection: collection.slug,
|
|
177
|
-
depth: 0,
|
|
178
|
-
draft: true,
|
|
179
|
-
locale: loc,
|
|
180
|
-
overrideAccess: true,
|
|
181
|
-
req: localeReq,
|
|
182
|
-
user: req.user
|
|
183
|
-
});
|
|
184
|
-
// Extract the path fields and title from the parent
|
|
185
|
-
// If paths weren't computed (undefined), compute them manually for root documents
|
|
186
|
-
let parentSlugPath = parentForLocale[parentHierarchyConfig.slugPathFieldName];
|
|
187
|
-
let parentTitlePath = parentForLocale[parentHierarchyConfig.titlePathFieldName];
|
|
188
|
-
const parentTitle = parentForLocale[parentTitleField];
|
|
189
|
-
// If paths are undefined, this might be a root document - compute paths from title
|
|
190
|
-
if (!parentSlugPath && parentTitle) {
|
|
191
|
-
parentSlugPath = parentSlugify(parentTitle);
|
|
192
|
-
}
|
|
193
|
-
if (!parentTitlePath && parentTitle) {
|
|
194
|
-
parentTitlePath = parentTitle;
|
|
195
|
-
}
|
|
196
|
-
parentPathsByLocale[loc] = {
|
|
197
|
-
slugPath: parentSlugPath,
|
|
198
|
-
title: parentTitle,
|
|
199
|
-
titlePath: parentTitlePath
|
|
200
|
-
};
|
|
201
|
-
} catch (localeError) {
|
|
202
|
-
// This locale doesn't exist, skip it
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
// Combine the path data from all locales into a single parent object
|
|
206
|
-
const combinedSlugPaths = {};
|
|
207
|
-
const combinedTitlePaths = {};
|
|
208
|
-
const combinedTitles = {};
|
|
209
|
-
for (const loc of locales){
|
|
210
|
-
if (parentPathsByLocale[loc]) {
|
|
211
|
-
combinedSlugPaths[loc] = parentPathsByLocale[loc].slugPath;
|
|
212
|
-
combinedTitlePaths[loc] = parentPathsByLocale[loc].titlePath;
|
|
213
|
-
combinedTitles[loc] = parentPathsByLocale[loc].title;
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
// Return a parent object with only the hierarchy fields we need
|
|
217
|
-
// (all properly formatted as multi-locale objects)
|
|
218
|
-
return {
|
|
219
|
-
id: validParentID,
|
|
220
|
-
[parentHierarchyConfig.slugPathFieldName]: combinedSlugPaths,
|
|
221
|
-
[parentHierarchyConfig.titlePathFieldName]: combinedTitlePaths,
|
|
222
|
-
[parentTitleField]: combinedTitles
|
|
223
|
-
};
|
|
224
|
-
}
|
|
225
|
-
} else {
|
|
226
|
-
// Normal case: single locale, can pass draft parameter
|
|
227
|
-
return await req.payload.findByID({
|
|
228
|
-
id: validParentID,
|
|
229
|
-
collection: collection.slug,
|
|
230
|
-
depth: 0,
|
|
231
|
-
draft,
|
|
232
|
-
locale,
|
|
233
|
-
overrideAccess: true,
|
|
234
|
-
req: parentReq,
|
|
235
|
-
select: {
|
|
236
|
-
[parentHierarchyConfig.parentFieldName]: true,
|
|
237
|
-
[parentHierarchyConfig.slugPathFieldName]: true,
|
|
238
|
-
[parentHierarchyConfig.titlePathFieldName]: true,
|
|
239
|
-
[parentTitleField]: true
|
|
240
|
-
},
|
|
241
|
-
user: req.user
|
|
242
|
-
});
|
|
243
|
-
}
|
|
244
|
-
};
|
|
245
|
-
try {
|
|
246
|
-
parent = await fetchParent();
|
|
247
|
-
// Store in cache
|
|
248
|
-
cache[cacheKey] = parent;
|
|
249
|
-
} catch {
|
|
250
|
-
// If we can't fetch the parent at all (even with fallbacks), treat this as a root document
|
|
251
|
-
// This can happen with complex draft/locale combinations
|
|
252
|
-
parentID = undefined;
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
// If parent fetch failed, treat as root document
|
|
256
|
-
if (!parentID || !parent) {
|
|
257
|
-
const titleValue = getTitleValue({
|
|
258
|
-
document: doc,
|
|
259
|
-
isTitleLocalized,
|
|
260
|
-
locale,
|
|
261
|
-
req,
|
|
262
|
-
titleFieldName
|
|
263
|
-
});
|
|
264
|
-
if (isTitleLocalized && locale === 'all') {
|
|
265
|
-
return buildLocalizedHierarchyPaths({
|
|
266
|
-
req,
|
|
267
|
-
slugify,
|
|
268
|
-
titleValue: titleValue
|
|
269
|
-
});
|
|
270
|
-
}
|
|
271
|
-
return {
|
|
272
|
-
slugPath: slugify(titleValue),
|
|
273
|
-
titlePath: titleValue
|
|
274
|
-
};
|
|
275
|
-
}
|
|
276
|
-
const docTitle = getTitleValue({
|
|
277
|
-
document: doc,
|
|
278
|
-
isTitleLocalized,
|
|
279
|
-
locale,
|
|
280
|
-
req,
|
|
281
|
-
titleFieldName
|
|
282
|
-
});
|
|
283
|
-
// Cache the current document (in its own collection's cache)
|
|
284
|
-
const currentDocCacheKey = `${doc.id}_${locale || 'default'}`;
|
|
285
|
-
if (!context.hierarchyAncestorCache[collection.slug]) {
|
|
286
|
-
context.hierarchyAncestorCache[collection.slug] = {};
|
|
287
|
-
}
|
|
288
|
-
context.hierarchyAncestorCache[collection.slug][currentDocCacheKey] = {
|
|
289
|
-
[parentFieldName]: parentID,
|
|
290
|
-
[slugPathFieldName]: undefined,
|
|
291
|
-
[titleFieldName]: docTitle,
|
|
292
|
-
[titlePathFieldName]: undefined
|
|
293
|
-
};
|
|
294
|
-
// Get parent's path field names from hierarchy config
|
|
295
|
-
const parentSlugPathFieldName = parentCollectionConfig.hierarchy !== false ? parentCollectionConfig.hierarchy.slugPathFieldName : HIERARCHY_SLUG_PATH_FIELD;
|
|
296
|
-
const parentTitlePathFieldName = parentCollectionConfig.hierarchy !== false ? parentCollectionConfig.hierarchy.titlePathFieldName : HIERARCHY_TITLE_PATH_FIELD;
|
|
297
|
-
// Handle localized case (locale === 'all' with localized title field)
|
|
298
|
-
if (isTitleLocalized && locale === 'all') {
|
|
299
|
-
// Parent might have non-localized title field, resulting in string paths instead of objects
|
|
300
|
-
// Convert parent paths to objects if they're strings (use same value for all locales)
|
|
301
|
-
let parentSlugPathObj = parent[parentSlugPathFieldName];
|
|
302
|
-
let parentTitlePathObj = parent[parentTitlePathFieldName];
|
|
303
|
-
// If parent paths are strings (non-localized parent), convert to objects for all locales
|
|
304
|
-
if (typeof parentSlugPathObj === 'string') {
|
|
305
|
-
const locales = req.payload.config.localization ? req.payload.config.localization.localeCodes : [];
|
|
306
|
-
const slugValue = parentSlugPathObj;
|
|
307
|
-
parentSlugPathObj = {};
|
|
308
|
-
for (const loc of locales){
|
|
309
|
-
parentSlugPathObj[loc] = slugValue;
|
|
310
|
-
}
|
|
311
|
-
}
|
|
312
|
-
if (typeof parentTitlePathObj === 'string') {
|
|
313
|
-
const locales = req.payload.config.localization ? req.payload.config.localization.localeCodes : [];
|
|
314
|
-
const titleValue = parentTitlePathObj;
|
|
315
|
-
parentTitlePathObj = {};
|
|
316
|
-
for (const loc of locales){
|
|
317
|
-
parentTitlePathObj[loc] = titleValue;
|
|
318
|
-
}
|
|
319
|
-
}
|
|
320
|
-
// If parent paths are undefined (parent fetch failed or paths not computed),
|
|
321
|
-
// buildLocalizedHierarchyPaths will handle it by using just the child's title
|
|
322
|
-
const result = buildLocalizedHierarchyPaths({
|
|
323
|
-
parentSlugPath: parentSlugPathObj,
|
|
324
|
-
parentTitlePath: parentTitlePathObj,
|
|
325
|
-
req,
|
|
326
|
-
slugify,
|
|
327
|
-
titleValue: docTitle
|
|
328
|
-
});
|
|
329
|
-
// Update cache with computed paths
|
|
330
|
-
context.hierarchyAncestorCache[collection.slug][currentDocCacheKey][slugPathFieldName] = result.slugPath;
|
|
331
|
-
context.hierarchyAncestorCache[collection.slug][currentDocCacheKey][titlePathFieldName] = result.titlePath;
|
|
332
|
-
return result;
|
|
333
|
-
}
|
|
334
|
-
// Single locale case
|
|
335
|
-
const result = {
|
|
336
|
-
slugPath: parent[parentSlugPathFieldName] + '/' + slugify(docTitle),
|
|
337
|
-
titlePath: parent[parentTitlePathFieldName] + '/' + docTitle
|
|
338
|
-
};
|
|
339
|
-
// Update cache with computed paths
|
|
340
|
-
context.hierarchyAncestorCache[collection.slug][currentDocCacheKey][slugPathFieldName] = result.slugPath;
|
|
341
|
-
context.hierarchyAncestorCache[collection.slug][currentDocCacheKey][titlePathFieldName] = result.titlePath;
|
|
342
|
-
return result;
|
|
343
|
-
} else {
|
|
344
|
-
const titleValue = getTitleValue({
|
|
345
|
-
document: doc,
|
|
346
|
-
isTitleLocalized,
|
|
347
|
-
locale,
|
|
348
|
-
req,
|
|
349
|
-
titleFieldName
|
|
350
|
-
});
|
|
351
|
-
context.hierarchyAncestorCache[collection.slug][doc.id] = {
|
|
352
|
-
[parentFieldName]: null,
|
|
353
|
-
[titleFieldName]: titleValue
|
|
354
|
-
};
|
|
355
|
-
// Handle localized case (locale === 'all' with localized title field)
|
|
356
|
-
if (isTitleLocalized && locale === 'all') {
|
|
357
|
-
return buildLocalizedHierarchyPaths({
|
|
358
|
-
req,
|
|
359
|
-
slugify,
|
|
360
|
-
titleValue: titleValue
|
|
361
|
-
});
|
|
362
|
-
}
|
|
363
|
-
// Single locale case
|
|
364
|
-
return {
|
|
365
|
-
slugPath: slugify(titleValue),
|
|
366
|
-
titlePath: titleValue
|
|
367
|
-
};
|
|
368
|
-
}
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
//# sourceMappingURL=computePaths.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/hierarchy/utils/computePaths.ts"],"sourcesContent":["import type { SanitizedCollectionConfig } from '../../collections/config/types.js'\nimport type { Document, PayloadRequest } from '../../types/index.js'\n\nimport { slugify as payloadSlugify } from '../../utilities/slugify.js'\nimport {\n HIERARCHY_DEFAULT_LOCALE,\n HIERARCHY_SLUG_PATH_FIELD,\n HIERARCHY_TITLE_PATH_FIELD,\n} from '../constants.js'\nimport { buildLocalizedHierarchyPaths } from './buildLocalizedHierarchyPaths.js'\nimport { findUseAsTitleField } from './findUseAsTitle.js'\nimport { getLocalizedValue } from './getLocalizedValue.js'\n\ntype ComputePathsArgs = {\n collection: SanitizedCollectionConfig\n doc: Document\n draft?: boolean\n locale?: string\n parentFieldName: string\n req: PayloadRequest\n slugPathFieldName?: string\n titlePathFieldName?: string\n}\n\ntype ComputePathsResult = {\n slugPath: Record<string, string> | string\n titlePath: Record<string, string> | string\n}\n\n// Helper to get title value - returns string for single locale, object for 'all' locales\nconst getTitleValue = ({\n document,\n isTitleLocalized = false,\n locale,\n req,\n titleFieldName,\n}: {\n document: Document\n isTitleLocalized?: boolean\n locale?: string\n req: PayloadRequest\n titleFieldName: string\n}): Record<string, string> | string => {\n const titleValue = document[titleFieldName]\n\n if (!titleValue) {\n return document.id?.toString() || 'untitled'\n }\n\n // If field is localized and we want all locales, return the full object\n if (isTitleLocalized && locale === 'all' && typeof titleValue === 'object') {\n return titleValue\n }\n\n // Single locale - use getLocalizedValue to handle fallback\n if (isTitleLocalized && typeof titleValue === 'object') {\n const localizedValue = getLocalizedValue({\n fallbackLocale: req.fallbackLocale,\n fieldType: 'text',\n locale: locale || req.locale || 'en',\n value: titleValue,\n })\n return localizedValue || document.id?.toString() || 'untitled'\n }\n\n return titleValue\n}\n\n/**\n * Computes both slug and title breadcrumb paths for a document by walking up the parent chain.\n * More efficient than computing them separately since it only walks the chain once.\n *\n * Note: Ancestor fetches always use `overrideAccess: true` to ensure paths are complete.\n * If a user can read a document, they should see its full breadcrumb path even if they\n * cannot read all ancestor documents. This prevents broken breadcrumbs and provides\n * better UX at the cost of minimal information leakage (ancestor titles in paths).\n *\n * @param args - Configuration for path computation\n * @returns Object with slugPath and titlePath\n */\nexport async function computePaths(args: ComputePathsArgs): Promise<ComputePathsResult> {\n const {\n collection,\n doc,\n draft = false,\n locale,\n parentFieldName,\n req,\n slugPathFieldName = HIERARCHY_SLUG_PATH_FIELD,\n titlePathFieldName = HIERARCHY_TITLE_PATH_FIELD,\n } = args\n\n const slugify =\n (collection.hierarchy !== false && collection.hierarchy.slugify) ||\n ((text: string) => payloadSlugify(text) || '')\n const { localized: isTitleLocalized, titleFieldName } = findUseAsTitleField(collection)\n\n // Initialize cache if it doesn't exist\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const context = req.context as any\n if (!context.hierarchyAncestorCache) {\n context.hierarchyAncestorCache = {}\n }\n if (!context.hierarchyAncestorCache[collection.slug]) {\n context.hierarchyAncestorCache[collection.slug] = {}\n }\n\n // Initialize cache stats if debug is enabled\n if (req.payload.config.debug && !context.hierarchyCacheStats) {\n context.hierarchyCacheStats = {\n hits: 0,\n misses: 0,\n queries: 0,\n }\n }\n\n const parentValue = doc[parentFieldName]\n let parentID: number | string | undefined\n\n if (!parentValue) {\n // No parent - root document\n parentID = undefined\n } else {\n // Extract ID from parent value\n // Parent can be:\n // - Plain ID (string/number)\n // - Populated object with { id: ... }\n if (typeof parentValue === 'object' && 'id' in parentValue) {\n parentID = parentValue.id\n } else {\n parentID = parentValue as number | string\n }\n }\n\n if (parentID) {\n // Parent is always from the same collection (self-referential)\n const parentCollectionConfig = collection\n const parentHierarchyConfig = parentCollectionConfig.hierarchy\n\n // If parent collection doesn't have hierarchy, we can't compute paths through it\n if (!parentHierarchyConfig || !parentCollectionConfig) {\n const titleValue = getTitleValue({\n document: doc,\n isTitleLocalized,\n locale,\n req,\n titleFieldName,\n })\n\n if (isTitleLocalized && locale === 'all') {\n return buildLocalizedHierarchyPaths({\n req,\n slugify,\n titleValue: titleValue as Record<string, string>,\n })\n }\n\n return {\n slugPath: slugify(titleValue as string),\n titlePath: titleValue as string,\n }\n }\n\n // Initialize cache for parent collection if needed\n if (!context.hierarchyAncestorCache[collection.slug]) {\n context.hierarchyAncestorCache[collection.slug] = {}\n }\n\n const cache = context.hierarchyAncestorCache[collection.slug]\n const cacheKey = `${parentID}_${locale || 'default'}`\n\n // Check cache first\n let parent = cache[cacheKey]\n\n if (parent) {\n // Cache hit\n if (context.hierarchyCacheStats) {\n context.hierarchyCacheStats.hits += 1\n }\n } else {\n // Cache miss - fetch parent\n if (context.hierarchyCacheStats) {\n context.hierarchyCacheStats.misses += 1\n context.hierarchyCacheStats.queries += 1\n }\n\n const parentTitleField = findUseAsTitleField(parentCollectionConfig).titleFieldName\n\n // parentID is guaranteed to be defined here (we're inside if (parentID))\n const validParentID = parentID\n\n // Create new context with computeHierarchyPaths enabled to trigger recursive path computation\n const parentReq = {\n ...req,\n context: {\n ...req.context,\n computeHierarchyPaths: true,\n },\n }\n\n // Fetch parent\n // When locale === 'all', we need special handling because Payload doesn't support\n // fetching all locales of a draft document (drafts are stored per-locale).\n // Strategy: Try published first, fallback to fetching each locale separately for drafts.\n const fetchParent = async () => {\n if (locale === 'all') {\n try {\n // First try to fetch published version with all locales\n return await req.payload.findByID({\n id: validParentID,\n collection: collection.slug,\n depth: 0,\n locale,\n overrideAccess: true,\n req: parentReq,\n select: {\n [parentHierarchyConfig.parentFieldName]: true,\n [parentHierarchyConfig.slugPathFieldName]: true,\n [parentHierarchyConfig.titlePathFieldName]: true,\n [parentTitleField]: true,\n },\n user: req.user,\n })\n } catch (_error) {\n // Published version not found, must be a draft\n // Payload doesn't support fetching all locales of a draft with a single query\n // So we need to fetch each locale separately and combine the path data\n const locales = req.payload.config.localization\n ? req.payload.config.localization.localeCodes\n : []\n const parentPathsByLocale: Record<\n string,\n { slugPath?: string; title?: string; titlePath?: string }\n > = {}\n\n // Get parent collection's slugify function (may differ from child's)\n const parentSlugify =\n (parentCollectionConfig.hierarchy !== false &&\n parentCollectionConfig.hierarchy.slugify) ||\n ((text: string) => payloadSlugify(text) || '')\n\n // Fetch parent for each locale to get paths\n for (const loc of locales) {\n // Create a new request with this specific locale but keep computeHierarchyPaths flag\n const localeReq = {\n ...req,\n context: {\n ...req.context,\n computeHierarchyPaths: true,\n },\n locale: loc,\n }\n\n try {\n const parentForLocale = await req.payload.findByID({\n id: validParentID,\n collection: collection.slug,\n depth: 0,\n draft: true,\n locale: loc,\n overrideAccess: true,\n req: localeReq,\n user: req.user,\n })\n\n // Extract the path fields and title from the parent\n // If paths weren't computed (undefined), compute them manually for root documents\n let parentSlugPath = parentForLocale[parentHierarchyConfig.slugPathFieldName]\n let parentTitlePath = parentForLocale[parentHierarchyConfig.titlePathFieldName]\n const parentTitle = parentForLocale[parentTitleField]\n\n // If paths are undefined, this might be a root document - compute paths from title\n if (!parentSlugPath && parentTitle) {\n parentSlugPath = parentSlugify(parentTitle)\n }\n if (!parentTitlePath && parentTitle) {\n parentTitlePath = parentTitle\n }\n\n parentPathsByLocale[loc] = {\n slugPath: parentSlugPath,\n title: parentTitle,\n titlePath: parentTitlePath,\n }\n } catch (localeError) {\n // This locale doesn't exist, skip it\n }\n }\n\n // Combine the path data from all locales into a single parent object\n const combinedSlugPaths: Record<string, string | undefined> = {}\n const combinedTitlePaths: Record<string, string | undefined> = {}\n const combinedTitles: Record<string, string | undefined> = {}\n\n for (const loc of locales) {\n if (parentPathsByLocale[loc]) {\n combinedSlugPaths[loc] = parentPathsByLocale[loc].slugPath\n combinedTitlePaths[loc] = parentPathsByLocale[loc].titlePath\n combinedTitles[loc] = parentPathsByLocale[loc].title\n }\n }\n\n // Return a parent object with only the hierarchy fields we need\n // (all properly formatted as multi-locale objects)\n return {\n id: validParentID,\n [parentHierarchyConfig.slugPathFieldName]: combinedSlugPaths,\n [parentHierarchyConfig.titlePathFieldName]: combinedTitlePaths,\n [parentTitleField]: combinedTitles,\n }\n }\n } else {\n // Normal case: single locale, can pass draft parameter\n return await req.payload.findByID({\n id: validParentID,\n collection: collection.slug,\n depth: 0,\n draft,\n locale,\n overrideAccess: true,\n req: parentReq,\n select: {\n [parentHierarchyConfig.parentFieldName]: true,\n [parentHierarchyConfig.slugPathFieldName]: true,\n [parentHierarchyConfig.titlePathFieldName]: true,\n [parentTitleField]: true,\n },\n user: req.user,\n })\n }\n }\n\n try {\n parent = await fetchParent()\n\n // Store in cache\n cache[cacheKey] = parent\n } catch {\n // If we can't fetch the parent at all (even with fallbacks), treat this as a root document\n // This can happen with complex draft/locale combinations\n parentID = undefined\n }\n }\n\n // If parent fetch failed, treat as root document\n if (!parentID || !parent) {\n const titleValue = getTitleValue({\n document: doc,\n isTitleLocalized,\n locale,\n req,\n titleFieldName,\n })\n\n if (isTitleLocalized && locale === 'all') {\n return buildLocalizedHierarchyPaths({\n req,\n slugify,\n titleValue: titleValue as Record<string, string>,\n })\n }\n\n return {\n slugPath: slugify(titleValue as string),\n titlePath: titleValue as string,\n }\n }\n\n const docTitle = getTitleValue({ document: doc, isTitleLocalized, locale, req, titleFieldName })\n\n // Cache the current document (in its own collection's cache)\n const currentDocCacheKey = `${doc.id}_${locale || 'default'}`\n if (!context.hierarchyAncestorCache[collection.slug]) {\n context.hierarchyAncestorCache[collection.slug] = {}\n }\n context.hierarchyAncestorCache[collection.slug][currentDocCacheKey] = {\n [parentFieldName]: parentID,\n [slugPathFieldName]: undefined, // Will be set below\n [titleFieldName]: docTitle,\n [titlePathFieldName]: undefined, // Will be set below\n }\n\n // Get parent's path field names from hierarchy config\n const parentSlugPathFieldName =\n parentCollectionConfig.hierarchy !== false\n ? parentCollectionConfig.hierarchy.slugPathFieldName\n : HIERARCHY_SLUG_PATH_FIELD\n const parentTitlePathFieldName =\n parentCollectionConfig.hierarchy !== false\n ? parentCollectionConfig.hierarchy.titlePathFieldName\n : HIERARCHY_TITLE_PATH_FIELD\n\n // Handle localized case (locale === 'all' with localized title field)\n if (isTitleLocalized && locale === 'all') {\n // Parent might have non-localized title field, resulting in string paths instead of objects\n // Convert parent paths to objects if they're strings (use same value for all locales)\n let parentSlugPathObj: Record<string, string> | undefined = parent[\n parentSlugPathFieldName\n ] as Record<string, string> | undefined\n let parentTitlePathObj: Record<string, string> | undefined = parent[\n parentTitlePathFieldName\n ] as Record<string, string> | undefined\n\n // If parent paths are strings (non-localized parent), convert to objects for all locales\n if (typeof parentSlugPathObj === 'string') {\n const locales = req.payload.config.localization\n ? req.payload.config.localization.localeCodes\n : []\n const slugValue = parentSlugPathObj\n parentSlugPathObj = {}\n for (const loc of locales) {\n parentSlugPathObj[loc] = slugValue\n }\n }\n\n if (typeof parentTitlePathObj === 'string') {\n const locales = req.payload.config.localization\n ? req.payload.config.localization.localeCodes\n : []\n const titleValue = parentTitlePathObj\n parentTitlePathObj = {}\n for (const loc of locales) {\n parentTitlePathObj[loc] = titleValue\n }\n }\n\n // If parent paths are undefined (parent fetch failed or paths not computed),\n // buildLocalizedHierarchyPaths will handle it by using just the child's title\n const result = buildLocalizedHierarchyPaths({\n parentSlugPath: parentSlugPathObj,\n parentTitlePath: parentTitlePathObj,\n req,\n slugify,\n titleValue: docTitle as Record<string, string>,\n })\n\n // Update cache with computed paths\n context.hierarchyAncestorCache[collection.slug][currentDocCacheKey][slugPathFieldName] =\n result.slugPath\n context.hierarchyAncestorCache[collection.slug][currentDocCacheKey][titlePathFieldName] =\n result.titlePath\n\n return result\n }\n\n // Single locale case\n const result = {\n slugPath: (parent[parentSlugPathFieldName] as string) + '/' + slugify(docTitle as string),\n titlePath: (parent[parentTitlePathFieldName] as string) + '/' + (docTitle as string),\n }\n\n // Update cache with computed paths\n context.hierarchyAncestorCache[collection.slug][currentDocCacheKey][slugPathFieldName] =\n result.slugPath\n context.hierarchyAncestorCache[collection.slug][currentDocCacheKey][titlePathFieldName] =\n result.titlePath\n\n return result\n } else {\n const titleValue = getTitleValue({\n document: doc,\n isTitleLocalized,\n locale,\n req,\n titleFieldName,\n })\n context.hierarchyAncestorCache[collection.slug][doc.id] = {\n [parentFieldName]: null,\n [titleFieldName]: titleValue,\n }\n\n // Handle localized case (locale === 'all' with localized title field)\n if (isTitleLocalized && locale === 'all') {\n return buildLocalizedHierarchyPaths({\n req,\n slugify,\n titleValue: titleValue as Record<string, string>,\n })\n }\n\n // Single locale case\n return {\n slugPath: slugify(titleValue as string),\n titlePath: titleValue as string,\n }\n }\n}\n"],"names":["slugify","payloadSlugify","HIERARCHY_SLUG_PATH_FIELD","HIERARCHY_TITLE_PATH_FIELD","buildLocalizedHierarchyPaths","findUseAsTitleField","getLocalizedValue","getTitleValue","document","isTitleLocalized","locale","req","titleFieldName","titleValue","id","toString","localizedValue","fallbackLocale","fieldType","value","computePaths","args","collection","doc","draft","parentFieldName","slugPathFieldName","titlePathFieldName","hierarchy","text","localized","context","hierarchyAncestorCache","slug","payload","config","debug","hierarchyCacheStats","hits","misses","queries","parentValue","parentID","undefined","parentCollectionConfig","parentHierarchyConfig","slugPath","titlePath","cache","cacheKey","parent","parentTitleField","validParentID","parentReq","computeHierarchyPaths","fetchParent","findByID","depth","overrideAccess","select","user","_error","locales","localization","localeCodes","parentPathsByLocale","parentSlugify","loc","localeReq","parentForLocale","parentSlugPath","parentTitlePath","parentTitle","title","localeError","combinedSlugPaths","combinedTitlePaths","combinedTitles","docTitle","currentDocCacheKey","parentSlugPathFieldName","parentTitlePathFieldName","parentSlugPathObj","parentTitlePathObj","slugValue","result"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"findUseAsTitle.d.ts","sourceRoot":"","sources":["../../../src/hierarchy/utils/findUseAsTitle.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAA;AAGzE,wBAAgB,mBAAmB,CAAC,gBAAgB,EAAE,gBAAgB,GAAG;IACvE,SAAS,EAAE,OAAO,CAAA;IAClB,cAAc,EAAE,MAAM,CAAA;CACvB,CAGA"}
|
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
export function findUseAsTitleField(collectionConfig) {
|
|
2
|
-
const titleFieldName = collectionConfig.admin?.useAsTitle || 'id';
|
|
3
|
-
return iterateFields({
|
|
4
|
-
fields: collectionConfig.fields,
|
|
5
|
-
titleFieldName
|
|
6
|
-
});
|
|
7
|
-
}
|
|
8
|
-
function iterateFields({ fields, titleFieldName }) {
|
|
9
|
-
let titleField;
|
|
10
|
-
if (titleFieldName === 'id') {
|
|
11
|
-
return {
|
|
12
|
-
localized: false,
|
|
13
|
-
titleFieldName
|
|
14
|
-
};
|
|
15
|
-
}
|
|
16
|
-
for (const field of fields){
|
|
17
|
-
switch(field.type){
|
|
18
|
-
case 'text':
|
|
19
|
-
case 'number':
|
|
20
|
-
case 'textarea':
|
|
21
|
-
if (field.name === titleFieldName) {
|
|
22
|
-
return {
|
|
23
|
-
localized: Boolean(field.localized),
|
|
24
|
-
titleFieldName: field.name
|
|
25
|
-
};
|
|
26
|
-
}
|
|
27
|
-
break;
|
|
28
|
-
case 'row':
|
|
29
|
-
case 'collapsible':
|
|
30
|
-
{
|
|
31
|
-
const result = iterateFields({
|
|
32
|
-
fields: field.fields,
|
|
33
|
-
titleFieldName
|
|
34
|
-
});
|
|
35
|
-
if (result) {
|
|
36
|
-
titleField = result;
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
break;
|
|
40
|
-
case 'group':
|
|
41
|
-
if (!('name' in field)) {
|
|
42
|
-
const result = iterateFields({
|
|
43
|
-
fields: field.fields,
|
|
44
|
-
titleFieldName
|
|
45
|
-
});
|
|
46
|
-
if (result) {
|
|
47
|
-
titleField = result;
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
break;
|
|
51
|
-
case 'tabs':
|
|
52
|
-
for (const tab of field.tabs){
|
|
53
|
-
if (!('name' in tab)) {
|
|
54
|
-
const result = iterateFields({
|
|
55
|
-
fields: tab.fields,
|
|
56
|
-
titleFieldName
|
|
57
|
-
});
|
|
58
|
-
if (result) {
|
|
59
|
-
titleField = result;
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
// If we found the field in recursion, return it
|
|
65
|
-
if (titleField) {
|
|
66
|
-
return titleField;
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
throw new Error(`The hierarchy title field "${titleFieldName}" was not found. It cannot be nested within named fields i.e. named groups, named tabs, etc.`);
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
//# sourceMappingURL=findUseAsTitle.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/hierarchy/utils/findUseAsTitle.ts"],"sourcesContent":["import type { CollectionConfig } from '../../collections/config/types.js'\nimport type { Field } from '../../fields/config/types.js'\n\nexport function findUseAsTitleField(collectionConfig: CollectionConfig): {\n localized: boolean\n titleFieldName: string\n} {\n const titleFieldName = collectionConfig.admin?.useAsTitle || 'id'\n return iterateFields({ fields: collectionConfig.fields, titleFieldName })\n}\n\nfunction iterateFields({ fields, titleFieldName }: { fields: Field[]; titleFieldName: string }): {\n localized: boolean\n titleFieldName: string\n} {\n let titleField: { localized: boolean; titleFieldName: string } | undefined\n\n if (titleFieldName === 'id') {\n return {\n localized: false,\n titleFieldName,\n }\n }\n\n for (const field of fields) {\n switch (field.type) {\n case 'text':\n case 'number':\n case 'textarea':\n if (field.name === titleFieldName) {\n return {\n localized: Boolean(field.localized),\n titleFieldName: field.name,\n }\n }\n break\n case 'row':\n case 'collapsible':\n {\n const result = iterateFields({ fields: field.fields, titleFieldName })\n if (result) {titleField = result}\n }\n break\n case 'group':\n if (!('name' in field)) {\n const result = iterateFields({ fields: field.fields, titleFieldName })\n if (result) {titleField = result}\n }\n break\n case 'tabs':\n for (const tab of field.tabs) {\n if (!('name' in tab)) {\n const result = iterateFields({ fields: tab.fields, titleFieldName })\n if (result) {titleField = result}\n }\n }\n }\n\n // If we found the field in recursion, return it\n if (titleField) {\n return titleField\n }\n }\n\n throw new Error(\n `The hierarchy title field \"${titleFieldName}\" was not found. It cannot be nested within named fields i.e. named groups, named tabs, etc.`,\n )\n}\n"],"names":["findUseAsTitleField","collectionConfig","titleFieldName","admin","useAsTitle","iterateFields","fields","titleField","localized","field","type","name","Boolean","result","tab","tabs","Error"],"mappings":"AAGA,OAAO,SAASA,oBAAoBC,gBAAkC;IAIpE,MAAMC,iBAAiBD,iBAAiBE,KAAK,EAAEC,cAAc;IAC7D,OAAOC,cAAc;QAAEC,QAAQL,iBAAiBK,MAAM;QAAEJ;IAAe;AACzE;AAEA,SAASG,cAAc,EAAEC,MAAM,EAAEJ,cAAc,EAA+C;IAI5F,IAAIK;IAEJ,IAAIL,mBAAmB,MAAM;QAC3B,OAAO;YACLM,WAAW;YACXN;QACF;IACF;IAEA,KAAK,MAAMO,SAASH,OAAQ;QAC1B,OAAQG,MAAMC,IAAI;YAChB,KAAK;YACL,KAAK;YACL,KAAK;gBACH,IAAID,MAAME,IAAI,KAAKT,gBAAgB;oBACjC,OAAO;wBACLM,WAAWI,QAAQH,MAAMD,SAAS;wBAClCN,gBAAgBO,MAAME,IAAI;oBAC5B;gBACF;gBACA;YACF,KAAK;YACL,KAAK;gBACH;oBACE,MAAME,SAASR,cAAc;wBAAEC,QAAQG,MAAMH,MAAM;wBAAEJ;oBAAe;oBACpE,IAAIW,QAAQ;wBAACN,aAAaM;oBAAM;gBAClC;gBACA;YACF,KAAK;gBACH,IAAI,CAAE,CAAA,UAAUJ,KAAI,GAAI;oBACtB,MAAMI,SAASR,cAAc;wBAAEC,QAAQG,MAAMH,MAAM;wBAAEJ;oBAAe;oBACpE,IAAIW,QAAQ;wBAACN,aAAaM;oBAAM;gBAClC;gBACA;YACF,KAAK;gBACH,KAAK,MAAMC,OAAOL,MAAMM,IAAI,CAAE;oBAC5B,IAAI,CAAE,CAAA,UAAUD,GAAE,GAAI;wBACpB,MAAMD,SAASR,cAAc;4BAAEC,QAAQQ,IAAIR,MAAM;4BAAEJ;wBAAe;wBAClE,IAAIW,QAAQ;4BAACN,aAAaM;wBAAM;oBAClC;gBACF;QACJ;QAEA,gDAAgD;QAChD,IAAIN,YAAY;YACd,OAAOA;QACT;IACF;IAEA,MAAM,IAAIS,MACR,CAAC,2BAA2B,EAAEd,eAAe,4FAA4F,CAAC;AAE9I"}
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import type { CollectionSlug } from '../../index.js';
|
|
2
|
-
import type { PayloadRequest } from '../../types/index.js';
|
|
3
|
-
export type Ancestor = {
|
|
4
|
-
id: number | string;
|
|
5
|
-
title: string;
|
|
6
|
-
};
|
|
7
|
-
type GetAncestorsArgs = {
|
|
8
|
-
/**
|
|
9
|
-
* The collection slug
|
|
10
|
-
*/
|
|
11
|
-
collectionSlug: CollectionSlug;
|
|
12
|
-
/**
|
|
13
|
-
* The document ID to get ancestors for
|
|
14
|
-
*/
|
|
15
|
-
id: number | string;
|
|
16
|
-
/**
|
|
17
|
-
* Include the document itself in the returned ancestors (as last item)
|
|
18
|
-
* @default true
|
|
19
|
-
*/
|
|
20
|
-
includeSelf?: boolean;
|
|
21
|
-
/**
|
|
22
|
-
* The request object
|
|
23
|
-
*/
|
|
24
|
-
req: PayloadRequest;
|
|
25
|
-
};
|
|
26
|
-
/**
|
|
27
|
-
* Get ancestor chain for a hierarchical document.
|
|
28
|
-
* Returns array of {id, title} from root to the document.
|
|
29
|
-
*
|
|
30
|
-
* Uses request context caching for efficiency when called multiple times.
|
|
31
|
-
*/
|
|
32
|
-
export declare function getAncestors({ id, collectionSlug, includeSelf, req, }: GetAncestorsArgs): Promise<Ancestor[]>;
|
|
33
|
-
export {};
|
|
34
|
-
//# sourceMappingURL=getAncestors.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"getAncestors.d.ts","sourceRoot":"","sources":["../../../src/hierarchy/utils/getAncestors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AACpD,OAAO,KAAK,EAAY,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAKpE,MAAM,MAAM,QAAQ,GAAG;IACrB,EAAE,EAAE,MAAM,GAAG,MAAM,CAAA;IACnB,KAAK,EAAE,MAAM,CAAA;CACd,CAAA;AAED,KAAK,gBAAgB,GAAG;IACtB;;OAEG;IACH,cAAc,EAAE,cAAc,CAAA;IAC9B;;OAEG;IACH,EAAE,EAAE,MAAM,GAAG,MAAM,CAAA;IACnB;;;OAGG;IACH,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB;;OAEG;IACH,GAAG,EAAE,cAAc,CAAA;CACpB,CAAA;AAED;;;;;GAKG;AACH,wBAAsB,YAAY,CAAC,EACjC,EAAE,EACF,cAAc,EACd,WAAkB,EAClB,GAAG,GACJ,EAAE,gBAAgB,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC,CAqGxC"}
|
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
import { findUseAsTitleField } from './findUseAsTitle.js';
|
|
2
|
-
import { getLocalizedValue } from './getLocalizedValue.js';
|
|
3
|
-
/**
|
|
4
|
-
* Get ancestor chain for a hierarchical document.
|
|
5
|
-
* Returns array of {id, title} from root to the document.
|
|
6
|
-
*
|
|
7
|
-
* Uses request context caching for efficiency when called multiple times.
|
|
8
|
-
*/ export async function getAncestors({ id, collectionSlug, includeSelf = true, req }) {
|
|
9
|
-
const { payload, user } = req;
|
|
10
|
-
const collectionConfig = payload.collections[collectionSlug]?.config;
|
|
11
|
-
if (!collectionConfig) {
|
|
12
|
-
throw new Error(`Collection "${collectionSlug}" not found`);
|
|
13
|
-
}
|
|
14
|
-
const hierarchyConfig = collectionConfig.hierarchy;
|
|
15
|
-
if (!hierarchyConfig) {
|
|
16
|
-
throw new Error(`Collection "${collectionSlug}" does not have hierarchy enabled`);
|
|
17
|
-
}
|
|
18
|
-
const parentFieldName = hierarchyConfig.parentFieldName;
|
|
19
|
-
const { localized: isTitleLocalized, titleFieldName } = findUseAsTitleField(collectionConfig);
|
|
20
|
-
// Initialize cache if needed
|
|
21
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
22
|
-
const context = req.context;
|
|
23
|
-
if (!context.hierarchyAncestorCache) {
|
|
24
|
-
context.hierarchyAncestorCache = {};
|
|
25
|
-
}
|
|
26
|
-
if (!context.hierarchyAncestorCache[collectionSlug]) {
|
|
27
|
-
context.hierarchyAncestorCache[collectionSlug] = {};
|
|
28
|
-
}
|
|
29
|
-
const cache = context.hierarchyAncestorCache[collectionSlug];
|
|
30
|
-
const ancestors = [];
|
|
31
|
-
let currentId = id;
|
|
32
|
-
while(currentId !== null){
|
|
33
|
-
const cacheKey = `ancestors_${currentId}`;
|
|
34
|
-
// Check cache first
|
|
35
|
-
let doc = cache[cacheKey];
|
|
36
|
-
if (!doc) {
|
|
37
|
-
// Cache miss - fetch document
|
|
38
|
-
try {
|
|
39
|
-
doc = await payload.findByID({
|
|
40
|
-
id: currentId,
|
|
41
|
-
collection: collectionSlug,
|
|
42
|
-
depth: 0,
|
|
43
|
-
overrideAccess: false,
|
|
44
|
-
req,
|
|
45
|
-
select: {
|
|
46
|
-
[parentFieldName]: true,
|
|
47
|
-
[titleFieldName]: true
|
|
48
|
-
},
|
|
49
|
-
user
|
|
50
|
-
});
|
|
51
|
-
cache[cacheKey] = doc;
|
|
52
|
-
} catch {
|
|
53
|
-
break;
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
if (!doc) {
|
|
57
|
-
break;
|
|
58
|
-
}
|
|
59
|
-
// Extract title
|
|
60
|
-
const rawTitle = doc[titleFieldName];
|
|
61
|
-
let title;
|
|
62
|
-
if (isTitleLocalized && rawTitle && typeof rawTitle === 'object' && req.locale) {
|
|
63
|
-
const localizedValue = getLocalizedValue({
|
|
64
|
-
fallbackLocale: req.fallbackLocale,
|
|
65
|
-
fieldType: 'text',
|
|
66
|
-
locale: req.locale,
|
|
67
|
-
value: rawTitle
|
|
68
|
-
});
|
|
69
|
-
title = localizedValue || String(doc.id || currentId);
|
|
70
|
-
} else if (isTitleLocalized && rawTitle && typeof rawTitle === 'object') {
|
|
71
|
-
// No locale set - use first available value
|
|
72
|
-
const values = Object.values(rawTitle);
|
|
73
|
-
title = values[0] || String(doc.id || currentId);
|
|
74
|
-
} else {
|
|
75
|
-
title = String(rawTitle || doc.id || currentId);
|
|
76
|
-
}
|
|
77
|
-
ancestors.unshift({
|
|
78
|
-
id: currentId,
|
|
79
|
-
title
|
|
80
|
-
});
|
|
81
|
-
// Get parent ID for next iteration
|
|
82
|
-
const parentValue = doc[parentFieldName];
|
|
83
|
-
if (!parentValue) {
|
|
84
|
-
break;
|
|
85
|
-
}
|
|
86
|
-
currentId = typeof parentValue === 'object' && parentValue !== null && 'id' in parentValue ? parentValue.id : parentValue;
|
|
87
|
-
}
|
|
88
|
-
if (!includeSelf && ancestors.length > 0) {
|
|
89
|
-
ancestors.pop();
|
|
90
|
-
}
|
|
91
|
-
return ancestors;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
//# sourceMappingURL=getAncestors.js.map
|