Use Cases (Actualizado: 2/6/2026)

Deno TypeScript con Claude Code: permisos, deno.json y Deno.serve

Guía práctica para Deno con Claude Code: permisos mínimos, tareas en deno.json, Deno.serve y fmt/lint/test con código copiable.

Deno TypeScript con Claude Code: permisos, deno.json y Deno.serve

Empieza por el modelo de permisos de Deno

Deno es un runtime para JavaScript y TypeScript: la capa que ejecuta tu código. Su diferencia práctica es que es seguro por defecto. El acceso a archivos, red, variables de entorno y procesos externos no está abierto hasta que lo permites. La referencia oficial es Security and permissions.

Claude Code acelera mucho el trabajo porque puede generar servidor, tests, deno.json y checklist de revisión. Pero si el prompt es vago, puede producir -A, suposiciones de Node.js o herramientas innecesarias. Conviene decirle qué API usar, qué no usar, qué permisos abrir y qué comando debe pasar.

Términos básicos: un permiso es la lista de recursos que el programa puede tocar; un deno task es un comando con nombre dentro de deno.json; formatter, linter y test runner son herramientas para formato, revisión estática y pruebas. Deno las incluye. Para ampliar, revisa desarrollo de API, estrategias de testing y tips de TypeScript.

Prompt recomendado para Claude Code

Crea una API JSON pequeña con Deno. Usa Deno.serve, no Express. Crea deno.json con tareas dev, start, fmt, lint, test y check. No uses -A. Permite solo --allow-net=127.0.0.1:8000, --allow-read=./data y --allow-write=./data. Escribe las pruebas con Deno.test().

Ese prompt se alinea con la documentación oficial de configuration, deno task, Deno.serve y deno test.

deno.json con tareas reproducibles

{
  "tasks": {
    "dev": "deno run --watch --allow-net=127.0.0.1:8000 --allow-read=./data --allow-write=./data server.ts",
    "start": "deno run --allow-net=127.0.0.1:8000 --allow-read=./data --allow-write=./data server.ts",
    "fmt": "deno fmt",
    "lint": "deno lint",
    "test": "deno test",
    "check": "deno fmt --check && deno lint && deno test"
  },
  "fmt": {
    "lineWidth": 100,
    "semiColons": true
  },
  "lint": {
    "rules": {
      "tags": ["recommended"]
    }
  },
  "imports": {
    "@std/assert": "jsr:@std/assert"
  }
}

La tarea check es el contrato de calidad: formato, lint y tests en una sola entrada para Claude Code y CI.

API copiable con Deno.serve

// app.ts
export type Item = {
  id: string;
  title: string;
  done: boolean;
};

export interface ItemStore {
  list(): Promise<Item[]>;
  save(items: Item[]): Promise<void>;
}

export class FileItemStore implements ItemStore {
  constructor(private readonly path = "./data/items.json") {}

  async list(): Promise<Item[]> {
    try {
      const text = await Deno.readTextFile(this.path);
      return JSON.parse(text) as Item[];
    } catch (error) {
      if (error instanceof Deno.errors.NotFound) {
        return [];
      }
      throw error;
    }
  }

  async save(items: Item[]): Promise<void> {
    await Deno.writeTextFile(this.path, JSON.stringify(items, null, 2));
  }
}

export function createHandler(store: ItemStore): (request: Request) => Promise<Response> {
  return async (request: Request): Promise<Response> => {
    const url = new URL(request.url);

    if (url.pathname === "/health") {
      return Response.json({ ok: true });
    }

    if (url.pathname === "/api/items" && request.method === "GET") {
      return Response.json(await store.list());
    }

    if (url.pathname === "/api/items" && request.method === "POST") {
      const body = await request.json().catch(() => null) as { title?: unknown } | null;

      if (!body || typeof body.title !== "string" || body.title.trim() === "") {
        return Response.json({ error: "title is required" }, { status: 400 });
      }

      const items = await store.list();
      const item: Item = {
        id: crypto.randomUUID(),
        title: body.title.trim(),
        done: false
      };

      await store.save([...items, item]);
      return Response.json(item, { status: 201 });
    }

    return new Response("Not Found", { status: 404 });
  };
}
// server.ts
import { createHandler, FileItemStore } from "./app.ts";

