payload 3.85.0 → 3.85.2
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/bin.js +11 -0
- package/dist/admin/fields/Row.d.ts +2 -2
- package/dist/admin/fields/Row.d.ts.map +1 -1
- package/dist/admin/fields/Row.js.map +1 -1
- package/dist/admin/forms/Field.d.ts +1 -3
- package/dist/admin/forms/Field.d.ts.map +1 -1
- package/dist/admin/forms/Field.js.map +1 -1
- package/dist/collections/operations/create.d.ts.map +1 -1
- package/dist/collections/operations/create.js +1 -0
- package/dist/collections/operations/create.js.map +1 -1
- package/dist/collections/operations/update.d.ts.map +1 -1
- package/dist/collections/operations/update.js +7 -2
- package/dist/collections/operations/update.js.map +1 -1
- package/dist/collections/operations/utilities/copyDataWithFreshRowIDs.d.ts +9 -0
- package/dist/collections/operations/utilities/copyDataWithFreshRowIDs.d.ts.map +1 -0
- package/dist/collections/operations/utilities/copyDataWithFreshRowIDs.js +170 -0
- package/dist/collections/operations/utilities/copyDataWithFreshRowIDs.js.map +1 -0
- package/dist/collections/operations/utilities/update.d.ts.map +1 -1
- package/dist/collections/operations/utilities/update.js +16 -8
- package/dist/collections/operations/utilities/update.js.map +1 -1
- package/dist/config/orderable/index.d.ts.map +1 -1
- package/dist/config/orderable/index.js +23 -0
- package/dist/config/orderable/index.js.map +1 -1
- package/dist/errors/ValidationError.d.ts +1 -0
- package/dist/errors/ValidationError.d.ts.map +1 -1
- package/dist/errors/ValidationError.js.map +1 -1
- package/dist/index.bundled.d.ts +4 -5
- package/dist/uploads/generateFileData.d.ts +2 -1
- package/dist/uploads/generateFileData.d.ts.map +1 -1
- package/dist/uploads/generateFileData.js +5 -2
- package/dist/uploads/generateFileData.js.map +1 -1
- package/dist/utilities/addDataAndFileToRequest.d.ts.map +1 -1
- package/dist/utilities/addDataAndFileToRequest.js +6 -0
- package/dist/utilities/addDataAndFileToRequest.js.map +1 -1
- package/package.json +4 -4
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/collections/operations/utilities/copyDataWithFreshRowIDs.ts"],"sourcesContent":["import type { SanitizedConfig } from '../../../config/types.js'\nimport type { ArrayField, Block, BlocksField, Field } from '../../../fields/config/types.js'\n\nimport { tabHasName } from '../../../fields/config/types.js'\nimport { deepCopyObjectSimple } from '../../../utilities/deepCopyObject.js'\nimport { traverseFields } from '../../../utilities/traverseFields.js'\n\ntype LevelEntry =\n | { field: ArrayField | BlocksField; localized: boolean; type: 'rows' }\n | { fields: Field[]; localized: boolean; type: 'subfields' }\n\nconst buildLevelMap = (fields: Field[], map: Map<string, LevelEntry> = new Map()) => {\n for (const field of fields) {\n if (field.type === 'row' || field.type === 'collapsible') {\n buildLevelMap(field.fields, map)\n } else if (field.type === 'tabs') {\n for (const tab of field.tabs) {\n if (tabHasName(tab)) {\n map.set(tab.name, {\n type: 'subfields',\n fields: tab.fields,\n localized: Boolean(tab.localized),\n })\n } else {\n buildLevelMap(tab.fields, map)\n }\n }\n } else if (field.type === 'group') {\n if ('name' in field && field.name) {\n map.set(field.name, {\n type: 'subfields',\n fields: field.fields,\n localized: Boolean(field.localized),\n })\n } else {\n buildLevelMap(field.fields, map)\n }\n } else if ((field.type === 'array' || field.type === 'blocks') && field.name) {\n map.set(field.name, { type: 'rows', field, localized: Boolean(field.localized) })\n }\n }\n return map\n}\n\nconst isLocaleKeyed = (value: object, config: SanitizedConfig): boolean => {\n if (Array.isArray(value)) {\n return false\n }\n const localeCodes = config.localization ? config.localization.localeCodes : []\n const keys = Object.keys(value)\n return keys.length > 0 && keys.every((key) => localeCodes.includes(key))\n}\n\nconst resolveBlockFields = (\n field: BlocksField,\n blockType: unknown,\n config: SanitizedConfig,\n): Field[] => {\n if (typeof blockType !== 'string') {\n return []\n }\n const block =\n config.blocks?.find((b) => b.slug === blockType) ??\n field.blocks.find((b): b is Block => typeof b !== 'string' && b.slug === blockType)\n return block?.fields ?? []\n}\n\nconst copyRow = ({\n config,\n existingRowIDs,\n field,\n parentIsLocalized,\n row,\n}: {\n config: SanitizedConfig\n existingRowIDs: Set<string>\n field: ArrayField | BlocksField\n parentIsLocalized: boolean\n row: unknown\n}): unknown => {\n if (!row || typeof row !== 'object') {\n return deepCopyObjectSimple(row as never)\n }\n\n const subfields =\n field.type === 'array'\n ? field.fields\n : resolveBlockFields(field, (row as Record<string, unknown>).blockType, config)\n\n const newRow = copyObject({\n config,\n data: row as Record<string, unknown>,\n existingRowIDs,\n fields: subfields,\n parentIsLocalized,\n })\n\n if (typeof newRow.id === 'string' && !existingRowIDs.has(newRow.id)) {\n delete newRow.id\n }\n\n return newRow\n}\n\nconst copyObject = ({\n config,\n data,\n existingRowIDs,\n fields,\n parentIsLocalized,\n}: {\n config: SanitizedConfig\n data: Record<string, unknown>\n existingRowIDs: Set<string>\n fields: Field[]\n parentIsLocalized: boolean\n}): Record<string, unknown> => {\n const levelMap = buildLevelMap(fields)\n const result: Record<string, unknown> = {}\n\n for (const key of Object.keys(data)) {\n const value = data[key]\n const entry = levelMap.get(key)\n\n if (!entry || value === null || typeof value !== 'object') {\n result[key] = deepCopyObjectSimple(value as never)\n continue\n }\n\n const childParentIsLocalized = parentIsLocalized || entry.localized\n\n if (entry.type === 'subfields') {\n const valueIsLocaleKeyed =\n entry.localized && !parentIsLocalized && isLocaleKeyed(value, config)\n\n result[key] = valueIsLocaleKeyed\n ? mapLocales(value, (localeValue) =>\n copyObject({\n config,\n data: localeValue,\n existingRowIDs,\n fields: entry.fields,\n parentIsLocalized: true,\n }),\n )\n : copyObject({\n config,\n data: value as Record<string, unknown>,\n existingRowIDs,\n fields: entry.fields,\n parentIsLocalized: childParentIsLocalized,\n })\n continue\n }\n\n const copyRows = (rows: unknown) =>\n Array.isArray(rows)\n ? rows.map((row) =>\n copyRow({\n config,\n existingRowIDs,\n field: entry.field,\n parentIsLocalized: childParentIsLocalized,\n row,\n }),\n )\n : deepCopyObjectSimple(rows as never)\n\n result[key] = Array.isArray(value) ? copyRows(value) : mapLocales(value, copyRows)\n }\n\n return result\n}\n\nconst mapLocales = (\n value: object,\n copyLocaleValue: (localeValue: Record<string, unknown>) => unknown,\n): unknown => {\n if (Array.isArray(value)) {\n return deepCopyObjectSimple(value as never)\n }\n const out: Record<string, unknown> = {}\n for (const locale of Object.keys(value)) {\n const localeValue = (value as Record<string, unknown>)[locale]\n out[locale] =\n localeValue && typeof localeValue === 'object'\n ? copyLocaleValue(localeValue as Record<string, unknown>)\n : deepCopyObjectSimple(localeValue as never)\n }\n return out\n}\n\nconst collectExistingRowIDs = ({\n config,\n existingDoc,\n fields,\n}: {\n config: SanitizedConfig\n existingDoc: Record<string, unknown>\n fields: Field[]\n}): Set<string> => {\n const existingRowIDs = new Set<string>()\n\n traverseFields({\n callback: ({ field, ref }) => {\n if (\n (field.type !== 'array' && field.type !== 'blocks') ||\n !('name' in field) ||\n !field.name ||\n !ref ||\n typeof ref !== 'object'\n ) {\n return\n }\n\n const value = (ref as Record<string, unknown>)[field.name]\n\n const visitRows = (rows: unknown) => {\n if (!Array.isArray(rows)) {\n return\n }\n for (const row of rows) {\n if (\n row &&\n typeof row === 'object' &&\n typeof (row as Record<string, unknown>).id === 'string'\n ) {\n existingRowIDs.add((row as Record<string, unknown>).id as string)\n }\n }\n }\n\n if (Array.isArray(value)) {\n visitRows(value)\n } else if (value && typeof value === 'object') {\n for (const localeValue of Object.values(value as Record<string, unknown>)) {\n visitRows(localeValue)\n }\n }\n },\n config,\n fields,\n fillEmpty: false,\n ref: existingDoc,\n })\n\n return existingRowIDs\n}\n\nexport const copyDataWithFreshRowIDs = ({\n config,\n data,\n existingDoc,\n fields,\n}: {\n config: SanitizedConfig\n data: Record<string, unknown>\n existingDoc: Record<string, unknown>\n fields: Field[]\n}): Record<string, unknown> => {\n const existingRowIDs = collectExistingRowIDs({ config, existingDoc, fields })\n\n return copyObject({\n config,\n data,\n existingRowIDs,\n fields,\n parentIsLocalized: false,\n })\n}\n"],"names":["tabHasName","deepCopyObjectSimple","traverseFields","buildLevelMap","fields","map","Map","field","type","tab","tabs","set","name","localized","Boolean","isLocaleKeyed","value","config","Array","isArray","localeCodes","localization","keys","Object","length","every","key","includes","resolveBlockFields","blockType","block","blocks","find","b","slug","copyRow","existingRowIDs","parentIsLocalized","row","subfields","newRow","copyObject","data","id","has","levelMap","result","entry","get","childParentIsLocalized","valueIsLocaleKeyed","mapLocales","localeValue","copyRows","rows","copyLocaleValue","out","locale","collectExistingRowIDs","existingDoc","Set","callback","ref","visitRows","add","values","fillEmpty","copyDataWithFreshRowIDs"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"update.d.ts","sourceRoot":"","sources":["../../../../src/collections/operations/utilities/update.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAGhD,OAAO,KAAK,EACV,cAAc,EACd,UAAU,EACV,eAAe,EACf,mBAAmB,EACpB,MAAM,mBAAmB,CAAA;AAC1B,OAAO,KAAK,EACV,UAAU,EACV,OAAO,EACP,cAAc,EACd,YAAY,EACZ,UAAU,EACV,6BAA6B,EAC9B,MAAM,yBAAyB,CAAA;AAChC,OAAO,KAAK,EACV,sBAAsB,EACtB,yBAAyB,EACzB,wBAAwB,EACxB,UAAU,EACX,MAAM,uBAAuB,CAAA;AAkB9B,MAAM,MAAM,wBAAwB,CAAC,KAAK,SAAS,cAAc,IAAI;IACnE,QAAQ,EAAE,OAAO,CAAA;IACjB,gBAAgB,EAAE,yBAAyB,CAAA;IAC3C,MAAM,EAAE,eAAe,CAAA;IACvB,IAAI,EAAE,WAAW,CAAC,sBAAsB,CAAC,KAAK,CAAC,CAAC,CAAA;IAChD,KAAK,EAAE,MAAM,CAAA;IACb,cAAc,EAAE,UAAU,GAAG,UAAU,CAAA;IACvC,QAAQ,EAAE,OAAO,CAAA;IACjB,cAAc,EAAE,mBAAmB,CAAA;IACnC,aAAa,EAAE,UAAU,EAAE,CAAA;IAC3B,EAAE,EAAE,MAAM,GAAG,MAAM,CAAA;IACnB,MAAM,EAAE,MAAM,CAAA;IACd,cAAc,EAAE,OAAO,CAAA;IACvB,YAAY,EAAE,OAAO,CAAA;IACrB,OAAO,EAAE,OAAO,CAAA;IAChB,QAAQ,CAAC,EAAE,YAAY,CAAA;IACvB,iBAAiB,CAAC,EAAE,OAAO,CAAA;IAC3B,qBAAqB,CAAC,EAAE,MAAM,CAAA;IAC9B,GAAG,EAAE,cAAc,CAAA;IACnB,MAAM,EAAE,UAAU,CAAA;IAClB,gBAAgB,EAAE,OAAO,CAAA;IACzB,mBAAmB,CAAC,EAAE,OAAO,CAAA;CAC9B,CAAA;AAED;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,cAAc,GACzB,KAAK,SAAS,cAAc,EAC5B,OAAO,SAAS,wBAAwB,CAAC,KAAK,CAAC,uUAuB9C,wBAAwB,CAAC,KAAK,CAAC,KAAG,OAAO,CAAC,6BAA6B,CAAC,KAAK,EAAE,OAAO,CAAC,
|
|
1
|
+
{"version":3,"file":"update.d.ts","sourceRoot":"","sources":["../../../../src/collections/operations/utilities/update.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAGhD,OAAO,KAAK,EACV,cAAc,EACd,UAAU,EACV,eAAe,EACf,mBAAmB,EACpB,MAAM,mBAAmB,CAAA;AAC1B,OAAO,KAAK,EACV,UAAU,EACV,OAAO,EACP,cAAc,EACd,YAAY,EACZ,UAAU,EACV,6BAA6B,EAC9B,MAAM,yBAAyB,CAAA;AAChC,OAAO,KAAK,EACV,sBAAsB,EACtB,yBAAyB,EACzB,wBAAwB,EACxB,UAAU,EACX,MAAM,uBAAuB,CAAA;AAkB9B,MAAM,MAAM,wBAAwB,CAAC,KAAK,SAAS,cAAc,IAAI;IACnE,QAAQ,EAAE,OAAO,CAAA;IACjB,gBAAgB,EAAE,yBAAyB,CAAA;IAC3C,MAAM,EAAE,eAAe,CAAA;IACvB,IAAI,EAAE,WAAW,CAAC,sBAAsB,CAAC,KAAK,CAAC,CAAC,CAAA;IAChD,KAAK,EAAE,MAAM,CAAA;IACb,cAAc,EAAE,UAAU,GAAG,UAAU,CAAA;IACvC,QAAQ,EAAE,OAAO,CAAA;IACjB,cAAc,EAAE,mBAAmB,CAAA;IACnC,aAAa,EAAE,UAAU,EAAE,CAAA;IAC3B,EAAE,EAAE,MAAM,GAAG,MAAM,CAAA;IACnB,MAAM,EAAE,MAAM,CAAA;IACd,cAAc,EAAE,OAAO,CAAA;IACvB,YAAY,EAAE,OAAO,CAAA;IACrB,OAAO,EAAE,OAAO,CAAA;IAChB,QAAQ,CAAC,EAAE,YAAY,CAAA;IACvB,iBAAiB,CAAC,EAAE,OAAO,CAAA;IAC3B,qBAAqB,CAAC,EAAE,MAAM,CAAA;IAC9B,GAAG,EAAE,cAAc,CAAA;IACnB,MAAM,EAAE,UAAU,CAAA;IAClB,gBAAgB,EAAE,OAAO,CAAA;IACzB,mBAAmB,CAAC,EAAE,OAAO,CAAA;CAC9B,CAAA;AAED;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,cAAc,GACzB,KAAK,SAAS,cAAc,EAC5B,OAAO,SAAS,wBAAwB,CAAC,KAAK,CAAC,uUAuB9C,wBAAwB,CAAC,KAAK,CAAC,KAAG,OAAO,CAAC,6BAA6B,CAAC,KAAK,EAAE,OAAO,CAAC,CAqXzF,CAAA"}
|
|
@@ -68,14 +68,22 @@ import { mergeLocalizedData } from '../../../utilities/mergeLocalizedData.js';
|
|
|
68
68
|
// /////////////////////////////////////
|
|
69
69
|
// Delete any associated files
|
|
70
70
|
// /////////////////////////////////////
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
71
|
+
// When saving a draft on a document whose latest version is published, the file
|
|
72
|
+
// referenced by docWithLocales is still actively used by the published main document.
|
|
73
|
+
// Deleting it here would break the published document's file even though no publish
|
|
74
|
+
// is happening. Only skip deletion in this case; when the latest version is already a
|
|
75
|
+
// draft, it is safe to delete the old draft file as it is being replaced.
|
|
76
|
+
const isDraftOverPublished = isSavingDraft && docWithLocales._status === 'published';
|
|
77
|
+
if (!isDraftOverPublished) {
|
|
78
|
+
await deleteAssociatedFiles({
|
|
79
|
+
collectionConfig,
|
|
80
|
+
config,
|
|
81
|
+
doc: docWithLocales,
|
|
82
|
+
files: filesToUpload,
|
|
83
|
+
overrideDelete: false,
|
|
84
|
+
req
|
|
85
|
+
});
|
|
86
|
+
}
|
|
79
87
|
// /////////////////////////////////////
|
|
80
88
|
// beforeValidate - Fields
|
|
81
89
|
// /////////////////////////////////////
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/collections/operations/utilities/update.ts"],"sourcesContent":["import type { DeepPartial } from 'ts-essentials'\n\nimport type { Args } from '../../../fields/hooks/beforeChange/index.js'\nimport type {\n CollectionSlug,\n FileToSave,\n SanitizedConfig,\n TypedFallbackLocale,\n} from '../../../index.js'\nimport type {\n JsonObject,\n Payload,\n PayloadRequest,\n PopulateType,\n SelectType,\n TransformCollectionWithSelect,\n} from '../../../types/index.js'\nimport type {\n DataFromCollectionSlug,\n SanitizedCollectionConfig,\n SelectFromCollectionSlug,\n TypeWithID,\n} from '../../config/types.js'\n\nimport { ensureUsernameOrEmail } from '../../../auth/ensureUsernameOrEmail.js'\nimport { generatePasswordSaltHash } from '../../../auth/strategies/local/generatePasswordSaltHash.js'\nimport { afterChange } from '../../../fields/hooks/afterChange/index.js'\nimport { afterRead } from '../../../fields/hooks/afterRead/index.js'\nimport { beforeChange } from '../../../fields/hooks/beforeChange/index.js'\nimport { beforeValidate } from '../../../fields/hooks/beforeValidate/index.js'\nimport { deepCopyObjectSimple, getLatestCollectionVersion, saveVersion } from '../../../index.js'\nimport { deleteAssociatedFiles } from '../../../uploads/deleteAssociatedFiles.js'\nimport { uploadFiles } from '../../../uploads/uploadFiles.js'\nimport { checkDocumentLockStatus } from '../../../utilities/checkDocumentLockStatus.js'\nimport {\n hasDraftsEnabled,\n hasDraftValidationEnabled,\n hasLocalizeStatusEnabled,\n} from '../../../utilities/getVersionsConfig.js'\nimport { mergeLocalizedData } from '../../../utilities/mergeLocalizedData.js'\nexport type SharedUpdateDocumentArgs<TSlug extends CollectionSlug> = {\n autosave: boolean\n collectionConfig: SanitizedCollectionConfig\n config: SanitizedConfig\n data: DeepPartial<DataFromCollectionSlug<TSlug>>\n depth: number\n docWithLocales: JsonObject & TypeWithID\n draftArg: boolean\n fallbackLocale: TypedFallbackLocale\n filesToUpload: FileToSave[]\n id: number | string\n locale: string\n overrideAccess: boolean\n overrideLock: boolean\n payload: Payload\n populate?: PopulateType\n publishAllLocales?: boolean\n publishSpecificLocale?: string\n req: PayloadRequest\n select: SelectType\n showHiddenFields: boolean\n unpublishAllLocales?: boolean\n}\n\n/**\n * This function is used to update a document in the DB and return the result.\n *\n * It runs the following hooks in order:\n * - beforeValidate - Fields\n * - beforeValidate - Collection\n * - beforeChange - Collection\n * - beforeChange - Fields\n * - afterRead - Fields\n * - afterRead - Collection\n * - afterChange - Fields\n * - afterChange - Collection\n */\nexport const updateDocument = async <\n TSlug extends CollectionSlug,\n TSelect extends SelectFromCollectionSlug<TSlug> = SelectType,\n>({\n id,\n autosave,\n collectionConfig,\n config,\n data,\n depth,\n docWithLocales,\n draftArg,\n fallbackLocale,\n filesToUpload,\n locale,\n overrideAccess,\n overrideLock,\n payload,\n populate,\n publishAllLocales: publishAllLocalesArg,\n publishSpecificLocale,\n req,\n select,\n showHiddenFields,\n unpublishAllLocales: unpublishAllLocalesArg,\n}: SharedUpdateDocumentArgs<TSlug>): Promise<TransformCollectionWithSelect<TSlug, TSelect>> => {\n const password = data?.password\n const publishAllLocales =\n !draftArg &&\n (publishAllLocalesArg ?? (hasLocalizeStatusEnabled(collectionConfig) ? false : true))\n const unpublishAllLocales =\n typeof unpublishAllLocalesArg === 'string'\n ? unpublishAllLocalesArg === 'true'\n : !!unpublishAllLocalesArg\n const isSavingDraft =\n Boolean(draftArg && hasDraftsEnabled(collectionConfig)) &&\n data._status !== 'published' &&\n !publishAllLocales\n const shouldSavePassword = Boolean(\n password &&\n collectionConfig.auth &&\n (!collectionConfig.auth.disableLocalStrategy ||\n (typeof collectionConfig.auth.disableLocalStrategy === 'object' &&\n collectionConfig.auth.disableLocalStrategy.enableFields)) &&\n !isSavingDraft,\n )\n\n if (isSavingDraft) {\n data._status = 'draft'\n }\n\n // /////////////////////////////////////\n // Handle potentially locked documents\n // /////////////////////////////////////\n\n await checkDocumentLockStatus({\n id,\n collectionSlug: collectionConfig.slug,\n lockErrorMessage: `Document with ID ${id} is currently locked by another user and cannot be updated.`,\n overrideLock,\n req,\n })\n\n const originalDoc = await afterRead({\n collection: collectionConfig,\n context: req.context,\n depth: 0,\n doc: deepCopyObjectSimple(docWithLocales),\n draft: draftArg,\n fallbackLocale: id ? null : fallbackLocale,\n global: null,\n locale,\n overrideAccess: true,\n req,\n showHiddenFields: true,\n })\n\n const isRestoringDraftFromTrash = Boolean(originalDoc?.deletedAt) && data?._status !== 'published'\n\n if (collectionConfig.auth) {\n ensureUsernameOrEmail<TSlug>({\n authOptions: collectionConfig.auth,\n collectionSlug: collectionConfig.slug,\n data,\n operation: 'update',\n originalDoc,\n req,\n })\n }\n\n // /////////////////////////////////////\n // Delete any associated files\n // /////////////////////////////////////\n\n await deleteAssociatedFiles({\n collectionConfig,\n config,\n doc: docWithLocales,\n files: filesToUpload,\n overrideDelete: false,\n req,\n })\n\n // /////////////////////////////////////\n // beforeValidate - Fields\n // /////////////////////////////////////\n\n data = await beforeValidate<DeepPartial<DataFromCollectionSlug<TSlug>>>({\n id,\n collection: collectionConfig,\n context: req.context,\n data,\n doc: originalDoc,\n global: null,\n operation: 'update',\n overrideAccess,\n req,\n })\n\n // /////////////////////////////////////\n // beforeValidate - Collection\n // /////////////////////////////////////\n\n if (collectionConfig.hooks?.beforeValidate?.length) {\n for (const hook of collectionConfig.hooks.beforeValidate) {\n data =\n (await hook({\n collection: collectionConfig,\n context: req.context,\n data,\n operation: 'update',\n originalDoc,\n req,\n })) || data\n }\n }\n\n // /////////////////////////////////////\n // Write files to local storage\n // /////////////////////////////////////\n\n if (!collectionConfig.upload.disableLocalStorage) {\n await uploadFiles(payload, filesToUpload, req)\n }\n\n // /////////////////////////////////////\n // beforeChange - Collection\n // /////////////////////////////////////\n\n if (collectionConfig.hooks?.beforeChange?.length) {\n for (const hook of collectionConfig.hooks.beforeChange) {\n data =\n (await hook({\n collection: collectionConfig,\n context: req.context,\n data,\n operation: 'update',\n originalDoc,\n req,\n })) || data\n }\n }\n\n // /////////////////////////////////////\n // beforeChange - Fields\n // /////////////////////////////////////\n\n const beforeChangeArgs: Args<DataFromCollectionSlug<TSlug>> = {\n id,\n collection: collectionConfig,\n context: req.context,\n data: { ...data, id },\n doc: originalDoc,\n docWithLocales,\n global: null,\n operation: 'update',\n overrideAccess,\n req,\n skipValidation:\n // only skip validation for drafts when draft validation is false\n (isSavingDraft && !hasDraftValidationEnabled(collectionConfig)) ||\n // Skip validation for trash operations since they're just metadata updates\n (collectionConfig.trash && (Boolean(data?.deletedAt) || isRestoringDraftFromTrash)) ||\n // Skip validation for unpublish operations — they only change _status, not document data\n unpublishAllLocales,\n }\n\n // /////////////////////////////////////\n // Handle Localized Data Merging\n // /////////////////////////////////////\n\n let result: JsonObject = await beforeChange(beforeChangeArgs)\n let snapshotToSave: JsonObject | undefined\n\n if (config.localization && collectionConfig.versions) {\n let snapshotData: JsonObject | undefined\n let currentDoc\n\n if (collectionConfig.versions.drafts && collectionConfig.versions.drafts.localizeStatus) {\n if (publishAllLocales || unpublishAllLocales) {\n let accessibleLocaleCodes = config.localization.localeCodes\n\n if (config.localization.filterAvailableLocales) {\n const filteredLocales = await config.localization.filterAvailableLocales({\n locales: config.localization.locales,\n req,\n })\n accessibleLocaleCodes = filteredLocales.map((locale) =>\n typeof locale === 'string' ? locale : locale.code,\n )\n }\n\n if (typeof result._status !== 'object' || result._status === null) {\n result._status = {}\n }\n\n for (const localeCode of accessibleLocaleCodes) {\n result._status[localeCode] = unpublishAllLocales ? 'draft' : 'published'\n }\n } else if (!isSavingDraft) {\n // publishing a single locale\n currentDoc = await payload.db.findOne<DataFromCollectionSlug<TSlug>>({\n collection: collectionConfig.slug,\n req,\n where: { id: { equals: id } },\n })\n snapshotData = result\n }\n } else if (publishSpecificLocale) {\n // previous way of publishing a single locale\n currentDoc = await getLatestCollectionVersion({\n id,\n config: collectionConfig,\n payload,\n published: true,\n query: {\n collection: collectionConfig.slug,\n locale: 'all',\n req,\n where: { id: { equals: id } },\n },\n req,\n })\n snapshotData = {\n ...result,\n _status: 'draft',\n }\n }\n\n if (snapshotData) {\n snapshotToSave = deepCopyObjectSimple(snapshotData || {})\n\n result = mergeLocalizedData({\n configBlockReferences: config.blocks,\n dataWithLocales: result || {},\n docWithLocales: currentDoc || {},\n fields: collectionConfig.fields,\n selectedLocales: [locale],\n })\n }\n }\n\n const dataToUpdate: JsonObject = { ...result }\n\n // /////////////////////////////////////\n // Handle potential password update\n // /////////////////////////////////////\n\n if (shouldSavePassword && typeof password === 'string') {\n const { hash, salt } = await generatePasswordSaltHash({\n collection: collectionConfig,\n password,\n req,\n })\n dataToUpdate.salt = salt\n dataToUpdate.hash = hash\n delete dataToUpdate.password\n delete data.password\n }\n\n // /////////////////////////////////////\n // Update\n // /////////////////////////////////////\n\n if (!isSavingDraft) {\n // Ensure updatedAt date is always updated\n dataToUpdate.updatedAt = new Date().toISOString()\n result = await req.payload.db.updateOne({\n id,\n collection: collectionConfig.slug,\n data: dataToUpdate,\n locale,\n req,\n })\n }\n\n // /////////////////////////////////////\n // Create version\n // /////////////////////////////////////\n\n if (collectionConfig.versions) {\n result = await saveVersion({\n id,\n autosave,\n collection: collectionConfig,\n docWithLocales: result,\n draft: isSavingDraft,\n operation: 'update',\n payload,\n publishSpecificLocale,\n req,\n snapshot: snapshotToSave,\n unpublish: unpublishAllLocales,\n })\n }\n\n // /////////////////////////////////////\n // afterRead - Fields\n // /////////////////////////////////////\n\n result = await afterRead({\n collection: collectionConfig,\n context: req.context,\n depth,\n doc: result,\n draft: draftArg,\n fallbackLocale,\n global: null,\n locale,\n overrideAccess,\n populate,\n req,\n select,\n showHiddenFields,\n })\n\n // /////////////////////////////////////\n // afterRead - Collection\n // /////////////////////////////////////\n\n if (collectionConfig.hooks?.afterRead?.length) {\n for (const hook of collectionConfig.hooks.afterRead) {\n result =\n (await hook({\n collection: collectionConfig,\n context: req.context,\n doc: result,\n overrideAccess,\n req,\n })) || result\n }\n }\n\n // /////////////////////////////////////\n // afterChange - Fields\n // /////////////////////////////////////\n\n result = await afterChange({\n collection: collectionConfig,\n context: req.context,\n data,\n doc: result,\n global: null,\n operation: 'update',\n previousDoc: originalDoc,\n req,\n })\n\n // /////////////////////////////////////\n // afterChange - Collection\n // /////////////////////////////////////\n\n if (collectionConfig.hooks?.afterChange?.length) {\n for (const hook of collectionConfig.hooks.afterChange) {\n result =\n (await hook({\n collection: collectionConfig,\n context: req.context,\n data,\n doc: result,\n operation: 'update',\n overrideAccess,\n previousDoc: originalDoc,\n req,\n })) || result\n }\n }\n\n return result as TransformCollectionWithSelect<TSlug, TSelect>\n}\n"],"names":["ensureUsernameOrEmail","generatePasswordSaltHash","afterChange","afterRead","beforeChange","beforeValidate","deepCopyObjectSimple","getLatestCollectionVersion","saveVersion","deleteAssociatedFiles","uploadFiles","checkDocumentLockStatus","hasDraftsEnabled","hasDraftValidationEnabled","hasLocalizeStatusEnabled","mergeLocalizedData","updateDocument","id","autosave","collectionConfig","config","data","depth","docWithLocales","draftArg","fallbackLocale","filesToUpload","locale","overrideAccess","overrideLock","payload","populate","publishAllLocales","publishAllLocalesArg","publishSpecificLocale","req","select","showHiddenFields","unpublishAllLocales","unpublishAllLocalesArg","password","isSavingDraft","Boolean","_status","shouldSavePassword","auth","disableLocalStrategy","enableFields","collectionSlug","slug","lockErrorMessage","originalDoc","collection","context","doc","draft","global","isRestoringDraftFromTrash","deletedAt","authOptions","operation","files","overrideDelete","hooks","length","hook","upload","disableLocalStorage","beforeChangeArgs","skipValidation","trash","result","snapshotToSave","localization","versions","snapshotData","currentDoc","drafts","localizeStatus","accessibleLocaleCodes","localeCodes","filterAvailableLocales","filteredLocales","locales","map","code","localeCode","db","findOne","where","equals","published","query","configBlockReferences","blocks","dataWithLocales","fields","selectedLocales","dataToUpdate","hash","salt","updatedAt","Date","toISOString","updateOne","snapshot","unpublish","previousDoc"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../src/collections/operations/utilities/update.ts"],"sourcesContent":["import type { DeepPartial } from 'ts-essentials'\n\nimport type { Args } from '../../../fields/hooks/beforeChange/index.js'\nimport type {\n CollectionSlug,\n FileToSave,\n SanitizedConfig,\n TypedFallbackLocale,\n} from '../../../index.js'\nimport type {\n JsonObject,\n Payload,\n PayloadRequest,\n PopulateType,\n SelectType,\n TransformCollectionWithSelect,\n} from '../../../types/index.js'\nimport type {\n DataFromCollectionSlug,\n SanitizedCollectionConfig,\n SelectFromCollectionSlug,\n TypeWithID,\n} from '../../config/types.js'\n\nimport { ensureUsernameOrEmail } from '../../../auth/ensureUsernameOrEmail.js'\nimport { generatePasswordSaltHash } from '../../../auth/strategies/local/generatePasswordSaltHash.js'\nimport { afterChange } from '../../../fields/hooks/afterChange/index.js'\nimport { afterRead } from '../../../fields/hooks/afterRead/index.js'\nimport { beforeChange } from '../../../fields/hooks/beforeChange/index.js'\nimport { beforeValidate } from '../../../fields/hooks/beforeValidate/index.js'\nimport { deepCopyObjectSimple, getLatestCollectionVersion, saveVersion } from '../../../index.js'\nimport { deleteAssociatedFiles } from '../../../uploads/deleteAssociatedFiles.js'\nimport { uploadFiles } from '../../../uploads/uploadFiles.js'\nimport { checkDocumentLockStatus } from '../../../utilities/checkDocumentLockStatus.js'\nimport {\n hasDraftsEnabled,\n hasDraftValidationEnabled,\n hasLocalizeStatusEnabled,\n} from '../../../utilities/getVersionsConfig.js'\nimport { mergeLocalizedData } from '../../../utilities/mergeLocalizedData.js'\nexport type SharedUpdateDocumentArgs<TSlug extends CollectionSlug> = {\n autosave: boolean\n collectionConfig: SanitizedCollectionConfig\n config: SanitizedConfig\n data: DeepPartial<DataFromCollectionSlug<TSlug>>\n depth: number\n docWithLocales: JsonObject & TypeWithID\n draftArg: boolean\n fallbackLocale: TypedFallbackLocale\n filesToUpload: FileToSave[]\n id: number | string\n locale: string\n overrideAccess: boolean\n overrideLock: boolean\n payload: Payload\n populate?: PopulateType\n publishAllLocales?: boolean\n publishSpecificLocale?: string\n req: PayloadRequest\n select: SelectType\n showHiddenFields: boolean\n unpublishAllLocales?: boolean\n}\n\n/**\n * This function is used to update a document in the DB and return the result.\n *\n * It runs the following hooks in order:\n * - beforeValidate - Fields\n * - beforeValidate - Collection\n * - beforeChange - Collection\n * - beforeChange - Fields\n * - afterRead - Fields\n * - afterRead - Collection\n * - afterChange - Fields\n * - afterChange - Collection\n */\nexport const updateDocument = async <\n TSlug extends CollectionSlug,\n TSelect extends SelectFromCollectionSlug<TSlug> = SelectType,\n>({\n id,\n autosave,\n collectionConfig,\n config,\n data,\n depth,\n docWithLocales,\n draftArg,\n fallbackLocale,\n filesToUpload,\n locale,\n overrideAccess,\n overrideLock,\n payload,\n populate,\n publishAllLocales: publishAllLocalesArg,\n publishSpecificLocale,\n req,\n select,\n showHiddenFields,\n unpublishAllLocales: unpublishAllLocalesArg,\n}: SharedUpdateDocumentArgs<TSlug>): Promise<TransformCollectionWithSelect<TSlug, TSelect>> => {\n const password = data?.password\n const publishAllLocales =\n !draftArg &&\n (publishAllLocalesArg ?? (hasLocalizeStatusEnabled(collectionConfig) ? false : true))\n const unpublishAllLocales =\n typeof unpublishAllLocalesArg === 'string'\n ? unpublishAllLocalesArg === 'true'\n : !!unpublishAllLocalesArg\n const isSavingDraft =\n Boolean(draftArg && hasDraftsEnabled(collectionConfig)) &&\n data._status !== 'published' &&\n !publishAllLocales\n const shouldSavePassword = Boolean(\n password &&\n collectionConfig.auth &&\n (!collectionConfig.auth.disableLocalStrategy ||\n (typeof collectionConfig.auth.disableLocalStrategy === 'object' &&\n collectionConfig.auth.disableLocalStrategy.enableFields)) &&\n !isSavingDraft,\n )\n\n if (isSavingDraft) {\n data._status = 'draft'\n }\n\n // /////////////////////////////////////\n // Handle potentially locked documents\n // /////////////////////////////////////\n\n await checkDocumentLockStatus({\n id,\n collectionSlug: collectionConfig.slug,\n lockErrorMessage: `Document with ID ${id} is currently locked by another user and cannot be updated.`,\n overrideLock,\n req,\n })\n\n const originalDoc = await afterRead({\n collection: collectionConfig,\n context: req.context,\n depth: 0,\n doc: deepCopyObjectSimple(docWithLocales),\n draft: draftArg,\n fallbackLocale: id ? null : fallbackLocale,\n global: null,\n locale,\n overrideAccess: true,\n req,\n showHiddenFields: true,\n })\n\n const isRestoringDraftFromTrash = Boolean(originalDoc?.deletedAt) && data?._status !== 'published'\n\n if (collectionConfig.auth) {\n ensureUsernameOrEmail<TSlug>({\n authOptions: collectionConfig.auth,\n collectionSlug: collectionConfig.slug,\n data,\n operation: 'update',\n originalDoc,\n req,\n })\n }\n\n // /////////////////////////////////////\n // Delete any associated files\n // /////////////////////////////////////\n\n // When saving a draft on a document whose latest version is published, the file\n // referenced by docWithLocales is still actively used by the published main document.\n // Deleting it here would break the published document's file even though no publish\n // is happening. Only skip deletion in this case; when the latest version is already a\n // draft, it is safe to delete the old draft file as it is being replaced.\n const isDraftOverPublished = isSavingDraft && docWithLocales._status === 'published'\n\n if (!isDraftOverPublished) {\n await deleteAssociatedFiles({\n collectionConfig,\n config,\n doc: docWithLocales,\n files: filesToUpload,\n overrideDelete: false,\n req,\n })\n }\n\n // /////////////////////////////////////\n // beforeValidate - Fields\n // /////////////////////////////////////\n\n data = await beforeValidate<DeepPartial<DataFromCollectionSlug<TSlug>>>({\n id,\n collection: collectionConfig,\n context: req.context,\n data,\n doc: originalDoc,\n global: null,\n operation: 'update',\n overrideAccess,\n req,\n })\n\n // /////////////////////////////////////\n // beforeValidate - Collection\n // /////////////////////////////////////\n\n if (collectionConfig.hooks?.beforeValidate?.length) {\n for (const hook of collectionConfig.hooks.beforeValidate) {\n data =\n (await hook({\n collection: collectionConfig,\n context: req.context,\n data,\n operation: 'update',\n originalDoc,\n req,\n })) || data\n }\n }\n\n // /////////////////////////////////////\n // Write files to local storage\n // /////////////////////////////////////\n\n if (!collectionConfig.upload.disableLocalStorage) {\n await uploadFiles(payload, filesToUpload, req)\n }\n\n // /////////////////////////////////////\n // beforeChange - Collection\n // /////////////////////////////////////\n\n if (collectionConfig.hooks?.beforeChange?.length) {\n for (const hook of collectionConfig.hooks.beforeChange) {\n data =\n (await hook({\n collection: collectionConfig,\n context: req.context,\n data,\n operation: 'update',\n originalDoc,\n req,\n })) || data\n }\n }\n\n // /////////////////////////////////////\n // beforeChange - Fields\n // /////////////////////////////////////\n\n const beforeChangeArgs: Args<DataFromCollectionSlug<TSlug>> = {\n id,\n collection: collectionConfig,\n context: req.context,\n data: { ...data, id },\n doc: originalDoc,\n docWithLocales,\n global: null,\n operation: 'update',\n overrideAccess,\n req,\n skipValidation:\n // only skip validation for drafts when draft validation is false\n (isSavingDraft && !hasDraftValidationEnabled(collectionConfig)) ||\n // Skip validation for trash operations since they're just metadata updates\n (collectionConfig.trash && (Boolean(data?.deletedAt) || isRestoringDraftFromTrash)) ||\n // Skip validation for unpublish operations — they only change _status, not document data\n unpublishAllLocales,\n }\n\n // /////////////////////////////////////\n // Handle Localized Data Merging\n // /////////////////////////////////////\n\n let result: JsonObject = await beforeChange(beforeChangeArgs)\n let snapshotToSave: JsonObject | undefined\n\n if (config.localization && collectionConfig.versions) {\n let snapshotData: JsonObject | undefined\n let currentDoc\n\n if (collectionConfig.versions.drafts && collectionConfig.versions.drafts.localizeStatus) {\n if (publishAllLocales || unpublishAllLocales) {\n let accessibleLocaleCodes = config.localization.localeCodes\n\n if (config.localization.filterAvailableLocales) {\n const filteredLocales = await config.localization.filterAvailableLocales({\n locales: config.localization.locales,\n req,\n })\n accessibleLocaleCodes = filteredLocales.map((locale) =>\n typeof locale === 'string' ? locale : locale.code,\n )\n }\n\n if (typeof result._status !== 'object' || result._status === null) {\n result._status = {}\n }\n\n for (const localeCode of accessibleLocaleCodes) {\n result._status[localeCode] = unpublishAllLocales ? 'draft' : 'published'\n }\n } else if (!isSavingDraft) {\n // publishing a single locale\n currentDoc = await payload.db.findOne<DataFromCollectionSlug<TSlug>>({\n collection: collectionConfig.slug,\n req,\n where: { id: { equals: id } },\n })\n snapshotData = result\n }\n } else if (publishSpecificLocale) {\n // previous way of publishing a single locale\n currentDoc = await getLatestCollectionVersion({\n id,\n config: collectionConfig,\n payload,\n published: true,\n query: {\n collection: collectionConfig.slug,\n locale: 'all',\n req,\n where: { id: { equals: id } },\n },\n req,\n })\n snapshotData = {\n ...result,\n _status: 'draft',\n }\n }\n\n if (snapshotData) {\n snapshotToSave = deepCopyObjectSimple(snapshotData || {})\n\n result = mergeLocalizedData({\n configBlockReferences: config.blocks,\n dataWithLocales: result || {},\n docWithLocales: currentDoc || {},\n fields: collectionConfig.fields,\n selectedLocales: [locale],\n })\n }\n }\n\n const dataToUpdate: JsonObject = { ...result }\n\n // /////////////////////////////////////\n // Handle potential password update\n // /////////////////////////////////////\n\n if (shouldSavePassword && typeof password === 'string') {\n const { hash, salt } = await generatePasswordSaltHash({\n collection: collectionConfig,\n password,\n req,\n })\n dataToUpdate.salt = salt\n dataToUpdate.hash = hash\n delete dataToUpdate.password\n delete data.password\n }\n\n // /////////////////////////////////////\n // Update\n // /////////////////////////////////////\n\n if (!isSavingDraft) {\n // Ensure updatedAt date is always updated\n dataToUpdate.updatedAt = new Date().toISOString()\n result = await req.payload.db.updateOne({\n id,\n collection: collectionConfig.slug,\n data: dataToUpdate,\n locale,\n req,\n })\n }\n\n // /////////////////////////////////////\n // Create version\n // /////////////////////////////////////\n\n if (collectionConfig.versions) {\n result = await saveVersion({\n id,\n autosave,\n collection: collectionConfig,\n docWithLocales: result,\n draft: isSavingDraft,\n operation: 'update',\n payload,\n publishSpecificLocale,\n req,\n snapshot: snapshotToSave,\n unpublish: unpublishAllLocales,\n })\n }\n\n // /////////////////////////////////////\n // afterRead - Fields\n // /////////////////////////////////////\n\n result = await afterRead({\n collection: collectionConfig,\n context: req.context,\n depth,\n doc: result,\n draft: draftArg,\n fallbackLocale,\n global: null,\n locale,\n overrideAccess,\n populate,\n req,\n select,\n showHiddenFields,\n })\n\n // /////////////////////////////////////\n // afterRead - Collection\n // /////////////////////////////////////\n\n if (collectionConfig.hooks?.afterRead?.length) {\n for (const hook of collectionConfig.hooks.afterRead) {\n result =\n (await hook({\n collection: collectionConfig,\n context: req.context,\n doc: result,\n overrideAccess,\n req,\n })) || result\n }\n }\n\n // /////////////////////////////////////\n // afterChange - Fields\n // /////////////////////////////////////\n\n result = await afterChange({\n collection: collectionConfig,\n context: req.context,\n data,\n doc: result,\n global: null,\n operation: 'update',\n previousDoc: originalDoc,\n req,\n })\n\n // /////////////////////////////////////\n // afterChange - Collection\n // /////////////////////////////////////\n\n if (collectionConfig.hooks?.afterChange?.length) {\n for (const hook of collectionConfig.hooks.afterChange) {\n result =\n (await hook({\n collection: collectionConfig,\n context: req.context,\n data,\n doc: result,\n operation: 'update',\n overrideAccess,\n previousDoc: originalDoc,\n req,\n })) || result\n }\n }\n\n return result as TransformCollectionWithSelect<TSlug, TSelect>\n}\n"],"names":["ensureUsernameOrEmail","generatePasswordSaltHash","afterChange","afterRead","beforeChange","beforeValidate","deepCopyObjectSimple","getLatestCollectionVersion","saveVersion","deleteAssociatedFiles","uploadFiles","checkDocumentLockStatus","hasDraftsEnabled","hasDraftValidationEnabled","hasLocalizeStatusEnabled","mergeLocalizedData","updateDocument","id","autosave","collectionConfig","config","data","depth","docWithLocales","draftArg","fallbackLocale","filesToUpload","locale","overrideAccess","overrideLock","payload","populate","publishAllLocales","publishAllLocalesArg","publishSpecificLocale","req","select","showHiddenFields","unpublishAllLocales","unpublishAllLocalesArg","password","isSavingDraft","Boolean","_status","shouldSavePassword","auth","disableLocalStrategy","enableFields","collectionSlug","slug","lockErrorMessage","originalDoc","collection","context","doc","draft","global","isRestoringDraftFromTrash","deletedAt","authOptions","operation","isDraftOverPublished","files","overrideDelete","hooks","length","hook","upload","disableLocalStorage","beforeChangeArgs","skipValidation","trash","result","snapshotToSave","localization","versions","snapshotData","currentDoc","drafts","localizeStatus","accessibleLocaleCodes","localeCodes","filterAvailableLocales","filteredLocales","locales","map","code","localeCode","db","findOne","where","equals","published","query","configBlockReferences","blocks","dataWithLocales","fields","selectedLocales","dataToUpdate","hash","salt","updatedAt","Date","toISOString","updateOne","snapshot","unpublish","previousDoc"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/config/orderable/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAoB,gBAAgB,EAAE,MAAM,mCAAmC,CAAA;AAC3F,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAA;AAEnD,OAAO,KAAK,EAA4B,eAAe,EAAE,MAAM,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/config/orderable/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAoB,gBAAgB,EAAE,MAAM,mCAAmC,CAAA;AAC3F,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAA;AAEnD,OAAO,KAAK,EAA4B,eAAe,EAAE,MAAM,aAAa,CAAA;AAgB5E,eAAO,MAAM,yBAAyB,eACxB,gBAAgB,UACpB,MAAM,uBACO,MAAM,EAAE,+BACA,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,kBA2F9D,CAAA;AAED;;;GAGG;AACH,MAAM,MAAM,qBAAqB,GAAG;IAClC,cAAc,EAAE,MAAM,CAAA;IACtB,UAAU,EAAE,MAAM,EAAE,CAAA;IACpB,YAAY,EAAE,SAAS,GAAG,MAAM,CAAA;IAChC,kBAAkB,EAAE,MAAM,CAAA;IAC1B,MAAM,EAAE;QACN,EAAE,EAAE,MAAM,CAAA;QACV,GAAG,EAAE,MAAM,CAAA;KACZ,CAAA;CACF,CAAA;AAED,eAAO,MAAM,oBAAoB,WACvB,eAAe,8BACK,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,SAiN7D,CAAA"}
|
|
@@ -4,8 +4,10 @@ import { APIError } from '../../errors/index.js';
|
|
|
4
4
|
import { sanitizeField } from '../../fields/config/sanitize.js';
|
|
5
5
|
import { combineWhereConstraints } from '../../utilities/combineWhereConstraints.js';
|
|
6
6
|
import { commitTransaction } from '../../utilities/commitTransaction.js';
|
|
7
|
+
import { hasDraftsEnabled } from '../../utilities/getVersionsConfig.js';
|
|
7
8
|
import { initTransaction } from '../../utilities/initTransaction.js';
|
|
8
9
|
import { killTransaction } from '../../utilities/killTransaction.js';
|
|
10
|
+
import { getLatestCollectionVersion } from '../../versions/getLatestCollectionVersion.js';
|
|
9
11
|
import { generateKeyBetween, generateNKeysBetween } from './fractional-indexing.js';
|
|
10
12
|
import { getJoinScopeContext } from './utils/getJoinScopeContext.js';
|
|
11
13
|
import { getJoinScopeWhereFromDocData } from './utils/getJoinScopeWhereFromDocData.js';
|
|
@@ -259,8 +261,28 @@ export const addOrderableEndpoint = (config, joinFieldPathsByCollection)=>{
|
|
|
259
261
|
// Currently N (= docsToMove.length) is always 1. Maybe in the future we will
|
|
260
262
|
// allow dragging and reordering multiple documents at once via the UI.
|
|
261
263
|
const orderValues = newKeyWillBe === 'greater' ? generateNKeysBetween(targetKey, adjacentDocKey, docsToMove.length) : generateNKeysBetween(adjacentDocKey, targetKey, docsToMove.length);
|
|
264
|
+
const draftsEnabled = hasDraftsEnabled(collection);
|
|
262
265
|
// Update each document with its new order value
|
|
263
266
|
for (const [index, id] of docsToMove.entries()){
|
|
267
|
+
let draft;
|
|
268
|
+
if (draftsEnabled) {
|
|
269
|
+
const latestVersion = await getLatestCollectionVersion({
|
|
270
|
+
id,
|
|
271
|
+
config: collection,
|
|
272
|
+
payload: req.payload,
|
|
273
|
+
query: {
|
|
274
|
+
collection: collection.slug,
|
|
275
|
+
req,
|
|
276
|
+
where: {
|
|
277
|
+
id: {
|
|
278
|
+
equals: id
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
},
|
|
282
|
+
req
|
|
283
|
+
});
|
|
284
|
+
draft = latestVersion?._status === 'draft';
|
|
285
|
+
}
|
|
264
286
|
await req.payload.update({
|
|
265
287
|
id,
|
|
266
288
|
collection: collection.slug,
|
|
@@ -268,6 +290,7 @@ export const addOrderableEndpoint = (config, joinFieldPathsByCollection)=>{
|
|
|
268
290
|
[orderableFieldName]: orderValues[index]
|
|
269
291
|
},
|
|
270
292
|
depth: 0,
|
|
293
|
+
draft,
|
|
271
294
|
req
|
|
272
295
|
});
|
|
273
296
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/config/orderable/index.ts"],"sourcesContent":["import { status as httpStatus } from 'http-status'\n\nimport type { BeforeChangeHook, CollectionConfig } from '../../collections/config/types.js'\nimport type { Config } from '../../config/types.js'\nimport type { Field, TextField } from '../../fields/config/types.js'\nimport type { Endpoint, PayloadHandler, SanitizedConfig } from '../types.js'\n\nimport { executeAccess } from '../../auth/executeAccess.js'\nimport { APIError } from '../../errors/index.js'\nimport { sanitizeField } from '../../fields/config/sanitize.js'\nimport { combineWhereConstraints } from '../../utilities/combineWhereConstraints.js'\nimport { commitTransaction } from '../../utilities/commitTransaction.js'\nimport { initTransaction } from '../../utilities/initTransaction.js'\nimport { killTransaction } from '../../utilities/killTransaction.js'\nimport { generateKeyBetween, generateNKeysBetween } from './fractional-indexing.js'\nimport { getJoinScopeContext } from './utils/getJoinScopeContext.js'\nimport { getJoinScopeWhereFromDocData } from './utils/getJoinScopeWhereFromDocData.js'\nimport { resolvePendingTargetKey } from './utils/resolvePendingTargetKey.js'\n\nexport const addOrderableFieldsAndHook = async (\n collection: CollectionConfig,\n config: Config,\n orderableFieldNames: string[],\n joinFieldPathsByCollection?: Map<string, Map<string, string>>,\n) => {\n // 1. Add fields\n for (const orderableFieldName of orderableFieldNames) {\n const orderField: TextField = {\n name: orderableFieldName,\n type: 'text',\n admin: {\n disableBulkEdit: true,\n disabled: true,\n disableGroupBy: true,\n disableListColumn: true,\n disableListFilter: true,\n hidden: true,\n readOnly: true,\n },\n hooks: {\n beforeDuplicate: [\n ({ siblingData }) => {\n delete siblingData[orderableFieldName]\n },\n ],\n },\n index: true,\n }\n\n // Sanitize the field using the standard sanitization logic\n await sanitizeField({\n collectionConfig: collection,\n config,\n existingFieldNames: new Set(),\n field: orderField,\n index: 0,\n isTopLevelField: true,\n joinPath: '',\n parentIndexPath: '',\n parentIsLocalized: false,\n parentSchemaPath: '',\n requireFieldLevelRichTextEditor: false,\n validRelationships: null,\n })\n\n collection.fields.unshift(orderField)\n }\n\n // 2. Add hook\n if (!collection.hooks) {\n collection.hooks = {}\n }\n if (!collection.hooks.beforeChange) {\n collection.hooks.beforeChange = []\n }\n\n const orderBeforeChangeHook: BeforeChangeHook = async ({ data, originalDoc, req }) => {\n for (const orderableFieldName of orderableFieldNames) {\n if (!data[orderableFieldName] && !originalDoc?.[orderableFieldName]) {\n const joinScopeWhere = getJoinScopeWhereFromDocData({\n collectionSlug: collection.slug,\n data,\n joinFieldPathsByCollection,\n orderableFieldName,\n originalDoc,\n })\n\n const lastDoc = await req.payload.find({\n collection: collection.slug,\n depth: 0,\n limit: 1,\n pagination: false,\n req,\n select: { [orderableFieldName]: true },\n sort: `-${orderableFieldName}`,\n where: combineWhereConstraints([\n {\n [orderableFieldName]: {\n exists: true,\n },\n },\n joinScopeWhere ?? undefined,\n ]),\n })\n\n const lastOrderValue = lastDoc.docs[0]?.[orderableFieldName] || null\n data[orderableFieldName] = generateKeyBetween(lastOrderValue, null)\n }\n }\n\n return data\n }\n\n collection.hooks.beforeChange.push(orderBeforeChangeHook)\n}\n\n/**\n * The body of the reorder endpoint.\n * @internal\n */\nexport type OrderableEndpointBody = {\n collectionSlug: string\n docsToMove: string[]\n newKeyWillBe: 'greater' | 'less'\n orderableFieldName: string\n target: {\n id: string\n key: string\n }\n}\n\nexport const addOrderableEndpoint = (\n config: SanitizedConfig,\n joinFieldPathsByCollection: Map<string, Map<string, string>>,\n) => {\n // 3. Add endpoint\n const reorderHandler: PayloadHandler = async (req) => {\n const body = (await req.json?.()) as OrderableEndpointBody\n\n const { collectionSlug, docsToMove, newKeyWillBe, orderableFieldName, target } = body\n\n if (!Array.isArray(docsToMove) || docsToMove.length === 0) {\n return new Response(JSON.stringify({ error: 'docsToMove must be a non-empty array' }), {\n headers: { 'Content-Type': 'application/json' },\n status: 400,\n })\n }\n if (newKeyWillBe !== 'greater' && newKeyWillBe !== 'less') {\n return new Response(JSON.stringify({ error: 'newKeyWillBe must be \"greater\" or \"less\"' }), {\n headers: { 'Content-Type': 'application/json' },\n status: 400,\n })\n }\n const collection = config.collections.find((c) => c.slug === collectionSlug)\n if (!collection) {\n return new Response(JSON.stringify({ error: `Collection ${collectionSlug} not found` }), {\n headers: { 'Content-Type': 'application/json' },\n status: 400,\n })\n }\n if (typeof orderableFieldName !== 'string') {\n return new Response(JSON.stringify({ error: 'orderableFieldName must be a string' }), {\n headers: { 'Content-Type': 'application/json' },\n status: 400,\n })\n }\n\n const { joinScopeWhere, targetDoc } = await getJoinScopeContext({\n collectionSlug: collection.slug,\n joinFieldPathsByCollection,\n orderableFieldName,\n req,\n target,\n })\n\n // Prevent reordering if user doesn't have editing permissions\n if (collection.access?.update) {\n await executeAccess(\n {\n // Currently only one doc can be moved at a time. We should review this if we want to allow\n // multiple docs to be moved at once in the future.\n id: docsToMove[0],\n data: {},\n req,\n },\n collection.access.update,\n )\n }\n /**\n * If there is no target.key, we can assume the user enabled `orderable`\n * on a collection with existing documents, and that this is the first\n * time they tried to reorder them. Therefore, we perform a one-time\n * migration by setting the key value for all documents. We do this\n * instead of enforcing `required` and `unique` at the database schema\n * level, so that users don't have to run a migration when they enable\n * `orderable` on a collection with existing documents.\n */\n if (!target.key) {\n const { docs } = await req.payload.find({\n collection: collection.slug,\n depth: 0,\n limit: 0,\n req,\n select: { [orderableFieldName]: true },\n where: combineWhereConstraints([\n {\n [orderableFieldName]: {\n exists: false,\n },\n },\n joinScopeWhere ?? undefined,\n ]),\n })\n await initTransaction(req)\n // We cannot update all documents in a single operation with `payload.update`,\n // because they would all end up with the same order key (`a0`).\n try {\n for (const doc of docs) {\n await req.payload.update({\n id: doc.id,\n collection: collection.slug,\n data: {\n // no data needed since the order hooks will handle this\n },\n depth: 0,\n req,\n })\n await commitTransaction(req)\n }\n } catch (e) {\n await killTransaction(req)\n if (e instanceof Error) {\n throw new APIError(e.message, httpStatus.INTERNAL_SERVER_ERROR)\n }\n }\n\n return new Response(JSON.stringify({ message: 'initial migration', success: true }), {\n headers: { 'Content-Type': 'application/json' },\n status: 200,\n })\n }\n\n if (\n typeof target !== 'object' ||\n typeof target.id === 'undefined' ||\n typeof target.key !== 'string'\n ) {\n return new Response(JSON.stringify({ error: 'target must be an object with id' }), {\n headers: { 'Content-Type': 'application/json' },\n status: 400,\n })\n }\n\n const targetId = target.id\n const targetKey = await resolvePendingTargetKey({\n collectionSlug: collection.slug,\n orderableFieldName,\n req,\n targetDoc,\n targetID: targetId,\n targetKey: target.key,\n })\n\n // The reason the endpoint does not receive this docId as an argument is that there\n // are situations where the user may not see or know what the next or previous one is. For\n // example, access control restrictions, if docBefore is the last one on the page, etc.\n const adjacentDoc = await req.payload.find({\n collection: collection.slug,\n depth: 0,\n limit: 1,\n pagination: false,\n select: { [orderableFieldName]: true },\n sort: newKeyWillBe === 'greater' ? orderableFieldName : `-${orderableFieldName}`,\n where: combineWhereConstraints([\n {\n [orderableFieldName]: {\n [newKeyWillBe === 'greater' ? 'greater_than' : 'less_than']: targetKey,\n },\n },\n joinScopeWhere ?? undefined,\n ]),\n })\n const adjacentDocKey = adjacentDoc.docs?.[0]?.[orderableFieldName] || null\n\n // Currently N (= docsToMove.length) is always 1. Maybe in the future we will\n // allow dragging and reordering multiple documents at once via the UI.\n const orderValues =\n newKeyWillBe === 'greater'\n ? generateNKeysBetween(targetKey, adjacentDocKey, docsToMove.length)\n : generateNKeysBetween(adjacentDocKey, targetKey, docsToMove.length)\n\n // Update each document with its new order value\n for (const [index, id] of docsToMove.entries()) {\n await req.payload.update({\n id,\n collection: collection.slug,\n data: {\n [orderableFieldName]: orderValues[index],\n },\n depth: 0,\n req,\n })\n }\n\n return new Response(JSON.stringify({ orderValues, success: true }), {\n headers: { 'Content-Type': 'application/json' },\n status: 200,\n })\n }\n\n const reorderEndpoint: Endpoint = {\n handler: reorderHandler,\n method: 'post',\n path: '/reorder',\n }\n\n if (!config.endpoints) {\n config.endpoints = []\n }\n\n config.endpoints.push(reorderEndpoint)\n}\n"],"names":["status","httpStatus","executeAccess","APIError","sanitizeField","combineWhereConstraints","commitTransaction","initTransaction","killTransaction","generateKeyBetween","generateNKeysBetween","getJoinScopeContext","getJoinScopeWhereFromDocData","resolvePendingTargetKey","addOrderableFieldsAndHook","collection","config","orderableFieldNames","joinFieldPathsByCollection","orderableFieldName","orderField","name","type","admin","disableBulkEdit","disabled","disableGroupBy","disableListColumn","disableListFilter","hidden","readOnly","hooks","beforeDuplicate","siblingData","index","collectionConfig","existingFieldNames","Set","field","isTopLevelField","joinPath","parentIndexPath","parentIsLocalized","parentSchemaPath","requireFieldLevelRichTextEditor","validRelationships","fields","unshift","beforeChange","orderBeforeChangeHook","data","originalDoc","req","joinScopeWhere","collectionSlug","slug","lastDoc","payload","find","depth","limit","pagination","select","sort","where","exists","undefined","lastOrderValue","docs","push","addOrderableEndpoint","reorderHandler","body","json","docsToMove","newKeyWillBe","target","Array","isArray","length","Response","JSON","stringify","error","headers","collections","c","targetDoc","access","update","id","key","doc","e","Error","message","INTERNAL_SERVER_ERROR","success","targetId","targetKey","targetID","adjacentDoc","adjacentDocKey","orderValues","entries","reorderEndpoint","handler","method","path","endpoints"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../src/config/orderable/index.ts"],"sourcesContent":["import { status as httpStatus } from 'http-status'\n\nimport type { BeforeChangeHook, CollectionConfig } from '../../collections/config/types.js'\nimport type { Config } from '../../config/types.js'\nimport type { Field, TextField } from '../../fields/config/types.js'\nimport type { Endpoint, PayloadHandler, SanitizedConfig } from '../types.js'\n\nimport { executeAccess } from '../../auth/executeAccess.js'\nimport { APIError } from '../../errors/index.js'\nimport { sanitizeField } from '../../fields/config/sanitize.js'\nimport { combineWhereConstraints } from '../../utilities/combineWhereConstraints.js'\nimport { commitTransaction } from '../../utilities/commitTransaction.js'\nimport { hasDraftsEnabled } from '../../utilities/getVersionsConfig.js'\nimport { initTransaction } from '../../utilities/initTransaction.js'\nimport { killTransaction } from '../../utilities/killTransaction.js'\nimport { getLatestCollectionVersion } from '../../versions/getLatestCollectionVersion.js'\nimport { generateKeyBetween, generateNKeysBetween } from './fractional-indexing.js'\nimport { getJoinScopeContext } from './utils/getJoinScopeContext.js'\nimport { getJoinScopeWhereFromDocData } from './utils/getJoinScopeWhereFromDocData.js'\nimport { resolvePendingTargetKey } from './utils/resolvePendingTargetKey.js'\n\nexport const addOrderableFieldsAndHook = async (\n collection: CollectionConfig,\n config: Config,\n orderableFieldNames: string[],\n joinFieldPathsByCollection?: Map<string, Map<string, string>>,\n) => {\n // 1. Add fields\n for (const orderableFieldName of orderableFieldNames) {\n const orderField: TextField = {\n name: orderableFieldName,\n type: 'text',\n admin: {\n disableBulkEdit: true,\n disabled: true,\n disableGroupBy: true,\n disableListColumn: true,\n disableListFilter: true,\n hidden: true,\n readOnly: true,\n },\n hooks: {\n beforeDuplicate: [\n ({ siblingData }) => {\n delete siblingData[orderableFieldName]\n },\n ],\n },\n index: true,\n }\n\n // Sanitize the field using the standard sanitization logic\n await sanitizeField({\n collectionConfig: collection,\n config,\n existingFieldNames: new Set(),\n field: orderField,\n index: 0,\n isTopLevelField: true,\n joinPath: '',\n parentIndexPath: '',\n parentIsLocalized: false,\n parentSchemaPath: '',\n requireFieldLevelRichTextEditor: false,\n validRelationships: null,\n })\n\n collection.fields.unshift(orderField)\n }\n\n // 2. Add hook\n if (!collection.hooks) {\n collection.hooks = {}\n }\n if (!collection.hooks.beforeChange) {\n collection.hooks.beforeChange = []\n }\n\n const orderBeforeChangeHook: BeforeChangeHook = async ({ data, originalDoc, req }) => {\n for (const orderableFieldName of orderableFieldNames) {\n if (!data[orderableFieldName] && !originalDoc?.[orderableFieldName]) {\n const joinScopeWhere = getJoinScopeWhereFromDocData({\n collectionSlug: collection.slug,\n data,\n joinFieldPathsByCollection,\n orderableFieldName,\n originalDoc,\n })\n\n const lastDoc = await req.payload.find({\n collection: collection.slug,\n depth: 0,\n limit: 1,\n pagination: false,\n req,\n select: { [orderableFieldName]: true },\n sort: `-${orderableFieldName}`,\n where: combineWhereConstraints([\n {\n [orderableFieldName]: {\n exists: true,\n },\n },\n joinScopeWhere ?? undefined,\n ]),\n })\n\n const lastOrderValue = lastDoc.docs[0]?.[orderableFieldName] || null\n data[orderableFieldName] = generateKeyBetween(lastOrderValue, null)\n }\n }\n\n return data\n }\n\n collection.hooks.beforeChange.push(orderBeforeChangeHook)\n}\n\n/**\n * The body of the reorder endpoint.\n * @internal\n */\nexport type OrderableEndpointBody = {\n collectionSlug: string\n docsToMove: string[]\n newKeyWillBe: 'greater' | 'less'\n orderableFieldName: string\n target: {\n id: string\n key: string\n }\n}\n\nexport const addOrderableEndpoint = (\n config: SanitizedConfig,\n joinFieldPathsByCollection: Map<string, Map<string, string>>,\n) => {\n // 3. Add endpoint\n const reorderHandler: PayloadHandler = async (req) => {\n const body = (await req.json?.()) as OrderableEndpointBody\n\n const { collectionSlug, docsToMove, newKeyWillBe, orderableFieldName, target } = body\n\n if (!Array.isArray(docsToMove) || docsToMove.length === 0) {\n return new Response(JSON.stringify({ error: 'docsToMove must be a non-empty array' }), {\n headers: { 'Content-Type': 'application/json' },\n status: 400,\n })\n }\n if (newKeyWillBe !== 'greater' && newKeyWillBe !== 'less') {\n return new Response(JSON.stringify({ error: 'newKeyWillBe must be \"greater\" or \"less\"' }), {\n headers: { 'Content-Type': 'application/json' },\n status: 400,\n })\n }\n const collection = config.collections.find((c) => c.slug === collectionSlug)\n if (!collection) {\n return new Response(JSON.stringify({ error: `Collection ${collectionSlug} not found` }), {\n headers: { 'Content-Type': 'application/json' },\n status: 400,\n })\n }\n if (typeof orderableFieldName !== 'string') {\n return new Response(JSON.stringify({ error: 'orderableFieldName must be a string' }), {\n headers: { 'Content-Type': 'application/json' },\n status: 400,\n })\n }\n\n const { joinScopeWhere, targetDoc } = await getJoinScopeContext({\n collectionSlug: collection.slug,\n joinFieldPathsByCollection,\n orderableFieldName,\n req,\n target,\n })\n\n // Prevent reordering if user doesn't have editing permissions\n if (collection.access?.update) {\n await executeAccess(\n {\n // Currently only one doc can be moved at a time. We should review this if we want to allow\n // multiple docs to be moved at once in the future.\n id: docsToMove[0],\n data: {},\n req,\n },\n collection.access.update,\n )\n }\n /**\n * If there is no target.key, we can assume the user enabled `orderable`\n * on a collection with existing documents, and that this is the first\n * time they tried to reorder them. Therefore, we perform a one-time\n * migration by setting the key value for all documents. We do this\n * instead of enforcing `required` and `unique` at the database schema\n * level, so that users don't have to run a migration when they enable\n * `orderable` on a collection with existing documents.\n */\n if (!target.key) {\n const { docs } = await req.payload.find({\n collection: collection.slug,\n depth: 0,\n limit: 0,\n req,\n select: { [orderableFieldName]: true },\n where: combineWhereConstraints([\n {\n [orderableFieldName]: {\n exists: false,\n },\n },\n joinScopeWhere ?? undefined,\n ]),\n })\n await initTransaction(req)\n // We cannot update all documents in a single operation with `payload.update`,\n // because they would all end up with the same order key (`a0`).\n try {\n for (const doc of docs) {\n await req.payload.update({\n id: doc.id,\n collection: collection.slug,\n data: {\n // no data needed since the order hooks will handle this\n },\n depth: 0,\n req,\n })\n await commitTransaction(req)\n }\n } catch (e) {\n await killTransaction(req)\n if (e instanceof Error) {\n throw new APIError(e.message, httpStatus.INTERNAL_SERVER_ERROR)\n }\n }\n\n return new Response(JSON.stringify({ message: 'initial migration', success: true }), {\n headers: { 'Content-Type': 'application/json' },\n status: 200,\n })\n }\n\n if (\n typeof target !== 'object' ||\n typeof target.id === 'undefined' ||\n typeof target.key !== 'string'\n ) {\n return new Response(JSON.stringify({ error: 'target must be an object with id' }), {\n headers: { 'Content-Type': 'application/json' },\n status: 400,\n })\n }\n\n const targetId = target.id\n const targetKey = await resolvePendingTargetKey({\n collectionSlug: collection.slug,\n orderableFieldName,\n req,\n targetDoc,\n targetID: targetId,\n targetKey: target.key,\n })\n\n // The reason the endpoint does not receive this docId as an argument is that there\n // are situations where the user may not see or know what the next or previous one is. For\n // example, access control restrictions, if docBefore is the last one on the page, etc.\n const adjacentDoc = await req.payload.find({\n collection: collection.slug,\n depth: 0,\n limit: 1,\n pagination: false,\n select: { [orderableFieldName]: true },\n sort: newKeyWillBe === 'greater' ? orderableFieldName : `-${orderableFieldName}`,\n where: combineWhereConstraints([\n {\n [orderableFieldName]: {\n [newKeyWillBe === 'greater' ? 'greater_than' : 'less_than']: targetKey,\n },\n },\n joinScopeWhere ?? undefined,\n ]),\n })\n const adjacentDocKey = adjacentDoc.docs?.[0]?.[orderableFieldName] || null\n\n // Currently N (= docsToMove.length) is always 1. Maybe in the future we will\n // allow dragging and reordering multiple documents at once via the UI.\n const orderValues =\n newKeyWillBe === 'greater'\n ? generateNKeysBetween(targetKey, adjacentDocKey, docsToMove.length)\n : generateNKeysBetween(adjacentDocKey, targetKey, docsToMove.length)\n\n const draftsEnabled = hasDraftsEnabled(collection)\n\n // Update each document with its new order value\n for (const [index, id] of docsToMove.entries()) {\n let draft: boolean | undefined\n\n if (draftsEnabled) {\n const latestVersion = await getLatestCollectionVersion({\n id,\n config: collection,\n payload: req.payload,\n query: {\n collection: collection.slug,\n req,\n where: { id: { equals: id } },\n },\n req,\n })\n\n draft = latestVersion?._status === 'draft'\n }\n\n await req.payload.update({\n id,\n collection: collection.slug,\n data: {\n [orderableFieldName]: orderValues[index],\n },\n depth: 0,\n draft,\n req,\n })\n }\n\n return new Response(JSON.stringify({ orderValues, success: true }), {\n headers: { 'Content-Type': 'application/json' },\n status: 200,\n })\n }\n\n const reorderEndpoint: Endpoint = {\n handler: reorderHandler,\n method: 'post',\n path: '/reorder',\n }\n\n if (!config.endpoints) {\n config.endpoints = []\n }\n\n config.endpoints.push(reorderEndpoint)\n}\n"],"names":["status","httpStatus","executeAccess","APIError","sanitizeField","combineWhereConstraints","commitTransaction","hasDraftsEnabled","initTransaction","killTransaction","getLatestCollectionVersion","generateKeyBetween","generateNKeysBetween","getJoinScopeContext","getJoinScopeWhereFromDocData","resolvePendingTargetKey","addOrderableFieldsAndHook","collection","config","orderableFieldNames","joinFieldPathsByCollection","orderableFieldName","orderField","name","type","admin","disableBulkEdit","disabled","disableGroupBy","disableListColumn","disableListFilter","hidden","readOnly","hooks","beforeDuplicate","siblingData","index","collectionConfig","existingFieldNames","Set","field","isTopLevelField","joinPath","parentIndexPath","parentIsLocalized","parentSchemaPath","requireFieldLevelRichTextEditor","validRelationships","fields","unshift","beforeChange","orderBeforeChangeHook","data","originalDoc","req","joinScopeWhere","collectionSlug","slug","lastDoc","payload","find","depth","limit","pagination","select","sort","where","exists","undefined","lastOrderValue","docs","push","addOrderableEndpoint","reorderHandler","body","json","docsToMove","newKeyWillBe","target","Array","isArray","length","Response","JSON","stringify","error","headers","collections","c","targetDoc","access","update","id","key","doc","e","Error","message","INTERNAL_SERVER_ERROR","success","targetId","targetKey","targetID","adjacentDoc","adjacentDocKey","orderValues","draftsEnabled","entries","draft","latestVersion","query","equals","_status","reorderEndpoint","handler","method","path","endpoints"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ValidationError.d.ts","sourceRoot":"","sources":["../../src/errors/ValidationError.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAA;AAKzD,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AACpE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA;AAEvD,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AAExC,+EAA+E;AAC/E,eAAO,MAAM,mBAAmB,oBAAoB,CAAA;AAEpD,MAAM,MAAM,oBAAoB,GAAG;IACjC,KAAK,CAAC,EAAE,aAAa,GAAG,WAAW,CAAA;IAEnC,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,MAAM,CAAA;
|
|
1
|
+
{"version":3,"file":"ValidationError.d.ts","sourceRoot":"","sources":["../../src/errors/ValidationError.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAA;AAKzD,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AACpE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA;AAEvD,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AAExC,+EAA+E;AAC/E,eAAO,MAAM,mBAAmB,oBAAoB,CAAA;AAEpD,MAAM,MAAM,oBAAoB,GAAG;IACjC,KAAK,CAAC,EAAE,aAAa,GAAG,WAAW,CAAA;IAEnC,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,CAAA;AAED,qBAAa,eAAgB,SAAQ,QAAQ,CAAC;IAC5C,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,MAAM,EAAE,oBAAoB,EAAE,CAAA;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB,CAAC;gBAEE,OAAO,EAAE;QACP,UAAU,CAAC,EAAE,MAAM,CAAA;QACnB,MAAM,EAAE,oBAAoB,EAAE,CAAA;QAC9B,MAAM,CAAC,EAAE,MAAM,CAAA;QACf,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;QACpB;;WAEG;QACH,GAAG,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,CAAA;KAC9B,EACD,CAAC,CAAC,EAAE,SAAS;CA0ChB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/errors/ValidationError.ts"],"sourcesContent":["import type { TFunction } from '@payloadcms/translations'\n\nimport { en } from '@payloadcms/translations/languages/en'\nimport { status as httpStatus } from 'http-status'\n\nimport type { LabelFunction, StaticLabel } from '../config/types.js'\nimport type { PayloadRequest } from '../types/index.js'\n\nimport { APIError } from './APIError.js'\n\n/** @deprecated Use `instanceof ValidationError` instead of name comparison. */\nexport const ValidationErrorName = 'ValidationError'\n\nexport type ValidationFieldError = {\n label?: LabelFunction | StaticLabel\n // The error message to display for this field\n message: string\n path: string\n}\n\nexport class ValidationError extends APIError<{\n collection?: string\n errors: ValidationFieldError[]\n global?: string\n}> {\n constructor(\n results: {\n collection?: string\n errors: ValidationFieldError[]\n global?: string\n id?: number | string\n /**\n * req needs to be passed through (if you have one) in order to resolve label functions that may be part of the errors array\n */\n req?: Partial<PayloadRequest>\n },\n t?: TFunction,\n ) {\n const message = t\n ? t('error:followingFieldsInvalid', { count: results.errors.length })\n : results.errors.length === 1\n ? en.translations.error.followingFieldsInvalid_one\n : en.translations.error.followingFieldsInvalid_other\n\n const req = results.req\n // delete to avoid logging the whole req\n delete results['req']\n\n super(\n `${message} ${results.errors\n .map((f) => {\n if (f.label) {\n if (typeof f.label === 'function') {\n if (!req || !req.i18n || !req.t) {\n return f.path\n }\n\n return f.label({ i18n: req.i18n, t: req.t })\n }\n\n if (typeof f.label === 'object') {\n if (req?.i18n?.language) {\n return f.label[req.i18n.language]\n }\n\n return f.label[Object.keys(f.label)[0]!]\n }\n\n return f.label\n }\n\n return f.path\n })\n .join(', ')}`,\n httpStatus.BAD_REQUEST,\n results,\n )\n }\n}\n"],"names":["en","status","httpStatus","APIError","ValidationErrorName","ValidationError","results","t","message","count","errors","length","translations","error","followingFieldsInvalid_one","followingFieldsInvalid_other","req","map","f","label","i18n","path","language","Object","keys","join","BAD_REQUEST"],"mappings":"AAEA,SAASA,EAAE,QAAQ,wCAAuC;AAC1D,SAASC,UAAUC,UAAU,QAAQ,cAAa;AAKlD,SAASC,QAAQ,QAAQ,gBAAe;AAExC,6EAA6E,GAC7E,OAAO,MAAMC,sBAAsB,kBAAiB;
|
|
1
|
+
{"version":3,"sources":["../../src/errors/ValidationError.ts"],"sourcesContent":["import type { TFunction } from '@payloadcms/translations'\n\nimport { en } from '@payloadcms/translations/languages/en'\nimport { status as httpStatus } from 'http-status'\n\nimport type { LabelFunction, StaticLabel } from '../config/types.js'\nimport type { PayloadRequest } from '../types/index.js'\n\nimport { APIError } from './APIError.js'\n\n/** @deprecated Use `instanceof ValidationError` instead of name comparison. */\nexport const ValidationErrorName = 'ValidationError'\n\nexport type ValidationFieldError = {\n label?: LabelFunction | StaticLabel\n // The error message to display for this field\n message: string\n path: string\n tableName?: string\n}\n\nexport class ValidationError extends APIError<{\n collection?: string\n errors: ValidationFieldError[]\n global?: string\n}> {\n constructor(\n results: {\n collection?: string\n errors: ValidationFieldError[]\n global?: string\n id?: number | string\n /**\n * req needs to be passed through (if you have one) in order to resolve label functions that may be part of the errors array\n */\n req?: Partial<PayloadRequest>\n },\n t?: TFunction,\n ) {\n const message = t\n ? t('error:followingFieldsInvalid', { count: results.errors.length })\n : results.errors.length === 1\n ? en.translations.error.followingFieldsInvalid_one\n : en.translations.error.followingFieldsInvalid_other\n\n const req = results.req\n // delete to avoid logging the whole req\n delete results['req']\n\n super(\n `${message} ${results.errors\n .map((f) => {\n if (f.label) {\n if (typeof f.label === 'function') {\n if (!req || !req.i18n || !req.t) {\n return f.path\n }\n\n return f.label({ i18n: req.i18n, t: req.t })\n }\n\n if (typeof f.label === 'object') {\n if (req?.i18n?.language) {\n return f.label[req.i18n.language]\n }\n\n return f.label[Object.keys(f.label)[0]!]\n }\n\n return f.label\n }\n\n return f.path\n })\n .join(', ')}`,\n httpStatus.BAD_REQUEST,\n results,\n )\n }\n}\n"],"names":["en","status","httpStatus","APIError","ValidationErrorName","ValidationError","results","t","message","count","errors","length","translations","error","followingFieldsInvalid_one","followingFieldsInvalid_other","req","map","f","label","i18n","path","language","Object","keys","join","BAD_REQUEST"],"mappings":"AAEA,SAASA,EAAE,QAAQ,wCAAuC;AAC1D,SAASC,UAAUC,UAAU,QAAQ,cAAa;AAKlD,SAASC,QAAQ,QAAQ,gBAAe;AAExC,6EAA6E,GAC7E,OAAO,MAAMC,sBAAsB,kBAAiB;AAUpD,OAAO,MAAMC,wBAAwBF;IAKnC,YACEG,OASC,EACDC,CAAa,CACb;QACA,MAAMC,UAAUD,IACZA,EAAE,gCAAgC;YAAEE,OAAOH,QAAQI,MAAM,CAACC,MAAM;QAAC,KACjEL,QAAQI,MAAM,CAACC,MAAM,KAAK,IACxBX,GAAGY,YAAY,CAACC,KAAK,CAACC,0BAA0B,GAChDd,GAAGY,YAAY,CAACC,KAAK,CAACE,4BAA4B;QAExD,MAAMC,MAAMV,QAAQU,GAAG;QACvB,wCAAwC;QACxC,OAAOV,OAAO,CAAC,MAAM;QAErB,KAAK,CACH,GAAGE,QAAQ,CAAC,EAAEF,QAAQI,MAAM,CACzBO,GAAG,CAAC,CAACC;YACJ,IAAIA,EAAEC,KAAK,EAAE;gBACX,IAAI,OAAOD,EAAEC,KAAK,KAAK,YAAY;oBACjC,IAAI,CAACH,OAAO,CAACA,IAAII,IAAI,IAAI,CAACJ,IAAIT,CAAC,EAAE;wBAC/B,OAAOW,EAAEG,IAAI;oBACf;oBAEA,OAAOH,EAAEC,KAAK,CAAC;wBAAEC,MAAMJ,IAAII,IAAI;wBAAEb,GAAGS,IAAIT,CAAC;oBAAC;gBAC5C;gBAEA,IAAI,OAAOW,EAAEC,KAAK,KAAK,UAAU;oBAC/B,IAAIH,KAAKI,MAAME,UAAU;wBACvB,OAAOJ,EAAEC,KAAK,CAACH,IAAII,IAAI,CAACE,QAAQ,CAAC;oBACnC;oBAEA,OAAOJ,EAAEC,KAAK,CAACI,OAAOC,IAAI,CAACN,EAAEC,KAAK,CAAC,CAAC,EAAE,CAAE;gBAC1C;gBAEA,OAAOD,EAAEC,KAAK;YAChB;YAEA,OAAOD,EAAEG,IAAI;QACf,GACCI,IAAI,CAAC,OAAO,EACfvB,WAAWwB,WAAW,EACtBpB;IAEJ;AACF"}
|
package/dist/index.bundled.d.ts
CHANGED
|
@@ -764,6 +764,7 @@ type ValidationFieldError = {
|
|
|
764
764
|
label?: LabelFunction | StaticLabel;
|
|
765
765
|
message: string;
|
|
766
766
|
path: string;
|
|
767
|
+
tableName?: string;
|
|
767
768
|
};
|
|
768
769
|
declare class ValidationError extends APIError<{
|
|
769
770
|
collection?: string;
|
|
@@ -1132,11 +1133,9 @@ type FieldPaths = {
|
|
|
1132
1133
|
* Nested fields will have a path that includes the parent field names
|
|
1133
1134
|
* if they are nested within a group, array, block or named tab.
|
|
1134
1135
|
*
|
|
1135
|
-
* Collapsibles and unnamed tabs will have arbitrary paths
|
|
1136
|
+
* Collapsibles, rows and unnamed tabs will have arbitrary paths
|
|
1136
1137
|
* that look like _index-0, _index-1, etc.
|
|
1137
1138
|
*
|
|
1138
|
-
* Row fields will not have a path.
|
|
1139
|
-
*
|
|
1140
1139
|
* @example 'parentGroupField.childTextField'
|
|
1141
1140
|
*
|
|
1142
1141
|
* @default field.name
|
|
@@ -7326,8 +7325,8 @@ type RelationshipFieldDiffServerComponent = FieldDiffServerComponent<Relationshi
|
|
|
7326
7325
|
type RelationshipFieldDiffClientComponent = FieldDiffClientComponent<RelationshipFieldClient>;
|
|
7327
7326
|
|
|
7328
7327
|
type RowFieldClientWithoutType = MarkOptional<RowFieldClient, 'type'>;
|
|
7329
|
-
type RowFieldBaseClientProps =
|
|
7330
|
-
type RowFieldClientProps =
|
|
7328
|
+
type RowFieldBaseClientProps = FieldPaths & Pick<ClientComponentProps, 'forceRender'>;
|
|
7329
|
+
type RowFieldClientProps = ClientFieldBase<RowFieldClientWithoutType> & RowFieldBaseClientProps;
|
|
7331
7330
|
type RowFieldServerProps = ServerFieldBase<RowField, RowFieldClientWithoutType>;
|
|
7332
7331
|
type RowFieldServerComponent = FieldServerComponent<RowField, RowFieldClientWithoutType>;
|
|
7333
7332
|
type RowFieldClientComponent = FieldClientComponent<RowFieldClientWithoutType, RowFieldBaseClientProps>;
|
|
@@ -6,6 +6,7 @@ type Args<T> = {
|
|
|
6
6
|
collection: Collection;
|
|
7
7
|
config: SanitizedConfig;
|
|
8
8
|
data: T;
|
|
9
|
+
draft?: boolean;
|
|
9
10
|
isDuplicating?: boolean;
|
|
10
11
|
operation: 'create' | 'update';
|
|
11
12
|
originalDoc?: T;
|
|
@@ -17,6 +18,6 @@ type Result<T> = Promise<{
|
|
|
17
18
|
data: T;
|
|
18
19
|
files: FileToSave[];
|
|
19
20
|
}>;
|
|
20
|
-
export declare const generateFileData: <T>({ collection: { config: collectionConfig }, data, isDuplicating, operation, originalDoc, overwriteExistingFiles, req, throwOnMissingFile, }: Args<T>) => Result<T>;
|
|
21
|
+
export declare const generateFileData: <T>({ collection: { config: collectionConfig }, data, draft, isDuplicating, operation, originalDoc, overwriteExistingFiles, req, throwOnMissingFile, }: Args<T>) => Result<T>;
|
|
21
22
|
export {};
|
|
22
23
|
//# sourceMappingURL=generateFileData.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generateFileData.d.ts","sourceRoot":"","sources":["../../src/uploads/generateFileData.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAA;AAChE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;AACzD,OAAO,KAAK,EAAY,cAAc,EAAE,MAAM,mBAAmB,CAAA;AACjE,OAAO,KAAK,EAAY,UAAU,EAAgC,MAAM,YAAY,CAAA;AAcpF,KAAK,IAAI,CAAC,CAAC,IAAI;IACb,UAAU,EAAE,UAAU,CAAA;IACtB,MAAM,EAAE,eAAe,CAAA;IACvB,IAAI,EAAE,CAAC,CAAA;IACP,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,SAAS,EAAE,QAAQ,GAAG,QAAQ,CAAA;IAC9B,WAAW,CAAC,EAAE,CAAC,CAAA;IACf,sBAAsB,CAAC,EAAE,OAAO,CAAA;IAChC,GAAG,EAAE,cAAc,CAAA;IACnB,kBAAkB,CAAC,EAAE,OAAO,CAAA;CAC7B,CAAA;AAED,KAAK,MAAM,CAAC,CAAC,IAAI,OAAO,CAAC;IACvB,IAAI,EAAE,CAAC,CAAA;IACP,KAAK,EAAE,UAAU,EAAE,CAAA;CACpB,CAAC,CAAA;AA6BF,eAAO,MAAM,gBAAgB,GAAU,CAAC
|
|
1
|
+
{"version":3,"file":"generateFileData.d.ts","sourceRoot":"","sources":["../../src/uploads/generateFileData.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAA;AAChE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;AACzD,OAAO,KAAK,EAAY,cAAc,EAAE,MAAM,mBAAmB,CAAA;AACjE,OAAO,KAAK,EAAY,UAAU,EAAgC,MAAM,YAAY,CAAA;AAcpF,KAAK,IAAI,CAAC,CAAC,IAAI;IACb,UAAU,EAAE,UAAU,CAAA;IACtB,MAAM,EAAE,eAAe,CAAA;IACvB,IAAI,EAAE,CAAC,CAAA;IACP,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,SAAS,EAAE,QAAQ,GAAG,QAAQ,CAAA;IAC9B,WAAW,CAAC,EAAE,CAAC,CAAA;IACf,sBAAsB,CAAC,EAAE,OAAO,CAAA;IAChC,GAAG,EAAE,cAAc,CAAA;IACnB,kBAAkB,CAAC,EAAE,OAAO,CAAA;CAC7B,CAAA;AAED,KAAK,MAAM,CAAC,CAAC,IAAI,OAAO,CAAC;IACvB,IAAI,EAAE,CAAC,CAAA;IACP,KAAK,EAAE,UAAU,EAAE,CAAA;CACpB,CAAC,CAAA;AA6BF,eAAO,MAAM,gBAAgB,GAAU,CAAC,sJAUrC,IAAI,CAAC,CAAC,CAAC,KAAG,MAAM,CAAC,CAAC,CAmWpB,CAAA"}
|
|
@@ -31,7 +31,7 @@ const shouldReupload = (uploadEdits, fileData)=>{
|
|
|
31
31
|
}
|
|
32
32
|
return false;
|
|
33
33
|
};
|
|
34
|
-
export const generateFileData = async ({ collection: { config: collectionConfig }, data, isDuplicating, operation, originalDoc, overwriteExistingFiles, req, throwOnMissingFile })=>{
|
|
34
|
+
export const generateFileData = async ({ collection: { config: collectionConfig }, data, draft, isDuplicating, operation, originalDoc, overwriteExistingFiles, req, throwOnMissingFile })=>{
|
|
35
35
|
if (!collectionConfig.upload) {
|
|
36
36
|
return {
|
|
37
37
|
data,
|
|
@@ -321,7 +321,10 @@ export const generateFileData = async ({ collection: { config: collectionConfig
|
|
|
321
321
|
}
|
|
322
322
|
newData = {
|
|
323
323
|
...newData,
|
|
324
|
-
...fileData
|
|
324
|
+
...fileData,
|
|
325
|
+
...draft ? {
|
|
326
|
+
_status: 'draft'
|
|
327
|
+
} : {}
|
|
325
328
|
};
|
|
326
329
|
return {
|
|
327
330
|
data: newData,
|