payload-nested-docs-page-tree 1.2.3 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +136 -47
  3. package/dist/components/PageTreeContext.d.ts +13 -1
  4. package/dist/components/PageTreeContext.js +11 -1
  5. package/dist/components/PageTreeContext.js.map +1 -1
  6. package/dist/components/PageTreeListView.client.d.ts +3 -4
  7. package/dist/components/PageTreeListView.client.js +645 -381
  8. package/dist/components/PageTreeListView.client.js.map +1 -1
  9. package/dist/components/PageTreeListView.module.css +90 -67
  10. package/dist/components/PageTreeListView.server.js +18 -28
  11. package/dist/components/PageTreeListView.server.js.map +1 -1
  12. package/dist/components/PageTreeTitleCell.js +80 -18
  13. package/dist/components/PageTreeTitleCell.js.map +1 -1
  14. package/dist/endpoints/createMovePageEndpoint.d.ts +2 -0
  15. package/dist/endpoints/createMovePageEndpoint.js +166 -123
  16. package/dist/endpoints/createMovePageEndpoint.js.map +1 -1
  17. package/dist/endpoints/createReorderPageEndpoint.d.ts +8 -0
  18. package/dist/endpoints/createReorderPageEndpoint.js +703 -0
  19. package/dist/endpoints/createReorderPageEndpoint.js.map +1 -0
  20. package/dist/endpoints/shared.d.ts +40 -0
  21. package/dist/endpoints/shared.js +93 -0
  22. package/dist/endpoints/shared.js.map +1 -0
  23. package/dist/exports/client.js.map +1 -1
  24. package/dist/exports/rsc.js.map +1 -1
  25. package/dist/index.js +105 -26
  26. package/dist/index.js.map +1 -1
  27. package/dist/types.d.ts +9 -2
  28. package/dist/types.js +0 -2
  29. package/dist/types.js.map +1 -1
  30. package/dist/utilities/badgeConfig.js.map +1 -1
  31. package/dist/utilities/diagnostics.d.ts +42 -0
  32. package/dist/utilities/diagnostics.js +83 -0
  33. package/dist/utilities/diagnostics.js.map +1 -0
  34. package/dist/utilities/dropTargets.d.ts +2 -2
  35. package/dist/utilities/dropTargets.js +9 -7
  36. package/dist/utilities/dropTargets.js.map +1 -1
  37. package/dist/utilities/pageTree.js +4 -6
  38. package/dist/utilities/pageTree.js.map +1 -1
  39. package/dist/utilities/pageTreeCollision.d.ts +6 -0
  40. package/dist/utilities/pageTreeCollision.js +39 -4
  41. package/dist/utilities/pageTreeCollision.js.map +1 -1
  42. package/dist/utilities/pageTreeConfig.js.map +1 -1
  43. package/dist/utilities/status.d.ts +1 -1
  44. package/dist/utilities/status.js +7 -3
  45. package/dist/utilities/status.js.map +1 -1
  46. package/package.json +13 -12
