# Object Storage API

A [Functions](/pt-br/documentacao/produtos/build/applications/functions/) Storage API é uma interface que permite o acesso ao Azion Object Storage. Através dessa interface, é possível ler e escrever dados no storage e seus buckets.

---

## Instanciação da classe

Para a utilização dessa API, é necessário importar e instanciar a classe `Storage`, passando o nome do bucket.

### Sintaxe

Importação:

```javascript
import Storage from "azion:storage";
```

Instanciação:

```js
const storage = new Storage(bucket);
```

### Parâmetros

| Parâmetro | Tipo   | Descrição                                                                                                                                                         |
| ---------- | ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `bucket`   | String | Nome de um bucket |

:::note 
A criação de um **bucket** é realizada durante um deploy de uma aplicação estática através da [Azion CLI](/pt-br/documentacao/produtos/azion-cli/visao-geral/) ou através de requições na [API da Azion](https://api.azion.com/).
:::

### Valor de Retorno

Objeto `Storage` usado para acessar o Object Storage.

---

## Métodos

### `async storage.put`

O método `Storage.put` é usado para inserir um novo objeto no storage.

:::note
Este é um método assíncrono e deve ser usado com `await` ou `event.waitUntil`.
:::

#### Sintaxe

```js
async Storage.put(key, value, options)
```

#### Parâmetros

| Parâmetro | Tipo             | Descrição                                                                                             |
| --------- | --------------- | ----------------------------------------------------------------------------------------------------- |
| `key` | String  | Identificador que permite a busca por um objeto no storage |
| `value` | ArrayBuffer ou ReadableStream | Conteúdo do objeto sendo armazenado. No caso de `value` implementar um [ReadableStream](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream), as APIs de Stream podem ser usadas e a opção `content-length` é obrigatória |
| `options` | Object | Os atributos `options` são descritos na tabela abaixo |

**options**

Para passar o parâmetro `options`, você deve fornecer um objeto com os seguintes atributos:

| Atributo          | Tipo   | Descrição                                                                                                                                                        |
| ----------------- | ------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `content-type` | String | O `content-type` do objeto sendo criado. É semelhante ao cabeçalho HTTP `content-type` e descreve como o conteúdo do Object Storage deve ser tratado. `content-type` é opcional. O valor padrão é `application/octet-stream` |
| `content-length` | String | O tamanho do objeto a ser criado, em bytes. É obrigatório quando o valor é ReadableStream |
| `metadata` | Object | Qualquer objeto JavaScript contendo informações sobre o objeto que será armazenado no Storage. Todas as propriedades do objeto devem ser strings |

#### Retorno

| Sucesso          | Erro                      |
| ---------------- | ------------------------- |
| Nenhuma resposta | Lança um `StorageError`    |

#### Exemplo de Código

1. Para persistir o corpo da requisição:

```js
import Storage from "azion:storage";

async function handleRequest(event) {
    try{
        const bucket = "meubucket";
        const storage = new Storage(bucket);
        const key = "teste";
        const inputStream = event.request.body;
        let contentLength = event.request.headers.get("content-length");
        await storage.put(key, inputStream, { "content-length": contentLength });
        return new Response("OK");
    }catch(error){
        return new Response(error, {status:500});
    }
}

addEventListener("fetch", (event) => {
    event.respondWith(handleRequest(event));
});
```

2. Para persistir um objeto JSON:

```js
import Storage from "azion:storage";

async function handleRequest(event) {
    try{
        const bucket = "meubucket";
        const storage = new Storage(bucket);
        const key = "teste";
        const data = JSON.stringify({
            nome:"João",
            endereco:"Abbey Road"
        });
        const buffer = new TextEncoder().encode(data);
        await storage.put(key, buffer);
        return new Response("OK");
    }catch(error){
        return new Response(error, {status:500});
    }
}

addEventListener("fetch", (event) => {
    event.respondWith(handleRequest(event));
});
```

3. Para salvar um JSON com metadados:

```js
import Storage from "azion:storage";

async function handleRequest(event) {
    try{
        const bucket = "meubucket";
        const storage = new Storage(bucket);
        const key = "teste2";
        const data = JSON.stringify({
            nome:"Paulo",
            endereco:"Abbey Road"
        });
        const buffer = new TextEncoder().encode(data);
        const options = { "content-type": "application/json",
                          "metadata": {
                            info:"informação de teste",
                            contador: "1",
                          }}
        await storage.put(key, buffer, options);
        return new Response("OK");
    }catch(error){
        return new Response(error, {status:500});
    }
}

addEventListener("fetch", (event) => {
    event.respondWith(handleRequest(event));
});
```

---

### `async storage.get(key)`

O método `storage.get(key)` é usado para recuperar um objeto.

:::note
O método é assíncrono e deve ser usado com `await` ou `event.waitUntil`.
:::

#### Sintaxe

```js
async storage.get(key)
```

#### Parâmetros

| Parâmetro | Tipo   | Descrição                                                                                          |
| --------- | ------ | -------------------------------------------------------------------------------------------------- |
| `key` | String | Identificador que permite a busca por um objeto no bucket |

#### Retorno

| Sucesso                                          | Erro                       |
| ------------------------------------------------ | -------------------------- |
| Retorna um objeto da classe `StorageObject`       | Lança um `StorageError`    |

#### Exemplo de Código

1. Para recuperar e retornar o conteúdo do storage:

```js
import Storage from "azion:storage";

async function handleRequest(event) {
    try{
        const bucket = "meubucket";
        const storage = new Storage(bucket);
        const key = "teste";
        const storageObject = await storage.get(key);
        return new Response(storageObject.content);
    }catch(error){
        return new Response(error, {status:500});
    }
}

addEventListener("fetch", (event) => {
    event.respondWith(handleRequest(event));
});
```

2. Para obter um JSON do storage:

```js
import Storage from "azion:storage";

async function handleRequest(event) {
    try{
        const bucket = "meubucket";
       

 const storage = new Storage(bucket);
        const key = "teste";
        const storageObject = await storage.get(key); 
        const data = new TextDecoder().decode(await storageObject.arrayBuffer());
        return new Response(data);
    }catch(error){
        return new Response(error, {status:500});
    }
}

addEventListener("fetch", (event) => {
    event.respondWith(handleRequest(event));
});
```

3. Para ler os metadados de um objeto:

```js
import Storage from "azion:storage";

async function handleRequest(event) {
    try{
        const bucket = "meubucket";
        const storage = new Storage(bucket);
        const key = "teste2";
        const storageObject = await storage.get(key);
        return new Response(storageObject.metadata.get("info"));   
    }catch(error){
        return new Response(error, {status:500});
    }
}

addEventListener("fetch", (event) => {
    event.respondWith(handleRequest(event));
});
``` 

---

### `async storage.delete(key)`

O `Storage.delete(key)` é usado para remover um objeto do Object Storage.

:::note
O método é assíncrono e deve ser usado com `await` ou `event.waitUntil`.
:::

#### Sintaxe

```js
async Storage.delete(key)
```

#### Parâmetros

| Parâmetro | Tipo   | Descrição                                                                                          |
| --------- | ------ | -------------------------------------------------------------------------------------------------- |
| `key` | String | Identificador que permite a busca por um objeto no bucket  |

#### Retorno

| Sucesso                                            | Erro                       |
| -------------------------------------------------- | -------------------------- |
| Nenhuma resposta     | Lança um `StorageError`    |

#### Exemplo de Código

1. Para excluir um objeto armazenado no Object Storage:

```js
import Storage from "azion:storage";

async function handleRequest(event) {
    const bucket = "meubucket";
    const storage = new Storage(bucket);
    const key = "teste";
    try{
        await storage.delete(key);
    }catch(error){
        return new Response(error, {status:500});
    }
    return new Response("Ok");
}

addEventListener("fetch", (event) => {
    event.respondWith(handleRequest(event));
});
```

---

### `async storage.list()`

O método `Storage.list()` é usado para listar todos os objetos pertencentes ao `bucket` específico.

:::note
O método é assíncrono e deve ser usado com `await` ou `event.waitUntil`.
:::

#### Sintaxe 

```js
await storage.list()
```

#### Retorno

| Sucesso       | Erro                       |
| ------------- | -------------------------- |
| Retorna StorageObjectList | Lança um `StorageError`    |

#### Exemplo de Código

1. Listando objetos do Object Storage:

```js
import Storage from "azion:storage";

async function handleRequest(event) {
    try{
        const bucket = "meubucket";
        const storage = new Storage(bucket);
        const objectsList = await storage.list();
        for (const entry of objectsList.entries) {
            console.log(`chave: ${entry.key} tamanho: ${entry.content_length}`);
        }
        return new Response("Ok");   
    }catch(error){
        return new Response(error, {status:500});
    }
}

addEventListener("fetch", (event) => {
    event.respondWith(handleRequest(event));
});
```
---

### Métodos da Classe `StorageObject`

| Método                                      | Descrição                                                                                                         |
| ------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ |
| `StorageObject.content` | Propriedade de leitura contendo um ReadableStream para o conteúdo armazenado no storage |
| `async StorageObject.arrayBuffer()` | Função assíncrona que retorna um ArrayBuffer com o conteúdo armazenado no storage. Este método consome o ReadableStream da propriedade de content |
| `StorageObject.metadata` | Propriedade de leitura contendo um [objeto Map](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map) com os metadados do objeto armazenados no storage |
| `StorageObject.contentType` | Propriedade de leitura contendo o `content-type` do conteúdo armazenado no storage |
| `StorageObject.contentLength` | Propriedade de leitura contendo o tamanho em bytes do conteúdo armazenado no storage |