payload 4.0.0-internal.cd69eef → 4.0.0-internal.d1cc1d3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/admin/RichText.d.ts +1 -1
- package/dist/admin/RichText.d.ts.map +1 -1
- package/dist/admin/RichText.js.map +1 -1
- package/dist/admin/functions/index.d.ts +10 -8
- 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 +2 -2
- package/dist/admin/types.d.ts.map +1 -1
- package/dist/admin/types.js.map +1 -1
- package/dist/auth/endpoints/login.d.ts.map +1 -1
- package/dist/auth/endpoints/login.js +2 -11
- package/dist/auth/endpoints/login.js.map +1 -1
- package/dist/auth/loginWithCookie.d.ts +33 -0
- package/dist/auth/loginWithCookie.d.ts.map +1 -0
- package/dist/auth/loginWithCookie.js +34 -0
- package/dist/auth/loginWithCookie.js.map +1 -0
- package/dist/auth/serverFunctions/cookies.d.ts +47 -0
- package/dist/auth/serverFunctions/cookies.d.ts.map +1 -0
- package/dist/auth/serverFunctions/cookies.js +52 -0
- package/dist/auth/serverFunctions/cookies.js.map +1 -0
- package/dist/auth/serverFunctions/login.d.ts +29 -0
- package/dist/auth/serverFunctions/login.d.ts.map +1 -0
- package/dist/auth/serverFunctions/login.js +63 -0
- package/dist/auth/serverFunctions/login.js.map +1 -0
- package/dist/auth/serverFunctions/logout.d.ts +17 -0
- package/dist/auth/serverFunctions/logout.d.ts.map +1 -0
- package/dist/auth/serverFunctions/logout.js +58 -0
- package/dist/auth/serverFunctions/logout.js.map +1 -0
- package/dist/auth/serverFunctions/refresh.d.ts +17 -0
- package/dist/auth/serverFunctions/refresh.d.ts.map +1 -0
- package/dist/auth/serverFunctions/refresh.js +61 -0
- package/dist/auth/serverFunctions/refresh.js.map +1 -0
- package/dist/collections/config/client.d.ts +2 -3
- package/dist/collections/config/client.d.ts.map +1 -1
- package/dist/collections/config/client.js +5 -7
- package/dist/collections/config/client.js.map +1 -1
- package/dist/collections/config/defaults.d.ts.map +1 -1
- package/dist/collections/config/defaults.js +1 -0
- package/dist/collections/config/defaults.js.map +1 -1
- package/dist/collections/config/sanitize.d.ts +3 -8
- package/dist/collections/config/sanitize.d.ts.map +1 -1
- package/dist/collections/config/sanitize.js +2 -6
- package/dist/collections/config/sanitize.js.map +1 -1
- package/dist/collections/config/types.d.ts +1 -1
- package/dist/collections/config/types.d.ts.map +1 -1
- package/dist/collections/config/types.js.map +1 -1
- package/dist/collections/config/useAsTitle.spec.js +27 -27
- package/dist/collections/config/useAsTitle.spec.js.map +1 -1
- package/dist/collections/operations/create.d.ts.map +1 -1
- package/dist/collections/operations/create.js +10 -0
- package/dist/collections/operations/create.js.map +1 -1
- package/dist/collections/operations/restoreVersion.d.ts.map +1 -1
- package/dist/collections/operations/restoreVersion.js +7 -4
- package/dist/collections/operations/restoreVersion.js.map +1 -1
- package/dist/collections/operations/updateByID.js +1 -0
- package/dist/collections/operations/updateByID.js.map +1 -1
- package/dist/config/build.js +1 -1
- package/dist/config/build.js.map +1 -1
- package/dist/config/defaults.d.ts.map +1 -1
- package/dist/config/defaults.js +5 -2
- package/dist/config/defaults.js.map +1 -1
- package/dist/config/orderable/index.d.ts +1 -1
- package/dist/config/orderable/index.d.ts.map +1 -1
- package/dist/config/orderable/index.js +2 -2
- package/dist/config/orderable/index.js.map +1 -1
- package/dist/config/sanitize.d.ts +1 -1
- package/dist/config/sanitize.d.ts.map +1 -1
- package/dist/config/sanitize.js +33 -40
- package/dist/config/sanitize.js.map +1 -1
- package/dist/config/types.d.ts +1 -1
- package/dist/config/types.js.map +1 -1
- package/dist/database/createDatabaseAdapter.d.ts +1 -1
- package/dist/database/createDatabaseAdapter.d.ts.map +1 -1
- package/dist/database/createDatabaseAdapter.js +0 -2
- package/dist/database/createDatabaseAdapter.js.map +1 -1
- package/dist/database/types.d.ts +6 -0
- package/dist/database/types.d.ts.map +1 -1
- package/dist/database/types.js.map +1 -1
- package/dist/exports/auth.d.ts +5 -0
- package/dist/exports/auth.d.ts.map +1 -0
- package/dist/exports/auth.js +6 -0
- package/dist/exports/auth.js.map +1 -0
- 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/duplicateContext.d.ts +11 -0
- package/dist/fields/baseFields/slug/duplicateContext.d.ts.map +1 -0
- package/dist/fields/baseFields/slug/duplicateContext.js +21 -0
- package/dist/fields/baseFields/slug/duplicateContext.js.map +1 -0
- package/dist/fields/baseFields/slug/fillEmptyLocalizedSlugs.d.ts +22 -0
- package/dist/fields/baseFields/slug/fillEmptyLocalizedSlugs.d.ts.map +1 -0
- package/dist/fields/baseFields/slug/fillEmptyLocalizedSlugs.js +63 -0
- package/dist/fields/baseFields/slug/fillEmptyLocalizedSlugs.js.map +1 -0
- package/dist/fields/baseFields/slug/generateSlug.d.ts +13 -8
- package/dist/fields/baseFields/slug/generateSlug.d.ts.map +1 -1
- package/dist/fields/baseFields/slug/generateSlug.js +98 -45
- package/dist/fields/baseFields/slug/generateSlug.js.map +1 -1
- package/dist/fields/baseFields/slug/generateSlugBeforeDuplicate.d.ts +18 -0
- package/dist/fields/baseFields/slug/generateSlugBeforeDuplicate.d.ts.map +1 -0
- package/dist/fields/baseFields/slug/generateSlugBeforeDuplicate.js +20 -0
- package/dist/fields/baseFields/slug/generateSlugBeforeDuplicate.js.map +1 -0
- package/dist/fields/baseFields/slug/getSlugFallbackValue.d.ts +22 -0
- package/dist/fields/baseFields/slug/getSlugFallbackValue.d.ts.map +1 -0
- package/dist/fields/baseFields/slug/getSlugFallbackValue.js +23 -0
- package/dist/fields/baseFields/slug/getSlugFallbackValue.js.map +1 -0
- package/dist/fields/baseFields/slug/hasValue.d.ts +3 -0
- package/dist/fields/baseFields/slug/hasValue.d.ts.map +1 -0
- package/dist/fields/baseFields/slug/hasValue.js +3 -0
- package/dist/fields/baseFields/slug/hasValue.js.map +1 -0
- package/dist/fields/config/reservedFieldNames.spec.js +18 -18
- package/dist/fields/config/reservedFieldNames.spec.js.map +1 -1
- package/dist/fields/config/sanitize.d.ts +3 -9
- package/dist/fields/config/sanitize.d.ts.map +1 -1
- package/dist/fields/config/sanitize.js +33 -34
- package/dist/fields/config/sanitize.js.map +1 -1
- package/dist/fields/config/sanitize.spec.js +128 -105
- package/dist/fields/config/sanitize.spec.js.map +1 -1
- package/dist/fields/config/types.d.ts +4 -3
- package/dist/fields/config/types.d.ts.map +1 -1
- package/dist/fields/config/types.js.map +1 -1
- package/dist/fields/hooks/beforeValidate/promise.d.ts.map +1 -1
- package/dist/fields/hooks/beforeValidate/promise.js +5 -3
- package/dist/fields/hooks/beforeValidate/promise.js.map +1 -1
- package/dist/fields/hooks/beforeValidate/stripNullRows.d.ts +10 -0
- package/dist/fields/hooks/beforeValidate/stripNullRows.d.ts.map +1 -0
- package/dist/fields/hooks/beforeValidate/stripNullRows.js +18 -0
- package/dist/fields/hooks/beforeValidate/stripNullRows.js.map +1 -0
- package/dist/fields/validations.d.ts.map +1 -1
- package/dist/fields/validations.js +7 -8
- package/dist/fields/validations.js.map +1 -1
- package/dist/fields/validations.spec.js +61 -37
- package/dist/fields/validations.spec.js.map +1 -1
- package/dist/globals/config/sanitize.d.ts +2 -7
- package/dist/globals/config/sanitize.d.ts.map +1 -1
- package/dist/globals/config/sanitize.js +2 -6
- package/dist/globals/config/sanitize.js.map +1 -1
- package/dist/globals/config/sanitize.spec.js +6 -6
- package/dist/globals/config/sanitize.spec.js.map +1 -1
- package/dist/globals/operations/countGlobalVersions.d.ts.map +1 -1
- package/dist/globals/operations/countGlobalVersions.js +1 -0
- package/dist/globals/operations/countGlobalVersions.js.map +1 -1
- package/dist/index.bundled.d.ts +247 -178
- package/dist/index.d.ts +49 -17
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/query-presets/constraints.js +1 -1
- package/dist/query-presets/constraints.js.map +1 -1
- package/dist/queues/config/collection.d.ts.map +1 -1
- package/dist/queues/config/collection.js +37 -43
- package/dist/queues/config/collection.js.map +1 -1
- package/dist/queues/config/global.d.ts +5 -6
- package/dist/queues/config/global.d.ts.map +1 -1
- package/dist/queues/config/global.js +1 -1
- package/dist/queues/config/global.js.map +1 -1
- package/dist/queues/config/types/index.d.ts +29 -24
- package/dist/queues/config/types/index.d.ts.map +1 -1
- package/dist/queues/config/types/index.js.map +1 -1
- package/dist/queues/config/types/taskTypes.d.ts +4 -7
- package/dist/queues/config/types/taskTypes.d.ts.map +1 -1
- package/dist/queues/config/types/taskTypes.js.map +1 -1
- package/dist/queues/config/types/workflowJSONTypes.d.ts +10 -9
- package/dist/queues/config/types/workflowJSONTypes.d.ts.map +1 -1
- package/dist/queues/config/types/workflowJSONTypes.js.map +1 -1
- package/dist/queues/config/types/workflowTypes.d.ts +11 -58
- package/dist/queues/config/types/workflowTypes.d.ts.map +1 -1
- package/dist/queues/config/types/workflowTypes.js.map +1 -1
- package/dist/queues/endpoints/handleSchedules.js +1 -1
- package/dist/queues/endpoints/handleSchedules.js.map +1 -1
- package/dist/queues/errors/handleTaskError.js +4 -4
- package/dist/queues/errors/handleTaskError.js.map +1 -1
- package/dist/queues/errors/handleWorkflowError.js +1 -1
- package/dist/queues/errors/handleWorkflowError.js.map +1 -1
- package/dist/queues/errors/index.d.ts +6 -0
- package/dist/queues/errors/index.d.ts.map +1 -1
- package/dist/queues/errors/index.js +5 -0
- package/dist/queues/errors/index.js.map +1 -1
- package/dist/queues/localAPI.d.ts +4 -4
- package/dist/queues/localAPI.d.ts.map +1 -1
- package/dist/queues/localAPI.js +63 -66
- package/dist/queues/localAPI.js.map +1 -1
- package/dist/queues/operations/handleSchedules/countRunnableOrActiveJobsForQueue.d.ts +4 -4
- package/dist/queues/operations/handleSchedules/countRunnableOrActiveJobsForQueue.d.ts.map +1 -1
- package/dist/queues/operations/handleSchedules/countRunnableOrActiveJobsForQueue.js.map +1 -1
- package/dist/queues/operations/handleSchedules/index.d.ts +1 -1
- package/dist/queues/operations/handleSchedules/index.d.ts.map +1 -1
- package/dist/queues/operations/handleSchedules/index.js +1 -1
- package/dist/queues/operations/handleSchedules/index.js.map +1 -1
- package/dist/queues/operations/runJobs/heartbeat.d.ts +13 -0
- package/dist/queues/operations/runJobs/heartbeat.d.ts.map +1 -0
- package/dist/queues/operations/runJobs/heartbeat.js +66 -0
- package/dist/queues/operations/runJobs/heartbeat.js.map +1 -0
- package/dist/queues/operations/runJobs/index.d.ts.map +1 -1
- package/dist/queues/operations/runJobs/index.js +133 -84
- package/dist/queues/operations/runJobs/index.js.map +1 -1
- package/dist/queues/operations/runJobs/runJSONJob/index.d.ts.map +1 -1
- package/dist/queues/operations/runJobs/runJSONJob/index.js +6 -3
- package/dist/queues/operations/runJobs/runJSONJob/index.js.map +1 -1
- package/dist/queues/operations/runJobs/runJob/getRunTaskFunction.js +5 -5
- package/dist/queues/operations/runJobs/runJob/getRunTaskFunction.js.map +1 -1
- package/dist/queues/operations/runJobs/runJob/getUpdateJobFunction.d.ts +2 -1
- package/dist/queues/operations/runJobs/runJob/getUpdateJobFunction.d.ts.map +1 -1
- package/dist/queues/operations/runJobs/runJob/getUpdateJobFunction.js +39 -8
- package/dist/queues/operations/runJobs/runJob/getUpdateJobFunction.js.map +1 -1
- package/dist/queues/operations/runJobs/runJob/importHandlerPath.js.map +1 -1
- package/dist/queues/operations/runJobs/runJob/index.d.ts.map +1 -1
- package/dist/queues/operations/runJobs/runJob/index.js +4 -4
- package/dist/queues/operations/runJobs/runJob/index.js.map +1 -1
- package/dist/queues/utilities/updateJob.d.ts.map +1 -1
- package/dist/queues/utilities/updateJob.js +3 -0
- package/dist/queues/utilities/updateJob.js.map +1 -1
- package/dist/types/index.d.ts +2 -2
- 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 +12 -0
- package/dist/uploads/endpoints/uploadInstructions.d.ts.map +1 -1
- package/dist/uploads/endpoints/uploadInstructions.js +66 -20
- package/dist/uploads/endpoints/uploadInstructions.js.map +1 -1
- package/dist/uploads/generateFileData.js +4 -1
- package/dist/uploads/generateFileData.js.map +1 -1
- 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/getImageSize.d.ts +12 -1
- package/dist/uploads/getImageSize.d.ts.map +1 -1
- package/dist/uploads/getImageSize.js +20 -18
- package/dist/uploads/getImageSize.js.map +1 -1
- package/dist/uploads/getImageSize.spec.js +298 -0
- package/dist/uploads/getImageSize.spec.js.map +1 -0
- package/dist/uploads/probeImageSize.d.ts +39 -0
- package/dist/uploads/probeImageSize.d.ts.map +1 -0
- package/dist/uploads/probeImageSize.js +374 -0
- package/dist/uploads/probeImageSize.js.map +1 -0
- package/dist/uploads/probeImageSize.spec.js +366 -0
- package/dist/uploads/probeImageSize.spec.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 +41 -13
- 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 -46
- package/dist/utilities/addDataAndFileToRequest.js.map +1 -1
- package/dist/utilities/configToJSONSchema.spec.js +33 -33
- package/dist/utilities/configToJSONSchema.spec.js.map +1 -1
- package/dist/utilities/fieldValueExists.d.ts +29 -0
- package/dist/utilities/fieldValueExists.d.ts.map +1 -0
- package/dist/utilities/fieldValueExists.js +27 -0
- package/dist/utilities/fieldValueExists.js.map +1 -0
- package/dist/utilities/getUniqueFieldValue.d.ts +27 -0
- package/dist/utilities/getUniqueFieldValue.d.ts.map +1 -0
- package/dist/utilities/getUniqueFieldValue.js +26 -0
- package/dist/utilities/getUniqueFieldValue.js.map +1 -0
- package/dist/versions/deleteScheduledPublishJobs.js +2 -2
- package/dist/versions/deleteScheduledPublishJobs.js.map +1 -1
- package/dist/versions/payloadPackageList.d.ts.map +1 -1
- package/dist/versions/payloadPackageList.js +0 -1
- package/dist/versions/payloadPackageList.js.map +1 -1
- package/package.json +8 -3
- package/dist/database/defaultUpdateJobs.d.ts +0 -3
- package/dist/database/defaultUpdateJobs.d.ts.map +0 -1
- package/dist/database/defaultUpdateJobs.js +0 -41
- package/dist/database/defaultUpdateJobs.js.map +0 -1
- 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
- package/dist/uploads/tempFile.d.ts +0 -7
- package/dist/uploads/tempFile.d.ts.map +0 -1
- package/dist/uploads/tempFile.js +0 -39
- package/dist/uploads/tempFile.js.map +0 -1
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
import { mkdtempSync, readFileSync, rmSync, writeFileSync } from 'fs';
|
|
2
|
+
import os from 'os';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import sharp from 'sharp';
|
|
5
|
+
import { fileURLToPath } from 'url';
|
|
6
|
+
import { afterAll, afterEach, describe, expect, it, vi } from 'vitest';
|
|
7
|
+
import { getImageSize } from './getImageSize.js';
|
|
8
|
+
// Tracks bytes actually read off disk so the streaming test below can assert
|
|
9
|
+
// that a large file's tail is never pulled into memory
|
|
10
|
+
const counters = vi.hoisted(()=>({
|
|
11
|
+
bytesReadFromDisk: 0
|
|
12
|
+
}));
|
|
13
|
+
vi.mock('fs', async (importOriginal)=>{
|
|
14
|
+
const actual = await importOriginal();
|
|
15
|
+
return {
|
|
16
|
+
...actual,
|
|
17
|
+
createReadStream: (...args)=>{
|
|
18
|
+
const stream = actual.createReadStream(...args);
|
|
19
|
+
stream.on('data', (chunk)=>{
|
|
20
|
+
counters.bytesReadFromDisk += chunk.length;
|
|
21
|
+
});
|
|
22
|
+
return stream;
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
});
|
|
26
|
+
const dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
27
|
+
const fixturesDir = path.resolve(dirname, '../../../../test/uploads');
|
|
28
|
+
// Minimal JPEG XL bare-codestream encoder (bit-packed, little-endian, LSB
|
|
29
|
+
// first). See probeImageSize.spec.ts for the full JXL parsing test suite;
|
|
30
|
+
// this only needs to produce a valid header for the sharp-fallback tests below
|
|
31
|
+
const encodeJXLCodestream = (width, height)=>{
|
|
32
|
+
const bits = [];
|
|
33
|
+
const pushBits = (value, length)=>{
|
|
34
|
+
for(let i = 0; i < length; i++){
|
|
35
|
+
bits.push(value >> i & 1);
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
const pushDimension = (value)=>{
|
|
39
|
+
const n = value - 1;
|
|
40
|
+
const sizeClasses = [
|
|
41
|
+
9,
|
|
42
|
+
13,
|
|
43
|
+
18,
|
|
44
|
+
30
|
|
45
|
+
];
|
|
46
|
+
const classIndex = sizeClasses.findIndex((extraBits)=>n < 2 ** extraBits);
|
|
47
|
+
pushBits(classIndex, 2);
|
|
48
|
+
pushBits(n, sizeClasses[classIndex]);
|
|
49
|
+
};
|
|
50
|
+
pushBits(0, 1); // isSmallImage = false
|
|
51
|
+
pushDimension(height);
|
|
52
|
+
pushBits(0, 3); // widthMode = 0 (explicit dimension)
|
|
53
|
+
pushDimension(width);
|
|
54
|
+
const body = Buffer.alloc(Math.ceil(bits.length / 8));
|
|
55
|
+
bits.forEach((bit, i)=>{
|
|
56
|
+
if (bit) {
|
|
57
|
+
body[Math.floor(i / 8)] |= 1 << i % 8;
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
return Buffer.concat([
|
|
61
|
+
Buffer.from([
|
|
62
|
+
0xff,
|
|
63
|
+
0x0a
|
|
64
|
+
]),
|
|
65
|
+
body
|
|
66
|
+
]);
|
|
67
|
+
};
|
|
68
|
+
const fileFor = (name)=>{
|
|
69
|
+
const data = readFileSync(path.join(fixturesDir, name));
|
|
70
|
+
// In-memory uploads carry an empty `tempFilePath`, which must fall back to `data`
|
|
71
|
+
return {
|
|
72
|
+
data,
|
|
73
|
+
mimetype: 'image/test',
|
|
74
|
+
name,
|
|
75
|
+
size: data.length,
|
|
76
|
+
tempFilePath: ''
|
|
77
|
+
};
|
|
78
|
+
};
|
|
79
|
+
describe('getImageSize', ()=>{
|
|
80
|
+
const cases = [
|
|
81
|
+
{
|
|
82
|
+
file: 'test-image.png',
|
|
83
|
+
height: 800,
|
|
84
|
+
width: 800
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
file: 'test-image.jpg',
|
|
88
|
+
height: 800,
|
|
89
|
+
width: 800
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
file: 'non-animated.webp',
|
|
93
|
+
height: 420,
|
|
94
|
+
width: 900
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
file: 'test-image-avif.avif',
|
|
98
|
+
height: 800,
|
|
99
|
+
width: 800
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
file: 'image.svg',
|
|
103
|
+
height: 260,
|
|
104
|
+
width: 260
|
|
105
|
+
}
|
|
106
|
+
];
|
|
107
|
+
it.each(cases)('should read $file dimensions via sharp', async ({ file, height, width })=>{
|
|
108
|
+
expect(await getImageSize({
|
|
109
|
+
file: fileFor(file),
|
|
110
|
+
sharp
|
|
111
|
+
})).toEqual({
|
|
112
|
+
height,
|
|
113
|
+
width
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
it.each(cases)('should read $file dimensions via the probe fallback', async ({ file, height, width })=>{
|
|
117
|
+
expect(await getImageSize({
|
|
118
|
+
file: fileFor(file)
|
|
119
|
+
})).toEqual({
|
|
120
|
+
height,
|
|
121
|
+
width
|
|
122
|
+
});
|
|
123
|
+
});
|
|
124
|
+
it('should fall back to the probe when sharp cannot decode a header-only image', async ()=>{
|
|
125
|
+
// A 1x1 PNG truncated after IHDR: the header is readable but there is no
|
|
126
|
+
// pixel data, so sharp throws while the probe still measures it.
|
|
127
|
+
const data = Buffer.from('89504e470d0a1a0a0000000d49484452000000010000000108060000001f15c489', 'hex');
|
|
128
|
+
const file = {
|
|
129
|
+
data,
|
|
130
|
+
mimetype: 'image/png',
|
|
131
|
+
name: 'truncated.png',
|
|
132
|
+
size: data.length,
|
|
133
|
+
tempFilePath: ''
|
|
134
|
+
};
|
|
135
|
+
expect(await getImageSize({
|
|
136
|
+
file,
|
|
137
|
+
sharp
|
|
138
|
+
})).toEqual({
|
|
139
|
+
height: 1,
|
|
140
|
+
width: 1
|
|
141
|
+
});
|
|
142
|
+
expect(await getImageSize({
|
|
143
|
+
file
|
|
144
|
+
})).toEqual({
|
|
145
|
+
height: 1,
|
|
146
|
+
width: 1
|
|
147
|
+
});
|
|
148
|
+
});
|
|
149
|
+
it('should read TIFF dimensions from a tempFilePath without a temp-file workaround', async ()=>{
|
|
150
|
+
const tempFilePath = path.join(fixturesDir, 'test-image.tiff');
|
|
151
|
+
const file = {
|
|
152
|
+
mimetype: 'image/tiff',
|
|
153
|
+
name: 'test-image.tiff',
|
|
154
|
+
tempFilePath
|
|
155
|
+
};
|
|
156
|
+
expect(await getImageSize({
|
|
157
|
+
file,
|
|
158
|
+
sharp
|
|
159
|
+
})).toEqual({
|
|
160
|
+
height: 100,
|
|
161
|
+
width: 200
|
|
162
|
+
});
|
|
163
|
+
expect(await getImageSize({
|
|
164
|
+
file
|
|
165
|
+
})).toEqual({
|
|
166
|
+
height: 100,
|
|
167
|
+
width: 200
|
|
168
|
+
});
|
|
169
|
+
});
|
|
170
|
+
describe('sharp cannot decode JPEG XL', ()=>{
|
|
171
|
+
const tempDir = mkdtempSync(path.join(os.tmpdir(), 'payload-get-image-size-jxl-'));
|
|
172
|
+
afterAll(()=>{
|
|
173
|
+
rmSync(tempDir, {
|
|
174
|
+
recursive: true,
|
|
175
|
+
force: true
|
|
176
|
+
});
|
|
177
|
+
});
|
|
178
|
+
it('should fall back to the probe for an in-memory JPEG XL buffer', async ()=>{
|
|
179
|
+
// `isImage('image/jxl')` is true, so `generateFileData` always calls
|
|
180
|
+
// `getImageSize` with `sharp` for JXL uploads; sharp rejects the format
|
|
181
|
+
// (libvips has no JXL codec) and the probe must take over
|
|
182
|
+
const data = encodeJXLCodestream(1920, 1080);
|
|
183
|
+
const file = {
|
|
184
|
+
data,
|
|
185
|
+
mimetype: 'image/jxl',
|
|
186
|
+
name: 'test.jxl',
|
|
187
|
+
size: data.length,
|
|
188
|
+
tempFilePath: ''
|
|
189
|
+
};
|
|
190
|
+
expect(await getImageSize({
|
|
191
|
+
file,
|
|
192
|
+
sharp
|
|
193
|
+
})).toEqual({
|
|
194
|
+
height: 1080,
|
|
195
|
+
width: 1920
|
|
196
|
+
});
|
|
197
|
+
});
|
|
198
|
+
it('should fall back to the probe for a JPEG XL tempFilePath', async ()=>{
|
|
199
|
+
const tempFilePath = path.join(tempDir, 'test.jxl');
|
|
200
|
+
writeFileSync(tempFilePath, encodeJXLCodestream(640, 480));
|
|
201
|
+
const file = {
|
|
202
|
+
mimetype: 'image/jxl',
|
|
203
|
+
name: 'test.jxl',
|
|
204
|
+
tempFilePath
|
|
205
|
+
};
|
|
206
|
+
expect(await getImageSize({
|
|
207
|
+
file,
|
|
208
|
+
sharp
|
|
209
|
+
})).toEqual({
|
|
210
|
+
height: 480,
|
|
211
|
+
width: 640
|
|
212
|
+
});
|
|
213
|
+
});
|
|
214
|
+
});
|
|
215
|
+
describe('streaming from tempFilePath', ()=>{
|
|
216
|
+
const tempDir = mkdtempSync(path.join(os.tmpdir(), 'payload-get-image-size-'));
|
|
217
|
+
afterEach(()=>{
|
|
218
|
+
counters.bytesReadFromDisk = 0;
|
|
219
|
+
});
|
|
220
|
+
afterAll(()=>{
|
|
221
|
+
rmSync(tempDir, {
|
|
222
|
+
recursive: true,
|
|
223
|
+
force: true
|
|
224
|
+
});
|
|
225
|
+
});
|
|
226
|
+
it('should not read a whole large PNG into memory when probing via tempFilePath', async ()=>{
|
|
227
|
+
// image-dimensions only reads the PNG signature (bytes 0-7) and the
|
|
228
|
+
// width/height fields (bytes 16-23); everything else here is filler
|
|
229
|
+
const header = Buffer.alloc(24);
|
|
230
|
+
header.write('\x89PNG\r\n\x1a\n', 0, 'binary');
|
|
231
|
+
header.writeUInt32BE(1920, 16);
|
|
232
|
+
header.writeUInt32BE(1080, 20);
|
|
233
|
+
const largeFileSize = 3 * 1024 * 1024;
|
|
234
|
+
const largeFile = Buffer.concat([
|
|
235
|
+
header,
|
|
236
|
+
Buffer.alloc(largeFileSize)
|
|
237
|
+
]);
|
|
238
|
+
const tempFilePath = path.join(tempDir, 'large.png');
|
|
239
|
+
writeFileSync(tempFilePath, largeFile);
|
|
240
|
+
const file = {
|
|
241
|
+
mimetype: 'image/png',
|
|
242
|
+
name: 'large.png',
|
|
243
|
+
tempFilePath
|
|
244
|
+
};
|
|
245
|
+
expect(await getImageSize({
|
|
246
|
+
file
|
|
247
|
+
})).toEqual({
|
|
248
|
+
height: 1080,
|
|
249
|
+
width: 1920
|
|
250
|
+
});
|
|
251
|
+
// Confirms the read actually went through `createReadStream` rather
|
|
252
|
+
// than skipping it entirely (which would trivially satisfy "< 500KB")
|
|
253
|
+
expect(counters.bytesReadFromDisk).toBeGreaterThan(0);
|
|
254
|
+
expect(counters.bytesReadFromDisk).toBeLessThan(500 * 1024);
|
|
255
|
+
expect(counters.bytesReadFromDisk).toBeLessThan(largeFile.length);
|
|
256
|
+
});
|
|
257
|
+
it.each(cases.filter(({ file })=>file !== 'image.svg'))('should read $file dimensions via imageDimensionsFromStream when streamed from a tempFilePath', async ({ file, height, width })=>{
|
|
258
|
+
const tempFilePath = path.join(tempDir, file);
|
|
259
|
+
writeFileSync(tempFilePath, readFileSync(path.join(fixturesDir, file)));
|
|
260
|
+
const streamedFile = {
|
|
261
|
+
mimetype: 'image/test',
|
|
262
|
+
name: file,
|
|
263
|
+
tempFilePath
|
|
264
|
+
};
|
|
265
|
+
expect(await getImageSize({
|
|
266
|
+
file: streamedFile
|
|
267
|
+
})).toEqual({
|
|
268
|
+
height,
|
|
269
|
+
width
|
|
270
|
+
});
|
|
271
|
+
});
|
|
272
|
+
it('should read GIF dimensions when streamed from a tempFilePath', async ()=>{
|
|
273
|
+
// No GIF fixture lives in this directory; `image-dimensions` only needs
|
|
274
|
+
// the 6-byte signature plus the 4-byte width/height fields that follow it
|
|
275
|
+
const header = Buffer.concat([
|
|
276
|
+
Buffer.from('GIF89a', 'ascii'),
|
|
277
|
+
Buffer.alloc(4)
|
|
278
|
+
]);
|
|
279
|
+
header.writeUInt16LE(64, 6);
|
|
280
|
+
header.writeUInt16LE(48, 8);
|
|
281
|
+
const tempFilePath = path.join(tempDir, 'test.gif');
|
|
282
|
+
writeFileSync(tempFilePath, header);
|
|
283
|
+
const file = {
|
|
284
|
+
mimetype: 'image/gif',
|
|
285
|
+
name: 'test.gif',
|
|
286
|
+
tempFilePath
|
|
287
|
+
};
|
|
288
|
+
expect(await getImageSize({
|
|
289
|
+
file
|
|
290
|
+
})).toEqual({
|
|
291
|
+
height: 48,
|
|
292
|
+
width: 64
|
|
293
|
+
});
|
|
294
|
+
});
|
|
295
|
+
});
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
//# sourceMappingURL=getImageSize.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/uploads/getImageSize.spec.ts"],"sourcesContent":["import { mkdtempSync, readFileSync, rmSync, writeFileSync } from 'fs'\nimport os from 'os'\nimport path from 'path'\nimport sharp from 'sharp'\nimport { fileURLToPath } from 'url'\nimport { afterAll, afterEach, describe, expect, it, vi } from 'vitest'\n\nimport type { PayloadRequest } from '../types/index.js'\n\nimport { getImageSize } from './getImageSize.js'\n\n// Tracks bytes actually read off disk so the streaming test below can assert\n// that a large file's tail is never pulled into memory\nconst counters = vi.hoisted(() => ({ bytesReadFromDisk: 0 }))\n\nvi.mock('fs', async (importOriginal) => {\n const actual = await importOriginal<typeof import('fs')>()\n return {\n ...actual,\n createReadStream: (...args: Parameters<typeof actual.createReadStream>) => {\n const stream = actual.createReadStream(...args)\n stream.on('data', (chunk: Buffer) => {\n counters.bytesReadFromDisk += chunk.length\n })\n return stream\n },\n }\n})\n\nconst dirname = path.dirname(fileURLToPath(import.meta.url))\nconst fixturesDir = path.resolve(dirname, '../../../../test/uploads')\n\n// Minimal JPEG XL bare-codestream encoder (bit-packed, little-endian, LSB\n// first). See probeImageSize.spec.ts for the full JXL parsing test suite;\n// this only needs to produce a valid header for the sharp-fallback tests below\nconst encodeJXLCodestream = (width: number, height: number): Buffer => {\n const bits: number[] = []\n const pushBits = (value: number, length: number) => {\n for (let i = 0; i < length; i++) {\n bits.push((value >> i) & 1)\n }\n }\n const pushDimension = (value: number) => {\n const n = value - 1\n const sizeClasses = [9, 13, 18, 30]\n const classIndex = sizeClasses.findIndex((extraBits) => n < 2 ** extraBits)\n pushBits(classIndex, 2)\n pushBits(n, sizeClasses[classIndex]!)\n }\n\n pushBits(0, 1) // isSmallImage = false\n pushDimension(height)\n pushBits(0, 3) // widthMode = 0 (explicit dimension)\n pushDimension(width)\n\n const body = Buffer.alloc(Math.ceil(bits.length / 8))\n bits.forEach((bit, i) => {\n if (bit) {\n body[Math.floor(i / 8)]! |= 1 << i % 8\n }\n })\n\n return Buffer.concat([Buffer.from([0xff, 0x0a]), body])\n}\n\nconst fileFor = (name: string): PayloadRequest['file'] => {\n const data = readFileSync(path.join(fixturesDir, name))\n // In-memory uploads carry an empty `tempFilePath`, which must fall back to `data`\n return {\n data,\n mimetype: 'image/test',\n name,\n size: data.length,\n tempFilePath: '',\n } as PayloadRequest['file']\n}\n\ndescribe('getImageSize', () => {\n const cases: Array<{ file: string; height: number; width: number }> = [\n { file: 'test-image.png', height: 800, width: 800 },\n { file: 'test-image.jpg', height: 800, width: 800 },\n { file: 'non-animated.webp', height: 420, width: 900 },\n { file: 'test-image-avif.avif', height: 800, width: 800 },\n { file: 'image.svg', height: 260, width: 260 },\n ]\n\n it.each(cases)('should read $file dimensions via sharp', async ({ file, height, width }) => {\n expect(await getImageSize({ file: fileFor(file), sharp })).toEqual({ height, width })\n })\n\n it.each(cases)(\n 'should read $file dimensions via the probe fallback',\n async ({ file, height, width }) => {\n expect(await getImageSize({ file: fileFor(file) })).toEqual({ height, width })\n },\n )\n\n it('should fall back to the probe when sharp cannot decode a header-only image', async () => {\n // A 1x1 PNG truncated after IHDR: the header is readable but there is no\n // pixel data, so sharp throws while the probe still measures it.\n const data = Buffer.from(\n '89504e470d0a1a0a0000000d49484452000000010000000108060000001f15c489',\n 'hex',\n )\n const file = {\n data,\n mimetype: 'image/png',\n name: 'truncated.png',\n size: data.length,\n tempFilePath: '',\n } as PayloadRequest['file']\n\n expect(await getImageSize({ file, sharp })).toEqual({ height: 1, width: 1 })\n expect(await getImageSize({ file })).toEqual({ height: 1, width: 1 })\n })\n\n it('should read TIFF dimensions from a tempFilePath without a temp-file workaround', async () => {\n const tempFilePath = path.join(fixturesDir, 'test-image.tiff')\n const file = {\n mimetype: 'image/tiff',\n name: 'test-image.tiff',\n tempFilePath,\n } as PayloadRequest['file']\n\n expect(await getImageSize({ file, sharp })).toEqual({ height: 100, width: 200 })\n expect(await getImageSize({ file })).toEqual({ height: 100, width: 200 })\n })\n\n describe('sharp cannot decode JPEG XL', () => {\n const tempDir = mkdtempSync(path.join(os.tmpdir(), 'payload-get-image-size-jxl-'))\n\n afterAll(() => {\n rmSync(tempDir, { recursive: true, force: true })\n })\n\n it('should fall back to the probe for an in-memory JPEG XL buffer', async () => {\n // `isImage('image/jxl')` is true, so `generateFileData` always calls\n // `getImageSize` with `sharp` for JXL uploads; sharp rejects the format\n // (libvips has no JXL codec) and the probe must take over\n const data = encodeJXLCodestream(1920, 1080)\n const file = {\n data,\n mimetype: 'image/jxl',\n name: 'test.jxl',\n size: data.length,\n tempFilePath: '',\n } as PayloadRequest['file']\n\n expect(await getImageSize({ file, sharp })).toEqual({ height: 1080, width: 1920 })\n })\n\n it('should fall back to the probe for a JPEG XL tempFilePath', async () => {\n const tempFilePath = path.join(tempDir, 'test.jxl')\n writeFileSync(tempFilePath, encodeJXLCodestream(640, 480))\n\n const file = {\n mimetype: 'image/jxl',\n name: 'test.jxl',\n tempFilePath,\n } as PayloadRequest['file']\n\n expect(await getImageSize({ file, sharp })).toEqual({ height: 480, width: 640 })\n })\n })\n\n describe('streaming from tempFilePath', () => {\n const tempDir = mkdtempSync(path.join(os.tmpdir(), 'payload-get-image-size-'))\n\n afterEach(() => {\n counters.bytesReadFromDisk = 0\n })\n\n afterAll(() => {\n rmSync(tempDir, { recursive: true, force: true })\n })\n\n it('should not read a whole large PNG into memory when probing via tempFilePath', async () => {\n // image-dimensions only reads the PNG signature (bytes 0-7) and the\n // width/height fields (bytes 16-23); everything else here is filler\n const header = Buffer.alloc(24)\n header.write('\\x89PNG\\r\\n\\x1a\\n', 0, 'binary')\n header.writeUInt32BE(1920, 16)\n header.writeUInt32BE(1080, 20)\n const largeFileSize = 3 * 1024 * 1024\n const largeFile = Buffer.concat([header, Buffer.alloc(largeFileSize)])\n\n const tempFilePath = path.join(tempDir, 'large.png')\n writeFileSync(tempFilePath, largeFile)\n\n const file = {\n mimetype: 'image/png',\n name: 'large.png',\n tempFilePath,\n } as PayloadRequest['file']\n\n expect(await getImageSize({ file })).toEqual({ height: 1080, width: 1920 })\n // Confirms the read actually went through `createReadStream` rather\n // than skipping it entirely (which would trivially satisfy \"< 500KB\")\n expect(counters.bytesReadFromDisk).toBeGreaterThan(0)\n expect(counters.bytesReadFromDisk).toBeLessThan(500 * 1024)\n expect(counters.bytesReadFromDisk).toBeLessThan(largeFile.length)\n })\n\n it.each(cases.filter(({ file }) => file !== 'image.svg'))(\n 'should read $file dimensions via imageDimensionsFromStream when streamed from a tempFilePath',\n async ({ file, height, width }) => {\n const tempFilePath = path.join(tempDir, file)\n writeFileSync(tempFilePath, readFileSync(path.join(fixturesDir, file)))\n\n const streamedFile = {\n mimetype: 'image/test',\n name: file,\n tempFilePath,\n } as PayloadRequest['file']\n\n expect(await getImageSize({ file: streamedFile })).toEqual({ height, width })\n },\n )\n\n it('should read GIF dimensions when streamed from a tempFilePath', async () => {\n // No GIF fixture lives in this directory; `image-dimensions` only needs\n // the 6-byte signature plus the 4-byte width/height fields that follow it\n const header = Buffer.concat([Buffer.from('GIF89a', 'ascii'), Buffer.alloc(4)])\n header.writeUInt16LE(64, 6)\n header.writeUInt16LE(48, 8)\n\n const tempFilePath = path.join(tempDir, 'test.gif')\n writeFileSync(tempFilePath, header)\n\n const file = {\n mimetype: 'image/gif',\n name: 'test.gif',\n tempFilePath,\n } as PayloadRequest['file']\n\n expect(await getImageSize({ file })).toEqual({ height: 48, width: 64 })\n })\n })\n})\n"],"names":["mkdtempSync","readFileSync","rmSync","writeFileSync","os","path","sharp","fileURLToPath","afterAll","afterEach","describe","expect","it","vi","getImageSize","counters","hoisted","bytesReadFromDisk","mock","importOriginal","actual","createReadStream","args","stream","on","chunk","length","dirname","url","fixturesDir","resolve","encodeJXLCodestream","width","height","bits","pushBits","value","i","push","pushDimension","n","sizeClasses","classIndex","findIndex","extraBits","body","Buffer","alloc","Math","ceil","forEach","bit","floor","concat","from","fileFor","name","data","join","mimetype","size","tempFilePath","cases","file","each","toEqual","tempDir","tmpdir","recursive","force","header","write","writeUInt32BE","largeFileSize","largeFile","toBeGreaterThan","toBeLessThan","filter","streamedFile","writeUInt16LE"],"mappings":"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"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { ProbedImageSize } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Image dimension probe used as a fallback when `sharp` is not configured.
|
|
4
|
+
* Reads only the header bytes needed to determine width and height.
|
|
5
|
+
*
|
|
6
|
+
* PNG, JPEG, GIF, WebP, AVIF and HEIF/HEIC are delegated to `image-dimensions`
|
|
7
|
+
* (actively maintained, zero dependencies). BMP, ICO/CUR, SVG, TIFF and JPEG
|
|
8
|
+
* XL have no such maintained equivalent, so they're read here directly; each
|
|
9
|
+
* of those parsers advances by a fixed amount or is bounded by an explicit
|
|
10
|
+
* guard, so malformed input can never block the event loop.
|
|
11
|
+
*
|
|
12
|
+
* Replaces the archived `image-size` package, whose ICNS/HEIF parsers shipped
|
|
13
|
+
* unpatched denial-of-service vulnerabilities (CVE-2025-71330, CVE-2025-71319).
|
|
14
|
+
*
|
|
15
|
+
* Two edge cases changed behavior compared to the previous hand-rolled parser:
|
|
16
|
+
* - JPEG files using arithmetic coding or hierarchical encoding (SOF markers
|
|
17
|
+
* 5-7, 9-11, 13-15) are no longer read; `image-dimensions` only recognizes
|
|
18
|
+
* baseline and progressive JPEG (SOF0-3). These encodings are not produced
|
|
19
|
+
* by browsers or cameras, so this is not expected to affect real uploads.
|
|
20
|
+
* - AVIF/HEIF detection now checks the container's brand list instead of
|
|
21
|
+
* accepting any ISO base media file with a `ftyp` box, so non-image formats
|
|
22
|
+
* that share the same container (for example MP4/MOV) are correctly no
|
|
23
|
+
* longer misidentified as images.
|
|
24
|
+
*
|
|
25
|
+
* @throws if the buffer is not a recognized/parseable image format
|
|
26
|
+
*/
|
|
27
|
+
export declare function probeImageSize(data: Buffer): ProbedImageSize;
|
|
28
|
+
/**
|
|
29
|
+
* Probe used when the file lives on disk via `tempFilePath`. PNG, JPEG, GIF,
|
|
30
|
+
* WebP, AVIF and HEIF/HEIC are read through `imageDimensionsFromStream`,
|
|
31
|
+
* which reads only as many bytes as are needed to find the header, so a
|
|
32
|
+
* large file's data is never pulled into memory. BMP, ICO/CUR, SVG, TIFF and
|
|
33
|
+
* JPEG XL are detected from a small header sniff and, only then, read in
|
|
34
|
+
* full for `probeImageSize` to parse.
|
|
35
|
+
*
|
|
36
|
+
* @throws if the file is not a recognized/parseable image format
|
|
37
|
+
*/
|
|
38
|
+
export declare function probeImageSizeFromPath(tempFilePath: string): Promise<ProbedImageSize>;
|
|
39
|
+
//# sourceMappingURL=probeImageSize.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"probeImageSize.d.ts","sourceRoot":"","sources":["../../src/uploads/probeImageSize.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAEjD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,CAW5D;AAQD;;;;;;;;;GASG;AACH,wBAAsB,sBAAsB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,CAgB3F"}
|