@payloadcms/plugin-cloud-storage 4.0.0-internal.8001944 → 4.0.0-internal.8089ef7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/dist/fields/getFields.d.ts.map +1 -1
  2. package/dist/fields/getFields.js +73 -8
  3. package/dist/fields/getFields.js.map +1 -1
  4. package/dist/hooks/afterChange.d.ts +3 -1
  5. package/dist/hooks/afterChange.d.ts.map +1 -1
  6. package/dist/hooks/afterChange.js +64 -6
  7. package/dist/hooks/afterChange.js.map +1 -1
  8. package/dist/hooks/afterDelete.d.ts.map +1 -1
  9. package/dist/hooks/afterDelete.js +10 -2
  10. package/dist/hooks/afterDelete.js.map +1 -1
  11. package/dist/hooks/afterRead.d.ts +6 -1
  12. package/dist/hooks/afterRead.d.ts.map +1 -1
  13. package/dist/hooks/afterRead.js +20 -6
  14. package/dist/hooks/afterRead.js.map +1 -1
  15. package/dist/hooks/beforeChange.d.ts +2 -1
  16. package/dist/hooks/beforeChange.d.ts.map +1 -1
  17. package/dist/hooks/beforeChange.js +7 -4
  18. package/dist/hooks/beforeChange.js.map +1 -1
  19. package/dist/hooks/publicOriginalURL.d.ts +8 -0
  20. package/dist/hooks/publicOriginalURL.d.ts.map +1 -0
  21. package/dist/hooks/publicOriginalURL.js +34 -0
  22. package/dist/hooks/publicOriginalURL.js.map +1 -0
  23. package/dist/plugin.d.ts.map +1 -1
  24. package/dist/plugin.js +29 -4
  25. package/dist/plugin.js.map +1 -1
  26. package/dist/types.d.ts +26 -1
  27. package/dist/types.d.ts.map +1 -1
  28. package/dist/types.js.map +1 -1
  29. package/dist/utilities/createFileOperations.d.ts +13 -0
  30. package/dist/utilities/createFileOperations.d.ts.map +1 -0
  31. package/dist/utilities/createFileOperations.js +258 -0
  32. package/dist/utilities/createFileOperations.js.map +1 -0
  33. package/dist/utilities/getFilePrefix.d.ts +2 -5
  34. package/dist/utilities/getFilePrefix.d.ts.map +1 -1
  35. package/dist/utilities/getFilePrefix.js +25 -10
  36. package/dist/utilities/getFilePrefix.js.map +1 -1
  37. package/dist/utilities/getIncomingFiles.js +2 -2
  38. package/dist/utilities/getIncomingFiles.js.map +1 -1
  39. package/dist/utilities/getStorageLocationSelect.d.ts +9 -0
  40. package/dist/utilities/getStorageLocationSelect.d.ts.map +1 -0
  41. package/dist/utilities/getStorageLocationSelect.js +54 -0
  42. package/dist/utilities/getStorageLocationSelect.js.map +1 -0
  43. package/dist/utilities/resolveSignedURLKey.d.ts.map +1 -1
  44. package/dist/utilities/resolveSignedURLKey.js +15 -7
  45. package/dist/utilities/resolveSignedURLKey.js.map +1 -1
  46. package/package.json +4 -4
