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.
- package/dist/collections/endpoints/duplicate.js +1 -1
- package/dist/collections/endpoints/duplicate.js.map +1 -1
- package/dist/collections/operations/restoreVersion.d.ts.map +1 -1
- package/dist/collections/operations/restoreVersion.js +16 -11
- package/dist/collections/operations/restoreVersion.js.map +1 -1
- package/dist/config/orderable/index.d.ts +2 -2
- package/dist/config/orderable/index.d.ts.map +1 -1
- package/dist/config/orderable/index.js +60 -34
- package/dist/config/orderable/index.js.map +1 -1
- package/dist/config/orderable/utils/buildJoinScopeWhere.d.ts +10 -0
- package/dist/config/orderable/utils/buildJoinScopeWhere.d.ts.map +1 -0
- package/dist/config/orderable/utils/buildJoinScopeWhere.js +43 -0
- package/dist/config/orderable/utils/buildJoinScopeWhere.js.map +1 -0
- package/dist/config/orderable/utils/getJoinScopeContext.d.ts +16 -0
- package/dist/config/orderable/utils/getJoinScopeContext.d.ts.map +1 -0
- package/dist/config/orderable/utils/getJoinScopeContext.js +41 -0
- package/dist/config/orderable/utils/getJoinScopeContext.js.map +1 -0
- package/dist/config/orderable/utils/getJoinScopeWhereFromDocData.d.ts +12 -0
- package/dist/config/orderable/utils/getJoinScopeWhereFromDocData.d.ts.map +1 -0
- package/dist/config/orderable/utils/getJoinScopeWhereFromDocData.js +18 -0
- package/dist/config/orderable/utils/getJoinScopeWhereFromDocData.js.map +1 -0
- package/dist/config/orderable/utils/getValueAtPath.d.ts +5 -0
- package/dist/config/orderable/utils/getValueAtPath.d.ts.map +1 -0
- package/dist/config/orderable/utils/getValueAtPath.js +18 -0
- package/dist/config/orderable/utils/getValueAtPath.js.map +1 -0
- package/dist/config/orderable/utils/resolvePendingTargetKey.d.ts +13 -0
- package/dist/config/orderable/utils/resolvePendingTargetKey.d.ts.map +1 -0
- package/dist/config/orderable/utils/resolvePendingTargetKey.js +23 -0
- package/dist/config/orderable/utils/resolvePendingTargetKey.js.map +1 -0
- 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,
|
|
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,
|
|
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:
|
|
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:
|
|
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:
|
|
108
|
+
locale: validationLocale,
|
|
108
109
|
overrideAccess: true,
|
|
109
110
|
req,
|
|
110
111
|
showHiddenFields: true
|
|
111
112
|
});
|
|
112
|
-
// version 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:
|
|
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;
|
|
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
|
-
|
|
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
|
-
|
|
114
|
-
|
|
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
|
-
|
|
201
|
-
|
|
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
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
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
|
-
|
|
275
|
-
[
|
|
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 @@
|
|
|
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-
|
|
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-
|
|
118
|
+
"@payloadcms/translations": "3.79.0-internal.2874f3f"
|
|
119
119
|
},
|
|
120
120
|
"devDependencies": {
|
|
121
121
|
"@hyrious/esbuild-plugin-commonjs": "0.2.6",
|