> ## Documentation Index
> Fetch the complete documentation index at: https://docs.squarecloud.app/llms.txt
> Use this file to discover all available pages before exploring further.

# Migración a v4

> Qué cambió en @squarecloud/blob 4.0.0: una política de reintentos más segura, menos reintentos por defecto, un SavedRule.active_from opcional y un borrado por lotes coherente con un solo id.

La versión 4.0.0 cambia **cómo reintenta el SDK**, para que solo repita lo que es seguro repetir. **No se ha renombrado ni eliminado ningún método, opción ni export.**

## Requisitos

Sin cambios: **Node.js 20** o más reciente, o un navegador; ESM y CommonJS.

## Resumen de cambios incompatibles

| v3.x                                                     | v4.x                                                                               |
| -------------------------------------------------------- | ---------------------------------------------------------------------------------- |
| Se reintenta el `429`                                    | **Nunca se reintenta** (salvo `TOO_MANY_CONCURRENT_CHUNKS` en una parte multipart) |
| Las escrituras se reintentan ante errores de red y `5xx` | Las escrituras tienen **un único intento**                                         |
| Solo se reintenta ante `500` y `503`                     | Se reintenta ante **cualquier `5xx`** (lecturas y partes multipart)                |
| `maxRetries` por defecto `5`                             | Por defecto **`2`**                                                                |
| Backoff con un máximo de 30 s                            | Máximo de **8 s**: `min(8 s, 500 ms · 2^n) · U(0.5, 1)`                            |
| `SavedRule.active_from: string`                          | `active_from?: string` (**opcional**)                                              |
| `delete([id])` con un solo id lanza `PREFIX_NOT_ALLOWED` | Lo indica en `failed`                                                              |
| `RATE_LIMIT` en `BlobErrorCode`                          | **Obsoleto** (sigue en el tipo)                                                    |

## El `429` ya no se reintenta

`RATE_LIMITED` cubre tanto una ventana por ruta como un bloqueo de cuenta o de IP que puede durar unos 30 minutos, así que el SDK ya no lo reintenta. Esto incluye el límite de subidas simples y `TOO_MANY_CONCURRENT_UPLOADS`. Gestiónalo tú mismo y espera antes de volver a intentarlo:

```typescript theme={"system"}
import { SquareCloudBlobError } from "@squarecloud/blob";

try {
    await blob.put(file, { name: "report" });
} catch (error) {
    if (error instanceof SquareCloudBlobError && error.code === "RATE_LIMITED") {
        // back off: queue the job for later instead of retrying right away
    }
    throw error;
}
```

La única excepción es `TOO_MANY_CONCURRENT_CHUNKS` en una parte multipart: el servidor rechaza la parte antes de leerla, así que el SDK la vuelve a enviar dentro de `maxRetries`.

## Las escrituras tienen un único intento

Los errores de red y los `5xx` ahora solo se reintentan en las llamadas `GET` y en las partes de las subidas multipart. Estas llamadas tienen **un solo intento**:

* `put()` simple, y el inicio, la finalización y el aborto de una subida multipart;
* `update()`, `copy()`, `move()`, `delete()`;
* `rules.set()`, `uploadTokens.create()`, `shares.create()`, `shares.revoke()`.

Reintenta una escritura por tu cuenta solo cuando repetirla sea seguro para ti, por ejemplo un `put()` al mismo nombre con `overwrite: true`. Consulta [Reintentar escrituras por tu cuenta](/es/sdks/blob/errors#reintentar-escrituras-por-tu-cuenta).

## Menos reintentos, backoff más corto

`maxRetries` ahora vale `2` por defecto (antes `5`), y el backoff tiene un máximo de 8 segundos (antes 30). Para mantener el presupuesto anterior en las lecturas y las partes multipart:

```typescript theme={"system"}
const blob = new SquareCloudBlob(process.env.SQUARECLOUD_API_KEY, { maxRetries: 5 });
```

Esto no recupera los reintentos del `429` ni los de las escrituras.

## `SavedRule.active_from` es opcional

La API solo envía `active_from` en las reglas con `delete_after_days`. En TypeScript, ten en cuenta el caso `undefined`:

```typescript theme={"system"}
const rules = await blob.rules.get();

for (const rule of rules) {
    if (rule.active_from) {
        console.log(`${rule.prefix} starts deleting at ${rule.active_from}`);
    }
}
```

## `delete([id])` con un solo id

Un lote con un solo id ahora indica `PREFIX_NOT_ALLOWED` en `failed`, como cualquier otro lote, en lugar de lanzar un error:

```typescript theme={"system"}
// v3: threw SquareCloudBlobError (PREFIX_NOT_ALLOWED)
// v4:
const { failed } = await blob.delete([id]);
// failed: [{ id, code: "PREFIX_NOT_ALLOWED" }]
```

`delete(id)` con un string simple sigue lanzando el error.

## `RATE_LIMIT` está obsoleto

El servicio ya no envía `RATE_LIMIT`: el bloqueo de cuenta o de IP es `RATE_LIMITED`. El código antiguo se mantiene en `BlobErrorCode` para que las comparaciones existentes sigan compilando; cámbialas a `RATE_LIMITED`. Se ha añadido `DUPLICATE_RULE_PREFIX`.

## Correcciones

* Un cuerpo de respuesta cortado a mitad de lectura ahora es un **error de red**: se reintenta en las llamadas `GET` y en las partes multipart, y en los demás casos se lanza el error original de `fetch` (antes era `UNKNOWN_ERROR`).
* Una subida multipart fallida ahora **espera a las partes que aún están en curso** antes de abortar, para que ninguna parte llegue después del aborto y ninguna petición sobreviva a `put()`.

## Lista de comprobación

<Steps>
  <Step title="Gestiona el 429 tú mismo">
    Captura `RATE_LIMITED` y espera antes de reintentar; el SDK ya no lo reintenta.
  </Step>

  <Step title="Revisa las escrituras">
    Añade tu propio reintento solo a las escrituras que sea seguro repetir.
  </Step>

  <Step title="Elige un presupuesto de reintentos">
    Pasa `{ maxRetries: 5 }` si dependías del número anterior de intentos en las lecturas y las partes multipart.
  </Step>

  <Step title="Actualiza los tipos">
    Ten en cuenta que `active_from` puede ser `undefined`, y reemplaza `RATE_LIMIT` por `RATE_LIMITED`.
  </Step>
</Steps>
