@payloadcms/plugin-cloud-storage 3.91.0-internal.6e3dc85 → 4.0.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (104) hide show
  1. package/LICENSE.md +1 -1
  2. package/README.md +4 -4
  3. package/dist/client/createClientUploadHandler.d.ts +8 -7
  4. package/dist/client/createClientUploadHandler.d.ts.map +1 -1
  5. package/dist/client/createClientUploadHandler.js +26 -22
  6. package/dist/client/createClientUploadHandler.js.map +1 -1
  7. package/dist/exports/client.d.ts +1 -1
  8. package/dist/exports/client.d.ts.map +1 -1
  9. package/dist/exports/client.js +1 -1
  10. package/dist/exports/client.js.map +1 -1
  11. package/dist/exports/utilities.d.ts +2 -4
  12. package/dist/exports/utilities.d.ts.map +1 -1
  13. package/dist/exports/utilities.js +2 -4
  14. package/dist/exports/utilities.js.map +1 -1
  15. package/dist/fields/getFields.d.ts +1 -5
  16. package/dist/fields/getFields.d.ts.map +1 -1
  17. package/dist/fields/getFields.js +102 -35
  18. package/dist/fields/getFields.js.map +1 -1
  19. package/dist/hooks/afterChange.d.ts +3 -1
  20. package/dist/hooks/afterChange.d.ts.map +1 -1
  21. package/dist/hooks/afterChange.js +93 -27
  22. package/dist/hooks/afterChange.js.map +1 -1
  23. package/dist/hooks/afterDelete.d.ts.map +1 -1
  24. package/dist/hooks/afterDelete.js +10 -2
  25. package/dist/hooks/afterDelete.js.map +1 -1
  26. package/dist/hooks/afterRead.d.ts +6 -1
  27. package/dist/hooks/afterRead.d.ts.map +1 -1
  28. package/dist/hooks/afterRead.js +27 -11
  29. package/dist/hooks/afterRead.js.map +1 -1
  30. package/dist/hooks/beforeChange.d.ts +2 -1
  31. package/dist/hooks/beforeChange.d.ts.map +1 -1
  32. package/dist/hooks/beforeChange.js +14 -9
  33. package/dist/hooks/beforeChange.js.map +1 -1
  34. package/dist/hooks/publicOriginalURL.d.ts +8 -0
  35. package/dist/hooks/publicOriginalURL.d.ts.map +1 -0
  36. package/dist/hooks/publicOriginalURL.js +34 -0
  37. package/dist/hooks/publicOriginalURL.js.map +1 -0
  38. package/dist/plugin.d.ts.map +1 -1
  39. package/dist/plugin.js +198 -132
  40. package/dist/plugin.js.map +1 -1
  41. package/dist/types.d.ts +48 -31
  42. package/dist/types.d.ts.map +1 -1
  43. package/dist/types.js.map +1 -1
  44. package/dist/utilities/buildStoragePathData.d.ts +0 -6
  45. package/dist/utilities/buildStoragePathData.d.ts.map +1 -1
  46. package/dist/utilities/buildStoragePathData.js +0 -2
  47. package/dist/utilities/buildStoragePathData.js.map +1 -1
  48. package/dist/utilities/createFileOperations.d.ts +13 -0
  49. package/dist/utilities/createFileOperations.d.ts.map +1 -0
  50. package/dist/utilities/createFileOperations.js +258 -0
  51. package/dist/utilities/createFileOperations.js.map +1 -0
  52. package/dist/utilities/getFilePrefix.d.ts +9 -20
  53. package/dist/utilities/getFilePrefix.d.ts.map +1 -1
  54. package/dist/utilities/getFilePrefix.js +42 -31
  55. package/dist/utilities/getFilePrefix.js.map +1 -1
  56. package/dist/utilities/getIncomingFiles.js +4 -4
  57. package/dist/utilities/getIncomingFiles.js.map +1 -1
  58. package/dist/utilities/getStorageLocationSelect.d.ts +9 -0
  59. package/dist/utilities/getStorageLocationSelect.d.ts.map +1 -0
  60. package/dist/utilities/getStorageLocationSelect.js +54 -0
  61. package/dist/utilities/getStorageLocationSelect.js.map +1 -0
  62. package/dist/utilities/resolveSignedURLKey.d.ts +10 -10
  63. package/dist/utilities/resolveSignedURLKey.d.ts.map +1 -1
  64. package/dist/utilities/resolveSignedURLKey.js +33 -26
  65. package/dist/utilities/resolveSignedURLKey.js.map +1 -1
  66. package/dist/utilities/sanitizePrefix.d.ts +1 -9
  67. package/dist/utilities/sanitizePrefix.d.ts.map +1 -1
  68. package/dist/utilities/sanitizePrefix.js +1 -21
  69. package/dist/utilities/sanitizePrefix.js.map +1 -1
  70. package/package.json +6 -6
  71. package/dist/admin/fields/getFields.d.ts +0 -17
  72. package/dist/admin/fields/getFields.d.ts.map +0 -1
  73. package/dist/admin/fields/getFields.js +0 -98
  74. package/dist/admin/fields/getFields.js.map +0 -1
  75. package/dist/admin/index.d.ts +0 -4
  76. package/dist/admin/index.d.ts.map +0 -1
  77. package/dist/admin/index.js +0 -34
  78. package/dist/admin/index.js.map +0 -1
  79. package/dist/hooks/afterChange.spec.js +0 -150
  80. package/dist/hooks/afterChange.spec.js.map +0 -1
  81. package/dist/hooks/normalizeUploadPrefix.spec.js +0 -154
  82. package/dist/hooks/normalizeUploadPrefix.spec.js.map +0 -1
  83. package/dist/plugin.spec.js +0 -166
  84. package/dist/plugin.spec.js.map +0 -1
  85. package/dist/utilities/assertReceiptMatchesFileKey.d.ts +0 -15
  86. package/dist/utilities/assertReceiptMatchesFileKey.d.ts.map +0 -1
  87. package/dist/utilities/assertReceiptMatchesFileKey.js +0 -31
  88. package/dist/utilities/assertReceiptMatchesFileKey.js.map +0 -1
  89. package/dist/utilities/buildStoragePathData.spec.js +0 -254
  90. package/dist/utilities/buildStoragePathData.spec.js.map +0 -1
  91. package/dist/utilities/getFilePrefix.spec.js +0 -291
  92. package/dist/utilities/getFilePrefix.spec.js.map +0 -1
  93. package/dist/utilities/initClientUploads.d.ts +0 -13
  94. package/dist/utilities/initClientUploads.d.ts.map +0 -1
  95. package/dist/utilities/initClientUploads.js +0 -63
  96. package/dist/utilities/initClientUploads.js.map +0 -1
  97. package/dist/utilities/resolveSignedURLKey.spec.js +0 -56
  98. package/dist/utilities/resolveSignedURLKey.spec.js.map +0 -1
  99. package/dist/utilities/verifyClientUploadReceiptForFileKey.d.ts +0 -20
  100. package/dist/utilities/verifyClientUploadReceiptForFileKey.d.ts.map +0 -1
  101. package/dist/utilities/verifyClientUploadReceiptForFileKey.js +0 -24
  102. package/dist/utilities/verifyClientUploadReceiptForFileKey.js.map +0 -1
  103. package/dist/utilities/verifyClientUploadReceiptForFileKey.spec.js +0 -108
  104. package/dist/utilities/verifyClientUploadReceiptForFileKey.spec.js.map +0 -1
