Skip to main content

The File Model

The file model manages uploads — images, videos, and documents — with type-based directory routing, size limits, and mime validation. Source: back/models/file.ts.

export const file_type_enums = enums(["image", "video", "docs"]);

export const file_pure = {
name: string(),
mimeType: string(),
size: number(),
type: file_type_enums, // image | video | docs
alt_text: optional(string()),
...createUpdateAt,
};

Pure fields

FieldTypeNotes
namestring()original filename; text-indexed
mimeTypestring()e.g. image/png
sizenumber()bytes; validated at upload
typeenums(["image","video","docs"])routes the file to /uploads/{type}/
alt_textoptional(string())accessibility text; text-indexed

Relations

export const file_relations = {
uploader: {
schemaName: "user",
type: "single" as RelationDataType,
optional: false,
excludes: user_excludes,
relatedRelations: {
files: { type: "multiple" as RelationDataType, limit: 50, excludes: file_excludes },
},
},
};

Files are owned by the user who uploaded them (uploader → reverse files list). Everywhere else a file appears (user avatar, report documentFiles, blog coverImage, hero slide image), the relation is one-directional — defined on the other model with relatedRelations: {}, so files never accumulate duplicate back-lists.

The upload act

Uploading is multipart, not JSON. Lesan parses the form and the file lands in details.set.formData:

// src/file/uploadFile/uploadFile.fn.ts
export const uploadFileFn: ActFn = async (body) => {
const { set } = body.details;
const file = set.formData; // the parsed upload
// validate type + size, route to /uploads/{type}/, insert metadata
return await file.insertOne({ doc: { name, mimeType, size, type, ... }, projection: get });
};

Acts

get, gets, update, uploadFile, getFiles (by array of IDs — used to hydrate report document lists).

Next: Location Models.