---
slug: 14-modules
title: Módulos (use / export)
description: Dividí Synsema en archivos con use y export — un módulo es un map de sus exports, importado bajo un alias.
example_ids: [modules]
---

# Módulos (`use` / `export`)

Dividí el código en archivos. `export` hace público un `task`/`type`/`let`/`enum`/`routes`; todo lo demás queda privado. Un módulo es un **map de sus exports**, importado bajo un alias.

El módulo — `mathlib.syn`:

```synsema
export task square(n)
    give n * n

export let VERSION be "1.0"

task private_helper()        -- sin `export` → no visible para quien importa
    give 42
```

El entry que lo importa:

```synsema
-- Doc example: modules (use / export). Imports ./mathlib.syn under the alias `math`.
intent: "doc example: modules"
use "./mathlib.syn" as math

print("math.square(5) = " + text(math.square(5)) + ",  VERSION " + math.VERSION)

test "import an exported task and let (private_helper is NOT visible)"
    assert_eq(math.square(5), 25)
    assert_eq(math.VERSION, "1.0")
```

## Reglas

- `use "./path.syn" as alias` — los paths son **relativos al archivo que importa**; solo `.syn`, sin URLs/FFI, y el traversal (`../`) está bloqueado.
- Las llamadas entre archivos necesitan el **prefijo del alias**: `math.square(5)`, `math.VERSION`.
- Los imports están **cacheados** (se cargan una vez), son **transitivos** y con **chequeo de ciclos**.
- Un módulo **no** puede tener `require` ni `serve` top-level — eso va en el archivo entry. Un `require` por-task dentro de una task del módulo sí está bien.
- `synsema check entry.syn` resuelve y parsea el **grafo de imports completo** (paths rotos, ciclos, `serve`/`require` prohibidos en módulos: todo falla el check).

## `export routes` — grupos de rutas que un serve puede montar (`mount`)

Un sitio grande no tiene que ser un solo bloque serve. Un módulo exporta un grupo de rutas; el entry lo monta (los cuerpos llaman a los helpers **privados** del módulo por nombre simple):

```synsema
-- shop.syn
task fmt(n)                        -- privado
    give "$" + text(n)

export routes shop
    route "GET /shop"
        give html("<h1>" + fmt(99) + "</h1>")
    route "POST /shop/buy"
        expect body {item: text}
        give created(json of request)
```

```synsema
-- app.syn
use "./shop.syn" as shop
serve on 8080
    mount shop.shop                -- o: mount shop.shop at "/store"
```

Los grupos aceptan entradas `route` con su propio `rate_limit` y `timeout` (engine v0.6.19+: una ruta montada tiene su propia zona de rate limit, y un prefijo de mount es otra zona — antes de v0.6.19 los dos se rechazaban dentro de un grupo); las rutas `stream` y `socket` siguen yendo en el bloque serve, y `synsema check` lo dice con el mismo mensaje que daría `serve` al arrancar. Un `requires auth` montado sigue exigiendo `auth with` en el bloque serve, validado al construir el serve. Mirá [Servidor HTTP](40-serve) y [Construí un sitio web](41a-build-a-website).
