Proyectos

simcapture-sdk

SDK de SimCapture, la plataforma de grabación y evaluación de simulación clínica. Expone su API REST como un cliente TypeScript tipado.

Cada entidad tiene su propio namespace (sc.Course, sc.Reservation, …) que devuelve handles navegables, y sus builders validan antes de tocar la red.

Características

  • Namespaces por entidad con lookup por id o por nombre: named() matchea exacto e informa si no hay match (NotFoundError) o si hay varios (AmbiguousMatchError, con los ids para desambiguar)
  • Entidades navegables: reserva.organization() hace el fetch bajo demanda, y .raw expone el registro completo del API, incluso lo que el SDK no modela
  • Builders fluidos: save() valida local y reporta todos los campos faltantes en un solo ValidationError, en vez de un round-trip por error
  • Value objects: TimeWindow para ventanas de tiempo (overlap half-open, UTC explícito), Location, Attachment
  • all() recorre las páginas por dentro y concatena; corta solo con página vacía, y si el servidor nunca la devuelve lanza en vez de entregar media lista
  • Autenticación con caché del token y reintento transparente ante 401; las llamadas concurrentes comparten un único /auth en vuelo
  • Errores tipados bajo SimCaptureError, con el estado real del upstream en vez de un 400 genérico
  • Arquitectura hexagonal: el dominio solo conoce puertos (HttpClient, TokenStore), así que los tests corren sin red y podés inyectar tu propio transporte
  • Build dual ESM/CJS con tipos .d.ts generados y publicación automatizada en npm mediante GitHub Actions

Tecnologías

TypeScript, Bun, axios, GitHub Actions.

Instalación

npm install simcapture-sdk

Ejemplo de Uso

import { SimCapture, TimeWindow, Location, Reservation, SimCaptureError } from "simcapture-sdk";

const sc = new SimCapture({
  apiUrl: process.env.SIMCAPTURE_API!,
  inventoryUrl: process.env.SIMCAPTURE_INVENTORY_API!,
  credentials: {
    username: process.env.SIMCAPTURE_USER!,
    password: process.env.SIMCAPTURE_PASSWORD!,
    clientSubdomain: process.env.SIMCAPTURE_SUBDOMAIN!,
  },
});

const org  = await sc.Organization.named("Facultad de Medicina");
const room = new Location({ name: "P3-H1" });
const date = new TimeWindow("2026-06-05").start().at("23:00").end().at("23:10");

const reserva = await new Reservation()
  .titled("Reserva de prueba")
  .inOrganization(org)   // handle, UUID o nombre
  .at(room)
  .when(date)
  .save();

await reserva.organization();        // navegación: fetch bajo demanda
reserva.date.durationMinutes();

try {
  await sc.Reservation.get("bad-id");
} catch (error) {
  if (error instanceof SimCaptureError) console.error(error.status, error.message);
}

Motivación

La integración bidireccional entre la plataforma del Centro Interdisciplinario de Simulación Avanzada y SimCapture necesitaba el mismo cliente en varios microservicios. Extraerlo a un paquete versionado eliminó la duplicación de la lógica de autenticación y dejó las respuestas del API tipadas en un solo lugar.