El servidor La ruta
La ruta
createDriveHandler recibe un Request y devuelve un Response. Todas las rutas del drive viven bajo una misma ruta, y ninguna transporta los bytes salvo en un disco: al navegador se le dan direcciones a las que enviarlos y desde las que leerlos.En esta página
En Next.js
app/api/files/[...path]/route.ts
import { byRoles, createDriveHandler, s3OptionsFrom, s3Storage, sqliteMetadata } from '@rebofiles/server';
import { session } from '@/lib/auth'; // your own
const handle = createDriveHandler({
storage: s3Storage(s3OptionsFrom(process.env)),
metadata: await sqliteMetadata('drive.sqlite'),
identify: async (request) => {
const user = await session(request);
return user ? { id: user.id, admin: user.isAdmin } : null;
},
authorize: byRoles,
secret: process.env.REBOFILES_SECRET!,
base: '/api/files',
});
export { handle as GET, handle as POST, handle as PATCH, handle as PUT, handle as DELETE };Sobre node:http
nodeHandler lo convierte en un listener, para node:http, Express y lo que esté construido encima.
server.ts
import { createServer } from 'node:http';
import { createDriveHandler, diskStorage, everyone, memoryMetadata, nodeHandler } from '@rebofiles/server';
const handle = createDriveHandler({
storage: diskStorage({ folder: './storage', secret: process.env.REBOFILES_SECRET! }),
metadata: memoryMetadata(),
...everyone(), // only on your own machine: no sign-in, everyone may do everything
secret: process.env.REBOFILES_SECRET!,
base: '/api/files',
});
createServer(nodeHandler(handle)).listen(3000);Todas las opciones
| Opción | Type | What it does |
|---|---|---|
| storage | Storage | Dónde están los bytes: s3Storage(s3OptionsFrom(process.env)), gcsStorage(…), azureStorage(…) o diskStorage({ folder, secret }). |
| metadata | MetadataStore | Dónde están las entradas: memoryMetadata(), sqliteMetadata(path) o postgresMetadata(pool). |
| identify | (request) => User | null | Quién pregunta, a partir de tu sesión; null responde 401. { id, admin: true } puede configurar el drive con byRoles. |
| authorize | (user, action, entry, drive) => boolean | Se consulta en cada ruta; false responde 403. byRoles, o reglas propias alrededor. |
| secret | string | Con qué se firman los tokens: largo, aleatorio, el mismo en cada proceso. |
| base | string | La ruta bajo la que están las rutas: /api/files. |
| top | 'own' | 'everyone' | Lo que muestra Mis archivos arriba del todo: lo de cada persona (por defecto), o todo lo que uno puede leer, para un solo drive de todo un equipo. |
| maxSize | number | El archivo más grande que se acepta, en bytes; 5 GiB si no se dice. |
| settings | Partial<DriveSettings> | Los valores por defecto hasta que alguien los cambie: idioma, tema, color de marca, imágenes, quota, trashDays, y company, el nombre que muestra la página de una solicitud de archivos. |
| cors | { origins: string[] } | Páginas de otros orígenes que pueden usar las rutas: la ventana de escritorio, una página de otro dominio. |
| onShare | (event) => void | Cada compartición guardada, con quién, por quién y si es la primera: para avisar a la persona. |
| beforeUpload | (upload, drive) => boolean | void | Se pregunta antes de dar direcciones a una subida, con su nombre, tipo, tamaño y carpeta: lanza un Refused, o devuelve false, para rechazarla. |
| inspect | (upload, drive) => boolean | void | Se pregunta cuando llegaron los bytes, antes de listar el archivo, con un read de ellos: checkType(), clamav() o el tuyo. Un rechazo quita los bytes. |
| live | false | { poll } | Los cambios dichos en /events en el momento; los de otro proceso sobre el mismo store, en poll ms (2000). false para ninguno. |
| derive | Derive | Lo que el servidor hace de un archivo guardado, para lo que la página no hizo: imágenes, un placeholder, su texto (de un PDF, un Word, un libro de Excel; de una imagen con ocr()). deriveAll() de @rebofiles/server/derive. |
| onChange | ({ activity, entry }) => void | Cada cosa hecha al drive, como la dice su actividad: para webhooks, una auditoría, otro índice, cobrar por espacio. |
| onComment | ({ comment, entry, mentions, by }) => void | Cada comentario, con a quién nombra con @: para avisarles. |
| onReceived | ({ entry, from, item, request, got }) => void | Cada archivo que llegó por una solicitud, con quién lo envió, para qué documento y lo que llegó hasta ahora: para avisar al dueño. |
| onReview | ({ entry, status, reason, from, by }) => void | Cada archivo aceptado o devuelto: para avisar a quien lo envió. |
| reminders | { send(reminder) } | A quien se le envió una solicitud, recordado cada remind días de lo que falta, y al momento: mailReminders({ mail: resend(…), url }), o el tuyo. |
| check | false | ({ entry, item, text }) => … | Lo escrito en lo que llegó, contra las words y find de su documento: checkWritten salvo el tuyo; false para ninguno. |
| expiring | false | { field, days, onExpiring } | Al dueño de un archivo cuyo campo expires llega en days (15) se le avisa en la campana, y onExpiring; false para nada. |
| onRead | ({ action, user, link, entries, path }) => void | Cada cosa abierta, vista o bajada: una carpeta listada, un archivo visto o descargado, un .zip; por alguien o por un enlace. Para una auditoría. |
| people | { search(query, user), names?(ids, user) } | Quién es quién, de tu directorio: las personas y los grupos que coinciden con lo escrito al compartir, y sus nombres, que se muestran en lugar de los ids. |
| logger | Logger | Dónde se escribe lo que salió mal y no se respondió: pino(), console si no se da. |
| onRequest | (done) => void | Tras cada petición, su ruta, estado, tiempo y quién: para métricas, como openTelemetry(meter). |
| limits | Limits | false | Cuántas subidas, archivos .zip, búsquedas de texto, contraseñas erróneas de un enlace y peticiones puede hacer cada uno; un 429 pasado eso. |
| limiter | Limiter | Dónde se guardan las cuentas de limits: en el proceso si no se da; Redis para más de uno. |
| clientIp | (request) => string | La dirección de quien pregunta, para contar también por ella las contraseñas erróneas de un enlace. |
| now | () => Date | El reloj, para tests. |
| newId | () => string | Los ids de las entradas nuevas; UUID aleatorios si no se da. |
Guardado en memoria
El drive se lee una vez y se guarda, y solo se vuelve a leer cuando el almacén dice que cambió, por este proceso o por otro: un listado de 20 000 entradas pasó de 36 ms a menos de 1. Suficiente para un equipo y mucho más; no para millones de entradas.
Todas las rutas
Rutas HTTP las enumera, tal como las guarda el código.