payload 4.0.0-internal.cd69eef → 4.0.0-internal.d1cc1d3

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 (279) hide show
  1. package/dist/admin/RichText.d.ts +1 -1
  2. package/dist/admin/RichText.d.ts.map +1 -1
  3. package/dist/admin/RichText.js.map +1 -1
  4. package/dist/admin/functions/index.d.ts +10 -8
  5. package/dist/admin/functions/index.d.ts.map +1 -1
  6. package/dist/admin/functions/index.js.map +1 -1
  7. package/dist/admin/types.d.ts +2 -2
  8. package/dist/admin/types.d.ts.map +1 -1
  9. package/dist/admin/types.js.map +1 -1
  10. package/dist/auth/endpoints/login.d.ts.map +1 -1
  11. package/dist/auth/endpoints/login.js +2 -11
  12. package/dist/auth/endpoints/login.js.map +1 -1
  13. package/dist/auth/loginWithCookie.d.ts +33 -0
  14. package/dist/auth/loginWithCookie.d.ts.map +1 -0
  15. package/dist/auth/loginWithCookie.js +34 -0
  16. package/dist/auth/loginWithCookie.js.map +1 -0
  17. package/dist/auth/serverFunctions/cookies.d.ts +47 -0
  18. package/dist/auth/serverFunctions/cookies.d.ts.map +1 -0
  19. package/dist/auth/serverFunctions/cookies.js +52 -0
  20. package/dist/auth/serverFunctions/cookies.js.map +1 -0
  21. package/dist/auth/serverFunctions/login.d.ts +29 -0
  22. package/dist/auth/serverFunctions/login.d.ts.map +1 -0
  23. package/dist/auth/serverFunctions/login.js +63 -0
  24. package/dist/auth/serverFunctions/login.js.map +1 -0
  25. package/dist/auth/serverFunctions/logout.d.ts +17 -0
  26. package/dist/auth/serverFunctions/logout.d.ts.map +1 -0
  27. package/dist/auth/serverFunctions/logout.js +58 -0
  28. package/dist/auth/serverFunctions/logout.js.map +1 -0
  29. package/dist/auth/serverFunctions/refresh.d.ts +17 -0
  30. package/dist/auth/serverFunctions/refresh.d.ts.map +1 -0
  31. package/dist/auth/serverFunctions/refresh.js +61 -0
  32. package/dist/auth/serverFunctions/refresh.js.map +1 -0
  33. package/dist/collections/config/client.d.ts +2 -3
  34. package/dist/collections/config/client.d.ts.map +1 -1
  35. package/dist/collections/config/client.js +5 -7
  36. package/dist/collections/config/client.js.map +1 -1
  37. package/dist/collections/config/defaults.d.ts.map +1 -1
  38. package/dist/collections/config/defaults.js +1 -0
  39. package/dist/collections/config/defaults.js.map +1 -1
  40. package/dist/collections/config/sanitize.d.ts +3 -8
  41. package/dist/collections/config/sanitize.d.ts.map +1 -1
  42. package/dist/collections/config/sanitize.js +2 -6
  43. package/dist/collections/config/sanitize.js.map +1 -1
  44. package/dist/collections/config/types.d.ts +1 -1
  45. package/dist/collections/config/types.d.ts.map +1 -1
  46. package/dist/collections/config/types.js.map +1 -1
  47. package/dist/collections/config/useAsTitle.spec.js +27 -27
  48. package/dist/collections/config/useAsTitle.spec.js.map +1 -1
  49. package/dist/collections/operations/create.d.ts.map +1 -1
  50. package/dist/collections/operations/create.js +10 -0
  51. package/dist/collections/operations/create.js.map +1 -1
  52. package/dist/collections/operations/restoreVersion.d.ts.map +1 -1
  53. package/dist/collections/operations/restoreVersion.js +7 -4
  54. package/dist/collections/operations/restoreVersion.js.map +1 -1
  55. package/dist/collections/operations/updateByID.js +1 -0
  56. package/dist/collections/operations/updateByID.js.map +1 -1
  57. package/dist/config/build.js +1 -1
  58. package/dist/config/build.js.map +1 -1
  59. package/dist/config/defaults.d.ts.map +1 -1
  60. package/dist/config/defaults.js +5 -2
  61. package/dist/config/defaults.js.map +1 -1
  62. package/dist/config/orderable/index.d.ts +1 -1
  63. package/dist/config/orderable/index.d.ts.map +1 -1
  64. package/dist/config/orderable/index.js +2 -2
  65. package/dist/config/orderable/index.js.map +1 -1
  66. package/dist/config/sanitize.d.ts +1 -1
  67. package/dist/config/sanitize.d.ts.map +1 -1
  68. package/dist/config/sanitize.js +33 -40
  69. package/dist/config/sanitize.js.map +1 -1
  70. package/dist/config/types.d.ts +1 -1
  71. package/dist/config/types.js.map +1 -1
  72. package/dist/database/createDatabaseAdapter.d.ts +1 -1
  73. package/dist/database/createDatabaseAdapter.d.ts.map +1 -1
  74. package/dist/database/createDatabaseAdapter.js +0 -2
  75. package/dist/database/createDatabaseAdapter.js.map +1 -1
  76. package/dist/database/types.d.ts +6 -0
  77. package/dist/database/types.d.ts.map +1 -1
  78. package/dist/database/types.js.map +1 -1
  79. package/dist/exports/auth.d.ts +5 -0
  80. package/dist/exports/auth.d.ts.map +1 -0
  81. package/dist/exports/auth.js +6 -0
  82. package/dist/exports/auth.js.map +1 -0
  83. package/dist/exports/internal.d.ts +2 -0
  84. package/dist/exports/internal.d.ts.map +1 -1
  85. package/dist/exports/internal.js +3 -1
  86. package/dist/exports/internal.js.map +1 -1
  87. package/dist/fields/baseFields/slug/duplicateContext.d.ts +11 -0
  88. package/dist/fields/baseFields/slug/duplicateContext.d.ts.map +1 -0
  89. package/dist/fields/baseFields/slug/duplicateContext.js +21 -0
  90. package/dist/fields/baseFields/slug/duplicateContext.js.map +1 -0
  91. package/dist/fields/baseFields/slug/fillEmptyLocalizedSlugs.d.ts +22 -0
  92. package/dist/fields/baseFields/slug/fillEmptyLocalizedSlugs.d.ts.map +1 -0
  93. package/dist/fields/baseFields/slug/fillEmptyLocalizedSlugs.js +63 -0
  94. package/dist/fields/baseFields/slug/fillEmptyLocalizedSlugs.js.map +1 -0
  95. package/dist/fields/baseFields/slug/generateSlug.d.ts +13 -8
  96. package/dist/fields/baseFields/slug/generateSlug.d.ts.map +1 -1
  97. package/dist/fields/baseFields/slug/generateSlug.js +98 -45
  98. package/dist/fields/baseFields/slug/generateSlug.js.map +1 -1
  99. package/dist/fields/baseFields/slug/generateSlugBeforeDuplicate.d.ts +18 -0
  100. package/dist/fields/baseFields/slug/generateSlugBeforeDuplicate.d.ts.map +1 -0
  101. package/dist/fields/baseFields/slug/generateSlugBeforeDuplicate.js +20 -0
  102. package/dist/fields/baseFields/slug/generateSlugBeforeDuplicate.js.map +1 -0
  103. package/dist/fields/baseFields/slug/getSlugFallbackValue.d.ts +22 -0
  104. package/dist/fields/baseFields/slug/getSlugFallbackValue.d.ts.map +1 -0
  105. package/dist/fields/baseFields/slug/getSlugFallbackValue.js +23 -0
  106. package/dist/fields/baseFields/slug/getSlugFallbackValue.js.map +1 -0
  107. package/dist/fields/baseFields/slug/hasValue.d.ts +3 -0
  108. package/dist/fields/baseFields/slug/hasValue.d.ts.map +1 -0
  109. package/dist/fields/baseFields/slug/hasValue.js +3 -0
  110. package/dist/fields/baseFields/slug/hasValue.js.map +1 -0
  111. package/dist/fields/config/reservedFieldNames.spec.js +18 -18
  112. package/dist/fields/config/reservedFieldNames.spec.js.map +1 -1
  113. package/dist/fields/config/sanitize.d.ts +3 -9
  114. package/dist/fields/config/sanitize.d.ts.map +1 -1
  115. package/dist/fields/config/sanitize.js +33 -34
  116. package/dist/fields/config/sanitize.js.map +1 -1
  117. package/dist/fields/config/sanitize.spec.js +128 -105
  118. package/dist/fields/config/sanitize.spec.js.map +1 -1
  119. package/dist/fields/config/types.d.ts +4 -3
  120. package/dist/fields/config/types.d.ts.map +1 -1
  121. package/dist/fields/config/types.js.map +1 -1
  122. package/dist/fields/hooks/beforeValidate/promise.d.ts.map +1 -1
  123. package/dist/fields/hooks/beforeValidate/promise.js +5 -3
  124. package/dist/fields/hooks/beforeValidate/promise.js.map +1 -1
  125. package/dist/fields/hooks/beforeValidate/stripNullRows.d.ts +10 -0
  126. package/dist/fields/hooks/beforeValidate/stripNullRows.d.ts.map +1 -0
  127. package/dist/fields/hooks/beforeValidate/stripNullRows.js +18 -0
  128. package/dist/fields/hooks/beforeValidate/stripNullRows.js.map +1 -0
  129. package/dist/fields/validations.d.ts.map +1 -1
  130. package/dist/fields/validations.js +7 -8
  131. package/dist/fields/validations.js.map +1 -1
  132. package/dist/fields/validations.spec.js +61 -37
  133. package/dist/fields/validations.spec.js.map +1 -1
  134. package/dist/globals/config/sanitize.d.ts +2 -7
  135. package/dist/globals/config/sanitize.d.ts.map +1 -1
  136. package/dist/globals/config/sanitize.js +2 -6
  137. package/dist/globals/config/sanitize.js.map +1 -1
  138. package/dist/globals/config/sanitize.spec.js +6 -6
  139. package/dist/globals/config/sanitize.spec.js.map +1 -1
  140. package/dist/globals/operations/countGlobalVersions.d.ts.map +1 -1
  141. package/dist/globals/operations/countGlobalVersions.js +1 -0
  142. package/dist/globals/operations/countGlobalVersions.js.map +1 -1
  143. package/dist/index.bundled.d.ts +247 -178
  144. package/dist/index.d.ts +49 -17
  145. package/dist/index.d.ts.map +1 -1
  146. package/dist/index.js +3 -0
  147. package/dist/index.js.map +1 -1
  148. package/dist/query-presets/constraints.js +1 -1
  149. package/dist/query-presets/constraints.js.map +1 -1
  150. package/dist/queues/config/collection.d.ts.map +1 -1
  151. package/dist/queues/config/collection.js +37 -43
  152. package/dist/queues/config/collection.js.map +1 -1
  153. package/dist/queues/config/global.d.ts +5 -6
  154. package/dist/queues/config/global.d.ts.map +1 -1
  155. package/dist/queues/config/global.js +1 -1
  156. package/dist/queues/config/global.js.map +1 -1
  157. package/dist/queues/config/types/index.d.ts +29 -24
  158. package/dist/queues/config/types/index.d.ts.map +1 -1
  159. package/dist/queues/config/types/index.js.map +1 -1
  160. package/dist/queues/config/types/taskTypes.d.ts +4 -7
  161. package/dist/queues/config/types/taskTypes.d.ts.map +1 -1
  162. package/dist/queues/config/types/taskTypes.js.map +1 -1
  163. package/dist/queues/config/types/workflowJSONTypes.d.ts +10 -9
  164. package/dist/queues/config/types/workflowJSONTypes.d.ts.map +1 -1
  165. package/dist/queues/config/types/workflowJSONTypes.js.map +1 -1
  166. package/dist/queues/config/types/workflowTypes.d.ts +11 -58
  167. package/dist/queues/config/types/workflowTypes.d.ts.map +1 -1
  168. package/dist/queues/config/types/workflowTypes.js.map +1 -1
  169. package/dist/queues/endpoints/handleSchedules.js +1 -1
  170. package/dist/queues/endpoints/handleSchedules.js.map +1 -1
  171. package/dist/queues/errors/handleTaskError.js +4 -4
  172. package/dist/queues/errors/handleTaskError.js.map +1 -1
  173. package/dist/queues/errors/handleWorkflowError.js +1 -1
  174. package/dist/queues/errors/handleWorkflowError.js.map +1 -1
  175. package/dist/queues/errors/index.d.ts +6 -0
  176. package/dist/queues/errors/index.d.ts.map +1 -1
  177. package/dist/queues/errors/index.js +5 -0
  178. package/dist/queues/errors/index.js.map +1 -1
  179. package/dist/queues/localAPI.d.ts +4 -4
  180. package/dist/queues/localAPI.d.ts.map +1 -1
  181. package/dist/queues/localAPI.js +63 -66
  182. package/dist/queues/localAPI.js.map +1 -1
  183. package/dist/queues/operations/handleSchedules/countRunnableOrActiveJobsForQueue.d.ts +4 -4
  184. package/dist/queues/operations/handleSchedules/countRunnableOrActiveJobsForQueue.d.ts.map +1 -1
  185. package/dist/queues/operations/handleSchedules/countRunnableOrActiveJobsForQueue.js.map +1 -1
  186. package/dist/queues/operations/handleSchedules/index.d.ts +1 -1
  187. package/dist/queues/operations/handleSchedules/index.d.ts.map +1 -1
  188. package/dist/queues/operations/handleSchedules/index.js +1 -1
  189. package/dist/queues/operations/handleSchedules/index.js.map +1 -1
  190. package/dist/queues/operations/runJobs/heartbeat.d.ts +13 -0
  191. package/dist/queues/operations/runJobs/heartbeat.d.ts.map +1 -0
  192. package/dist/queues/operations/runJobs/heartbeat.js +66 -0
  193. package/dist/queues/operations/runJobs/heartbeat.js.map +1 -0
  194. package/dist/queues/operations/runJobs/index.d.ts.map +1 -1
  195. package/dist/queues/operations/runJobs/index.js +133 -84
  196. package/dist/queues/operations/runJobs/index.js.map +1 -1
  197. package/dist/queues/operations/runJobs/runJSONJob/index.d.ts.map +1 -1
  198. package/dist/queues/operations/runJobs/runJSONJob/index.js +6 -3
  199. package/dist/queues/operations/runJobs/runJSONJob/index.js.map +1 -1
  200. package/dist/queues/operations/runJobs/runJob/getRunTaskFunction.js +5 -5
  201. package/dist/queues/operations/runJobs/runJob/getRunTaskFunction.js.map +1 -1
  202. package/dist/queues/operations/runJobs/runJob/getUpdateJobFunction.d.ts +2 -1
  203. package/dist/queues/operations/runJobs/runJob/getUpdateJobFunction.d.ts.map +1 -1
  204. package/dist/queues/operations/runJobs/runJob/getUpdateJobFunction.js +39 -8
  205. package/dist/queues/operations/runJobs/runJob/getUpdateJobFunction.js.map +1 -1
  206. package/dist/queues/operations/runJobs/runJob/importHandlerPath.js.map +1 -1
  207. package/dist/queues/operations/runJobs/runJob/index.d.ts.map +1 -1
  208. package/dist/queues/operations/runJobs/runJob/index.js +4 -4
  209. package/dist/queues/operations/runJobs/runJob/index.js.map +1 -1
  210. package/dist/queues/utilities/updateJob.d.ts.map +1 -1
  211. package/dist/queues/utilities/updateJob.js +3 -0
  212. package/dist/queues/utilities/updateJob.js.map +1 -1
  213. package/dist/types/index.d.ts +2 -2
  214. package/dist/types/index.d.ts.map +1 -1
  215. package/dist/types/index.js.map +1 -1
  216. package/dist/uploads/checkFileRestrictions.d.ts +1 -1
  217. package/dist/uploads/checkFileRestrictions.d.ts.map +1 -1
  218. package/dist/uploads/checkFileRestrictions.js +15 -1
  219. package/dist/uploads/checkFileRestrictions.js.map +1 -1
  220. package/dist/uploads/endpoints/uploadInstructions.d.ts +12 -0
  221. package/dist/uploads/endpoints/uploadInstructions.d.ts.map +1 -1
  222. package/dist/uploads/endpoints/uploadInstructions.js +66 -20
  223. package/dist/uploads/endpoints/uploadInstructions.js.map +1 -1
  224. package/dist/uploads/generateFileData.js +4 -1
  225. package/dist/uploads/generateFileData.js.map +1 -1
  226. package/dist/uploads/getFileFromUploadInstructions.d.ts +8 -0
  227. package/dist/uploads/getFileFromUploadInstructions.d.ts.map +1 -0
  228. package/dist/uploads/getFileFromUploadInstructions.js +62 -0
  229. package/dist/uploads/getFileFromUploadInstructions.js.map +1 -0
  230. package/dist/uploads/getImageSize.d.ts +12 -1
  231. package/dist/uploads/getImageSize.d.ts.map +1 -1
  232. package/dist/uploads/getImageSize.js +20 -18
  233. package/dist/uploads/getImageSize.js.map +1 -1
  234. package/dist/uploads/getImageSize.spec.js +298 -0
  235. package/dist/uploads/getImageSize.spec.js.map +1 -0
  236. package/dist/uploads/probeImageSize.d.ts +39 -0
  237. package/dist/uploads/probeImageSize.d.ts.map +1 -0
  238. package/dist/uploads/probeImageSize.js +374 -0
  239. package/dist/uploads/probeImageSize.js.map +1 -0
  240. package/dist/uploads/probeImageSize.spec.js +366 -0
  241. package/dist/uploads/probeImageSize.spec.js.map +1 -0
  242. package/dist/uploads/stagedUpload.d.ts +27 -0
  243. package/dist/uploads/stagedUpload.d.ts.map +1 -0
  244. package/dist/uploads/stagedUpload.js +197 -0
  245. package/dist/uploads/stagedUpload.js.map +1 -0
  246. package/dist/uploads/types.d.ts +41 -13
  247. package/dist/uploads/types.d.ts.map +1 -1
  248. package/dist/uploads/types.js.map +1 -1
  249. package/dist/utilities/addDataAndFileToRequest.d.ts.map +1 -1
  250. package/dist/utilities/addDataAndFileToRequest.js +12 -46
  251. package/dist/utilities/addDataAndFileToRequest.js.map +1 -1
  252. package/dist/utilities/configToJSONSchema.spec.js +33 -33
  253. package/dist/utilities/configToJSONSchema.spec.js.map +1 -1
  254. package/dist/utilities/fieldValueExists.d.ts +29 -0
  255. package/dist/utilities/fieldValueExists.d.ts.map +1 -0
  256. package/dist/utilities/fieldValueExists.js +27 -0
  257. package/dist/utilities/fieldValueExists.js.map +1 -0
  258. package/dist/utilities/getUniqueFieldValue.d.ts +27 -0
  259. package/dist/utilities/getUniqueFieldValue.d.ts.map +1 -0
  260. package/dist/utilities/getUniqueFieldValue.js +26 -0
  261. package/dist/utilities/getUniqueFieldValue.js.map +1 -0
  262. package/dist/versions/deleteScheduledPublishJobs.js +2 -2
  263. package/dist/versions/deleteScheduledPublishJobs.js.map +1 -1
  264. package/dist/versions/payloadPackageList.d.ts.map +1 -1
  265. package/dist/versions/payloadPackageList.js +0 -1
  266. package/dist/versions/payloadPackageList.js.map +1 -1
  267. package/package.json +8 -3
  268. package/dist/database/defaultUpdateJobs.d.ts +0 -3
  269. package/dist/database/defaultUpdateJobs.d.ts.map +0 -1
  270. package/dist/database/defaultUpdateJobs.js +0 -41
  271. package/dist/database/defaultUpdateJobs.js.map +0 -1
  272. package/dist/fields/baseFields/slug/countVersions.d.ts +0 -13
  273. package/dist/fields/baseFields/slug/countVersions.d.ts.map +0 -1
  274. package/dist/fields/baseFields/slug/countVersions.js +0 -27
  275. package/dist/fields/baseFields/slug/countVersions.js.map +0 -1
  276. package/dist/uploads/tempFile.d.ts +0 -7
  277. package/dist/uploads/tempFile.d.ts.map +0 -1
  278. package/dist/uploads/tempFile.js +0 -39
  279. package/dist/uploads/tempFile.js.map +0 -1
