@quark-fw/plugin-uploads 0.1.21 → 0.1.23

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quark-fw/plugin-uploads",
3
- "version": "0.1.21",
3
+ "version": "0.1.23",
4
4
  "main": "src/index.ts",
5
5
  "types": "src/index.ts",
6
6
  "type": "module",
@@ -24,16 +24,16 @@
24
24
  "access": "public"
25
25
  },
26
26
  "dependencies": {
27
- "@quark-fw/plugin": "0.1.21",
27
+ "@quark-fw/plugin": "0.1.23",
28
+ "@types/busboy": "^1.5.4",
28
29
  "busboy": "^1.6.0",
29
30
  "express": "^5.2.1",
30
31
  "sharp": "^0.34.0"
31
32
  },
32
33
  "peerDependencies": {
33
- "@quark-fw/core": "0.1.21"
34
+ "@quark-fw/core": "0.1.23"
34
35
  },
35
36
  "devDependencies": {
36
- "@types/busboy": "^1.5.4",
37
37
  "@types/express": "^5.0.6",
38
38
  "vitest": "^5.0.0"
39
39
  }
@@ -125,6 +125,13 @@ test("корректная загрузка отвечает списком фа
125
125
  expect(files[0]!.size).toBe(5);
126
126
  });
127
127
 
128
+ test("имя файла в UTF-8 не искажается", async () => {
129
+ const res = await multipart(part("фото.txt", "hi") + "--X--\r\n");
130
+ expect(res.status).toBe(200);
131
+ const { files } = (await res.json()) as { files: StoredFile[] };
132
+ expect(files[0]!.originalName).toBe("фото.txt");
133
+ });
134
+
128
135
  test("оборванный multipart — 400, процесс жив", async () => {
129
136
  // нет закрывающей границы: busboy эмитит error «Unexpected end of form»
130
137
  const res = await multipart(part("a.txt", "hello"));
@@ -27,6 +27,9 @@ export const handleUpload = async (req: Request, res: Response) => {
27
27
  const parser = busboy({
28
28
  headers: req.headers,
29
29
  limits: { fileSize: uploads.maxFileSize, files: 20 },
30
+ // браузеры шлют имя файла в UTF-8, а busboy по умолчанию читает его
31
+ // как latin1 — кириллица превращалась в «Ð¤Ð¾Ñ‚Ð¾»
32
+ defParamCharset: "utf8",
30
33
  });
31
34
 
32
35
  const saved: (StoredFile | StoredImage)[] = [];
package/src/images.ts CHANGED
@@ -83,8 +83,11 @@ export async function processImage(
83
83
  const sharp = await loadSharp();
84
84
  const source = sharp(buffer, { failOn: "none" }).rotate(); // EXIF-поворот → реальная ориентация
85
85
  const meta = await source.metadata();
86
- const width = meta.width ?? 0;
87
- const height = meta.height ?? 0;
86
+ // metadata() даёт размеры до EXIF-поворота, а варианты уже повёрнуты:
87
+ // для ориентаций 5–8 (поворот на 90°) стороны меняются местами
88
+ const rotated = (meta.orientation ?? 1) >= 5;
89
+ const width = (rotated ? meta.height : meta.width) ?? 0;
90
+ const height = (rotated ? meta.width : meta.height) ?? 0;
88
91
  const out: ProcessedVariant[] = [];
89
92
  for (const [name, spec] of Object.entries(variants)) {
90
93
  const format = spec.format ?? "webp";