Nuxt 3 Auto-imports: configurando Zod e pasta de Schemas
Tags: nuxt, zod, vue, typescript
Published: 2023-10-05 00:41:56

Um dos grandes diferenciais do Nuxt 3 é a capacidade de gerenciar automaticamente as [importações baseada em seu sistema de diretórios](https://nuxt.com/docs/guide/concepts/auto-imports). Mas nem tudo são flores, e muitas vezes precisamos integrar outras ferramentas que não fazem parte do ecossistema Vue/Nuxt, é o caso do [Zod](https://zod.dev/), biblioteca de validação baseada em `schemas` e nativamente não possui um [módulo](https://nuxt.com/docs/guide/concepts/modules) dedicado para o Nuxt.

Criaremos um módulo interno em uma aplicação Nuxt 3 e configurar a importação automática do Zod e configurar uma pasta chamada `schemas` (que não é nativamente suportada pelo Nuxt) para importar automaticamente os arquivos dentro dela.


## Iniciando projeto
Iniciaremos um novo projeto inserindo o comando abaixo no nosso terminal.
```
> npx nuxi@latest init meu-app
```
## Instalando dependências
Com a aplicação iniciada, navegamos até a pasta raíz do app e instalar o `zod`.
```
> cd meu-app
> npm install zod
```
Após a instalação, é possível utilizar o Zod e definir schemas, mas é necessário realizar a importação dele em cada uso, similar ao arquivo abaixo.

```vue
<script setup lang="ts">
import { z } from "zod";

const NameSchema = z.object({
  name: z.string().min(3).max(10).optional(),
});

NameSchema.parse({ name: "John" });
</script>

<template>
  <div>Hello World</div>
</template>
```

Perceba que caso eu tome a decisão de isolar o `NameSchema` em um arquivo na pasta `schemas`, por exemplo, ainda existirá a necessidade de importar o zod nos arquivos, e importar os `schemas` da pasta, [que não é suportada nativamente pelo Nuxt](https://nuxt.com/docs/guide/concepts/auto-imports#directory-based-auto-imports).

Resolveremos isso criando um módulo.
## Escrevendo módulo interno

[Módulos](https://nuxt.com/docs/guide/concepts/modules) no ecossistema do Nuxt é considerado uma forma de simplificar integrações e extender/customizar as funcionalidades do framework, e as importações automáticas fazem parte desse comportamento.

Criaremos um arquivo chamado `zod.ts` na pasta `modules`, [sendo a pasta definida pelo Nuxt para criação de módulos e que vão ser carregados quando a aplicação iniciar](https://nuxt.com/docs/guide/directory-structure/modules).

Um modulo para adicionar a importação automática do Zod pode ser escrito da seguinte forma:
```ts
// modules/zod.ts

import { addImports, defineNuxtModule, logger } from "nuxt/kit";

// definimos o módulo
export default defineNuxtModule({
  meta: {
    // nome do módulo
    name: "zod",
  },
  // função que será executada quando o módulo for carregado
  setup() {
    // carregamos o módulo
    logger.success("Zod internal module loaded");

    // adicionamos o import
    // equivalente a import {z} from "zod";
    addImports({
      name: "z",
      from: "zod",
    });
  },
});

```
Ao executar a aplicação, podemos ver a mensagem que escrevemos no `logger` aparecer no terminal:

!["Zod internal module loaded"](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4k327f048d50jna9b64b.png)

A partir daqui, o {Z} não precisa ser importado em componentes, páginas, composables, server e etc.

## Adicionando pasta `Schemas`

Agora vamos adicionar o auto-import de uma pasta inteira para não existir a necessidade de importar cada `schema` que vamos escrever.

Modificando o módulo da seguinte forma:

```ts
// modules/zod.ts

// importamos o addImportsDir
import { addImports, addImportsDir, defineNuxtModule, logger } from "nuxt/kit";

export default defineNuxtModule({
  meta: {
    name: "zod",
  },
  setup() {
    logger.success("Zod internal module loaded");

    addImports({
      name: "z",
      from: "zod",
    });

    logger.info("Put Zod schemas in 'schemas' folder");

    // Adiciona todos os arquivos da pasta schemas como import
    addImportsDir("schemas");
  },
});
```

Agora todos os arquivos que tiverem uma exportação na pasta `schemas` vão ter a importação automática configurada.

Exemplo abaixo:

```ts
// schemas/nameSchema.ts

export const NameSchema = z.object({
  name: z.string().min(3).max(10).optional(),
});
```