@@ -1,7 +1,9 @@
1
1
  /**
2
2
  * Modules exported here are not part of the public API and are subject to change without notice and without a major version bump.
3
3
  */
4
+ export { getUploadInstructions } from '../uploads/endpoints/uploadInstructions.js';
4
5
  export { getExternalFile } from '../uploads/getExternalFile.js';
6
+ export { getFileFromUploadInstructions } from '../uploads/getFileFromUploadInstructions.js';
5
7
  export { getRangeRequestInfo } from '../uploads/getRangeRequestInfo.js';
6
8
  export { getSafeFileName } from '../uploads/getSafeFilename.js';
7
9
  export { parseRangeHeader } from '../uploads/parseRangeHeader.js';
@@ -1 +1 @@
1
- {"version":3,"file":"internal.d.ts","sourceRoot":"","sources":["../../src/exports/internal.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAA;AAC/D,OAAO,EAAE,mBAAmB,EAAE,MAAM,mCAAmC,CAAA;AACvE,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAA;AAC/D,OAAO,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAA;AACjE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2DAA2D,CAAA;AAChG,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAA;AAC3D,OAAO,EAAE,mBAAmB,EAAE,MAAM,qCAAqC,CAAA;AACzE,OAAO,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAA"}
1
+ {"version":3,"file":"internal.d.ts","sourceRoot":"","sources":["../../src/exports/internal.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,qBAAqB,EAAE,MAAM,4CAA4C,CAAA;AAClF,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAA;AAC/D,OAAO,EAAE,6BAA6B,EAAE,MAAM,6CAA6C,CAAA;AAC3F,OAAO,EAAE,mBAAmB,EAAE,MAAM,mCAAmC,CAAA;AACvE,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAA;AAC/D,OAAO,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAA;AACjE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2DAA2D,CAAA;AAChG,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAA;AAC3D,OAAO,EAAE,mBAAmB,EAAE,MAAM,qCAAqC,CAAA;AACzE,OAAO,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAA"}
@@ -1,6 +1,8 @@
1
1
  /**
2
2
  * Modules exported here are not part of the public API and are subject to change without notice and without a major version bump.
3
- */ export { getExternalFile } from '../uploads/getExternalFile.js';
3
+ */ export { getUploadInstructions } from '../uploads/endpoints/uploadInstructions.js';
4
+ export { getExternalFile } from '../uploads/getExternalFile.js';
5
+ export { getFileFromUploadInstructions } from '../uploads/getFileFromUploadInstructions.js';
4
6
  export { getRangeRequestInfo } from '../uploads/getRangeRequestInfo.js';
5
7
  export { getSafeFileName } from '../uploads/getSafeFilename.js';
6
8
  export { parseRangeHeader } from '../uploads/parseRangeHeader.js';
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/exports/internal.ts"],"sourcesContent":["/**\n * Modules exported here are not part of the public API and are subject to change without notice and without a major version bump.\n */\n\nexport { getExternalFile } from '../uploads/getExternalFile.js'\nexport { getRangeRequestInfo } from '../uploads/getRangeRequestInfo.js'\nexport { getSafeFileName } from '../uploads/getSafeFilename.js'\nexport { parseRangeHeader } from '../uploads/parseRangeHeader.js'\nexport { getEntityPermissions } from '../utilities/getEntityPermissions/getEntityPermissions.js'\nexport { isURLAllowed } from '../utilities/isURLAllowed.js'\nexport { sanitizePermissions } from '../utilities/sanitizePermissions.js'\nexport { sendTelemetryEvent } from '../utilities/telemetry/index.js'\n"],"names":["getExternalFile","getRangeRequestInfo","getSafeFileName","parseRangeHeader","getEntityPermissions","isURLAllowed","sanitizePermissions","sendTelemetryEvent"],"mappings":"AAAA;;CAEC,GAED,SAASA,eAAe,QAAQ,gCAA+B;AAC/D,SAASC,mBAAmB,QAAQ,oCAAmC;AACvE,SAASC,eAAe,QAAQ,gCAA+B;AAC/D,SAASC,gBAAgB,QAAQ,iCAAgC;AACjE,SAASC,oBAAoB,QAAQ,4DAA2D;AAChG,SAASC,YAAY,QAAQ,+BAA8B;AAC3D,SAASC,mBAAmB,QAAQ,sCAAqC;AACzE,SAASC,kBAAkB,QAAQ,kCAAiC"}
1
+ {"version":3,"sources":["../../src/exports/internal.ts"],"sourcesContent":["/**\n * Modules exported here are not part of the public API and are subject to change without notice and without a major version bump.\n */\n\nexport { getUploadInstructions } from '../uploads/endpoints/uploadInstructions.js'\nexport { getExternalFile } from '../uploads/getExternalFile.js'\nexport { getFileFromUploadInstructions } from '../uploads/getFileFromUploadInstructions.js'\nexport { getRangeRequestInfo } from '../uploads/getRangeRequestInfo.js'\nexport { getSafeFileName } from '../uploads/getSafeFilename.js'\nexport { parseRangeHeader } from '../uploads/parseRangeHeader.js'\nexport { getEntityPermissions } from '../utilities/getEntityPermissions/getEntityPermissions.js'\nexport { isURLAllowed } from '../utilities/isURLAllowed.js'\nexport { sanitizePermissions } from '../utilities/sanitizePermissions.js'\nexport { sendTelemetryEvent } from '../utilities/telemetry/index.js'\n"],"names":["getUploadInstructions","getExternalFile","getFileFromUploadInstructions","getRangeRequestInfo","getSafeFileName","parseRangeHeader","getEntityPermissions","isURLAllowed","sanitizePermissions","sendTelemetryEvent"],"mappings":"AAAA;;CAEC,GAED,SAASA,qBAAqB,QAAQ,6CAA4C;AAClF,SAASC,eAAe,QAAQ,gCAA+B;AAC/D,SAASC,6BAA6B,QAAQ,8CAA6C;AAC3F,SAASC,mBAAmB,QAAQ,oCAAmC;AACvE,SAASC,eAAe,QAAQ,gCAA+B;AAC/D,SAASC,gBAAgB,QAAQ,iCAAgC;AACjE,SAASC,oBAAoB,QAAQ,4DAA2D;AAChG,SAASC,YAAY,QAAQ,+BAA8B;AAC3D,SAASC,mBAAmB,QAAQ,sCAAqC;AACzE,SAASC,kBAAkB,QAAQ,kCAAiC"}
@@ -0,0 +1,11 @@
1
+ import type { RequestContext } from '../../../index.js';
2
+ /**
3
+ * Bridges the two hooks in a duplicate: `beforeDuplicate` marks a slug field, and the copy's
4
+ * `beforeChange` reads the mark to take a fresh `<singular>-<N>` fallback — skipping both the
5
+ * explicit-collision check (the copy isn't a user-typed value) and source derivation (which would
6
+ * drift toward the original's slug).
7
+ */
8
+ export declare const markSlugForDuplicateFallback: (context: RequestContext, name: string) => void;
9
+ /** Reads and clears the mark so it can't leak into a later operation on the same request. */
10
+ export declare const consumeSlugDuplicateFallback: (context: RequestContext, name: string) => boolean;
11
+ //# sourceMappingURL=duplicateContext.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"duplicateContext.d.ts","sourceRoot":"","sources":["../../../../src/fields/baseFields/slug/duplicateContext.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA;AAIvD;;;;;GAKG;AACH,eAAO,MAAM,4BAA4B,YAAa,cAAc,QAAQ,MAAM,KAAG,IAIpF,CAAA;AAED,6FAA6F;AAC7F,eAAO,MAAM,4BAA4B,YAAa,cAAc,QAAQ,MAAM,KAAG,OASpF,CAAA"}
@@ -0,0 +1,21 @@
1
+ const CONTEXT_KEY = '_slugDuplicateFallbackFields';
2
+ /**
3
+ * Bridges the two hooks in a duplicate: `beforeDuplicate` marks a slug field, and the copy's
4
+ * `beforeChange` reads the mark to take a fresh `<singular>-<N>` fallback — skipping both the
5
+ * explicit-collision check (the copy isn't a user-typed value) and source derivation (which would
6
+ * drift toward the original's slug).
7
+ */ export const markSlugForDuplicateFallback = (context, name)=>{
8
+ const fields = context[CONTEXT_KEY] ?? {};
9
+ fields[name] = true;
10
+ context[CONTEXT_KEY] = fields;
11
+ };
12
+ /** Reads and clears the mark so it can't leak into a later operation on the same request. */ export const consumeSlugDuplicateFallback = (context, name)=>{
13
+ const fields = context[CONTEXT_KEY];
14
+ if (!fields?.[name]) {
15
+ return false;
16
+ }
17
+ delete fields[name];
18
+ return true;
19
+ };
20
+
21
+ //# sourceMappingURL=duplicateContext.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/fields/baseFields/slug/duplicateContext.ts"],"sourcesContent":["import type { RequestContext } from '../../../index.js'\n\nconst CONTEXT_KEY = '_slugDuplicateFallbackFields'\n\n/**\n * Bridges the two hooks in a duplicate: `beforeDuplicate` marks a slug field, and the copy's\n * `beforeChange` reads the mark to take a fresh `<singular>-<N>` fallback — skipping both the\n * explicit-collision check (the copy isn't a user-typed value) and source derivation (which would\n * drift toward the original's slug).\n */\nexport const markSlugForDuplicateFallback = (context: RequestContext, name: string): void => {\n const fields = (context[CONTEXT_KEY] as Record<string, boolean> | undefined) ?? {}\n fields[name] = true\n context[CONTEXT_KEY] = fields\n}\n\n/** Reads and clears the mark so it can't leak into a later operation on the same request. */\nexport const consumeSlugDuplicateFallback = (context: RequestContext, name: string): boolean => {\n const fields = context[CONTEXT_KEY] as Record<string, boolean> | undefined\n\n if (!fields?.[name]) {\n return false\n }\n\n delete fields[name]\n return true\n}\n"],"names":["CONTEXT_KEY","markSlugForDuplicateFallback","context","name","fields","consumeSlugDuplicateFallback"],"mappings":"AAEA,MAAMA,cAAc;AAEpB;;;;;CAKC,GACD,OAAO,MAAMC,+BAA+B,CAACC,SAAyBC;IACpE,MAAMC,SAAS,AAACF,OAAO,CAACF,YAAY,IAA4C,CAAC;IACjFI,MAAM,CAACD,KAAK,GAAG;IACfD,OAAO,CAACF,YAAY,GAAGI;AACzB,EAAC;AAED,2FAA2F,GAC3F,OAAO,MAAMC,+BAA+B,CAACH,SAAyBC;IACpE,MAAMC,SAASF,OAAO,CAACF,YAAY;IAEnC,IAAI,CAACI,QAAQ,CAACD,KAAK,EAAE;QACnB,OAAO;IACT;IAEA,OAAOC,MAAM,CAACD,KAAK;IACnB,OAAO;AACT,EAAC"}
@@ -0,0 +1,22 @@
1
+ import type { SanitizedCollectionConfig } from '../../../collections/config/types.js';
2
+ import type { JsonObject, PayloadRequest } from '../../../types/index.js';
3
+ type Args = {
4
+ collection: SanitizedCollectionConfig;
5
+ /** The post-`beforeChange` data, with localized fields already keyed by locale. */
6
+ data: JsonObject;
7
+ req: PayloadRequest;
8
+ };
9
+ /**
10
+ * On create, seed every locale of a localized slug field so switching locales never lands on an
11
+ * empty slug. Each empty locale derives from its own source value — a non-localized source applies
12
+ * to every locale, so they follow it just like the active locale did — and falls back to a per-locale
13
+ * `<singular>-<N>` only when that locale has no source. Both are deduped within the locale, so one
14
+ * document never claims another's per-locale value.
15
+ *
16
+ * Runs after field `beforeChange` (similar to the localized `_status` treatment). The slug field hook
17
+ * only sees the active locale, so the other locales are filled here at the operation level. A slug
18
+ * is static once set, so this is create-only; per-locale edits afterward stay scoped to their locale.
19
+ */
20
+ export declare const fillEmptyLocalizedSlugs: ({ collection, data, req, }: Args) => Promise<JsonObject>;
21
+ export {};
22
+ //# sourceMappingURL=fillEmptyLocalizedSlugs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fillEmptyLocalizedSlugs.d.ts","sourceRoot":"","sources":["../../../../src/fields/baseFields/slug/fillEmptyLocalizedSlugs.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,sCAAsC,CAAA;AACrF,OAAO,KAAK,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAA;AASzE,KAAK,IAAI,GAAG;IACV,UAAU,EAAE,yBAAyB,CAAA;IACrC,mFAAmF;IACnF,IAAI,EAAE,UAAU,CAAA;IAChB,GAAG,EAAE,cAAc,CAAA;CACpB,CAAA;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,uBAAuB,+BAIjC,IAAI,KAAG,OAAO,CAAC,UAAU,CAyD3B,CAAA"}
@@ -0,0 +1,63 @@
1
+ import { getUniqueFieldValue } from '../../../utilities/getUniqueFieldValue.js';
2
+ import { hasDraftsEnabled } from '../../../utilities/getVersionsConfig.js';
3
+ import { slugify as defaultSlugify } from '../../../utilities/slugify.js';
4
+ import { getSlugFallbackValue } from './getSlugFallbackValue.js';
5
+ import { hasValue } from './hasValue.js';
6
+ /**
7
+ * On create, seed every locale of a localized slug field so switching locales never lands on an
8
+ * empty slug. Each empty locale derives from its own source value — a non-localized source applies
9
+ * to every locale, so they follow it just like the active locale did — and falls back to a per-locale
10
+ * `<singular>-<N>` only when that locale has no source. Both are deduped within the locale, so one
11
+ * document never claims another's per-locale value.
12
+ *
13
+ * Runs after field `beforeChange` (similar to the localized `_status` treatment). The slug field hook
14
+ * only sees the active locale, so the other locales are filled here at the operation level. A slug
15
+ * is static once set, so this is create-only; per-locale edits afterward stay scoped to their locale.
16
+ */ export const fillEmptyLocalizedSlugs = async ({ collection, data, req })=>{
17
+ const { localization } = req.payload.config;
18
+ if (!localization || localization.localeCodes.length < 2) {
19
+ return data;
20
+ }
21
+ const draftsEnabled = hasDraftsEnabled(collection);
22
+ for (const field of collection.flattenedFields){
23
+ if (field.type !== 'slug' || !field.localized) {
24
+ continue;
25
+ }
26
+ const customSlugify = field.custom?.slugify;
27
+ const slugify = (valueToSlugify)=>customSlugify ? customSlugify({
28
+ data,
29
+ req,
30
+ valueToSlugify
31
+ }) : defaultSlugify(valueToSlugify);
32
+ // The source value for a given locale: a non-localized source is shared across all locales, a
33
+ // localized one is read per-locale (only the locales present in this create have a value).
34
+ const sourceField = field.useAsSlug ? collection.flattenedFields.find((f)=>f.name === field.useAsSlug) : undefined;
35
+ const source = field.useAsSlug ? data[field.useAsSlug] : undefined;
36
+ const localeValues = data[field.name] ?? {};
37
+ for (const locale of localization.localeCodes){
38
+ if (hasValue(localeValues[locale])) {
39
+ continue;
40
+ }
41
+ const sourceForLocale = sourceField?.localized ? source?.[locale] : source;
42
+ const derived = sourceForLocale ? await slugify(sourceForLocale) : undefined;
43
+ localeValues[locale] = hasValue(derived) ? await getUniqueFieldValue({
44
+ collection: collection.slug,
45
+ draftsEnabled,
46
+ field: field.name,
47
+ locale,
48
+ req,
49
+ value: derived
50
+ }) : await getSlugFallbackValue({
51
+ collection,
52
+ field: field.name,
53
+ locale,
54
+ req,
55
+ slugify
56
+ });
57
+ }
58
+ data[field.name] = localeValues;
59
+ }
60
+ return data;
61
+ };
62
+
63
+ //# sourceMappingURL=fillEmptyLocalizedSlugs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/fields/baseFields/slug/fillEmptyLocalizedSlugs.ts"],"sourcesContent":["import type { SanitizedCollectionConfig } from '../../../collections/config/types.js'\nimport type { JsonObject, PayloadRequest } from '../../../types/index.js'\nimport type { Slugify } from './types.js'\n\nimport { getUniqueFieldValue } from '../../../utilities/getUniqueFieldValue.js'\nimport { hasDraftsEnabled } from '../../../utilities/getVersionsConfig.js'\nimport { slugify as defaultSlugify } from '../../../utilities/slugify.js'\nimport { getSlugFallbackValue } from './getSlugFallbackValue.js'\nimport { hasValue } from './hasValue.js'\n\ntype Args = {\n collection: SanitizedCollectionConfig\n /** The post-`beforeChange` data, with localized fields already keyed by locale. */\n data: JsonObject\n req: PayloadRequest\n}\n\n/**\n * On create, seed every locale of a localized slug field so switching locales never lands on an\n * empty slug. Each empty locale derives from its own source value — a non-localized source applies\n * to every locale, so they follow it just like the active locale did — and falls back to a per-locale\n * `<singular>-<N>` only when that locale has no source. Both are deduped within the locale, so one\n * document never claims another's per-locale value.\n *\n * Runs after field `beforeChange` (similar to the localized `_status` treatment). The slug field hook\n * only sees the active locale, so the other locales are filled here at the operation level. A slug\n * is static once set, so this is create-only; per-locale edits afterward stay scoped to their locale.\n */\nexport const fillEmptyLocalizedSlugs = async ({\n collection,\n data,\n req,\n}: Args): Promise<JsonObject> => {\n const { localization } = req.payload.config\n\n if (!localization || localization.localeCodes.length < 2) {\n return data\n }\n\n const draftsEnabled = hasDraftsEnabled(collection)\n\n for (const field of collection.flattenedFields) {\n if (field.type !== 'slug' || !field.localized) {\n continue\n }\n\n const customSlugify = field.custom?.slugify as Slugify | undefined\n\n const slugify = (valueToSlugify: unknown) =>\n customSlugify\n ? customSlugify({ data, req, valueToSlugify })\n : defaultSlugify(valueToSlugify as string)\n\n // The source value for a given locale: a non-localized source is shared across all locales, a\n // localized one is read per-locale (only the locales present in this create have a value).\n const sourceField = field.useAsSlug\n ? collection.flattenedFields.find((f) => f.name === field.useAsSlug)\n : undefined\n const source = field.useAsSlug ? data[field.useAsSlug] : undefined\n\n const localeValues = (data[field.name] ?? {}) as Record<string, unknown>\n\n for (const locale of localization.localeCodes) {\n if (hasValue(localeValues[locale])) {\n continue\n }\n\n const sourceForLocale = sourceField?.localized\n ? (source as Record<string, unknown> | undefined)?.[locale]\n : source\n\n const derived = sourceForLocale ? await slugify(sourceForLocale) : undefined\n\n localeValues[locale] = hasValue(derived)\n ? await getUniqueFieldValue({\n collection: collection.slug,\n draftsEnabled,\n field: field.name,\n locale,\n req,\n value: derived as string,\n })\n : await getSlugFallbackValue({ collection, field: field.name, locale, req, slugify })\n }\n\n data[field.name] = localeValues\n }\n\n return data\n}\n"],"names":["getUniqueFieldValue","hasDraftsEnabled","slugify","defaultSlugify","getSlugFallbackValue","hasValue","fillEmptyLocalizedSlugs","collection","data","req","localization","payload","config","localeCodes","length","draftsEnabled","field","flattenedFields","type","localized","customSlugify","custom","valueToSlugify","sourceField","useAsSlug","find","f","name","undefined","source","localeValues","locale","sourceForLocale","derived","slug","value"],"mappings":"AAIA,SAASA,mBAAmB,QAAQ,4CAA2C;AAC/E,SAASC,gBAAgB,QAAQ,0CAAyC;AAC1E,SAASC,WAAWC,cAAc,QAAQ,gCAA+B;AACzE,SAASC,oBAAoB,QAAQ,4BAA2B;AAChE,SAASC,QAAQ,QAAQ,gBAAe;AASxC;;;;;;;;;;CAUC,GACD,OAAO,MAAMC,0BAA0B,OAAO,EAC5CC,UAAU,EACVC,IAAI,EACJC,GAAG,EACE;IACL,MAAM,EAAEC,YAAY,EAAE,GAAGD,IAAIE,OAAO,CAACC,MAAM;IAE3C,IAAI,CAACF,gBAAgBA,aAAaG,WAAW,CAACC,MAAM,GAAG,GAAG;QACxD,OAAON;IACT;IAEA,MAAMO,gBAAgBd,iBAAiBM;IAEvC,KAAK,MAAMS,SAAST,WAAWU,eAAe,CAAE;QAC9C,IAAID,MAAME,IAAI,KAAK,UAAU,CAACF,MAAMG,SAAS,EAAE;YAC7C;QACF;QAEA,MAAMC,gBAAgBJ,MAAMK,MAAM,EAAEnB;QAEpC,MAAMA,UAAU,CAACoB,iBACfF,gBACIA,cAAc;gBAAEZ;gBAAMC;gBAAKa;YAAe,KAC1CnB,eAAemB;QAErB,8FAA8F;QAC9F,2FAA2F;QAC3F,MAAMC,cAAcP,MAAMQ,SAAS,GAC/BjB,WAAWU,eAAe,CAACQ,IAAI,CAAC,CAACC,IAAMA,EAAEC,IAAI,KAAKX,MAAMQ,SAAS,IACjEI;QACJ,MAAMC,SAASb,MAAMQ,SAAS,GAAGhB,IAAI,CAACQ,MAAMQ,SAAS,CAAC,GAAGI;QAEzD,MAAME,eAAgBtB,IAAI,CAACQ,MAAMW,IAAI,CAAC,IAAI,CAAC;QAE3C,KAAK,MAAMI,UAAUrB,aAAaG,WAAW,CAAE;YAC7C,IAAIR,SAASyB,YAAY,CAACC,OAAO,GAAG;gBAClC;YACF;YAEA,MAAMC,kBAAkBT,aAAaJ,YAChCU,QAAgD,CAACE,OAAO,GACzDF;YAEJ,MAAMI,UAAUD,kBAAkB,MAAM9B,QAAQ8B,mBAAmBJ;YAEnEE,YAAY,CAACC,OAAO,GAAG1B,SAAS4B,WAC5B,MAAMjC,oBAAoB;gBACxBO,YAAYA,WAAW2B,IAAI;gBAC3BnB;gBACAC,OAAOA,MAAMW,IAAI;gBACjBI;gBACAtB;gBACA0B,OAAOF;YACT,KACA,MAAM7B,qBAAqB;gBAAEG;gBAAYS,OAAOA,MAAMW,IAAI;gBAAEI;gBAAQtB;gBAAKP;YAAQ;QACvF;QAEAM,IAAI,CAACQ,MAAMW,IAAI,CAAC,GAAGG;IACrB;IAEA,OAAOtB;AACT,EAAC"}
@@ -1,19 +1,24 @@
1
1
  import type { FieldHook } from '../../config/types.js';
2
2
  import type { Slugify } from './types.js';
3
3
  type Args = {
4
+ localized?: boolean;
4
5
  name: string;
5
6
  slugify?: Slugify;
6
- useAsSlug: string;
7
+ useAsSlug?: string;
7
8
  };
8
9
  /**
9
- * Field `beforeChange` hook for the native `slug` field. Returns the slug value.
10
+ * `beforeChange` hook for the native `slug` field.
10
11
  *
11
- * Auto-tracking is derived statelessly: the slug follows its source while it is
12
- * empty or still equals `slugify(storedSource)`. Once it diverges (the admin
13
- * overwrites it), it freezes and stays frozen, because the stored value keeps
14
- * differing from `slugify(source)`. Re-aligning (the UI generate button) resumes
15
- * tracking.
12
+ * Fills the slug only while empty and never rewrites one that's set, so a lagging autosave can't
13
+ * clobber it with a stale value:
14
+ * - empty with no source falls back to `<singular>-<N>`, e.g. `posts-1` (see {@link getSlugFallbackValue})
15
+ * - explicit input and the source field are slugified, e.g. "Hello World" → "hello-world"
16
+ * - an already-set slug is preserved as-is
17
+ *
18
+ * Generated values dedupe against existing slugs; a localized slug is unique per-locale, so its
19
+ * dedupe and fallback are scoped to the locale being written. Globals have no collection to dedupe
20
+ * against, so their slug is left as-is.
16
21
  */
17
- export declare const generateSlug: ({ name, slugify: customSlugify, useAsSlug }: Args) => FieldHook;
22
+ export declare const generateSlug: ({ name, localized, slugify: customSlugify, useAsSlug }: Args) => FieldHook;
18
23
  export {};
19
24
  //# sourceMappingURL=generateSlug.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"generateSlug.d.ts","sourceRoot":"","sources":["../../../../src/fields/baseFields/slug/generateSlug.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAA;AACtD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAA;AAMzC,KAAK,IAAI,GAAG;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;CAClB,CAAA;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,YAAY,gDACuB,IAAI,KAAG,SA+DpD,CAAA"}
1
+ {"version":3,"file":"generateSlug.d.ts","sourceRoot":"","sources":["../../../../src/fields/baseFields/slug/generateSlug.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAA;AACtD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAA;AAWzC,KAAK,IAAI,GAAG;IACV,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,CAAA;AAED;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,YAAY,2DACkC,IAAI,KAAG,SAgG/D,CAAA"}
@@ -1,64 +1,117 @@
1
- import { hasAutosaveEnabled } from '../../../utilities/getVersionsConfig.js';
1
+ import { ValidationError } from '../../../errors/index.js';
2
+ import { fieldValueExists } from '../../../utilities/fieldValueExists.js';
3
+ import { getUniqueFieldValue } from '../../../utilities/getUniqueFieldValue.js';
4
+ import { hasDraftsEnabled } from '../../../utilities/getVersionsConfig.js';
2
5
  import { slugify as defaultSlugify } from '../../../utilities/slugify.js';
3
- import { countVersions } from './countVersions.js';
6
+ import { consumeSlugDuplicateFallback } from './duplicateContext.js';
7
+ import { getSlugFallbackValue } from './getSlugFallbackValue.js';
8
+ import { hasValue } from './hasValue.js';
4
9
  /**
5
- * Field `beforeChange` hook for the native `slug` field. Returns the slug value.
10
+ * `beforeChange` hook for the native `slug` field.
6
11
  *
7
- * Auto-tracking is derived statelessly: the slug follows its source while it is
8
- * empty or still equals `slugify(storedSource)`. Once it diverges (the admin
9
- * overwrites it), it freezes and stays frozen, because the stored value keeps
10
- * differing from `slugify(source)`. Re-aligning (the UI generate button) resumes
11
- * tracking.
12
- */ export const generateSlug = ({ name, slugify: customSlugify, useAsSlug })=>async ({ collection, data, global, operation, originalDoc, req, value })=>{
13
- const source = data?.[useAsSlug];
12
+ * Fills the slug only while empty and never rewrites one that's set, so a lagging autosave can't
13
+ * clobber it with a stale value:
14
+ * - empty with no source falls back to `<singular>-<N>`, e.g. `posts-1` (see {@link getSlugFallbackValue})
15
+ * - explicit input and the source field are slugified, e.g. "Hello World" → "hello-world"
16
+ * - an already-set slug is preserved as-is
17
+ *
18
+ * Generated values dedupe against existing slugs; a localized slug is unique per-locale, so its
19
+ * dedupe and fallback are scoped to the locale being written. Globals have no collection to dedupe
20
+ * against, so their slug is left as-is.
21
+ */ export const generateSlug = ({ name, localized, slugify: customSlugify, useAsSlug })=>async ({ collection, context, data, operation, originalDoc, req, value })=>{
14
22
  const slugify = (valueToSlugify)=>customSlugify ? customSlugify({
15
23
  data: data ?? {},
16
24
  req,
17
25
  valueToSlugify
18
26
  }) : defaultSlugify(valueToSlugify);
19
- const entity = collection || global;
20
- if (operation === 'create') {
21
- // Autosave drafts: do not auto-generate on the initial draft — the user is still entering content.
22
- // Keep the explicit non-slugified value (if any); generation begins on a later autosave.
23
- if (hasAutosaveEnabled(entity) && data?._status === 'draft') {
24
- return value || null;
25
- }
26
- // Keep an explicitly provided slug; otherwise generate from the source.
27
- return await slugify(value || source);
27
+ // A localized slug is unique only within its locale, so every uniqueness query below is scoped
28
+ // to the locale being written.
29
+ const locale = localized ? req.locale ?? undefined : undefined;
30
+ // A duplicated document:
31
+ // - Takes a fresh `<singular>-<N>` fallback — not the original's slug, not a source-derived one
32
+ // - Skips the explicit-collision check below (see generateSlugBeforeDuplicate).
33
+ if (collection && consumeSlugDuplicateFallback(context, name)) {
34
+ return await getSlugFallbackValue({
35
+ collection,
36
+ field: name,
37
+ locale,
38
+ req,
39
+ slugify
40
+ });
28
41
  }
29
42
  const storedSlug = originalDoc?.[name];
30
- const originalSource = originalDoc?.[useAsSlug];
31
- // User explicitly edited the slug (or cleared the value): respect it.
32
- if (value !== undefined && value !== storedSlug) {
33
- return value;
43
+ const storedSlugHasValue = hasValue(storedSlug);
44
+ // Explicit value from the client wins normalized through the field's slugify.
45
+ // It must be unique: reject a collision rather than silently changing it,
46
+ // only generated values are automatically deduped.
47
+ // A value that slugifies to nothing (e.g. "!!!") isn't a usable slug,
48
+ // so fall through to the source/fallback rather than store an empty one.
49
+ if (hasValue(value)) {
50
+ const slugified = await slugify(value);
51
+ if (hasValue(slugified)) {
52
+ // Unchanged from what's stored — already unique, so skip the collision query. Autosave
53
+ // resends the current slug on every tick; without this each tick runs a needless read.
54
+ if (slugified === storedSlug) {
55
+ return storedSlug;
56
+ }
57
+ if (collection && await fieldValueExists({
58
+ id: originalDoc?.id,
59
+ collection: collection.slug,
60
+ draftsEnabled: hasDraftsEnabled(collection),
61
+ field: name,
62
+ locale,
63
+ req,
64
+ value: slugified
65
+ })) {
66
+ throw new ValidationError({
67
+ errors: [
68
+ {
69
+ message: req.t('error:valueMustBeUnique'),
70
+ path: name
71
+ }
72
+ ]
73
+ }, req.t);
74
+ }
75
+ return slugified;
76
+ }
34
77
  }
35
- // No explicit edit this save. If the stored slug doesn't match what its source
36
- // would generate, it was customized on an earlier save — keep it frozen.
37
- const storedSlugIsCustom = storedSlug && storedSlug !== await slugify(originalSource);
38
- if (storedSlugIsCustom) {
78
+ // On update, preserve a slug that is already set only fill it while empty.
79
+ if (operation !== 'create' && storedSlugHasValue) {
39
80
  return storedSlug;
40
81
  }
41
- if (!hasAutosaveEnabled(entity)) {
42
- // Non-autosave: generate once while empty, then freeze.
43
- return storedSlug || await slugify(source);
44
- }
45
- // Autosave / drafts
46
- const priorVersions = await countVersions({
47
- collectionSlug: collection?.slug,
48
- globalSlug: global?.slug,
49
- parentID: originalDoc?.id,
50
- req
51
- });
52
- // Do not generate on the very first draft (no prior version yet).
53
- if (priorVersions === 0) {
54
- return storedSlug ?? null;
82
+ // Derive an empty slug from its source, when present.
83
+ // Dedupe so two documents don't both claim it if they have the same source value.
84
+ // Globals have no collection to dedupe against.
85
+ const source = useAsSlug ? data?.[useAsSlug] : undefined;
86
+ const derived = source ? await slugify(source) : undefined;
87
+ if (hasValue(derived)) {
88
+ if (!collection) {
89
+ return derived;
90
+ }
91
+ return await getUniqueFieldValue({
92
+ id: originalDoc?.id,
93
+ collection: collection.slug,
94
+ draftsEnabled: hasDraftsEnabled(collection),
95
+ field: name,
96
+ locale,
97
+ req,
98
+ value: derived
99
+ });
55
100
  }
56
- // Stabilize after publish to protect live URLs.
57
- if (data?._status === 'published' || originalDoc?._status === 'published') {
101
+ // No usable source: keep a stored value, otherwise fall back to `<singular>-<N>`.
102
+ if (storedSlugHasValue) {
58
103
  return storedSlug;
59
104
  }
60
- // Still auto-tracking an unpublished draft with content.
61
- return source ? await slugify(source) : null;
105
+ if (!collection) {
106
+ return undefined;
107
+ }
108
+ return await getSlugFallbackValue({
109
+ collection,
110
+ field: name,
111
+ locale,
112
+ req,
113
+ slugify
114
+ });
62
115
  };
63
116
 
64
117
  //# sourceMappingURL=generateSlug.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/fields/baseFields/slug/generateSlug.ts"],"sourcesContent":["import type { TypeWithID } from '../../../collections/config/types.js'\nimport type { FieldHook } from '../../config/types.js'\nimport type { Slugify } from './types.js'\n\nimport { hasAutosaveEnabled } from '../../../utilities/getVersionsConfig.js'\nimport { slugify as defaultSlugify } from '../../../utilities/slugify.js'\nimport { countVersions } from './countVersions.js'\n\ntype Args = {\n name: string\n slugify?: Slugify\n useAsSlug: string\n}\n\n/**\n * Field `beforeChange` hook for the native `slug` field. Returns the slug value.\n *\n * Auto-tracking is derived statelessly: the slug follows its source while it is\n * empty or still equals `slugify(storedSource)`. Once it diverges (the admin\n * overwrites it), it freezes and stays frozen, because the stored value keeps\n * differing from `slugify(source)`. Re-aligning (the UI generate button) resumes\n * tracking.\n */\nexport const generateSlug =\n ({ name, slugify: customSlugify, useAsSlug }: Args): FieldHook =>\n async ({ collection, data, global, operation, originalDoc, req, value }) => {\n const source = data?.[useAsSlug]\n\n const slugify = (valueToSlugify: unknown) =>\n customSlugify\n ? customSlugify({ data: (data ?? {}) as TypeWithID, req, valueToSlugify })\n : defaultSlugify(valueToSlugify as string)\n\n const entity = collection || global!\n\n if (operation === 'create') {\n // Autosave drafts: do not auto-generate on the initial draft — the user is still entering content.\n // Keep the explicit non-slugified value (if any); generation begins on a later autosave.\n if (hasAutosaveEnabled(entity) && data?._status === 'draft') {\n return value || null\n }\n\n // Keep an explicitly provided slug; otherwise generate from the source.\n return await slugify(value || source)\n }\n\n const storedSlug = originalDoc?.[name]\n const originalSource = originalDoc?.[useAsSlug]\n\n // User explicitly edited the slug (or cleared the value): respect it.\n if (value !== undefined && value !== storedSlug) {\n return value\n }\n\n // No explicit edit this save. If the stored slug doesn't match what its source\n // would generate, it was customized on an earlier save keep it frozen.\n const storedSlugIsCustom = storedSlug && storedSlug !== (await slugify(originalSource))\n\n if (storedSlugIsCustom) {\n return storedSlug\n }\n\n if (!hasAutosaveEnabled(entity)) {\n // Non-autosave: generate once while empty, then freeze.\n return storedSlug || (await slugify(source))\n }\n\n // Autosave / drafts\n const priorVersions = await countVersions({\n collectionSlug: collection?.slug,\n globalSlug: global?.slug,\n parentID: originalDoc?.id,\n req,\n })\n\n // Do not generate on the very first draft (no prior version yet).\n if (priorVersions === 0) {\n return storedSlug ?? null\n }\n\n // Stabilize after publish to protect live URLs.\n if (data?._status === 'published' || originalDoc?._status === 'published') {\n return storedSlug\n }\n\n // Still auto-tracking an unpublished draft with content.\n return source ? await slugify(source) : null\n }\n"],"names":["hasAutosaveEnabled","slugify","defaultSlugify","countVersions","generateSlug","name","customSlugify","useAsSlug","collection","data","global","operation","originalDoc","req","value","source","valueToSlugify","entity","_status","storedSlug","originalSource","undefined","storedSlugIsCustom","priorVersions","collectionSlug","slug","globalSlug","parentID","id"],"mappings":"AAIA,SAASA,kBAAkB,QAAQ,0CAAyC;AAC5E,SAASC,WAAWC,cAAc,QAAQ,gCAA+B;AACzE,SAASC,aAAa,QAAQ,qBAAoB;AAQlD;;;;;;;;CAQC,GACD,OAAO,MAAMC,eACX,CAAC,EAAEC,IAAI,EAAEJ,SAASK,aAAa,EAAEC,SAAS,EAAQ,GAClD,OAAO,EAAEC,UAAU,EAAEC,IAAI,EAAEC,MAAM,EAAEC,SAAS,EAAEC,WAAW,EAAEC,GAAG,EAAEC,KAAK,EAAE;QACrE,MAAMC,SAASN,MAAM,CAACF,UAAU;QAEhC,MAAMN,UAAU,CAACe,iBACfV,gBACIA,cAAc;gBAAEG,MAAOA,QAAQ,CAAC;gBAAkBI;gBAAKG;YAAe,KACtEd,eAAec;QAErB,MAAMC,SAAST,cAAcE;QAE7B,IAAIC,cAAc,UAAU;YAC1B,mGAAmG;YACnG,yFAAyF;YACzF,IAAIX,mBAAmBiB,WAAWR,MAAMS,YAAY,SAAS;gBAC3D,OAAOJ,SAAS;YAClB;YAEA,wEAAwE;YACxE,OAAO,MAAMb,QAAQa,SAASC;QAChC;QAEA,MAAMI,aAAaP,aAAa,CAACP,KAAK;QACtC,MAAMe,iBAAiBR,aAAa,CAACL,UAAU;QAE/C,sEAAsE;QACtE,IAAIO,UAAUO,aAAaP,UAAUK,YAAY;YAC/C,OAAOL;QACT;QAEA,+EAA+E;QAC/E,yEAAyE;QACzE,MAAMQ,qBAAqBH,cAAcA,eAAgB,MAAMlB,QAAQmB;QAEvE,IAAIE,oBAAoB;YACtB,OAAOH;QACT;QAEA,IAAI,CAACnB,mBAAmBiB,SAAS;YAC/B,wDAAwD;YACxD,OAAOE,cAAe,MAAMlB,QAAQc;QACtC;QAEA,oBAAoB;QACpB,MAAMQ,gBAAgB,MAAMpB,cAAc;YACxCqB,gBAAgBhB,YAAYiB;YAC5BC,YAAYhB,QAAQe;YACpBE,UAAUf,aAAagB;YACvBf;QACF;QAEA,kEAAkE;QAClE,IAAIU,kBAAkB,GAAG;YACvB,OAAOJ,cAAc;QACvB;QAEA,gDAAgD;QAChD,IAAIV,MAAMS,YAAY,eAAeN,aAAaM,YAAY,aAAa;YACzE,OAAOC;QACT;QAEA,yDAAyD;QACzD,OAAOJ,SAAS,MAAMd,QAAQc,UAAU;IAC1C,EAAC"}
1
+ {"version":3,"sources":["../../../../src/fields/baseFields/slug/generateSlug.ts"],"sourcesContent":["import type { TypeWithID } from '../../../collections/config/types.js'\nimport type { FieldHook } from '../../config/types.js'\nimport type { Slugify } from './types.js'\n\nimport { ValidationError } from '../../../errors/index.js'\nimport { fieldValueExists } from '../../../utilities/fieldValueExists.js'\nimport { getUniqueFieldValue } from '../../../utilities/getUniqueFieldValue.js'\nimport { hasDraftsEnabled } from '../../../utilities/getVersionsConfig.js'\nimport { slugify as defaultSlugify } from '../../../utilities/slugify.js'\nimport { consumeSlugDuplicateFallback } from './duplicateContext.js'\nimport { getSlugFallbackValue } from './getSlugFallbackValue.js'\nimport { hasValue } from './hasValue.js'\n\ntype Args = {\n localized?: boolean\n name: string\n slugify?: Slugify\n useAsSlug?: string\n}\n\n/**\n * `beforeChange` hook for the native `slug` field.\n *\n * Fills the slug only while empty and never rewrites one that's set, so a lagging autosave can't\n * clobber it with a stale value:\n * - empty with no source falls back to `<singular>-<N>`, e.g. `posts-1` (see {@link getSlugFallbackValue})\n * - explicit input and the source field are slugified, e.g. \"Hello World\" → \"hello-world\"\n * - an already-set slug is preserved as-is\n *\n * Generated values dedupe against existing slugs; a localized slug is unique per-locale, so its\n * dedupe and fallback are scoped to the locale being written. Globals have no collection to dedupe\n * against, so their slug is left as-is.\n */\nexport const generateSlug =\n ({ name, localized, slugify: customSlugify, useAsSlug }: Args): FieldHook =>\n async ({ collection, context, data, operation, originalDoc, req, value }) => {\n const slugify = (valueToSlugify: unknown) =>\n customSlugify\n ? customSlugify({ data: (data ?? {}) as TypeWithID, req, valueToSlugify })\n : defaultSlugify(valueToSlugify as string)\n\n // A localized slug is unique only within its locale, so every uniqueness query below is scoped\n // to the locale being written.\n const locale = localized ? (req.locale ?? undefined) : undefined\n\n // A duplicated document:\n // - Takes a fresh `<singular>-<N>` fallbacknot the original's slug, not a source-derived one\n // - Skips the explicit-collision check below (see generateSlugBeforeDuplicate).\n if (collection && consumeSlugDuplicateFallback(context, name)) {\n return await getSlugFallbackValue({ collection, field: name, locale, req, slugify })\n }\n\n const storedSlug = originalDoc?.[name]\n\n const storedSlugHasValue = hasValue(storedSlug)\n\n // Explicit value from the client wins normalized through the field's slugify.\n // It must be unique: reject a collision rather than silently changing it,\n // only generated values are automatically deduped.\n // A value that slugifies to nothing (e.g. \"!!!\") isn't a usable slug,\n // so fall through to the source/fallback rather than store an empty one.\n if (hasValue(value)) {\n const slugified = await slugify(value)\n\n if (hasValue(slugified)) {\n // Unchanged from what's stored already unique, so skip the collision query. Autosave\n // resends the current slug on every tick; without this each tick runs a needless read.\n if (slugified === storedSlug) {\n return storedSlug\n }\n\n if (\n collection &&\n (await fieldValueExists({\n id: originalDoc?.id,\n collection: collection.slug,\n draftsEnabled: hasDraftsEnabled(collection),\n field: name,\n locale,\n req,\n value: slugified,\n }))\n ) {\n throw new ValidationError(\n { errors: [{ message: req.t('error:valueMustBeUnique'), path: name }] },\n req.t,\n )\n }\n\n return slugified\n }\n }\n\n // On update, preserve a slug that is already set — only fill it while empty.\n if (operation !== 'create' && storedSlugHasValue) {\n return storedSlug\n }\n\n // Derive an empty slug from its source, when present.\n // Dedupe so two documents don't both claim it if they have the same source value.\n // Globals have no collection to dedupe against.\n const source = useAsSlug ? data?.[useAsSlug] : undefined\n const derived = source ? await slugify(source) : undefined\n\n if (hasValue(derived)) {\n if (!collection) {\n return derived\n }\n\n return await getUniqueFieldValue({\n id: originalDoc?.id,\n collection: collection.slug,\n draftsEnabled: hasDraftsEnabled(collection),\n field: name,\n locale,\n req,\n value: derived as string,\n })\n }\n\n // No usable source: keep a stored value, otherwise fall back to `<singular>-<N>`.\n if (storedSlugHasValue) {\n return storedSlug\n }\n\n if (!collection) {\n return undefined\n }\n\n return await getSlugFallbackValue({ collection, field: name, locale, req, slugify })\n }\n"],"names":["ValidationError","fieldValueExists","getUniqueFieldValue","hasDraftsEnabled","slugify","defaultSlugify","consumeSlugDuplicateFallback","getSlugFallbackValue","hasValue","generateSlug","name","localized","customSlugify","useAsSlug","collection","context","data","operation","originalDoc","req","value","valueToSlugify","locale","undefined","field","storedSlug","storedSlugHasValue","slugified","id","slug","draftsEnabled","errors","message","t","path","source","derived"],"mappings":"AAIA,SAASA,eAAe,QAAQ,2BAA0B;AAC1D,SAASC,gBAAgB,QAAQ,yCAAwC;AACzE,SAASC,mBAAmB,QAAQ,4CAA2C;AAC/E,SAASC,gBAAgB,QAAQ,0CAAyC;AAC1E,SAASC,WAAWC,cAAc,QAAQ,gCAA+B;AACzE,SAASC,4BAA4B,QAAQ,wBAAuB;AACpE,SAASC,oBAAoB,QAAQ,4BAA2B;AAChE,SAASC,QAAQ,QAAQ,gBAAe;AASxC;;;;;;;;;;;;CAYC,GACD,OAAO,MAAMC,eACX,CAAC,EAAEC,IAAI,EAAEC,SAAS,EAAEP,SAASQ,aAAa,EAAEC,SAAS,EAAQ,GAC7D,OAAO,EAAEC,UAAU,EAAEC,OAAO,EAAEC,IAAI,EAAEC,SAAS,EAAEC,WAAW,EAAEC,GAAG,EAAEC,KAAK,EAAE;QACtE,MAAMhB,UAAU,CAACiB,iBACfT,gBACIA,cAAc;gBAAEI,MAAOA,QAAQ,CAAC;gBAAkBG;gBAAKE;YAAe,KACtEhB,eAAegB;QAErB,+FAA+F;QAC/F,+BAA+B;QAC/B,MAAMC,SAASX,YAAaQ,IAAIG,MAAM,IAAIC,YAAaA;QAEvD,yBAAyB;QACzB,iGAAiG;QACjG,iFAAiF;QACjF,IAAIT,cAAcR,6BAA6BS,SAASL,OAAO;YAC7D,OAAO,MAAMH,qBAAqB;gBAAEO;gBAAYU,OAAOd;gBAAMY;gBAAQH;gBAAKf;YAAQ;QACpF;QAEA,MAAMqB,aAAaP,aAAa,CAACR,KAAK;QAEtC,MAAMgB,qBAAqBlB,SAASiB;QAEpC,gFAAgF;QAChF,0EAA0E;QAC1E,mDAAmD;QACnD,sEAAsE;QACtE,yEAAyE;QACzE,IAAIjB,SAASY,QAAQ;YACnB,MAAMO,YAAY,MAAMvB,QAAQgB;YAEhC,IAAIZ,SAASmB,YAAY;gBACvB,uFAAuF;gBACvF,uFAAuF;gBACvF,IAAIA,cAAcF,YAAY;oBAC5B,OAAOA;gBACT;gBAEA,IACEX,cACC,MAAMb,iBAAiB;oBACtB2B,IAAIV,aAAaU;oBACjBd,YAAYA,WAAWe,IAAI;oBAC3BC,eAAe3B,iBAAiBW;oBAChCU,OAAOd;oBACPY;oBACAH;oBACAC,OAAOO;gBACT,IACA;oBACA,MAAM,IAAI3B,gBACR;wBAAE+B,QAAQ;4BAAC;gCAAEC,SAASb,IAAIc,CAAC,CAAC;gCAA4BC,MAAMxB;4BAAK;yBAAE;oBAAC,GACtES,IAAIc,CAAC;gBAET;gBAEA,OAAON;YACT;QACF;QAEA,6EAA6E;QAC7E,IAAIV,cAAc,YAAYS,oBAAoB;YAChD,OAAOD;QACT;QAEA,sDAAsD;QACtD,kFAAkF;QAClF,gDAAgD;QAChD,MAAMU,SAAStB,YAAYG,MAAM,CAACH,UAAU,GAAGU;QAC/C,MAAMa,UAAUD,SAAS,MAAM/B,QAAQ+B,UAAUZ;QAEjD,IAAIf,SAAS4B,UAAU;YACrB,IAAI,CAACtB,YAAY;gBACf,OAAOsB;YACT;YAEA,OAAO,MAAMlC,oBAAoB;gBAC/B0B,IAAIV,aAAaU;gBACjBd,YAAYA,WAAWe,IAAI;gBAC3BC,eAAe3B,iBAAiBW;gBAChCU,OAAOd;gBACPY;gBACAH;gBACAC,OAAOgB;YACT;QACF;QAEA,kFAAkF;QAClF,IAAIV,oBAAoB;YACtB,OAAOD;QACT;QAEA,IAAI,CAACX,YAAY;YACf,OAAOS;QACT;QAEA,OAAO,MAAMhB,qBAAqB;YAAEO;YAAYU,OAAOd;YAAMY;YAAQH;YAAKf;QAAQ;IACpF,EAAC"}
@@ -0,0 +1,18 @@
1
+ import type { FieldHook } from '../../config/types.js';
2
+ type Args = {
3
+ name: string;
4
+ };
5
+ /**
6
+ * `beforeDuplicate` hook for the native `slug` field.
7
+ *
8
+ * Marks the slug so the copy's `beforeChange` takes a fresh `<singular>-<N>` fallback instead of the
9
+ * original's slug or a source-derived one — see {@link consumeSlugDuplicateFallback} and
10
+ * {@link generateSlug}. Deferring to that path keeps the fallback deduped in one place.
11
+ *
12
+ * Returns `undefined` (not `''`) so a localized slug's non-active locales are dropped rather than
13
+ * stored as `''`, which two copies of the same source would collide on under the unique index. The
14
+ * active locale is regenerated by `beforeChange` via the mark.
15
+ */
16
+ export declare const generateSlugBeforeDuplicate: ({ name }: Args) => FieldHook;
17
+ export {};
18
+ //# sourceMappingURL=generateSlugBeforeDuplicate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generateSlugBeforeDuplicate.d.ts","sourceRoot":"","sources":["../../../../src/fields/baseFields/slug/generateSlugBeforeDuplicate.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAA;AAItD,KAAK,IAAI,GAAG;IACV,IAAI,EAAE,MAAM,CAAA;CACb,CAAA;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,2BAA2B,aAC3B,IAAI,KAAG,SAQjB,CAAA"}
@@ -0,0 +1,20 @@
1
+ import { markSlugForDuplicateFallback } from './duplicateContext.js';
2
+ /**
3
+ * `beforeDuplicate` hook for the native `slug` field.
4
+ *
5
+ * Marks the slug so the copy's `beforeChange` takes a fresh `<singular>-<N>` fallback instead of the
6
+ * original's slug or a source-derived one — see {@link consumeSlugDuplicateFallback} and
7
+ * {@link generateSlug}. Deferring to that path keeps the fallback deduped in one place.
8
+ *
9
+ * Returns `undefined` (not `''`) so a localized slug's non-active locales are dropped rather than
10
+ * stored as `''`, which two copies of the same source would collide on under the unique index. The
11
+ * active locale is regenerated by `beforeChange` via the mark.
12
+ */ export const generateSlugBeforeDuplicate = ({ name })=>({ collection, context })=>{
13
+ if (!collection) {
14
+ return undefined;
15
+ }
16
+ markSlugForDuplicateFallback(context, name);
17
+ return undefined;
18
+ };
19
+
20
+ //# sourceMappingURL=generateSlugBeforeDuplicate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/fields/baseFields/slug/generateSlugBeforeDuplicate.ts"],"sourcesContent":["import type { FieldHook } from '../../config/types.js'\n\nimport { markSlugForDuplicateFallback } from './duplicateContext.js'\n\ntype Args = {\n name: string\n}\n\n/**\n * `beforeDuplicate` hook for the native `slug` field.\n *\n * Marks the slug so the copy's `beforeChange` takes a fresh `<singular>-<N>` fallback instead of the\n * original's slug or a source-derived one — see {@link consumeSlugDuplicateFallback} and\n * {@link generateSlug}. Deferring to that path keeps the fallback deduped in one place.\n *\n * Returns `undefined` (not `''`) so a localized slug's non-active locales are dropped rather than\n * stored as `''`, which two copies of the same source would collide on under the unique index. The\n * active locale is regenerated by `beforeChange` via the mark.\n */\nexport const generateSlugBeforeDuplicate =\n ({ name }: Args): FieldHook =>\n ({ collection, context }) => {\n if (!collection) {\n return undefined\n }\n\n markSlugForDuplicateFallback(context, name)\n return undefined\n }\n"],"names":["markSlugForDuplicateFallback","generateSlugBeforeDuplicate","name","collection","context","undefined"],"mappings":"AAEA,SAASA,4BAA4B,QAAQ,wBAAuB;AAMpE;;;;;;;;;;CAUC,GACD,OAAO,MAAMC,8BACX,CAAC,EAAEC,IAAI,EAAQ,GACf,CAAC,EAAEC,UAAU,EAAEC,OAAO,EAAE;QACtB,IAAI,CAACD,YAAY;YACf,OAAOE;QACT;QAEAL,6BAA6BI,SAASF;QACtC,OAAOG;IACT,EAAC"}
@@ -0,0 +1,22 @@
1
+ import type { SanitizedCollectionConfig } from '../../../collections/config/types.js';
2
+ import type { DefaultDocumentIDType, Locale } from '../../../index.js';
3
+ import type { PayloadRequest } from '../../../types/index.js';
4
+ type Args = {
5
+ collection: SanitizedCollectionConfig;
6
+ field: string;
7
+ /** Exclude this doc from the check, so a regenerate can reuse its own value. */
8
+ id?: DefaultDocumentIDType;
9
+ /** Locale to scope the uniqueness check to, for a localized slug. */
10
+ locale?: Locale['code'];
11
+ req: PayloadRequest;
12
+ slugify: (value: unknown) => Promise<string | undefined> | string | undefined;
13
+ };
14
+ /**
15
+ * The slug a document falls back to when it has no source to derive from, e.g. `useAsSlug` is empty or missing.
16
+ * The fallback is unique within the collection and locale, so two documents never claim the same value.
17
+ * The format is: `<singular>-<N>`, where `N` is the first available integer. Uses the collection's singular
18
+ * label when it resolves to a plain string, otherwise the collection slug. See {@link getUniqueFieldValue}.
19
+ */
20
+ export declare const getSlugFallbackValue: ({ id, collection, field, locale, req, slugify, }: Args) => Promise<string>;
21
+ export {};
22
+ //# sourceMappingURL=getSlugFallbackValue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getSlugFallbackValue.d.ts","sourceRoot":"","sources":["../../../../src/fields/baseFields/slug/getSlugFallbackValue.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,sCAAsC,CAAA;AACrF,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAA;AACtE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAA;AAK7D,KAAK,IAAI,GAAG;IACV,UAAU,EAAE,yBAAyB,CAAA;IACrC,KAAK,EAAE,MAAM,CAAA;IACb,gFAAgF;IAChF,EAAE,CAAC,EAAE,qBAAqB,CAAA;IAC1B,qEAAqE;IACrE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,CAAC,CAAA;IACvB,GAAG,EAAE,cAAc,CAAA;IACnB,OAAO,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,GAAG,MAAM,GAAG,SAAS,CAAA;CAC9E,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB,qDAO9B,IAAI,KAAG,OAAO,CAAC,MAAM,CAcvB,CAAA"}
@@ -0,0 +1,23 @@
1
+ import { getUniqueFieldValue } from '../../../utilities/getUniqueFieldValue.js';
2
+ import { hasDraftsEnabled } from '../../../utilities/getVersionsConfig.js';
3
+ /**
4
+ * The slug a document falls back to when it has no source to derive from, e.g. `useAsSlug` is empty or missing.
5
+ * The fallback is unique within the collection and locale, so two documents never claim the same value.
6
+ * The format is: `<singular>-<N>`, where `N` is the first available integer. Uses the collection's singular
7
+ * label when it resolves to a plain string, otherwise the collection slug. See {@link getUniqueFieldValue}.
8
+ */ export const getSlugFallbackValue = async ({ id, collection, field, locale, req, slugify })=>{
9
+ const singularLabel = collection.labels?.singular;
10
+ const base = typeof singularLabel === 'string' ? singularLabel : collection.slug;
11
+ return getUniqueFieldValue({
12
+ id,
13
+ collection: collection.slug,
14
+ draftsEnabled: hasDraftsEnabled(collection),
15
+ field,
16
+ locale,
17
+ req,
18
+ startIndex: 1,
19
+ value: await slugify(base) || collection.slug
20
+ });
21
+ };
22
+
23
+ //# sourceMappingURL=getSlugFallbackValue.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/fields/baseFields/slug/getSlugFallbackValue.ts"],"sourcesContent":["import type { SanitizedCollectionConfig } from '../../../collections/config/types.js'\nimport type { DefaultDocumentIDType, Locale } from '../../../index.js'\nimport type { PayloadRequest } from '../../../types/index.js'\n\nimport { getUniqueFieldValue } from '../../../utilities/getUniqueFieldValue.js'\nimport { hasDraftsEnabled } from '../../../utilities/getVersionsConfig.js'\n\ntype Args = {\n collection: SanitizedCollectionConfig\n field: string\n /** Exclude this doc from the check, so a regenerate can reuse its own value. */\n id?: DefaultDocumentIDType\n /** Locale to scope the uniqueness check to, for a localized slug. */\n locale?: Locale['code']\n req: PayloadRequest\n slugify: (value: unknown) => Promise<string | undefined> | string | undefined\n}\n\n/**\n * The slug a document falls back to when it has no source to derive from, e.g. `useAsSlug` is empty or missing.\n * The fallback is unique within the collection and locale, so two documents never claim the same value.\n * The format is: `<singular>-<N>`, where `N` is the first available integer. Uses the collection's singular\n * label when it resolves to a plain string, otherwise the collection slug. See {@link getUniqueFieldValue}.\n */\nexport const getSlugFallbackValue = async ({\n id,\n collection,\n field,\n locale,\n req,\n slugify,\n}: Args): Promise<string> => {\n const singularLabel = collection.labels?.singular\n const base = typeof singularLabel === 'string' ? singularLabel : collection.slug\n\n return getUniqueFieldValue({\n id,\n collection: collection.slug,\n draftsEnabled: hasDraftsEnabled(collection),\n field,\n locale,\n req,\n startIndex: 1,\n value: (await slugify(base)) || collection.slug,\n })\n}\n"],"names":["getUniqueFieldValue","hasDraftsEnabled","getSlugFallbackValue","id","collection","field","locale","req","slugify","singularLabel","labels","singular","base","slug","draftsEnabled","startIndex","value"],"mappings":"AAIA,SAASA,mBAAmB,QAAQ,4CAA2C;AAC/E,SAASC,gBAAgB,QAAQ,0CAAyC;AAa1E;;;;;CAKC,GACD,OAAO,MAAMC,uBAAuB,OAAO,EACzCC,EAAE,EACFC,UAAU,EACVC,KAAK,EACLC,MAAM,EACNC,GAAG,EACHC,OAAO,EACF;IACL,MAAMC,gBAAgBL,WAAWM,MAAM,EAAEC;IACzC,MAAMC,OAAO,OAAOH,kBAAkB,WAAWA,gBAAgBL,WAAWS,IAAI;IAEhF,OAAOb,oBAAoB;QACzBG;QACAC,YAAYA,WAAWS,IAAI;QAC3BC,eAAeb,iBAAiBG;QAChCC;QACAC;QACAC;QACAQ,YAAY;QACZC,OAAO,AAAC,MAAMR,QAAQI,SAAUR,WAAWS,IAAI;IACjD;AACF,EAAC"}
@@ -0,0 +1,3 @@
1
+ /** A slug counts as set only when non-empty; `null`/`undefined`/`''` all mean "no slug yet". */
2
+ export declare const hasValue: (value: unknown) => boolean;
3
+ //# sourceMappingURL=hasValue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hasValue.d.ts","sourceRoot":"","sources":["../../../../src/fields/baseFields/slug/hasValue.ts"],"names":[],"mappings":"AAAA,gGAAgG;AAChG,eAAO,MAAM,QAAQ,UAAW,OAAO,KAAG,OACa,CAAA"}
@@ -0,0 +1,3 @@
1
+ /** A slug counts as set only when non-empty; `null`/`undefined`/`''` all mean "no slug yet". */ export const hasValue = (value)=>value !== undefined && value !== null && value !== '';
2
+
3
+ //# sourceMappingURL=hasValue.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/fields/baseFields/slug/hasValue.ts"],"sourcesContent":["/** A slug counts as set only when non-empty; `null`/`undefined`/`''` all mean \"no slug yet\". */\nexport const hasValue = (value: unknown): boolean =>\n value !== undefined && value !== null && value !== ''\n"],"names":["hasValue","value","undefined"],"mappings":"AAAA,8FAA8F,GAC9F,OAAO,MAAMA,WAAW,CAACC,QACvBA,UAAUC,aAAaD,UAAU,QAAQA,UAAU,GAAE"}