@@ -1 +1 @@
1
- {"version":3,"file":"getFields.d.ts","sourceRoot":"","sources":["../../src/fields/getFields.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,KAAK,EAAyB,MAAM,SAAS,CAAA;AAI7E,OAAO,KAAK,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAMpE,UAAU,IAAI;IACZ,OAAO,CAAC,EAAE,gBAAgB,CAAA;IAC1B,UAAU,EAAE,gBAAgB,CAAA;IAC5B,2BAA2B,CAAC,EAAE,IAAI,CAAA;IAClC,eAAe,CAAC,EAAE,eAAe,CAAA;IACjC,MAAM,CAAC,EAAE,MAAM,CAAA;IACf;;;OAGG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAA;CAC/B;AAED,eAAO,MAAM,SAAS,yGAOnB,IAAI,KAAG,KAAK,EA2Md,CAAA"}
1
+ {"version":3,"file":"getFields.d.ts","sourceRoot":"","sources":["../../src/fields/getFields.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,KAAK,EAAgD,MAAM,SAAS,CAAA;AAIpG,OAAO,KAAK,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAMpE,UAAU,IAAI;IACZ,OAAO,CAAC,EAAE,gBAAgB,CAAA;IAC1B,UAAU,EAAE,gBAAgB,CAAA;IAC5B,2BAA2B,CAAC,EAAE,IAAI,CAAA;IAClC,eAAe,CAAC,EAAE,eAAe,CAAA;IACjC,MAAM,CAAC,EAAE,MAAM,CAAA;IACf;;;OAGG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAA;CAC/B;AAED,eAAO,MAAM,SAAS,yGAOnB,IAAI,KAAG,KAAK,EAgSd,CAAA"}
@@ -26,11 +26,27 @@ export const getFields = ({ adapter, collection, disablePayloadAccessControl, ge
26
26
  readOnly: true
27
27
  }
28
28
  };
29
- // Server-owned key segment; hidden from the API and admin, read internally via showHiddenFields.
29
+ // Server-owned key segment. Field-level `hidden` would remove it before the URL hooks can read it.
30
30
  const baseObjectKeyField = {
31
31
  name: '_objectKey',
32
32
  type: 'text',
33
- hidden: true
33
+ admin: {
34
+ disabled: {
35
+ bulkEdit: true,
36
+ column: true,
37
+ filter: true,
38
+ groupBy: true
39
+ },
40
+ hidden: true,
41
+ readOnly: true
42
+ }
43
+ };
44
+ const storedPrefixField = {
45
+ ...basePrefixField,
46
+ admin: {
47
+ ...basePrefixField.admin,
48
+ disabled: true
49
+ }
34
50
  };
35
51
  const fields = [
36
52
  ...collection.fields,
@@ -80,10 +96,54 @@ export const getFields = ({ adapter, collection, disablePayloadAccessControl, ge
80
96
  ...existingURLField || {}
81
97
  });
82
98
  }
83
- if (typeof collection.upload === 'object' && collection.upload.imageSizes) {
99
+ let originalField = fields.find((field)=>field.type === 'group' && 'name' in field && field.name === 'original');
100
+ if (adapter && !originalField) {
101
+ originalField = {
102
+ name: 'original',
103
+ type: 'group',
104
+ fields: [
105
+ baseURLField
106
+ ]
107
+ };
108
+ fields.push(originalField);
109
+ }
110
+ const originalURLFieldIndex = originalField?.fields.findIndex((field)=>'name' in field && field.name === 'url');
111
+ if (adapter && originalField && originalURLFieldIndex !== undefined && originalURLFieldIndex >= 0) {
112
+ const originalURLField = originalField.fields[originalURLFieldIndex];
113
+ originalField.fields[originalURLFieldIndex] = {
114
+ ...baseURLField,
115
+ ...originalURLField,
116
+ hooks: {
117
+ afterRead: [
118
+ getAfterReadHook({
119
+ adapter,
120
+ collection,
121
+ disablePayloadAccessControl,
122
+ generateFileURL,
123
+ isOriginal: true
124
+ }),
125
+ ...originalURLField.hooks?.afterRead || []
126
+ ],
127
+ beforeChange: [
128
+ getBeforeChangeHook({
129
+ adapter,
130
+ collection,
131
+ disablePayloadAccessControl,
132
+ generateFileURL,
133
+ isOriginal: true
134
+ }),
135
+ ...originalURLField.hooks?.beforeChange || []
136
+ ]
137
+ }
138
+ };
139
+ }
140
+ // Storage adapters add these fields during their `init`, after transformers (e.g. Sharp) have
141
+ // written each collection's image sizes onto its upload config.
142
+ const variants = typeof collection.upload === 'object' ? collection.upload.variants : undefined;
143
+ if (variants) {
84
144
  let existingSizesFieldIndex = -1;
85
145
  const existingSizesField = fields.find((existingField, i)=>{
86
- if ('name' in existingField && existingField.name === 'sizes') {
146
+ if ('name' in existingField && existingField.name === 'variants') {
87
147
  existingSizesFieldIndex = i;
88
148
  return true;
89
149
  }
@@ -94,12 +154,12 @@ export const getFields = ({ adapter, collection, disablePayloadAccessControl, ge
94
154
  }
95
155
  const sizesField = {
96
156
  ...existingSizesField || {},
97
- name: 'sizes',
157
+ name: 'variants',
98
158
  type: 'group',
99
159
  admin: {
100
160
  hidden: true
101
161
  },
102
- fields: collection.upload.imageSizes.map((size)=>{
162
+ fields: variants.map((size)=>{
103
163
  const existingSizeField = existingSizesField?.fields.find((existingField)=>'name' in existingField && existingField.name === size.name);
104
164
  const existingSizeURLField = existingSizeField?.fields.find((existingField)=>'name' in existingField && existingField.name === 'url');
105
165
  // Only add afterRead hook if adapter is provided
@@ -137,8 +197,13 @@ export const getFields = ({ adapter, collection, disablePayloadAccessControl, ge
137
197
  name: size.name,
138
198
  type: 'group',
139
199
  fields: [
140
- ...adapter?.fields || [],
141
- sizeURLField
200
+ ...(adapter?.fields || []).filter((field)=>!('name' in field && [
201
+ '_objectKey',
202
+ 'prefix'
203
+ ].includes(field.name))),
204
+ sizeURLField,
205
+ storedPrefixField,
206
+ baseObjectKeyField
142
207
  ]
143
208
  };
144
209
  })
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/fields/getFields.ts"],"sourcesContent":["import type { CollectionConfig, Field, GroupField, TextField } from 'payload'\n\nimport path from 'path'\n\nimport type { GeneratedAdapter, GenerateFileURL } from '../types.js'\n\nimport { getAfterReadHook } from '../hooks/afterRead.js'\nimport { getBeforeChangeHook } from '../hooks/beforeChange.js'\nimport { getNormalizeUploadPrefixFieldHook } from '../hooks/normalizeUploadPrefix.js'\n\ninterface Args {\n adapter?: GeneratedAdapter\n collection: CollectionConfig\n disablePayloadAccessControl?: true\n generateFileURL?: GenerateFileURL\n prefix?: string\n /**\n * When true, do not default the `prefix` field to the collection prefix; the\n * document field holds only the document-level segment.\n */\n useCompositePrefixes?: boolean\n}\n\nexport const getFields = ({\n adapter,\n collection,\n disablePayloadAccessControl,\n generateFileURL,\n prefix,\n useCompositePrefixes = false,\n}: Args): Field[] => {\n const baseURLField: TextField = {\n name: 'url',\n type: 'text',\n admin: {\n hidden: true,\n readOnly: true,\n },\n label: 'URL',\n }\n\n const basePrefixField: TextField = {\n name: 'prefix',\n type: 'text',\n admin: {\n disabled: {\n bulkEdit: true,\n column: true,\n filter: true,\n groupBy: true,\n },\n hidden: true,\n readOnly: true,\n },\n }\n\n // Server-owned key segment; hidden from the API and admin, read internally via showHiddenFields.\n const baseObjectKeyField: TextField = {\n name: '_objectKey',\n type: 'text',\n hidden: true,\n }\n\n const fields = [...collection.fields, ...(adapter?.fields || [])]\n\n // Inject a hook into all URL fields to generate URLs\n\n let existingURLFieldIndex = -1\n\n const existingURLField = fields.find((existingField, i) => {\n if ('name' in existingField && existingField.name === 'url') {\n existingURLFieldIndex = i\n return true\n }\n return false\n }) as TextField\n\n if (existingURLFieldIndex > -1) {\n fields.splice(existingURLFieldIndex, 1)\n }\n\n // Only add afterRead hook if adapter is provided\n if (adapter) {\n fields.push({\n ...baseURLField,\n ...(existingURLField || {}),\n hooks: {\n afterRead: [\n getAfterReadHook({ adapter, collection, disablePayloadAccessControl, generateFileURL }),\n ...(existingURLField?.hooks?.afterRead || []),\n ],\n beforeChange: [\n getBeforeChangeHook({\n adapter,\n collection,\n disablePayloadAccessControl,\n generateFileURL,\n }),\n ...(existingURLField?.hooks?.beforeChange || []),\n ],\n },\n } as TextField)\n } else {\n fields.push({\n ...baseURLField,\n ...(existingURLField || {}),\n } as TextField)\n }\n\n if (typeof collection.upload === 'object' && collection.upload.imageSizes) {\n let existingSizesFieldIndex = -1\n\n const existingSizesField = fields.find((existingField, i) => {\n if ('name' in existingField && existingField.name === 'sizes') {\n existingSizesFieldIndex = i\n return true\n }\n\n return false\n }) as GroupField\n\n if (existingSizesFieldIndex > -1) {\n fields.splice(existingSizesFieldIndex, 1)\n }\n\n const sizesField: Field = {\n ...(existingSizesField || {}),\n name: 'sizes',\n type: 'group',\n admin: {\n hidden: true,\n },\n fields: collection.upload.imageSizes.map((size) => {\n const existingSizeField = existingSizesField?.fields.find(\n (existingField) => 'name' in existingField && existingField.name === size.name,\n ) as GroupField\n\n const existingSizeURLField = existingSizeField?.fields.find(\n (existingField) => 'name' in existingField && existingField.name === 'url',\n ) as TextField\n\n // Only add afterRead hook if adapter is provided\n const sizeURLField: TextField = adapter\n ? ({\n ...(existingSizeURLField || {}),\n ...baseURLField,\n hooks: {\n afterRead: [\n getAfterReadHook({\n adapter,\n collection,\n disablePayloadAccessControl,\n generateFileURL,\n size,\n }),\n ...((typeof existingSizeURLField === 'object' &&\n 'hooks' in existingSizeURLField &&\n existingSizeURLField?.hooks?.afterRead) ||\n []),\n ],\n beforeChange: [\n getBeforeChangeHook({\n adapter,\n collection,\n disablePayloadAccessControl,\n generateFileURL,\n size,\n }),\n ...((typeof existingSizeURLField === 'object' &&\n 'hooks' in existingSizeURLField &&\n existingSizeURLField?.hooks?.beforeChange) ||\n []),\n ],\n },\n } as TextField)\n : ({\n ...(existingSizeURLField || {}),\n ...baseURLField,\n } as TextField)\n\n return {\n ...existingSizeField,\n name: size.name,\n type: 'group',\n fields: [...(adapter?.fields || []), sizeURLField],\n } as Field\n }),\n }\n\n fields.push(sizesField)\n }\n\n // Always insert the prefix field so the schema stays consistent regardless of\n // whether the plugin is enabled or a prefix is configured.\n let existingPrefixFieldIndex = -1\n\n const existingPrefixField = fields.find((existingField, i) => {\n if ('name' in existingField && existingField.name === 'prefix') {\n existingPrefixFieldIndex = i\n return true\n }\n return false\n }) as TextField\n\n if (existingPrefixFieldIndex > -1) {\n fields.splice(existingPrefixFieldIndex, 1)\n }\n\n fields.push({\n ...basePrefixField,\n ...(existingPrefixField || {}),\n defaultValue:\n existingPrefixField?.defaultValue ??\n (useCompositePrefixes ? '' : prefix ? path.posix.join(prefix) : ''),\n hooks: {\n ...existingPrefixField?.hooks,\n beforeChange: [\n ...(existingPrefixField?.hooks?.beforeChange || []),\n getNormalizeUploadPrefixFieldHook({ collectionPrefix: prefix, useCompositePrefixes }),\n ],\n },\n } as TextField)\n\n const existingObjectKeyFieldIndex = fields.findIndex(\n (existingField) => 'name' in existingField && existingField.name === '_objectKey',\n )\n if (existingObjectKeyFieldIndex > -1) {\n fields.splice(existingObjectKeyFieldIndex, 1)\n }\n\n fields.push({ ...baseObjectKeyField } as TextField)\n\n return fields\n}\n"],"names":["path","getAfterReadHook","getBeforeChangeHook","getNormalizeUploadPrefixFieldHook","getFields","adapter","collection","disablePayloadAccessControl","generateFileURL","prefix","useCompositePrefixes","baseURLField","name","type","admin","hidden","readOnly","label","basePrefixField","disabled","bulkEdit","column","filter","groupBy","baseObjectKeyField","fields","existingURLFieldIndex","existingURLField","find","existingField","i","splice","push","hooks","afterRead","beforeChange","upload","imageSizes","existingSizesFieldIndex","existingSizesField","sizesField","map","size","existingSizeField","existingSizeURLField","sizeURLField","existingPrefixFieldIndex","existingPrefixField","defaultValue","posix","join","collectionPrefix","existingObjectKeyFieldIndex","findIndex"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/fields/getFields.ts"],"sourcesContent":["import type { CollectionConfig, Field, GroupField, SanitizedUploadConfig, TextField } from 'payload'\n\nimport path from 'path'\n\nimport type { GeneratedAdapter, GenerateFileURL } from '../types.js'\n\nimport { getAfterReadHook } from '../hooks/afterRead.js'\nimport { getBeforeChangeHook } from '../hooks/beforeChange.js'\nimport { getNormalizeUploadPrefixFieldHook } from '../hooks/normalizeUploadPrefix.js'\n\ninterface Args {\n adapter?: GeneratedAdapter\n collection: CollectionConfig\n disablePayloadAccessControl?: true\n generateFileURL?: GenerateFileURL\n prefix?: string\n /**\n * When true, do not default the `prefix` field to the collection prefix; the\n * document field holds only the document-level segment.\n */\n useCompositePrefixes?: boolean\n}\n\nexport const getFields = ({\n adapter,\n collection,\n disablePayloadAccessControl,\n generateFileURL,\n prefix,\n useCompositePrefixes = false,\n}: Args): Field[] => {\n const baseURLField: TextField = {\n name: 'url',\n type: 'text',\n admin: {\n hidden: true,\n readOnly: true,\n },\n label: 'URL',\n }\n\n const basePrefixField: TextField = {\n name: 'prefix',\n type: 'text',\n admin: {\n disabled: {\n bulkEdit: true,\n column: true,\n filter: true,\n groupBy: true,\n },\n hidden: true,\n readOnly: true,\n },\n }\n\n // Server-owned key segment. Field-level `hidden` would remove it before the URL hooks can read it.\n const baseObjectKeyField: TextField = {\n name: '_objectKey',\n type: 'text',\n admin: {\n disabled: {\n bulkEdit: true,\n column: true,\n filter: true,\n groupBy: true,\n },\n hidden: true,\n readOnly: true,\n },\n }\n\n const storedPrefixField: TextField = {\n ...basePrefixField,\n admin: {\n ...basePrefixField.admin,\n disabled: true,\n },\n }\n\n const fields = [...collection.fields, ...(adapter?.fields || [])]\n\n // Inject a hook into all URL fields to generate URLs\n\n let existingURLFieldIndex = -1\n\n const existingURLField = fields.find((existingField, i) => {\n if ('name' in existingField && existingField.name === 'url') {\n existingURLFieldIndex = i\n return true\n }\n return false\n }) as TextField\n\n if (existingURLFieldIndex > -1) {\n fields.splice(existingURLFieldIndex, 1)\n }\n\n // Only add afterRead hook if adapter is provided\n if (adapter) {\n fields.push({\n ...baseURLField,\n ...(existingURLField || {}),\n hooks: {\n afterRead: [\n getAfterReadHook({ adapter, collection, disablePayloadAccessControl, generateFileURL }),\n ...(existingURLField?.hooks?.afterRead || []),\n ],\n beforeChange: [\n getBeforeChangeHook({\n adapter,\n collection,\n disablePayloadAccessControl,\n generateFileURL,\n }),\n ...(existingURLField?.hooks?.beforeChange || []),\n ],\n },\n } as TextField)\n } else {\n fields.push({\n ...baseURLField,\n ...(existingURLField || {}),\n } as TextField)\n }\n\n let originalField = fields.find(\n (field): field is GroupField =>\n field.type === 'group' && 'name' in field && field.name === 'original',\n )\n\n if (adapter && !originalField) {\n originalField = {\n name: 'original',\n type: 'group',\n fields: [baseURLField],\n }\n fields.push(originalField)\n }\n\n const originalURLFieldIndex = originalField?.fields.findIndex(\n (field) => 'name' in field && field.name === 'url',\n )\n\n if (\n adapter &&\n originalField &&\n originalURLFieldIndex !== undefined &&\n originalURLFieldIndex >= 0\n ) {\n const originalURLField = originalField.fields[originalURLFieldIndex] as TextField\n\n originalField.fields[originalURLFieldIndex] = {\n ...baseURLField,\n ...originalURLField,\n hooks: {\n afterRead: [\n getAfterReadHook({\n adapter,\n collection,\n disablePayloadAccessControl,\n generateFileURL,\n isOriginal: true,\n }),\n ...(originalURLField.hooks?.afterRead || []),\n ],\n beforeChange: [\n getBeforeChangeHook({\n adapter,\n collection,\n disablePayloadAccessControl,\n generateFileURL,\n isOriginal: true,\n }),\n ...(originalURLField.hooks?.beforeChange || []),\n ],\n },\n } as TextField\n }\n\n // Storage adapters add these fields during their `init`, after transformers (e.g. Sharp) have\n // written each collection's image sizes onto its upload config.\n const variants =\n typeof collection.upload === 'object'\n ? (collection.upload as SanitizedUploadConfig).variants\n : undefined\n\n if (variants) {\n let existingSizesFieldIndex = -1\n\n const existingSizesField = fields.find((existingField, i) => {\n if ('name' in existingField && existingField.name === 'variants') {\n existingSizesFieldIndex = i\n return true\n }\n\n return false\n }) as GroupField\n\n if (existingSizesFieldIndex > -1) {\n fields.splice(existingSizesFieldIndex, 1)\n }\n\n const sizesField: Field = {\n ...(existingSizesField || {}),\n name: 'variants',\n type: 'group',\n admin: {\n hidden: true,\n },\n fields: variants.map((size) => {\n const existingSizeField = existingSizesField?.fields.find(\n (existingField) => 'name' in existingField && existingField.name === size.name,\n ) as GroupField\n\n const existingSizeURLField = existingSizeField?.fields.find(\n (existingField) => 'name' in existingField && existingField.name === 'url',\n ) as TextField\n\n // Only add afterRead hook if adapter is provided\n const sizeURLField: TextField = adapter\n ? ({\n ...(existingSizeURLField || {}),\n ...baseURLField,\n hooks: {\n afterRead: [\n getAfterReadHook({\n adapter,\n collection,\n disablePayloadAccessControl,\n generateFileURL,\n size,\n }),\n ...((typeof existingSizeURLField === 'object' &&\n 'hooks' in existingSizeURLField &&\n existingSizeURLField?.hooks?.afterRead) ||\n []),\n ],\n beforeChange: [\n getBeforeChangeHook({\n adapter,\n collection,\n disablePayloadAccessControl,\n generateFileURL,\n size,\n }),\n ...((typeof existingSizeURLField === 'object' &&\n 'hooks' in existingSizeURLField &&\n existingSizeURLField?.hooks?.beforeChange) ||\n []),\n ],\n },\n } as TextField)\n : ({\n ...(existingSizeURLField || {}),\n ...baseURLField,\n } as TextField)\n\n return {\n ...existingSizeField,\n name: size.name,\n type: 'group',\n fields: [\n ...(adapter?.fields || []).filter(\n (field) => !('name' in field && ['_objectKey', 'prefix'].includes(field.name)),\n ),\n sizeURLField,\n storedPrefixField,\n baseObjectKeyField,\n ],\n } as Field\n }),\n }\n\n fields.push(sizesField)\n }\n\n // Always insert the prefix field so the schema stays consistent regardless of\n // whether the plugin is enabled or a prefix is configured.\n let existingPrefixFieldIndex = -1\n\n const existingPrefixField = fields.find((existingField, i) => {\n if ('name' in existingField && existingField.name === 'prefix') {\n existingPrefixFieldIndex = i\n return true\n }\n return false\n }) as TextField\n\n if (existingPrefixFieldIndex > -1) {\n fields.splice(existingPrefixFieldIndex, 1)\n }\n\n fields.push({\n ...basePrefixField,\n ...(existingPrefixField || {}),\n defaultValue:\n existingPrefixField?.defaultValue ??\n (useCompositePrefixes ? '' : prefix ? path.posix.join(prefix) : ''),\n hooks: {\n ...existingPrefixField?.hooks,\n beforeChange: [\n ...(existingPrefixField?.hooks?.beforeChange || []),\n getNormalizeUploadPrefixFieldHook({ collectionPrefix: prefix, useCompositePrefixes }),\n ],\n },\n } as TextField)\n\n const existingObjectKeyFieldIndex = fields.findIndex(\n (existingField) => 'name' in existingField && existingField.name === '_objectKey',\n )\n if (existingObjectKeyFieldIndex > -1) {\n fields.splice(existingObjectKeyFieldIndex, 1)\n }\n\n fields.push({ ...baseObjectKeyField } as TextField)\n\n return fields\n}\n"],"names":["path","getAfterReadHook","getBeforeChangeHook","getNormalizeUploadPrefixFieldHook","getFields","adapter","collection","disablePayloadAccessControl","generateFileURL","prefix","useCompositePrefixes","baseURLField","name","type","admin","hidden","readOnly","label","basePrefixField","disabled","bulkEdit","column","filter","groupBy","baseObjectKeyField","storedPrefixField","fields","existingURLFieldIndex","existingURLField","find","existingField","i","splice","push","hooks","afterRead","beforeChange","originalField","field","originalURLFieldIndex","findIndex","undefined","originalURLField","isOriginal","variants","upload","existingSizesFieldIndex","existingSizesField","sizesField","map","size","existingSizeField","existingSizeURLField","sizeURLField","includes","existingPrefixFieldIndex","existingPrefixField","defaultValue","posix","join","collectionPrefix","existingObjectKeyFieldIndex"],"mappings":"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"}
@@ -4,8 +4,10 @@ interface Args {
4
4
  adapter: GeneratedAdapter;
5
5
  collection: CollectionConfig;
6
6
  collectionPrefix?: string;
7
+ disablePayloadAccessControl?: boolean;
8
+ hasCustomFileURL?: boolean;
7
9
  useCompositePrefixes?: boolean;
8
10
  }
9
- export declare const getAfterChangeHook: ({ adapter, collection, collectionPrefix, useCompositePrefixes, }: Args) => CollectionAfterChangeHook<FileData & TypeWithID>;
11
+ export declare const getAfterChangeHook: ({ adapter, collection, collectionPrefix, disablePayloadAccessControl, hasCustomFileURL, useCompositePrefixes, }: Args) => CollectionAfterChangeHook<FileData & TypeWithID>;
10
12
  export {};
11
13
  //# sourceMappingURL=afterChange.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"afterChange.d.ts","sourceRoot":"","sources":["../../src/hooks/afterChange.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,yBAAyB,EAAE,gBAAgB,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AAIhG,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAA;AASnD,UAAU,IAAI;IACZ,OAAO,EAAE,gBAAgB,CAAA;IACzB,UAAU,EAAE,gBAAgB,CAAA;IAC5B,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,oBAAoB,CAAC,EAAE,OAAO,CAAA;CAC/B;AAQD,eAAO,MAAM,kBAAkB,qEAM1B,IAAI,KAAG,yBAAyB,CAAC,QAAQ,GAAG,UAAU,CA8KxD,CAAA"}
1
+ {"version":3,"file":"afterChange.d.ts","sourceRoot":"","sources":["../../src/hooks/afterChange.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,yBAAyB,EAAE,gBAAgB,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AAIhG,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAA;AAUnD,UAAU,IAAI;IACZ,OAAO,EAAE,gBAAgB,CAAA;IACzB,UAAU,EAAE,gBAAgB,CAAA;IAC5B,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,2BAA2B,CAAC,EAAE,OAAO,CAAA;IACrC,gBAAgB,CAAC,EAAE,OAAO,CAAA;IAC1B,oBAAoB,CAAC,EAAE,OAAO,CAAA;CAC/B;AAQD,eAAO,MAAM,kBAAkB,oHAQ1B,IAAI,KAAG,yBAAyB,CAAC,QAAQ,GAAG,UAAU,CA2OxD,CAAA"}
@@ -2,6 +2,7 @@ import { deepMergeWithSourceArrays } from 'payload';
2
2
  import { buildPrefixWithObjectKey } from '../utilities/buildPrefixWithObjectKey.js';
3
3
  import { buildStoragePathData, buildUploadStoragePathData } from '../utilities/buildStoragePathData.js';
4
4
  import { getIncomingFiles } from '../utilities/getIncomingFiles.js';
5
+ import { appendProxyPrefix } from './afterRead.js';
5
6
  // The object's folder: semantic prefix + `_objectKey` segment.
6
7
  const getObjectFolder = (data)=>{
7
8
  const record = data ?? {};
@@ -10,15 +11,72 @@ const getObjectFolder = (data)=>{
10
11
  prefix: record.prefix
11
12
  });
12
13
  };
13
- export const getAfterChangeHook = ({ adapter, collection, collectionPrefix, useCompositePrefixes })=>async ({ data, doc, operation, previousDoc, req, select })=>{
14
+ export const getAfterChangeHook = ({ adapter, collection, collectionPrefix, disablePayloadAccessControl, hasCustomFileURL, useCompositePrefixes })=>async ({ data, doc, operation, previousDoc, req, select })=>{
14
15
  // Skip if this is an internal update to prevent infinite loop
15
16
  if (req.context?.skipCloudStorage) {
16
17
  return doc;
17
18
  }
18
19
  // Restore upload metadata removed by select, including partially selected image sizes.
19
20
  const uploadData = select ? deepMergeWithSourceArrays(data, doc) : doc;
21
+ const withProxyPrefix = (upload)=>{
22
+ const { prefix } = upload;
23
+ if (disablePayloadAccessControl || hasCustomFileURL || !useCompositePrefixes || !prefix) {
24
+ return upload;
25
+ }
26
+ return {
27
+ ...upload,
28
+ ...upload.url && {
29
+ url: appendProxyPrefix({
30
+ prefix,
31
+ url: upload.url
32
+ })
33
+ },
34
+ ...upload.original?.url && {
35
+ original: {
36
+ ...upload.original,
37
+ url: appendProxyPrefix({
38
+ prefix,
39
+ url: upload.original.url
40
+ })
41
+ }
42
+ }
43
+ };
44
+ };
20
45
  const isDraftSave = uploadData._status === 'draft';
21
46
  const isDraftOverPublished = isDraftSave && previousDoc?._status === 'published';
47
+ if (req.context?._payloadManagedCloudStorage) {
48
+ const metadata = req.context._payloadManagedCloudMetadata;
49
+ if (!metadata || Object.keys(metadata).length === 0) {
50
+ return withProxyPrefix(doc);
51
+ }
52
+ req.context.skipCloudStorage = true;
53
+ req.file = undefined;
54
+ req.payloadUploadSizes = undefined;
55
+ const originalQuery = req.query;
56
+ req.query = {
57
+ ...req.query
58
+ };
59
+ delete req.query.uploadEdits;
60
+ try {
61
+ const updatedDoc = await req.payload.update({
62
+ id: doc.id,
63
+ collection: collection.slug,
64
+ data: metadata,
65
+ depth: 0,
66
+ draft: isDraftSave,
67
+ overrideAccess: true,
68
+ req,
69
+ select
70
+ });
71
+ return withProxyPrefix({
72
+ ...doc,
73
+ ...updatedDoc
74
+ });
75
+ } finally{
76
+ req.query = originalQuery;
77
+ delete req.context.skipCloudStorage;
78
+ }
79
+ }
22
80
  try {
23
81
  const files = getIncomingFiles({
24
82
  data: uploadData,
@@ -85,13 +143,13 @@ export const getAfterChangeHook = ({ adapter, collection, collectionPrefix, useC
85
143
  // persistence have succeeded. Deleting earlier would orphan the
86
144
  // record if a later step throws (e.g. a user-defined afterChange
87
145
  // hook on the same collection).
88
- if (previousDoc && operation === 'update' && !isDraftOverPublished) {
146
+ if (previousDoc && operation === 'update' && !isDraftOverPublished && !collection.versions && !previousDoc.original) {
89
147
  let filesToDelete = [];
90
148
  if (typeof previousDoc?.filename === 'string') {
91
149
  filesToDelete.push(previousDoc.filename);
92
150
  }
93
- if (typeof previousDoc.sizes === 'object') {
94
- filesToDelete = filesToDelete.concat(Object.values(previousDoc?.sizes || []).map((resizedFileData)=>resizedFileData?.filename));
151
+ if (typeof previousDoc.variants === 'object') {
152
+ filesToDelete = filesToDelete.concat(Object.values(previousDoc?.variants || []).map((resizedFileData)=>resizedFileData?.filename));
95
153
  }
96
154
  // Compare full locations: a replacement can reuse a filename while moving
97
155
  // a legacy object beneath the collection prefix.
@@ -103,8 +161,8 @@ export const getAfterChangeHook = ({ adapter, collection, collectionPrefix, useC
103
161
  if (typeof newFileData.filename === 'string') {
104
162
  newFilenames.add(newFileData.filename);
105
163
  }
106
- if (typeof newFileData.sizes === 'object') {
107
- for (const size of Object.values(newFileData.sizes || {})){
164
+ if (typeof newFileData.variants === 'object') {
165
+ for (const size of Object.values(newFileData.variants || {})){
108
166
  if (size?.filename && typeof size.filename === 'string') {
109
167
  newFilenames.add(size.filename);
110
168
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/hooks/afterChange.ts"],"sourcesContent":["import type { CollectionAfterChangeHook, CollectionConfig, FileData, TypeWithID } from 'payload'\n\nimport { deepMergeWithSourceArrays } from 'payload'\n\nimport type { GeneratedAdapter } from '../types.js'\n\nimport { buildPrefixWithObjectKey } from '../utilities/buildPrefixWithObjectKey.js'\nimport {\n buildStoragePathData,\n buildUploadStoragePathData,\n} from '../utilities/buildStoragePathData.js'\nimport { getIncomingFiles } from '../utilities/getIncomingFiles.js'\n\ninterface Args {\n adapter: GeneratedAdapter\n collection: CollectionConfig\n collectionPrefix?: string\n useCompositePrefixes?: boolean\n}\n\n// The object's folder: semantic prefix + `_objectKey` segment.\nconst getObjectFolder = (data: unknown): string => {\n const record = (data ?? {}) as { _objectKey?: string; prefix?: string }\n return buildPrefixWithObjectKey({ objectKey: record._objectKey, prefix: record.prefix })\n}\n\nexport const getAfterChangeHook =\n ({\n adapter,\n collection,\n collectionPrefix,\n useCompositePrefixes,\n }: Args): CollectionAfterChangeHook<FileData & TypeWithID> =>\n async ({ data, doc, operation, previousDoc, req, select }) => {\n // Skip if this is an internal update to prevent infinite loop\n if (req.context?.skipCloudStorage) {\n return doc\n }\n\n // Restore upload metadata removed by select, including partially selected image sizes.\n const uploadData = select ? deepMergeWithSourceArrays<FileData & TypeWithID>(data, doc) : doc\n const isDraftSave = (uploadData as { _status?: string })._status === 'draft'\n const isDraftOverPublished =\n isDraftSave && (previousDoc as { _status?: string } | undefined)?._status === 'published'\n\n try {\n const files = getIncomingFiles({ data: uploadData, req })\n\n if (files.length > 0) {\n // Fold `_objectKey` so generated sizes land in the same folder as the original.\n const dataForUpload = { ...uploadData, prefix: getObjectFolder(uploadData) }\n\n const uploadResults = await Promise.all(\n files\n .filter((file) => !file.uploadReference)\n .map((file) =>\n adapter.handleUpload({\n collection,\n data: dataForUpload,\n file,\n req,\n storageFilePath: buildUploadStoragePathData({\n collectionPrefix,\n docPrefix: dataForUpload.prefix,\n filename: file.filename,\n useCompositePrefixes,\n }).storageFilePath,\n }),\n ),\n )\n\n const uploadMetadata = uploadResults\n .filter(\n (result): result is Partial<FileData & TypeWithID> =>\n result != null && typeof result === 'object',\n )\n .reduce(\n (acc, metadata) => ({ ...acc, ...metadata }),\n {} as Partial<FileData & TypeWithID>,\n )\n\n // Adapters may echo `data` back as metadata; keep the document's own `prefix`/`_objectKey`.\n delete (uploadMetadata as Record<string, unknown>).prefix\n delete (uploadMetadata as Record<string, unknown>)._objectKey\n\n let docWithMetadata = doc\n\n if (Object.keys(uploadMetadata).length > 0) {\n if (!req.context) {\n req.context = {}\n }\n req.context.skipCloudStorage = true\n\n // Clear to prevent re-processing\n req.file = undefined\n req.payloadUploadSizes = undefined\n\n try {\n const updatedDoc = await req.payload.update({\n id: doc.id,\n collection: collection.slug,\n data: uploadMetadata,\n depth: 0,\n draft: isDraftSave,\n overrideAccess: true,\n req,\n select,\n })\n\n // Persist all adapter metadata, but do not add unselected fields to the response.\n docWithMetadata = select ? { ...doc, ...updatedDoc } : { ...doc, ...uploadMetadata }\n } finally {\n delete req.context.skipCloudStorage\n }\n }\n\n // Delete previous files only after the new upload and metadata\n // persistence have succeeded. Deleting earlier would orphan the\n // record if a later step throws (e.g. a user-defined afterChange\n // hook on the same collection).\n if (previousDoc && operation === 'update' && !isDraftOverPublished) {\n let filesToDelete: string[] = []\n\n if (typeof previousDoc?.filename === 'string') {\n filesToDelete.push(previousDoc.filename)\n }\n\n if (typeof previousDoc.sizes === 'object') {\n filesToDelete = filesToDelete.concat(\n Object.values(previousDoc?.sizes || []).map(\n (resizedFileData) => resizedFileData?.filename as string,\n ),\n )\n }\n\n // Compare full locations: a replacement can reuse a filename while moving\n // a legacy object beneath the collection prefix.\n const newFileData = { ...uploadData, ...uploadMetadata }\n const newFilenames = new Set<string>()\n if (typeof newFileData.filename === 'string') {\n newFilenames.add(newFileData.filename)\n }\n if (typeof newFileData.sizes === 'object') {\n for (const size of Object.values(newFileData.sizes || {})) {\n if (size?.filename && typeof size.filename === 'string') {\n newFilenames.add(size.filename)\n }\n }\n }\n\n const resolveKey = ({\n data,\n filename,\n }: {\n data: { _objectKey?: string; prefix?: string }\n filename: string\n }) =>\n buildStoragePathData({\n collectionPrefix,\n docPrefix: getObjectFolder(data),\n filename,\n useCompositePrefixes,\n }).storageFilePath\n const newKeys = new Set(\n [...newFilenames].map((filename) =>\n resolveKey({\n data: newFileData as { _objectKey?: string; prefix?: string },\n filename,\n }),\n ),\n )\n\n const deletionPromises = filesToDelete.map(async (filename) => {\n if (!filename) {\n return\n }\n const storageFilePath = resolveKey({\n data: previousDoc as { _objectKey?: string; prefix?: string },\n filename,\n })\n if (!newKeys.has(storageFilePath)) {\n await adapter.handleDelete({\n collection,\n doc: previousDoc,\n filename,\n req,\n storageFilePath,\n })\n }\n })\n\n await Promise.all(deletionPromises)\n }\n\n if (docWithMetadata !== doc) {\n return docWithMetadata\n }\n }\n } catch (err: unknown) {\n req.payload.logger.error(\n `There was an error while uploading files corresponding to the collection ${collection.slug} with filename ${doc.filename}:`,\n )\n req.payload.logger.error({ err })\n throw err\n }\n return doc\n }\n"],"names":["deepMergeWithSourceArrays","buildPrefixWithObjectKey","buildStoragePathData","buildUploadStoragePathData","getIncomingFiles","getObjectFolder","data","record","objectKey","_objectKey","prefix","getAfterChangeHook","adapter","collection","collectionPrefix","useCompositePrefixes","doc","operation","previousDoc","req","select","context","skipCloudStorage","uploadData","isDraftSave","_status","isDraftOverPublished","files","length","dataForUpload","uploadResults","Promise","all","filter","file","uploadReference","map","handleUpload","storageFilePath","docPrefix","filename","uploadMetadata","result","reduce","acc","metadata","docWithMetadata","Object","keys","undefined","payloadUploadSizes","updatedDoc","payload","update","id","slug","depth","draft","overrideAccess","filesToDelete","push","sizes","concat","values","resizedFileData","newFileData","newFilenames","Set","add","size","resolveKey","newKeys","deletionPromises","has","handleDelete","err","logger","error"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/hooks/afterChange.ts"],"sourcesContent":["import type { CollectionAfterChangeHook, CollectionConfig, FileData, TypeWithID } from 'payload'\n\nimport { deepMergeWithSourceArrays } from 'payload'\n\nimport type { GeneratedAdapter } from '../types.js'\n\nimport { buildPrefixWithObjectKey } from '../utilities/buildPrefixWithObjectKey.js'\nimport {\n buildStoragePathData,\n buildUploadStoragePathData,\n} from '../utilities/buildStoragePathData.js'\nimport { getIncomingFiles } from '../utilities/getIncomingFiles.js'\nimport { appendProxyPrefix } from './afterRead.js'\n\ninterface Args {\n adapter: GeneratedAdapter\n collection: CollectionConfig\n collectionPrefix?: string\n disablePayloadAccessControl?: boolean\n hasCustomFileURL?: boolean\n useCompositePrefixes?: boolean\n}\n\n// The object's folder: semantic prefix + `_objectKey` segment.\nconst getObjectFolder = (data: unknown): string => {\n const record = (data ?? {}) as { _objectKey?: string; prefix?: string }\n return buildPrefixWithObjectKey({ objectKey: record._objectKey, prefix: record.prefix })\n}\n\nexport const getAfterChangeHook =\n ({\n adapter,\n collection,\n collectionPrefix,\n disablePayloadAccessControl,\n hasCustomFileURL,\n useCompositePrefixes,\n }: Args): CollectionAfterChangeHook<FileData & TypeWithID> =>\n async ({ data, doc, operation, previousDoc, req, select }) => {\n // Skip if this is an internal update to prevent infinite loop\n if (req.context?.skipCloudStorage) {\n return doc\n }\n\n // Restore upload metadata removed by select, including partially selected image sizes.\n const uploadData = select ? deepMergeWithSourceArrays<FileData & TypeWithID>(data, doc) : doc\n const withProxyPrefix = (upload: FileData & TypeWithID): FileData & TypeWithID => {\n const { prefix } = upload as { prefix?: string } & FileData & TypeWithID\n\n if (disablePayloadAccessControl || hasCustomFileURL || !useCompositePrefixes || !prefix) {\n return upload\n }\n\n return {\n ...upload,\n ...(upload.url && {\n url: appendProxyPrefix({ prefix, url: upload.url }),\n }),\n ...(upload.original?.url && {\n original: {\n ...upload.original,\n url: appendProxyPrefix({ prefix, url: upload.original.url }),\n },\n }),\n }\n }\n const isDraftSave = (uploadData as { _status?: string })._status === 'draft'\n const isDraftOverPublished =\n isDraftSave && (previousDoc as { _status?: string } | undefined)?._status === 'published'\n\n if (req.context?._payloadManagedCloudStorage) {\n const metadata = req.context._payloadManagedCloudMetadata as\n | Partial<FileData & TypeWithID>\n | undefined\n\n if (!metadata || Object.keys(metadata).length === 0) {\n return withProxyPrefix(doc)\n }\n\n req.context.skipCloudStorage = true\n req.file = undefined\n req.payloadUploadSizes = undefined\n const originalQuery = req.query\n req.query = { ...req.query }\n delete req.query.uploadEdits\n\n try {\n const updatedDoc = await req.payload.update({\n id: doc.id,\n collection: collection.slug,\n data: metadata,\n depth: 0,\n draft: isDraftSave,\n overrideAccess: true,\n req,\n select,\n })\n\n return withProxyPrefix({ ...doc, ...updatedDoc })\n } finally {\n req.query = originalQuery\n delete req.context.skipCloudStorage\n }\n }\n\n try {\n const files = getIncomingFiles({ data: uploadData, req })\n\n if (files.length > 0) {\n // Fold `_objectKey` so generated sizes land in the same folder as the original.\n const dataForUpload = { ...uploadData, prefix: getObjectFolder(uploadData) }\n\n const uploadResults = await Promise.all(\n files\n .filter((file) => !file.uploadReference)\n .map((file) =>\n adapter.handleUpload({\n collection,\n data: dataForUpload,\n file,\n req,\n storageFilePath: buildUploadStoragePathData({\n collectionPrefix,\n docPrefix: dataForUpload.prefix,\n filename: file.filename,\n useCompositePrefixes,\n }).storageFilePath,\n }),\n ),\n )\n\n const uploadMetadata = uploadResults\n .filter(\n (result): result is Partial<FileData & TypeWithID> =>\n result != null && typeof result === 'object',\n )\n .reduce(\n (acc, metadata) => ({ ...acc, ...metadata }),\n {} as Partial<FileData & TypeWithID>,\n )\n\n // Adapters may echo `data` back as metadata; keep the document's own `prefix`/`_objectKey`.\n delete (uploadMetadata as Record<string, unknown>).prefix\n delete (uploadMetadata as Record<string, unknown>)._objectKey\n\n let docWithMetadata = doc\n\n if (Object.keys(uploadMetadata).length > 0) {\n if (!req.context) {\n req.context = {}\n }\n req.context.skipCloudStorage = true\n\n // Clear to prevent re-processing\n req.file = undefined\n req.payloadUploadSizes = undefined\n\n try {\n const updatedDoc = await req.payload.update({\n id: doc.id,\n collection: collection.slug,\n data: uploadMetadata,\n depth: 0,\n draft: isDraftSave,\n overrideAccess: true,\n req,\n select,\n })\n\n // Persist all adapter metadata, but do not add unselected fields to the response.\n docWithMetadata = select ? { ...doc, ...updatedDoc } : { ...doc, ...uploadMetadata }\n } finally {\n delete req.context.skipCloudStorage\n }\n }\n\n // Delete previous files only after the new upload and metadata\n // persistence have succeeded. Deleting earlier would orphan the\n // record if a later step throws (e.g. a user-defined afterChange\n // hook on the same collection).\n if (\n previousDoc &&\n operation === 'update' &&\n !isDraftOverPublished &&\n !collection.versions &&\n !previousDoc.original\n ) {\n let filesToDelete: string[] = []\n\n if (typeof previousDoc?.filename === 'string') {\n filesToDelete.push(previousDoc.filename)\n }\n\n if (typeof previousDoc.variants === 'object') {\n filesToDelete = filesToDelete.concat(\n Object.values(previousDoc?.variants || []).map(\n (resizedFileData) => resizedFileData?.filename as string,\n ),\n )\n }\n\n // Compare full locations: a replacement can reuse a filename while moving\n // a legacy object beneath the collection prefix.\n const newFileData = { ...uploadData, ...uploadMetadata }\n const newFilenames = new Set<string>()\n if (typeof newFileData.filename === 'string') {\n newFilenames.add(newFileData.filename)\n }\n if (typeof newFileData.variants === 'object') {\n for (const size of Object.values(newFileData.variants || {})) {\n if (size?.filename && typeof size.filename === 'string') {\n newFilenames.add(size.filename)\n }\n }\n }\n\n const resolveKey = ({\n data,\n filename,\n }: {\n data: { _objectKey?: string; prefix?: string }\n filename: string\n }) =>\n buildStoragePathData({\n collectionPrefix,\n docPrefix: getObjectFolder(data),\n filename,\n useCompositePrefixes,\n }).storageFilePath\n const newKeys = new Set(\n [...newFilenames].map((filename) =>\n resolveKey({\n data: newFileData as { _objectKey?: string; prefix?: string },\n filename,\n }),\n ),\n )\n\n const deletionPromises = filesToDelete.map(async (filename) => {\n if (!filename) {\n return\n }\n const storageFilePath = resolveKey({\n data: previousDoc as { _objectKey?: string; prefix?: string },\n filename,\n })\n if (!newKeys.has(storageFilePath)) {\n await adapter.handleDelete({\n collection,\n doc: previousDoc,\n filename,\n req,\n storageFilePath,\n })\n }\n })\n\n await Promise.all(deletionPromises)\n }\n\n if (docWithMetadata !== doc) {\n return docWithMetadata\n }\n }\n } catch (err: unknown) {\n req.payload.logger.error(\n `There was an error while uploading files corresponding to the collection ${collection.slug} with filename ${doc.filename}:`,\n )\n req.payload.logger.error({ err })\n throw err\n }\n return doc\n }\n"],"names":["deepMergeWithSourceArrays","buildPrefixWithObjectKey","buildStoragePathData","buildUploadStoragePathData","getIncomingFiles","appendProxyPrefix","getObjectFolder","data","record","objectKey","_objectKey","prefix","getAfterChangeHook","adapter","collection","collectionPrefix","disablePayloadAccessControl","hasCustomFileURL","useCompositePrefixes","doc","operation","previousDoc","req","select","context","skipCloudStorage","uploadData","withProxyPrefix","upload","url","original","isDraftSave","_status","isDraftOverPublished","_payloadManagedCloudStorage","metadata","_payloadManagedCloudMetadata","Object","keys","length","file","undefined","payloadUploadSizes","originalQuery","query","uploadEdits","updatedDoc","payload","update","id","slug","depth","draft","overrideAccess","files","dataForUpload","uploadResults","Promise","all","filter","uploadReference","map","handleUpload","storageFilePath","docPrefix","filename","uploadMetadata","result","reduce","acc","docWithMetadata","versions","filesToDelete","push","variants","concat","values","resizedFileData","newFileData","newFilenames","Set","add","size","resolveKey","newKeys","deletionPromises","has","handleDelete","err","logger","error"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"afterDelete.d.ts","sourceRoot":"","sources":["../../src/hooks/afterDelete.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,yBAAyB,EAAE,gBAAgB,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AAEhG,OAAO,KAAK,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAKnE,UAAU,IAAI;IACZ,OAAO,EAAE,gBAAgB,CAAA;IACzB,UAAU,EAAE,gBAAgB,CAAA;IAC5B,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,oBAAoB,CAAC,EAAE,OAAO,CAAA;CAC/B;AAED,eAAO,MAAM,kBAAkB,qEAK5B,IAAI,KAAG,yBAAyB,CAAC,QAAQ,GAAG,UAAU,GAAG,cAAc,CAqCzE,CAAA"}
1
+ {"version":3,"file":"afterDelete.d.ts","sourceRoot":"","sources":["../../src/hooks/afterDelete.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,yBAAyB,EAAE,gBAAgB,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AAEhG,OAAO,KAAK,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAKnE,UAAU,IAAI;IACZ,OAAO,EAAE,gBAAgB,CAAA;IACzB,UAAU,EAAE,gBAAgB,CAAA;IAC5B,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,oBAAoB,CAAC,EAAE,OAAO,CAAA;CAC/B;AAED,eAAO,MAAM,kBAAkB,qEAK5B,IAAI,KAAG,yBAAyB,CAAC,QAAQ,GAAG,UAAU,GAAG,cAAc,CAiDzE,CAAA"}
@@ -1,7 +1,15 @@
1
1
  import { buildPrefixWithObjectKey } from '../utilities/buildPrefixWithObjectKey.js';
2
2
  import { buildStoragePathData } from '../utilities/buildStoragePathData.js';
3
3
  export const getAfterDeleteHook = ({ adapter, collection, collectionPrefix, useCompositePrefixes })=>{
4
- return async ({ doc, req })=>{
4
+ return async ({ id, doc, req })=>{
5
+ // Managed objects are deleted after the operation commits and all references are checked.
6
+ const managedDeletedUploads = req.context?._payloadManagedDeletedUploads;
7
+ if (collection.versions || Boolean(doc.original) && typeof doc.original?.filename === 'string' || managedDeletedUploads?.has(JSON.stringify([
8
+ collection.slug,
9
+ String(id)
10
+ ]))) {
11
+ return doc;
12
+ }
5
13
  try {
6
14
  // Fold `_objectKey` so deletes target the real object folder.
7
15
  const docPrefix = buildPrefixWithObjectKey({
@@ -10,7 +18,7 @@ export const getAfterDeleteHook = ({ adapter, collection, collectionPrefix, useC
10
18
  });
11
19
  const filesToDelete = [
12
20
  doc.filename,
13
- ...Object.values(doc?.sizes || []).map((resizedFileData)=>resizedFileData?.filename)
21
+ ...Object.values(doc?.variants || []).map((resizedFileData)=>resizedFileData?.filename)
14
22
  ];
15
23
  const promises = filesToDelete.map(async (filename)=>{
16
24
  if (filename) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/hooks/afterDelete.ts"],"sourcesContent":["import type { CollectionAfterDeleteHook, CollectionConfig, FileData, TypeWithID } from 'payload'\n\nimport type { GeneratedAdapter, TypeWithPrefix } from '../types.js'\n\nimport { buildPrefixWithObjectKey } from '../utilities/buildPrefixWithObjectKey.js'\nimport { buildStoragePathData } from '../utilities/buildStoragePathData.js'\n\ninterface Args {\n adapter: GeneratedAdapter\n collection: CollectionConfig\n collectionPrefix?: string\n useCompositePrefixes?: boolean\n}\n\nexport const getAfterDeleteHook = ({\n adapter,\n collection,\n collectionPrefix,\n useCompositePrefixes,\n}: Args): CollectionAfterDeleteHook<FileData & TypeWithID & TypeWithPrefix> => {\n return async ({ doc, req }) => {\n try {\n // Fold `_objectKey` so deletes target the real object folder.\n const docPrefix = buildPrefixWithObjectKey({\n objectKey: (doc as { _objectKey?: string })._objectKey,\n prefix: doc.prefix,\n })\n\n const filesToDelete: string[] = [\n doc.filename,\n ...Object.values(doc?.sizes || []).map(\n (resizedFileData) => resizedFileData?.filename as string,\n ),\n ]\n\n const promises = filesToDelete.map(async (filename) => {\n if (filename) {\n const { storageFilePath } = buildStoragePathData({\n collectionPrefix,\n docPrefix,\n filename,\n useCompositePrefixes,\n })\n await adapter.handleDelete({ collection, doc, filename, req, storageFilePath })\n }\n })\n\n await Promise.all(promises)\n } catch (err: unknown) {\n req.payload.logger.error({\n err,\n msg: `There was an error while deleting files corresponding to the ${collection.labels?.singular} with ID ${doc.id}.`,\n })\n }\n return doc\n }\n}\n"],"names":["buildPrefixWithObjectKey","buildStoragePathData","getAfterDeleteHook","adapter","collection","collectionPrefix","useCompositePrefixes","doc","req","docPrefix","objectKey","_objectKey","prefix","filesToDelete","filename","Object","values","sizes","map","resizedFileData","promises","storageFilePath","handleDelete","Promise","all","err","payload","logger","error","msg","labels","singular","id"],"mappings":"AAIA,SAASA,wBAAwB,QAAQ,2CAA0C;AACnF,SAASC,oBAAoB,QAAQ,uCAAsC;AAS3E,OAAO,MAAMC,qBAAqB,CAAC,EACjCC,OAAO,EACPC,UAAU,EACVC,gBAAgB,EAChBC,oBAAoB,EACf;IACL,OAAO,OAAO,EAAEC,GAAG,EAAEC,GAAG,EAAE;QACxB,IAAI;YACF,8DAA8D;YAC9D,MAAMC,YAAYT,yBAAyB;gBACzCU,WAAW,AAACH,IAAgCI,UAAU;gBACtDC,QAAQL,IAAIK,MAAM;YACpB;YAEA,MAAMC,gBAA0B;gBAC9BN,IAAIO,QAAQ;mBACTC,OAAOC,MAAM,CAACT,KAAKU,SAAS,EAAE,EAAEC,GAAG,CACpC,CAACC,kBAAoBA,iBAAiBL;aAEzC;YAED,MAAMM,WAAWP,cAAcK,GAAG,CAAC,OAAOJ;gBACxC,IAAIA,UAAU;oBACZ,MAAM,EAAEO,eAAe,EAAE,GAAGpB,qBAAqB;wBAC/CI;wBACAI;wBACAK;wBACAR;oBACF;oBACA,MAAMH,QAAQmB,YAAY,CAAC;wBAAElB;wBAAYG;wBAAKO;wBAAUN;wBAAKa;oBAAgB;gBAC/E;YACF;YAEA,MAAME,QAAQC,GAAG,CAACJ;QACpB,EAAE,OAAOK,KAAc;YACrBjB,IAAIkB,OAAO,CAACC,MAAM,CAACC,KAAK,CAAC;gBACvBH;gBACAI,KAAK,CAAC,6DAA6D,EAAEzB,WAAW0B,MAAM,EAAEC,SAAS,SAAS,EAAExB,IAAIyB,EAAE,CAAC,CAAC,CAAC;YACvH;QACF;QACA,OAAOzB;IACT;AACF,EAAC"}
1
+ {"version":3,"sources":["../../src/hooks/afterDelete.ts"],"sourcesContent":["import type { CollectionAfterDeleteHook, CollectionConfig, FileData, TypeWithID } from 'payload'\n\nimport type { GeneratedAdapter, TypeWithPrefix } from '../types.js'\n\nimport { buildPrefixWithObjectKey } from '../utilities/buildPrefixWithObjectKey.js'\nimport { buildStoragePathData } from '../utilities/buildStoragePathData.js'\n\ninterface Args {\n adapter: GeneratedAdapter\n collection: CollectionConfig\n collectionPrefix?: string\n useCompositePrefixes?: boolean\n}\n\nexport const getAfterDeleteHook = ({\n adapter,\n collection,\n collectionPrefix,\n useCompositePrefixes,\n}: Args): CollectionAfterDeleteHook<FileData & TypeWithID & TypeWithPrefix> => {\n return async ({ id, doc, req }) => {\n // Managed objects are deleted after the operation commits and all references are checked.\n const managedDeletedUploads = req.context?._payloadManagedDeletedUploads as\n | Set<string>\n | undefined\n if (\n collection.versions ||\n (Boolean(doc.original) && typeof doc.original?.filename === 'string') ||\n managedDeletedUploads?.has(JSON.stringify([collection.slug, String(id)]))\n ) {\n return doc\n }\n\n try {\n // Fold `_objectKey` so deletes target the real object folder.\n const docPrefix = buildPrefixWithObjectKey({\n objectKey: (doc as { _objectKey?: string })._objectKey,\n prefix: doc.prefix,\n })\n\n const filesToDelete: string[] = [\n doc.filename,\n ...Object.values(doc?.variants || []).map(\n (resizedFileData) => resizedFileData?.filename as string,\n ),\n ]\n\n const promises = filesToDelete.map(async (filename) => {\n if (filename) {\n const { storageFilePath } = buildStoragePathData({\n collectionPrefix,\n docPrefix,\n filename,\n useCompositePrefixes,\n })\n await adapter.handleDelete({ collection, doc, filename, req, storageFilePath })\n }\n })\n\n await Promise.all(promises)\n } catch (err: unknown) {\n req.payload.logger.error({\n err,\n msg: `There was an error while deleting files corresponding to the ${collection.labels?.singular} with ID ${doc.id}.`,\n })\n }\n return doc\n }\n}\n"],"names":["buildPrefixWithObjectKey","buildStoragePathData","getAfterDeleteHook","adapter","collection","collectionPrefix","useCompositePrefixes","id","doc","req","managedDeletedUploads","context","_payloadManagedDeletedUploads","versions","Boolean","original","filename","has","JSON","stringify","slug","String","docPrefix","objectKey","_objectKey","prefix","filesToDelete","Object","values","variants","map","resizedFileData","promises","storageFilePath","handleDelete","Promise","all","err","payload","logger","error","msg","labels","singular"],"mappings":"AAIA,SAASA,wBAAwB,QAAQ,2CAA0C;AACnF,SAASC,oBAAoB,QAAQ,uCAAsC;AAS3E,OAAO,MAAMC,qBAAqB,CAAC,EACjCC,OAAO,EACPC,UAAU,EACVC,gBAAgB,EAChBC,oBAAoB,EACf;IACL,OAAO,OAAO,EAAEC,EAAE,EAAEC,GAAG,EAAEC,GAAG,EAAE;QAC5B,0FAA0F;QAC1F,MAAMC,wBAAwBD,IAAIE,OAAO,EAAEC;QAG3C,IACER,WAAWS,QAAQ,IAClBC,QAAQN,IAAIO,QAAQ,KAAK,OAAOP,IAAIO,QAAQ,EAAEC,aAAa,YAC5DN,uBAAuBO,IAAIC,KAAKC,SAAS,CAAC;YAACf,WAAWgB,IAAI;YAAEC,OAAOd;SAAI,IACvE;YACA,OAAOC;QACT;QAEA,IAAI;YACF,8DAA8D;YAC9D,MAAMc,YAAYtB,yBAAyB;gBACzCuB,WAAW,AAACf,IAAgCgB,UAAU;gBACtDC,QAAQjB,IAAIiB,MAAM;YACpB;YAEA,MAAMC,gBAA0B;gBAC9BlB,IAAIQ,QAAQ;mBACTW,OAAOC,MAAM,CAACpB,KAAKqB,YAAY,EAAE,EAAEC,GAAG,CACvC,CAACC,kBAAoBA,iBAAiBf;aAEzC;YAED,MAAMgB,WAAWN,cAAcI,GAAG,CAAC,OAAOd;gBACxC,IAAIA,UAAU;oBACZ,MAAM,EAAEiB,eAAe,EAAE,GAAGhC,qBAAqB;wBAC/CI;wBACAiB;wBACAN;wBACAV;oBACF;oBACA,MAAMH,QAAQ+B,YAAY,CAAC;wBAAE9B;wBAAYI;wBAAKQ;wBAAUP;wBAAKwB;oBAAgB;gBAC/E;YACF;YAEA,MAAME,QAAQC,GAAG,CAACJ;QACpB,EAAE,OAAOK,KAAc;YACrB5B,IAAI6B,OAAO,CAACC,MAAM,CAACC,KAAK,CAAC;gBACvBH;gBACAI,KAAK,CAAC,6DAA6D,EAAErC,WAAWsC,MAAM,EAAEC,SAAS,SAAS,EAAEnC,IAAID,EAAE,CAAC,CAAC,CAAC;YACvH;QACF;QACA,OAAOC;IACT;AACF,EAAC"}
@@ -5,8 +5,13 @@ interface Args {
5
5
  collection: CollectionConfig;
6
6
  disablePayloadAccessControl?: boolean;
7
7
  generateFileURL?: GenerateFileURL;
8
+ isOriginal?: boolean;
8
9
  size?: ImageSize;
9
10
  }
10
- export declare const getAfterReadHook: ({ adapter, collection, disablePayloadAccessControl, generateFileURL, size }: Args) => FieldHook;
11
+ export declare const getAfterReadHook: ({ adapter, collection, disablePayloadAccessControl, generateFileURL, isOriginal, size, }: Args) => FieldHook;
12
+ export declare const appendProxyPrefix: ({ prefix, url }: {
13
+ prefix: string;
14
+ url: string;
15
+ }) => string;
11
16
  export {};
12
17
  //# sourceMappingURL=afterRead.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"afterRead.d.ts","sourceRoot":"","sources":["../../src/hooks/afterRead.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA;AAErE,OAAO,KAAK,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAIpE,UAAU,IAAI;IACZ,OAAO,EAAE,gBAAgB,CAAA;IACzB,UAAU,EAAE,gBAAgB,CAAA;IAC5B,2BAA2B,CAAC,EAAE,OAAO,CAAA;IACrC,eAAe,CAAC,EAAE,eAAe,CAAA;IACjC,IAAI,CAAC,EAAE,SAAS,CAAA;CACjB;AAiBD,eAAO,MAAM,gBAAgB,gFACmD,IAAI,KAAG,SA8BpF,CAAA"}
1
+ {"version":3,"file":"afterRead.d.ts","sourceRoot":"","sources":["../../src/hooks/afterRead.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA;AAErE,OAAO,KAAK,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAIpE,UAAU,IAAI;IACZ,OAAO,EAAE,gBAAgB,CAAA;IACzB,UAAU,EAAE,gBAAgB,CAAA;IAC5B,2BAA2B,CAAC,EAAE,OAAO,CAAA;IACrC,eAAe,CAAC,EAAE,eAAe,CAAA;IACjC,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,IAAI,CAAC,EAAE,SAAS,CAAA;CACjB;AAiBD,eAAO,MAAM,gBAAgB,6FAQxB,IAAI,KAAG,SAkCT,CAAA;AAEH,eAAO,MAAM,iBAAiB,oBAAqB;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,KAAG,MAMpF,CAAA"}
@@ -9,11 +9,16 @@ const getObjectFolder = (data)=>{
9
9
  }
10
10
  return safePrefix || safeObjectKey;
11
11
  };
12
- export const getAfterReadHook = ({ adapter, collection, disablePayloadAccessControl, generateFileURL, size })=>async ({ data, value })=>{
13
- const filename = size ? data?.sizes?.[size.name]?.filename : data?.filename;
14
- const prefix = data?.prefix;
12
+ export const getAfterReadHook = ({ adapter, collection, disablePayloadAccessControl, generateFileURL, isOriginal, size })=>async ({ data, value })=>{
13
+ const representation = isOriginal ? data?.original : size ? data?.variants?.[size.name] : data;
14
+ const filename = representation?.filename;
15
+ const hasLegacyVariant = Boolean(size && !data?.original?.filename);
16
+ const prefix = representation?.prefix ?? (hasLegacyVariant ? data?.prefix : undefined);
15
17
  // Direct-serve URLs encode the full location; the proxy resolves `_objectKey` server-side.
16
- const objectFolder = getObjectFolder(data);
18
+ const objectFolder = getObjectFolder({
19
+ _objectKey: representation?._objectKey ?? (hasLegacyVariant ? data?._objectKey : undefined),
20
+ prefix
21
+ });
17
22
  let url = value;
18
23
  if (filename) {
19
24
  if (generateFileURL) {
@@ -31,11 +36,20 @@ export const getAfterReadHook = ({ adapter, collection, disablePayloadAccessCont
31
36
  prefix: objectFolder
32
37
  });
33
38
  } else if (url && prefix) {
34
- const separator = url.includes('?') ? '&' : '?';
35
- url = `${url}${separator}prefix=${encodeURIComponent(prefix)}`;
39
+ url = appendProxyPrefix({
40
+ prefix,
41
+ url
42
+ });
36
43
  }
37
44
  }
38
45
  return url;
39
46
  };
47
+ export const appendProxyPrefix = ({ prefix, url })=>{
48
+ if (new URL(url, 'http://payload.local').searchParams.has('prefix')) {
49
+ return url;
50
+ }
51
+ const separator = url.includes('?') ? '&' : '?';
52
+ return `${url}${separator}prefix=${encodeURIComponent(prefix)}`;
53
+ };
40
54
 
41
55
  //# sourceMappingURL=afterRead.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/hooks/afterRead.ts"],"sourcesContent":["import type { CollectionConfig, FieldHook, ImageSize } from 'payload'\n\nimport type { GeneratedAdapter, GenerateFileURL } from '../types.js'\n\nimport { sanitizePrefix } from '../utilities/sanitizePrefix.js'\n\ninterface Args {\n adapter: GeneratedAdapter\n collection: CollectionConfig\n disablePayloadAccessControl?: boolean\n generateFileURL?: GenerateFileURL\n size?: ImageSize\n}\n\n// The object's folder: semantic prefix + `_objectKey` segment.\nconst getObjectFolder = (data: unknown): string => {\n const record = (data ?? {}) as Record<string, unknown>\n const safePrefix = sanitizePrefix(typeof record.prefix === 'string' ? record.prefix : '')\n const safeObjectKey = sanitizePrefix(\n typeof record._objectKey === 'string' ? record._objectKey : '',\n )\n\n if (safePrefix && safeObjectKey) {\n return `${safePrefix}/${safeObjectKey}`\n }\n\n return safePrefix || safeObjectKey\n}\n\nexport const getAfterReadHook =\n ({ adapter, collection, disablePayloadAccessControl, generateFileURL, size }: Args): FieldHook =>\n async ({ data, value }) => {\n const filename = size ? data?.sizes?.[size.name]?.filename : data?.filename\n const prefix = data?.prefix\n // Direct-serve URLs encode the full location; the proxy resolves `_objectKey` server-side.\n const objectFolder = getObjectFolder(data)\n let url = value\n\n if (filename) {\n if (generateFileURL) {\n url = await generateFileURL({\n collection,\n filename,\n prefix: objectFolder,\n size,\n })\n } else if (disablePayloadAccessControl && adapter.generateURL) {\n url = await adapter.generateURL({\n collection,\n data,\n filename,\n prefix: objectFolder,\n })\n } else if (url && prefix) {\n const separator = url.includes('?') ? '&' : '?'\n url = `${url}${separator}prefix=${encodeURIComponent(prefix)}`\n }\n }\n\n return url\n }\n"],"names":["sanitizePrefix","getObjectFolder","data","record","safePrefix","prefix","safeObjectKey","_objectKey","getAfterReadHook","adapter","collection","disablePayloadAccessControl","generateFileURL","size","value","filename","sizes","name","objectFolder","url","generateURL","separator","includes","encodeURIComponent"],"mappings":"AAIA,SAASA,cAAc,QAAQ,iCAAgC;AAU/D,+DAA+D;AAC/D,MAAMC,kBAAkB,CAACC;IACvB,MAAMC,SAAUD,QAAQ,CAAC;IACzB,MAAME,aAAaJ,eAAe,OAAOG,OAAOE,MAAM,KAAK,WAAWF,OAAOE,MAAM,GAAG;IACtF,MAAMC,gBAAgBN,eACpB,OAAOG,OAAOI,UAAU,KAAK,WAAWJ,OAAOI,UAAU,GAAG;IAG9D,IAAIH,cAAcE,eAAe;QAC/B,OAAO,GAAGF,WAAW,CAAC,EAAEE,eAAe;IACzC;IAEA,OAAOF,cAAcE;AACvB;AAEA,OAAO,MAAME,mBACX,CAAC,EAAEC,OAAO,EAAEC,UAAU,EAAEC,2BAA2B,EAAEC,eAAe,EAAEC,IAAI,EAAQ,GAClF,OAAO,EAAEX,IAAI,EAAEY,KAAK,EAAE;QACpB,MAAMC,WAAWF,OAAOX,MAAMc,OAAO,CAACH,KAAKI,IAAI,CAAC,EAAEF,WAAWb,MAAMa;QACnE,MAAMV,SAASH,MAAMG;QACrB,2FAA2F;QAC3F,MAAMa,eAAejB,gBAAgBC;QACrC,IAAIiB,MAAML;QAEV,IAAIC,UAAU;YACZ,IAAIH,iBAAiB;gBACnBO,MAAM,MAAMP,gBAAgB;oBAC1BF;oBACAK;oBACAV,QAAQa;oBACRL;gBACF;YACF,OAAO,IAAIF,+BAA+BF,QAAQW,WAAW,EAAE;gBAC7DD,MAAM,MAAMV,QAAQW,WAAW,CAAC;oBAC9BV;oBACAR;oBACAa;oBACAV,QAAQa;gBACV;YACF,OAAO,IAAIC,OAAOd,QAAQ;gBACxB,MAAMgB,YAAYF,IAAIG,QAAQ,CAAC,OAAO,MAAM;gBAC5CH,MAAM,GAAGA,MAAME,UAAU,OAAO,EAAEE,mBAAmBlB,SAAS;YAChE;QACF;QAEA,OAAOc;IACT,EAAC"}
1
+ {"version":3,"sources":["../../src/hooks/afterRead.ts"],"sourcesContent":["import type { CollectionConfig, FieldHook, ImageSize } from 'payload'\n\nimport type { GeneratedAdapter, GenerateFileURL } from '../types.js'\n\nimport { sanitizePrefix } from '../utilities/sanitizePrefix.js'\n\ninterface Args {\n adapter: GeneratedAdapter\n collection: CollectionConfig\n disablePayloadAccessControl?: boolean\n generateFileURL?: GenerateFileURL\n isOriginal?: boolean\n size?: ImageSize\n}\n\n// The object's folder: semantic prefix + `_objectKey` segment.\nconst getObjectFolder = (data: unknown): string => {\n const record = (data ?? {}) as Record<string, unknown>\n const safePrefix = sanitizePrefix(typeof record.prefix === 'string' ? record.prefix : '')\n const safeObjectKey = sanitizePrefix(\n typeof record._objectKey === 'string' ? record._objectKey : '',\n )\n\n if (safePrefix && safeObjectKey) {\n return `${safePrefix}/${safeObjectKey}`\n }\n\n return safePrefix || safeObjectKey\n}\n\nexport const getAfterReadHook =\n ({\n adapter,\n collection,\n disablePayloadAccessControl,\n generateFileURL,\n isOriginal,\n size,\n }: Args): FieldHook =>\n async ({ data, value }) => {\n const representation = isOriginal ? data?.original : size ? data?.variants?.[size.name] : data\n const filename = representation?.filename\n const hasLegacyVariant = Boolean(size && !data?.original?.filename)\n const prefix = representation?.prefix ?? (hasLegacyVariant ? data?.prefix : undefined)\n // Direct-serve URLs encode the full location; the proxy resolves `_objectKey` server-side.\n const objectFolder = getObjectFolder({\n _objectKey: representation?._objectKey ?? (hasLegacyVariant ? data?._objectKey : undefined),\n prefix,\n })\n let url = value\n\n if (filename) {\n if (generateFileURL) {\n url = await generateFileURL({\n collection,\n filename,\n prefix: objectFolder,\n size,\n })\n } else if (disablePayloadAccessControl && adapter.generateURL) {\n url = await adapter.generateURL({\n collection,\n data,\n filename,\n prefix: objectFolder,\n })\n } else if (url && prefix) {\n url = appendProxyPrefix({ prefix, url })\n }\n }\n\n return url\n }\n\nexport const appendProxyPrefix = ({ prefix, url }: { prefix: string; url: string }): string => {\n if (new URL(url, 'http://payload.local').searchParams.has('prefix')) {\n return url\n }\n const separator = url.includes('?') ? '&' : '?'\n return `${url}${separator}prefix=${encodeURIComponent(prefix)}`\n}\n"],"names":["sanitizePrefix","getObjectFolder","data","record","safePrefix","prefix","safeObjectKey","_objectKey","getAfterReadHook","adapter","collection","disablePayloadAccessControl","generateFileURL","isOriginal","size","value","representation","original","variants","name","filename","hasLegacyVariant","Boolean","undefined","objectFolder","url","generateURL","appendProxyPrefix","URL","searchParams","has","separator","includes","encodeURIComponent"],"mappings":"AAIA,SAASA,cAAc,QAAQ,iCAAgC;AAW/D,+DAA+D;AAC/D,MAAMC,kBAAkB,CAACC;IACvB,MAAMC,SAAUD,QAAQ,CAAC;IACzB,MAAME,aAAaJ,eAAe,OAAOG,OAAOE,MAAM,KAAK,WAAWF,OAAOE,MAAM,GAAG;IACtF,MAAMC,gBAAgBN,eACpB,OAAOG,OAAOI,UAAU,KAAK,WAAWJ,OAAOI,UAAU,GAAG;IAG9D,IAAIH,cAAcE,eAAe;QAC/B,OAAO,GAAGF,WAAW,CAAC,EAAEE,eAAe;IACzC;IAEA,OAAOF,cAAcE;AACvB;AAEA,OAAO,MAAME,mBACX,CAAC,EACCC,OAAO,EACPC,UAAU,EACVC,2BAA2B,EAC3BC,eAAe,EACfC,UAAU,EACVC,IAAI,EACC,GACP,OAAO,EAAEZ,IAAI,EAAEa,KAAK,EAAE;QACpB,MAAMC,iBAAiBH,aAAaX,MAAMe,WAAWH,OAAOZ,MAAMgB,UAAU,CAACJ,KAAKK,IAAI,CAAC,GAAGjB;QAC1F,MAAMkB,WAAWJ,gBAAgBI;QACjC,MAAMC,mBAAmBC,QAAQR,QAAQ,CAACZ,MAAMe,UAAUG;QAC1D,MAAMf,SAASW,gBAAgBX,UAAWgB,CAAAA,mBAAmBnB,MAAMG,SAASkB,SAAQ;QACpF,2FAA2F;QAC3F,MAAMC,eAAevB,gBAAgB;YACnCM,YAAYS,gBAAgBT,cAAec,CAAAA,mBAAmBnB,MAAMK,aAAagB,SAAQ;YACzFlB;QACF;QACA,IAAIoB,MAAMV;QAEV,IAAIK,UAAU;YACZ,IAAIR,iBAAiB;gBACnBa,MAAM,MAAMb,gBAAgB;oBAC1BF;oBACAU;oBACAf,QAAQmB;oBACRV;gBACF;YACF,OAAO,IAAIH,+BAA+BF,QAAQiB,WAAW,EAAE;gBAC7DD,MAAM,MAAMhB,QAAQiB,WAAW,CAAC;oBAC9BhB;oBACAR;oBACAkB;oBACAf,QAAQmB;gBACV;YACF,OAAO,IAAIC,OAAOpB,QAAQ;gBACxBoB,MAAME,kBAAkB;oBAAEtB;oBAAQoB;gBAAI;YACxC;QACF;QAEA,OAAOA;IACT,EAAC;AAEH,OAAO,MAAME,oBAAoB,CAAC,EAAEtB,MAAM,EAAEoB,GAAG,EAAmC;IAChF,IAAI,IAAIG,IAAIH,KAAK,wBAAwBI,YAAY,CAACC,GAAG,CAAC,WAAW;QACnE,OAAOL;IACT;IACA,MAAMM,YAAYN,IAAIO,QAAQ,CAAC,OAAO,MAAM;IAC5C,OAAO,GAAGP,MAAMM,UAAU,OAAO,EAAEE,mBAAmB5B,SAAS;AACjE,EAAC"}
@@ -5,8 +5,9 @@ interface Args {
5
5
  collection: CollectionConfig;
6
6
  disablePayloadAccessControl?: boolean;
7
7
  generateFileURL?: GenerateFileURL;
8
+ isOriginal?: boolean;
8
9
  size?: ImageSize;
9
10
  }
10
- export declare const getBeforeChangeHook: ({ adapter, collection, disablePayloadAccessControl, generateFileURL, size }: Args) => FieldHook;
11
+ export declare const getBeforeChangeHook: ({ adapter, collection, disablePayloadAccessControl, generateFileURL, isOriginal, size, }: Args) => FieldHook;
11
12
  export {};
12
13
  //# sourceMappingURL=beforeChange.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"beforeChange.d.ts","sourceRoot":"","sources":["../../src/hooks/beforeChange.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA;AAErE,OAAO,KAAK,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAIpE,UAAU,IAAI;IACZ,OAAO,EAAE,gBAAgB,CAAA;IACzB,UAAU,EAAE,gBAAgB,CAAA;IAC5B,2BAA2B,CAAC,EAAE,OAAO,CAAA;IACrC,eAAe,CAAC,EAAE,eAAe,CAAA;IACjC,IAAI,CAAC,EAAE,SAAS,CAAA;CACjB;AAiBD,eAAO,MAAM,mBAAmB,gFACgD,IAAI,KAAG,SA2BpF,CAAA"}
1
+ {"version":3,"file":"beforeChange.d.ts","sourceRoot":"","sources":["../../src/hooks/beforeChange.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA;AAErE,OAAO,KAAK,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAIpE,UAAU,IAAI;IACZ,OAAO,EAAE,gBAAgB,CAAA;IACzB,UAAU,EAAE,gBAAgB,CAAA;IAC5B,2BAA2B,CAAC,EAAE,OAAO,CAAA;IACrC,eAAe,CAAC,EAAE,eAAe,CAAA;IACjC,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,IAAI,CAAC,EAAE,SAAS,CAAA;CACjB;AAiBD,eAAO,MAAM,mBAAmB,6FAQ3B,IAAI,KAAG,SAoCT,CAAA"}
@@ -9,11 +9,14 @@ const getObjectFolder = (data, originalDoc)=>{
9
9
  }
10
10
  return safePrefix || safeObjectKey;
11
11
  };
12
- export const getBeforeChangeHook = ({ adapter, collection, disablePayloadAccessControl, generateFileURL, size })=>async ({ data, originalDoc, value })=>{
13
- const newFilename = size ? data?.sizes?.[size.name]?.filename : data?.filename;
14
- const originalFilename = size ? originalDoc?.sizes?.[size.name]?.filename : originalDoc?.filename;
12
+ export const getBeforeChangeHook = ({ adapter, collection, disablePayloadAccessControl, generateFileURL, isOriginal, size })=>async ({ data, originalDoc, value })=>{
13
+ const newRepresentation = isOriginal ? data?.original : size ? data?.variants?.[size.name] : data;
14
+ const originalRepresentation = isOriginal ? originalDoc?.original : size ? originalDoc?.variants?.[size.name] : originalDoc;
15
+ const newFilename = newRepresentation?.filename;
16
+ const originalFilename = originalRepresentation?.filename;
15
17
  const filename = newFilename || originalFilename;
16
- const prefix = getObjectFolder(data, originalDoc);
18
+ const representation = newRepresentation ?? originalRepresentation;
19
+ const prefix = getObjectFolder(representation, data ?? originalDoc);
17
20
  let url = value;
18
21
  if (generateFileURL && filename) {
19
22
  url = await generateFileURL({
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/hooks/beforeChange.ts"],"sourcesContent":["import type { CollectionConfig, FieldHook, ImageSize } from 'payload'\n\nimport type { GeneratedAdapter, GenerateFileURL } from '../types.js'\n\nimport { sanitizePrefix } from '../utilities/sanitizePrefix.js'\n\ninterface Args {\n adapter: GeneratedAdapter\n collection: CollectionConfig\n disablePayloadAccessControl?: boolean\n generateFileURL?: GenerateFileURL\n size?: ImageSize\n}\n\n// The object's folder: semantic prefix + `_objectKey` segment.\nconst getObjectFolder = (data: unknown, originalDoc: unknown): string => {\n const source = (data ?? originalDoc ?? {}) as Record<string, unknown>\n const safePrefix = sanitizePrefix(typeof source.prefix === 'string' ? source.prefix : '')\n const safeObjectKey = sanitizePrefix(\n typeof source._objectKey === 'string' ? source._objectKey : '',\n )\n\n if (safePrefix && safeObjectKey) {\n return `${safePrefix}/${safeObjectKey}`\n }\n\n return safePrefix || safeObjectKey\n}\n\nexport const getBeforeChangeHook =\n ({ adapter, collection, disablePayloadAccessControl, generateFileURL, size }: Args): FieldHook =>\n async ({ data, originalDoc, value }) => {\n const newFilename = size ? data?.sizes?.[size.name]?.filename : data?.filename\n const originalFilename = size\n ? originalDoc?.sizes?.[size.name]?.filename\n : originalDoc?.filename\n const filename = newFilename || originalFilename\n const prefix = getObjectFolder(data, originalDoc)\n let url = value\n\n if (generateFileURL && filename) {\n url = await generateFileURL({\n collection,\n filename,\n prefix,\n size,\n })\n } else if (disablePayloadAccessControl && filename && adapter.generateURL) {\n url = await adapter.generateURL({\n collection,\n data: data || originalDoc,\n filename,\n prefix,\n })\n }\n\n return url\n }\n"],"names":["sanitizePrefix","getObjectFolder","data","originalDoc","source","safePrefix","prefix","safeObjectKey","_objectKey","getBeforeChangeHook","adapter","collection","disablePayloadAccessControl","generateFileURL","size","value","newFilename","sizes","name","filename","originalFilename","url","generateURL"],"mappings":"AAIA,SAASA,cAAc,QAAQ,iCAAgC;AAU/D,+DAA+D;AAC/D,MAAMC,kBAAkB,CAACC,MAAeC;IACtC,MAAMC,SAAUF,QAAQC,eAAe,CAAC;IACxC,MAAME,aAAaL,eAAe,OAAOI,OAAOE,MAAM,KAAK,WAAWF,OAAOE,MAAM,GAAG;IACtF,MAAMC,gBAAgBP,eACpB,OAAOI,OAAOI,UAAU,KAAK,WAAWJ,OAAOI,UAAU,GAAG;IAG9D,IAAIH,cAAcE,eAAe;QAC/B,OAAO,GAAGF,WAAW,CAAC,EAAEE,eAAe;IACzC;IAEA,OAAOF,cAAcE;AACvB;AAEA,OAAO,MAAME,sBACX,CAAC,EAAEC,OAAO,EAAEC,UAAU,EAAEC,2BAA2B,EAAEC,eAAe,EAAEC,IAAI,EAAQ,GAClF,OAAO,EAAEZ,IAAI,EAAEC,WAAW,EAAEY,KAAK,EAAE;QACjC,MAAMC,cAAcF,OAAOZ,MAAMe,OAAO,CAACH,KAAKI,IAAI,CAAC,EAAEC,WAAWjB,MAAMiB;QACtE,MAAMC,mBAAmBN,OACrBX,aAAac,OAAO,CAACH,KAAKI,IAAI,CAAC,EAAEC,WACjChB,aAAagB;QACjB,MAAMA,WAAWH,eAAeI;QAChC,MAAMd,SAASL,gBAAgBC,MAAMC;QACrC,IAAIkB,MAAMN;QAEV,IAAIF,mBAAmBM,UAAU;YAC/BE,MAAM,MAAMR,gBAAgB;gBAC1BF;gBACAQ;gBACAb;gBACAQ;YACF;QACF,OAAO,IAAIF,+BAA+BO,YAAYT,QAAQY,WAAW,EAAE;YACzED,MAAM,MAAMX,QAAQY,WAAW,CAAC;gBAC9BX;gBACAT,MAAMA,QAAQC;gBACdgB;gBACAb;YACF;QACF;QAEA,OAAOe;IACT,EAAC"}
1
+ {"version":3,"sources":["../../src/hooks/beforeChange.ts"],"sourcesContent":["import type { CollectionConfig, FieldHook, ImageSize } from 'payload'\n\nimport type { GeneratedAdapter, GenerateFileURL } from '../types.js'\n\nimport { sanitizePrefix } from '../utilities/sanitizePrefix.js'\n\ninterface Args {\n adapter: GeneratedAdapter\n collection: CollectionConfig\n disablePayloadAccessControl?: boolean\n generateFileURL?: GenerateFileURL\n isOriginal?: boolean\n size?: ImageSize\n}\n\n// The object's folder: semantic prefix + `_objectKey` segment.\nconst getObjectFolder = (data: unknown, originalDoc: unknown): string => {\n const source = (data ?? originalDoc ?? {}) as Record<string, unknown>\n const safePrefix = sanitizePrefix(typeof source.prefix === 'string' ? source.prefix : '')\n const safeObjectKey = sanitizePrefix(\n typeof source._objectKey === 'string' ? source._objectKey : '',\n )\n\n if (safePrefix && safeObjectKey) {\n return `${safePrefix}/${safeObjectKey}`\n }\n\n return safePrefix || safeObjectKey\n}\n\nexport const getBeforeChangeHook =\n ({\n adapter,\n collection,\n disablePayloadAccessControl,\n generateFileURL,\n isOriginal,\n size,\n }: Args): FieldHook =>\n async ({ data, originalDoc, value }) => {\n const newRepresentation = isOriginal\n ? data?.original\n : size\n ? data?.variants?.[size.name]\n : data\n const originalRepresentation = isOriginal\n ? originalDoc?.original\n : size\n ? originalDoc?.variants?.[size.name]\n : originalDoc\n const newFilename = newRepresentation?.filename\n const originalFilename = originalRepresentation?.filename\n const filename = newFilename || originalFilename\n const representation = newRepresentation ?? originalRepresentation\n const prefix = getObjectFolder(representation, data ?? originalDoc)\n let url = value\n\n if (generateFileURL && filename) {\n url = await generateFileURL({\n collection,\n filename,\n prefix,\n size,\n })\n } else if (disablePayloadAccessControl && filename && adapter.generateURL) {\n url = await adapter.generateURL({\n collection,\n data: data || originalDoc,\n filename,\n prefix,\n })\n }\n\n return url\n }\n"],"names":["sanitizePrefix","getObjectFolder","data","originalDoc","source","safePrefix","prefix","safeObjectKey","_objectKey","getBeforeChangeHook","adapter","collection","disablePayloadAccessControl","generateFileURL","isOriginal","size","value","newRepresentation","original","variants","name","originalRepresentation","newFilename","filename","originalFilename","representation","url","generateURL"],"mappings":"AAIA,SAASA,cAAc,QAAQ,iCAAgC;AAW/D,+DAA+D;AAC/D,MAAMC,kBAAkB,CAACC,MAAeC;IACtC,MAAMC,SAAUF,QAAQC,eAAe,CAAC;IACxC,MAAME,aAAaL,eAAe,OAAOI,OAAOE,MAAM,KAAK,WAAWF,OAAOE,MAAM,GAAG;IACtF,MAAMC,gBAAgBP,eACpB,OAAOI,OAAOI,UAAU,KAAK,WAAWJ,OAAOI,UAAU,GAAG;IAG9D,IAAIH,cAAcE,eAAe;QAC/B,OAAO,GAAGF,WAAW,CAAC,EAAEE,eAAe;IACzC;IAEA,OAAOF,cAAcE;AACvB;AAEA,OAAO,MAAME,sBACX,CAAC,EACCC,OAAO,EACPC,UAAU,EACVC,2BAA2B,EAC3BC,eAAe,EACfC,UAAU,EACVC,IAAI,EACC,GACP,OAAO,EAAEb,IAAI,EAAEC,WAAW,EAAEa,KAAK,EAAE;QACjC,MAAMC,oBAAoBH,aACtBZ,MAAMgB,WACNH,OACEb,MAAMiB,UAAU,CAACJ,KAAKK,IAAI,CAAC,GAC3BlB;QACN,MAAMmB,yBAAyBP,aAC3BX,aAAae,WACbH,OACEZ,aAAagB,UAAU,CAACJ,KAAKK,IAAI,CAAC,GAClCjB;QACN,MAAMmB,cAAcL,mBAAmBM;QACvC,MAAMC,mBAAmBH,wBAAwBE;QACjD,MAAMA,WAAWD,eAAeE;QAChC,MAAMC,iBAAiBR,qBAAqBI;QAC5C,MAAMf,SAASL,gBAAgBwB,gBAAgBvB,QAAQC;QACvD,IAAIuB,MAAMV;QAEV,IAAIH,mBAAmBU,UAAU;YAC/BG,MAAM,MAAMb,gBAAgB;gBAC1BF;gBACAY;gBACAjB;gBACAS;YACF;QACF,OAAO,IAAIH,+BAA+BW,YAAYb,QAAQiB,WAAW,EAAE;YACzED,MAAM,MAAMhB,QAAQiB,WAAW,CAAC;gBAC9BhB;gBACAT,MAAMA,QAAQC;gBACdoB;gBACAjB;YACF;QACF;QAEA,OAAOoB;IACT,EAAC"}
@@ -0,0 +1,8 @@
1
+ import type { CollectionAfterReadHook, CollectionConfig } from 'payload';
2
+ import type { GeneratedAdapter, GenerateFileURL } from '../types.js';
3
+ export declare const getPublicOriginalURLHook: ({ adapter, collection, generateFileURL, }: {
4
+ adapter: GeneratedAdapter;
5
+ collection: CollectionConfig;
6
+ generateFileURL?: GenerateFileURL;
7
+ }) => CollectionAfterReadHook;
8
+ //# sourceMappingURL=publicOriginalURL.d.ts.map