Skip to content

Estructura de la interfaz de Verticales

En este proyecto manejamos una arquitectura basada en verticales. Cada vertical representa un dominio o línea de negocio con sus propias configuraciones, servicios y tipos de datos. Los servicios están tipados con TypeScript para asegurar la consistencia y evitar errores en tiempo de compilación.


Define los servicios básicos que deben estar presentes en la mayoría o todos los verticales. Cada función acepta ciertos parámetros y retorna un tipo específico.

interface CommonServices {
getAllContentsPage: FunctionService<unknown>;
getBlogBySlug: FunctionService<Blog, FilterParams>;
getBlogs: FunctionService<Blog[], FilterParams>;
getChangePassword: FunctionService<
ChangePasswordResponse | unknown,
ChangePasswordPayload
>;
getCoursePage: FunctionService<unknown>;
getEpisodesBySlug: FunctionService<Episode, Slug>;
getExperts: FunctionService<ExpertCardItem[], FilterParams>;
getExpertsBySlug: FunctionService<Expert, FilterParams>;
getForgotPassword: FunctionService<
ForgotPasswordResponse | unknown,
ForgotPasswordPayload
>;
getHomePage: FunctionService<unknown>;
getLegalPages: FunctionService<LegalPagesApi, FilterParams>;
getModuleCategories: FunctionService<
CategoriesByModule,
ModuleCategoriesParams
>;
getMastersPage: FunctionService<unknown>;
getPartners: FunctionService<Partner[], FilterParams>;
getPartnersBySlug: FunctionService<Partner, FilterParams>;
getSeriesByCategory: FunctionService<FilteredSeriesByCategory, FilterParams>;
getSeriesBySlug: FunctionService<Serie, FilterParams>;
getSeriesPage: FunctionService<Serie, FilterParams>;
getUserLogin: FunctionService<Strapi<LoginResponse>, LoginPayload>;
getUserRegistration: FunctionService<
Strapi<RegisteredUser>,
UserRegistrationPayload
>;
}

Notas:

  • No se permite que los tipos de retorno usen ? (opcionales) para forzar la implementación.
  • Si un servicio no aplica a un vertical, se omite en ese vertical.

Servicios específicos que solo ciertos verticales implementan, por ejemplo:

interface SpecificServices {
getDentalProcedure: FunctionService<{
products: (BuyCardItem | ConsultativeCardItem)[];
}>;
getPremiumPage: FunctionService<PremiumPage>;
getInspiriaTalks: FunctionService<TalksCard[], FilterParams>;
}

Representa la configuración general de un vertical.

export interface Verticals {
analyticsCode?: string;
developmentApi: `http://localhost:${number}`;
exclusivePages?: LayoutPage[];
favicon: string;
i18nDirectory: string;
layoutDirectory: string;
localeDirectory: string;
name: string;
primaryColor: string;
productionApi: string;
productionURL: string;
secondaryColor: string;
services: CommonServices & Partial<SpecificServices>;
strapiService:
| "inspiria"
| "traumatologia"
| "emergencias"
| "salud mental"
| "oncologia"
| "pharma";
subdomain: string;
verticalLogo: string;
zohoConfig?: ZohoConfig;
}

  • Para controlar qué servicios específicos o comunes implementa cada vertical, existen interfaces derivadas que extienden la interfaz base Verticals.
  • Para ello usaremos el patrón Omit de TypeScript para excluir el campo services y luego definirlo con los servicios específicos requeridos.
  • Usaremos Pick y Omit para definir qué servicios específicos se implementan en cada vertical.
