Rama de desarrollo experimental sobre el Oasis de epsylon, sin afiliacion con el proyecto original. Base: 0.9.5. Trae el modulo Karvan —salas efimeras en memoria con autodestruccion por TTL, chat que funciona sin JavaScript y llamadas de audio y video sobre WebRTC— con el enlace en el menu lateral por el mismo patron que el resto de modulos: renderKarvanLink calcado de renderPollsLink, entrada en modules_view y en la lista de /modules. Los estilos del modulo van en su propia hoja, styles/karvan.css, siguiendo el patron de highlight.css: asi se ve igual con cualquier tema, sin depender del tema movil. Sin servidores ICE de terceros: no hay STUN de fabrica, porque un STUN aprende la IP publica y el momento de cada llamada. Solo candidatos host salvo que se configure un TURN propio en oasis-config.json, con credenciales efimeras por el mecanismo REST de coturn. El codigo propio vive separado —views/fork/, backend/fork_routes.js, models/karvan_model.js y translations/fork/— de modo que sobre los ficheros de upstream solo hay enganches de una linea y cada version nueva se integra sin arrastrar nada. Respecto al arbol de Android: fuera el wrapper y main.js, que es su arranque; el tema vuelve a Dark-SNH y se restauran los modulos que en movil se recortan por peso. Verificado arrancando sin OASIS_MOBILE: nueve rutas OK, menu lateral de upstream con 27 grupos y el enlace de Karvan, cero rastro de la interfaz movil (ni hexagonos, ni topbar, ni barra inferior), y una sala creada y servida.
262 lines
13 KiB
Text
262 lines
13 KiB
Text
================================================================================
|
|
OASIS · MAPA DE FUNCIONES Y FLUJO
|
|
Cómo se relacionan las funciones lógicas entre archivos,
|
|
la persistencia (SSB) y la media (blobs)
|
|
versión 0.8.1
|
|
================================================================================
|
|
|
|
LEYENDA
|
|
[proc] proceso ( ) función / método
|
|
--> llamada / flujo === límite de proceso ~~~ red / disco
|
|
*.js archivo #NNN número de línea aprox.
|
|
|
|
|
|
================================================================================
|
|
0. VISIÓN GLOBAL: DOS PROCESOS
|
|
================================================================================
|
|
|
|
NAVEGADOR OTROS PEERS SSB
|
|
(HTML puro, (misma SHS cap)
|
|
sin JS) |
|
|
| HTTP :3000 | net:IP:8008~shs
|
|
v v ~~~~~~~~~~~~~
|
|
============================[proc gui]== ==============[proc sbot]======
|
|
| src/backend/backend.js (Koa router) | | src/server/SSB_server.js |
|
|
| | | SecretStack({caps}).use(..)|
|
|
| cooler = src/client/gui.js | | ssb-db (log append-only) |
|
|
| | | <-> | ssb-ebt / ssb-friends |
|
|
| | cooler.open() |unix | ssb-blobs / ssb-conn |
|
|
| v |sock | ssb-box / ssb-private |
|
|
| ssb (cliente muxrpc) ---------------|~noauth-> muxrpc API (publish,get, |
|
|
| | | createLogStream,...) |
|
|
========================================= ===============================
|
|
modelos + vistas replicación P2P por gossip
|
|
|
|
|
|
================================================================================
|
|
1. CADENA DE UNA PETICIÓN (el patrón de TODO módulo)
|
|
================================================================================
|
|
|
|
navegador
|
|
| GET /modulo (o POST /modulo/accion)
|
|
v
|
|
middleware.js (#43..#209) ── app.listen({host,port})
|
|
| setLanguage(cookie) · gate indexación · refresco shared-state(60s)
|
|
v
|
|
backend.js router.get('/modulo') #1270..#7124 (~472 rutas)
|
|
| checkMod(ctx,'moduloMod') #170 ── off? --> redirect /modules
|
|
|
|
|
+--> xModel.metodo(filtro) [ LECTURA / ESCRITURA SSB ] -----+
|
|
| (src/models/xxx_model.js) |
|
|
| v
|
|
| <------------------ datos JS ------------------------ cooler.open()
|
|
| (gui.js)
|
|
+--> xView(datos, filtro) [ RENDER HTML ] |
|
|
| (src/views/xxx_view.js) v
|
|
| template(i18n.titulo, section(...)) ssb muxrpc
|
|
v
|
|
ctx.body = "<html>...</html>" --> Koa --> navegador
|
|
|
|
POST: koaBody() -> stripDangerousTags() -> xModel.crear() -> ctx.redirect()
|
|
(patrón Post/Redirect/Get; el GET siguiente re-renderiza)
|
|
|
|
|
|
================================================================================
|
|
2. PERSISTENCIA: cómo el MODELO habla con SSB (pull-stream + publish)
|
|
================================================================================
|
|
|
|
src/models/xxx_model.js = module.exports = ({cooler, ...deps}) => ({...})
|
|
|
|
openSsb() ............ if(!ssb) ssb = await cooler.open(); // lazy, cacheado
|
|
|
|
|
v
|
|
ESCRIBIR (persistir):
|
|
ssb.publish({ type:'<tipo>', ...campos }, cb)
|
|
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
+--> ssb-db: añade mensaje FIRMADO (ed25519) al log append-only
|
|
| del feed propio @miclave.ed25519
|
|
+--> ssb-ebt replica el mensaje a los peers (hops<=2) ~~~~>
|
|
|
|
LEER (consultar):
|
|
pull(
|
|
ssb.createLogStream({limit}) <-- lee el log local (todos los feeds
|
|
pull.filter(m => m.value.content.type === '<tipo>') replicados)
|
|
pull.collect((err,res)=>...)
|
|
)
|
|
(variantes: ssb.messagesByType, ssb.query.read, ssb.backlinks.read,
|
|
ssb.createUserStream{id})
|
|
|
|
BORRAR (lógico; el log NO se borra):
|
|
ssb.publish({ type:'tombstone', target:<msgId>, author })
|
|
|
|
|
+--> tombstone_validator.js :: buildValidatedTombstoneSet(msgs)
|
|
acepta SOLO si author(tombstone) === author(target) [autoría]
|
|
|
|
EDITAR:
|
|
ssb.publish({ ...nuevo, replaces:<idAnterior> }) + tombstone del viejo
|
|
|
|
|
+--> al leer, se sigue la cadena replaces -> hasta la "punta"
|
|
|
|
----------------------------------------------------------------------------
|
|
TIPOS DE MENSAJE (content.type) = el discriminador en el log compartido
|
|
----------------------------------------------------------------------------
|
|
nativos SSB : post · vote(like) · contact(follow/block) · about(perfil)
|
|
Oasis : votes · tombstone · task · event · calendar · transfer ·
|
|
tribe · market · report · job · project · gameScore · ...
|
|
|
|
|
|
================================================================================
|
|
3. MEDIA: cómo viajan los ficheros (BLOBS, fuera del log)
|
|
================================================================================
|
|
|
|
El log solo guarda el HASH. El binario viaja aparte por la red SSB.
|
|
|
|
SUBIR:
|
|
navegador --(multipart)--> backend.js --> blobHandler.js
|
|
ssb.blobs.add(pull-stream) --> &<sha256>.sha256 (ref = hash)
|
|
(luego se publica un mensaje con ese ref dentro de content)
|
|
|
|
MOSTRAR / DESCARGAR:
|
|
vista genera <img src="/blob/&xxx.sha256"> ó markdown.js resuelve menciones
|
|
|
|
|
v
|
|
backend.js ruta /blob/:id --> blobHandler.js
|
|
ssb.blobs.has(id)? --- no ---> ssb.blobs.want(id) ~~~~~~~~~~~~~~~~~>
|
|
| (gossip "want/has" a los peers)
|
|
+-- si ---> ssb.blobs.get(id) -> pull-stream -> ctx.body (bytes)
|
|
|
|
límite: 50 MB (ssb_config.js #17-19)
|
|
|
|
|
|
================================================================================
|
|
4. RENDER: cómo la VISTA construye HTML (hyperaxe, sin .html)
|
|
================================================================================
|
|
|
|
src/views/xxx_view.js
|
|
require("../server/node_modules/hyperaxe") -> div(), form(), section()...
|
|
require('./main_views') -> { template, i18n, userLink, markdown, chips }
|
|
|
|
exports.xView(datos) =
|
|
template( i18n.xTitle, // <- LAYOUT global
|
|
section( h2(i18n.xTitle), ...lista... ) )
|
|
|
|
|
v
|
|
main_views.js :: template(titulo, ...elems) #1017..#1321
|
|
html
|
|
+- head: <title> · CSS · /assets/themes/<tema>.css (oasis-config.themes)
|
|
+- body
|
|
+- header (logo, inbox badge <- shared-state, publish, search)
|
|
+- sidebar-left = navGroup(...) { renderXxxLink() por módulo }
|
|
| navLink({href,emoji,text}) #327
|
|
| renderGamesLink() #898 -> si gamesMod==='on' (config-manager)
|
|
+- main-content = tus secciones
|
|
|
|
i18n: objeto compartido mutado por setLanguage(lang) (11 idiomas)
|
|
backend middleware lo fija por cookie en cada request
|
|
markdown.js: ssb-markdown -> resuelve @feed,%msg,&blob,#hashtag a rutas /...
|
|
|
|
|
|
================================================================================
|
|
5. GRAFO DE DEPENDENCIAS ENTRE ARCHIVOS
|
|
================================================================================
|
|
|
|
src/backend/backend.js (orquestador central)
|
|
|--require--> ../client/gui.js .................. cooler (conexión SSB)
|
|
|--require--> ../client/middleware.js ........... http server Koa
|
|
|--require--> ../configs/config-manager.js ...... getConfig/saveConfig
|
|
|--require--> ../configs/shared-state.js ........ estado en memoria
|
|
|--require--> ./sanitizeHtml.js / ./blobHandler.js
|
|
|--require--> ../server/SSB_server.js ........... config + (sbot in-process)
|
|
|--require--> ../models/*_model.js (factories: ({cooler,deps}))
|
|
| |--inyecta--> otros modelos (agenda<-tasks,events,market..)
|
|
| |--inyecta--> *Crypto (crypto.js por dominio)
|
|
|--require--> ../views/*_view.js (funciones de render)
|
|
|
|
src/models/xxx_model.js
|
|
|--require--> pull-stream · moment
|
|
|--require--> ./tombstone_validator.js (función pura, sin deps)
|
|
|--require--> ../configs/config-manager.js
|
|
|--recibe----> cooler (NO importa gui directamente)
|
|
|
|
src/views/xxx_view.js
|
|
|--require--> hyperaxe
|
|
|--require--> ./main_views.js { template, i18n, userLink, helpers }
|
|
|--require--> moment · (a veces) ../server/SSB_server (feedId propio)
|
|
|
|
src/views/main_views.js (el "framework" de vistas)
|
|
|--require--> hyperaxe · lodash · highlight.js · qrcode · moment
|
|
|--require--> ./markdown.js · ../backend/renderUrl.js · ./sanitizeHtml?
|
|
|--require--> ../backend/nameCache.js (Map nombres <- main_models warmup)
|
|
|--require--> ../client/gui.js · ../configs/{config-manager,shared-state}
|
|
|--require--> ../client/assets/translations/i18n.js (11 idiomas)
|
|
|
|
src/server/SSB_server.js (sbot)
|
|
|--require--> secret-stack · ssb-caps · ssb-db · plugins ssb-*
|
|
|--require--> ./ssb_config.js (<- server-config.json) · ./ssb_metadata.js
|
|
|--require--> ./lanRouter.js (descubrimiento LAN)
|
|
|
|
|
|
================================================================================
|
|
6. EL MÓDULO GAMES, DE PRINCIPIO A FIN (ejemplo concreto)
|
|
================================================================================
|
|
|
|
MENU main_views.js #898 renderGamesLink() --(gamesMod==on)--> /games
|
|
|
|
|
LOBBY backend.js #1358 GET /games |
|
|
checkMod #170 -> gamesModel.getHallOfFame() #40 ----------+
|
|
| pull(createLogStream) |
|
|
| filter type==='gameScore' |
|
|
| best[game:author]=max(score) |
|
|
gamesView(filter,hall) #95 -> HTML |
|
|
|
|
|
PLAY GET /games/:name #1364 -> gameShellView(name) #60 |
|
|
<iframe src="/game-assets/<name>/index.html"> |
|
|
| |
|
|
STATIC middleware.js #109 mount('/game-assets', src/games/) ~~disk~+
|
|
|
|
|
JUEGO src/games/<name>/index.html (HTML+CSS+JS inline, canvas)
|
|
al terminar: form POST -> /games/submit-score target=_top
|
|
|
|
|
SCORE POST /games/submit-score #1369
|
|
gamesModel.submitScore(game,score) #28
|
|
ssb.publish({type:'gameScore',game,score}) ~~> SSB log
|
|
redirect /games?filter=scoring -> Hall of Fame
|
|
|
|
LISTAS A SINCRONIZAR (sin registro central):
|
|
games_view.js getGames() #5 + VALID_GAME_IDS #58 (16 juegos)
|
|
games_model.js VALID_GAMES #5 (14 -> falta rps,audio)
|
|
backend.js listas módulos #1346 #7038 #7054 #7040 ('games')
|
|
oasis-config.json modules.gamesMod
|
|
modules_view.js array modules #23
|
|
oasis_*.js gamesTitle, games<Nombre>Title/Desc (x11 idiomas)
|
|
|
|
|
|
================================================================================
|
|
7. CONFIG Y ESTADO (puntos de coordinación transversal)
|
|
================================================================================
|
|
|
|
oasis-config.json <--getConfig()/saveConfig()--> config-manager.js
|
|
| modules.{xMod:on/off} themes.current ux.current language
|
|
| wish pmVisibility lanBroadcasting ssbLogStream.limit wallet
|
|
+--leen--> backend.js (checkMod) · main_views (render links/tema) · modelos
|
|
|
|
server-config.json <-- ssb_config.js --> SSB_server.js
|
|
| caps.shs (red privada) friends.hops=2 connections (puerto 8008, unix)
|
|
|
|
shared-state.js (memoria, NO persistente)
|
|
| inboxCount carbon peersOnline ecoValue lastRefresh
|
|
+--escribe--> middleware refresco 60s +--lee--> main_views (badges)
|
|
|
|
nameCache.js (Map en memoria)
|
|
+--alimenta--> main_models._startNameWarmup (escucha 'about' en live)
|
|
+--consume---> main_models.about · main_views (mostrar nombres)
|
|
|
|
|
|
================================================================================
|
|
RESUMEN EN UNA FRASE
|
|
================================================================================
|
|
backend.js enruta -> el MODELO persiste/lee mensajes tipados en el log SSB
|
|
(replicado P2P por hops) y los blobs por want/has -> la VISTA (hyperaxe)
|
|
los pinta dentro de template() con i18n y tema -> y todo módulo se activa con
|
|
un flag xMod en oasis-config.json comprobado por checkMod().
|
|
================================================================================
|