payload
Version:
Node, React, Headless CMS and Application Framework built on Next.js
220 lines (219 loc) • 8.57 kB
JavaScript
// @ts-strict-ignore
import executeAccess from '../../auth/executeAccess.js';
import { combineQueries } from '../../database/combineQueries.js';
import { sanitizeJoinQuery } from '../../database/sanitizeJoinQuery.js';
import { NotFound } from '../../errors/index.js';
import { afterRead } from '../../fields/hooks/afterRead/index.js';
import { validateQueryPaths } from '../../index.js';
import { lockedDocumentsCollectionSlug } from '../../locked-documents/config.js';
import { killTransaction } from '../../utilities/killTransaction.js';
import { sanitizeSelect } from '../../utilities/sanitizeSelect.js';
import replaceWithDraftIfAvailable from '../../versions/drafts/replaceWithDraftIfAvailable.js';
import { buildAfterOperation } from './utils.js';
export const findByIDOperation = async (incomingArgs)=>{
let args = incomingArgs;
try {
// /////////////////////////////////////
// beforeOperation - Collection
// /////////////////////////////////////
if (args.collection.config.hooks?.beforeOperation?.length) {
for (const hook of args.collection.config.hooks.beforeOperation){
args = await hook({
args,
collection: args.collection.config,
context: args.req.context,
operation: 'read',
req: args.req
}) || args;
}
}
const { id, collection: { config: collectionConfig }, currentDepth, depth, disableErrors, draft: draftEnabled = false, includeLockStatus, joins, overrideAccess = false, populate, req: { fallbackLocale, locale, t }, req, select: incomingSelect, showHiddenFields } = args;
const select = sanitizeSelect({
forceSelect: collectionConfig.forceSelect,
select: incomingSelect
});
// /////////////////////////////////////
// Access
// /////////////////////////////////////
const accessResult = !overrideAccess ? await executeAccess({
id,
disableErrors,
req
}, collectionConfig.access.read) : true;
// If errors are disabled, and access returns false, return null
if (accessResult === false) {
return null;
}
const where = {
id: {
equals: id
}
};
const fullWhere = combineQueries(where, accessResult);
const sanitizedJoins = await sanitizeJoinQuery({
collectionConfig,
joins,
overrideAccess,
req
});
const findOneArgs = {
collection: collectionConfig.slug,
draftsEnabled: draftEnabled,
joins: req.payloadAPI === 'GraphQL' ? false : sanitizedJoins,
locale,
req: {
transactionID: req.transactionID
},
select,
where: fullWhere
};
// execute only if there's a custom ID and potentially overwriten access on id
if (req.payload.collections[collectionConfig.slug].customIDType) {
await validateQueryPaths({
collectionConfig,
overrideAccess,
req,
where
});
}
// /////////////////////////////////////
// Find by ID
// /////////////////////////////////////
if (!findOneArgs.where.and[0].id) {
throw new NotFound(t);
}
let result = await req.payload.db.findOne(findOneArgs);
if (!result) {
if (!disableErrors) {
throw new NotFound(req.t);
}
return null;
}
// /////////////////////////////////////
// Include Lock Status if required
// /////////////////////////////////////
if (includeLockStatus && id) {
let lockStatus = null;
try {
const lockDocumentsProp = collectionConfig?.lockDocuments;
const lockDurationDefault = 300 // Default 5 minutes in seconds
;
const lockDuration = typeof lockDocumentsProp === 'object' ? lockDocumentsProp.duration : lockDurationDefault;
const lockDurationInMilliseconds = lockDuration * 1000;
const lockedDocument = await req.payload.find({
collection: lockedDocumentsCollectionSlug,
depth: 1,
limit: 1,
overrideAccess: false,
pagination: false,
req,
where: {
and: [
{
'document.relationTo': {
equals: collectionConfig.slug
}
},
{
'document.value': {
equals: id
}
},
// Query where the lock is newer than the current time minus lock time
{
updatedAt: {
greater_than: new Date(new Date().getTime() - lockDurationInMilliseconds)
}
}
]
}
});
if (lockedDocument && lockedDocument.docs.length > 0) {
lockStatus = lockedDocument.docs[0];
}
} catch {
// swallow error
}
result._isLocked = !!lockStatus;
result._userEditing = lockStatus?.user?.value ?? null;
}
// /////////////////////////////////////
// Replace document with draft if available
// /////////////////////////////////////
if (collectionConfig.versions?.drafts && draftEnabled) {
result = await replaceWithDraftIfAvailable({
accessResult,
doc: result,
entity: collectionConfig,
entityType: 'collection',
overrideAccess,
req,
select
});
}
// /////////////////////////////////////
// beforeRead - Collection
// /////////////////////////////////////
if (collectionConfig.hooks?.beforeRead?.length) {
for (const hook of collectionConfig.hooks.beforeRead){
result = await hook({
collection: collectionConfig,
context: req.context,
doc: result,
query: findOneArgs.where,
req
}) || result;
}
}
// /////////////////////////////////////
// afterRead - Fields
// /////////////////////////////////////
result = await afterRead({
collection: collectionConfig,
context: req.context,
currentDepth,
depth,
doc: result,
draft: draftEnabled,
fallbackLocale,
global: null,
locale,
overrideAccess,
populate,
req,
select,
showHiddenFields
});
// /////////////////////////////////////
// afterRead - Collection
// /////////////////////////////////////
if (collectionConfig.hooks?.afterRead?.length) {
for (const hook of collectionConfig.hooks.afterRead){
result = await hook({
collection: collectionConfig,
context: req.context,
doc: result,
query: findOneArgs.where,
req
}) || result;
}
}
// /////////////////////////////////////
// afterOperation - Collection
// /////////////////////////////////////
result = await buildAfterOperation({
args,
collection: collectionConfig,
operation: 'findByID',
result
});
// /////////////////////////////////////
// Return results
// /////////////////////////////////////
return result;
} catch (error) {
await killTransaction(args.req);
throw error;
}
};
//# sourceMappingURL=findByID.js.map