file-service: frontend service \u2014 blob_id type, supplier_id upload param, keep_blob delete, purgeSoftDeletedBlobs admin

This commit is contained in:
Yashwin 2026-06-01 10:58:56 +05:30
parent 0a672619ea
commit e2bc2254a6

View File

@ -30,6 +30,8 @@ export interface FileAttachment {
version: number;
is_current_version: boolean;
previous_version_id: string | null;
/** Reference to the physical file blob (dedup model) */
blob_id: string | null;
is_public: boolean;
access_level: string;
download_count: number;
@ -136,6 +138,8 @@ export interface UploadFilesParams {
files: File[];
entity_type: string; // required
entity_id: string; // required — must be valid UUID
/** UUID from the suppliers table. When provided, file deduplication is scoped to this supplier. */
supplier_id?: string | null;
category?: string; // optional string label
category_id?: string; // optional
description?: string; // max 500 chars
@ -226,6 +230,7 @@ export const fileAttachmentService = {
formData.append('file', params.files[0]);
formData.append('entity_type', params.entity_type);
formData.append('entity_id', params.entity_id);
if (params.supplier_id) formData.append('supplier_id', params.supplier_id);
if (params.category) formData.append('category', params.category);
if (params.category_id) formData.append('category_id', params.category_id);
if (params.description) formData.append('description', params.description);
@ -245,6 +250,7 @@ export const fileAttachmentService = {
params.files.forEach((file) => formData.append('files', file));
formData.append('entity_type', params.entity_type);
formData.append('entity_id', params.entity_id);
if (params.supplier_id) formData.append('supplier_id', params.supplier_id);
if (params.category) formData.append('category', params.category);
if (params.category_id) formData.append('category_id', params.category_id);
if (params.description) formData.append('description', params.description);
@ -267,9 +273,18 @@ export const fileAttachmentService = {
return response.data;
},
/** DELETE /files/:id */
delete: async (id: string, hard = false): Promise<{ success: boolean }> => {
const response = await apiClient.delete(`/files/${id}`, { params: { hard } });
/**
* DELETE /files/:id
* @param hard - true: remove reference row from DB; false (default): soft-delete
* @param keepBlob - true: keep binary on disk even if last reference (Layer 3)
*/
delete: async (id: string, hard = false, keepBlob = false): Promise<{ success: boolean }> => {
const response = await apiClient.delete(`/files/${id}`, {
params: {
...(hard && { hard: 'true' }),
...(keepBlob && { keep_blob: 'true' }),
},
});
return response.data;
},
@ -387,6 +402,18 @@ export const fileAttachmentService = {
}>(`/files/${id}/content`);
return response.data;
},
/**
* POST /files/blobs/purge-soft-deleted admin only.
* Purges soft-deleted blobs with zero references older than olderThanHours.
* @param olderThanHours - 0 means purge all eligible blobs regardless of age.
*/
purgeSoftDeletedBlobs: async (olderThanHours = 0): Promise<{ success: boolean; data: { purged: number } }> => {
const response = await apiClient.post('/files/blobs/purge-soft-deleted', null, {
params: olderThanHours > 0 ? { older_than_hours: olderThanHours } : {},
});
return response.data;
},
};
export default fileAttachmentService;