Introducción: Swift no solo para aplicaciones móviles
Muchos desarrolladores están acostumbrados a asociar Swift exclusivamente con iOS y macOS. Sin embargo, este lenguaje ha trascendido hace tiempo los límites del ecosistema de Apple. Con la aparición de frameworks de servidor como Vapor y Kitura, Swift se ha convertido en una herramienta completa para crear backend. En este artículo, en 30 minutos escribiremos una API REST completa en Swift utilizando el framework Vapor. Aprenderás cómo configurar el proyecto, crear endpoints, conectar una base de datos y manejar errores. ¿Listo? ¡Vamos allá!
Paso 1: Instalación y configuración del proyecto
Para empezar, asegúrate de tener instalado Swift 5.5 o superior. Puedes verificar la versión con el comando:
swift --version
A continuación, instala Vapor Toolbox, la utilidad para gestionar proyectos:
brew install vapor
Ahora crearemos un nuevo proyecto:
vapor new MyAPI --template=api
Este comando creará una estructura de carpetas con una plantilla de API lista. Navega a la carpeta del proyecto e inicia la compilación:
cd MyAPI
vapor build
Si la compilación se realiza con éxito, inicia el servidor:
vapor run
Por defecto, el servidor estará disponible en la dirección http://127.0.0.1:8080. Abre el navegador y ve a esta dirección; deberías ver un mensaje de bienvenida.
Estructura del proyecto Vapor
- Sources/App — directorio principal con el código de la aplicación
- Sources/App/Controllers — controladores para procesar solicitudes
- Sources/App/Models — modelos de datos
- Sources/App/routes.swift — archivo para registrar rutas
- configure.swift — configuración de la aplicación y la base de datos
Paso 2: Creamos el modelo de datos y la base de datos
Como ejemplo, crearemos una API simple para gestionar una lista de tareas (Todo). Empecemos con el modelo de datos. Crea el archivo Todo.swift en la carpeta Sources/App/Models:
import Fluent
import Vapor
final class Todo: Model, Content {
static let schema = "todos"
@ID(key: .id)
var id: UUID?
@Field(key: "title")
var title: String
@Field(key: "is_completed")
var isCompleted: Bool
init() {}
init(id: UUID? = nil, title: String, isCompleted: Bool = false) {
self.id = id
self.title = title
self.isCompleted = isCompleted
}
}
Ahora crearemos una migración para la tabla. En el archivo Sources/App/Migrations/CreateTodo.swift:
import Fluent
struct CreateTodo: Migration {
func prepare(on database: Database) -> EventLoopFuture<Void> {
database.schema("todos")
.id()
.field("title", .string, .required)
.field("is_completed", .bool, .required)
.create()
}
func revert(on database: Database) -> EventLoopFuture<Void> {
database.schema("todos").delete()
}
}
No olvides registrar la migración en configure.swift:
app.migrations.add(CreateTodo())
Para simplificar, usaremos SQLite (base de datos integrada). Añade en configure.swift:
app.databases.use(.sqlite(.file("db.sqlite")), as: .sqlite)
Paso 3: Creamos los endpoints de la REST API
Ahora viene la parte más interesante: la implementación de las operaciones CRUD. Crea el controlador TodoController.swift en la carpeta Sources/App/Controllers:
import Vapor
struct TodoController: RouteCollection {
func boot(routes: RoutesBuilder) throws {
let todos = routes.grouped("api", "todos")
todos.get(use: index)
todos.post(use: create)
todos.group(":todoID") { todo in
todo.get(use: show)
```