# Como usar KV Store com SDK compatível com Redis

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

O SDK Azion KV fornece uma interface de cliente similar ao Redis para interagir 
com o KV Store. Isso facilita a migração de aplicações existentes que usam 
padrões Redis e proporciona uma experiência familiar para desenvolvedores.

<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:

- Uma [conta Azion](https://console.azion.com/signup).
- Um namespace do KV Store criado via Console ou API.
- Node.js 18+ ou um runtime JavaScript compatível.

---

## Instalando o SDK

Instale o SDK da Azion usando npm:

```bash
npm install azion
```

---

## Criando um cliente

O SDK usa um padrão de cliente similar ao Redis com métodos encadeáveis:

```typescript
import { createClient } from 'azion/kv';

// Criar e conectar um cliente
const client = await createClient()
  .on('error', (err) => console.error('Erro do Cliente KV:', err))
  .connect();
```

### Opções do cliente

Você pode personalizar o cliente com opções:

```typescript
const client = await createClient({
  namespace: 'meu-namespace',
  apiToken: 'meu-token',
})
  .on('error', (err) => console.error('Erro KV:', err))
  .connect();
```

| Opção | Tipo | Descrição |
|-------|------|-----------|
| `namespace` | string | O namespace do KV Store a ser usado |
| `apiToken` | string | Seu token da API Azion (obrigatório para provider API) |

---

## Armazenando dados

Use o método `set` para armazenar valores:

```typescript
// Set simples
await client.set('user:123', 'John Doe');

// Set com expiração (10 segundos)
await client.set('session:abc', 'dados-sessao', {
  expiration: {
    type: 'EX',
    value: 10,
  },
});

// Set com metadados
await client.set('config:theme', 'dark', {
  metadata: { 
    updatedBy: 'admin',
    version: 1 
  },
});

// Set com expiração e metadados
await client.set('cache:api-response', JSON.stringify(data), {
  expiration: {
    type: 'EX',
    value: 300, // 5 minutos
  },
  metadata: { 
    source: 'external-api',
    cached_at: Date.now() 
  },
});
```

### Tipos de expiração

| Tipo | Descrição |
|------|-----------|
| `EX` | Tempo de expiração em segundos |
| `PX` | Tempo de expiração em milissegundos |
| `EXAT` | Timestamp Unix em segundos |
| `PXAT` | Timestamp Unix em milissegundos |

---

## Recuperando dados

Use o método `get` para recuperar valores:

```typescript
// Get simples
const value = await client.get('user:123');
console.log(value); // 'John Doe'

// Retorna null se a chave não existir
const missing = await client.get('inexistente');
console.log(missing); // null
```

### Recuperando com metadados

Use `getWithMetadata` para obter tanto o valor quanto seus metadados:

```typescript
const result = await client.getWithMetadata('config:theme');
console.log(result.value);    // 'dark'
console.log(result.metadata); // { updatedBy: 'admin', version: 1 }
```

---

## Excluindo dados

Use `delete` ou `del` para remover chaves:

```typescript
await client.delete('user:123');
// ou
await client.del('user:123');
```

---

## Operações de hash

O SDK fornece operações de hash compatíveis com Redis para trabalhar com pares campo-valor:

### hSet / HSET

Armazena um par campo-valor:

```typescript
await client.hSet('user:profile:123', 'name', 'John Doe');
await client.hSet('user:profile:123', 'email', 'john@example.com');
await client.hSet('user:profile:123', 'role', 'admin');

// Alias em maiúsculas também disponível
await client.HSET('user:profile:123', 'status', 'active');
```

### hGetAll / HGETALL

Obtém todos os campos e valores:

```typescript
const profile = await client.hGetAll('user:profile:123');
console.log(profile);
// { name: 'John Doe', email: 'john@example.com', role: 'admin', status: 'active' }

// Alias em maiúsculas
const data = await client.HGETALL('user:profile:123');
```

### hVals / HVALS

Obtém todos os valores (sem os nomes dos campos):

```typescript
const values = await client.hVals('user:profile:123');
console.log(values);
// ['John Doe', 'john@example.com', 'admin', 'active']

// Alias em maiúsculas
const vals = await client.HVALS('user:profile:123');
```

---

## Detecção de provider

O SDK detecta automaticamente o ambiente de execução e seleciona o provider apropriado:

- **Provider nativo**: Usado quando executando dentro do runtime de Functions da Azion
- **Provider API**: Usado quando executando fora da Azion (desenvolvimento local, servidores externos)

Você pode verificar qual provider está sendo usado:

```typescript
const providerType = client.getProviderType();
console.log(providerType); // 'native' ou 'api'
```

---

## Tratamento de erros

O SDK usa um padrão de tratamento de erros baseado em eventos:

```typescript
const client = await createClient()
  .on('error', (err) => {
    console.error('Erro KV:', err.message);
    // Tratar erro (retry, fallback, etc.)
  })
  .connect();
```

Você também pode usar try-catch para operações individuais:

```typescript
try {
  await client.set('key', 'value');
} catch (error) {
  console.error('Falha ao definir valor:', error);
}
```

---

## Desconectando

Sempre desconecte quando terminar:

```typescript
await client.disconnect();
// ou
await client.quit();
```

---

## Exemplo completo

Aqui está um exemplo completo mostrando operações comuns:

```typescript
import { createClient } from 'azion/kv';

async function main() {
  // Criar e conectar cliente
  const client = await createClient({
    namespace: 'minha-app',
  })
    .on('error', (err) => console.error('Erro KV:', err))
    .connect();

  try {
    // Armazenar dados do usuário
    await client.set('user:1', JSON.stringify({ name: 'Alice', age: 30 }), {
      expiration: { type: 'EX', value: 3600 }, // 1 hora
      metadata: { created: Date.now() },
    });

    // Armazenar perfil do usuário usando operações de hash
    await client.hSet('profile:1', 'theme', 'dark');
    await client.hSet('profile:1', 'language', 'pt-br');
    await client.hSet('profile:1', 'notifications', 'true');

    // Recuperar dados do usuário
    const userData = await client.get('user:1');
    console.log('Usuário:', JSON.parse(userData));

    // Recuperar com metadados
    const result = await client.getWithMetadata('user:1');
    console.log('Criado em:', result.metadata.created);

    // Obter todas as configurações do perfil
    const profile = await client.hGetAll('profile:1');
    console.log('Perfil:', profile);

    // Limpar
    await client.delete('user:1');

  } finally {
    await client.disconnect();
  }
}

main().catch(console.error);
```

---

## Mapeamento de métodos Redis

| Comando Redis | Método SDK | Descrição |
|---------------|------------|-----------|
| `GET` | `get(key)` | Obtém um valor |
| `SET` | `set(key, value, options?)` | Define um valor |
| `DEL` | `delete(key)` / `del(key)` | Exclui uma chave |
| `HSET` | `hSet(key, field, value)` / `HSET(...)` | Define campo de hash |
| `HGETALL` | `hGetAll(key)` / `HGETALL(key)` | Obtém todos os campos do hash |
| `HVALS` | `hVals(key)` / `HVALS(key)` | Obtém todos os valores do hash |

---

## Próximos passos

- Saiba mais sobre o [KV Store](/pt-br/documentacao/produtos/store/kv-store/)
- Explore [gerenciar KV Store com Functions](/pt-br/documentacao/produtos/guias/kv-store/gerenciar-com-funcoes/)