Scopes — el contrato

Declara una vez a dónde va un archivo, quién puede leerlo, qué tamaño admite y qué reemplaza. Ambos lados validan contra la misma definición.

Scopes — el contrato

Un scope es un destino con nombre: la única fuente de verdad sobre dónde aterriza un archivo, quién puede leerlo y qué se acepta ahí. El registro es un objeto plano que importan el cliente y el servidor, y eso es lo que hace que las dos validaciones coincidan por construcción.

Definir scopes

import { defineScopes, MB } from 'uploaderkit'

export const scopes = defineScopes({
	'user-avatar': {
		path: userId => `Users/${userId}/avatar`,
		visibility: 'public',
		accept: ['png', 'jpg', 'jpeg', 'webp'],
		maxBytes: 5 * MB,
		category: 'image',
		compress: { maxWidth: 512, quality: 0.8, stripExif: true },
	},
})
CampoSignificado
path(entityId, file) => string — la key de almacenamiento. Tú controlas colisiones y forma de carpetas.
visibility'public' (URL directa) o 'private' (solo URL firmada con expiración).
acceptExtensiones permitidas aquí. Más angosto que el preset de la categoría, nunca más ancho.
maxBytesTope duro. Se exportan los helpers KB / MB / GB.
category'image' | 'pdf' | 'document' | 'data' | 'video' | 'audio' | 'certificate' | 'key' | 'any'. Elige el preset que decide si se leen los magic numbers.
encryptEntrega los bytes al cipher de la app antes de que salgan del servidor.
compressPipeline de imagen en el cliente: maxWidth, maxHeight, quality, stripExif (por defecto true).
maxFilesCuántos archivos puede tener una entidad aquí. Default 1; el uploader deriva multiple de esto.
replaceQué borra una subida. Derivado por default — ver Replace.
prefix(entityId) => string — objetos que un replace 'entity' puede borrar. Default: la carpeta de la key resuelta.
metadataEtiquetas libres que se reenvían al provider cuando las soporta.

defineScopes devuelve un ScopeRegistry: names, get(name), has(name) y accept(name) — este último es el string listo para <input accept>.

Replace — nunca dejar un archivo muerto

El object storage no limpia solo. Un scope cuya key incluye el nombre del archivo escribe un objeto NUEVO cada vez, así que re-subir un logo deja el anterior pagando renta para siempre. replace decide eso, y su default se deriva para que no haya prop que olvidar:

El scopereplace derivadoPor qué
maxFiles: 1 (default), la key lleva file.name'entity'Cada subida cae en una key nueva — hay que barrer la anterior.
maxFiles: 1, la key ignora file.name'key'La key es estable; el provider ya sobrescribe en su lugar.
maxFiles > 1'key'Es una colección: los hermanos son el punto.

Declararlo explícito solo sirve para salirse: replace: false conserva todas las versiones.

El barrido 'entity' corre después de un put exitoso y borra todo lo que esté bajo el prefijo de la entidad y no sea la key nueva. Dos guardas evitan que alcance de más, ambas al momento de defineScopes:

  • replace: 'entity' junto con maxFiles > 1 truena. Un scope no puede guardar una colección y borrarla en cada subida.
  • Dos scopes cuyas carpetas se solapan truenan si alguno barre, así que subir un avatar nunca puede borrar los documentos del mismo usuario. Dale a cada uno su carpeta, o acota uno con prefix.

On this page