@@ -1,36 +1,94 @@
1
+ import { deepMergeWithSourceArrays } from 'payload';
1
2
  import { buildPrefixWithObjectKey } from '../utilities/buildPrefixWithObjectKey.js';
2
3
  import { buildStoragePathData, buildUploadStoragePathData } from '../utilities/buildStoragePathData.js';
3
4
  import { getIncomingFiles } from '../utilities/getIncomingFiles.js';
5
+ import { appendProxyPrefix } from './afterRead.js';
4
6
  // The object's folder: semantic prefix + `_objectKey` segment.
5
- const getObjectFolder = (doc)=>{
6
- const record = doc ?? {};
7
+ const getObjectFolder = (data)=>{
8
+ const record = data ?? {};
7
9
  return buildPrefixWithObjectKey({
8
10
  objectKey: record._objectKey,
9
11
  prefix: record.prefix
10
12
  });
11
13
  };
12
- export const getAfterChangeHook = ({ adapter, collection, collectionPrefix, useCompositePrefixes })=>async ({ doc, operation, previousDoc, req })=>{
14
+ export const getAfterChangeHook = ({ adapter, collection, collectionPrefix, disablePayloadAccessControl, hasCustomFileURL, useCompositePrefixes })=>async ({ data, doc, operation, previousDoc, req, select })=>{
13
15
  // Skip if this is an internal update to prevent infinite loop
14
16
  if (req.context?.skipCloudStorage) {
15
17
  return doc;
16
18
  }
17
- const isDraftSave = doc._status === 'draft';
19
+ // Restore upload metadata removed by select, including partially selected image sizes.
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
+ };
45
+ const isDraftSave = uploadData._status === 'draft';
18
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
+ }
19
80
  try {
20
81
  const files = getIncomingFiles({
21
- data: doc,
82
+ data: uploadData,
22
83
  req
23
84
  });
24
85
  if (files.length > 0) {
25
86
  // Fold `_objectKey` so generated sizes land in the same folder as the original.
26
87
  const dataForUpload = {
27
- ...doc,
28
- prefix: getObjectFolder(doc)
88
+ ...uploadData,
89
+ prefix: getObjectFolder(uploadData)
29
90
  };
30
- const uploadResults = await Promise.all(files// Files with a clientUploadContext are already in storage (uploaded
31
- // directly by the browser), so skip re-uploading them here.
32
- .filter((file)=>!file.clientUploadContext).map((file)=>adapter.handleUpload({
33
- clientUploadContext: file.clientUploadContext,
91
+ const uploadResults = await Promise.all(files.filter((file)=>!file.uploadReference).map((file)=>adapter.handleUpload({
34
92
  collection,
35
93
  data: dataForUpload,
36
94
  file,
@@ -59,49 +117,57 @@ export const getAfterChangeHook = ({ adapter, collection, collectionPrefix, useC
59
117
  req.file = undefined;
60
118
  req.payloadUploadSizes = undefined;
61
119
  try {
62
- await req.payload.update({
120
+ const updatedDoc = await req.payload.update({
63
121
  id: doc.id,
64
122
  collection: collection.slug,
65
123
  data: uploadMetadata,
66
124
  depth: 0,
67
125
  draft: isDraftSave,
68
- req
126
+ overrideAccess: true,
127
+ req,
128
+ select
69
129
  });
130
+ // Persist all adapter metadata, but do not add unselected fields to the response.
131
+ docWithMetadata = select ? {
132
+ ...doc,
133
+ ...updatedDoc
134
+ } : {
135
+ ...doc,
136
+ ...uploadMetadata
137
+ };
70
138
  } finally{
71
139
  delete req.context.skipCloudStorage;
72
140
  }
73
- docWithMetadata = {
74
- ...doc,
75
- ...uploadMetadata
76
- };
77
141
  }
78
142
  // Delete previous files only after the new upload and metadata
79
143
  // persistence have succeeded. Deleting earlier would orphan the
80
144
  // record if a later step throws (e.g. a user-defined afterChange
81
145
  // hook on the same collection).
82
- if (previousDoc && operation === 'update' && !isDraftOverPublished) {
146
+ if (previousDoc && operation === 'update' && !isDraftOverPublished && !collection.versions && !previousDoc.original) {
83
147
  let filesToDelete = [];
84
148
  if (typeof previousDoc?.filename === 'string') {
85
149
  filesToDelete.push(previousDoc.filename);
86
150
  }
87
- if (typeof previousDoc.sizes === 'object') {
88
- 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));
89
153
  }
90
154
  // Compare full locations: a replacement can reuse a filename while moving
91
155
  // a legacy object beneath the collection prefix.
156
+ const newFileData = {
157
+ ...uploadData,
158
+ ...uploadMetadata
159
+ };
92
160
  const newFilenames = new Set();
93
- if (typeof docWithMetadata.filename === 'string') {
94
- newFilenames.add(docWithMetadata.filename);
161
+ if (typeof newFileData.filename === 'string') {
162
+ newFilenames.add(newFileData.filename);
95
163
  }
96
- if (typeof docWithMetadata.sizes === 'object') {
97
- for (const size of Object.values(docWithMetadata.sizes || {})){
164
+ if (typeof newFileData.variants === 'object') {
165
+ for (const size of Object.values(newFileData.variants || {})){
98
166
  if (size?.filename && typeof size.filename === 'string') {
99
167
  newFilenames.add(size.filename);
100
168
  }
101
169
  }
102
170
  }
103
- // Resolve each object's real location, folding `_objectKey` so a client-uploaded
104
- // original is compared and deleted at `prefix/_objectKey/filename`.
105
171
  const resolveKey = ({ data, filename })=>buildStoragePathData({
106
172
  collectionPrefix,
107
173
  docPrefix: getObjectFolder(data),
@@ -111,7 +177,7 @@ export const getAfterChangeHook = ({ adapter, collection, collectionPrefix, useC
111
177
  const newKeys = new Set([
112
178
  ...newFilenames
113
179
  ].map((filename)=>resolveKey({
114
- data: docWithMetadata,
180
+ data: newFileData,
115
181
  filename
116
182
  })));
117
183
  const deletionPromises = filesToDelete.map(async (filename)=>{
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/hooks/afterChange.ts"],"sourcesContent":["import type { CollectionAfterChangeHook, CollectionConfig, FileData, TypeWithID } 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 = (doc: unknown): string => {\n const record = (doc ?? {}) 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 ({ doc, operation, previousDoc, req }) => {\n // Skip if this is an internal update to prevent infinite loop\n if (req.context?.skipCloudStorage) {\n return doc\n }\n\n const isDraftSave = (doc 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: doc, req })\n\n if (files.length > 0) {\n // Fold `_objectKey` so generated sizes land in the same folder as the original.\n const dataForUpload = { ...doc, prefix: getObjectFolder(doc) }\n\n const uploadResults = await Promise.all(\n files\n // Files with a clientUploadContext are already in storage (uploaded\n // directly by the browser), so skip re-uploading them here.\n .filter((file) => !file.clientUploadContext)\n .map((file) =>\n adapter.handleUpload({\n clientUploadContext: file.clientUploadContext,\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 await req.payload.update({\n id: doc.id,\n collection: collection.slug,\n data: uploadMetadata,\n depth: 0,\n draft: isDraftSave,\n req,\n })\n } finally {\n delete req.context.skipCloudStorage\n }\n\n docWithMetadata = { ...doc, ...uploadMetadata }\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 newFilenames = new Set<string>()\n if (typeof docWithMetadata.filename === 'string') {\n newFilenames.add(docWithMetadata.filename)\n }\n if (typeof docWithMetadata.sizes === 'object') {\n for (const size of Object.values(docWithMetadata.sizes || {})) {\n if (size?.filename && typeof size.filename === 'string') {\n newFilenames.add(size.filename)\n }\n }\n }\n\n // Resolve each object's real location, folding `_objectKey` so a client-uploaded\n // original is compared and deleted at `prefix/_objectKey/filename`.\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\n const newKeys = new Set(\n [...newFilenames].map((filename) =>\n resolveKey({\n data: docWithMetadata 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":["buildPrefixWithObjectKey","buildStoragePathData","buildUploadStoragePathData","getIncomingFiles","getObjectFolder","doc","record","objectKey","_objectKey","prefix","getAfterChangeHook","adapter","collection","collectionPrefix","useCompositePrefixes","operation","previousDoc","req","context","skipCloudStorage","isDraftSave","_status","isDraftOverPublished","files","data","length","dataForUpload","uploadResults","Promise","all","filter","file","clientUploadContext","map","handleUpload","storageFilePath","docPrefix","filename","uploadMetadata","result","reduce","acc","metadata","docWithMetadata","Object","keys","undefined","payloadUploadSizes","payload","update","id","slug","depth","draft","filesToDelete","push","sizes","concat","values","resizedFileData","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;AAQD,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"}
@@ -1,17 +1,24 @@
1
- import { buildPrefixWithObjectKey } from '../utilities/buildPrefixWithObjectKey.js';
1
+ import { sanitizePrefix } from '../utilities/sanitizePrefix.js';
2
2
  // The object's folder: semantic prefix + `_objectKey` segment.
3
3
  const getObjectFolder = (data)=>{
4
4
  const record = data ?? {};
5
- return buildPrefixWithObjectKey({
6
- objectKey: record._objectKey,
7
- prefix: record.prefix
8
- });
5
+ const safePrefix = sanitizePrefix(typeof record.prefix === 'string' ? record.prefix : '');
6
+ const safeObjectKey = sanitizePrefix(typeof record._objectKey === 'string' ? record._objectKey : '');
7
+ if (safePrefix && safeObjectKey) {
8
+ return `${safePrefix}/${safeObjectKey}`;
9
+ }
10
+ return safePrefix || safeObjectKey;
9
11
  };
10
- export const getAfterReadHook = ({ adapter, collection, disablePayloadAccessControl, generateFileURL, size })=>async ({ data, value })=>{
11
- const filename = size ? data?.sizes?.[size.name]?.filename : data?.filename;
12
- 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);
13
17
  // Direct-serve URLs encode the full location; the proxy resolves `_objectKey` server-side.
14
- const objectFolder = getObjectFolder(data);
18
+ const objectFolder = getObjectFolder({
19
+ _objectKey: representation?._objectKey ?? (hasLegacyVariant ? data?._objectKey : undefined),
20
+ prefix
21
+ });
15
22
  let url = value;
16
23
  if (filename) {
17
24
  if (generateFileURL) {
@@ -29,11 +36,20 @@ export const getAfterReadHook = ({ adapter, collection, disablePayloadAccessCont
29
36
  prefix: objectFolder
30
37
  });
31
38
  } else if (url && prefix) {
32
- const separator = url.includes('?') ? '&' : '?';
33
- url = `${url}${separator}prefix=${encodeURIComponent(prefix)}`;
39
+ url = appendProxyPrefix({
40
+ prefix,
41
+ url
42
+ });
34
43
  }
35
44
  }
36
45
  return url;
37
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
+ };
38
54
 
39
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 { buildPrefixWithObjectKey } from '../utilities/buildPrefixWithObjectKey.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: { _objectKey?: string; prefix?: string } | undefined): string => {\n const record = (data ?? {}) as { _objectKey?: string; prefix?: string }\n return buildPrefixWithObjectKey({ objectKey: record._objectKey, prefix: record.prefix })\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":["buildPrefixWithObjectKey","getObjectFolder","data","record","objectKey","_objectKey","prefix","getAfterReadHook","adapter","collection","disablePayloadAccessControl","generateFileURL","size","value","filename","sizes","name","objectFolder","url","generateURL","separator","includes","encodeURIComponent"],"mappings":"AAIA,SAASA,wBAAwB,QAAQ,2CAA0C;AAUnF,+DAA+D;AAC/D,MAAMC,kBAAkB,CAACC;IACvB,MAAMC,SAAUD,QAAQ,CAAC;IACzB,OAAOF,yBAAyB;QAAEI,WAAWD,OAAOE,UAAU;QAAEC,QAAQH,OAAOG,MAAM;IAAC;AACxF;AAEA,OAAO,MAAMC,mBACX,CAAC,EAAEC,OAAO,EAAEC,UAAU,EAAEC,2BAA2B,EAAEC,eAAe,EAAEC,IAAI,EAAQ,GAClF,OAAO,EAAEV,IAAI,EAAEW,KAAK,EAAE;QACpB,MAAMC,WAAWF,OAAOV,MAAMa,OAAO,CAACH,KAAKI,IAAI,CAAC,EAAEF,WAAWZ,MAAMY;QACnE,MAAMR,SAASJ,MAAMI;QACrB,2FAA2F;QAC3F,MAAMW,eAAehB,gBAAgBC;QACrC,IAAIgB,MAAML;QAEV,IAAIC,UAAU;YACZ,IAAIH,iBAAiB;gBACnBO,MAAM,MAAMP,gBAAgB;oBAC1BF;oBACAK;oBACAR,QAAQW;oBACRL;gBACF;YACF,OAAO,IAAIF,+BAA+BF,QAAQW,WAAW,EAAE;gBAC7DD,MAAM,MAAMV,QAAQW,WAAW,CAAC;oBAC9BV;oBACAP;oBACAY;oBACAR,QAAQW;gBACV;YACF,OAAO,IAAIC,OAAOZ,QAAQ;gBACxB,MAAMc,YAAYF,IAAIG,QAAQ,CAAC,OAAO,MAAM;gBAC5CH,MAAM,GAAGA,MAAME,UAAU,OAAO,EAAEE,mBAAmBhB,SAAS;YAChE;QACF;QAEA,OAAOY;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;AAWD,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"}
@@ -1,17 +1,22 @@
1
- import { buildPrefixWithObjectKey } from '../utilities/buildPrefixWithObjectKey.js';
1
+ import { sanitizePrefix } from '../utilities/sanitizePrefix.js';
2
2
  // The object's folder: semantic prefix + `_objectKey` segment.
3
3
  const getObjectFolder = (data, originalDoc)=>{
4
4
  const source = data ?? originalDoc ?? {};
5
- return buildPrefixWithObjectKey({
6
- objectKey: source._objectKey,
7
- prefix: source.prefix
8
- });
5
+ const safePrefix = sanitizePrefix(typeof source.prefix === 'string' ? source.prefix : '');
6
+ const safeObjectKey = sanitizePrefix(typeof source._objectKey === 'string' ? source._objectKey : '');
7
+ if (safePrefix && safeObjectKey) {
8
+ return `${safePrefix}/${safeObjectKey}`;
9
+ }
10
+ return safePrefix || safeObjectKey;
9
11
  };
10
- export const getBeforeChangeHook = ({ adapter, collection, disablePayloadAccessControl, generateFileURL, size })=>async ({ data, originalDoc, value })=>{
11
- const newFilename = size ? data?.sizes?.[size.name]?.filename : data?.filename;
12
- 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;
13
17
  const filename = newFilename || originalFilename;
14
- const prefix = getObjectFolder(data, originalDoc);
18
+ const representation = newRepresentation ?? originalRepresentation;
19
+ const prefix = getObjectFolder(representation, data ?? originalDoc);
15
20
  let url = value;
16
21
  if (generateFileURL && filename) {
17
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 { buildPrefixWithObjectKey } from '../utilities/buildPrefixWithObjectKey.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 { _objectKey?: string; prefix?: string }\n return buildPrefixWithObjectKey({\n objectKey: source._objectKey,\n prefix: source.prefix,\n })\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":["buildPrefixWithObjectKey","getObjectFolder","data","originalDoc","source","objectKey","_objectKey","prefix","getBeforeChangeHook","adapter","collection","disablePayloadAccessControl","generateFileURL","size","value","newFilename","sizes","name","filename","originalFilename","url","generateURL"],"mappings":"AAIA,SAASA,wBAAwB,QAAQ,2CAA0C;AAUnF,+DAA+D;AAC/D,MAAMC,kBAAkB,CAACC,MAAeC;IACtC,MAAMC,SAAUF,QAAQC,eAAe,CAAC;IACxC,OAAOH,yBAAyB;QAC9BK,WAAWD,OAAOE,UAAU;QAC5BC,QAAQH,OAAOG,MAAM;IACvB;AACF;AAEA,OAAO,MAAMC,sBACX,CAAC,EAAEC,OAAO,EAAEC,UAAU,EAAEC,2BAA2B,EAAEC,eAAe,EAAEC,IAAI,EAAQ,GAClF,OAAO,EAAEX,IAAI,EAAEC,WAAW,EAAEW,KAAK,EAAE;QACjC,MAAMC,cAAcF,OAAOX,MAAMc,OAAO,CAACH,KAAKI,IAAI,CAAC,EAAEC,WAAWhB,MAAMgB;QACtE,MAAMC,mBAAmBN,OACrBV,aAAaa,OAAO,CAACH,KAAKI,IAAI,CAAC,EAAEC,WACjCf,aAAae;QACjB,MAAMA,WAAWH,eAAeI;QAChC,MAAMZ,SAASN,gBAAgBC,MAAMC;QACrC,IAAIiB,MAAMN;QAEV,IAAIF,mBAAmBM,UAAU;YAC/BE,MAAM,MAAMR,gBAAgB;gBAC1BF;gBACAQ;gBACAX;gBACAM;YACF;QACF,OAAO,IAAIF,+BAA+BO,YAAYT,QAAQY,WAAW,EAAE;YACzED,MAAM,MAAMX,QAAQY,WAAW,CAAC;gBAC9BX;gBACAR,MAAMA,QAAQC;gBACde;gBACAX;YACF;QACF;QAEA,OAAOa;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
@@ -0,0 +1 @@
1
+ {"version":3,"file":"publicOriginalURL.d.ts","sourceRoot":"","sources":["../../src/hooks/publicOriginalURL.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,uBAAuB,EAAE,gBAAgB,EAAwB,MAAM,SAAS,CAAA;AAE9F,OAAO,KAAK,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAIpE,eAAO,MAAM,wBAAwB,8CAKhC;IACD,OAAO,EAAE,gBAAgB,CAAA;IACzB,UAAU,EAAE,gBAAgB,CAAA;IAC5B,eAAe,CAAC,EAAE,eAAe,CAAA;CAClC,KAAG,uBAsBH,CAAA"}
@@ -0,0 +1,34 @@
1
+ import { buildPrefixWithObjectKey } from '../utilities/buildPrefixWithObjectKey.js';
2
+ export const getPublicOriginalURLHook = ({ adapter, collection, generateFileURL })=>async ({ doc })=>{
3
+ const upload = doc;
4
+ const filename = upload.original?.filename;
5
+ if (!filename) {
6
+ return doc;
7
+ }
8
+ if (upload.original?.url && !upload.original.url.startsWith('/')) {
9
+ return doc;
10
+ }
11
+ const prefix = buildPrefixWithObjectKey({
12
+ objectKey: upload.original?._objectKey,
13
+ prefix: upload.original?.prefix
14
+ });
15
+ const url = generateFileURL ? await generateFileURL({
16
+ collection,
17
+ filename,
18
+ prefix
19
+ }) : await adapter.generateURL?.({
20
+ collection,
21
+ data: upload,
22
+ filename,
23
+ prefix
24
+ });
25
+ return url ? {
26
+ ...doc,
27
+ original: {
28
+ ...upload.original,
29
+ url
30
+ }
31
+ } : doc;
32
+ };
33
+
34
+ //# sourceMappingURL=publicOriginalURL.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/hooks/publicOriginalURL.ts"],"sourcesContent":["import type { CollectionAfterReadHook, CollectionConfig, FileData, TypeWithID } from 'payload'\n\nimport type { GeneratedAdapter, GenerateFileURL } from '../types.js'\n\nimport { buildPrefixWithObjectKey } from '../utilities/buildPrefixWithObjectKey.js'\n\nexport const getPublicOriginalURLHook =\n ({\n adapter,\n collection,\n generateFileURL,\n }: {\n adapter: GeneratedAdapter\n collection: CollectionConfig\n generateFileURL?: GenerateFileURL\n }): CollectionAfterReadHook =>\n async ({ doc }) => {\n const upload = doc as { _objectKey?: string; prefix?: string } & FileData & TypeWithID\n const filename = upload.original?.filename\n\n if (!filename) {\n return doc\n }\n\n if (upload.original?.url && !upload.original.url.startsWith('/')) {\n return doc\n }\n\n const prefix = buildPrefixWithObjectKey({\n objectKey: upload.original?._objectKey,\n prefix: upload.original?.prefix,\n })\n const url = generateFileURL\n ? await generateFileURL({ collection, filename, prefix })\n : await adapter.generateURL?.({ collection, data: upload, filename, prefix })\n\n return url ? { ...doc, original: { ...upload.original, url } } : doc\n }\n"],"names":["buildPrefixWithObjectKey","getPublicOriginalURLHook","adapter","collection","generateFileURL","doc","upload","filename","original","url","startsWith","prefix","objectKey","_objectKey","generateURL","data"],"mappings":"AAIA,SAASA,wBAAwB,QAAQ,2CAA0C;AAEnF,OAAO,MAAMC,2BACX,CAAC,EACCC,OAAO,EACPC,UAAU,EACVC,eAAe,EAKhB,GACD,OAAO,EAAEC,GAAG,EAAE;QACZ,MAAMC,SAASD;QACf,MAAME,WAAWD,OAAOE,QAAQ,EAAED;QAElC,IAAI,CAACA,UAAU;YACb,OAAOF;QACT;QAEA,IAAIC,OAAOE,QAAQ,EAAEC,OAAO,CAACH,OAAOE,QAAQ,CAACC,GAAG,CAACC,UAAU,CAAC,MAAM;YAChE,OAAOL;QACT;QAEA,MAAMM,SAASX,yBAAyB;YACtCY,WAAWN,OAAOE,QAAQ,EAAEK;YAC5BF,QAAQL,OAAOE,QAAQ,EAAEG;QAC3B;QACA,MAAMF,MAAML,kBACR,MAAMA,gBAAgB;YAAED;YAAYI;YAAUI;QAAO,KACrD,MAAMT,QAAQY,WAAW,GAAG;YAAEX;YAAYY,MAAMT;YAAQC;YAAUI;QAAO;QAE7E,OAAOF,MAAM;YAAE,GAAGJ,GAAG;YAAEG,UAAU;gBAAE,GAAGF,OAAOE,QAAQ;gBAAEC;YAAI;QAAE,IAAIJ;IACnE,EAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AAErC,OAAO,KAAK,EAAa,aAAa,EAAE,MAAM,YAAY,CAAA;AAiB1D,eAAO,MAAM,kBAAkB,kBACb,aAAa,sBACZ,MAAM,KAAG,MA8LzB,CAAA"}
1
+ {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AAErC,OAAO,KAAK,EAAsB,aAAa,EAAE,MAAM,YAAY,CAAA;AAoBnE,eAAO,MAAM,kBAAkB,kBACb,aAAa,sBACZ,MAAM,KAAG,MA+PzB,CAAA"}