@@ -0,0 +1,703 @@
1
+ import { combineWhereConstraints, generateNKeysBetween } from 'payload/shared';
2
+ import { pageTreeMoveContextKey } from '../types.js';
3
+ import { createFlowID, DIAGNOSTICS_FLOW_CONTEXT_KEY, readMainRowSnapshot } from '../utilities/diagnostics.js';
4
+ import { getDocParentID, stringifyDocID } from '../utilities/pageTree.js';
5
+ import { assertUpdateAccess, collectionHasDrafts, getRequestedLocale, normalizeID, respond, toCollectionID } from './shared.js';
6
+ const SNAPSHOT_FIELDS = [
7
+ '_status'
8
+ ];
9
+ function hasOwnProperty(value, key) {
10
+ return Object.prototype.hasOwnProperty.call(value, key);
11
+ }
12
+ function normalizeOptionalString(value) {
13
+ return typeof value === 'string' && value.length > 0 ? value : null;
14
+ }
15
+ function normalizeFrontendOrderEntry(value, fallbackIndex) {
16
+ if (!value || typeof value !== 'object' || Array.isArray(value)) {
17
+ return null;
18
+ }
19
+ const data = value;
20
+ return {
21
+ slug: normalizeOptionalString(data.slug),
22
+ index: typeof data.index === 'number' && Number.isFinite(data.index) ? data.index : fallbackIndex,
23
+ orderKey: normalizeOptionalString(data.orderKey)
24
+ };
25
+ }
26
+ function normalizeFrontendOrder(value) {
27
+ if (!value || typeof value !== 'object' || Array.isArray(value)) {
28
+ return undefined;
29
+ }
30
+ const data = value;
31
+ if (!Array.isArray(data.before) || !Array.isArray(data.after)) {
32
+ return undefined;
33
+ }
34
+ const before = data.before.slice(0, 250).map((entry, index)=>normalizeFrontendOrderEntry(entry, index)).filter((entry)=>Boolean(entry));
35
+ const after = data.after.slice(0, 250).map((entry, index)=>normalizeFrontendOrderEntry(entry, index)).filter((entry)=>Boolean(entry));
36
+ return {
37
+ activeSlug: normalizeOptionalString(data.activeSlug),
38
+ after,
39
+ before,
40
+ moveFromIndex: typeof data.moveFromIndex === 'number' && Number.isFinite(data.moveFromIndex) ? data.moveFromIndex : -1,
41
+ moveToIndex: typeof data.moveToIndex === 'number' && Number.isFinite(data.moveToIndex) ? data.moveToIndex : -1,
42
+ newAfterRowSlug: normalizeOptionalString(data.newAfterRowSlug),
43
+ newBeforeRowSlug: normalizeOptionalString(data.newBeforeRowSlug),
44
+ sort: normalizeOptionalString(data.sort),
45
+ targetSlug: normalizeOptionalString(data.targetSlug)
46
+ };
47
+ }
48
+ function normalizeReorderDocumentBody(value) {
49
+ const incomingData = typeof value === 'string' ? (()=>{
50
+ try {
51
+ return JSON.parse(value);
52
+ } catch {
53
+ return null;
54
+ }
55
+ })() : value;
56
+ if (!incomingData || typeof incomingData !== 'object' || Array.isArray(incomingData)) {
57
+ return null;
58
+ }
59
+ const data = incomingData;
60
+ const target = data.target;
61
+ if (!Array.isArray(data.docsToMove) || data.docsToMove.length !== 1) {
62
+ return null;
63
+ }
64
+ if (data.newKeyWillBe !== 'greater' && data.newKeyWillBe !== 'less') {
65
+ return null;
66
+ }
67
+ if (typeof data.orderableFieldName !== 'string' || data.orderableFieldName.length === 0) {
68
+ return null;
69
+ }
70
+ if (!target || typeof target !== 'object' || Array.isArray(target)) {
71
+ return null;
72
+ }
73
+ const targetData = target;
74
+ const movedID = normalizeID(data.docsToMove[0]);
75
+ const targetID = normalizeID(targetData.id);
76
+ if (!movedID || !targetID) {
77
+ return null;
78
+ }
79
+ const key = hasOwnProperty(targetData, 'key') ? targetData.key : null;
80
+ if (key !== null && key !== undefined && typeof key !== 'string') {
81
+ return null;
82
+ }
83
+ return {
84
+ docsToMove: [
85
+ movedID
86
+ ],
87
+ frontendOrder: normalizeFrontendOrder(data.frontendOrder),
88
+ newKeyWillBe: data.newKeyWillBe,
89
+ orderableFieldName: data.orderableFieldName,
90
+ target: {
91
+ id: targetID,
92
+ key: key || null
93
+ }
94
+ };
95
+ }
96
+ async function readBodyFromRequest(req) {
97
+ let lastAttempt = null;
98
+ if (req.data !== undefined && req.data !== null) {
99
+ lastAttempt = {
100
+ raw: req.data,
101
+ source: 'req.data'
102
+ };
103
+ const directBody = normalizeReorderDocumentBody(req.data);
104
+ if (directBody) {
105
+ return {
106
+ body: directBody,
107
+ lastAttempt
108
+ };
109
+ }
110
+ }
111
+ if (typeof req.json === 'function') {
112
+ try {
113
+ const raw = await req.json();
114
+ lastAttempt = {
115
+ raw,
116
+ source: 'req.json'
117
+ };
118
+ const jsonBody = normalizeReorderDocumentBody(raw);
119
+ if (jsonBody) {
120
+ return {
121
+ body: jsonBody,
122
+ lastAttempt
123
+ };
124
+ }
125
+ } catch {
126
+ // Fall through to the text-based fallback when the runtime does not hydrate req.data.
127
+ }
128
+ }
129
+ if (typeof req.text === 'function') {
130
+ try {
131
+ const raw = await req.text();
132
+ lastAttempt = {
133
+ raw,
134
+ source: 'req.text'
135
+ };
136
+ const textBody = normalizeReorderDocumentBody(raw);
137
+ if (textBody) {
138
+ return {
139
+ body: textBody,
140
+ lastAttempt
141
+ };
142
+ }
143
+ } catch {
144
+ return {
145
+ body: null,
146
+ lastAttempt
147
+ };
148
+ }
149
+ }
150
+ return {
151
+ body: null,
152
+ lastAttempt
153
+ };
154
+ }
155
+ function getParentScopeWhere(args) {
156
+ const { parentFieldSlug, parentID } = args;
157
+ return {
158
+ [parentFieldSlug]: {
159
+ equals: parentID
160
+ }
161
+ };
162
+ }
163
+ function getOrderableKey(doc, orderableFieldName) {
164
+ const value = doc?.[orderableFieldName];
165
+ return typeof value === 'string' && value.length > 0 ? value : null;
166
+ }
167
+ function getDiagnosticDocString(value, locale) {
168
+ if (typeof value === 'string' && value.length > 0) {
169
+ return value;
170
+ }
171
+ if (!value || typeof value !== 'object' || Array.isArray(value)) {
172
+ return null;
173
+ }
174
+ const localizedValue = value;
175
+ const localeValue = locale ? localizedValue[locale] : undefined;
176
+ if (typeof localeValue === 'string' && localeValue.length > 0) {
177
+ return localeValue;
178
+ }
179
+ const firstString = Object.values(localizedValue).find((entry)=>typeof entry === 'string' && entry.length > 0);
180
+ return firstString ?? null;
181
+ }
182
+ function getBackendOrderEntry(args) {
183
+ const { doc, index, locale, orderableFieldName } = args;
184
+ return {
185
+ slug: getDiagnosticDocString(doc.slug, locale),
186
+ index,
187
+ orderKey: getOrderableKey(doc, orderableFieldName),
188
+ status: getDiagnosticDocString(doc._status, locale)
189
+ };
190
+ }
191
+ function getMainRowOrderSnapshot(snapshot, orderableFieldName) {
192
+ if (!snapshot) {
193
+ return null;
194
+ }
195
+ return {
196
+ orderKey: normalizeOptionalString(snapshot[orderableFieldName]),
197
+ status: normalizeOptionalString(snapshot._status)
198
+ };
199
+ }
200
+ async function readBackendSiblingOrder(args) {
201
+ const { collectionSlug, draft, orderableFieldName, parentScopeWhere, req } = args;
202
+ const locale = getRequestedLocale(req);
203
+ try {
204
+ const result = await req.payload.find({
205
+ collection: collectionSlug,
206
+ depth: 0,
207
+ draft: draft,
208
+ limit: 250,
209
+ locale: locale,
210
+ overrideAccess: true,
211
+ pagination: false,
212
+ req,
213
+ sort: orderableFieldName,
214
+ where: parentScopeWhere
215
+ });
216
+ return result.docs.map((doc, index)=>getBackendOrderEntry({
217
+ doc,
218
+ index,
219
+ locale,
220
+ orderableFieldName
221
+ }));
222
+ } catch {
223
+ return [];
224
+ }
225
+ }
226
+ function getOrderValuesBetween(args) {
227
+ const { adjacentDocKey, docsToMoveLength, movedBoundaryKey, newKeyWillBe, targetKey } = args;
228
+ const orderValues = newKeyWillBe === 'greater' ? generateNKeysBetween(targetKey, adjacentDocKey, docsToMoveLength) : generateNKeysBetween(adjacentDocKey, targetKey, docsToMoveLength);
229
+ if (orderValues[0] !== movedBoundaryKey) {
230
+ return {
231
+ orderValues,
232
+ usedMovedKeyBoundary: false
233
+ };
234
+ }
235
+ if (newKeyWillBe === 'greater' && movedBoundaryKey && movedBoundaryKey > targetKey) {
236
+ return {
237
+ orderValues: generateNKeysBetween(targetKey, movedBoundaryKey, docsToMoveLength),
238
+ usedMovedKeyBoundary: true
239
+ };
240
+ }
241
+ if (newKeyWillBe === 'less' && movedBoundaryKey && movedBoundaryKey < targetKey) {
242
+ return {
243
+ orderValues: generateNKeysBetween(movedBoundaryKey, targetKey, docsToMoveLength),
244
+ usedMovedKeyBoundary: true
245
+ };
246
+ }
247
+ return {
248
+ orderValues,
249
+ usedMovedKeyBoundary: false
250
+ };
251
+ }
252
+ async function readLatestVersion(args) {
253
+ const { id, collectionSlug, req } = args;
254
+ const versions = await req.payload.db.findVersions({
255
+ collection: collectionSlug,
256
+ limit: 1,
257
+ pagination: false,
258
+ req,
259
+ sort: '-updatedAt',
260
+ where: {
261
+ latest: {
262
+ equals: true
263
+ },
264
+ parent: {
265
+ equals: id
266
+ }
267
+ }
268
+ });
269
+ const latestVersion = versions.docs[0];
270
+ if (!latestVersion?.version) {
271
+ return null;
272
+ }
273
+ return latestVersion;
274
+ }
275
+ async function updateLatestVersionOrder(args) {
276
+ const { id, collectionSlug, orderableFieldName, orderValue, req } = args;
277
+ const latestVersion = await readLatestVersion({
278
+ id,
279
+ collectionSlug,
280
+ req
281
+ });
282
+ if (!latestVersion?.id || !latestVersion.version) {
283
+ return false;
284
+ }
285
+ await req.payload.db.updateVersion({
286
+ id: latestVersion.id,
287
+ collection: collectionSlug,
288
+ locale: getRequestedLocale(req),
289
+ req,
290
+ returning: false,
291
+ versionData: {
292
+ createdAt: latestVersion.createdAt,
293
+ latest: latestVersion.latest,
294
+ parent: id,
295
+ publishedLocale: latestVersion.publishedLocale,
296
+ updatedAt: latestVersion.updatedAt,
297
+ version: {
298
+ ...latestVersion.version,
299
+ [orderableFieldName]: orderValue
300
+ }
301
+ }
302
+ });
303
+ return true;
304
+ }
305
+ async function updateOrderValueSilently(args) {
306
+ const { id, collectionSlug, hasDrafts, orderableFieldName, orderValue, req } = args;
307
+ await req.payload.db.updateOne({
308
+ id: id,
309
+ collection: collectionSlug,
310
+ data: {
311
+ [orderableFieldName]: orderValue,
312
+ updatedAt: null
313
+ },
314
+ locale: getRequestedLocale(req),
315
+ req,
316
+ returning: false
317
+ });
318
+ const updatedDraftVersion = hasDrafts ? await updateLatestVersionOrder({
319
+ id,
320
+ collectionSlug,
321
+ orderableFieldName,
322
+ orderValue,
323
+ req
324
+ }) : false;
325
+ return {
326
+ updatedDraftVersion
327
+ };
328
+ }
329
+ async function initializeMissingOrderKeys(args) {
330
+ const { collectionSlug, diagnostics, flow, hasDrafts, orderableFieldName, parentScopeWhere, req } = args;
331
+ const existingOrderedDocs = await req.payload.find({
332
+ collection: collectionSlug,
333
+ depth: 0,
334
+ draft: hasDrafts ? true : undefined,
335
+ limit: 1,
336
+ locale: getRequestedLocale(req),
337
+ overrideAccess: true,
338
+ pagination: false,
339
+ req,
340
+ select: {
341
+ [orderableFieldName]: true
342
+ },
343
+ sort: `-${orderableFieldName}`,
344
+ where: combineWhereConstraints([
345
+ {
346
+ [orderableFieldName]: {
347
+ exists: true
348
+ }
349
+ },
350
+ parentScopeWhere
351
+ ])
352
+ });
353
+ const missingOrderDocs = await req.payload.find({
354
+ collection: collectionSlug,
355
+ depth: 0,
356
+ draft: hasDrafts ? true : undefined,
357
+ limit: 0,
358
+ locale: getRequestedLocale(req),
359
+ overrideAccess: true,
360
+ pagination: false,
361
+ req,
362
+ select: {
363
+ [orderableFieldName]: true
364
+ },
365
+ where: combineWhereConstraints([
366
+ {
367
+ [orderableFieldName]: {
368
+ exists: false
369
+ }
370
+ },
371
+ parentScopeWhere
372
+ ])
373
+ });
374
+ const lastOrderValue = getOrderableKey(existingOrderedDocs.docs[0], orderableFieldName);
375
+ const orderValues = generateNKeysBetween(lastOrderValue, null, missingOrderDocs.docs.length);
376
+ for (const [index, doc] of missingOrderDocs.docs.entries()){
377
+ const docID = doc.id;
378
+ const orderValue = orderValues[index];
379
+ if (orderValue && (typeof docID === 'number' || typeof docID === 'string')) {
380
+ await updateOrderValueSilently({
381
+ id: docID,
382
+ collectionSlug,
383
+ hasDrafts,
384
+ orderableFieldName,
385
+ orderValue,
386
+ req
387
+ });
388
+ }
389
+ }
390
+ diagnostics.log({
391
+ collection: collectionSlug,
392
+ data: {
393
+ initializedCount: missingOrderDocs.docs.length,
394
+ orderableFieldName
395
+ },
396
+ flow,
397
+ level: 'info',
398
+ message: 'reorder endpoint initialized missing order keys',
399
+ source: 'reorder-endpoint:initial-migration'
400
+ });
401
+ return respond(200, {
402
+ message: 'initial migration',
403
+ success: true
404
+ });
405
+ }
406
+ export function createReorderPageEndpoint(args) {
407
+ const { collectionSlug, diagnostics, orderableFieldName, parentFieldSlug } = args;
408
+ const snapshotFields = [
409
+ ...SNAPSHOT_FIELDS,
410
+ parentFieldSlug,
411
+ orderableFieldName
412
+ ];
413
+ return {
414
+ handler: async (req)=>{
415
+ const movedIDFromRoute = normalizeID(req.routeParams?.id);
416
+ if (!movedIDFromRoute) {
417
+ return respond(400, {
418
+ message: 'Document ID was not specified.'
419
+ });
420
+ }
421
+ const { body, lastAttempt } = await readBodyFromRequest(req);
422
+ if (!body || body.orderableFieldName !== orderableFieldName || body.docsToMove[0] !== movedIDFromRoute) {
423
+ if (diagnostics.enabled) {
424
+ diagnostics.log({
425
+ collection: collectionSlug,
426
+ data: {
427
+ movedID: movedIDFromRoute,
428
+ rawBody: lastAttempt?.raw ?? null,
429
+ rawBodySource: lastAttempt?.source ?? null
430
+ },
431
+ flow: createFlowID('reorder-endpoint'),
432
+ level: 'warn',
433
+ message: 'reorder endpoint rejected request body',
434
+ source: 'reorder-endpoint:body-rejected'
435
+ });
436
+ }
437
+ return respond(400, {
438
+ message: 'A valid reorder request is required.'
439
+ });
440
+ }
441
+ if (body.target.id === movedIDFromRoute) {
442
+ return respond(400, {
443
+ message: 'Document is already in that position.'
444
+ });
445
+ }
446
+ const movedID = toCollectionID({
447
+ id: movedIDFromRoute,
448
+ collectionSlug,
449
+ req
450
+ });
451
+ const targetID = toCollectionID({
452
+ id: body.target.id,
453
+ collectionSlug,
454
+ req
455
+ });
456
+ const accessError = await assertUpdateAccess({
457
+ id: movedID,
458
+ collectionSlug,
459
+ data: {},
460
+ req
461
+ });
462
+ if (accessError) {
463
+ return accessError;
464
+ }
465
+ const flow = createFlowID('reorder-endpoint');
466
+ const reorderStart = Date.now();
467
+ const hasDrafts = collectionHasDrafts({
468
+ collectionSlug,
469
+ req
470
+ });
471
+ if (!req.context) {
472
+ req.context = {};
473
+ }
474
+ ;
475
+ req.context[pageTreeMoveContextKey] = true;
476
+ req.context[DIAGNOSTICS_FLOW_CONTEXT_KEY] = flow;
477
+ const relatedDocsResult = await req.payload.find({
478
+ collection: collectionSlug,
479
+ depth: 0,
480
+ draft: hasDrafts ? true : undefined,
481
+ limit: 2,
482
+ locale: getRequestedLocale(req),
483
+ overrideAccess: true,
484
+ req,
485
+ where: {
486
+ id: {
487
+ in: [
488
+ movedID,
489
+ targetID
490
+ ]
491
+ }
492
+ }
493
+ });
494
+ const docsByID = new Map(relatedDocsResult.docs.map((doc)=>[
495
+ stringifyDocID(doc.id),
496
+ doc
497
+ ]));
498
+ const movedDoc = docsByID.get(movedIDFromRoute);
499
+ const targetDoc = docsByID.get(body.target.id);
500
+ if (!movedDoc) {
501
+ return respond(404, {
502
+ message: 'Document not found.'
503
+ });
504
+ }
505
+ if (!targetDoc) {
506
+ return respond(400, {
507
+ message: 'Target document not found.'
508
+ });
509
+ }
510
+ const movedParentID = getDocParentID(movedDoc, parentFieldSlug);
511
+ const targetParentID = getDocParentID(targetDoc, parentFieldSlug);
512
+ if (movedParentID !== targetParentID) {
513
+ return respond(400, {
514
+ message: 'Documents can only be reordered within the same parent.'
515
+ });
516
+ }
517
+ const parentScopeWhere = getParentScopeWhere({
518
+ parentFieldSlug,
519
+ parentID: movedParentID === null ? null : toCollectionID({
520
+ id: movedParentID,
521
+ collectionSlug,
522
+ req
523
+ })
524
+ });
525
+ if (!body.target.key) {
526
+ return initializeMissingOrderKeys({
527
+ collectionSlug,
528
+ diagnostics,
529
+ flow,
530
+ hasDrafts,
531
+ orderableFieldName,
532
+ parentScopeWhere,
533
+ req
534
+ });
535
+ }
536
+ const beforeSnapshot = await readMainRowSnapshot({
537
+ id: movedID,
538
+ collectionSlug,
539
+ fields: snapshotFields,
540
+ req
541
+ });
542
+ const backendDraftOrderBefore = diagnostics.enabled ? await readBackendSiblingOrder({
543
+ collectionSlug,
544
+ draft: hasDrafts ? true : undefined,
545
+ orderableFieldName,
546
+ parentScopeWhere,
547
+ req
548
+ }) : null;
549
+ const backendMainOrderBefore = diagnostics.enabled ? await readBackendSiblingOrder({
550
+ collectionSlug,
551
+ draft: false,
552
+ orderableFieldName,
553
+ parentScopeWhere,
554
+ req
555
+ }) : null;
556
+ const adjacentDoc = await req.payload.find({
557
+ collection: collectionSlug,
558
+ depth: 0,
559
+ draft: hasDrafts ? true : undefined,
560
+ limit: 1,
561
+ locale: getRequestedLocale(req),
562
+ overrideAccess: true,
563
+ pagination: false,
564
+ req,
565
+ select: {
566
+ [orderableFieldName]: true
567
+ },
568
+ sort: body.newKeyWillBe === 'greater' ? orderableFieldName : `-${orderableFieldName}`,
569
+ where: combineWhereConstraints([
570
+ {
571
+ [orderableFieldName]: {
572
+ [body.newKeyWillBe === 'greater' ? 'greater_than' : 'less_than']: body.target.key
573
+ }
574
+ },
575
+ parentScopeWhere
576
+ ])
577
+ });
578
+ const adjacentDocKey = getOrderableKey(adjacentDoc.docs[0], orderableFieldName);
579
+ const movedDocKey = getOrderableKey(movedDoc, orderableFieldName);
580
+ const movedSlug = getDiagnosticDocString(movedDoc.slug, getRequestedLocale(req));
581
+ const targetSlug = getDiagnosticDocString(targetDoc.slug, getRequestedLocale(req));
582
+ const movedMainRowKey = typeof beforeSnapshot?.[orderableFieldName] === 'string' && beforeSnapshot[orderableFieldName].length > 0 ? beforeSnapshot[orderableFieldName] : movedDocKey;
583
+ const { orderValues, usedMovedKeyBoundary } = getOrderValuesBetween({
584
+ adjacentDocKey,
585
+ docsToMoveLength: body.docsToMove.length,
586
+ movedBoundaryKey: movedMainRowKey,
587
+ newKeyWillBe: body.newKeyWillBe,
588
+ targetKey: body.target.key
589
+ });
590
+ const orderValue = orderValues[0];
591
+ if (!orderValue) {
592
+ return respond(500, {
593
+ message: 'Could not generate a new order key.'
594
+ });
595
+ }
596
+ if (diagnostics.enabled) {
597
+ diagnostics.log({
598
+ collection: collectionSlug,
599
+ data: {
600
+ adjacentDocKey,
601
+ backendOrderBefore: {
602
+ draft: backendDraftOrderBefore,
603
+ main: backendMainOrderBefore
604
+ },
605
+ frontendOrder: body.frontendOrder ?? null,
606
+ mainRowBefore: getMainRowOrderSnapshot(beforeSnapshot, orderableFieldName),
607
+ movedDocKey,
608
+ movedMainRowKey,
609
+ movedSlug,
610
+ newKeyWillBe: body.newKeyWillBe,
611
+ orderableFieldName,
612
+ orderValue,
613
+ target: {
614
+ slug: targetSlug,
615
+ key: body.target.key
616
+ },
617
+ usedMovedKeyBoundary
618
+ },
619
+ flow,
620
+ level: 'info',
621
+ message: 'reorder endpoint entering: order key update only',
622
+ source: 'reorder-endpoint:enter'
623
+ });
624
+ }
625
+ try {
626
+ const updateResult = await updateOrderValueSilently({
627
+ id: movedID,
628
+ collectionSlug,
629
+ hasDrafts,
630
+ orderableFieldName,
631
+ orderValue,
632
+ req
633
+ });
634
+ if (diagnostics.enabled) {
635
+ const afterSnapshot = await readMainRowSnapshot({
636
+ id: movedID,
637
+ collectionSlug,
638
+ fields: snapshotFields,
639
+ req
640
+ });
641
+ const backendDraftOrderAfter = await readBackendSiblingOrder({
642
+ collectionSlug,
643
+ draft: hasDrafts ? true : undefined,
644
+ orderableFieldName,
645
+ parentScopeWhere,
646
+ req
647
+ });
648
+ const backendMainOrderAfter = await readBackendSiblingOrder({
649
+ collectionSlug,
650
+ draft: false,
651
+ orderableFieldName,
652
+ parentScopeWhere,
653
+ req
654
+ });
655
+ diagnostics.log({
656
+ collection: collectionSlug,
657
+ data: {
658
+ backendOrderAfter: {
659
+ draft: backendDraftOrderAfter,
660
+ main: backendMainOrderAfter
661
+ },
662
+ durMs: Date.now() - reorderStart,
663
+ mainRowAfter: getMainRowOrderSnapshot(afterSnapshot, orderableFieldName),
664
+ movedSlug,
665
+ orderValue,
666
+ updatedDraftVersion: updateResult.updatedDraftVersion
667
+ },
668
+ flow,
669
+ level: 'info',
670
+ message: 'reorder endpoint order key update succeeded',
671
+ source: 'reorder-endpoint:ok'
672
+ });
673
+ }
674
+ } catch (err) {
675
+ const error = err;
676
+ diagnostics.log({
677
+ collection: collectionSlug,
678
+ data: {
679
+ name: error?.name,
680
+ data: error?.data ?? null,
681
+ durMs: Date.now() - reorderStart,
682
+ message: error?.message,
683
+ movedSlug
684
+ },
685
+ flow,
686
+ level: 'error',
687
+ message: `reorder endpoint order key update failed: ${error?.message ?? 'unknown error'}`,
688
+ source: 'reorder-endpoint:error'
689
+ });
690
+ throw err;
691
+ }
692
+ return respond(200, {
693
+ movedID: movedIDFromRoute,
694
+ orderValues,
695
+ success: true
696
+ });
697
+ },
698
+ method: 'post',
699
+ path: '/:id/reorder'
700
+ };
701
+ }
702
+
703
+ //# sourceMappingURL=createReorderPageEndpoint.js.map