Saltearse al contenido

La interfaz

La interfaz está partida en dos, y el corte es deliberado:

  • @reply2social/core — TypeScript puro. Qué rutas existen, qué forma tiene lo que devuelven, y qué significa cada «no». Cero dependencias de framework.
  • @reply2social/svelte — cómo se pinta. Fino a propósito.

Envoltorios

@reply2social/core — sin framework

inyecta

transporte.ts

pedir() y FalloApi

esquemas.ts

zod: la forma de todo

cliente.ts

las rutas del servicio

vista.ts

legible(): un store de 15 líneas

vista_*.ts

una por pantalla

@reply2social/svelte

react / vue / lo que venga

El anfitrión

pone el transporte: cookies, tokens, base URL

El transporte entra como parámetro y no se resuelve adentro. Cómo se autentica quien mira es del anfitrión: en Antisionista es una cookie de sesión, en otra instalación podría ser un token. Si el núcleo supiera de cookies, no serviría en la segunda instalación — y sería el único módulo que hay que reescribir para portarlo.

Las capas, y qué decide cada una

usa

lanza

«type»

Transporte

+llamar(ruta, opts) : Promise<Response>

FalloApi

+clase: ClaseDeFallo

+message: string

+status?: number

+detalle?: string

+reintentable: bool

Cliente

+emisiones

+cuentas

+fuentes

+flujos

+archivo

+alertas

+cursores

+programacion

+consentimientos

+cauce

«interface»

Legible<T>

+subscribe(fn) : Desuscribir

VistaArchivo

+cargar()

+filtrar(cambios)

+alternar(fila)

+sembrar()

VistaFuentes

+cargar()

+probar()

+crear()

+otorgar(evidencia)

+semaforoDe(destino) : Marca

ClaseDeFallo: qué significa cada «no»

Un error HTTP crudo no le sirve a una pantalla. 401 y 503 son los dos «no pasás», y querés hacer cosas distintas con cada uno.

ClaseCuándoQué debería hacer la pantalla
sesion401Mandar a entrar de nuevo
permiso403Decir que no alcanza el rol; no reintentar
no_disponible503«No se pudo consultar» — no «no hay nada»
conflicto409Ya existe: explicarlo, no reintentar
peticion400El formulario tiene algo mal
servidor5xxReintentable
redno llegóReintentable
contratola forma no coincidePanel y servicio en versiones distintas

contrato existe como clase propia. Cuando el servicio devuelve algo que el panel no entiende, lo que pasó casi siempre es que están en versiones distintas —se desplegó uno y no el otro— y el mensaje lo dice. Sin esa clase, aparecía como un error de servidor y se buscaba el problema en el lugar equivocado.

Una vista por pantalla

Cada vista es una función que toma el cliente y devuelve un store legible más sus acciones. El contrato es subscribe, que es el mismo de Svelte — y por eso el envoltorio puede ser tan fino.

VistaPantallaLo que no puede hacer mal
vista_por_aprobarPor aprobarAprobar en lote sin decir cuántas y hacia dónde
vista_historialHistorialMostrar como iguales lo consentido y lo publicado por atribución
vista_archivoArchivoMandar ítems por la ruta de otra fuente
vista_fuentesFlujosDibujar en verde algo que no se probó
vista_altaAlta de cuentasReintentar sola para siempre
vista_programacionProgramaciónDecir «activo» leyendo la configuración en vez del latido
vista_rescateRescate históricoPintar una pausa por tasa como si fuera un error
vista_avisosAvisosMostrar sólo lo que se entregó bien

Por qué las reglas viven en el núcleo y no en la plantilla.

Cada una de esas reglas es una decisión que costó encontrar, y varias vinieron de un incidente. Si vivieran en el .svelte, el día que exista el envoltorio de React habría que reimplementarlas — y se perdería alguna. Están en TypeScript, con un test cada una, para que el port herede las cicatrices y no sólo la forma.

Un ejemplo: el semáforo de un flujo

Es la regla más importante de la interfaz, y cabe en un diagrama.

no

no

no

no

no

emitiria

no_emitiria

incierto

dibujar un conector

¿se corrió la sonda?

estado EN REPOSO

veredicto

¿tiene permiso?

✗ sin permiso

¿hay cliente

para esa red?

✗ sin cliente

¿la ruta está activa?

⏸ desactivado

¿el destino está activo?

⏸ destino pausado

? sin probar

✓ probado, emite

✗ N pasos fallan

? sin confirmar

Fijate que ningún camino de la rama izquierda llega a verde. Con los datos del listado se puede saber que algo está roto, pero no que funcione: para eso hay que preguntarle a la red. Lo mejor que dice un flujo sin probar es «sin probar». Un ✓ de reposo sería una promesa dibujada justo donde más se mira.

destino_activo === false, no !destino_activo. El panel y el servicio son procesos distintos: durante un despliegue, el panel le habla un rato a una versión del servicio que todavía no manda ese campo. Con la negación simple, ese undefined pintaría todos los flujos como pausados — y una alarma falsa en cada despliegue enseña a ignorar la alarma.