Una plataforma de comercio electrónico que corre aplicaciones de terceros.
El problema que organiza todo el repositorio: dejar que gente de afuera escriba código que corre en la tienda de un comerciante, sin que eso le cueste la velocidad de su vitrina ni la seguridad de su checkout.
No hay un solo límite de confianza. Hay tres, y cada uno paga distinto.
| quién la ve | cómo corren las apps | por qué | |
|---|---|---|---|
| admin | el comerciante, autenticado | iframe + postMessage |
sesión larga sobre su propia tienda: puede pagar un iframe, y a cambio la app tiene DOM propio |
| vitrina | gente anónima que llegó de una búsqueda | Web Worker + UI declarativa | su velocidad es la conversión: no hay presupuesto para un iframe por app |
| checkout | quien está por pagar | no corren apps | es donde hay plata; la superficie se mantiene chica para poder auditarla |
Dos paquetes andan y están probados. El resto es esqueleto con issues abiertas.
| paquete | estado | |
|---|---|---|
app-bridge |
funciona | 19 tests. El puente del admin, con el origen verificado en las dos direcciones |
app-runtime |
funciona | 28 tests. El Worker de la vitrina, con todo árbol entrante tratado como hostil |
types |
esqueleto | el vocabulario compartido |
ui |
esqueleto | las fábricas de componentes |
design-tokens |
esqueleto | |
design-system |
esqueleto | |
icons |
esqueleto | |
cli |
esqueleto |
import { createAppBridge } from "@tiendablue/app-bridge";
const bridge = createAppBridge({
clientId: "mi-app",
allowedOrigins: "https://admin.tiendablue.com", // obligatorio, sin comodín
});
const { token } = await bridge.request("auth:sessionToken");allowedOrigins no tiene valor por defecto porque no existe uno seguro, y
adivinarlo por quien llama es exactamente cómo se termina en "*".
// en el Worker
import { createAppRuntime } from "@tiendablue/app-runtime";
const app = createAppRuntime(self);
app.mount({
type: "col",
children: [
{ type: "txt", props: { text: "Nota de regalo" } },
{ type: "button", props: { text: "Agregar", onClick: () => enviar() } },
],
});La app nunca ve el DOM. Describe, y le avisan qué pasó.
Está en docs/arquitectura.md, con la evidencia.
El resumen: se estudió una plataforma que ya funciona a escala, cruzando sus 50 repositorios públicos contra sus 40 paquetes de npm. Los paquetes que existen sin repositorio son el perímetro privado, y sus descripciones filtran bastante.
Nada de acá es código de ellos. Lo que se tomó son decisiones de arquitectura, que no son propiedad de nadie.
npm install
npm test # los dos paquetes que andan
npm run typecheckLas issues abiertas están escritas para poder tomarse: cada una dice qué archivo tocar, qué tiene que pasar, y cómo se verifica que funcionó.
Comentá la issue con un plan concreto antes de mandar la PR. Se asigna por la calidad de ese plan, no por orden de llegada.
MIT. Ver LICENSE.