Introdução: Por que Swift é adequado para API REST?
\n\nQuando se trata de desenvolvimento de servidor, Swift não é a primeira linguagem que vem à mente. No entanto, com o surgimento do framework Vapor (e sua alternativa, Kitura), Swift se tornou uma ferramenta completa para criar APIs REST. Por que usar Swift no servidor? Primeiro, é uma linguagem única para iOS, macOS e backend — você pode reutilizar modelos de dados. Segundo, Swift é rápido, seguro e tem excelente suporte para assincronia via async/await.
\n\nNeste guia, criaremos uma API REST simples para gerenciar uma lista de tarefas (Todo list) em Swift usando o framework Vapor. Você aprenderá a configurar o servidor, criar rotas, trabalhar com JSON e testar a API. Todo o processo levará cerca de 30 minutos.
\n\nPasso 1: Instalação e configuração do projeto
\n\nAntes de escrever código, você precisa instalar o Vapor Toolbox — um utilitário de linha de comando para criar e gerenciar projetos Vapor.
\n\nInstalação do Vapor Toolbox
\nAbra o terminal e execute:
\nbrew install vapor\nSe você não tiver o Homebrew, instale-o em brew.sh.
\n\nCriação de um novo projeto
\nVamos criar um novo projeto chamado TodoAPI:
vapor new TodoAPI -n\ncd TodoAPI\nA flag -n significa "sem exemplo" — obteremos um template limpo.
Iniciando o servidor
\nAbra o projeto no Xcode:
\nopen Package.swift\nSelecione o esquema Run e pressione Cmd+R. Após alguns segundos, o servidor será iniciado em http://127.0.0.1:8080. Abra o navegador — você deve ver uma mensagem de boas-vindas do Vapor.
Passo 2: Criação do modelo de dados
\n\nNossa API gerenciará tarefas. Cada tarefa tem um ID, um título e um status de conclusão (concluída/não concluída).
\n\nVamos criar o modelo Todo. No Vapor, modelos são estruturas comuns que estão em conformidade com o protocolo Content (para serialização em JSON) e Codable.
Crie o arquivo Sources/App/Models/Todo.swift:
\nimport Vapor\n\nstruct Todo: Content, Codable {\n var id: UUID?\n var title: String\n var isCompleted: Bool\n \n init(id: UUID? = nil, title: String, isCompleted: Bool = false) {\n self.id = id\n self.title = title\n self.isCompleted = isCompleted\n }\n}\n\nObserve: id é um UUID opcional. Nós o geraremos no servidor ao criar a tarefa.
Passo 3: Criação do armazenamento e do controlador
\n\nPara simplificar, armazenaremos as tarefas na memória (em um array). Em um projeto real, você usaria um banco de dados (Fluent ORM), mas para uma demonstração de 30 minutos, isso é desnecessário.
\n\nArmazenamento (In-Memory Store)
\nCrie o arquivo Sources/App/Controllers/TodoStore.swift:
\nimport Vapor\n\nfinal class TodoStore {\n private var todos: [Todo] = []\n private let lock = NSLock()\n \n func getAll() -> [Todo] {\n lock.lock()\n defer { lock.unlock() }\n return todos\n }\n \n func get(id: UUID) -> Todo? {\n lock.lock()\n defer { lock.unlock() }\n return todos.first { $0.id == id }\n }\n \n func create(_ todo: inout Todo) -> Todo {\n lock.lock()\n defer { lock.unlock() }\n todo.id = UUID()\n todos.append(todo)\n return todo\n }\n \n func update(id: UUID, with updatedTodo: Todo) -> Todo? {\n lock.lock()\n defer { lock.unlock() }\n guard let index = todos.firstIndex(where: { $0.id == id }) else { return nil }\n var mutableTodo = updatedTodo\n mutableTodo.id = id\n todos[index] = mutableTodo\n return mutableTodo\n }\n \n func delete(id: UUID) ->