Deno.serve(
  { hostname: "127.0.0.1", port: 8000 },
  createHandler(new FileItemStore())
);
mkdir -p data
printf "[]\n" > data/items.json
deno task dev
curl http://127.0.0.1:8000/health
curl -X POST http://127.0.0.1:8000/api/items \
  -H "content-type: application/json" \
  -d '{"title":"Deno article draft"}'
curl http://127.0.0.1:8000/api/items

Pruebas sin permisos extra

// app_test.ts
import { assertEquals } from "@std/assert";
import { createHandler, type Item, type ItemStore } from "./app.ts";

class MemoryStore implements ItemStore {
  private items: Item[] = [];

  async list(): Promise<Item[]> {
    return [...this.items];
  }

  async save(items: Item[]): Promise<void> {
    this.items = [...items];
  }
}

Deno.test("GET /health returns ok", async () => {
  const handler = createHandler(new MemoryStore());
  const response = await handler(new Request("http://localhost/health"));

  assertEquals(response.status, 200);
  assertEquals(await response.json(), { ok: true });
});

Deno.test("POST /api/items creates an item", async () => {
  const handler = createHandler(new MemoryStore());
  const response = await handler(
    new Request("http://localhost/api/items", {
      method: "POST",
      headers: { "content-type": "application/json" },
      body: JSON.stringify({ title: "Write article" })
    })
  );

  const created = await response.json() as Item;

  assertEquals(response.status, 201);
  assertEquals(created.title, "Write article");
  assertEquals(created.done, false);
});

Deno.test("POST /api/items rejects an empty title", async () => {
  const handler = createHandler(new MemoryStore());
  const response = await handler(
    new Request("http://localhost/api/items", {
      method: "POST",
      headers: { "content-type": "application/json" },
      body: JSON.stringify({ title: "" })
    })
  );

  assertEquals(response.status, 400);
});

Casos de uso reales

Primero, prototipos de API internas: paneles de administración, receptores de webhooks y demos con JSON pueden empezar con Deno.serve antes de adoptar un framework grande.

Segundo, automatización del repositorio: revisar contenido, validar configuración o guardar snapshots de APIs encaja bien en deno task.

Tercero, onboarding del equipo: los errores de permisos explican de forma visible por qué un script necesita red, lectura o escritura.

Cuarto, servicios HTTP pequeños que podrían moverse a un entorno edge. Usar Request y Response estándar reduce el acoplamiento.

Errores frecuentes

No dejes -A en las tareas generadas. Abre todos los permisos y elimina la principal ventaja de seguridad.

No instales Express, Jest, Prettier y ESLint antes de probar las herramientas incluidas por Deno.

No olvides crear data/items.json. Si quieres que el código cree directorios, revisa con cuidado el permiso de escritura.

No hagas que todas las pruebas usen archivos o sockets reales. Usa una tienda en memoria para unit tests.

No copies ejemplos antiguos sin revisar la documentación oficial de Deno.

CTA y verificación

Si este flujo se repite, documenta permisos y comandos en CLAUDE.md. Empieza con el cheatsheet gratuito, usa productos y plantillas para prompts reutilizables y considera formación o consultoría si lo necesitas para un equipo.

Verificación práctica: crea data/items.json, ejecuta deno task dev, publica un item con curl y luego corre deno task check. En la revisión, prioriza eliminar -A, limitar rutas y mantener unit tests sin permisos.

#Claude Code #Deno #TypeScript #runtime #security
Gratis

PDF gratis: cheatsheet de Claude Code

Introduce tu email y descarga una hoja con comandos, hábitos de revisión y flujos seguros.

Cuidamos tus datos y no enviamos spam.

Masa

Sobre el autor

Masa

Ingeniero enfocado en workflows prácticos con Claude Code.