Files
klz-cables.com/.pnpm-store/v10/files/a2/2f6b0080a8a03b9a66fef11878ca949224bd41e605f2cb36c039128dc945687cba915c7005a44cc1d2bdd817b23a3e2704e3e71acc23177240b5272ad04582
Marc Mintel 5397309103
Some checks failed
Build & Deploy / 🔍 Prepare (push) Successful in 20s
Build & Deploy / 🧪 QA (push) Failing after 34s
Build & Deploy / 🏗️ Build (push) Has started running
Build & Deploy / 🚀 Deploy (push) Has been cancelled
Build & Deploy / 🧪 Smoke Test (push) Has been cancelled
Build & Deploy / ⚡ Lighthouse (push) Has been cancelled
Build & Deploy / 🔔 Notify (push) Has been cancelled
fix(products): fix breadcrumbs and product filtering (backport from main)
2026-02-24 16:04:21 +01:00

390 lines
12 KiB
Plaintext

import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { DocumentInfoProvider, EditDepthProvider, HydrateAuthProvider, LivePreviewProvider } from '@payloadcms/ui';
import { RenderServerComponent } from '@payloadcms/ui/elements/RenderServerComponent';
import { handleLivePreview, handlePreview } from '@payloadcms/ui/rsc';
import { isEditing as getIsEditing } from '@payloadcms/ui/shared';
import { buildFormState } from '@payloadcms/ui/utilities/buildFormState';
import { notFound, redirect } from 'next/navigation.js';
import { isolateObjectProperty, logError } from 'payload';
import { formatAdminURL, hasAutosaveEnabled, hasDraftsEnabled } from 'payload/shared';
import React from 'react';
import { DocumentHeader } from '../../elements/DocumentHeader/index.js';
import { getPreferences } from '../../utilities/getPreferences.js';
import { NotFoundView } from '../NotFound/index.js';
import { getDocPreferences } from './getDocPreferences.js';
import { getDocumentData } from './getDocumentData.js';
import { getDocumentPermissions } from './getDocumentPermissions.js';
import { getDocumentView } from './getDocumentView.js';
import { getIsLocked } from './getIsLocked.js';
import { getMetaBySegment } from './getMetaBySegment.js';
import { getVersions } from './getVersions.js';
import { renderDocumentSlots } from './renderDocumentSlots.js';
export const generateMetadata = async args => getMetaBySegment(args);
/**
* This function is responsible for rendering
* an Edit Document view on the server for both:
* - default document edit views
* - on-demand edit views within drawers
*/
export const renderDocument = async ({
disableActions,
documentSubViewType,
drawerSlug,
importMap,
initialData,
initPageResult,
overrideEntityVisibility,
params,
redirectAfterCreate,
redirectAfterDelete,
redirectAfterDuplicate,
redirectAfterRestore,
searchParams,
versions,
viewType
}) => {
const {
collectionConfig,
docID: idFromArgs,
globalConfig,
locale,
permissions,
req,
req: {
i18n,
payload,
payload: {
config,
config: {
routes: {
admin: adminRoute,
api: apiRoute
}
}
},
user
},
visibleEntities
} = initPageResult;
const segments = Array.isArray(params?.segments) ? params.segments : [];
const collectionSlug = collectionConfig?.slug || undefined;
const globalSlug = globalConfig?.slug || undefined;
let isEditing = getIsEditing({
id: idFromArgs,
collectionSlug,
globalSlug
});
// Fetch the doc required for the view
let doc = !idFromArgs && !globalSlug ? initialData || null : await getDocumentData({
id: idFromArgs,
collectionSlug,
globalSlug,
locale,
payload,
req,
segments,
user
});
if (isEditing && !doc) {
// If it's a collection document that doesn't exist, redirect to collection list
if (collectionSlug) {
const redirectURL = formatAdminURL({
adminRoute,
path: `/collections/${collectionSlug}?notFound=${encodeURIComponent(idFromArgs)}`
});
redirect(redirectURL);
} else {
// For globals or other cases, keep the 404 behavior
throw new Error('not-found');
}
}
const isTrashedDoc = Boolean(doc && 'deletedAt' in doc && typeof doc?.deletedAt === 'string');
// CRITICAL FIX FOR TRANSACTION RACE CONDITION:
// When running parallel operations with Promise.all, if they share the same req object
// and one operation calls initTransaction() which MUTATES req.transactionID, that mutation
// is visible to all parallel operations. This causes:
// 1. Operation A (e.g., getDocumentPermissions → docAccessOperation) calls initTransaction()
// which sets req.transactionID = Promise, then resolves it to a UUID
// 2. Operation B (e.g., getIsLocked) running in parallel receives the SAME req with the mutated transactionID
// 3. Operation A (does not even know that Operation B even exists and is stil using the transactionID) commits/ends its transaction
// 4. Operation B tries to use the now-expired session → MongoExpiredSessionError!
//
// Solution: Use isolateObjectProperty to create a Proxy that isolates the 'transactionID' property.
// This allows each operation to have its own transactionID without affecting the parent req.
// If parent req already has a transaction, preserve it (don't isolate), since this
// issue only arises when one of the operations calls initTransaction() themselves -
// because then, that operation will also try to commit/end the transaction itself.
// If the transactionID is already set, the parallel operations will not try to
// commit/end the transaction themselves, so we don't need to isolate the
// transactionID property.
const reqForPermissions = req.transactionID ? req : isolateObjectProperty(req, 'transactionID');
const reqForLockCheck = req.transactionID ? req : isolateObjectProperty(req, 'transactionID');
const [docPreferences, {
docPermissions,
hasPublishPermission,
hasSavePermission
}, {
currentEditor,
isLocked,
lastUpdateTime
}, entityPreferences] = await Promise.all([
// Get document preferences
getDocPreferences({
id: idFromArgs,
collectionSlug,
globalSlug,
payload,
user
}),
// Get permissions - isolated transactionID prevents cross-contamination
getDocumentPermissions({
id: idFromArgs,
collectionConfig,
data: doc,
globalConfig,
req: reqForPermissions
}),
// Fetch document lock state - isolated transactionID prevents cross-contamination
getIsLocked({
id: idFromArgs,
collectionConfig,
globalConfig,
isEditing,
req: reqForLockCheck
}),
// get entity preferences
getPreferences(collectionSlug ? `collection-${collectionSlug}` : `global-${globalSlug}`, payload, req.user.id, req.user.collection)]);
const operation = collectionSlug && idFromArgs || globalSlug ? 'update' : 'create';
const [{
hasPublishedDoc,
mostRecentVersionIsAutosaved,
unpublishedVersionCount,
versionCount
}, {
state: formState
}] = await Promise.all([getVersions({
id: idFromArgs,
collectionConfig,
doc,
docPermissions,
globalConfig,
locale: locale?.code,
payload,
user
}), buildFormState({
id: idFromArgs,
collectionSlug,
data: doc,
docPermissions,
docPreferences,
fallbackLocale: false,
globalSlug,
locale: locale?.code,
operation,
readOnly: isTrashedDoc || isLocked,
renderAllFields: true,
req,
schemaPath: collectionSlug || globalSlug,
skipValidation: true
})]);
const documentViewServerProps = {
doc,
hasPublishedDoc,
i18n,
initPageResult,
locale,
params,
payload,
permissions,
routeSegments: segments,
searchParams,
user,
versions
};
if (!overrideEntityVisibility && (collectionSlug && !visibleEntities?.collections?.find(visibleSlug => visibleSlug === collectionSlug) || globalSlug && !visibleEntities?.globals?.find(visibleSlug => visibleSlug === globalSlug))) {
throw new Error('not-found');
}
const formattedParams = new URLSearchParams();
if (hasDraftsEnabled(collectionConfig || globalConfig)) {
formattedParams.append('draft', 'true');
}
if (locale?.code) {
formattedParams.append('locale', locale.code);
}
const apiQueryParams = `?${formattedParams.toString()}`;
const apiURL = formatAdminURL({
apiRoute,
path: collectionSlug ? `/${collectionSlug}/${idFromArgs}${apiQueryParams}` : globalSlug ? `/${globalSlug}${apiQueryParams}` : ''
});
let View = null;
let showHeader = true;
const RootViewOverride = collectionConfig?.admin?.components?.views?.edit?.root && 'Component' in collectionConfig.admin.components.views.edit.root ? collectionConfig?.admin?.components?.views?.edit?.root?.Component : globalConfig?.admin?.components?.views?.edit?.root && 'Component' in globalConfig.admin.components.views.edit.root ? globalConfig?.admin?.components?.views?.edit?.root?.Component : null;
if (RootViewOverride) {
View = RootViewOverride;
showHeader = false;
} else {
({
View
} = getDocumentView({
collectionConfig,
config,
docPermissions,
globalConfig,
routeSegments: segments
}));
}
if (!View) {
View = NotFoundView;
}
/**
* Handle case where autoSave is enabled and the document is being created
* => create document and redirect
*/
const shouldAutosave = hasSavePermission && hasAutosaveEnabled(collectionConfig || globalConfig);
const validateDraftData = collectionConfig?.versions?.drafts && collectionConfig?.versions?.drafts?.validate;
let id = idFromArgs;
if (shouldAutosave && !validateDraftData && !idFromArgs && collectionSlug) {
doc = await payload.create({
collection: collectionSlug,
data: initialData || {},
depth: 0,
draft: true,
fallbackLocale: false,
locale: locale?.code,
req,
user
});
if (doc?.id) {
id = doc.id;
isEditing = getIsEditing({
id: doc.id,
collectionSlug,
globalSlug
});
if (!drawerSlug && redirectAfterCreate !== false) {
const redirectURL = formatAdminURL({
adminRoute,
path: `/collections/${collectionSlug}/${doc.id}`
});
redirect(redirectURL);
}
} else {
throw new Error('not-found');
}
}
const documentSlots = renderDocumentSlots({
id,
collectionConfig,
globalConfig,
hasSavePermission,
locale,
permissions,
req
});
// Extract Description from documentSlots to pass to DocumentHeader
const {
Description
} = documentSlots;
const clientProps = {
formState,
...documentSlots,
documentSubViewType,
viewType
};
const {
isLivePreviewEnabled,
livePreviewConfig,
livePreviewURL
} = await handleLivePreview({
collectionSlug,
config,
data: doc,
globalSlug,
operation,
req
});
const {
isPreviewEnabled,
previewURL
} = await handlePreview({
collectionSlug,
config,
data: doc,
globalSlug,
operation,
req
});
return {
data: doc,
Document: /*#__PURE__*/_jsx(DocumentInfoProvider, {
apiURL: apiURL,
collectionSlug: collectionConfig?.slug,
currentEditor: currentEditor,
disableActions: disableActions ?? false,
docPermissions: docPermissions,
globalSlug: globalConfig?.slug,
hasPublishedDoc: hasPublishedDoc,
hasPublishPermission: hasPublishPermission,
hasSavePermission: hasSavePermission,
id: id,
initialData: doc,
initialState: formState,
isEditing: isEditing,
isLocked: isLocked,
isTrashed: isTrashedDoc,
lastUpdateTime: lastUpdateTime,
mostRecentVersionIsAutosaved: mostRecentVersionIsAutosaved,
redirectAfterCreate: redirectAfterCreate,
redirectAfterDelete: redirectAfterDelete,
redirectAfterDuplicate: redirectAfterDuplicate,
redirectAfterRestore: redirectAfterRestore,
unpublishedVersionCount: unpublishedVersionCount,
versionCount: versionCount,
children: /*#__PURE__*/_jsxs(LivePreviewProvider, {
breakpoints: livePreviewConfig?.breakpoints,
isLivePreviewEnabled: isLivePreviewEnabled && operation !== 'create',
isLivePreviewing: Boolean(entityPreferences?.value?.editViewType === 'live-preview' && livePreviewURL),
isPreviewEnabled: Boolean(isPreviewEnabled),
previewURL: previewURL,
typeofLivePreviewURL: typeof livePreviewConfig?.url,
url: livePreviewURL,
children: [showHeader && !drawerSlug && /*#__PURE__*/_jsx(DocumentHeader, {
AfterHeader: Description,
collectionConfig: collectionConfig,
globalConfig: globalConfig,
permissions: permissions,
req: req
}), /*#__PURE__*/_jsx(HydrateAuthProvider, {
permissions: permissions
}), /*#__PURE__*/_jsx(EditDepthProvider, {
children: RenderServerComponent({
clientProps,
Component: View,
importMap,
serverProps: documentViewServerProps
})
})]
})
}, locale?.code)
};
};
export async function DocumentView(props) {
try {
const {
Document: RenderedDocument
} = await renderDocument(props);
return RenderedDocument;
} catch (error) {
if (error?.message === 'NEXT_REDIRECT') {
throw error;
}
logError({
err: error,
payload: props.initPageResult.req.payload
});
if (error.message === 'not-found') {
notFound();
}
}
}
//# sourceMappingURL=index.js.map