payload 3.32.0-internal.f2e77bd → 3.33.0-internal.d1efdd8
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/admin/forms/Form.d.ts +12 -1
- package/dist/admin/forms/Form.d.ts.map +1 -1
- package/dist/admin/forms/Form.js.map +1 -1
- package/dist/admin/functions/index.d.ts +1 -0
- package/dist/admin/functions/index.d.ts.map +1 -1
- package/dist/admin/functions/index.js.map +1 -1
- package/dist/bin/generateImportMap/index.js +3 -3
- package/dist/bin/generateImportMap/index.js.map +1 -1
- package/dist/bin/generateTypes.js +3 -3
- package/dist/bin/generateTypes.js.map +1 -1
- package/dist/collections/config/sanitize.d.ts.map +1 -1
- package/dist/collections/config/sanitize.js.map +1 -1
- package/dist/collections/config/types.d.ts +11 -0
- package/dist/collections/config/types.d.ts.map +1 -1
- package/dist/collections/config/types.js.map +1 -1
- package/dist/config/orderable/fractional-indexing.d.ts +31 -0
- package/dist/config/orderable/fractional-indexing.d.ts.map +1 -0
- package/dist/config/orderable/fractional-indexing.js +295 -0
- package/dist/config/orderable/fractional-indexing.js.map +1 -0
- package/dist/config/orderable/index.d.ts +28 -0
- package/dist/config/orderable/index.d.ts.map +1 -0
- package/dist/config/orderable/index.js +259 -0
- package/dist/config/orderable/index.js.map +1 -0
- package/dist/config/sanitize.d.ts.map +1 -1
- package/dist/config/sanitize.js +3 -0
- package/dist/config/sanitize.js.map +1 -1
- package/dist/database/defaultUpdateJobs.d.ts.map +1 -1
- package/dist/database/defaultUpdateJobs.js +1 -4
- package/dist/database/defaultUpdateJobs.js.map +1 -1
- package/dist/database/types.d.ts +6 -0
- package/dist/database/types.d.ts.map +1 -1
- package/dist/database/types.js.map +1 -1
- package/dist/fields/config/types.d.ts +12 -1
- package/dist/fields/config/types.d.ts.map +1 -1
- package/dist/fields/config/types.js.map +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/queues/config/types/index.d.ts +15 -1
- package/dist/queues/config/types/index.d.ts.map +1 -1
- package/dist/queues/config/types/index.js.map +1 -1
- package/dist/queues/config/types/workflowTypes.d.ts +1 -1
- package/dist/queues/config/types/workflowTypes.d.ts.map +1 -1
- package/dist/queues/config/types/workflowTypes.js.map +1 -1
- package/dist/queues/localAPI.d.ts +12 -1
- package/dist/queues/localAPI.d.ts.map +1 -1
- package/dist/queues/localAPI.js +2 -0
- package/dist/queues/localAPI.js.map +1 -1
- package/dist/queues/operations/runJobs/index.d.ts +15 -2
- package/dist/queues/operations/runJobs/index.d.ts.map +1 -1
- package/dist/queues/operations/runJobs/index.js +30 -4
- package/dist/queues/operations/runJobs/index.js.map +1 -1
- package/dist/queues/operations/runJobs/runJob/getRunTaskFunction.d.ts.map +1 -1
- package/dist/queues/operations/runJobs/runJob/getRunTaskFunction.js +5 -1
- package/dist/queues/operations/runJobs/runJob/getRunTaskFunction.js.map +1 -1
- package/dist/queues/operations/runJobs/runJob/getUpdateJobFunction.d.ts.map +1 -1
- package/dist/queues/operations/runJobs/runJob/getUpdateJobFunction.js +14 -1
- package/dist/queues/operations/runJobs/runJob/getUpdateJobFunction.js.map +1 -1
- package/dist/queues/operations/runJobs/runJob/index.d.ts.map +1 -1
- package/dist/queues/operations/runJobs/runJob/index.js +2 -0
- package/dist/queues/operations/runJobs/runJob/index.js.map +1 -1
- package/dist/queues/utilities/updateJob.d.ts.map +1 -1
- package/dist/queues/utilities/updateJob.js +10 -9
- package/dist/queues/utilities/updateJob.js.map +1 -1
- package/dist/uploads/deleteAssociatedFiles.js +3 -3
- package/dist/uploads/deleteAssociatedFiles.js.map +1 -1
- package/dist/uploads/fileExists.js +2 -2
- package/dist/uploads/fileExists.js.map +1 -1
- package/dist/uploads/generateFileData.d.ts.map +1 -1
- package/dist/uploads/generateFileData.js +4 -5
- package/dist/uploads/generateFileData.js.map +1 -1
- package/dist/uploads/getFileByPath.js +3 -3
- package/dist/uploads/getFileByPath.js.map +1 -1
- package/dist/uploads/getImageSize.js +2 -2
- package/dist/uploads/getImageSize.js.map +1 -1
- package/dist/uploads/imageResizer.js +2 -2
- package/dist/uploads/imageResizer.js.map +1 -1
- package/dist/uploads/saveBufferToFile.js +2 -2
- package/dist/uploads/saveBufferToFile.js.map +1 -1
- package/dist/uploads/tempFile.js +4 -4
- package/dist/uploads/tempFile.js.map +1 -1
- package/dist/uploads/unlinkTempFiles.d.ts.map +1 -1
- package/dist/uploads/unlinkTempFiles.js +2 -4
- package/dist/uploads/unlinkTempFiles.js.map +1 -1
- package/dist/utilities/configToJSONSchema.js +3 -3
- package/dist/utilities/configToJSONSchema.js.map +1 -1
- package/dist/utilities/configToJSONSchema.spec.js +29 -0
- package/dist/utilities/configToJSONSchema.spec.js.map +1 -1
- package/dist/utilities/flattenAllFields.d.ts +5 -0
- package/dist/utilities/flattenAllFields.d.ts.map +1 -1
- package/dist/utilities/flattenAllFields.js +5 -1
- package/dist/utilities/flattenAllFields.js.map +1 -1
- package/package.json +2 -2
- package/dist/queues/utilities/sanitizeUpdateData.d.ts +0 -9
- package/dist/queues/utilities/sanitizeUpdateData.d.ts.map +0 -1
- package/dist/queues/utilities/sanitizeUpdateData.js +0 -25
- package/dist/queues/utilities/sanitizeUpdateData.js.map +0 -1
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
/**
|
|
3
|
+
* THIS FILE IS COPIED FROM:
|
|
4
|
+
* https://github.com/rocicorp/fractional-indexing/blob/main/src/index.js
|
|
5
|
+
*
|
|
6
|
+
* I AM NOT INSTALLING THAT LIBRARY BECAUSE JEST COMPLAINS ABOUT THE ESM MODULE AND THE TESTS FAIL.
|
|
7
|
+
* DO NOT MODIFY IT
|
|
8
|
+
*/ // License: CC0 (no rights reserved).
|
|
9
|
+
// This is based on https://observablehq.com/@dgreensp/implementing-fractional-indexing
|
|
10
|
+
export const BASE_62_DIGITS = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
|
|
11
|
+
// `a` may be empty string, `b` is null or non-empty string.
|
|
12
|
+
// `a < b` lexicographically if `b` is non-null.
|
|
13
|
+
// no trailing zeros allowed.
|
|
14
|
+
// digits is a string such as '0123456789' for base 10. Digits must be in
|
|
15
|
+
// ascending character code order!
|
|
16
|
+
/**
|
|
17
|
+
* @param {string} a
|
|
18
|
+
* @param {string | null | undefined} b
|
|
19
|
+
* @param {string} digits
|
|
20
|
+
* @returns {string}
|
|
21
|
+
*/ function midpoint(a, b, digits) {
|
|
22
|
+
const zero = digits[0];
|
|
23
|
+
if (b != null && a >= b) {
|
|
24
|
+
throw new Error(a + ' >= ' + b);
|
|
25
|
+
}
|
|
26
|
+
if (a.slice(-1) === zero || b && b.slice(-1) === zero) {
|
|
27
|
+
throw new Error('trailing zero');
|
|
28
|
+
}
|
|
29
|
+
if (b) {
|
|
30
|
+
// remove longest common prefix. pad `a` with 0s as we
|
|
31
|
+
// go. note that we don't need to pad `b`, because it can't
|
|
32
|
+
// end before `a` while traversing the common prefix.
|
|
33
|
+
let n = 0;
|
|
34
|
+
while((a[n] || zero) === b[n]){
|
|
35
|
+
n++;
|
|
36
|
+
}
|
|
37
|
+
if (n > 0) {
|
|
38
|
+
return b.slice(0, n) + midpoint(a.slice(n), b.slice(n), digits);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
// first digits (or lack of digit) are different
|
|
42
|
+
const digitA = a ? digits.indexOf(a[0]) : 0;
|
|
43
|
+
const digitB = b != null ? digits.indexOf(b[0]) : digits.length;
|
|
44
|
+
if (digitB - digitA > 1) {
|
|
45
|
+
const midDigit = Math.round(0.5 * (digitA + digitB));
|
|
46
|
+
return digits[midDigit];
|
|
47
|
+
} else {
|
|
48
|
+
// first digits are consecutive
|
|
49
|
+
if (b && b.length > 1) {
|
|
50
|
+
return b.slice(0, 1);
|
|
51
|
+
} else {
|
|
52
|
+
// `b` is null or has length 1 (a single digit).
|
|
53
|
+
// the first digit of `a` is the previous digit to `b`,
|
|
54
|
+
// or 9 if `b` is null.
|
|
55
|
+
// given, for example, midpoint('49', '5'), return
|
|
56
|
+
// '4' + midpoint('9', null), which will become
|
|
57
|
+
// '4' + '9' + midpoint('', null), which is '495'
|
|
58
|
+
return digits[digitA] + midpoint(a.slice(1), null, digits);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* @param {string} int
|
|
64
|
+
* @return {void}
|
|
65
|
+
*/ function validateInteger(int) {
|
|
66
|
+
if (int.length !== getIntegerLength(int[0])) {
|
|
67
|
+
throw new Error('invalid integer part of order key: ' + int);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* @param {string} head
|
|
72
|
+
* @return {number}
|
|
73
|
+
*/ function getIntegerLength(head) {
|
|
74
|
+
if (head >= 'a' && head <= 'z') {
|
|
75
|
+
return head.charCodeAt(0) - 'a'.charCodeAt(0) + 2;
|
|
76
|
+
} else if (head >= 'A' && head <= 'Z') {
|
|
77
|
+
return 'Z'.charCodeAt(0) - head.charCodeAt(0) + 2;
|
|
78
|
+
} else {
|
|
79
|
+
throw new Error('invalid order key head: ' + head);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* @param {string} key
|
|
84
|
+
* @return {string}
|
|
85
|
+
*/ function getIntegerPart(key) {
|
|
86
|
+
const integerPartLength = getIntegerLength(key[0]);
|
|
87
|
+
if (integerPartLength > key.length) {
|
|
88
|
+
throw new Error('invalid order key: ' + key);
|
|
89
|
+
}
|
|
90
|
+
return key.slice(0, integerPartLength);
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* @param {string} key
|
|
94
|
+
* @param {string} digits
|
|
95
|
+
* @return {void}
|
|
96
|
+
*/ function validateOrderKey(key, digits) {
|
|
97
|
+
if (key === 'A' + digits[0].repeat(26)) {
|
|
98
|
+
throw new Error('invalid order key: ' + key);
|
|
99
|
+
}
|
|
100
|
+
// getIntegerPart will throw if the first character is bad,
|
|
101
|
+
// or the key is too short. we'd call it to check these things
|
|
102
|
+
// even if we didn't need the result
|
|
103
|
+
const i = getIntegerPart(key);
|
|
104
|
+
const f = key.slice(i.length);
|
|
105
|
+
if (f.slice(-1) === digits[0]) {
|
|
106
|
+
throw new Error('invalid order key: ' + key);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
// note that this may return null, as there is a largest integer
|
|
110
|
+
/**
|
|
111
|
+
* @param {string} x
|
|
112
|
+
* @param {string} digits
|
|
113
|
+
* @return {string | null}
|
|
114
|
+
*/ function incrementInteger(x, digits) {
|
|
115
|
+
validateInteger(x);
|
|
116
|
+
const [head, ...digs] = x.split('');
|
|
117
|
+
let carry = true;
|
|
118
|
+
for(let i = digs.length - 1; carry && i >= 0; i--){
|
|
119
|
+
const d = digits.indexOf(digs[i]) + 1;
|
|
120
|
+
if (d === digits.length) {
|
|
121
|
+
digs[i] = digits[0];
|
|
122
|
+
} else {
|
|
123
|
+
digs[i] = digits[d];
|
|
124
|
+
carry = false;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
if (carry) {
|
|
128
|
+
if (head === 'Z') {
|
|
129
|
+
return 'a' + digits[0];
|
|
130
|
+
}
|
|
131
|
+
if (head === 'z') {
|
|
132
|
+
return null;
|
|
133
|
+
}
|
|
134
|
+
const h = String.fromCharCode(head.charCodeAt(0) + 1);
|
|
135
|
+
if (h > 'a') {
|
|
136
|
+
digs.push(digits[0]);
|
|
137
|
+
} else {
|
|
138
|
+
digs.pop();
|
|
139
|
+
}
|
|
140
|
+
return h + digs.join('');
|
|
141
|
+
} else {
|
|
142
|
+
return head + digs.join('');
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
// note that this may return null, as there is a smallest integer
|
|
146
|
+
/**
|
|
147
|
+
* @param {string} x
|
|
148
|
+
* @param {string} digits
|
|
149
|
+
* @return {string | null}
|
|
150
|
+
*/ function decrementInteger(x, digits) {
|
|
151
|
+
validateInteger(x);
|
|
152
|
+
const [head, ...digs] = x.split('');
|
|
153
|
+
let borrow = true;
|
|
154
|
+
for(let i = digs.length - 1; borrow && i >= 0; i--){
|
|
155
|
+
const d = digits.indexOf(digs[i]) - 1;
|
|
156
|
+
if (d === -1) {
|
|
157
|
+
digs[i] = digits.slice(-1);
|
|
158
|
+
} else {
|
|
159
|
+
digs[i] = digits[d];
|
|
160
|
+
borrow = false;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
if (borrow) {
|
|
164
|
+
if (head === 'a') {
|
|
165
|
+
return 'Z' + digits.slice(-1);
|
|
166
|
+
}
|
|
167
|
+
if (head === 'A') {
|
|
168
|
+
return null;
|
|
169
|
+
}
|
|
170
|
+
const h = String.fromCharCode(head.charCodeAt(0) - 1);
|
|
171
|
+
if (h < 'Z') {
|
|
172
|
+
digs.push(digits.slice(-1));
|
|
173
|
+
} else {
|
|
174
|
+
digs.pop();
|
|
175
|
+
}
|
|
176
|
+
return h + digs.join('');
|
|
177
|
+
} else {
|
|
178
|
+
return head + digs.join('');
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
// `a` is an order key or null (START).
|
|
182
|
+
// `b` is an order key or null (END).
|
|
183
|
+
// `a < b` lexicographically if both are non-null.
|
|
184
|
+
// digits is a string such as '0123456789' for base 10. Digits must be in
|
|
185
|
+
// ascending character code order!
|
|
186
|
+
/**
|
|
187
|
+
* @param {string | null | undefined} a
|
|
188
|
+
* @param {string | null | undefined} b
|
|
189
|
+
* @param {string=} digits
|
|
190
|
+
* @return {string}
|
|
191
|
+
*/ export function generateKeyBetween(a, b, digits = BASE_62_DIGITS) {
|
|
192
|
+
if (a != null) {
|
|
193
|
+
validateOrderKey(a, digits);
|
|
194
|
+
}
|
|
195
|
+
if (b != null) {
|
|
196
|
+
validateOrderKey(b, digits);
|
|
197
|
+
}
|
|
198
|
+
if (a != null && b != null && a >= b) {
|
|
199
|
+
throw new Error(a + ' >= ' + b);
|
|
200
|
+
}
|
|
201
|
+
if (a == null) {
|
|
202
|
+
if (b == null) {
|
|
203
|
+
return 'a' + digits[0];
|
|
204
|
+
}
|
|
205
|
+
const ib = getIntegerPart(b);
|
|
206
|
+
const fb = b.slice(ib.length);
|
|
207
|
+
if (ib === 'A' + digits[0].repeat(26)) {
|
|
208
|
+
return ib + midpoint('', fb, digits);
|
|
209
|
+
}
|
|
210
|
+
if (ib < b) {
|
|
211
|
+
return ib;
|
|
212
|
+
}
|
|
213
|
+
const res = decrementInteger(ib, digits);
|
|
214
|
+
if (res == null) {
|
|
215
|
+
throw new Error('cannot decrement any more');
|
|
216
|
+
}
|
|
217
|
+
return res;
|
|
218
|
+
}
|
|
219
|
+
if (b == null) {
|
|
220
|
+
const ia = getIntegerPart(a);
|
|
221
|
+
const fa = a.slice(ia.length);
|
|
222
|
+
const i = incrementInteger(ia, digits);
|
|
223
|
+
return i == null ? ia + midpoint(fa, null, digits) : i;
|
|
224
|
+
}
|
|
225
|
+
const ia = getIntegerPart(a);
|
|
226
|
+
const fa = a.slice(ia.length);
|
|
227
|
+
const ib = getIntegerPart(b);
|
|
228
|
+
const fb = b.slice(ib.length);
|
|
229
|
+
if (ia === ib) {
|
|
230
|
+
return ia + midpoint(fa, fb, digits);
|
|
231
|
+
}
|
|
232
|
+
const i = incrementInteger(ia, digits);
|
|
233
|
+
if (i == null) {
|
|
234
|
+
throw new Error('cannot increment any more');
|
|
235
|
+
}
|
|
236
|
+
if (i < b) {
|
|
237
|
+
return i;
|
|
238
|
+
}
|
|
239
|
+
return ia + midpoint(fa, null, digits);
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* same preconditions as generateKeysBetween.
|
|
243
|
+
* n >= 0.
|
|
244
|
+
* Returns an array of n distinct keys in sorted order.
|
|
245
|
+
* If a and b are both null, returns [a0, a1, ...]
|
|
246
|
+
* If one or the other is null, returns consecutive "integer"
|
|
247
|
+
* keys. Otherwise, returns relatively short keys between
|
|
248
|
+
* a and b.
|
|
249
|
+
* @param {string | null | undefined} a
|
|
250
|
+
* @param {string | null | undefined} b
|
|
251
|
+
* @param {number} n
|
|
252
|
+
* @param {string} digits
|
|
253
|
+
* @return {string[]}
|
|
254
|
+
*/ export function generateNKeysBetween(a, b, n, digits = BASE_62_DIGITS) {
|
|
255
|
+
if (n === 0) {
|
|
256
|
+
return [];
|
|
257
|
+
}
|
|
258
|
+
if (n === 1) {
|
|
259
|
+
return [
|
|
260
|
+
generateKeyBetween(a, b, digits)
|
|
261
|
+
];
|
|
262
|
+
}
|
|
263
|
+
if (b == null) {
|
|
264
|
+
let c = generateKeyBetween(a, b, digits);
|
|
265
|
+
const result = [
|
|
266
|
+
c
|
|
267
|
+
];
|
|
268
|
+
for(let i = 0; i < n - 1; i++){
|
|
269
|
+
c = generateKeyBetween(c, b, digits);
|
|
270
|
+
result.push(c);
|
|
271
|
+
}
|
|
272
|
+
return result;
|
|
273
|
+
}
|
|
274
|
+
if (a == null) {
|
|
275
|
+
let c = generateKeyBetween(a, b, digits);
|
|
276
|
+
const result = [
|
|
277
|
+
c
|
|
278
|
+
];
|
|
279
|
+
for(let i = 0; i < n - 1; i++){
|
|
280
|
+
c = generateKeyBetween(a, c, digits);
|
|
281
|
+
result.push(c);
|
|
282
|
+
}
|
|
283
|
+
result.reverse();
|
|
284
|
+
return result;
|
|
285
|
+
}
|
|
286
|
+
const mid = Math.floor(n / 2);
|
|
287
|
+
const c = generateKeyBetween(a, b, digits);
|
|
288
|
+
return [
|
|
289
|
+
...generateNKeysBetween(a, c, mid, digits),
|
|
290
|
+
c,
|
|
291
|
+
...generateNKeysBetween(c, b, n - mid - 1, digits)
|
|
292
|
+
];
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
//# sourceMappingURL=fractional-indexing.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/config/orderable/fractional-indexing.js"],"sourcesContent":["// @ts-check\n\n/**\n * THIS FILE IS COPIED FROM:\n * https://github.com/rocicorp/fractional-indexing/blob/main/src/index.js\n *\n * I AM NOT INSTALLING THAT LIBRARY BECAUSE JEST COMPLAINS ABOUT THE ESM MODULE AND THE TESTS FAIL.\n * DO NOT MODIFY IT\n */\n\n// License: CC0 (no rights reserved).\n\n// This is based on https://observablehq.com/@dgreensp/implementing-fractional-indexing\n\nexport const BASE_62_DIGITS = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'\n\n// `a` may be empty string, `b` is null or non-empty string.\n// `a < b` lexicographically if `b` is non-null.\n// no trailing zeros allowed.\n// digits is a string such as '0123456789' for base 10. Digits must be in\n// ascending character code order!\n/**\n * @param {string} a\n * @param {string | null | undefined} b\n * @param {string} digits\n * @returns {string}\n */\nfunction midpoint(a, b, digits) {\n const zero = digits[0]\n if (b != null && a >= b) {\n throw new Error(a + ' >= ' + b)\n }\n if (a.slice(-1) === zero || (b && b.slice(-1) === zero)) {\n throw new Error('trailing zero')\n }\n if (b) {\n // remove longest common prefix. pad `a` with 0s as we\n // go. note that we don't need to pad `b`, because it can't\n // end before `a` while traversing the common prefix.\n let n = 0\n while ((a[n] || zero) === b[n]) {\n n++\n }\n if (n > 0) {\n return b.slice(0, n) + midpoint(a.slice(n), b.slice(n), digits)\n }\n }\n // first digits (or lack of digit) are different\n const digitA = a ? digits.indexOf(a[0]) : 0\n const digitB = b != null ? digits.indexOf(b[0]) : digits.length\n if (digitB - digitA > 1) {\n const midDigit = Math.round(0.5 * (digitA + digitB))\n return digits[midDigit]\n } else {\n // first digits are consecutive\n if (b && b.length > 1) {\n return b.slice(0, 1)\n } else {\n // `b` is null or has length 1 (a single digit).\n // the first digit of `a` is the previous digit to `b`,\n // or 9 if `b` is null.\n // given, for example, midpoint('49', '5'), return\n // '4' + midpoint('9', null), which will become\n // '4' + '9' + midpoint('', null), which is '495'\n return digits[digitA] + midpoint(a.slice(1), null, digits)\n }\n }\n}\n\n/**\n * @param {string} int\n * @return {void}\n */\n\nfunction validateInteger(int) {\n if (int.length !== getIntegerLength(int[0])) {\n throw new Error('invalid integer part of order key: ' + int)\n }\n}\n\n/**\n * @param {string} head\n * @return {number}\n */\n\nfunction getIntegerLength(head) {\n if (head >= 'a' && head <= 'z') {\n return head.charCodeAt(0) - 'a'.charCodeAt(0) + 2\n } else if (head >= 'A' && head <= 'Z') {\n return 'Z'.charCodeAt(0) - head.charCodeAt(0) + 2\n } else {\n throw new Error('invalid order key head: ' + head)\n }\n}\n\n/**\n * @param {string} key\n * @return {string}\n */\n\nfunction getIntegerPart(key) {\n const integerPartLength = getIntegerLength(key[0])\n if (integerPartLength > key.length) {\n throw new Error('invalid order key: ' + key)\n }\n return key.slice(0, integerPartLength)\n}\n\n/**\n * @param {string} key\n * @param {string} digits\n * @return {void}\n */\n\nfunction validateOrderKey(key, digits) {\n if (key === 'A' + digits[0].repeat(26)) {\n throw new Error('invalid order key: ' + key)\n }\n // getIntegerPart will throw if the first character is bad,\n // or the key is too short. we'd call it to check these things\n // even if we didn't need the result\n const i = getIntegerPart(key)\n const f = key.slice(i.length)\n if (f.slice(-1) === digits[0]) {\n throw new Error('invalid order key: ' + key)\n }\n}\n\n// note that this may return null, as there is a largest integer\n/**\n * @param {string} x\n * @param {string} digits\n * @return {string | null}\n */\nfunction incrementInteger(x, digits) {\n validateInteger(x)\n const [head, ...digs] = x.split('')\n let carry = true\n for (let i = digs.length - 1; carry && i >= 0; i--) {\n const d = digits.indexOf(digs[i]) + 1\n if (d === digits.length) {\n digs[i] = digits[0]\n } else {\n digs[i] = digits[d]\n carry = false\n }\n }\n if (carry) {\n if (head === 'Z') {\n return 'a' + digits[0]\n }\n if (head === 'z') {\n return null\n }\n const h = String.fromCharCode(head.charCodeAt(0) + 1)\n if (h > 'a') {\n digs.push(digits[0])\n } else {\n digs.pop()\n }\n return h + digs.join('')\n } else {\n return head + digs.join('')\n }\n}\n\n// note that this may return null, as there is a smallest integer\n/**\n * @param {string} x\n * @param {string} digits\n * @return {string | null}\n */\n\nfunction decrementInteger(x, digits) {\n validateInteger(x)\n const [head, ...digs] = x.split('')\n let borrow = true\n for (let i = digs.length - 1; borrow && i >= 0; i--) {\n const d = digits.indexOf(digs[i]) - 1\n if (d === -1) {\n digs[i] = digits.slice(-1)\n } else {\n digs[i] = digits[d]\n borrow = false\n }\n }\n if (borrow) {\n if (head === 'a') {\n return 'Z' + digits.slice(-1)\n }\n if (head === 'A') {\n return null\n }\n const h = String.fromCharCode(head.charCodeAt(0) - 1)\n if (h < 'Z') {\n digs.push(digits.slice(-1))\n } else {\n digs.pop()\n }\n return h + digs.join('')\n } else {\n return head + digs.join('')\n }\n}\n\n// `a` is an order key or null (START).\n// `b` is an order key or null (END).\n// `a < b` lexicographically if both are non-null.\n// digits is a string such as '0123456789' for base 10. Digits must be in\n// ascending character code order!\n/**\n * @param {string | null | undefined} a\n * @param {string | null | undefined} b\n * @param {string=} digits\n * @return {string}\n */\nexport function generateKeyBetween(a, b, digits = BASE_62_DIGITS) {\n if (a != null) {\n validateOrderKey(a, digits)\n }\n if (b != null) {\n validateOrderKey(b, digits)\n }\n if (a != null && b != null && a >= b) {\n throw new Error(a + ' >= ' + b)\n }\n if (a == null) {\n if (b == null) {\n return 'a' + digits[0]\n }\n\n const ib = getIntegerPart(b)\n const fb = b.slice(ib.length)\n if (ib === 'A' + digits[0].repeat(26)) {\n return ib + midpoint('', fb, digits)\n }\n if (ib < b) {\n return ib\n }\n const res = decrementInteger(ib, digits)\n if (res == null) {\n throw new Error('cannot decrement any more')\n }\n return res\n }\n\n if (b == null) {\n const ia = getIntegerPart(a)\n const fa = a.slice(ia.length)\n const i = incrementInteger(ia, digits)\n return i == null ? ia + midpoint(fa, null, digits) : i\n }\n\n const ia = getIntegerPart(a)\n const fa = a.slice(ia.length)\n const ib = getIntegerPart(b)\n const fb = b.slice(ib.length)\n if (ia === ib) {\n return ia + midpoint(fa, fb, digits)\n }\n const i = incrementInteger(ia, digits)\n if (i == null) {\n throw new Error('cannot increment any more')\n }\n if (i < b) {\n return i\n }\n return ia + midpoint(fa, null, digits)\n}\n\n/**\n * same preconditions as generateKeysBetween.\n * n >= 0.\n * Returns an array of n distinct keys in sorted order.\n * If a and b are both null, returns [a0, a1, ...]\n * If one or the other is null, returns consecutive \"integer\"\n * keys. Otherwise, returns relatively short keys between\n * a and b.\n * @param {string | null | undefined} a\n * @param {string | null | undefined} b\n * @param {number} n\n * @param {string} digits\n * @return {string[]}\n */\nexport function generateNKeysBetween(a, b, n, digits = BASE_62_DIGITS) {\n if (n === 0) {\n return []\n }\n if (n === 1) {\n return [generateKeyBetween(a, b, digits)]\n }\n if (b == null) {\n let c = generateKeyBetween(a, b, digits)\n const result = [c]\n for (let i = 0; i < n - 1; i++) {\n c = generateKeyBetween(c, b, digits)\n result.push(c)\n }\n return result\n }\n if (a == null) {\n let c = generateKeyBetween(a, b, digits)\n const result = [c]\n for (let i = 0; i < n - 1; i++) {\n c = generateKeyBetween(a, c, digits)\n result.push(c)\n }\n result.reverse()\n return result\n }\n const mid = Math.floor(n / 2)\n const c = generateKeyBetween(a, b, digits)\n return [\n ...generateNKeysBetween(a, c, mid, digits),\n c,\n ...generateNKeysBetween(c, b, n - mid - 1, digits),\n ]\n}\n"],"names":["BASE_62_DIGITS","midpoint","a","b","digits","zero","Error","slice","n","digitA","indexOf","digitB","length","midDigit","Math","round","validateInteger","int","getIntegerLength","head","charCodeAt","getIntegerPart","key","integerPartLength","validateOrderKey","repeat","i","f","incrementInteger","x","digs","split","carry","d","h","String","fromCharCode","push","pop","join","decrementInteger","borrow","generateKeyBetween","ib","fb","res","ia","fa","generateNKeysBetween","c","result","reverse","mid","floor"],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { CollectionConfig } from '../../collections/config/types.js';
|
|
2
|
+
import type { SanitizedConfig } from '../types.js';
|
|
3
|
+
/**
|
|
4
|
+
* This function creates:
|
|
5
|
+
* - N fields per collection, named `_order` or `_<collection>_<joinField>_order`
|
|
6
|
+
* - 1 hook per collection
|
|
7
|
+
* - 1 endpoint per app
|
|
8
|
+
*
|
|
9
|
+
* Also, if collection.defaultSort or joinField.defaultSort is not set, it will be set to the orderable field.
|
|
10
|
+
*/
|
|
11
|
+
export declare const setupOrderable: (config: SanitizedConfig) => void;
|
|
12
|
+
export declare const addOrderableFieldsAndHook: (collection: CollectionConfig, orderableFieldNames: string[]) => void;
|
|
13
|
+
/**
|
|
14
|
+
* The body of the reorder endpoint.
|
|
15
|
+
* @internal
|
|
16
|
+
*/
|
|
17
|
+
export type OrderableEndpointBody = {
|
|
18
|
+
collectionSlug: string;
|
|
19
|
+
docsToMove: string[];
|
|
20
|
+
newKeyWillBe: 'greater' | 'less';
|
|
21
|
+
orderableFieldName: string;
|
|
22
|
+
target: {
|
|
23
|
+
id: string;
|
|
24
|
+
key: string;
|
|
25
|
+
};
|
|
26
|
+
};
|
|
27
|
+
export declare const addOrderableEndpoint: (config: SanitizedConfig) => void;
|
|
28
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/config/orderable/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAoB,gBAAgB,EAAE,MAAM,mCAAmC,CAAA;AAE3F,OAAO,KAAK,EAA4B,eAAe,EAAE,MAAM,aAAa,CAAA;AAM5E;;;;;;;GAOG;AACH,eAAO,MAAM,cAAc,WAAY,eAAe,SAkDrD,CAAA;AAED,eAAO,MAAM,yBAAyB,eACxB,gBAAgB,uBACP,MAAM,EAAE,SA+D9B,CAAA;AAED;;;GAGG;AACH,MAAM,MAAM,qBAAqB,GAAG;IAClC,cAAc,EAAE,MAAM,CAAA;IACtB,UAAU,EAAE,MAAM,EAAE,CAAA;IACpB,YAAY,EAAE,SAAS,GAAG,MAAM,CAAA;IAChC,kBAAkB,EAAE,MAAM,CAAA;IAC1B,MAAM,EAAE;QACN,EAAE,EAAE,MAAM,CAAA;QACV,GAAG,EAAE,MAAM,CAAA;KACZ,CAAA;CACF,CAAA;AAED,eAAO,MAAM,oBAAoB,WAAY,eAAe,SA+H3D,CAAA"}
|
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
import executeAccess from '../../auth/executeAccess.js';
|
|
2
|
+
import { traverseFields } from '../../utilities/traverseFields.js';
|
|
3
|
+
import { generateKeyBetween, generateNKeysBetween } from './fractional-indexing.js';
|
|
4
|
+
/**
|
|
5
|
+
* This function creates:
|
|
6
|
+
* - N fields per collection, named `_order` or `_<collection>_<joinField>_order`
|
|
7
|
+
* - 1 hook per collection
|
|
8
|
+
* - 1 endpoint per app
|
|
9
|
+
*
|
|
10
|
+
* Also, if collection.defaultSort or joinField.defaultSort is not set, it will be set to the orderable field.
|
|
11
|
+
*/ export const setupOrderable = (config)=>{
|
|
12
|
+
const fieldsToAdd = new Map();
|
|
13
|
+
config.collections.forEach((collection)=>{
|
|
14
|
+
if (collection.orderable) {
|
|
15
|
+
const currentFields = fieldsToAdd.get(collection) || [];
|
|
16
|
+
fieldsToAdd.set(collection, [
|
|
17
|
+
...currentFields,
|
|
18
|
+
'_order'
|
|
19
|
+
]);
|
|
20
|
+
collection.defaultSort = collection.defaultSort ?? '_order';
|
|
21
|
+
}
|
|
22
|
+
traverseFields({
|
|
23
|
+
callback: ({ field, parentRef, ref })=>{
|
|
24
|
+
if (field.type === 'array' || field.type === 'blocks') {
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
if (field.type === 'group' || field.type === 'tab') {
|
|
28
|
+
// @ts-expect-error ref is untyped
|
|
29
|
+
const parentPrefix = parentRef?.prefix ? `${parentRef.prefix}_` : '';
|
|
30
|
+
// @ts-expect-error ref is untyped
|
|
31
|
+
ref.prefix = `${parentPrefix}${field.name}`;
|
|
32
|
+
}
|
|
33
|
+
if (field.type === 'join' && field.orderable === true) {
|
|
34
|
+
if (Array.isArray(field.collection)) {
|
|
35
|
+
throw new Error('Orderable joins must target a single collection');
|
|
36
|
+
}
|
|
37
|
+
const relationshipCollection = config.collections.find((c)=>c.slug === field.collection);
|
|
38
|
+
if (!relationshipCollection) {
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
field.defaultSort = field.defaultSort ?? `_${field.collection}_${field.name}_order`;
|
|
42
|
+
const currentFields = fieldsToAdd.get(relationshipCollection) || [];
|
|
43
|
+
// @ts-expect-error ref is untyped
|
|
44
|
+
const prefix = parentRef?.prefix ? `${parentRef.prefix}_` : '';
|
|
45
|
+
fieldsToAdd.set(relationshipCollection, [
|
|
46
|
+
...currentFields,
|
|
47
|
+
`_${field.collection}_${prefix}${field.name}_order`
|
|
48
|
+
]);
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
fields: collection.fields
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
Array.from(fieldsToAdd.entries()).forEach(([collection, orderableFields])=>{
|
|
55
|
+
addOrderableFieldsAndHook(collection, orderableFields);
|
|
56
|
+
});
|
|
57
|
+
if (fieldsToAdd.size > 0) {
|
|
58
|
+
addOrderableEndpoint(config);
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
export const addOrderableFieldsAndHook = (collection, orderableFieldNames)=>{
|
|
62
|
+
// 1. Add field
|
|
63
|
+
orderableFieldNames.forEach((orderableFieldName)=>{
|
|
64
|
+
const orderField = {
|
|
65
|
+
name: orderableFieldName,
|
|
66
|
+
type: 'text',
|
|
67
|
+
admin: {
|
|
68
|
+
disableBulkEdit: true,
|
|
69
|
+
disabled: true,
|
|
70
|
+
disableListColumn: true,
|
|
71
|
+
disableListFilter: true,
|
|
72
|
+
hidden: true,
|
|
73
|
+
readOnly: true
|
|
74
|
+
},
|
|
75
|
+
index: true,
|
|
76
|
+
required: true,
|
|
77
|
+
// override the schema to make order fields optional for payload.create()
|
|
78
|
+
typescriptSchema: [
|
|
79
|
+
()=>({
|
|
80
|
+
type: 'string',
|
|
81
|
+
required: false
|
|
82
|
+
})
|
|
83
|
+
],
|
|
84
|
+
unique: true
|
|
85
|
+
};
|
|
86
|
+
collection.fields.unshift(orderField);
|
|
87
|
+
});
|
|
88
|
+
// 2. Add hook
|
|
89
|
+
if (!collection.hooks) {
|
|
90
|
+
collection.hooks = {};
|
|
91
|
+
}
|
|
92
|
+
if (!collection.hooks.beforeChange) {
|
|
93
|
+
collection.hooks.beforeChange = [];
|
|
94
|
+
}
|
|
95
|
+
const orderBeforeChangeHook = async ({ data, operation, req })=>{
|
|
96
|
+
// Only set _order on create, not on update (unless explicitly provided)
|
|
97
|
+
if (operation === 'create') {
|
|
98
|
+
for (const orderableFieldName of orderableFieldNames){
|
|
99
|
+
if (!data[orderableFieldName]) {
|
|
100
|
+
const lastDoc = await req.payload.find({
|
|
101
|
+
collection: collection.slug,
|
|
102
|
+
depth: 0,
|
|
103
|
+
limit: 1,
|
|
104
|
+
pagination: false,
|
|
105
|
+
req,
|
|
106
|
+
select: {
|
|
107
|
+
[orderableFieldName]: true
|
|
108
|
+
},
|
|
109
|
+
sort: `-${orderableFieldName}`
|
|
110
|
+
});
|
|
111
|
+
const lastOrderValue = lastDoc.docs[0]?.[orderableFieldName] || null;
|
|
112
|
+
data[orderableFieldName] = generateKeyBetween(lastOrderValue, null);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
return data;
|
|
117
|
+
};
|
|
118
|
+
collection.hooks.beforeChange.push(orderBeforeChangeHook);
|
|
119
|
+
};
|
|
120
|
+
export const addOrderableEndpoint = (config)=>{
|
|
121
|
+
// 3. Add endpoint
|
|
122
|
+
const reorderHandler = async (req)=>{
|
|
123
|
+
const body = await req.json?.();
|
|
124
|
+
const { collectionSlug, docsToMove, newKeyWillBe, orderableFieldName, target } = body;
|
|
125
|
+
if (!Array.isArray(docsToMove) || docsToMove.length === 0) {
|
|
126
|
+
return new Response(JSON.stringify({
|
|
127
|
+
error: 'docsToMove must be a non-empty array'
|
|
128
|
+
}), {
|
|
129
|
+
headers: {
|
|
130
|
+
'Content-Type': 'application/json'
|
|
131
|
+
},
|
|
132
|
+
status: 400
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
if (typeof target !== 'object' || typeof target.id !== 'string' || typeof target.key !== 'string') {
|
|
136
|
+
return new Response(JSON.stringify({
|
|
137
|
+
error: 'target must be an object with id and key'
|
|
138
|
+
}), {
|
|
139
|
+
headers: {
|
|
140
|
+
'Content-Type': 'application/json'
|
|
141
|
+
},
|
|
142
|
+
status: 400
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
if (newKeyWillBe !== 'greater' && newKeyWillBe !== 'less') {
|
|
146
|
+
return new Response(JSON.stringify({
|
|
147
|
+
error: 'newKeyWillBe must be "greater" or "less"'
|
|
148
|
+
}), {
|
|
149
|
+
headers: {
|
|
150
|
+
'Content-Type': 'application/json'
|
|
151
|
+
},
|
|
152
|
+
status: 400
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
const collection = config.collections.find((c)=>c.slug === collectionSlug);
|
|
156
|
+
if (!collection) {
|
|
157
|
+
return new Response(JSON.stringify({
|
|
158
|
+
error: `Collection ${collectionSlug} not found`
|
|
159
|
+
}), {
|
|
160
|
+
headers: {
|
|
161
|
+
'Content-Type': 'application/json'
|
|
162
|
+
},
|
|
163
|
+
status: 400
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
if (typeof orderableFieldName !== 'string') {
|
|
167
|
+
return new Response(JSON.stringify({
|
|
168
|
+
error: 'orderableFieldName must be a string'
|
|
169
|
+
}), {
|
|
170
|
+
headers: {
|
|
171
|
+
'Content-Type': 'application/json'
|
|
172
|
+
},
|
|
173
|
+
status: 400
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
// Prevent reordering if user doesn't have editing permissions
|
|
177
|
+
if (collection.access?.update) {
|
|
178
|
+
await executeAccess({
|
|
179
|
+
// Currently only one doc can be moved at a time. We should review this if we want to allow
|
|
180
|
+
// multiple docs to be moved at once in the future.
|
|
181
|
+
id: docsToMove[0],
|
|
182
|
+
data: {},
|
|
183
|
+
req
|
|
184
|
+
}, collection.access.update);
|
|
185
|
+
}
|
|
186
|
+
const targetId = target.id;
|
|
187
|
+
let targetKey = target.key;
|
|
188
|
+
// If targetKey = pending, we need to find its current key.
|
|
189
|
+
// This can only happen if the user reorders rows quickly with a slow connection.
|
|
190
|
+
if (targetKey === 'pending') {
|
|
191
|
+
const beforeDoc = await req.payload.findByID({
|
|
192
|
+
id: targetId,
|
|
193
|
+
collection: collection.slug,
|
|
194
|
+
depth: 0,
|
|
195
|
+
select: {
|
|
196
|
+
[orderableFieldName]: true
|
|
197
|
+
}
|
|
198
|
+
});
|
|
199
|
+
targetKey = beforeDoc?.[orderableFieldName] || null;
|
|
200
|
+
}
|
|
201
|
+
// The reason the endpoint does not receive this docId as an argument is that there
|
|
202
|
+
// are situations where the user may not see or know what the next or previous one is. For
|
|
203
|
+
// example, access control restrictions, if docBefore is the last one on the page, etc.
|
|
204
|
+
const adjacentDoc = await req.payload.find({
|
|
205
|
+
collection: collection.slug,
|
|
206
|
+
depth: 0,
|
|
207
|
+
limit: 1,
|
|
208
|
+
pagination: false,
|
|
209
|
+
select: {
|
|
210
|
+
[orderableFieldName]: true
|
|
211
|
+
},
|
|
212
|
+
sort: newKeyWillBe === 'greater' ? orderableFieldName : `-${orderableFieldName}`,
|
|
213
|
+
where: {
|
|
214
|
+
[orderableFieldName]: {
|
|
215
|
+
[newKeyWillBe === 'greater' ? 'greater_than' : 'less_than']: targetKey
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
});
|
|
219
|
+
const adjacentDocKey = adjacentDoc.docs?.[0]?.[orderableFieldName] || null;
|
|
220
|
+
// Currently N (= docsToMove.length) is always 1. Maybe in the future we will
|
|
221
|
+
// allow dragging and reordering multiple documents at once via the UI.
|
|
222
|
+
const orderValues = newKeyWillBe === 'greater' ? generateNKeysBetween(targetKey, adjacentDocKey, docsToMove.length) : generateNKeysBetween(adjacentDocKey, targetKey, docsToMove.length);
|
|
223
|
+
// Update each document with its new order value
|
|
224
|
+
for (const [index, id] of docsToMove.entries()){
|
|
225
|
+
await req.payload.update({
|
|
226
|
+
id,
|
|
227
|
+
collection: collection.slug,
|
|
228
|
+
data: {
|
|
229
|
+
[orderableFieldName]: orderValues[index]
|
|
230
|
+
},
|
|
231
|
+
depth: 0,
|
|
232
|
+
req,
|
|
233
|
+
select: {
|
|
234
|
+
id: true
|
|
235
|
+
}
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
return new Response(JSON.stringify({
|
|
239
|
+
orderValues,
|
|
240
|
+
success: true
|
|
241
|
+
}), {
|
|
242
|
+
headers: {
|
|
243
|
+
'Content-Type': 'application/json'
|
|
244
|
+
},
|
|
245
|
+
status: 200
|
|
246
|
+
});
|
|
247
|
+
};
|
|
248
|
+
const reorderEndpoint = {
|
|
249
|
+
handler: reorderHandler,
|
|
250
|
+
method: 'post',
|
|
251
|
+
path: '/reorder'
|
|
252
|
+
};
|
|
253
|
+
if (!config.endpoints) {
|
|
254
|
+
config.endpoints = [];
|
|
255
|
+
}
|
|
256
|
+
config.endpoints.push(reorderEndpoint);
|
|
257
|
+
};
|
|
258
|
+
|
|
259
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/config/orderable/index.ts"],"sourcesContent":["import 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 { 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 Error('Orderable joins must target a single collection')\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 disableListColumn: true,\n disableListFilter: true,\n hidden: true,\n readOnly: true,\n },\n index: true,\n required: true,\n // override the schema to make order fields optional for payload.create()\n typescriptSchema: [\n () => ({\n type: 'string',\n required: false,\n }),\n ],\n unique: 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, operation, req }) => {\n // Only set _order on create, not on update (unless explicitly provided)\n if (operation === 'create') {\n for (const orderableFieldName of orderableFieldNames) {\n if (!data[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 })\n\n const lastOrderValue = lastDoc.docs[0]?.[orderableFieldName] || null\n data[orderableFieldName] = generateKeyBetween(lastOrderValue, null)\n }\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 (\n typeof target !== 'object' ||\n typeof target.id !== 'string' ||\n typeof target.key !== 'string'\n ) {\n return new Response(JSON.stringify({ error: 'target must be an object with id and key' }), {\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 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 select: { id: true },\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 config.endpoints.push(reorderEndpoint)\n}\n"],"names":["executeAccess","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","Error","relationshipCollection","find","c","slug","fields","from","entries","orderableFields","addOrderableFieldsAndHook","size","addOrderableEndpoint","orderableFieldNames","orderableFieldName","orderField","admin","disableBulkEdit","disabled","disableListColumn","disableListFilter","hidden","readOnly","index","required","typescriptSchema","unique","unshift","hooks","beforeChange","orderBeforeChangeHook","data","operation","req","lastDoc","payload","depth","limit","pagination","select","sort","lastOrderValue","docs","push","reorderHandler","body","json","collectionSlug","docsToMove","newKeyWillBe","target","length","Response","JSON","stringify","error","headers","status","id","key","access","update","targetId","targetKey","beforeDoc","findByID","adjacentDoc","where","adjacentDocKey","orderValues","success","reorderEndpoint","handler","method","path","endpoints"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sanitize.d.ts","sourceRoot":"","sources":["../../src/config/sanitize.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EACV,MAAM,EAGN,eAAe,EAEhB,MAAM,YAAY,CAAA;
|
|
1
|
+
{"version":3,"file":"sanitize.d.ts","sourceRoot":"","sources":["../../src/config/sanitize.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EACV,MAAM,EAGN,eAAe,EAEhB,MAAM,YAAY,CAAA;AA8FnB,eAAO,MAAM,cAAc,mBAA0B,MAAM,KAAG,OAAO,CAAC,eAAe,CAiTpF,CAAA"}
|