getFile
Fetches a single file document by its _id. Use it when you have a file id (from a user's avatar, a PO attachment, or a getFiles list) and want the full metadata โ and optionally the uploader snapshot. Open to all authenticated roles.
Import alias
The code below imports the framework as lesan โ that's the path alias this repo's app uses (see Project Layout). In your own project, import from @hemedani/lesan (npm/Bun) or jsr:@hemedani/lesan (Deno) instead.
Registration (mod.ts)โ
import { grantAccess, setTokens, setUser } from "@lib";
import { coreApp } from "../../../mod.ts";
import { getFileFn } from "./getFile.fn.ts";
import { getFileValidator } from "./getFile.val.ts";
export const getFileSetup = () =>
coreApp.acts.setAct({
schema: "file",
actName: "getFile",
preAct: [setTokens, setUser, grantAccess([{ roles: ["Manager", "Admin", "OrgHead", "UnitHead", "Employee", "Ordinary"] }])],
validator: getFileValidator(),
fn: getFileFn,
});
The validator (getFile.val.ts)โ
import { object, objectIdValidation } from "lesan";
import { selectStruct } from "../../../mod.ts";
import { activeRoleMixin } from "@lib";
export const getFileValidator = () => {
return object({
set: object({
...activeRoleMixin,
_id: objectIdValidation,
}),
get: selectStruct("file", 2),
});
};
setis justactiveRoleId+_id;objectIdValidationenforces a 24-hex-char ObjectId string.getisselectStruct("file", 2)โ depth 2, so you can project theuploaderrelation snapshot too, e.g.uploader: { _id: 1, first_name: 1 }.
The implementation (getFile.fn.ts)โ
import { type ActFn, ObjectId } from "lesan";
import { file } from "../../../mod.ts";
import { throwError } from "@lib";
export const getFileFn: ActFn = async (body) => {
const {
set: { _id },
get,
} = body.details;
const foundedFile = await file.findOne({
filters: { _id: new ObjectId(_id as string) },
projection: get,
});
!foundedFile && throwError("file not found");
return foundedFile;
};
_idcomes in as a string from JSON;new ObjectId(_id)converts it.file.findOneapplies the client'sgetprojection โ only the requested fields (and nested relation fields) come back.- A missing document is a hard error:
throwError("file not found"). The response becomes{ success: false, body: { message: "file not found" } }.
In the workflowโ
This is the detail view for a file picked from the getFiles list. uploader gives you the person who uploaded it without a second request.
- file model
- Sibling acts: uploadFile, getFiles, removeFile
Run itโ
curl http://localhost:1380/lesan \
-H "Content-Type: application/json" \
-H "token: <jwt>" \
-d '{
"model": "file",
"act": "getFile",
"details": {
"set": { "activeRoleId": "ghost-role", "_id": "<fileId>" },
"get": { "_id": 1, "name": 1, "mimeType": 1, "uploader": { "_id": 1, "first_name": 1 } }
}
}'
Errors & fixesโ
| Error | Meaning | Fix |
|---|---|---|
file not found | No file has that _id. | Check the id โ get it from an uploadFile/getFiles response. |
activeRoleId is required | No activeRoleId in set. | Add it (ghost: any string, e.g. "ghost-role"). |
Active role not found | activeRoleId isn't one of the user's roles. | Pass a real roleId from the user's roles. |
You cant do this | Active role not in the allowed list. | Use an allowed role or the ghost. |
Invalid or expired token / you should send your id with token key in req header | Auth header problem. | Send token: <jwt>; re-login if expired. |
| superstruct "expected ObjectId-like string" | _id isn't a valid ObjectId. | Send the 24-hex id string. |