payload 3.79.0-canary.3 → 3.79.0-internal.2874f3f

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.
Files changed (30) hide show
  1. package/dist/collections/endpoints/duplicate.js +1 -1
  2. package/dist/collections/endpoints/duplicate.js.map +1 -1
  3. package/dist/collections/operations/restoreVersion.d.ts.map +1 -1
  4. package/dist/collections/operations/restoreVersion.js +16 -11
  5. package/dist/collections/operations/restoreVersion.js.map +1 -1
  6. package/dist/config/orderable/index.d.ts +2 -2
  7. package/dist/config/orderable/index.d.ts.map +1 -1
  8. package/dist/config/orderable/index.js +60 -34
  9. package/dist/config/orderable/index.js.map +1 -1
  10. package/dist/config/orderable/utils/buildJoinScopeWhere.d.ts +10 -0
  11. package/dist/config/orderable/utils/buildJoinScopeWhere.d.ts.map +1 -0
  12. package/dist/config/orderable/utils/buildJoinScopeWhere.js +43 -0
  13. package/dist/config/orderable/utils/buildJoinScopeWhere.js.map +1 -0
  14. package/dist/config/orderable/utils/getJoinScopeContext.d.ts +16 -0
  15. package/dist/config/orderable/utils/getJoinScopeContext.d.ts.map +1 -0
  16. package/dist/config/orderable/utils/getJoinScopeContext.js +41 -0
  17. package/dist/config/orderable/utils/getJoinScopeContext.js.map +1 -0
  18. package/dist/config/orderable/utils/getJoinScopeWhereFromDocData.d.ts +12 -0
  19. package/dist/config/orderable/utils/getJoinScopeWhereFromDocData.d.ts.map +1 -0
  20. package/dist/config/orderable/utils/getJoinScopeWhereFromDocData.js +18 -0
  21. package/dist/config/orderable/utils/getJoinScopeWhereFromDocData.js.map +1 -0
  22. package/dist/config/orderable/utils/getValueAtPath.d.ts +5 -0
  23. package/dist/config/orderable/utils/getValueAtPath.d.ts.map +1 -0
  24. package/dist/config/orderable/utils/getValueAtPath.js +18 -0
  25. package/dist/config/orderable/utils/getValueAtPath.js.map +1 -0
  26. package/dist/config/orderable/utils/resolvePendingTargetKey.d.ts +13 -0
  27. package/dist/config/orderable/utils/resolvePendingTargetKey.d.ts.map +1 -0
  28. package/dist/config/orderable/utils/resolvePendingTargetKey.js +23 -0
  29. package/dist/config/orderable/utils/resolvePendingTargetKey.js.map +1 -0
  30. package/package.json +2 -2
@@ -6,7 +6,7 @@ import { parseParams } from '../../utilities/parseParams/index.js';
6
6
  import { duplicateOperation } from '../operations/duplicate.js';
