59 lines
2.1 KiB
TypeScript
59 lines
2.1 KiB
TypeScript
import type { UploadedFile } from "./upload.ts";
|
|
|
|
export function formatFileSize(bytes: number, locale = "en"): string {
|
|
const value = Math.max(0, Number(bytes) || 0);
|
|
if (value < 1_024) return `${value} B`;
|
|
const units = ["KB", "MB", "GB", "TB"];
|
|
let current = value / 1_024;
|
|
let unit = units[0]!;
|
|
for (let index = 1; index < units.length && current >= 1_024; index++) {
|
|
current /= 1_024;
|
|
unit = units[index]!;
|
|
}
|
|
return `${new Intl.NumberFormat(locale, { maximumFractionDigits: current < 10 ? 1 : 0 }).format(current)} ${unit}`;
|
|
}
|
|
|
|
export function uploadAccept(value: string | readonly string[]): string {
|
|
return (typeof value === "string" ? value.split(",") : [...value])
|
|
.map((entry) => entry.trim())
|
|
.filter(Boolean)
|
|
.join(",");
|
|
}
|
|
|
|
export function uploadedFileMap(files: readonly UploadedFile[]): Record<string, UploadedFile> {
|
|
return Object.fromEntries(files.map((file) => [file.key, file]));
|
|
}
|
|
|
|
export function uploaderAttributes(
|
|
options: {
|
|
store?: string;
|
|
endpoint?: string;
|
|
accept?: string | readonly string[];
|
|
maxBytes?: number;
|
|
multiple?: boolean;
|
|
field?: string;
|
|
label?: string;
|
|
} = {},
|
|
): Record<string, string | boolean> {
|
|
return {
|
|
"data-uploader": options.store ?? "default",
|
|
"data-endpoint": options.endpoint ?? "/api/upload",
|
|
...(options.accept ? { "data-accept": uploadAccept(options.accept) } : {}),
|
|
...(options.maxBytes ? { "data-max": String(options.maxBytes) } : {}),
|
|
...(options.multiple ? { "data-multiple": true } : {}),
|
|
...(options.field ? { "data-field": options.field } : {}),
|
|
...(options.label ? { "data-label": options.label } : {}),
|
|
};
|
|
}
|
|
|
|
export function assertUploadedFiles(
|
|
files: readonly UploadedFile[],
|
|
options: { min?: number; max?: number } = {},
|
|
): readonly UploadedFile[] {
|
|
const min = Math.max(0, options.min ?? 0);
|
|
const max = Math.max(min, options.max ?? Number.POSITIVE_INFINITY);
|
|
if (files.length < min) throw new Error(`WRN-UPLOAD-MIN-FILES: expected at least ${min}`);
|
|
if (files.length > max) throw new Error(`WRN-UPLOAD-MAX-FILES: expected at most ${max}`);
|
|
return files;
|
|
}
|