Add pending apps and frontend components

- apps/captain-mobile: Mobile API service
- apps/flow-ui: Flow UI application
- apps/mindlink: Mindlink application
- apps/storage: Storage API and workers
- apps/tzzr-cli: TZZR CLI tool
- deck-frontend/backups: Historical TypeScript versions
- hst-frontend: Standalone HST frontend

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
ARCHITECT
2026-01-16 18:26:59 +00:00
parent 17506aaee2
commit 9b244138b5
177 changed files with 15063 additions and 0 deletions

View File

@@ -0,0 +1,170 @@
/**
* Module Registry - Tipos e interfaces para el sistema modular
*/
import type { Store } from '@/state/store.ts';
import type { AppState, ViewType, BaseType } from '@/types/index.ts';
// Tipos de renderizado de módulos
export type ModuleRenderType =
| 'standard' // Grid/Tree/Graph normal (taxonomía, atc)
| 'chat' // Interfaz de chat con IA (mail, context)
| 'custom'; // Interfaz completamente custom (key, mindlink)
// Categorías de módulos para agrupar en UI
export type ModuleCategory =
| 'taxonomy' // hst, flg, itm, loc, ply
| 'masters' // mst, bck
| 'registry' // atc, mth
| 'communication' // mail, chat
| 'services'; // key, mindlink
// Configuración de vistas soportadas por módulo
export interface ModuleViews {
grid?: boolean;
tree?: boolean;
graph?: boolean;
custom?: string; // Nombre del componente custom a usar
}
// Configuración de API por módulo
export interface ModuleApiConfig {
schema: string | null; // PostgREST schema (null = public)
table: string; // Tabla principal
hasLibraries?: boolean; // ¿Soporta bibliotecas?
hasGroups?: boolean; // ¿Soporta grupos (set_hst)?
hasGraph?: boolean; // ¿Tiene datos de grafo?
hasTree?: boolean; // ¿Tiene datos de árbol?
}
// Configuración completa de un módulo
export interface BaseConfig {
id: BaseType;
name: string; // Nombre completo
shortName: string; // Para botón (3-4 chars)
category: ModuleCategory;
renderType: ModuleRenderType;
// Vistas soportadas
views: ModuleViews;
defaultView: ViewType | 'custom';
// API
api: ModuleApiConfig;
// Para módulos custom (lazy loading)
customModule?: () => Promise<{ default: new (ctx: ModuleContext) => BaseModule }>;
// Estado inicial específico del módulo
initialState?: Partial<ModuleState>;
// Módulo habilitado (false = mostrar "Próximamente")
enabled?: boolean;
}
// Estado específico de un módulo
export interface ModuleState {
loading: boolean;
error: string | null;
data: unknown;
}
// Contexto pasado a cada módulo
export interface ModuleContext {
container: HTMLElement;
leftPanel: HTMLElement;
groupsBar: HTMLElement;
store: Store<AppState>;
config: BaseConfig;
showDetail: (mrf: string) => void;
}
// Clase base abstracta para módulos
export abstract class BaseModule {
protected ctx: ModuleContext;
protected mounted = false;
protected unsubscribe: (() => void) | null = null;
constructor(ctx: ModuleContext) {
this.ctx = ctx;
}
// Lifecycle
abstract mount(): Promise<void>;
abstract unmount(): void;
abstract render(): void;
// Override para carga de datos específica
async loadData(): Promise<void> {
// Default: no hace nada, subclases implementan
}
// Override para contenido del sidebar (libraries/options)
renderSidebar(): void {
// Default: vacío
this.ctx.leftPanel.innerHTML = '';
}
// Override para barra de grupos
renderGroupsBar(): void {
// Default: vacío
this.ctx.groupsBar.innerHTML = '';
}
// Helpers
protected getState(): Readonly<AppState> {
return this.ctx.store.getState();
}
protected setState(partial: Partial<AppState>): void {
this.ctx.store.setState(partial);
}
protected getConfig(): BaseConfig {
return this.ctx.config;
}
protected subscribe(listener: (state: AppState) => void): void {
this.unsubscribe = this.ctx.store.subscribe(listener);
}
// Verificar si una vista está soportada
protected isViewSupported(view: ViewType): boolean {
return !!this.ctx.config.views[view];
}
}
// Helper para obtener config de módulo
export const getModuleConfig = (configs: Record<BaseType, BaseConfig>, base: BaseType): BaseConfig => {
const config = configs[base];
if (!config) {
throw new Error(`Module config not found for base: ${base}`);
}
return config;
};
// Helper para agrupar módulos por categoría
export const getModulesByCategory = (
configs: Record<BaseType, BaseConfig>
): Record<ModuleCategory, BaseConfig[]> => {
const result: Record<ModuleCategory, BaseConfig[]> = {
taxonomy: [],
masters: [],
registry: [],
communication: [],
services: []
};
Object.values(configs).forEach(config => {
result[config.category].push(config);
});
return result;
};
// Helper para obtener módulos habilitados
export const getEnabledModules = (
configs: Record<BaseType, BaseConfig>
): BaseConfig[] => {
return Object.values(configs).filter(c => c.enabled !== false);
};