payload 4.0.0-internal.e55ccef → 4.0.0-internal.e7d4ebc
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/admin/functions/index.d.ts +0 -7
- package/dist/admin/functions/index.d.ts.map +1 -1
- package/dist/admin/functions/index.js.map +1 -1
- package/dist/admin/types.d.ts +1 -1
- package/dist/admin/types.d.ts.map +1 -1
- package/dist/admin/types.js.map +1 -1
- package/dist/collections/config/client.d.ts +8 -2
- package/dist/collections/config/client.d.ts.map +1 -1
- package/dist/collections/config/client.js +6 -1
- package/dist/collections/config/client.js.map +1 -1
- package/dist/config/sanitize.d.ts.map +1 -1
- package/dist/config/sanitize.js +4 -0
- package/dist/config/sanitize.js.map +1 -1
- package/dist/exports/internal.d.ts +2 -0
- package/dist/exports/internal.d.ts.map +1 -1
- package/dist/exports/internal.js +3 -1
- package/dist/exports/internal.js.map +1 -1
- package/dist/fields/baseFields/slug/generateSlug.d.ts +16 -5
- package/dist/fields/baseFields/slug/generateSlug.d.ts.map +1 -1
- package/dist/fields/baseFields/slug/generateSlug.js +22 -26
- package/dist/fields/baseFields/slug/generateSlug.js.map +1 -1
- package/dist/index.bundled.d.ts +3907 -3862
- package/dist/types/index.d.ts +1 -4
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js.map +1 -1
- package/dist/uploads/checkFileRestrictions.d.ts +1 -1
- package/dist/uploads/checkFileRestrictions.d.ts.map +1 -1
- package/dist/uploads/checkFileRestrictions.js +15 -1
- package/dist/uploads/checkFileRestrictions.js.map +1 -1
- package/dist/uploads/endpoints/uploadInstructions.d.ts +15 -0
- package/dist/uploads/endpoints/uploadInstructions.d.ts.map +1 -0
- package/dist/uploads/endpoints/uploadInstructions.js +84 -0
- package/dist/uploads/endpoints/uploadInstructions.js.map +1 -0
- package/dist/uploads/getFileFromUploadInstructions.d.ts +8 -0
- package/dist/uploads/getFileFromUploadInstructions.d.ts.map +1 -0
- package/dist/uploads/getFileFromUploadInstructions.js +62 -0
- package/dist/uploads/getFileFromUploadInstructions.js.map +1 -0
- package/dist/uploads/stagedUpload.d.ts +27 -0
- package/dist/uploads/stagedUpload.d.ts.map +1 -0
- package/dist/uploads/stagedUpload.js +197 -0
- package/dist/uploads/stagedUpload.js.map +1 -0
- package/dist/uploads/types.d.ts +53 -1
- package/dist/uploads/types.d.ts.map +1 -1
- package/dist/uploads/types.js.map +1 -1
- package/dist/utilities/addDataAndFileToRequest.d.ts.map +1 -1
- package/dist/utilities/addDataAndFileToRequest.js +12 -45
- package/dist/utilities/addDataAndFileToRequest.js.map +1 -1
- package/package.json +2 -2
- package/dist/fields/baseFields/slug/countVersions.d.ts +0 -13
- package/dist/fields/baseFields/slug/countVersions.d.ts.map +0 -1
- package/dist/fields/baseFields/slug/countVersions.js +0 -27
- package/dist/fields/baseFields/slug/countVersions.js.map +0 -1
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
import { jwtVerify } from 'jose';
|
|
2
|
+
import { randomUUID } from 'node:crypto';
|
|
3
|
+
import fs from 'node:fs/promises';
|
|
4
|
+
import os from 'node:os';
|
|
5
|
+
import path from 'node:path';
|
|
6
|
+
import { jwtSign } from '../auth/jwt.js';
|
|
7
|
+
import { APIError, Forbidden } from '../errors/index.js';
|
|
8
|
+
import { formatAdminURL } from '../utilities/formatAdminURL.js';
|
|
9
|
+
import { checkFileRestrictions } from './checkFileRestrictions.js';
|
|
10
|
+
/**
|
|
11
|
+
* Creates a signed, one-hour URL where the client can send the file bytes. The returned file value
|
|
12
|
+
* is later passed to a document create or update request.
|
|
13
|
+
*/ export const generateStagedUploadInstructions = async ({ collectionSlug, docPrefix, filename, filesize, mimeType, req })=>{
|
|
14
|
+
await removeExpiredUploads(req, collectionSlug);
|
|
15
|
+
const { token: uploadId } = await jwtSign({
|
|
16
|
+
fieldsToSign: {
|
|
17
|
+
id: randomUUID(),
|
|
18
|
+
collectionSlug,
|
|
19
|
+
docPrefix,
|
|
20
|
+
filename,
|
|
21
|
+
filesize,
|
|
22
|
+
mimeType,
|
|
23
|
+
user: getUser(req)
|
|
24
|
+
},
|
|
25
|
+
secret: req.payload.secret,
|
|
26
|
+
tokenExpiration
|
|
27
|
+
});
|
|
28
|
+
return {
|
|
29
|
+
type: 'http',
|
|
30
|
+
file: {
|
|
31
|
+
filename,
|
|
32
|
+
mimeType,
|
|
33
|
+
size: filesize,
|
|
34
|
+
uploadReference: {
|
|
35
|
+
uploadId
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
request: {
|
|
39
|
+
headers: {
|
|
40
|
+
'Content-Length': String(filesize),
|
|
41
|
+
'Content-Type': mimeType
|
|
42
|
+
},
|
|
43
|
+
method: 'PUT',
|
|
44
|
+
url: formatAdminURL({
|
|
45
|
+
apiRoute: req.payload.config.routes.api,
|
|
46
|
+
path: `/upload-instructions/${uploadId}`,
|
|
47
|
+
serverURL: req.payload.config.serverURL
|
|
48
|
+
})
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
};
|
|
52
|
+
/**
|
|
53
|
+
* Saves the bytes sent to a signed upload URL. The file is written as a partial file first and only
|
|
54
|
+
* becomes available when its size exactly matches the size in the upload ID.
|
|
55
|
+
*/ export const uploadStagedFile = async (req)=>{
|
|
56
|
+
const upload = await verifyUploadID(req, req.routeParams?.uploadId);
|
|
57
|
+
const directory = await getUploadDirectory(req, upload.collectionSlug);
|
|
58
|
+
const uploadPath = path.join(directory, upload.id);
|
|
59
|
+
const temporaryPath = `${uploadPath}.${randomUUID()}.part`;
|
|
60
|
+
const file = await fs.open(temporaryPath, 'wx');
|
|
61
|
+
let uploadedSize = 0;
|
|
62
|
+
try {
|
|
63
|
+
try {
|
|
64
|
+
const reader = req.body?.getReader();
|
|
65
|
+
while(reader){
|
|
66
|
+
const { done, value } = await reader.read();
|
|
67
|
+
if (done) {
|
|
68
|
+
break;
|
|
69
|
+
}
|
|
70
|
+
uploadedSize += value.byteLength;
|
|
71
|
+
if (uploadedSize > upload.filesize) {
|
|
72
|
+
throw new APIError('Uploaded file is larger than expected.', 400);
|
|
73
|
+
}
|
|
74
|
+
let offset = 0;
|
|
75
|
+
while(offset < value.byteLength){
|
|
76
|
+
const { bytesWritten } = await file.write(value, offset);
|
|
77
|
+
offset += bytesWritten;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
if (uploadedSize !== upload.filesize) {
|
|
81
|
+
throw new APIError('Uploaded file size does not match the expected size.', 400);
|
|
82
|
+
}
|
|
83
|
+
} finally{
|
|
84
|
+
await file.close();
|
|
85
|
+
}
|
|
86
|
+
const collection = req.payload.collections[upload.collectionSlug].config;
|
|
87
|
+
await checkFileRestrictions({
|
|
88
|
+
collection,
|
|
89
|
+
file: {
|
|
90
|
+
name: upload.filename,
|
|
91
|
+
data: Buffer.alloc(0),
|
|
92
|
+
mimetype: upload.mimeType,
|
|
93
|
+
size: upload.filesize,
|
|
94
|
+
tempFilePath: temporaryPath
|
|
95
|
+
},
|
|
96
|
+
req
|
|
97
|
+
});
|
|
98
|
+
await fs.rename(temporaryPath, uploadPath);
|
|
99
|
+
} catch (error) {
|
|
100
|
+
await fs.rm(temporaryPath, {
|
|
101
|
+
force: true
|
|
102
|
+
});
|
|
103
|
+
throw error;
|
|
104
|
+
}
|
|
105
|
+
return new Response(null, {
|
|
106
|
+
status: 204
|
|
107
|
+
});
|
|
108
|
+
};
|
|
109
|
+
/** Removes a temporary upload that the client no longer needs. */ export const deleteStagedFile = async (req)=>{
|
|
110
|
+
const upload = await verifyUploadID(req, req.routeParams?.uploadId);
|
|
111
|
+
const directory = await getUploadDirectory(req, upload.collectionSlug);
|
|
112
|
+
await fs.rm(path.join(directory, upload.id), {
|
|
113
|
+
force: true
|
|
114
|
+
});
|
|
115
|
+
return new Response(null, {
|
|
116
|
+
status: 204
|
|
117
|
+
});
|
|
118
|
+
};
|
|
119
|
+
/**
|
|
120
|
+
* Loads a completed staged file for a document request. Only the same user and collection can use
|
|
121
|
+
* it, and the temporary file is deleted after it is read.
|
|
122
|
+
*/ export const getStagedFile = async ({ collectionSlug, req, uploadReference })=>{
|
|
123
|
+
if (!uploadReference || typeof uploadReference !== 'object' || Array.isArray(uploadReference) || !('uploadId' in uploadReference) || typeof uploadReference.uploadId !== 'string') {
|
|
124
|
+
throw new APIError('Invalid staged upload.', 400);
|
|
125
|
+
}
|
|
126
|
+
const { uploadId } = uploadReference;
|
|
127
|
+
const upload = await verifyUploadID(req, uploadId);
|
|
128
|
+
if (upload.collectionSlug !== collectionSlug || upload.user !== getUser(req)) {
|
|
129
|
+
throw new Forbidden(req.t);
|
|
130
|
+
}
|
|
131
|
+
const directory = await getUploadDirectory(req, upload.collectionSlug);
|
|
132
|
+
const tempFilePath = path.join(directory, upload.id);
|
|
133
|
+
let data;
|
|
134
|
+
try {
|
|
135
|
+
data = await fs.readFile(tempFilePath);
|
|
136
|
+
} catch {
|
|
137
|
+
throw new APIError('Staged upload was not found.', 400);
|
|
138
|
+
}
|
|
139
|
+
if (data.length !== upload.filesize) {
|
|
140
|
+
await fs.rm(tempFilePath, {
|
|
141
|
+
force: true
|
|
142
|
+
});
|
|
143
|
+
throw new APIError('Staged upload is incomplete.', 400);
|
|
144
|
+
}
|
|
145
|
+
await fs.rm(tempFilePath, {
|
|
146
|
+
force: true
|
|
147
|
+
});
|
|
148
|
+
return {
|
|
149
|
+
name: upload.filename,
|
|
150
|
+
data,
|
|
151
|
+
mimetype: upload.mimeType,
|
|
152
|
+
size: data.length
|
|
153
|
+
};
|
|
154
|
+
};
|
|
155
|
+
/**
|
|
156
|
+
* Staged uploads hold a file temporarily until a document create or update uses it. The signed
|
|
157
|
+
* upload ID remembers which file and user the upload belongs to.
|
|
158
|
+
*/ const tokenExpiration = 60 * 60;
|
|
159
|
+
const getUser = (req)=>req.user ? `${req.user.collection}:${String(req.user.id)}` : null;
|
|
160
|
+
/** Returns the hidden folder where temporary uploads for this collection are stored. */ const getUploadDirectory = async (req, collectionSlug)=>{
|
|
161
|
+
const upload = req.payload.collections[collectionSlug]?.config.upload;
|
|
162
|
+
const directory = path.resolve(upload && !upload.disableLocalStorage ? upload.staticDir || collectionSlug : req.payload.config.upload.tempFileDir || os.tmpdir(), '.payload-staged-uploads');
|
|
163
|
+
await fs.mkdir(directory, {
|
|
164
|
+
recursive: true
|
|
165
|
+
});
|
|
166
|
+
return directory;
|
|
167
|
+
};
|
|
168
|
+
/** Removes temporary files older than the one-hour upload window. */ const removeExpiredUploads = async (req, collectionSlug)=>{
|
|
169
|
+
const directory = await getUploadDirectory(req, collectionSlug);
|
|
170
|
+
const expiresBefore = Date.now() - tokenExpiration * 1000;
|
|
171
|
+
for (const filename of (await fs.readdir(directory))){
|
|
172
|
+
const filePath = path.join(directory, filename);
|
|
173
|
+
const stats = await fs.stat(filePath).catch(()=>null);
|
|
174
|
+
if (stats && stats.mtimeMs < expiresBefore) {
|
|
175
|
+
await fs.rm(filePath, {
|
|
176
|
+
force: true
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
};
|
|
181
|
+
/** Verifies that an upload ID was signed by Payload, has not expired, and contains valid details. */ const verifyUploadID = async (req, uploadID)=>{
|
|
182
|
+
try {
|
|
183
|
+
if (typeof uploadID !== 'string') {
|
|
184
|
+
throw new Error();
|
|
185
|
+
}
|
|
186
|
+
const secret = new TextEncoder().encode(req.payload.secret);
|
|
187
|
+
const { payload } = await jwtVerify(uploadID, secret);
|
|
188
|
+
if (typeof payload.id !== 'string' || !/^[\da-f-]{36}$/i.test(payload.id) || typeof payload.collectionSlug !== 'string' || typeof payload.filename !== 'string' || !Number.isSafeInteger(payload.filesize) || payload.filesize < 0 || typeof payload.mimeType !== 'string' || payload.user !== null && typeof payload.user !== 'string') {
|
|
189
|
+
throw new Error();
|
|
190
|
+
}
|
|
191
|
+
return payload;
|
|
192
|
+
} catch {
|
|
193
|
+
throw new APIError('Invalid or expired staged upload.', 400);
|
|
194
|
+
}
|
|
195
|
+
};
|
|
196
|
+
|
|
197
|
+
//# sourceMappingURL=stagedUpload.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/uploads/stagedUpload.ts"],"sourcesContent":["import { jwtVerify } from 'jose'\nimport { randomUUID } from 'node:crypto'\nimport fs from 'node:fs/promises'\nimport os from 'node:os'\nimport path from 'node:path'\n\nimport type { PayloadHandler } from '../config/types.js'\nimport type { PayloadRequest } from '../types/index.js'\nimport type { File, UploadInstructions, UploadInstructionsRequest } from './types.js'\n\nimport { jwtSign } from '../auth/jwt.js'\nimport { APIError, Forbidden } from '../errors/index.js'\nimport { formatAdminURL } from '../utilities/formatAdminURL.js'\nimport { checkFileRestrictions } from './checkFileRestrictions.js'\n\n/**\n * Creates a signed, one-hour URL where the client can send the file bytes. The returned file value\n * is later passed to a document create or update request.\n */\nexport const generateStagedUploadInstructions = async ({\n collectionSlug,\n docPrefix,\n filename,\n filesize,\n mimeType,\n req,\n}: { req: PayloadRequest } & UploadInstructionsRequest): Promise<UploadInstructions> => {\n await removeExpiredUploads(req, collectionSlug)\n\n const { token: uploadId } = await jwtSign({\n fieldsToSign: {\n id: randomUUID(),\n collectionSlug,\n docPrefix,\n filename,\n filesize,\n mimeType,\n user: getUser(req),\n },\n secret: req.payload.secret,\n tokenExpiration,\n })\n\n return {\n type: 'http',\n file: {\n filename,\n mimeType,\n size: filesize,\n uploadReference: { uploadId },\n },\n request: {\n headers: {\n 'Content-Length': String(filesize),\n 'Content-Type': mimeType,\n },\n method: 'PUT',\n url: formatAdminURL({\n apiRoute: req.payload.config.routes.api,\n path: `/upload-instructions/${uploadId}`,\n serverURL: req.payload.config.serverURL,\n }),\n },\n }\n}\n\n/**\n * Saves the bytes sent to a signed upload URL. The file is written as a partial file first and only\n * becomes available when its size exactly matches the size in the upload ID.\n */\nexport const uploadStagedFile: PayloadHandler = async (req) => {\n const upload = await verifyUploadID(req, req.routeParams?.uploadId)\n const directory = await getUploadDirectory(req, upload.collectionSlug)\n const uploadPath = path.join(directory, upload.id)\n const temporaryPath = `${uploadPath}.${randomUUID()}.part`\n const file = await fs.open(temporaryPath, 'wx')\n let uploadedSize = 0\n\n try {\n try {\n const reader = req.body?.getReader()\n\n while (reader) {\n const { done, value } = await reader.read()\n\n if (done) {\n break\n }\n\n uploadedSize += value.byteLength\n if (uploadedSize > upload.filesize) {\n throw new APIError('Uploaded file is larger than expected.', 400)\n }\n\n let offset = 0\n while (offset < value.byteLength) {\n const { bytesWritten } = await file.write(value, offset)\n offset += bytesWritten\n }\n }\n\n if (uploadedSize !== upload.filesize) {\n throw new APIError('Uploaded file size does not match the expected size.', 400)\n }\n } finally {\n await file.close()\n }\n\n const collection = req.payload.collections[upload.collectionSlug]!.config\n await checkFileRestrictions({\n collection,\n file: {\n name: upload.filename,\n data: Buffer.alloc(0),\n mimetype: upload.mimeType,\n size: upload.filesize,\n tempFilePath: temporaryPath,\n },\n req,\n })\n\n await fs.rename(temporaryPath, uploadPath)\n } catch (error) {\n await fs.rm(temporaryPath, { force: true })\n throw error\n }\n\n return new Response(null, { status: 204 })\n}\n\n/** Removes a temporary upload that the client no longer needs. */\nexport const deleteStagedFile: PayloadHandler = async (req) => {\n const upload = await verifyUploadID(req, req.routeParams?.uploadId)\n const directory = await getUploadDirectory(req, upload.collectionSlug)\n\n await fs.rm(path.join(directory, upload.id), { force: true })\n\n return new Response(null, { status: 204 })\n}\n\n/**\n * Loads a completed staged file for a document request. Only the same user and collection can use\n * it, and the temporary file is deleted after it is read.\n */\nexport const getStagedFile = async ({\n collectionSlug,\n req,\n uploadReference,\n}: {\n collectionSlug: string\n req: PayloadRequest\n uploadReference: unknown\n}): Promise<File> => {\n if (\n !uploadReference ||\n typeof uploadReference !== 'object' ||\n Array.isArray(uploadReference) ||\n !('uploadId' in uploadReference) ||\n typeof uploadReference.uploadId !== 'string'\n ) {\n throw new APIError('Invalid staged upload.', 400)\n }\n\n const { uploadId } = uploadReference\n const upload = await verifyUploadID(req, uploadId)\n\n if (upload.collectionSlug !== collectionSlug || upload.user !== getUser(req)) {\n throw new Forbidden(req.t)\n }\n\n const directory = await getUploadDirectory(req, upload.collectionSlug)\n const tempFilePath = path.join(directory, upload.id)\n let data: Buffer\n\n try {\n data = await fs.readFile(tempFilePath)\n } catch {\n throw new APIError('Staged upload was not found.', 400)\n }\n\n if (data.length !== upload.filesize) {\n await fs.rm(tempFilePath, { force: true })\n throw new APIError('Staged upload is incomplete.', 400)\n }\n\n await fs.rm(tempFilePath, { force: true })\n\n return {\n name: upload.filename,\n data,\n mimetype: upload.mimeType,\n size: data.length,\n }\n}\n\n/**\n * Staged uploads hold a file temporarily until a document create or update uses it. The signed\n * upload ID remembers which file and user the upload belongs to.\n */\nconst tokenExpiration = 60 * 60\n\n/** The file details stored inside the signed upload ID. */\ntype StagedUploadToken = {\n id: string\n user: null | string\n} & UploadInstructionsRequest\n\nconst getUser = (req: PayloadRequest) =>\n req.user ? `${req.user.collection}:${String(req.user.id)}` : null\n\n/** Returns the hidden folder where temporary uploads for this collection are stored. */\nconst getUploadDirectory = async (req: PayloadRequest, collectionSlug: string) => {\n const upload = req.payload.collections[collectionSlug]?.config.upload\n const directory = path.resolve(\n upload && !upload.disableLocalStorage\n ? upload.staticDir || collectionSlug\n : req.payload.config.upload.tempFileDir || os.tmpdir(),\n '.payload-staged-uploads',\n )\n\n await fs.mkdir(directory, { recursive: true })\n\n return directory\n}\n\n/** Removes temporary files older than the one-hour upload window. */\nconst removeExpiredUploads = async (req: PayloadRequest, collectionSlug: string) => {\n const directory = await getUploadDirectory(req, collectionSlug)\n const expiresBefore = Date.now() - tokenExpiration * 1000\n\n for (const filename of await fs.readdir(directory)) {\n const filePath = path.join(directory, filename)\n const stats = await fs.stat(filePath).catch(() => null)\n\n if (stats && stats.mtimeMs < expiresBefore) {\n await fs.rm(filePath, { force: true })\n }\n }\n}\n\n/** Verifies that an upload ID was signed by Payload, has not expired, and contains valid details. */\nconst verifyUploadID = async (\n req: PayloadRequest,\n uploadID: unknown,\n): Promise<StagedUploadToken> => {\n try {\n if (typeof uploadID !== 'string') {\n throw new Error()\n }\n\n const secret = new TextEncoder().encode(req.payload.secret)\n const { payload } = await jwtVerify<StagedUploadToken>(uploadID, secret)\n\n if (\n typeof payload.id !== 'string' ||\n !/^[\\da-f-]{36}$/i.test(payload.id) ||\n typeof payload.collectionSlug !== 'string' ||\n typeof payload.filename !== 'string' ||\n !Number.isSafeInteger(payload.filesize) ||\n payload.filesize < 0 ||\n typeof payload.mimeType !== 'string' ||\n (payload.user !== null && typeof payload.user !== 'string')\n ) {\n throw new Error()\n }\n\n return payload as StagedUploadToken\n } catch {\n throw new APIError('Invalid or expired staged upload.', 400)\n }\n}\n"],"names":["jwtVerify","randomUUID","fs","os","path","jwtSign","APIError","Forbidden","formatAdminURL","checkFileRestrictions","generateStagedUploadInstructions","collectionSlug","docPrefix","filename","filesize","mimeType","req","removeExpiredUploads","token","uploadId","fieldsToSign","id","user","getUser","secret","payload","tokenExpiration","type","file","size","uploadReference","request","headers","String","method","url","apiRoute","config","routes","api","serverURL","uploadStagedFile","upload","verifyUploadID","routeParams","directory","getUploadDirectory","uploadPath","join","temporaryPath","open","uploadedSize","reader","body","getReader","done","value","read","byteLength","offset","bytesWritten","write","close","collection","collections","name","data","Buffer","alloc","mimetype","tempFilePath","rename","error","rm","force","Response","status","deleteStagedFile","getStagedFile","Array","isArray","t","readFile","length","resolve","disableLocalStorage","staticDir","tempFileDir","tmpdir","mkdir","recursive","expiresBefore","Date","now","readdir","filePath","stats","stat","catch","mtimeMs","uploadID","Error","TextEncoder","encode","test","Number","isSafeInteger"],"mappings":"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"}
|
package/dist/uploads/types.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { ResizeOptions, Sharp, SharpOptions } from 'sharp';
|
|
2
2
|
import type { CollectionConfig, TypeWithID } from '../collections/config/types.js';
|
|
3
3
|
import type { PayloadComponent } from '../config/types.js';
|
|
4
|
+
import type { UploadCollectionSlug } from '../index.js';
|
|
4
5
|
import type { PayloadRequest } from '../types/index.js';
|
|
5
6
|
import type { WithMetadata } from './optionallyAppendMetadata.js';
|
|
6
7
|
export type FileSize = {
|
|
@@ -234,10 +235,10 @@ export type UploadConfig = {
|
|
|
234
235
|
doc: TypeWithID;
|
|
235
236
|
headers?: Headers;
|
|
236
237
|
params: {
|
|
237
|
-
clientUploadContext?: unknown;
|
|
238
238
|
collection: string;
|
|
239
239
|
filename: string;
|
|
240
240
|
prefix?: string;
|
|
241
|
+
uploadReference?: unknown;
|
|
241
242
|
};
|
|
242
243
|
}) => Promise<Response> | Promise<void> | Response | void)[];
|
|
243
244
|
/**
|
|
@@ -289,6 +290,11 @@ export type UploadConfig = {
|
|
|
289
290
|
*/
|
|
290
291
|
staticDir?: string;
|
|
291
292
|
trimOptions?: ImageUploadTrimOptions;
|
|
293
|
+
/**
|
|
294
|
+
* Adapter-provided upload instructions.
|
|
295
|
+
* @internal
|
|
296
|
+
*/
|
|
297
|
+
uploadInstructions?: UploadInstructionsCapability;
|
|
292
298
|
/**
|
|
293
299
|
* Optionally append metadata to the image during processing.
|
|
294
300
|
*
|
|
@@ -301,7 +307,53 @@ export type UploadConfig = {
|
|
|
301
307
|
*/
|
|
302
308
|
withMetadata?: WithMetadata;
|
|
303
309
|
};
|
|
310
|
+
export type UploadInstructionsAccess = (args: {
|
|
311
|
+
collectionSlug: UploadCollectionSlug;
|
|
312
|
+
req: PayloadRequest;
|
|
313
|
+
}) => boolean | Promise<boolean>;
|
|
314
|
+
export type UploadInstructionsRequest = {
|
|
315
|
+
collectionSlug: UploadCollectionSlug;
|
|
316
|
+
docPrefix?: string;
|
|
317
|
+
filename: string;
|
|
318
|
+
filesize: number;
|
|
319
|
+
mimeType: string;
|
|
320
|
+
};
|
|
321
|
+
export type UploadInstructions = {
|
|
322
|
+
file: {
|
|
323
|
+
collectionSlug?: UploadCollectionSlug;
|
|
324
|
+
filename: string;
|
|
325
|
+
mimeType: string;
|
|
326
|
+
size: number;
|
|
327
|
+
uploadReference: Record<string, unknown>;
|
|
328
|
+
};
|
|
329
|
+
} & ({
|
|
330
|
+
data?: unknown;
|
|
331
|
+
name: string;
|
|
332
|
+
type: 'dispatch';
|
|
333
|
+
} | {
|
|
334
|
+
request: {
|
|
335
|
+
headers?: Record<string, string>;
|
|
336
|
+
method: 'POST' | 'PUT';
|
|
337
|
+
url: string;
|
|
338
|
+
};
|
|
339
|
+
type: 'http';
|
|
340
|
+
});
|
|
341
|
+
export type GenerateUploadInstructions = (args: {
|
|
342
|
+
overrideAccess?: boolean;
|
|
343
|
+
req: PayloadRequest;
|
|
344
|
+
} & UploadInstructionsRequest) => Promise<UploadInstructions> | UploadInstructions;
|
|
345
|
+
export type UploadInstructionsCapability = {
|
|
346
|
+
/** Generates upload instructions. The generator or supporting endpoint must check access. */
|
|
347
|
+
generate: GenerateUploadInstructions;
|
|
348
|
+
/**
|
|
349
|
+
* Whether the Admin panel should use these instructions before saving a document.
|
|
350
|
+
* This can still be useful when upload chunks pass through Payload.
|
|
351
|
+
*/
|
|
352
|
+
useInAdmin: boolean;
|
|
353
|
+
};
|
|
304
354
|
export type checkFileRestrictionsParams = {
|
|
355
|
+
/** Set to false when the file bytes have not been uploaded yet. */
|
|
356
|
+
checkFileContents?: boolean;
|
|
305
357
|
collection: CollectionConfig;
|
|
306
358
|
file: File;
|
|
307
359
|
req: PayloadRequest;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/uploads/types.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/uploads/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/uploads/types.ts"],"sourcesContent":["import type { ResizeOptions, Sharp, SharpOptions } from 'sharp'\n\nimport type { CollectionConfig, TypeWithID } from '../collections/config/types.js'\nimport type { PayloadComponent } from '../config/types.js'\nimport type { PayloadRequest } from '../types/index.js'\nimport type { WithMetadata } from './optionallyAppendMetadata.js'\n\nexport type FileSize = {\n filename: null | string\n filesize: null | number\n height: null | number\n mimeType: null | string\n url: null | string\n width: null | number\n}\n\nexport type FileSizes = {\n [size: string]: FileSize\n}\n\nexport type FileData = {\n filename: string\n filesize: number\n focalX?: number\n focalY?: number\n height: number\n mimeType: string\n sizes: FileSizes\n tempFilePath?: string\n url?: string\n width: number\n}\n\nexport type ProbedImageSize = {\n height: number\n width: number\n}\n\n/**\n * Params sent to the sharp `toFormat()` function\n * @link https://sharp.pixelplumbing.com/api-output#toformat\n */\nexport type ImageUploadFormatOptions = {\n format: Parameters<Sharp['toFormat']>[0]\n options?: Parameters<Sharp['toFormat']>[1]\n}\n\n/**\n * Params sent to the sharp trim() function\n * @link https://sharp.pixelplumbing.com/api-resize#trim\n */\nexport type ImageUploadTrimOptions = Parameters<Sharp['trim']>[0]\n\nexport type GenerateImageName = (args: {\n extension: string\n height: number\n originalName: string\n sizeName: string\n width: number\n}) => string\n\nexport type ImageSize = {\n /**\n * Admin UI options that control how this image size appears in list views.\n */\n admin?: {\n /**\n * Controls visibility of this image size in the collection list view.\n * Defaults to hiding the image size from columns, filters, and group-by to reduce noise.\n *\n * - `column` — whether to hide this size from selectable list columns. @default false\n * - `filter` — whether to hide this size from filter options. @default false\n * - `groupBy` — whether to hide this size from group-by options. @default false\n */\n disabled?: {\n column?: boolean\n filter?: boolean\n groupBy?: boolean\n }\n }\n /**\n * @deprecated prefer position\n */\n crop?: string // comes from sharp package\n formatOptions?: ImageUploadFormatOptions\n /**\n * Generate a custom name for the file of this image size.\n */\n generateImageName?: GenerateImageName\n name: string\n trimOptions?: ImageUploadTrimOptions\n /**\n * When an uploaded image is smaller than the defined image size, we have 3 options:\n *\n * `undefined | false | true`\n *\n * 1. `undefined` [default]: uploading images with smaller width AND height than the image size will return null\n * 2. `false`: always enlarge images to the image size\n * 3. `true`: if the image is smaller than the image size, return the original image\n */\n withoutEnlargement?: ResizeOptions['withoutEnlargement']\n} & Omit<ResizeOptions, 'withoutEnlargement'>\n\nexport type GetAdminThumbnail = (args: { doc: Record<string, unknown> }) => false | null | string\n\nexport type AllowList = Array<{\n hostname: string\n pathname?: string\n port?: string\n protocol?: 'http' | 'https'\n search?: string\n}>\n\nexport type FileAllowList = Array<{\n extensions: string[]\n mimeType: string\n}>\n\nexport type UploadFilePreviewClientProps = {\n filename: string\n filesize: number\n /** Resolved URL of the file (data.url). */\n fileSrc: string\n height?: number\n mimeType: string\n width?: number\n}\n\ntype UploadFilePreviewMap = {\n [mimeTypePattern: string]: PayloadComponent\n}\n\ntype Admin = {\n components?: {\n /**\n * The Controls component to extend the upload controls in the admin panel.\n */\n controls?: PayloadComponent[]\n /**\n * A custom component to render in place of the default Thumbnail in the upload side panel.\n *\n * Can be a single PayloadComponent (renders for all MIME types) or a Record keyed by\n * MIME type patterns. Pattern resolution priority: exact match → category wildcard\n * (e.g. `video/*`) → universal fallback (`*`). Falls back to the default Thumbnail\n * when nothing matches.\n */\n filePreview?: PayloadComponent | UploadFilePreviewMap\n }\n}\n\nexport type UploadConfig = {\n /**\n * The adapter name to use for uploads. Used for storage adapter telemetry.\n * @default undefined\n */\n adapter?: string\n /**\n * The admin configuration for the upload field.\n */\n admin?: Admin\n /**\n * Represents an admin thumbnail, which can be either a React component or a string.\n * - If a string, it should be one of the image size names.\n * - A function that generates a fully qualified URL for the thumbnail, receives the doc as the only argument.\n **/\n adminThumbnail?: GetAdminThumbnail | string\n /**\n * Allow restricted file types known to be problematic.\n * - If set to `true`, it will allow all file types.\n * - If set to `false`, it will not allow file types and extensions known to be problematic.\n * - This setting is overriden by the `mimeTypes` option.\n * @default false\n */\n allowRestrictedFileTypes?: boolean\n /**\n * Enables bulk upload of files from the list view.\n * @default true\n */\n bulkUpload?: boolean\n /**\n * Appends a cache tag to the image URL when fetching the thumbnail in the admin panel. It may be desirable to disable this when hosting via CDNs with strict parameters.\n *\n * @default true\n */\n cacheTags?: boolean\n /**\n * Sharp constructor options to be passed to the uploaded file.\n * @link https://sharp.pixelplumbing.com/api-constructor/#sharp\n */\n constructorOptions?: SharpOptions\n /**\n * Enables cropping of images.\n * @default true\n */\n crop?: boolean\n /**\n * Disable the ability to save files to disk.\n * @default false\n */\n disableLocalStorage?: boolean\n /**\n * Enable displaying preview of the uploaded file in Upload fields related to this Collection.\n * Can be locally overridden by `displayPreview` option in Upload field.\n * @default false\n */\n displayPreview?: boolean\n /**\n *\n * Accepts existing headers and returns the headers after filtering or modifying.\n * If using this option, you should handle the removal of any sensitive cookies\n * (like payload-prefixed cookies) to prevent leaking session information to external\n * services. By default, Payload automatically filters out payload-prefixed cookies\n * when this option is NOT defined.\n *\n * Useful for adding custom headers to fetch from external providers.\n * @default undefined\n */\n externalFileHeaderFilter?: (headers: Record<string, string>) => Record<string, string>\n /**\n * Field slugs to use for a compound index instead of the default filename index.\n */\n filenameCompoundIndex?: string[]\n /**\n * Require files to be uploaded when creating a document.\n * @default true\n */\n filesRequiredOnCreate?: boolean\n /**\n * Enables focal point positioning for image manipulation.\n * @default true\n */\n focalPoint?: boolean\n /**\n * Format options for the uploaded file. Formatting image sizes needs to be done within each formatOptions individually.\n */\n formatOptions?: ImageUploadFormatOptions\n /**\n * Custom handlers to run when a file is fetched.\n *\n * - If a handler returns a Response, the response will be sent to the client and no further handlers will be run.\n * - If a handler returns null, the next handler will be run.\n * - If no handlers return a response the file will be returned by default.\n *\n * @link https://sharp.pixelplumbing.com/api-output/#toformat\n * @default undefined\n */\n handlers?: ((\n req: PayloadRequest,\n args: {\n doc: TypeWithID\n headers?: Headers\n params: {\n clientUploadContext?: unknown\n collection: string\n filename: string\n prefix?: string\n }\n },\n ) => Promise<Response> | Promise<void> | Response | void)[]\n /**\n * Set to `true` to prevent the admin UI from showing file inputs during document creation, useful for programmatic file generation.\n */\n hideFileInputOnCreate?: boolean\n /**\n * Set to `true` to prevent the admin UI having a way to remove an existing file while editing.\n */\n hideRemoveFile?: boolean\n imageSizes?: ImageSize[]\n /**\n * Restrict mimeTypes in the file picker. Array of valid mime types or mimetype wildcards\n * @example ['image/*', 'application/pdf']\n * @default undefined\n */\n mimeTypes?: string[]\n /**\n * Ability to modify the response headers fetching a file.\n * @default undefined\n */\n modifyResponseHeaders?: ({ headers }: { headers: Headers }) => Headers | void\n /**\n * Controls the behavior of pasting/uploading files from URLs.\n * If set to `false`, fetching from remote URLs is disabled.\n * If an `allowList` is provided, server-side fetching will be enabled for specified URLs.\n *\n * @default true (client-side fetching enabled)\n */\n pasteURL?:\n | {\n allowList: AllowList\n }\n | false\n /**\n * Sharp resize options for the original image.\n * @link https://sharp.pixelplumbing.com/api-resize#resize\n * @default undefined\n */\n resizeOptions?: ResizeOptions\n /**\n * Skip safe fetch when using server-side fetching for external files from these URLs.\n * @default false\n */\n skipSafeFetch?: AllowList | boolean\n /**\n * The directory to serve static files from. Defaults to collection slug.\n * @default undefined\n */\n staticDir?: string\n trimOptions?: ImageUploadTrimOptions\n /**\n * Optionally append metadata to the image during processing.\n *\n * Can be a boolean or a function.\n *\n * If true, metadata will be appended to the image.\n * If false, no metadata will be appended.\n * If a function, it will receive an object containing the metadata and should return a boolean indicating whether to append the metadata.\n * @default false\n */\n withMetadata?: WithMetadata\n}\nexport type checkFileRestrictionsParams = {\n collection: CollectionConfig\n file: File\n req: PayloadRequest\n}\n\nexport type SanitizedUploadConfig = {\n staticDir: UploadConfig['staticDir']\n} & UploadConfig\n\nexport type File = {\n /**\n * The buffer of the file.\n */\n data: Buffer\n /**\n * The mimetype of the file.\n */\n mimetype: string\n /**\n * The name of the file.\n */\n name: string\n /**\n * The size of the file in bytes.\n */\n size: number\n /**\n * Path to the temp file on disk when useTempFiles is enabled. In this case file.data will be an empty buffer.\n */\n tempFilePath?: string\n}\n\nexport type FileToSave = {\n /**\n * The buffer of the file.\n */\n buffer: Buffer\n /**\n * The path to save the file.\n */\n path: string\n}\n\ntype Crop = {\n height: number\n unit: '%' | 'px'\n width: number\n x: number\n y: number\n}\n\nexport type FocalPoint = {\n x: number\n y: number\n}\n\nexport type UploadEdits = {\n crop?: Crop\n focalPoint?: FocalPoint\n heightInPixels?: number\n widthInPixels?: number\n}\n"],"names":[],"mappings":"AAyXA,WAKC"}
|
|
1
|
+
{"version":3,"sources":["../../src/uploads/types.ts"],"sourcesContent":["import type { ResizeOptions, Sharp, SharpOptions } from 'sharp'\n\nimport type { CollectionConfig, TypeWithID } from '../collections/config/types.js'\nimport type { PayloadComponent } from '../config/types.js'\nimport type { UploadCollectionSlug } from '../index.js'\nimport type { PayloadRequest } from '../types/index.js'\nimport type { WithMetadata } from './optionallyAppendMetadata.js'\n\nexport type FileSize = {\n filename: null | string\n filesize: null | number\n height: null | number\n mimeType: null | string\n url: null | string\n width: null | number\n}\n\nexport type FileSizes = {\n [size: string]: FileSize\n}\n\nexport type FileData = {\n filename: string\n filesize: number\n focalX?: number\n focalY?: number\n height: number\n mimeType: string\n sizes: FileSizes\n tempFilePath?: string\n url?: string\n width: number\n}\n\nexport type ProbedImageSize = {\n height: number\n width: number\n}\n\n/**\n * Params sent to the sharp `toFormat()` function\n * @link https://sharp.pixelplumbing.com/api-output#toformat\n */\nexport type ImageUploadFormatOptions = {\n format: Parameters<Sharp['toFormat']>[0]\n options?: Parameters<Sharp['toFormat']>[1]\n}\n\n/**\n * Params sent to the sharp trim() function\n * @link https://sharp.pixelplumbing.com/api-resize#trim\n */\nexport type ImageUploadTrimOptions = Parameters<Sharp['trim']>[0]\n\nexport type GenerateImageName = (args: {\n extension: string\n height: number\n originalName: string\n sizeName: string\n width: number\n}) => string\n\nexport type ImageSize = {\n /**\n * Admin UI options that control how this image size appears in list views.\n */\n admin?: {\n /**\n * Controls visibility of this image size in the collection list view.\n * Defaults to hiding the image size from columns, filters, and group-by to reduce noise.\n *\n * - `column` — whether to hide this size from selectable list columns. @default false\n * - `filter` — whether to hide this size from filter options. @default false\n * - `groupBy` — whether to hide this size from group-by options. @default false\n */\n disabled?: {\n column?: boolean\n filter?: boolean\n groupBy?: boolean\n }\n }\n /**\n * @deprecated prefer position\n */\n crop?: string // comes from sharp package\n formatOptions?: ImageUploadFormatOptions\n /**\n * Generate a custom name for the file of this image size.\n */\n generateImageName?: GenerateImageName\n name: string\n trimOptions?: ImageUploadTrimOptions\n /**\n * When an uploaded image is smaller than the defined image size, we have 3 options:\n *\n * `undefined | false | true`\n *\n * 1. `undefined` [default]: uploading images with smaller width AND height than the image size will return null\n * 2. `false`: always enlarge images to the image size\n * 3. `true`: if the image is smaller than the image size, return the original image\n */\n withoutEnlargement?: ResizeOptions['withoutEnlargement']\n} & Omit<ResizeOptions, 'withoutEnlargement'>\n\nexport type GetAdminThumbnail = (args: { doc: Record<string, unknown> }) => false | null | string\n\nexport type AllowList = Array<{\n hostname: string\n pathname?: string\n port?: string\n protocol?: 'http' | 'https'\n search?: string\n}>\n\nexport type FileAllowList = Array<{\n extensions: string[]\n mimeType: string\n}>\n\nexport type UploadFilePreviewClientProps = {\n filename: string\n filesize: number\n /** Resolved URL of the file (data.url). */\n fileSrc: string\n height?: number\n mimeType: string\n width?: number\n}\n\ntype UploadFilePreviewMap = {\n [mimeTypePattern: string]: PayloadComponent\n}\n\ntype Admin = {\n components?: {\n /**\n * The Controls component to extend the upload controls in the admin panel.\n */\n controls?: PayloadComponent[]\n /**\n * A custom component to render in place of the default Thumbnail in the upload side panel.\n *\n * Can be a single PayloadComponent (renders for all MIME types) or a Record keyed by\n * MIME type patterns. Pattern resolution priority: exact match → category wildcard\n * (e.g. `video/*`) → universal fallback (`*`). Falls back to the default Thumbnail\n * when nothing matches.\n */\n filePreview?: PayloadComponent | UploadFilePreviewMap\n }\n}\n\nexport type UploadConfig = {\n /**\n * The adapter name to use for uploads. Used for storage adapter telemetry.\n * @default undefined\n */\n adapter?: string\n /**\n * The admin configuration for the upload field.\n */\n admin?: Admin\n /**\n * Represents an admin thumbnail, which can be either a React component or a string.\n * - If a string, it should be one of the image size names.\n * - A function that generates a fully qualified URL for the thumbnail, receives the doc as the only argument.\n **/\n adminThumbnail?: GetAdminThumbnail | string\n /**\n * Allow restricted file types known to be problematic.\n * - If set to `true`, it will allow all file types.\n * - If set to `false`, it will not allow file types and extensions known to be problematic.\n * - This setting is overriden by the `mimeTypes` option.\n * @default false\n */\n allowRestrictedFileTypes?: boolean\n /**\n * Enables bulk upload of files from the list view.\n * @default true\n */\n bulkUpload?: boolean\n /**\n * Appends a cache tag to the image URL when fetching the thumbnail in the admin panel. It may be desirable to disable this when hosting via CDNs with strict parameters.\n *\n * @default true\n */\n cacheTags?: boolean\n /**\n * Sharp constructor options to be passed to the uploaded file.\n * @link https://sharp.pixelplumbing.com/api-constructor/#sharp\n */\n constructorOptions?: SharpOptions\n /**\n * Enables cropping of images.\n * @default true\n */\n crop?: boolean\n /**\n * Disable the ability to save files to disk.\n * @default false\n */\n disableLocalStorage?: boolean\n /**\n * Enable displaying preview of the uploaded file in Upload fields related to this Collection.\n * Can be locally overridden by `displayPreview` option in Upload field.\n * @default false\n */\n displayPreview?: boolean\n /**\n *\n * Accepts existing headers and returns the headers after filtering or modifying.\n * If using this option, you should handle the removal of any sensitive cookies\n * (like payload-prefixed cookies) to prevent leaking session information to external\n * services. By default, Payload automatically filters out payload-prefixed cookies\n * when this option is NOT defined.\n *\n * Useful for adding custom headers to fetch from external providers.\n * @default undefined\n */\n externalFileHeaderFilter?: (headers: Record<string, string>) => Record<string, string>\n /**\n * Field slugs to use for a compound index instead of the default filename index.\n */\n filenameCompoundIndex?: string[]\n /**\n * Require files to be uploaded when creating a document.\n * @default true\n */\n filesRequiredOnCreate?: boolean\n /**\n * Enables focal point positioning for image manipulation.\n * @default true\n */\n focalPoint?: boolean\n /**\n * Format options for the uploaded file. Formatting image sizes needs to be done within each formatOptions individually.\n */\n formatOptions?: ImageUploadFormatOptions\n /**\n * Custom handlers to run when a file is fetched.\n *\n * - If a handler returns a Response, the response will be sent to the client and no further handlers will be run.\n * - If a handler returns null, the next handler will be run.\n * - If no handlers return a response the file will be returned by default.\n *\n * @link https://sharp.pixelplumbing.com/api-output/#toformat\n * @default undefined\n */\n handlers?: ((\n req: PayloadRequest,\n args: {\n doc: TypeWithID\n headers?: Headers\n params: {\n collection: string\n filename: string\n prefix?: string\n uploadReference?: unknown\n }\n },\n ) => Promise<Response> | Promise<void> | Response | void)[]\n /**\n * Set to `true` to prevent the admin UI from showing file inputs during document creation, useful for programmatic file generation.\n */\n hideFileInputOnCreate?: boolean\n /**\n * Set to `true` to prevent the admin UI having a way to remove an existing file while editing.\n */\n hideRemoveFile?: boolean\n imageSizes?: ImageSize[]\n /**\n * Restrict mimeTypes in the file picker. Array of valid mime types or mimetype wildcards\n * @example ['image/*', 'application/pdf']\n * @default undefined\n */\n mimeTypes?: string[]\n /**\n * Ability to modify the response headers fetching a file.\n * @default undefined\n */\n modifyResponseHeaders?: ({ headers }: { headers: Headers }) => Headers | void\n /**\n * Controls the behavior of pasting/uploading files from URLs.\n * If set to `false`, fetching from remote URLs is disabled.\n * If an `allowList` is provided, server-side fetching will be enabled for specified URLs.\n *\n * @default true (client-side fetching enabled)\n */\n pasteURL?:\n | {\n allowList: AllowList\n }\n | false\n /**\n * Sharp resize options for the original image.\n * @link https://sharp.pixelplumbing.com/api-resize#resize\n * @default undefined\n */\n resizeOptions?: ResizeOptions\n /**\n * Skip safe fetch when using server-side fetching for external files from these URLs.\n * @default false\n */\n skipSafeFetch?: AllowList | boolean\n /**\n * The directory to serve static files from. Defaults to collection slug.\n * @default undefined\n */\n staticDir?: string\n trimOptions?: ImageUploadTrimOptions\n /**\n * Adapter-provided upload instructions.\n * @internal\n */\n uploadInstructions?: UploadInstructionsCapability\n /**\n * Optionally append metadata to the image during processing.\n *\n * Can be a boolean or a function.\n *\n * If true, metadata will be appended to the image.\n * If false, no metadata will be appended.\n * If a function, it will receive an object containing the metadata and should return a boolean indicating whether to append the metadata.\n * @default false\n */\n withMetadata?: WithMetadata\n}\n\nexport type UploadInstructionsAccess = (args: {\n collectionSlug: UploadCollectionSlug\n req: PayloadRequest\n}) => boolean | Promise<boolean>\n\nexport type UploadInstructionsRequest = {\n collectionSlug: UploadCollectionSlug\n docPrefix?: string\n filename: string\n filesize: number\n mimeType: string\n}\n\nexport type UploadInstructions = {\n file: {\n collectionSlug?: UploadCollectionSlug\n filename: string\n mimeType: string\n size: number\n uploadReference: Record<string, unknown>\n }\n} & (\n | {\n data?: unknown\n name: string\n type: 'dispatch'\n }\n | {\n request: {\n headers?: Record<string, string>\n method: 'POST' | 'PUT'\n url: string\n }\n type: 'http'\n }\n)\n\nexport type GenerateUploadInstructions = (\n args: { overrideAccess?: boolean; req: PayloadRequest } & UploadInstructionsRequest,\n) => Promise<UploadInstructions> | UploadInstructions\n\nexport type UploadInstructionsCapability = {\n /** Generates upload instructions. The generator or supporting endpoint must check access. */\n generate: GenerateUploadInstructions\n /**\n * Whether the Admin panel should use these instructions before saving a document.\n * This can still be useful when upload chunks pass through Payload.\n */\n useInAdmin: boolean\n}\nexport type checkFileRestrictionsParams = {\n /** Set to false when the file bytes have not been uploaded yet. */\n checkFileContents?: boolean\n collection: CollectionConfig\n file: File\n req: PayloadRequest\n}\n\nexport type SanitizedUploadConfig = {\n staticDir: UploadConfig['staticDir']\n} & UploadConfig\n\nexport type File = {\n /**\n * The buffer of the file.\n */\n data: Buffer\n /**\n * The mimetype of the file.\n */\n mimetype: string\n /**\n * The name of the file.\n */\n name: string\n /**\n * The size of the file in bytes.\n */\n size: number\n /**\n * Path to the temp file on disk when useTempFiles is enabled. In this case file.data will be an empty buffer.\n */\n tempFilePath?: string\n}\n\nexport type FileToSave = {\n /**\n * The buffer of the file.\n */\n buffer: Buffer\n /**\n * The path to save the file.\n */\n path: string\n}\n\ntype Crop = {\n height: number\n unit: '%' | 'px'\n width: number\n x: number\n y: number\n}\n\nexport type FocalPoint = {\n x: number\n y: number\n}\n\nexport type UploadEdits = {\n crop?: Crop\n focalPoint?: FocalPoint\n heightInPixels?: number\n widthInPixels?: number\n}\n"],"names":[],"mappings":"AAobA,WAKC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"addDataAndFileToRequest.d.ts","sourceRoot":"","sources":["../../src/utilities/addDataAndFileToRequest.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA;
|
|
1
|
+
{"version":3,"file":"addDataAndFileToRequest.d.ts","sourceRoot":"","sources":["../../src/utilities/addDataAndFileToRequest.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA;AAOvD,KAAK,uBAAuB,GAAG,CAAC,GAAG,EAAE,cAAc,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;AAErE;;GAEG;AACH,eAAO,MAAM,uBAAuB,EAAE,uBA4ErC,CAAA"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { APIError } from '../errors/APIError.js';
|
|
2
2
|
import { processMultipartFormdata } from '../uploads/fetchAPI-multipart/index.js';
|
|
3
|
+
import { getFileFromUploadInstructions } from '../uploads/getFileFromUploadInstructions.js';
|
|
3
4
|
/**
|
|
4
5
|
* Mutates the Request, appending 'data' and 'file' if found
|
|
5
6
|
*/ export const addDataAndFileToRequest = async (req)=>{
|
|
@@ -50,56 +51,22 @@ import { processMultipartFormdata } from '../uploads/fetchAPI-multipart/index.js
|
|
|
50
51
|
req.data = JSON.parse(fields._payload);
|
|
51
52
|
}
|
|
52
53
|
if (!req.file && fields?.file && typeof fields?.file === 'string') {
|
|
53
|
-
let
|
|
54
|
+
let uploadedFile;
|
|
54
55
|
try {
|
|
55
|
-
;
|
|
56
|
-
({ clientUploadContext, collectionSlug, filename, mimeType, size } = JSON.parse(fields.file));
|
|
56
|
+
uploadedFile = JSON.parse(fields.file);
|
|
57
57
|
} catch {
|
|
58
58
|
throw new APIError('A file name is required.', 400);
|
|
59
59
|
}
|
|
60
|
-
const
|
|
61
|
-
|
|
62
|
-
|
|
60
|
+
const collectionSlug = typeof req.routeParams?.collection === 'string' ? req.routeParams.collection : uploadedFile.collectionSlug;
|
|
61
|
+
const uploadConfig = collectionSlug ? req.payload.collections[collectionSlug]?.config.upload : undefined;
|
|
62
|
+
if (!collectionSlug || !uploadConfig) {
|
|
63
|
+
throw new APIError('Invalid upload collection.', 400);
|
|
63
64
|
}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
doc: null,
|
|
70
|
-
params: {
|
|
71
|
-
clientUploadContext,
|
|
72
|
-
collection: collectionSlug,
|
|
73
|
-
filename
|
|
74
|
-
}
|
|
75
|
-
});
|
|
76
|
-
if (result) {
|
|
77
|
-
response = result;
|
|
78
|
-
}
|
|
79
|
-
// If we couldn't get the file from that handler, save the error and try other.
|
|
80
|
-
} catch (err) {
|
|
81
|
-
error = err;
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
if (!response) {
|
|
85
|
-
if (error) {
|
|
86
|
-
payload.logger.error(error);
|
|
87
|
-
}
|
|
88
|
-
throw new APIError('Expected response from the upload handler.');
|
|
89
|
-
}
|
|
90
|
-
if (response.status >= 300 && response.status < 400) {
|
|
91
|
-
const redirectUrl = response.headers.get('Location');
|
|
92
|
-
if (redirectUrl) {
|
|
93
|
-
response = await fetch(redirectUrl);
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
req.file = {
|
|
97
|
-
name: filename,
|
|
98
|
-
clientUploadContext,
|
|
99
|
-
data: Buffer.from(await response.arrayBuffer()),
|
|
100
|
-
mimetype: response.headers.get('Content-Type') || mimeType,
|
|
101
|
-
size
|
|
102
|
-
};
|
|
65
|
+
req.file = await getFileFromUploadInstructions({
|
|
66
|
+
collectionSlug,
|
|
67
|
+
file: uploadedFile,
|
|
68
|
+
req
|
|
69
|
+
});
|
|
103
70
|
}
|
|
104
71
|
}
|
|
105
72
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/utilities/addDataAndFileToRequest.ts"],"sourcesContent":["import type { PayloadRequest } from '../types/index.js'\n\nimport { APIError } from '../errors/APIError.js'\nimport { processMultipartFormdata } from '../uploads/fetchAPI-multipart/index.js'\n\ntype AddDataAndFileToRequest = (req: PayloadRequest) => Promise<void>\n\n/**\n * Mutates the Request, appending 'data' and 'file' if found\n */\nexport const addDataAndFileToRequest: AddDataAndFileToRequest = async (req) => {\n const { body, headers, method, payload } = req\n\n if (method && ['PATCH', 'POST', 'PUT'].includes(method.toUpperCase()) && body) {\n const [contentType] = (headers.get('Content-Type') || '').split(';', 1)\n const bodyByteSize = parseInt(req.headers.get('Content-Length') || '0', 10)\n const hasBodyStream = req.body !== null\n\n if (contentType === 'application/json') {\n try {\n const text = await req.text?.()\n const data = text ? JSON.parse(text) : {}\n req.data = data\n // @ts-expect-error attach json method to request\n req.json = () => Promise.resolve(data)\n } catch (error) {\n if (error instanceof SyntaxError) {\n throw new APIError('Invalid JSON', 400)\n }\n req.payload.logger.error(error)\n throw error\n }\n } else if ((bodyByteSize || hasBodyStream) && contentType?.includes('multipart/')) {\n const { error, fields, files } = await processMultipartFormdata({\n options: {\n ...(payload.config.bodyParser || {}),\n ...(payload.config.upload || {}),\n },\n request: req as Request,\n })\n\n if (error) {\n throw new APIError(error.message)\n }\n\n // Set all files on req.files for access by hooks\n if (files) {\n req.files = files\n // Backwards compatibility: set req.file for standard upload collections\n // Guard: if multiple files share the field name \"file\", files.file is an array — skip\n if (files.file && !Array.isArray(files.file)) {\n req.file = files.file\n }\n }\n\n if (fields?._payload && typeof fields._payload === 'string') {\n req.data = JSON.parse(fields._payload)\n }\n\n if (!req.file && fields?.file && typeof fields?.file === 'string') {\n let
|
|
1
|
+
{"version":3,"sources":["../../src/utilities/addDataAndFileToRequest.ts"],"sourcesContent":["import type { PayloadRequest } from '../types/index.js'\nimport type { UploadInstructions } from '../uploads/types.js'\n\nimport { APIError } from '../errors/APIError.js'\nimport { processMultipartFormdata } from '../uploads/fetchAPI-multipart/index.js'\nimport { getFileFromUploadInstructions } from '../uploads/getFileFromUploadInstructions.js'\n\ntype AddDataAndFileToRequest = (req: PayloadRequest) => Promise<void>\n\n/**\n * Mutates the Request, appending 'data' and 'file' if found\n */\nexport const addDataAndFileToRequest: AddDataAndFileToRequest = async (req) => {\n const { body, headers, method, payload } = req\n\n if (method && ['PATCH', 'POST', 'PUT'].includes(method.toUpperCase()) && body) {\n const [contentType] = (headers.get('Content-Type') || '').split(';', 1)\n const bodyByteSize = parseInt(req.headers.get('Content-Length') || '0', 10)\n const hasBodyStream = req.body !== null\n\n if (contentType === 'application/json') {\n try {\n const text = await req.text?.()\n const data = text ? JSON.parse(text) : {}\n req.data = data\n // @ts-expect-error attach json method to request\n req.json = () => Promise.resolve(data)\n } catch (error) {\n if (error instanceof SyntaxError) {\n throw new APIError('Invalid JSON', 400)\n }\n req.payload.logger.error(error)\n throw error\n }\n } else if ((bodyByteSize || hasBodyStream) && contentType?.includes('multipart/')) {\n const { error, fields, files } = await processMultipartFormdata({\n options: {\n ...(payload.config.bodyParser || {}),\n ...(payload.config.upload || {}),\n },\n request: req as Request,\n })\n\n if (error) {\n throw new APIError(error.message)\n }\n\n // Set all files on req.files for access by hooks\n if (files) {\n req.files = files\n // Backwards compatibility: set req.file for standard upload collections\n // Guard: if multiple files share the field name \"file\", files.file is an array — skip\n if (files.file && !Array.isArray(files.file)) {\n req.file = files.file\n }\n }\n\n if (fields?._payload && typeof fields._payload === 'string') {\n req.data = JSON.parse(fields._payload)\n }\n\n if (!req.file && fields?.file && typeof fields?.file === 'string') {\n let uploadedFile: UploadInstructions['file']\n try {\n uploadedFile = JSON.parse(fields.file)\n } catch {\n throw new APIError('A file name is required.', 400)\n }\n const collectionSlug =\n typeof req.routeParams?.collection === 'string'\n ? req.routeParams.collection\n : uploadedFile.collectionSlug\n const uploadConfig = collectionSlug\n ? req.payload.collections[collectionSlug]?.config.upload\n : undefined\n\n if (!collectionSlug || !uploadConfig) {\n throw new APIError('Invalid upload collection.', 400)\n }\n\n req.file = await getFileFromUploadInstructions({\n collectionSlug,\n file: uploadedFile,\n req,\n })\n }\n }\n }\n}\n"],"names":["APIError","processMultipartFormdata","getFileFromUploadInstructions","addDataAndFileToRequest","req","body","headers","method","payload","includes","toUpperCase","contentType","get","split","bodyByteSize","parseInt","hasBodyStream","text","data","JSON","parse","json","Promise","resolve","error","SyntaxError","logger","fields","files","options","config","bodyParser","upload","request","message","file","Array","isArray","_payload","uploadedFile","collectionSlug","routeParams","collection","uploadConfig","collections","undefined"],"mappings":"AAGA,SAASA,QAAQ,QAAQ,wBAAuB;AAChD,SAASC,wBAAwB,QAAQ,yCAAwC;AACjF,SAASC,6BAA6B,QAAQ,8CAA6C;AAI3F;;CAEC,GACD,OAAO,MAAMC,0BAAmD,OAAOC;IACrE,MAAM,EAAEC,IAAI,EAAEC,OAAO,EAAEC,MAAM,EAAEC,OAAO,EAAE,GAAGJ;IAE3C,IAAIG,UAAU;QAAC;QAAS;QAAQ;KAAM,CAACE,QAAQ,CAACF,OAAOG,WAAW,OAAOL,MAAM;QAC7E,MAAM,CAACM,YAAY,GAAG,AAACL,CAAAA,QAAQM,GAAG,CAAC,mBAAmB,EAAC,EAAGC,KAAK,CAAC,KAAK;QACrE,MAAMC,eAAeC,SAASX,IAAIE,OAAO,CAACM,GAAG,CAAC,qBAAqB,KAAK;QACxE,MAAMI,gBAAgBZ,IAAIC,IAAI,KAAK;QAEnC,IAAIM,gBAAgB,oBAAoB;YACtC,IAAI;gBACF,MAAMM,OAAO,MAAMb,IAAIa,IAAI;gBAC3B,MAAMC,OAAOD,OAAOE,KAAKC,KAAK,CAACH,QAAQ,CAAC;gBACxCb,IAAIc,IAAI,GAAGA;gBACX,iDAAiD;gBACjDd,IAAIiB,IAAI,GAAG,IAAMC,QAAQC,OAAO,CAACL;YACnC,EAAE,OAAOM,OAAO;gBACd,IAAIA,iBAAiBC,aAAa;oBAChC,MAAM,IAAIzB,SAAS,gBAAgB;gBACrC;gBACAI,IAAII,OAAO,CAACkB,MAAM,CAACF,KAAK,CAACA;gBACzB,MAAMA;YACR;QACF,OAAO,IAAI,AAACV,CAAAA,gBAAgBE,aAAY,KAAML,aAAaF,SAAS,eAAe;YACjF,MAAM,EAAEe,KAAK,EAAEG,MAAM,EAAEC,KAAK,EAAE,GAAG,MAAM3B,yBAAyB;gBAC9D4B,SAAS;oBACP,GAAIrB,QAAQsB,MAAM,CAACC,UAAU,IAAI,CAAC,CAAC;oBACnC,GAAIvB,QAAQsB,MAAM,CAACE,MAAM,IAAI,CAAC,CAAC;gBACjC;gBACAC,SAAS7B;YACX;YAEA,IAAIoB,OAAO;gBACT,MAAM,IAAIxB,SAASwB,MAAMU,OAAO;YAClC;YAEA,iDAAiD;YACjD,IAAIN,OAAO;gBACTxB,IAAIwB,KAAK,GAAGA;gBACZ,wEAAwE;gBACxE,sFAAsF;gBACtF,IAAIA,MAAMO,IAAI,IAAI,CAACC,MAAMC,OAAO,CAACT,MAAMO,IAAI,GAAG;oBAC5C/B,IAAI+B,IAAI,GAAGP,MAAMO,IAAI;gBACvB;YACF;YAEA,IAAIR,QAAQW,YAAY,OAAOX,OAAOW,QAAQ,KAAK,UAAU;gBAC3DlC,IAAIc,IAAI,GAAGC,KAAKC,KAAK,CAACO,OAAOW,QAAQ;YACvC;YAEA,IAAI,CAAClC,IAAI+B,IAAI,IAAIR,QAAQQ,QAAQ,OAAOR,QAAQQ,SAAS,UAAU;gBACjE,IAAII;gBACJ,IAAI;oBACFA,eAAepB,KAAKC,KAAK,CAACO,OAAOQ,IAAI;gBACvC,EAAE,OAAM;oBACN,MAAM,IAAInC,SAAS,4BAA4B;gBACjD;gBACA,MAAMwC,iBACJ,OAAOpC,IAAIqC,WAAW,EAAEC,eAAe,WACnCtC,IAAIqC,WAAW,CAACC,UAAU,GAC1BH,aAAaC,cAAc;gBACjC,MAAMG,eAAeH,iBACjBpC,IAAII,OAAO,CAACoC,WAAW,CAACJ,eAAe,EAAEV,OAAOE,SAChDa;gBAEJ,IAAI,CAACL,kBAAkB,CAACG,cAAc;oBACpC,MAAM,IAAI3C,SAAS,8BAA8B;gBACnD;gBAEAI,IAAI+B,IAAI,GAAG,MAAMjC,8BAA8B;oBAC7CsC;oBACAL,MAAMI;oBACNnC;gBACF;YACF;QACF;IACF;AACF,EAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "payload",
|
|
3
|
-
"version": "4.0.0-internal.
|
|
3
|
+
"version": "4.0.0-internal.e7d4ebc",
|
|
4
4
|
"description": "Node, React, Headless CMS and Application Framework built on Next.js",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"admin panel",
|
|
@@ -118,7 +118,7 @@
|
|
|
118
118
|
"undici": "7.28.0",
|
|
119
119
|
"uuid": "14.0.0",
|
|
120
120
|
"ws": "^8.16.0",
|
|
121
|
-
"@payloadcms/translations": "4.0.0-internal.
|
|
121
|
+
"@payloadcms/translations": "4.0.0-internal.e7d4ebc"
|
|
122
122
|
},
|
|
123
123
|
"devDependencies": {
|
|
124
124
|
"@hyrious/esbuild-plugin-commonjs": "0.2.6",
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import type { CollectionSlug, DefaultDocumentIDType, GlobalSlug, PayloadRequest } from '../../../index.js';
|
|
2
|
-
/**
|
|
3
|
-
* This is a cross-entity way to count the number of versions for any given document.
|
|
4
|
-
* It will work for both collections and globals.
|
|
5
|
-
* @returns number of versions
|
|
6
|
-
*/
|
|
7
|
-
export declare const countVersions: (args: {
|
|
8
|
-
collectionSlug?: CollectionSlug;
|
|
9
|
-
globalSlug?: GlobalSlug;
|
|
10
|
-
parentID?: DefaultDocumentIDType;
|
|
11
|
-
req: PayloadRequest;
|
|
12
|
-
}) => Promise<number>;
|
|
13
|
-
//# sourceMappingURL=countVersions.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"countVersions.d.ts","sourceRoot":"","sources":["../../../../src/fields/baseFields/slug/countVersions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,cAAc,EACd,qBAAqB,EACrB,UAAU,EACV,cAAc,EACf,MAAM,mBAAmB,CAAA;AAE1B;;;;GAIG;AACH,eAAO,MAAM,aAAa,SAAgB;IACxC,cAAc,CAAC,EAAE,cAAc,CAAA;IAC/B,UAAU,CAAC,EAAE,UAAU,CAAA;IACvB,QAAQ,CAAC,EAAE,qBAAqB,CAAA;IAChC,GAAG,EAAE,cAAc,CAAA;CACpB,KAAG,OAAO,CAAC,MAAM,CA2BjB,CAAA"}
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* This is a cross-entity way to count the number of versions for any given document.
|
|
3
|
-
* It will work for both collections and globals.
|
|
4
|
-
* @returns number of versions
|
|
5
|
-
*/ export const countVersions = async (args)=>{
|
|
6
|
-
const { collectionSlug, globalSlug, parentID, req } = args;
|
|
7
|
-
let countFn;
|
|
8
|
-
if (collectionSlug) {
|
|
9
|
-
countFn = ()=>req.payload.countVersions({
|
|
10
|
-
collection: collectionSlug,
|
|
11
|
-
where: {
|
|
12
|
-
parent: {
|
|
13
|
-
equals: parentID
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
});
|
|
17
|
-
}
|
|
18
|
-
if (globalSlug) {
|
|
19
|
-
countFn = ()=>req.payload.countGlobalVersions({
|
|
20
|
-
global: globalSlug
|
|
21
|
-
});
|
|
22
|
-
}
|
|
23
|
-
const res = countFn ? await countFn()?.then((res)=>res.totalDocs || 0) || 0 : 0;
|
|
24
|
-
return res;
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
//# sourceMappingURL=countVersions.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/fields/baseFields/slug/countVersions.ts"],"sourcesContent":["import type {\n CollectionSlug,\n DefaultDocumentIDType,\n GlobalSlug,\n PayloadRequest,\n} from '../../../index.js'\n\n/**\n * This is a cross-entity way to count the number of versions for any given document.\n * It will work for both collections and globals.\n * @returns number of versions\n */\nexport const countVersions = async (args: {\n collectionSlug?: CollectionSlug\n globalSlug?: GlobalSlug\n parentID?: DefaultDocumentIDType\n req: PayloadRequest\n}): Promise<number> => {\n const { collectionSlug, globalSlug, parentID, req } = args\n\n let countFn\n\n if (collectionSlug) {\n countFn = () =>\n req.payload.countVersions({\n collection: collectionSlug,\n where: {\n parent: {\n equals: parentID,\n },\n },\n })\n }\n\n if (globalSlug) {\n countFn = () =>\n req.payload.countGlobalVersions({\n global: globalSlug,\n })\n }\n\n const res = countFn ? (await countFn()?.then((res) => res.totalDocs || 0)) || 0 : 0\n\n return res\n}\n"],"names":["countVersions","args","collectionSlug","globalSlug","parentID","req","countFn","payload","collection","where","parent","equals","countGlobalVersions","global","res","then","totalDocs"],"mappings":"AAOA;;;;CAIC,GACD,OAAO,MAAMA,gBAAgB,OAAOC;IAMlC,MAAM,EAAEC,cAAc,EAAEC,UAAU,EAAEC,QAAQ,EAAEC,GAAG,EAAE,GAAGJ;IAEtD,IAAIK;IAEJ,IAAIJ,gBAAgB;QAClBI,UAAU,IACRD,IAAIE,OAAO,CAACP,aAAa,CAAC;gBACxBQ,YAAYN;gBACZO,OAAO;oBACLC,QAAQ;wBACNC,QAAQP;oBACV;gBACF;YACF;IACJ;IAEA,IAAID,YAAY;QACdG,UAAU,IACRD,IAAIE,OAAO,CAACK,mBAAmB,CAAC;gBAC9BC,QAAQV;YACV;IACJ;IAEA,MAAMW,MAAMR,UAAU,AAAC,MAAMA,WAAWS,KAAK,CAACD,MAAQA,IAAIE,SAAS,IAAI,MAAO,IAAI;IAElF,OAAOF;AACT,EAAC"}
|