# Como gerenciar KV Store com Functions

import DocButton from '~/components/webkit/DocButton.vue';

Este guia mostra como interagir com o KV Store a partir de suas Functions 
para armazenar, recuperar e excluir dados chave-valor.

<DocButton href="/pt-br/documentacao/produtos/store/kv-store/" label="Ir para referência do KV Store" kind="secondary" size="medium" />

---

## Requisitos 

Antes de começar, certifique-se de ter:

- [Functions habilitadas](/pt-br/documentacao/produtos/build/applications/functions/) em sua Application.
- Um namespace do KV Store criado via Console ou API.

---

## Criando uma função para interagir com o KV Store

Siga estes passos para criar uma function que se comunica com o KV Store:

1. Acesse o [Azion Console](https://console.azion.com).
2. No canto superior esquerdo, selecione **Functions**.
3. Clique em **+ Function**.
4. Digite um nome para sua função, por exemplo: `kv-store-handler`.
5. Exclua o código placeholder no editor.
6. Cole um dos exemplos de código abaixo de acordo com seu caso de uso.

---

## Armazenando dados

Este exemplo demonstra como armazenar diferentes tipos de dados no KV Store:

```javascript
async function handleRequest(request) {
    const kv = new Azion.KV();

    // Armazenar uma string simples
    await kv.put("saudacao", "Olá, Mundo!");

    // Armazenar um objeto JSON
    await kv.put("preferencias-usuario", {
        tema: "escuro",
        idioma: "pt-br",
        notificacoes: true
    });

    // Armazenar com metadados e expiração
    await kv.put("token-sessao", "abc123xyz", {
        metadata: { userId: "user-42" },
        expirationTtl: 3600 // expira em 1 hora
    });

    return new Response("Dados armazenados com sucesso", {
        headers: { "Content-Type": "text/plain" },
        status: 200
    });
}

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

---

## Recuperando dados

Este exemplo mostra como recuperar dados em diferentes formatos:

```javascript
async function handleRequest(request) {
    const kv = new Azion.KV();

    // Obter como texto (padrão)
    const saudacao = await kv.get("saudacao", "text");

    // Obter como objeto JSON
    const preferencias = await kv.get("preferencias-usuario", "json");

    // Tratar chaves inexistentes
    const inexistente = await kv.get("chave-inexistente", "text");
    if (inexistente === null) {
        console.log("Chave não encontrada");
    }

    const response = {
        saudacao,
        preferencias,
        chaveExiste: inexistente !== null
    };

    return new Response(JSON.stringify(response), {
        headers: { "Content-Type": "application/json" },
        status: 200
    });
}

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

---

## Recuperando múltiplas chaves

Busque múltiplos valores em uma única operação:

```javascript
async function handleRequest(request) {
    const kv = new Azion.KV();

    // Armazenar alguns dados de teste
    await kv.put("usuario-1", "Alice");
    await kv.put("usuario-2", "Bob");
    await kv.put("usuario-3", "Charlie");

    // Recuperar múltiplas chaves de uma vez
    const chaves = ["usuario-1", "usuario-2", "usuario-3", "usuario-4"];
    const usuarios = await kv.get(chaves, "text");

    // Resultado: { "usuario-1": "Alice", "usuario-2": "Bob", "usuario-3": "Charlie", "usuario-4": null }

    return new Response(JSON.stringify(usuarios), {
        headers: { "Content-Type": "application/json" },
        status: 200
    });
}

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

---

## Recuperando dados com metadados

Use `getWithMetadata` para recuperar tanto o valor quanto seus metadados associados:

```javascript
async function handleRequest(request) {
    const kv = new Azion.KV();

    // Armazenar dados com metadados
    await kv.put("sessao", "dados-sessao-ativa", {
        metadata: { 
            criadoEm: new Date().toISOString(),
            userId: "user-42"
        }
    });

    // Recuperar com metadados
    const resultado = await kv.getWithMetadata("sessao", "text");

    console.log(`Valor: ${resultado.value}`);
    console.log(`Metadados: ${JSON.stringify(resultado.metadata)}`);

    return new Response(JSON.stringify(resultado), {
        headers: { "Content-Type": "application/json" },
        status: 200
    });
}

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

---

## Excluindo dados

Remova uma chave do armazenamento:

```javascript
async function handleRequest(request) {
    const kv = new Azion.KV();

    const chave = "token-sessao";

    // Excluir a chave
    await kv.delete(chave);

    return new Response(`Chave '${chave}' excluída`, {
        headers: { "Content-Type": "text/plain" },
        status: 200
    });
}

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

---

## Trabalhando com dados binários

Armazene e recupere dados binários usando ArrayBuffer:

```javascript
async function handleRequest(request) {
    const kv = new Azion.KV();

    // Armazenar dados binários
    const encoder = new TextEncoder();
    const dadosBinarios = encoder.encode("Conteúdo binário aqui").buffer;
    await kv.put("chave-binaria", dadosBinarios);

    // Recuperar como ArrayBuffer
    const recuperado = await kv.get("chave-binaria", "arrayBuffer");

    // Decodificar de volta para string
    const decoder = new TextDecoder("utf-8");
    const stringDecodificada = decoder.decode(recuperado);

    return new Response(stringDecodificada, {
        headers: { "Content-Type": "text/plain" },
        status: 200
    });
}

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

---

## Trabalhando com streams

Para dados grandes, use ReadableStream para uso eficiente de memória:

```javascript
async function handleRequest(request) {
    const kv = new Azion.KV();
    const chave = "conteudo-grande";

    // Recuperar como stream
    const stream = await kv.get(chave, "stream");

    if (stream === null) {
        return new Response("Chave não encontrada", { status: 404 });
    }

    // Retornar o stream diretamente na resposta
    return new Response(stream, {
        headers: { "Content-Type": "application/octet-stream" },
        status: 200
    });
}

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

---

## Usando namespaces específicos

Trabalhe com diferentes namespaces para isolamento de dados:

```javascript
async function handleRequest(request) {
    // Usar um namespace específico
    const producaoKV = new Azion.KV("dados-producao");
    const stagingKV = new Azion.KV("dados-staging");

    // Ou usar o método open
    const cacheKV = await Azion.KV.open("namespace-cache");

    // Cada namespace é isolado
    await producaoKV.put("config", "valor-producao");
    await stagingKV.put("config", "valor-staging");

    const configProducao = await producaoKV.get("config", "text");
    const configStaging = await stagingKV.get("config", "text");

    return new Response(JSON.stringify({
        producao: configProducao,
        staging: configStaging
    }), {
        headers: { "Content-Type": "application/json" },
        status: 200
    });
}

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

---

## Instanciando a função

Após criar sua função, você precisa instanciá-la em sua application:

<DocButton href="/pt-br/documentacao/produtos/guias/build/instanciar-functions/" label="Ir para como instanciar functions em sua aplicação" kind="secondary" size="medium" />

---

## Próximos passos

- Saiba mais sobre o [KV Store](/pt-br/documentacao/produtos/store/kv-store/)
- Explore as [Functions](/pt-br/documentacao/produtos/build/applications/functions/)