7
7
  export const duplicateHandler = async (req)=>{
8
8
  const { id, collection } = getRequestCollectionWithID(req);
9
- const { depth, draft, populate, select, selectedLocales } = parseParams(req.query);
9
+ const { depth, draft = true, populate, select, selectedLocales } = parseParams(req.query);
10
10
  const doc = await duplicateOperation({
11
11
  id,
12
12
  collection,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/collections/endpoints/duplicate.ts"],"sourcesContent":["import { getTranslation } from '@payloadcms/translations'\nimport { status as httpStatus } from 'http-status'\n\nimport type { PayloadHandler } from '../../config/types.js'\n\nimport { getRequestCollectionWithID } from '../../utilities/getRequestEntity.js'\nimport { headersWithCors } from '../../utilities/headersWithCors.js'\nimport { parseParams } from '../../utilities/parseParams/index.js'\nimport { duplicateOperation } from '../operations/duplicate.js'\n\nexport const duplicateHandler: PayloadHandler = async (req) => {\n const { id, collection } = getRequestCollectionWithID(req)\n\n const { depth, draft, populate, select, selectedLocales } = parseParams(req.query)\n\n const doc = await duplicateOperation({\n id,\n collection,\n data: req.data,\n depth,\n draft,\n populate,\n req,\n select,\n selectedLocales,\n })\n\n const message = req.t('general:successfullyDuplicated', {\n label: getTranslation(collection.config.labels.singular, req.i18n),\n })\n\n return Response.json(\n {\n doc,\n message,\n },\n {\n headers: headersWithCors({\n headers: new Headers(),\n req,\n }),\n status: httpStatus.OK,\n },\n )\n}\n"],"names":["getTranslation","status","httpStatus","getRequestCollectionWithID","headersWithCors","parseParams","duplicateOperation","duplicateHandler","req","id","collection","depth","draft","populate","select","selectedLocales","query","doc","data","message","t","label","config","labels","singular","i18n","Response","json","headers","Headers","OK"],"mappings":"AAAA,SAASA,cAAc,QAAQ,2BAA0B;AACzD,SAASC,UAAUC,UAAU,QAAQ,cAAa;AAIlD,SAASC,0BAA0B,QAAQ,sCAAqC;AAChF,SAASC,eAAe,QAAQ,qCAAoC;AACpE,SAASC,WAAW,QAAQ,uCAAsC;AAClE,SAASC,kBAAkB,QAAQ,6BAA4B;AAE/D,OAAO,MAAMC,mBAAmC,OAAOC;IACrD,MAAM,EAAEC,EAAE,EAAEC,UAAU,EAAE,GAAGP,2BAA2BK;IAEtD,MAAM,EAAEG,KAAK,EAAEC,KAAK,EAAEC,QAAQ,EAAEC,MAAM,EAAEC,eAAe,EAAE,GAAGV,YAAYG,IAAIQ,KAAK;IAEjF,MAAMC,MAAM,MAAMX,mBAAmB;QACnCG;QACAC;QACAQ,MAAMV,IAAIU,IAAI;QACdP;QACAC;QACAC;QACAL;QACAM;QACAC;IACF;IAEA,MAAMI,UAAUX,IAAIY,CAAC,CAAC,kCAAkC;QACtDC,OAAOrB,eAAeU,WAAWY,MAAM,CAACC,MAAM,CAACC,QAAQ,EAAEhB,IAAIiB,IAAI;IACnE;IAEA,OAAOC,SAASC,IAAI,CAClB;QACEV;QACAE;IACF,GACA;QACES,SAASxB,gBAAgB;YACvBwB,SAAS,IAAIC;YACbrB;QACF;QACAP,QAAQC,WAAW4B,EAAE;IACvB;AAEJ,EAAC"}
1
+ {"version":3,"sources":["../../../src/collections/endpoints/duplicate.ts"],"sourcesContent":["import { getTranslation } from '@payloadcms/translations'\nimport { status as httpStatus } from 'http-status'\n\nimport type { PayloadHandler } from '../../config/types.js'\n\nimport { getRequestCollectionWithID } from '../../utilities/getRequestEntity.js'\nimport { headersWithCors } from '../../utilities/headersWithCors.js'\nimport { parseParams } from '../../utilities/parseParams/index.js'\nimport { duplicateOperation } from '../operations/duplicate.js'\n\nexport const duplicateHandler: PayloadHandler = async (req) => {\n const { id, collection } = getRequestCollectionWithID(req)\n\n const { depth, draft = true, populate, select, selectedLocales } = parseParams(req.query)\n\n const doc = await duplicateOperation({\n id,\n collection,\n data: req.data,\n depth,\n draft,\n populate,\n req,\n select,\n selectedLocales,\n })\n\n const message = req.t('general:successfullyDuplicated', {\n label: getTranslation(collection.config.labels.singular, req.i18n),\n })\n\n return Response.json(\n {\n doc,\n message,\n },\n {\n headers: headersWithCors({\n headers: new Headers(),\n req,\n }),\n status: httpStatus.OK,\n },\n )\n}\n"],"names":["getTranslation","status","httpStatus","getRequestCollectionWithID","headersWithCors","parseParams","duplicateOperation","duplicateHandler","req","id","collection","depth","draft","populate","select","selectedLocales","query","doc","data","message","t","label","config","labels","singular","i18n","Response","json","headers","Headers","OK"],"mappings":"AAAA,SAASA,cAAc,QAAQ,2BAA0B;AACzD,SAASC,UAAUC,UAAU,QAAQ,cAAa;AAIlD,SAASC,0BAA0B,QAAQ,sCAAqC;AAChF,SAASC,eAAe,QAAQ,qCAAoC;AACpE,SAASC,WAAW,QAAQ,uCAAsC;AAClE,SAASC,kBAAkB,QAAQ,6BAA4B;AAE/D,OAAO,MAAMC,mBAAmC,OAAOC;IACrD,MAAM,EAAEC,EAAE,EAAEC,UAAU,EAAE,GAAGP,2BAA2BK;IAEtD,MAAM,EAAEG,KAAK,EAAEC,QAAQ,IAAI,EAAEC,QAAQ,EAAEC,MAAM,EAAEC,eAAe,EAAE,GAAGV,YAAYG,IAAIQ,KAAK;IAExF,MAAMC,MAAM,MAAMX,mBAAmB;QACnCG;QACAC;QACAQ,MAAMV,IAAIU,IAAI;QACdP;QACAC;QACAC;QACAL;QACAM;QACAC;IACF;IAEA,MAAMI,UAAUX,IAAIY,CAAC,CAAC,kCAAkC;QACtDC,OAAOrB,eAAeU,WAAWY,MAAM,CAACC,MAAM,CAACC,QAAQ,EAAEhB,IAAIiB,IAAI;IACnE;IAEA,OAAOC,SAASC,IAAI,CAClB;QACEV;QACAE;IACF,GACA;QACES,SAASxB,gBAAgB;YACvBwB,SAAS,IAAIC;YACbrB;QACF;QACAP,QAAQC,WAAW4B,EAAE;IACvB;AAEJ,EAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"restoreVersion.d.ts","sourceRoot":"","sources":["../../../src/collections/operations/restoreVersion.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,cAAc,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAA;AAChG,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAA;AAChE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAoBlD,MAAM,MAAM,SAAS,GAAG;IACtB,UAAU,EAAE,UAAU,CAAA;IACtB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,kBAAkB,CAAC,EAAE,OAAO,CAAA;IAC5B,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,EAAE,EAAE,MAAM,GAAG,MAAM,CAAA;IACnB,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB,QAAQ,CAAC,EAAE,YAAY,CAAA;IACvB,GAAG,EAAE,cAAc,CAAA;IACnB,gBAAgB,CAAC,EAAE,OAAO,CAAA;CAC3B,GAAG,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,UAAU,CAAC,EAAE,QAAQ,CAAC,CAAA;AAEnD,eAAO,MAAM,uBAAuB,GAClC,KAAK,SAAS,UAAU,GAAG,UAAU,kCAE/B,SAAS,KACd,OAAO,CAAC,KAAK,CA+Uf,CAAA"}
1
+ {"version":3,"file":"restoreVersion.d.ts","sourceRoot":"","sources":["../../../src/collections/operations/restoreVersion.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,cAAc,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAA;AAChG,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAA;AAChE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAoBlD,MAAM,MAAM,SAAS,GAAG;IACtB,UAAU,EAAE,UAAU,CAAA;IACtB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,kBAAkB,CAAC,EAAE,OAAO,CAAA;IAC5B,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,EAAE,EAAE,MAAM,GAAG,MAAM,CAAA;IACnB,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB,QAAQ,CAAC,EAAE,YAAY,CAAA;IACvB,GAAG,EAAE,cAAc,CAAA;IACnB,gBAAgB,CAAC,EAAE,OAAO,CAAA;CAC3B,GAAG,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,UAAU,CAAC,EAAE,QAAQ,CAAC,CAAA;AAEnD,eAAO,MAAM,uBAAuB,GAClC,KAAK,SAAS,UAAU,GAAG,UAAU,kCAE/B,SAAS,KACd,OAAO,CAAC,KAAK,CAwVf,CAAA"}
@@ -39,7 +39,7 @@ export const restoreVersionOperation = async (args)=>{
39
39
  const { docs: versionDocs } = await req.payload.db.findVersions({
40
40
  collection: collectionConfig.slug,
41
41
  limit: 1,
42
- locale: locale,
42
+ locale: 'all',
43
43
  pagination: false,
44
44
  req,
45
45
  where: {
@@ -66,7 +66,7 @@ export const restoreVersionOperation = async (args)=>{
66
66
  // /////////////////////////////////////
67
67
  const findOneArgs = {
68
68
  collection: collectionConfig.slug,
69
- locale: locale,
69
+ locale: 'all',
70
70
  req,
71
71
  where: combineQueries({
72
72
  id: {
@@ -96,6 +96,7 @@ export const restoreVersionOperation = async (args)=>{
96
96
  req
97
97
  });
98
98
  // originalDoc with hoisted localized data
99
+ const validationLocale = payload.config.localization ? payload.config.localization.defaultLocale : locale;
99
100
  const originalDoc = await afterRead({
100
101
  collection: collectionConfig,
101
102
  context: req.context,
@@ -104,12 +105,12 @@ export const restoreVersionOperation = async (args)=>{
104
105
  draft: draftArg,
105
106
  fallbackLocale: null,
106
107
  global: null,
107
- locale: locale,
108
+ locale: validationLocale,
108
109
  overrideAccess: true,
109
110
  req,
110
111
  showHiddenFields: true
111
112
  });
112
- // version data with hoisted localized data
113
+ // Use locale-hoisted version data for validation while preserving all locales in docWithLocales.
113
114
  const prevVersionDoc = await afterRead({
114
115
  collection: collectionConfig,
115
116
  context: req.context,
@@ -118,7 +119,7 @@ export const restoreVersionOperation = async (args)=>{
118
119
  draft: draftArg,
119
120
  fallbackLocale: null,
120
121
  global: null,
121
- locale: locale,
122
+ locale: validationLocale,
122
123
  overrideAccess: true,
123
124
  req,
124
125
  showHiddenFields: true
@@ -126,6 +127,10 @@ export const restoreVersionOperation = async (args)=>{
126
127
  // /////////////////////////////////////
127
128
  // beforeValidate - Fields
128
129
  // /////////////////////////////////////
130
+ const reqWithValidationLocale = Object.assign(Object.create(req), req, {
131
+ fallbackLocale: null,
132
+ locale: validationLocale
133
+ });
129
134
  let data = await beforeValidate({
130
135
  id: parentDocID,
131
136
  collection: collectionConfig,
@@ -135,7 +140,7 @@ export const restoreVersionOperation = async (args)=>{
135
140
  global: null,
136
141
  operation: 'update',
137
142
  overrideAccess,
138
- req
143
+ req: reqWithValidationLocale
139
144
  });
140
145
  // /////////////////////////////////////
141
146
  // beforeValidate - Collection
@@ -148,7 +153,7 @@ export const restoreVersionOperation = async (args)=>{
148
153
  data,
149
154
  operation: 'update',
150
155
  originalDoc,
151
- req
156
+ req: reqWithValidationLocale
152
157
  }) || data;
153
158
  }
154
159
  }
@@ -163,7 +168,7 @@ export const restoreVersionOperation = async (args)=>{
163
168
  data,
164
169
  operation: 'update',
165
170
  originalDoc,
166
- req
171
+ req: reqWithValidationLocale
167
172
  }) || data;
168
173
  }
169
174
  }
@@ -183,7 +188,7 @@ export const restoreVersionOperation = async (args)=>{
183
188
  global: null,
184
189
  operation: 'update',
185
190
  overrideAccess,
186
- req,
191
+ req: reqWithValidationLocale,
187
192
  skipValidation: draftArg && !hasDraftValidationEnabled(collectionConfig)
188
193
  });
189
194
  // /////////////////////////////////////
@@ -203,7 +208,7 @@ export const restoreVersionOperation = async (args)=>{
203
208
  id: parentDocID,
204
209
  collection: collectionConfig.slug,
205
210
  data: result,
206
- req,
211
+ req: reqWithValidationLocale,
207
212
  select
208
213
  });
209
214
  }
@@ -218,7 +223,7 @@ export const restoreVersionOperation = async (args)=>{
218
223
  draft: draftArg,
219
224
  operation: 'restoreVersion',
220
225
  payload,
221
- req,
226
+ req: reqWithValidationLocale,
222
227
  select
223
228
  });
224
229
  // /////////////////////////////////////
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/collections/operations/restoreVersion.ts"],"sourcesContent":["import { status as httpStatus } from 'http-status'\n\nimport type { FindOneArgs } from '../../database/types.js'\nimport type { JsonObject, PayloadRequest, PopulateType, SelectType } from '../../types/index.js'\nimport type { Collection, TypeWithID } from '../config/types.js'\nimport type { FindOptions } from './local/find.js'\n\nimport { executeAccess } from '../../auth/executeAccess.js'\nimport { hasWhereAccessResult } from '../../auth/types.js'\nimport { combineQueries } from '../../database/combineQueries.js'\nimport { APIError, Forbidden, NotFound } from '../../errors/index.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 { commitTransaction } from '../../utilities/commitTransaction.js'\nimport { deepCopyObjectSimple } from '../../utilities/deepCopyObject.js'\nimport { hasDraftValidationEnabled } from '../../utilities/getVersionsConfig.js'\nimport { initTransaction } from '../../utilities/initTransaction.js'\nimport { killTransaction } from '../../utilities/killTransaction.js'\nimport { sanitizeSelect } from '../../utilities/sanitizeSelect.js'\nimport { getLatestCollectionVersion } from '../../versions/getLatestCollectionVersion.js'\nimport { saveVersion } from '../../versions/saveVersion.js'\nimport { buildAfterOperation } from './utilities/buildAfterOperation.js'\nimport { buildBeforeOperation } from './utilities/buildBeforeOperation.js'\nexport type Arguments = {\n collection: Collection\n currentDepth?: number\n depth?: number\n disableErrors?: boolean\n disableTransaction?: boolean\n draft?: boolean\n id: number | string\n overrideAccess?: boolean\n populate?: PopulateType\n req: PayloadRequest\n showHiddenFields?: boolean\n} & Pick<FindOptions<string, SelectType>, 'select'>\n\nexport const restoreVersionOperation = async <\n TData extends JsonObject & TypeWithID = JsonObject & TypeWithID,\n>(\n args: Arguments,\n): Promise<TData> => {\n const {\n id,\n collection: { config: collectionConfig },\n depth,\n draft: draftArg = false,\n overrideAccess = false,\n populate,\n req,\n req: { fallbackLocale, locale, payload },\n select: incomingSelect,\n showHiddenFields,\n } = args\n\n try {\n const shouldCommit = !args.disableTransaction && (await initTransaction(args.req))\n\n // /////////////////////////////////////\n // beforeOperation - Collection\n // /////////////////////////////////////\n\n args = await buildBeforeOperation({\n args,\n collection: args.collection.config,\n operation: 'restoreVersion',\n overrideAccess,\n })\n\n if (!id) {\n throw new APIError('Missing ID of version to restore.', httpStatus.BAD_REQUEST)\n }\n\n // /////////////////////////////////////\n // Retrieve original raw version\n // /////////////////////////////////////\n\n const { docs: versionDocs } = await req.payload.db.findVersions({\n collection: collectionConfig.slug,\n limit: 1,\n locale: locale!,\n pagination: false,\n req,\n where: { id: { equals: id } },\n })\n\n const [rawVersionToRestore] = versionDocs\n\n if (!rawVersionToRestore) {\n throw new NotFound(req.t)\n }\n\n const { parent: parentDocID, version: versionToRestoreWithLocales } = rawVersionToRestore\n\n // /////////////////////////////////////\n // Access\n // /////////////////////////////////////\n\n const accessResults = !overrideAccess\n ? await executeAccess({ id: parentDocID, req }, collectionConfig.access.update)\n : true\n const hasWherePolicy = hasWhereAccessResult(accessResults)\n\n // /////////////////////////////////////\n // Retrieve document\n // /////////////////////////////////////\n\n const findOneArgs: FindOneArgs = {\n collection: collectionConfig.slug,\n locale: locale!,\n req,\n where: combineQueries({ id: { equals: parentDocID } }, accessResults),\n }\n\n // Get the document from the non versioned collection\n const doc = await req.payload.db.findOne<TData>(findOneArgs)\n\n if (!doc && !hasWherePolicy) {\n throw new NotFound(req.t)\n }\n if (!doc && hasWherePolicy) {\n throw new Forbidden(req.t)\n }\n\n if (collectionConfig.trash && doc?.deletedAt) {\n throw new APIError(\n `Cannot restore a version of a trashed document (ID: ${parentDocID}). Restore the document first.`,\n httpStatus.FORBIDDEN,\n )\n }\n\n // /////////////////////////////////////\n // fetch previousDoc\n // /////////////////////////////////////\n const prevDocWithLocales = await getLatestCollectionVersion({\n id: parentDocID,\n config: collectionConfig,\n payload,\n query: findOneArgs,\n req,\n })\n\n // originalDoc with hoisted localized data\n const originalDoc = await afterRead({\n collection: collectionConfig,\n context: req.context,\n depth: 0,\n doc: deepCopyObjectSimple(prevDocWithLocales),\n draft: draftArg,\n fallbackLocale: null,\n global: null,\n locale: locale!,\n overrideAccess: true,\n req,\n showHiddenFields: true,\n })\n\n // version data with hoisted localized data\n const prevVersionDoc = await afterRead({\n collection: collectionConfig,\n context: req.context,\n depth: 0,\n doc: deepCopyObjectSimple(rawVersionToRestore.version),\n draft: draftArg,\n fallbackLocale: null,\n global: null,\n locale: locale!,\n overrideAccess: true,\n req,\n showHiddenFields: true,\n })\n\n // /////////////////////////////////////\n // beforeValidate - Fields\n // /////////////////////////////////////\n\n let data = await beforeValidate({\n id: parentDocID,\n collection: collectionConfig,\n context: req.context,\n data: deepCopyObjectSimple(prevVersionDoc),\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 // 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 let result = await beforeChange({\n id: parentDocID,\n collection: collectionConfig,\n context: req.context,\n data: { ...data, id: parentDocID },\n doc: originalDoc,\n docWithLocales: versionToRestoreWithLocales,\n global: null,\n operation: 'update',\n overrideAccess,\n req,\n skipValidation: draftArg && !hasDraftValidationEnabled(collectionConfig),\n })\n\n // /////////////////////////////////////\n // Update\n // /////////////////////////////////////\n\n const select = sanitizeSelect({\n fields: collectionConfig.flattenedFields,\n forceSelect: collectionConfig.forceSelect,\n select: incomingSelect,\n })\n\n // Ensure updatedAt date is always updated\n result.updatedAt = new Date().toISOString()\n // Ensure status respects restoreAsDraft arg\n result._status = draftArg ? 'draft' : result._status\n if (!draftArg) {\n result = await req.payload.db.updateOne({\n id: parentDocID,\n collection: collectionConfig.slug,\n data: result,\n req,\n select,\n })\n }\n\n // /////////////////////////////////////\n // Save restored doc as a new version\n // /////////////////////////////////////\n\n result = await saveVersion({\n id: parentDocID,\n autosave: false,\n collection: collectionConfig,\n docWithLocales: result,\n draft: draftArg,\n operation: 'restoreVersion',\n payload,\n req,\n select,\n })\n\n // /////////////////////////////////////\n // afterRead - Fields\n // /////////////////////////////////////\n\n result = await afterRead({\n collection: collectionConfig,\n context: req.context,\n depth: depth!,\n doc: result,\n // @ts-expect-error - vestiges of when tsconfig was not strict. Feel free to improve\n draft: undefined,\n fallbackLocale: fallbackLocale!,\n global: null,\n locale: locale!,\n overrideAccess,\n populate,\n req,\n select,\n showHiddenFields: 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: result,\n doc: result,\n global: null,\n operation: 'update',\n previousDoc: prevDocWithLocales,\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: result,\n doc: result,\n operation: 'update',\n overrideAccess,\n previousDoc: prevDocWithLocales,\n req,\n })) || result\n }\n }\n\n // /////////////////////////////////////\n // afterOperation - Collection\n // /////////////////////////////////////\n\n result = await buildAfterOperation({\n args,\n collection: collectionConfig,\n operation: 'restoreVersion',\n overrideAccess,\n result,\n })\n\n if (shouldCommit) {\n await commitTransaction(req)\n }\n\n return result\n } catch (error: unknown) {\n await killTransaction(req)\n throw error\n }\n}\n"],"names":["status","httpStatus","executeAccess","hasWhereAccessResult","combineQueries","APIError","Forbidden","NotFound","afterChange","afterRead","beforeChange","beforeValidate","commitTransaction","deepCopyObjectSimple","hasDraftValidationEnabled","initTransaction","killTransaction","sanitizeSelect","getLatestCollectionVersion","saveVersion","buildAfterOperation","buildBeforeOperation","restoreVersionOperation","args","id","collection","config","collectionConfig","depth","draft","draftArg","overrideAccess","populate","req","fallbackLocale","locale","payload","select","incomingSelect","showHiddenFields","shouldCommit","disableTransaction","operation","BAD_REQUEST","docs","versionDocs","db","findVersions","slug","limit","pagination","where","equals","rawVersionToRestore","t","parent","parentDocID","version","versionToRestoreWithLocales","accessResults","access","update","hasWherePolicy","findOneArgs","doc","findOne","trash","deletedAt","FORBIDDEN","prevDocWithLocales","query","originalDoc","context","global","prevVersionDoc","data","hooks","length","hook","result","docWithLocales","skipValidation","fields","flattenedFields","forceSelect","updatedAt","Date","toISOString","_status","updateOne","autosave","undefined","previousDoc","error"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/collections/operations/restoreVersion.ts"],"sourcesContent":["import { status as httpStatus } from 'http-status'\n\nimport type { FindOneArgs } from '../../database/types.js'\nimport type { JsonObject, PayloadRequest, PopulateType, SelectType } from '../../types/index.js'\nimport type { Collection, TypeWithID } from '../config/types.js'\nimport type { FindOptions } from './local/find.js'\n\nimport { executeAccess } from '../../auth/executeAccess.js'\nimport { hasWhereAccessResult } from '../../auth/types.js'\nimport { combineQueries } from '../../database/combineQueries.js'\nimport { APIError, Forbidden, NotFound } from '../../errors/index.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 { commitTransaction } from '../../utilities/commitTransaction.js'\nimport { deepCopyObjectSimple } from '../../utilities/deepCopyObject.js'\nimport { hasDraftValidationEnabled } from '../../utilities/getVersionsConfig.js'\nimport { initTransaction } from '../../utilities/initTransaction.js'\nimport { killTransaction } from '../../utilities/killTransaction.js'\nimport { sanitizeSelect } from '../../utilities/sanitizeSelect.js'\nimport { getLatestCollectionVersion } from '../../versions/getLatestCollectionVersion.js'\nimport { saveVersion } from '../../versions/saveVersion.js'\nimport { buildAfterOperation } from './utilities/buildAfterOperation.js'\nimport { buildBeforeOperation } from './utilities/buildBeforeOperation.js'\nexport type Arguments = {\n collection: Collection\n currentDepth?: number\n depth?: number\n disableErrors?: boolean\n disableTransaction?: boolean\n draft?: boolean\n id: number | string\n overrideAccess?: boolean\n populate?: PopulateType\n req: PayloadRequest\n showHiddenFields?: boolean\n} & Pick<FindOptions<string, SelectType>, 'select'>\n\nexport const restoreVersionOperation = async <\n TData extends JsonObject & TypeWithID = JsonObject & TypeWithID,\n>(\n args: Arguments,\n): Promise<TData> => {\n const {\n id,\n collection: { config: collectionConfig },\n depth,\n draft: draftArg = false,\n overrideAccess = false,\n populate,\n req,\n req: { fallbackLocale, locale, payload },\n select: incomingSelect,\n showHiddenFields,\n } = args\n\n try {\n const shouldCommit = !args.disableTransaction && (await initTransaction(args.req))\n\n // /////////////////////////////////////\n // beforeOperation - Collection\n // /////////////////////////////////////\n\n args = await buildBeforeOperation({\n args,\n collection: args.collection.config,\n operation: 'restoreVersion',\n overrideAccess,\n })\n\n if (!id) {\n throw new APIError('Missing ID of version to restore.', httpStatus.BAD_REQUEST)\n }\n\n // /////////////////////////////////////\n // Retrieve original raw version\n // /////////////////////////////////////\n\n const { docs: versionDocs } = await req.payload.db.findVersions({\n collection: collectionConfig.slug,\n limit: 1,\n locale: 'all',\n pagination: false,\n req,\n where: { id: { equals: id } },\n })\n\n const [rawVersionToRestore] = versionDocs\n\n if (!rawVersionToRestore) {\n throw new NotFound(req.t)\n }\n\n const { parent: parentDocID, version: versionToRestoreWithLocales } = rawVersionToRestore\n\n // /////////////////////////////////////\n // Access\n // /////////////////////////////////////\n\n const accessResults = !overrideAccess\n ? await executeAccess({ id: parentDocID, req }, collectionConfig.access.update)\n : true\n const hasWherePolicy = hasWhereAccessResult(accessResults)\n\n // /////////////////////////////////////\n // Retrieve document\n // /////////////////////////////////////\n\n const findOneArgs: FindOneArgs = {\n collection: collectionConfig.slug,\n locale: 'all',\n req,\n where: combineQueries({ id: { equals: parentDocID } }, accessResults),\n }\n\n // Get the document from the non versioned collection\n const doc = await req.payload.db.findOne<TData>(findOneArgs)\n\n if (!doc && !hasWherePolicy) {\n throw new NotFound(req.t)\n }\n if (!doc && hasWherePolicy) {\n throw new Forbidden(req.t)\n }\n\n if (collectionConfig.trash && doc?.deletedAt) {\n throw new APIError(\n `Cannot restore a version of a trashed document (ID: ${parentDocID}). Restore the document first.`,\n httpStatus.FORBIDDEN,\n )\n }\n\n // /////////////////////////////////////\n // fetch previousDoc\n // /////////////////////////////////////\n const prevDocWithLocales = await getLatestCollectionVersion({\n id: parentDocID,\n config: collectionConfig,\n payload,\n query: findOneArgs,\n req,\n })\n\n // originalDoc with hoisted localized data\n const validationLocale = payload.config.localization\n ? payload.config.localization.defaultLocale\n : locale!\n\n const originalDoc = await afterRead({\n collection: collectionConfig,\n context: req.context,\n depth: 0,\n doc: deepCopyObjectSimple(prevDocWithLocales),\n draft: draftArg,\n fallbackLocale: null,\n global: null,\n locale: validationLocale,\n overrideAccess: true,\n req,\n showHiddenFields: true,\n })\n\n // Use locale-hoisted version data for validation while preserving all locales in docWithLocales.\n const prevVersionDoc = await afterRead({\n collection: collectionConfig,\n context: req.context,\n depth: 0,\n doc: deepCopyObjectSimple(rawVersionToRestore.version),\n draft: draftArg,\n fallbackLocale: null,\n global: null,\n locale: validationLocale,\n overrideAccess: true,\n req,\n showHiddenFields: true,\n })\n\n // /////////////////////////////////////\n // beforeValidate - Fields\n // /////////////////////////////////////\n\n const reqWithValidationLocale = Object.assign(Object.create(req), req, {\n fallbackLocale: null,\n locale: validationLocale,\n })\n\n let data = await beforeValidate({\n id: parentDocID,\n collection: collectionConfig,\n context: req.context,\n data: deepCopyObjectSimple(prevVersionDoc),\n doc: originalDoc,\n global: null,\n operation: 'update',\n overrideAccess,\n req: reqWithValidationLocale,\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: reqWithValidationLocale,\n })) || data\n }\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: reqWithValidationLocale,\n })) || data\n }\n }\n\n // /////////////////////////////////////\n // beforeChange - Fields\n // /////////////////////////////////////\n\n let result = await beforeChange({\n id: parentDocID,\n collection: collectionConfig,\n context: req.context,\n data: { ...data, id: parentDocID },\n doc: originalDoc,\n docWithLocales: versionToRestoreWithLocales,\n global: null,\n operation: 'update',\n overrideAccess,\n req: reqWithValidationLocale,\n skipValidation: draftArg && !hasDraftValidationEnabled(collectionConfig),\n })\n\n // /////////////////////////////////////\n // Update\n // /////////////////////////////////////\n\n const select = sanitizeSelect({\n fields: collectionConfig.flattenedFields,\n forceSelect: collectionConfig.forceSelect,\n select: incomingSelect,\n })\n\n // Ensure updatedAt date is always updated\n result.updatedAt = new Date().toISOString()\n // Ensure status respects restoreAsDraft arg\n result._status = draftArg ? 'draft' : result._status\n if (!draftArg) {\n result = await req.payload.db.updateOne({\n id: parentDocID,\n collection: collectionConfig.slug,\n data: result,\n req: reqWithValidationLocale,\n select,\n })\n }\n\n // /////////////////////////////////////\n // Save restored doc as a new version\n // /////////////////////////////////////\n\n result = await saveVersion({\n id: parentDocID,\n autosave: false,\n collection: collectionConfig,\n docWithLocales: result,\n draft: draftArg,\n operation: 'restoreVersion',\n payload,\n req: reqWithValidationLocale,\n select,\n })\n\n // /////////////////////////////////////\n // afterRead - Fields\n // /////////////////////////////////////\n\n result = await afterRead({\n collection: collectionConfig,\n context: req.context,\n depth: depth!,\n doc: result,\n // @ts-expect-error - vestiges of when tsconfig was not strict. Feel free to improve\n draft: undefined,\n fallbackLocale: fallbackLocale!,\n global: null,\n locale: locale!,\n overrideAccess,\n populate,\n req,\n select,\n showHiddenFields: 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: result,\n doc: result,\n global: null,\n operation: 'update',\n previousDoc: prevDocWithLocales,\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: result,\n doc: result,\n operation: 'update',\n overrideAccess,\n previousDoc: prevDocWithLocales,\n req,\n })) || result\n }\n }\n\n // /////////////////////////////////////\n // afterOperation - Collection\n // /////////////////////////////////////\n\n result = await buildAfterOperation({\n args,\n collection: collectionConfig,\n operation: 'restoreVersion',\n overrideAccess,\n result,\n })\n\n if (shouldCommit) {\n await commitTransaction(req)\n }\n\n return result\n } catch (error: unknown) {\n await killTransaction(req)\n throw error\n }\n}\n"],"names":["status","httpStatus","executeAccess","hasWhereAccessResult","combineQueries","APIError","Forbidden","NotFound","afterChange","afterRead","beforeChange","beforeValidate","commitTransaction","deepCopyObjectSimple","hasDraftValidationEnabled","initTransaction","killTransaction","sanitizeSelect","getLatestCollectionVersion","saveVersion","buildAfterOperation","buildBeforeOperation","restoreVersionOperation","args","id","collection","config","collectionConfig","depth","draft","draftArg","overrideAccess","populate","req","fallbackLocale","locale","payload","select","incomingSelect","showHiddenFields","shouldCommit","disableTransaction","operation","BAD_REQUEST","docs","versionDocs","db","findVersions","slug","limit","pagination","where","equals","rawVersionToRestore","t","parent","parentDocID","version","versionToRestoreWithLocales","accessResults","access","update","hasWherePolicy","findOneArgs","doc","findOne","trash","deletedAt","FORBIDDEN","prevDocWithLocales","query","validationLocale","localization","defaultLocale","originalDoc","context","global","prevVersionDoc","reqWithValidationLocale","Object","assign","create","data","hooks","length","hook","result","docWithLocales","skipValidation","fields","flattenedFields","forceSelect","updatedAt","Date","toISOString","_status","updateOne","autosave","undefined","previousDoc","error"],"mappings":"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"}
@@ -9,7 +9,7 @@ import type { SanitizedConfig } from '../types.js';
9
9
  * Also, if collection.defaultSort or joinField.defaultSort is not set, it will be set to the orderable field.
10
10
  */
11
11
  export declare const setupOrderable: (config: SanitizedConfig) => void;
12
- export declare const addOrderableFieldsAndHook: (collection: CollectionConfig, orderableFieldNames: string[]) => void;
12
+ export declare const addOrderableFieldsAndHook: (collection: CollectionConfig, orderableFieldNames: string[], joinFieldPathsByCollection?: Map<string, Map<string, string>>) => void;
13
13
  /**
14
14
  * The body of the reorder endpoint.
15
15
  * @internal
@@ -24,5 +24,5 @@ export type OrderableEndpointBody = {
24
24
  key: string;
25
25
  };
26
26
  };
27
- export declare const addOrderableEndpoint: (config: SanitizedConfig) => void;
27
+ export declare const addOrderableEndpoint: (config: SanitizedConfig, joinFieldPathsByCollection: Map<string, Map<string, string>>) => void;
28
28
  //# sourceMappingURL=index.d.ts.map
@@ -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;AAE3F,OAAO,KAAK,EAA4B,eAAe,EAAE,MAAM,aAAa,CAAA;AAU5E;;;;;;;GAOG;AACH,eAAO,MAAM,cAAc,WAAY,eAAe,SAuDrD,CAAA;AAED,eAAO,MAAM,yBAAyB,eACxB,gBAAgB,uBACP,MAAM,EAAE,SAgE9B,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,WAAY,eAAe,SAkL3D,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;AAE3F,OAAO,KAAK,EAA4B,eAAe,EAAE,MAAM,aAAa,CAAA;AAc5E;;;;;;;GAOG;AACH,eAAO,MAAM,cAAc,WAAY,eAAe,SA2DrD,CAAA;AAED,eAAO,MAAM,yBAAyB,eACxB,gBAAgB,uBACP,MAAM,EAAE,+BACA,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,SA2E9D,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,SA4L7D,CAAA"}
@@ -1,11 +1,15 @@
1
1
  import { status as httpStatus } from 'http-status';
2
2
  import { executeAccess } from '../../auth/executeAccess.js';
3
3
  import { APIError } from '../../errors/index.js';
4
+ import { combineWhereConstraints } from '../../utilities/combineWhereConstraints.js';
4
5
  import { commitTransaction } from '../../utilities/commitTransaction.js';
5
6
  import { initTransaction } from '../../utilities/initTransaction.js';
6
7
  import { killTransaction } from '../../utilities/killTransaction.js';
7
8
  import { traverseFields } from '../../utilities/traverseFields.js';
8
9
  import { generateKeyBetween, generateNKeysBetween } from './fractional-indexing.js';
10
+ import { getJoinScopeContext } from './utils/getJoinScopeContext.js';
11
+ import { getJoinScopeWhereFromDocData } from './utils/getJoinScopeWhereFromDocData.js';
12
+ import { resolvePendingTargetKey } from './utils/resolvePendingTargetKey.js';
9
13
  /**
10
14
  * This function creates:
11
15
  * - N fields per collection, named `_order` or `_<collection>_<joinField>_order`
@@ -15,6 +19,7 @@ import { generateKeyBetween, generateNKeysBetween } from './fractional-indexing.
15
19
  * Also, if collection.defaultSort or joinField.defaultSort is not set, it will be set to the orderable field.
16
20
  */ export const setupOrderable = (config)=>{
17
21
  const fieldsToAdd = new Map();
22
+ const joinFieldPathsByCollection = new Map();
18
23
  config.collections.forEach((collection)=>{
19
24
  if (collection.orderable) {
20
25
  const currentFields = fieldsToAdd.get(collection) || [];
@@ -47,23 +52,27 @@ import { generateKeyBetween, generateNKeysBetween } from './fractional-indexing.
47
52
  const currentFields = fieldsToAdd.get(relationshipCollection) || [];
48
53
  // @ts-expect-error ref is untyped
49
54
  const prefix = parentRef?.prefix ? `${parentRef.prefix}_` : '';
55
+ const joinOrderableFieldName = `_${field.collection}_${prefix}${field.name}_order`;
50
56
  fieldsToAdd.set(relationshipCollection, [
51
57
  ...currentFields,
52
- `_${field.collection}_${prefix}${field.name}_order`
58
+ joinOrderableFieldName
53
59
  ]);
60
+ const currentJoinFieldPaths = joinFieldPathsByCollection.get(relationshipCollection.slug) || new Map();
61
+ currentJoinFieldPaths.set(joinOrderableFieldName, field.on);
62
+ joinFieldPathsByCollection.set(relationshipCollection.slug, currentJoinFieldPaths);
54
63
  }
55
64
  },
56
65
  fields: collection.fields
57
66
  });
58
67
  });
59
68
  Array.from(fieldsToAdd.entries()).forEach(([collection, orderableFields])=>{
60
- addOrderableFieldsAndHook(collection, orderableFields);
69
+ addOrderableFieldsAndHook(collection, orderableFields, joinFieldPathsByCollection);
61
70
  });
62
71
  if (fieldsToAdd.size > 0) {
63
- addOrderableEndpoint(config);
72
+ addOrderableEndpoint(config, joinFieldPathsByCollection);
64
73
  }
65
74
  };
66
- export const addOrderableFieldsAndHook = (collection, orderableFieldNames)=>{
75
+ export const addOrderableFieldsAndHook = (collection, orderableFieldNames, joinFieldPathsByCollection)=>{
67
76
  // 1. Add field
68
77
  orderableFieldNames.forEach((orderableFieldName)=>{
69
78
  const orderField = {
@@ -99,6 +108,13 @@ export const addOrderableFieldsAndHook = (collection, orderableFieldNames)=>{
99
108
  const orderBeforeChangeHook = async ({ data, originalDoc, req })=>{
100
109
  for (const orderableFieldName of orderableFieldNames){
101
110
  if (!data[orderableFieldName] && !originalDoc?.[orderableFieldName]) {
111
+ const joinScopeWhere = getJoinScopeWhereFromDocData({
112
+ collectionSlug: collection.slug,
113
+ data,
114
+ joinFieldPathsByCollection,
115
+ orderableFieldName,
116
+ originalDoc
117
+ });
102
118
  const lastDoc = await req.payload.find({
103
119
  collection: collection.slug,
104
120
  depth: 0,
@@ -109,11 +125,14 @@ export const addOrderableFieldsAndHook = (collection, orderableFieldNames)=>{
109
125
  [orderableFieldName]: true
110
126
  },
111
127
  sort: `-${orderableFieldName}`,
112
- where: {
113
- [orderableFieldName]: {
114
- exists: true
115
- }
116
- }
128
+ where: combineWhereConstraints([
129
+ {
130
+ [orderableFieldName]: {
131
+ exists: true
132
+ }
133
+ },
134
+ joinScopeWhere ?? undefined
135
+ ])
117
136
  });
118
137
  const lastOrderValue = lastDoc.docs[0]?.[orderableFieldName] || null;
119
138
  data[orderableFieldName] = generateKeyBetween(lastOrderValue, null);
@@ -123,7 +142,7 @@ export const addOrderableFieldsAndHook = (collection, orderableFieldNames)=>{
123
142
  };
124
143
  collection.hooks.beforeChange.push(orderBeforeChangeHook);
125
144
  };
126
- export const addOrderableEndpoint = (config)=>{
145
+ export const addOrderableEndpoint = (config, joinFieldPathsByCollection)=>{
127
146
  // 3. Add endpoint
128
147
  const reorderHandler = async (req)=>{
129
148
  const body = await req.json?.();
@@ -169,6 +188,13 @@ export const addOrderableEndpoint = (config)=>{
169
188
  status: 400
170
189
  });
171
190
  }
191
+ const { joinScopeWhere, targetDoc } = await getJoinScopeContext({
192
+ collectionSlug: collection.slug,
193
+ joinFieldPathsByCollection,
194
+ orderableFieldName,
195
+ req,
196
+ target
197
+ });
172
198
  // Prevent reordering if user doesn't have editing permissions
173
199
  if (collection.access?.update) {
174
200
  await executeAccess({
@@ -196,11 +222,14 @@ export const addOrderableEndpoint = (config)=>{
196
222
  select: {
197
223
  [orderableFieldName]: true
198
224
  },
199
- where: {
200
- [orderableFieldName]: {
201
- exists: false
202
- }
203
- }
225
+ where: combineWhereConstraints([
226
+ {
227
+ [orderableFieldName]: {
228
+ exists: false
229
+ }
230
+ },
231
+ joinScopeWhere ?? undefined
232
+ ])
204
233
  });
205
234
  await initTransaction(req);
206
235
  // We cannot update all documents in a single operation with `payload.update`,
@@ -244,20 +273,14 @@ export const addOrderableEndpoint = (config)=>{
244
273
  });
245
274
  }
246
275
  const targetId = target.id;
247
- let targetKey = target.key;
248
- // If targetKey = pending, we need to find its current key.
249
- // This can only happen if the user reorders rows quickly with a slow connection.
250
- if (targetKey === 'pending') {
251
- const beforeDoc = await req.payload.findByID({
252
- id: targetId,
253
- collection: collection.slug,
254
- depth: 0,
255
- select: {
256
- [orderableFieldName]: true
257
- }
258
- });
259
- targetKey = beforeDoc?.[orderableFieldName] || null;
260
- }
276
+ const targetKey = await resolvePendingTargetKey({
277
+ collectionSlug: collection.slug,
278
+ orderableFieldName,
279
+ req,
280
+ targetDoc,
281
+ targetID: targetId,
282
+ targetKey: target.key
283
+ });
261
284
  // The reason the endpoint does not receive this docId as an argument is that there
262
285
  // are situations where the user may not see or know what the next or previous one is. For
263
286
  // example, access control restrictions, if docBefore is the last one on the page, etc.
@@ -270,11 +293,14 @@ export const addOrderableEndpoint = (config)=>{
270
293
  [orderableFieldName]: true
271
294
  },
272
295
  sort: newKeyWillBe === 'greater' ? orderableFieldName : `-${orderableFieldName}`,
273
- where: {
274
- [orderableFieldName]: {
275
- [newKeyWillBe === 'greater' ? 'greater_than' : 'less_than']: targetKey
276
- }
277
- }
296
+ where: combineWhereConstraints([
297
+ {
298
+ [orderableFieldName]: {
299
+ [newKeyWillBe === 'greater' ? 'greater_than' : 'less_than']: targetKey
300
+ }
301
+ },
302
+ joinScopeWhere ?? undefined
303
+ ])
278
304
  });
279
305
  const adjacentDocKey = adjacentDoc.docs?.[0]?.[orderableFieldName] || null;
280
306
  // Currently N (= docsToMove.length) is always 1. Maybe in the future we will
@@ -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 { Field } 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 { commitTransaction } from '../../utilities/commitTransaction.js'\nimport { initTransaction } from '../../utilities/initTransaction.js'\nimport { killTransaction } from '../../utilities/killTransaction.js'\nimport { traverseFields } from '../../utilities/traverseFields.js'\nimport { generateKeyBetween, generateNKeysBetween } from './fractional-indexing.js'\n\n/**\n * This function creates:\n * - N fields per collection, named `_order` or `_<collection>_<joinField>_order`\n * - 1 hook per collection\n * - 1 endpoint per app\n *\n * Also, if collection.defaultSort or joinField.defaultSort is not set, it will be set to the orderable field.\n */\nexport const setupOrderable = (config: SanitizedConfig) => {\n const fieldsToAdd = new Map<CollectionConfig, string[]>()\n\n config.collections.forEach((collection) => {\n if (collection.orderable) {\n const currentFields = fieldsToAdd.get(collection) || []\n fieldsToAdd.set(collection, [...currentFields, '_order'])\n collection.defaultSort = collection.defaultSort ?? '_order'\n }\n\n traverseFields({\n callback: ({ field, parentRef, ref }) => {\n if (field.type === 'array' || field.type === 'blocks') {\n return false\n }\n if (field.type === 'group' || field.type === 'tab') {\n // @ts-expect-error ref is untyped\n const parentPrefix = parentRef?.prefix ? `${parentRef.prefix}_` : ''\n // @ts-expect-error ref is untyped\n ref.prefix = `${parentPrefix}${field.name}`\n }\n if (field.type === 'join' && field.orderable === true) {\n if (Array.isArray(field.collection)) {\n throw new APIError(\n 'Orderable joins must target a single collection',\n httpStatus.BAD_REQUEST,\n {},\n true,\n )\n }\n const relationshipCollection = config.collections.find((c) => c.slug === field.collection)\n if (!relationshipCollection) {\n return false\n }\n field.defaultSort = field.defaultSort ?? `_${field.collection}_${field.name}_order`\n const currentFields = fieldsToAdd.get(relationshipCollection) || []\n // @ts-expect-error ref is untyped\n const prefix = parentRef?.prefix ? `${parentRef.prefix}_` : ''\n fieldsToAdd.set(relationshipCollection, [\n ...currentFields,\n `_${field.collection}_${prefix}${field.name}_order`,\n ])\n }\n },\n fields: collection.fields,\n })\n })\n\n Array.from(fieldsToAdd.entries()).forEach(([collection, orderableFields]) => {\n addOrderableFieldsAndHook(collection, orderableFields)\n })\n\n if (fieldsToAdd.size > 0) {\n addOrderableEndpoint(config)\n }\n}\n\nexport const addOrderableFieldsAndHook = (\n collection: CollectionConfig,\n orderableFieldNames: string[],\n) => {\n // 1. Add field\n orderableFieldNames.forEach((orderableFieldName) => {\n const orderField: Field = {\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 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 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: {\n [orderableFieldName]: {\n exists: true,\n },\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 = (config: SanitizedConfig) => {\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 // 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: {\n [orderableFieldName]: {\n exists: false,\n },\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 let targetKey = target.key\n\n // If targetKey = pending, we need to find its current key.\n // This can only happen if the user reorders rows quickly with a slow connection.\n if (targetKey === 'pending') {\n const beforeDoc = await req.payload.findByID({\n id: targetId,\n collection: collection.slug,\n depth: 0,\n select: { [orderableFieldName]: true },\n })\n targetKey = beforeDoc?.[orderableFieldName] || null\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: {\n [orderableFieldName]: {\n [newKeyWillBe === 'greater' ? 'greater_than' : 'less_than']: targetKey,\n },\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","commitTransaction","initTransaction","killTransaction","traverseFields","generateKeyBetween","generateNKeysBetween","setupOrderable","config","fieldsToAdd","Map","collections","forEach","collection","orderable","currentFields","get","set","defaultSort","callback","field","parentRef","ref","type","parentPrefix","prefix","name","Array","isArray","BAD_REQUEST","relationshipCollection","find","c","slug","fields","from","entries","orderableFields","addOrderableFieldsAndHook","size","addOrderableEndpoint","orderableFieldNames","orderableFieldName","orderField","admin","disableBulkEdit","disabled","disableGroupBy","disableListColumn","disableListFilter","hidden","readOnly","hooks","beforeDuplicate","siblingData","index","unshift","beforeChange","orderBeforeChangeHook","data","originalDoc","req","lastDoc","payload","depth","limit","pagination","select","sort","where","exists","lastOrderValue","docs","push","reorderHandler","body","json","collectionSlug","docsToMove","newKeyWillBe","target","length","Response","JSON","stringify","error","headers","access","update","id","key","doc","e","Error","message","INTERNAL_SERVER_ERROR","success","targetId","targetKey","beforeDoc","findByID","adjacentDoc","adjacentDocKey","orderValues","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 { Field } 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 { combineWhereConstraints } from '../../utilities/combineWhereConstraints.js'\nimport { commitTransaction } from '../../utilities/commitTransaction.js'\nimport { initTransaction } from '../../utilities/initTransaction.js'\nimport { killTransaction } from '../../utilities/killTransaction.js'\nimport { traverseFields } from '../../utilities/traverseFields.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\n/**\n * This function creates:\n * - N fields per collection, named `_order` or `_<collection>_<joinField>_order`\n * - 1 hook per collection\n * - 1 endpoint per app\n *\n * Also, if collection.defaultSort or joinField.defaultSort is not set, it will be set to the orderable field.\n */\nexport const setupOrderable = (config: SanitizedConfig) => {\n const fieldsToAdd = new Map<CollectionConfig, string[]>()\n const joinFieldPathsByCollection = new Map<string, Map<string, string>>()\n\n config.collections.forEach((collection) => {\n if (collection.orderable) {\n const currentFields = fieldsToAdd.get(collection) || []\n fieldsToAdd.set(collection, [...currentFields, '_order'])\n collection.defaultSort = collection.defaultSort ?? '_order'\n }\n\n traverseFields({\n callback: ({ field, parentRef, ref }) => {\n if (field.type === 'array' || field.type === 'blocks') {\n return false\n }\n if (field.type === 'group' || field.type === 'tab') {\n // @ts-expect-error ref is untyped\n const parentPrefix = parentRef?.prefix ? `${parentRef.prefix}_` : ''\n // @ts-expect-error ref is untyped\n ref.prefix = `${parentPrefix}${field.name}`\n }\n if (field.type === 'join' && field.orderable === true) {\n if (Array.isArray(field.collection)) {\n throw new APIError(\n 'Orderable joins must target a single collection',\n httpStatus.BAD_REQUEST,\n {},\n true,\n )\n }\n const relationshipCollection = config.collections.find((c) => c.slug === field.collection)\n if (!relationshipCollection) {\n return false\n }\n field.defaultSort = field.defaultSort ?? `_${field.collection}_${field.name}_order`\n const currentFields = fieldsToAdd.get(relationshipCollection) || []\n // @ts-expect-error ref is untyped\n const prefix = parentRef?.prefix ? `${parentRef.prefix}_` : ''\n const joinOrderableFieldName = `_${field.collection}_${prefix}${field.name}_order`\n fieldsToAdd.set(relationshipCollection, [...currentFields, joinOrderableFieldName])\n\n const currentJoinFieldPaths =\n joinFieldPathsByCollection.get(relationshipCollection.slug) || new Map<string, string>()\n currentJoinFieldPaths.set(joinOrderableFieldName, field.on)\n joinFieldPathsByCollection.set(relationshipCollection.slug, currentJoinFieldPaths)\n }\n },\n fields: collection.fields,\n })\n })\n\n Array.from(fieldsToAdd.entries()).forEach(([collection, orderableFields]) => {\n addOrderableFieldsAndHook(collection, orderableFields, joinFieldPathsByCollection)\n })\n\n if (fieldsToAdd.size > 0) {\n addOrderableEndpoint(config, joinFieldPathsByCollection)\n }\n}\n\nexport const addOrderableFieldsAndHook = (\n collection: CollectionConfig,\n orderableFieldNames: string[],\n joinFieldPathsByCollection?: Map<string, Map<string, string>>,\n) => {\n // 1. Add field\n orderableFieldNames.forEach((orderableFieldName) => {\n const orderField: Field = {\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 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","combineWhereConstraints","commitTransaction","initTransaction","killTransaction","traverseFields","generateKeyBetween","generateNKeysBetween","getJoinScopeContext","getJoinScopeWhereFromDocData","resolvePendingTargetKey","setupOrderable","config","fieldsToAdd","Map","joinFieldPathsByCollection","collections","forEach","collection","orderable","currentFields","get","set","defaultSort","callback","field","parentRef","ref","type","parentPrefix","prefix","name","Array","isArray","BAD_REQUEST","relationshipCollection","find","c","slug","joinOrderableFieldName","currentJoinFieldPaths","on","fields","from","entries","orderableFields","addOrderableFieldsAndHook","size","addOrderableEndpoint","orderableFieldNames","orderableFieldName","orderField","admin","disableBulkEdit","disabled","disableGroupBy","disableListColumn","disableListFilter","hidden","readOnly","hooks","beforeDuplicate","siblingData","index","unshift","beforeChange","orderBeforeChangeHook","data","originalDoc","req","joinScopeWhere","collectionSlug","lastDoc","payload","depth","limit","pagination","select","sort","where","exists","undefined","lastOrderValue","docs","push","reorderHandler","body","json","docsToMove","newKeyWillBe","target","length","Response","JSON","stringify","error","headers","targetDoc","access","update","id","key","doc","e","Error","message","INTERNAL_SERVER_ERROR","success","targetId","targetKey","targetID","adjacentDoc","adjacentDocKey","orderValues","reorderEndpoint","handler","method","path","endpoints"],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import type { Where } from '../../../types/index.js';
2
+ /**
3
+ * Builds a `where` fragment that scopes order operations to docs sharing the
4
+ * same join `on` field value.
5
+ */
6
+ export declare function buildJoinScopeWhere(args: {
7
+ joinOnFieldPath: string;
8
+ scopeValue: unknown;
9
+ }): null | Where;
10
+ //# sourceMappingURL=buildJoinScopeWhere.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"buildJoinScopeWhere.d.ts","sourceRoot":"","sources":["../../../../src/config/orderable/utils/buildJoinScopeWhere.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,yBAAyB,CAAA;AAEpD;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE;IACxC,eAAe,EAAE,MAAM,CAAA;IACvB,UAAU,EAAE,OAAO,CAAA;CACpB,GAAG,IAAI,GAAG,KAAK,CAgDf"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Builds a `where` fragment that scopes order operations to docs sharing the
3
+ * same join `on` field value.
4
+ */ export function buildJoinScopeWhere(args) {
5
+ const { joinOnFieldPath, scopeValue } = args;
6
+ if (typeof scopeValue === 'undefined') {
7
+ return null;
8
+ }
9
+ if (Array.isArray(scopeValue)) {
10
+ return buildJoinScopeWhere({
11
+ joinOnFieldPath,
12
+ scopeValue: scopeValue[0]
13
+ });
14
+ }
15
+ if (scopeValue && typeof scopeValue === 'object' && 'relationTo' in scopeValue && 'value' in scopeValue) {
16
+ const relation = scopeValue.relationTo;
17
+ const value = scopeValue.value;
18
+ if (typeof relation === 'undefined' || typeof value === 'undefined') {
19
+ return null;
20
+ }
21
+ return {
22
+ and: [
23
+ {
24
+ [`${joinOnFieldPath}.relationTo`]: {
25
+ equals: relation
26
+ }
27
+ },
28
+ {
29
+ [`${joinOnFieldPath}.value`]: {
30
+ equals: value
31
+ }
32
+ }
33
+ ]
34
+ };
35
+ }
36
+ return {
37
+ [joinOnFieldPath]: {
38
+ equals: scopeValue
39
+ }
40
+ };
41
+ }
42
+
43
+ //# sourceMappingURL=buildJoinScopeWhere.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/config/orderable/utils/buildJoinScopeWhere.ts"],"sourcesContent":["import type { Where } from '../../../types/index.js'\n\n/**\n * Builds a `where` fragment that scopes order operations to docs sharing the\n * same join `on` field value.\n */\nexport function buildJoinScopeWhere(args: {\n joinOnFieldPath: string\n scopeValue: unknown\n}): null | Where {\n const { joinOnFieldPath, scopeValue } = args\n\n if (typeof scopeValue === 'undefined') {\n return null\n }\n\n if (Array.isArray(scopeValue)) {\n return buildJoinScopeWhere({\n joinOnFieldPath,\n scopeValue: scopeValue[0],\n })\n }\n\n if (\n scopeValue &&\n typeof scopeValue === 'object' &&\n 'relationTo' in scopeValue &&\n 'value' in scopeValue\n ) {\n const relation = (scopeValue as { relationTo?: unknown }).relationTo\n const value = (scopeValue as { value?: unknown }).value\n\n if (typeof relation === 'undefined' || typeof value === 'undefined') {\n return null\n }\n\n return {\n and: [\n {\n [`${joinOnFieldPath}.relationTo`]: {\n equals: relation,\n },\n },\n {\n [`${joinOnFieldPath}.value`]: {\n equals: value,\n },\n },\n ],\n }\n }\n\n return {\n [joinOnFieldPath]: {\n equals: scopeValue,\n },\n }\n}\n"],"names":["buildJoinScopeWhere","args","joinOnFieldPath","scopeValue","Array","isArray","relation","relationTo","value","and","equals"],"mappings":"AAEA;;;CAGC,GACD,OAAO,SAASA,oBAAoBC,IAGnC;IACC,MAAM,EAAEC,eAAe,EAAEC,UAAU,EAAE,GAAGF;IAExC,IAAI,OAAOE,eAAe,aAAa;QACrC,OAAO;IACT;IAEA,IAAIC,MAAMC,OAAO,CAACF,aAAa;QAC7B,OAAOH,oBAAoB;YACzBE;YACAC,YAAYA,UAAU,CAAC,EAAE;QAC3B;IACF;IAEA,IACEA,cACA,OAAOA,eAAe,YACtB,gBAAgBA,cAChB,WAAWA,YACX;QACA,MAAMG,WAAW,AAACH,WAAwCI,UAAU;QACpE,MAAMC,QAAQ,AAACL,WAAmCK,KAAK;QAEvD,IAAI,OAAOF,aAAa,eAAe,OAAOE,UAAU,aAAa;YACnE,OAAO;QACT;QAEA,OAAO;YACLC,KAAK;gBACH;oBACE,CAAC,GAAGP,gBAAgB,WAAW,CAAC,CAAC,EAAE;wBACjCQ,QAAQJ;oBACV;gBACF;gBACA;oBACE,CAAC,GAAGJ,gBAAgB,MAAM,CAAC,CAAC,EAAE;wBAC5BQ,QAAQF;oBACV;gBACF;aACD;QACH;IACF;IAEA,OAAO;QACL,CAACN,gBAAgB,EAAE;YACjBQ,QAAQP;QACV;IACF;AACF"}
@@ -0,0 +1,16 @@
1
+ import type { PayloadHandler } from '../../types.js';
2
+ import { buildJoinScopeWhere } from './buildJoinScopeWhere.js';
3
+ /**
4
+ * Resolves join scope and target document context for reorder operations.
5
+ */
6
+ export declare function getJoinScopeContext(args: {
7
+ collectionSlug: string;
8
+ joinFieldPathsByCollection: Map<string, Map<string, string>>;
9
+ orderableFieldName: string;
10
+ req: Parameters<PayloadHandler>[0];
11
+ target: unknown;
12
+ }): Promise<{
13
+ joinScopeWhere: ReturnType<typeof buildJoinScopeWhere>;
14
+ targetDoc: null | Record<string, unknown>;
15
+ }>;
16
+ //# sourceMappingURL=getJoinScopeContext.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getJoinScopeContext.d.ts","sourceRoot":"","sources":["../../../../src/config/orderable/utils/getJoinScopeContext.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAEpD,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAA;AAG9D;;GAEG;AACH,wBAAsB,mBAAmB,CAAC,IAAI,EAAE;IAC9C,cAAc,EAAE,MAAM,CAAA;IACtB,0BAA0B,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;IAC5D,kBAAkB,EAAE,MAAM,CAAA;IAC1B,GAAG,EAAE,UAAU,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAA;IAClC,MAAM,EAAE,OAAO,CAAA;CAChB,GAAG,OAAO,CAAC;IACV,cAAc,EAAE,UAAU,CAAC,OAAO,mBAAmB,CAAC,CAAA;IACtD,SAAS,EAAE,IAAI,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAC1C,CAAC,CA2CD"}
@@ -0,0 +1,41 @@
1
+ import { buildJoinScopeWhere } from './buildJoinScopeWhere.js';
2
+ import { getValueAtPath } from './getValueAtPath.js';
3
+ /**
4
+ * Resolves join scope and target document context for reorder operations.
5
+ */ export async function getJoinScopeContext(args) {
6
+ const { collectionSlug, joinFieldPathsByCollection, orderableFieldName, req, target } = args;
7
+ const joinOnFieldPath = joinFieldPathsByCollection.get(collectionSlug)?.get(orderableFieldName);
8
+ let targetDoc = null;
9
+ if (typeof target === 'object' && target && 'id' in target && (joinOnFieldPath || 'key' in target && target.key === 'pending')) {
10
+ const targetID = target.id;
11
+ if (typeof targetID === 'number' || typeof targetID === 'string') {
12
+ targetDoc = await req.payload.findByID({
13
+ id: targetID,
14
+ collection: collectionSlug,
15
+ depth: 0,
16
+ select: {
17
+ ...joinOnFieldPath ? {
18
+ [joinOnFieldPath]: true
19
+ } : {},
20
+ [orderableFieldName]: true
21
+ }
22
+ });
23
+ }
24
+ }
25
+ if (!joinOnFieldPath) {
26
+ return {
27
+ joinScopeWhere: null,
28
+ targetDoc
29
+ };
30
+ }
31
+ const joinScopeValue = getValueAtPath(targetDoc, joinOnFieldPath);
32
+ return {
33
+ joinScopeWhere: buildJoinScopeWhere({
34
+ joinOnFieldPath,
35
+ scopeValue: joinScopeValue
36
+ }),
37
+ targetDoc
38
+ };
39
+ }
40
+
41
+ //# sourceMappingURL=getJoinScopeContext.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/config/orderable/utils/getJoinScopeContext.ts"],"sourcesContent":["import type { PayloadHandler } from '../../types.js'\n\nimport { buildJoinScopeWhere } from './buildJoinScopeWhere.js'\nimport { getValueAtPath } from './getValueAtPath.js'\n\n/**\n * Resolves join scope and target document context for reorder operations.\n */\nexport async function getJoinScopeContext(args: {\n collectionSlug: string\n joinFieldPathsByCollection: Map<string, Map<string, string>>\n orderableFieldName: string\n req: Parameters<PayloadHandler>[0]\n target: unknown\n}): Promise<{\n joinScopeWhere: ReturnType<typeof buildJoinScopeWhere>\n targetDoc: null | Record<string, unknown>\n}> {\n const { collectionSlug, joinFieldPathsByCollection, orderableFieldName, req, target } = args\n\n const joinOnFieldPath = joinFieldPathsByCollection.get(collectionSlug)?.get(orderableFieldName)\n let targetDoc: null | Record<string, unknown> = null\n\n if (\n typeof target === 'object' &&\n target &&\n 'id' in target &&\n (joinOnFieldPath || ('key' in target && target.key === 'pending'))\n ) {\n const targetID = (target as { id?: unknown }).id\n\n if (typeof targetID === 'number' || typeof targetID === 'string') {\n targetDoc = await req.payload.findByID({\n id: targetID,\n collection: collectionSlug,\n depth: 0,\n select: {\n ...(joinOnFieldPath ? { [joinOnFieldPath]: true } : {}),\n [orderableFieldName]: true,\n },\n })\n }\n }\n\n if (!joinOnFieldPath) {\n return {\n joinScopeWhere: null,\n targetDoc,\n }\n }\n\n const joinScopeValue = getValueAtPath(targetDoc, joinOnFieldPath)\n\n return {\n joinScopeWhere: buildJoinScopeWhere({\n joinOnFieldPath,\n scopeValue: joinScopeValue,\n }),\n targetDoc,\n }\n}\n"],"names":["buildJoinScopeWhere","getValueAtPath","getJoinScopeContext","args","collectionSlug","joinFieldPathsByCollection","orderableFieldName","req","target","joinOnFieldPath","get","targetDoc","key","targetID","id","payload","findByID","collection","depth","select","joinScopeWhere","joinScopeValue","scopeValue"],"mappings":"AAEA,SAASA,mBAAmB,QAAQ,2BAA0B;AAC9D,SAASC,cAAc,QAAQ,sBAAqB;AAEpD;;CAEC,GACD,OAAO,eAAeC,oBAAoBC,IAMzC;IAIC,MAAM,EAAEC,cAAc,EAAEC,0BAA0B,EAAEC,kBAAkB,EAAEC,GAAG,EAAEC,MAAM,EAAE,GAAGL;IAExF,MAAMM,kBAAkBJ,2BAA2BK,GAAG,CAACN,iBAAiBM,IAAIJ;IAC5E,IAAIK,YAA4C;IAEhD,IACE,OAAOH,WAAW,YAClBA,UACA,QAAQA,UACPC,CAAAA,mBAAoB,SAASD,UAAUA,OAAOI,GAAG,KAAK,SAAS,GAChE;QACA,MAAMC,WAAW,AAACL,OAA4BM,EAAE;QAEhD,IAAI,OAAOD,aAAa,YAAY,OAAOA,aAAa,UAAU;YAChEF,YAAY,MAAMJ,IAAIQ,OAAO,CAACC,QAAQ,CAAC;gBACrCF,IAAID;gBACJI,YAAYb;gBACZc,OAAO;gBACPC,QAAQ;oBACN,GAAIV,kBAAkB;wBAAE,CAACA,gBAAgB,EAAE;oBAAK,IAAI,CAAC,CAAC;oBACtD,CAACH,mBAAmB,EAAE;gBACxB;YACF;QACF;IACF;IAEA,IAAI,CAACG,iBAAiB;QACpB,OAAO;YACLW,gBAAgB;YAChBT;QACF;IACF;IAEA,MAAMU,iBAAiBpB,eAAeU,WAAWF;IAEjD,OAAO;QACLW,gBAAgBpB,oBAAoB;YAClCS;YACAa,YAAYD;QACd;QACAV;IACF;AACF"}
@@ -0,0 +1,12 @@
1
+ import { buildJoinScopeWhere } from './buildJoinScopeWhere.js';
2
+ /**
3
+ * Builds a join-scope filter for order key generation during beforeChange.
4
+ */
5
+ export declare function getJoinScopeWhereFromDocData(args: {
6
+ collectionSlug: string;
7
+ data: Record<string, unknown>;
8
+ joinFieldPathsByCollection?: Map<string, Map<string, string>>;
9
+ orderableFieldName: string;
10
+ originalDoc?: Record<string, unknown>;
11
+ }): ReturnType<typeof buildJoinScopeWhere>;
12
+ //# sourceMappingURL=getJoinScopeWhereFromDocData.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getJoinScopeWhereFromDocData.d.ts","sourceRoot":"","sources":["../../../../src/config/orderable/utils/getJoinScopeWhereFromDocData.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAA;AAG9D;;GAEG;AACH,wBAAgB,4BAA4B,CAAC,IAAI,EAAE;IACjD,cAAc,EAAE,MAAM,CAAA;IACtB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC7B,0BAA0B,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;IAC7D,kBAAkB,EAAE,MAAM,CAAA;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CACtC,GAAG,UAAU,CAAC,OAAO,mBAAmB,CAAC,CAgBzC"}
@@ -0,0 +1,18 @@
1
+ import { buildJoinScopeWhere } from './buildJoinScopeWhere.js';
2
+ import { getValueAtPath } from './getValueAtPath.js';
3
+ /**
4
+ * Builds a join-scope filter for order key generation during beforeChange.
5
+ */ export function getJoinScopeWhereFromDocData(args) {
6
+ const { collectionSlug, data, joinFieldPathsByCollection, orderableFieldName, originalDoc } = args;
7
+ const joinOnFieldPath = joinFieldPathsByCollection?.get(collectionSlug)?.get(orderableFieldName);
8
+ if (!joinOnFieldPath) {
9
+ return null;
10
+ }
11
+ const scopeValue = getValueAtPath(data, joinOnFieldPath) ?? getValueAtPath(originalDoc, joinOnFieldPath);
12
+ return buildJoinScopeWhere({
13
+ joinOnFieldPath,
14
+ scopeValue
15
+ });
16
+ }
17
+
18
+ //# sourceMappingURL=getJoinScopeWhereFromDocData.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/config/orderable/utils/getJoinScopeWhereFromDocData.ts"],"sourcesContent":["import { buildJoinScopeWhere } from './buildJoinScopeWhere.js'\nimport { getValueAtPath } from './getValueAtPath.js'\n\n/**\n * Builds a join-scope filter for order key generation during beforeChange.\n */\nexport function getJoinScopeWhereFromDocData(args: {\n collectionSlug: string\n data: Record<string, unknown>\n joinFieldPathsByCollection?: Map<string, Map<string, string>>\n orderableFieldName: string\n originalDoc?: Record<string, unknown>\n}): ReturnType<typeof buildJoinScopeWhere> {\n const { collectionSlug, data, joinFieldPathsByCollection, orderableFieldName, originalDoc } = args\n\n const joinOnFieldPath = joinFieldPathsByCollection?.get(collectionSlug)?.get(orderableFieldName)\n\n if (!joinOnFieldPath) {\n return null\n }\n\n const scopeValue =\n getValueAtPath(data, joinOnFieldPath) ?? getValueAtPath(originalDoc, joinOnFieldPath)\n\n return buildJoinScopeWhere({\n joinOnFieldPath,\n scopeValue,\n })\n}\n"],"names":["buildJoinScopeWhere","getValueAtPath","getJoinScopeWhereFromDocData","args","collectionSlug","data","joinFieldPathsByCollection","orderableFieldName","originalDoc","joinOnFieldPath","get","scopeValue"],"mappings":"AAAA,SAASA,mBAAmB,QAAQ,2BAA0B;AAC9D,SAASC,cAAc,QAAQ,sBAAqB;AAEpD;;CAEC,GACD,OAAO,SAASC,6BAA6BC,IAM5C;IACC,MAAM,EAAEC,cAAc,EAAEC,IAAI,EAAEC,0BAA0B,EAAEC,kBAAkB,EAAEC,WAAW,EAAE,GAAGL;IAE9F,MAAMM,kBAAkBH,4BAA4BI,IAAIN,iBAAiBM,IAAIH;IAE7E,IAAI,CAACE,iBAAiB;QACpB,OAAO;IACT;IAEA,MAAME,aACJV,eAAeI,MAAMI,oBAAoBR,eAAeO,aAAaC;IAEvE,OAAOT,oBAAoB;QACzBS;QACAE;IACF;AACF"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Reads a nested value from an object using dot-notation path syntax.
3
+ */
4
+ export declare function getValueAtPath(data: unknown, path: string): unknown;
5
+ //# sourceMappingURL=getValueAtPath.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getValueAtPath.d.ts","sourceRoot":"","sources":["../../../../src/config/orderable/utils/getValueAtPath.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAiBnE"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Reads a nested value from an object using dot-notation path syntax.
3
+ */ export function getValueAtPath(data, path) {
4
+ if (!data || typeof data !== 'object') {
5
+ return undefined;
6
+ }
7
+ const segments = path.split('.');
8
+ let currentValue = data;
9
+ for (const segment of segments){
10
+ if (!currentValue || typeof currentValue !== 'object') {
11
+ return undefined;
12
+ }
13
+ currentValue = currentValue[segment];
14
+ }
15
+ return currentValue;
16
+ }
17
+
18
+ //# sourceMappingURL=getValueAtPath.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/config/orderable/utils/getValueAtPath.ts"],"sourcesContent":["/**\n * Reads a nested value from an object using dot-notation path syntax.\n */\nexport function getValueAtPath(data: unknown, path: string): unknown {\n if (!data || typeof data !== 'object') {\n return undefined\n }\n\n const segments = path.split('.')\n let currentValue: unknown = data\n\n for (const segment of segments) {\n if (!currentValue || typeof currentValue !== 'object') {\n return undefined\n }\n\n currentValue = (currentValue as Record<string, unknown>)[segment]\n }\n\n return currentValue\n}\n"],"names":["getValueAtPath","data","path","undefined","segments","split","currentValue","segment"],"mappings":"AAAA;;CAEC,GACD,OAAO,SAASA,eAAeC,IAAa,EAAEC,IAAY;IACxD,IAAI,CAACD,QAAQ,OAAOA,SAAS,UAAU;QACrC,OAAOE;IACT;IAEA,MAAMC,WAAWF,KAAKG,KAAK,CAAC;IAC5B,IAAIC,eAAwBL;IAE5B,KAAK,MAAMM,WAAWH,SAAU;QAC9B,IAAI,CAACE,gBAAgB,OAAOA,iBAAiB,UAAU;YACrD,OAAOH;QACT;QAEAG,eAAe,AAACA,YAAwC,CAACC,QAAQ;IACnE;IAEA,OAAOD;AACT"}
@@ -0,0 +1,13 @@
1
+ import type { PayloadHandler } from '../../types.js';
2
+ /**
3
+ * Resolves the target key when the client sends the temporary `pending` marker.
4
+ */
5
+ export declare function resolvePendingTargetKey(args: {
6
+ collectionSlug: string;
7
+ orderableFieldName: string;
8
+ req: Parameters<PayloadHandler>[0];
9
+ targetDoc: null | Record<string, unknown>;
10
+ targetID: string;
11
+ targetKey: string;
12
+ }): Promise<null | string>;
13
+ //# sourceMappingURL=resolvePendingTargetKey.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolvePendingTargetKey.d.ts","sourceRoot":"","sources":["../../../../src/config/orderable/utils/resolvePendingTargetKey.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAEpD;;GAEG;AACH,wBAAsB,uBAAuB,CAAC,IAAI,EAAE;IAClD,cAAc,EAAE,MAAM,CAAA;IACtB,kBAAkB,EAAE,MAAM,CAAA;IAC1B,GAAG,EAAE,UAAU,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAA;IAClC,SAAS,EAAE,IAAI,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACzC,QAAQ,EAAE,MAAM,CAAA;IAChB,SAAS,EAAE,MAAM,CAAA;CAClB,GAAG,OAAO,CAAC,IAAI,GAAG,MAAM,CAAC,CAoBzB"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Resolves the target key when the client sends the temporary `pending` marker.
3
+ */ export async function resolvePendingTargetKey(args) {
4
+ const { collectionSlug, orderableFieldName, req, targetDoc, targetID, targetKey } = args;
5
+ if (targetKey !== 'pending') {
6
+ return targetKey;
7
+ }
8
+ const targetDocKey = targetDoc?.[orderableFieldName];
9
+ if (typeof targetDocKey === 'string') {
10
+ return targetDocKey;
11
+ }
12
+ const beforeDoc = await req.payload.findByID({
13
+ id: targetID,
14
+ collection: collectionSlug,
15
+ depth: 0,
16
+ select: {
17
+ [orderableFieldName]: true
18
+ }
19
+ });
20
+ return beforeDoc?.[orderableFieldName] || null;
21
+ }
22
+
23
+ //# sourceMappingURL=resolvePendingTargetKey.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/config/orderable/utils/resolvePendingTargetKey.ts"],"sourcesContent":["import type { PayloadHandler } from '../../types.js'\n\n/**\n * Resolves the target key when the client sends the temporary `pending` marker.\n */\nexport async function resolvePendingTargetKey(args: {\n collectionSlug: string\n orderableFieldName: string\n req: Parameters<PayloadHandler>[0]\n targetDoc: null | Record<string, unknown>\n targetID: string\n targetKey: string\n}): Promise<null | string> {\n const { collectionSlug, orderableFieldName, req, targetDoc, targetID, targetKey } = args\n\n if (targetKey !== 'pending') {\n return targetKey\n }\n\n const targetDocKey = targetDoc?.[orderableFieldName]\n if (typeof targetDocKey === 'string') {\n return targetDocKey\n }\n\n const beforeDoc = await req.payload.findByID({\n id: targetID,\n collection: collectionSlug,\n depth: 0,\n select: { [orderableFieldName]: true },\n })\n\n return beforeDoc?.[orderableFieldName] || null\n}\n"],"names":["resolvePendingTargetKey","args","collectionSlug","orderableFieldName","req","targetDoc","targetID","targetKey","targetDocKey","beforeDoc","payload","findByID","id","collection","depth","select"],"mappings":"AAEA;;CAEC,GACD,OAAO,eAAeA,wBAAwBC,IAO7C;IACC,MAAM,EAAEC,cAAc,EAAEC,kBAAkB,EAAEC,GAAG,EAAEC,SAAS,EAAEC,QAAQ,EAAEC,SAAS,EAAE,GAAGN;IAEpF,IAAIM,cAAc,WAAW;QAC3B,OAAOA;IACT;IAEA,MAAMC,eAAeH,WAAW,CAACF,mBAAmB;IACpD,IAAI,OAAOK,iBAAiB,UAAU;QACpC,OAAOA;IACT;IAEA,MAAMC,YAAY,MAAML,IAAIM,OAAO,CAACC,QAAQ,CAAC;QAC3CC,IAAIN;QACJO,YAAYX;QACZY,OAAO;QACPC,QAAQ;YAAE,CAACZ,mBAAmB,EAAE;QAAK;IACvC;IAEA,OAAOM,WAAW,CAACN,mBAAmB,IAAI;AAC5C"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "payload",
3
- "version": "3.79.0-canary.3",
3
+ "version": "3.79.0-internal.2874f3f",
4
4
  "description": "Node, React, Headless CMS and Application Framework built on Next.js",
5
5
  "keywords": [
6
6
  "admin panel",
@@ -115,7 +115,7 @@
115
115
  "undici": "7.18.2",
116
116
  "uuid": "10.0.0",
117
117
  "ws": "^8.16.0",
118
- "@payloadcms/translations": "3.79.0-canary.3"
118
+ "@payloadcms/translations": "3.79.0-internal.2874f3f"
119
119
  },
120
120
  "devDependencies": {
121
121
  "@hyrious/esbuild-plugin-commonjs": "0.2.6",