Skip to content

Commit 2b33752

Browse files
committed
Improve attachment upload media type detection
1 parent e341190 commit 2b33752

4 files changed

Lines changed: 73 additions & 1 deletion

File tree

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,12 +58,14 @@
5858
"chalk": "^5.6.2",
5959
"cli-table3": "^0.6.5",
6060
"dayjs": "^1.11.20",
61+
"mime-types": "^3.0.2",
6162
"ora": "^9.3.0",
6263
"pretty-bytes": "^7.1.0",
6364
"semver": "^7.7.4",
6465
"string-width": "^8.2.0"
6566
},
6667
"devDependencies": {
68+
"@types/mime-types": "^3.0.1",
6769
"@types/node": "^24.12.0",
6870
"@types/semver": "^7.7.1",
6971
"@typescript/native-preview": "7.0.0-dev.20260318.1",

pnpm-lock.yaml

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/commands/attachment/__test__/attachment-entry.spec.ts

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,63 @@ test("tryRunAttachmentCommand dispatches upload subcommands from urls", async ()
148148
});
149149
});
150150

151+
test("tryRunAttachmentCommand infers media type for local file uploads", async () => {
152+
silenceStdout();
153+
154+
const uploadAttachmentForConsole = vi.fn().mockResolvedValue({
155+
data: {
156+
metadata: {
157+
name: "attachment-1",
158+
},
159+
spec: {
160+
displayName: "image.png",
161+
},
162+
status: {
163+
permalink: "https://example.com/image.png",
164+
},
165+
},
166+
});
167+
const runtimeMock = {
168+
getClientsForOptions: vi.fn().mockResolvedValue({
169+
profile: {
170+
baseUrl: "https://example.com",
171+
},
172+
clients: {
173+
axios: {},
174+
},
175+
}),
176+
};
177+
178+
const { AttachmentV1alpha1ConsoleApi } = await import("@halo-dev/api-client");
179+
vi.spyOn(AttachmentV1alpha1ConsoleApi.prototype, "uploadAttachmentForConsole").mockImplementation(
180+
uploadAttachmentForConsole,
181+
);
182+
183+
const fsPromises = await import("node:fs/promises");
184+
const tempFilePath = "/tmp/halo-cli-attachment-upload-image.png";
185+
await fsPromises.writeFile(tempFilePath, Buffer.from("png"));
186+
187+
try {
188+
await expect(
189+
tryRunAttachmentCommand(
190+
["attachment", "upload", "--file", tempFilePath, "--json"],
191+
runtimeMock as never,
192+
),
193+
).resolves.toBe(true);
194+
} finally {
195+
await fsPromises.unlink(tempFilePath).catch(() => undefined);
196+
}
197+
198+
expect(runtimeMock.getClientsForOptions).toHaveBeenCalledOnce();
199+
expect(uploadAttachmentForConsole).toHaveBeenCalledOnce();
200+
expect(uploadAttachmentForConsole.mock.calls[0]?.[0]).toMatchObject({
201+
file: expect.objectContaining({
202+
name: "halo-cli-attachment-upload-image.png",
203+
type: "image/png",
204+
}),
205+
});
206+
});
207+
151208
test("tryRunAttachmentCommand dispatches delete subcommands", async () => {
152209
silenceStdout();
153210

src/commands/attachment/index.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { basename } from "node:path";
44

55
import { AttachmentV1alpha1Api, AttachmentV1alpha1ConsoleApi } from "@halo-dev/api-client";
66
import cac, { type CAC } from "cac";
7+
import { lookup as lookupMimeType } from "mime-types";
78
import ora from "ora";
89
import prettyBytes from "pretty-bytes";
910

@@ -67,8 +68,9 @@ export function resolveAttachmentUploadSource(options: AttachmentUploadOptions):
6768
async function loadFileAsAttachment(filePath: string): Promise<File> {
6869
const normalizedPath = filePath.trim();
6970
const buffer = await readFile(normalizedPath);
71+
const mediaType = lookupMimeType(normalizedPath) || "application/octet-stream";
7072
return new File([buffer], basename(normalizedPath), {
71-
type: "application/octet-stream",
73+
type: mediaType,
7274
});
7375
}
7476

0 commit comments

Comments
 (0)