export interface TraumatologyVertical extends Omit<Verticals, "services"> {
services: CommonServices & {};
}
export interface InspiriaVertical extends Omit<Verticals, "services"> {
services: CommonServices &
Pick<
SpecificServices,
"getPremiumPage" | "getDentalProcedure" | "getInspiriaTalks"
>;
}
export interface EmergencyVertical extends Omit<Verticals, "services"> {
services: CommonServices & Pick<SpecificServices, "getPremiumPage"> & {};
}
export interface OncologyVertical extends Omit<Verticals, "services"> {
services: Omit<
CommonServices,
| "getCoursePage"
| "getAllContentsPage"
| "getHomePage"
| "getMastersPage"
| "getEpisodesBySlug"
| "getSeriesByCategory"
| "getSeriesBySlug"
| "getSeriesPage"
> & {};
}
export interface MentalHealthVertical extends Omit<Verticals, "services"> {
services: CommonServices & {};
}
export interface PharmaVertical extends Omit<Verticals, "services"> {
services: Omit<
CommonServices,
| "getMastersPage"
| "getEpisodesBySlug"
| "getSeriesByCategory"
| "getSeriesBySlug"
| "getSeriesPage"
| "getModuleCategories"
> & {};
}

Implementación de un Vertical Ejemplo: Pharma

Section titled “Implementación de un Vertical Ejemplo: Pharma”

Este vertical es un ejemplo concreto que implementa solo CommonServices sin servicios específicos.

export const PHARMA: PharmaVertical = {
name: "pharma",
subdomain: "pharma",
i18nDirectory: "pharma",
primaryColor: "#7049bc",
secondaryColor: "#00edc8",
productionURL: "https://pharma.alebateducation.com/",
productionApi: "https://multiverticales.alebateducation.com/",
developmentApi: "http://localhost:1337",
favicon: "/favicon-pharma.png",
verticalLogo: "/logo-pharma.svg",
strapiService: "pharma",
services: {
getExperts: async (lang, vertical: FilterParams) =>
await getExperts(lang, vertical),
getExpertsBySlug: async (lang, { slug, vertical }: FilterParams) =>
await getExpertsBySlug(lang, { slug, vertical }),
getHomePage: getPharmaHomePage,
getCoursePage: getPharmaCoursePage,
getPartners: async (lang, vertical: FilterParams) =>
await getPartners(lang, vertical),
getPartnersBySlug: async (lang, { slug, vertical }: FilterParams) =>
await getPartnersBySlug(lang, { slug, vertical }),
getBlogs: async (lang, vertical: FilterParams) =>
await getBlogs(lang, vertical),
getBlogBySlug: async (lang, { slug, vertical }: FilterParams) =>
await getBlogBySlug(lang, { slug, vertical }),
getAllContentsPage: async (lang) => await getAllContents(lang),
getLegalPages: async (lang) => await getLegalPages(lang),
getUserRegistration: registerUserForVertical,
getUserLogin: loginUserForVertical,
getForgotPassword: forgotPasswordForVertical,
getChangePassword: changePasswordForVertical,
},
localeDirectory: "pharma",
layoutDirectory: "pharma",
analyticsCode: "G-L001MXFYPR",
};

Hemos omitido getMastersPage, getEpisodesBySlug, getSeriesByCategory, getSeriesBySlug, getSeriesPage, etc. porque no son relevantes para este vertical.

Puntos importantes:

  • Se definen las URLs de producción y desarrollo.
  • Se asignan los servicios implementados con funciones asincrónicas.
  • Algunos servicios no implementados lanzan errores para evitar uso accidental.
  • Se incluye configuración visual y de i18n (localización).

  1. Crear una interfaz que extienda Verticals (ejemplo: MyNewVertical).
  2. Implementar los servicios necesarios siguiendo CommonServices y/o SpecificServices.
  3. Definir la configuración visual y URLs propias.
  4. Registrar el vertical en la configuración general del proyecto.

  • No implementar un servicio obligatorio: Puede causar fallos en runtime. Mejor lanzar errores explícitos como en TRAUMATOLOGY.
  • Usar tipos incorrectos: Siempre usar los tipos definidos para parámetros y respuestas.
  • No manejar idiomas: Siempre pasar el parámetro lang para asegurar la localización.
  • Usar ? en tipos de retorno: No permitido en CommonServices, para asegurar implementación.

Este sistema tipado y modular facilita la escalabilidad y mantenimiento de verticales en el proyecto, asegurando que cada vertical implemente solo los servicios necesarios y con un contrato claro.