fix(worker): recognize native 7z multipart volumes (.7z.001, .7z.002, ...)
continuous-integration/drone/push Build is passing

detectArchive() had multipart patterns for ZIP and RAR but none for 7z's
own volume-split naming, so files like "Name.7z.001" matched nothing and
were dropped before ever reaching grouping or the skipped-package
bookkeeping — no Package row, no SkippedPackage row, no log line.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JMm2E4ecmATJo8HuBx92NP
This commit is contained in:
2026-08-21 16:50:41 +02:00
co-authored by Claude Sonnet 5
parent d8e01f3398
commit f6381e3178
2 changed files with 48 additions and 1 deletions
+39
View File
@@ -0,0 +1,39 @@
import { describe, it, expect } from "vitest";
import { detectArchive, isArchiveAttachment } from "./detect.js";
describe("detectArchive — 7z numbered multipart (pack.7z.001, pack.7z.002, ...)", () => {
it("recognizes a 7z multipart part as an archive attachment", () => {
expect(isArchiveAttachment("Lost Adventures Vol2.7z.001")).toBe(true);
});
it("extracts format, baseName, and partNumber", () => {
const info = detectArchive("Lost Adventures Vol2.7z.001");
expect(info).toEqual({
baseName: "Lost Adventures Vol2.7z",
partNumber: 1,
format: "7Z",
pattern: "SEVENZ_NUMBERED",
});
});
it("groups multiple parts under the same baseName + format key regardless of part number", () => {
const part1 = detectArchive("Lost Adventures Vol2.7z.001");
const part2 = detectArchive("Lost Adventures Vol2.7z.010");
expect(part1?.baseName).toBe(part2?.baseName);
expect(part1?.format).toBe(part2?.format);
expect(part2?.partNumber).toBe(10);
});
it("is case-insensitive on the .7z extension", () => {
expect(detectArchive("Archive.7Z.002")?.format).toBe("7Z");
});
it("still recognizes a standalone single .7z file", () => {
expect(detectArchive("Single Pack.7z")).toEqual({
baseName: "Single Pack",
partNumber: -1,
format: "7Z",
pattern: "SINGLE",
});
});
});
+9 -1
View File
@@ -4,7 +4,7 @@ export interface MultipartInfo {
baseName: string;
partNumber: number;
format: ArchiveFormat;
pattern: "ZIP_NUMBERED" | "ZIP_LEGACY" | "RAR_PART" | "RAR_LEGACY" | "SINGLE";
pattern: "ZIP_NUMBERED" | "ZIP_LEGACY" | "RAR_PART" | "RAR_LEGACY" | "SEVENZ_NUMBERED" | "SINGLE";
}
const patterns: {
@@ -46,6 +46,14 @@ const patterns: {
getBaseName: (m) => m[1],
getPartNumber: (m) => parseInt(m[2], 10),
},
// pack.7z.001, pack.7z.002 (native 7z volume split)
{
regex: /^(.+\.7z)\.(\d{3,})$/i,
format: "7Z",
pattern: "SEVENZ_NUMBERED",
getBaseName: (m) => m[1],
getPartNumber: (m) => parseInt(m[2], 10),
},
];
/** Extensions we recognize as fetchable documents (archives + standalone files) */