UNPKG

@nitrogenbuilder/client-core

Version:

Nitrogen Builder Core Client

131 lines (111 loc) 3.77 kB
import type { BuilderModule, ComponentSettings, Module, } from '@nitrogenbuilder/types'; import { logger } from './utils/logger.js'; import { updateModuleProps } from './utils/updateWithDefaultProps.js'; export class Nitrogen { static instance: Nitrogen; static modules = new Map<string, Module>(); static moduleComponents = new Map<string, any>(); static moduleDataFetchers = new Map<string, (props: any) => Promise<any>>(); // The idea hereis that the moduleData map key is a cache key. The first item in the array is always the moduleId. // This logic is not yet implemented. Right now it only works with one array item which is the moduleId. static moduleData = new Map<string[], any>(); constructor() { if (Nitrogen.instance) { return Nitrogen.instance; } Nitrogen.instance = this; } getModule(moduleId: string | number) { return Nitrogen.modules.get(`${moduleId}`); } getModuleComponent(moduleId: string | number) { return Nitrogen.moduleComponents.get(`${moduleId}`); } getModuleData(moduleId: string | number) { logger.log( 'getting Nitrogen.moduleData, ' + moduleId, { context: { moduleData: Nitrogen.moduleData.get([`${moduleId}`]) } } ); return Nitrogen.moduleData.get([`${moduleId}`]); } getModuleDataFetcher(moduleId: string | number) { return Nitrogen.moduleDataFetchers.get(`${moduleId}`); } async getRequestedData({ page, dynamicData, }: { page: BuilderModule[]; dynamicData?: any; }) { async function recursiveGetRequestedData(modules: BuilderModule[]) { for (let i = 0; i < modules.length; i++) { const module = modules[i]; if (module.module) { const moduleId = module.id; const moduleName = typeof module.module === 'object' ? module.module.name : module.module; if (Nitrogen.moduleDataFetchers.has(moduleName)) { // We know we have a data fetcher for this module because of the if statement above // Update module props with defaults and dynamic data before passing to the data fetcher const updatedModule = updateModuleProps(module, dynamicData); const data = await Nitrogen.moduleDataFetchers.get(moduleName)!( updatedModule.props ); Nitrogen.moduleData.set([`${moduleId}`], data); } } // TODO: Figure out if I can combine these with a Promise.all() type call if (module.props?.children) { if (Array.isArray(module.props.children)) { await recursiveGetRequestedData(module.props.children); } else if (typeof module.props.children === 'object') { for (let slot in module.props.children) { await recursiveGetRequestedData(module.props.children[slot]); } } } } } await recursiveGetRequestedData(page); return Object.fromEntries(Nitrogen.moduleData); } registerModule( moduleId: string | number, Component: any, module: ComponentSettings, getData?: (props: any) => Promise<any> ) { Nitrogen.modules.set(`${moduleId}`, { ...module, name: `${moduleId}`, id: moduleId, } as Module); // overwriting the type so we can sneak in the id field Nitrogen.moduleComponents.set(`${moduleId}`, Component); if (getData) { Nitrogen.moduleDataFetchers.set(`${moduleId}`, getData); } logger.log('Nitrogen.modules', { context: { modules: Nitrogen.modules, windowType: typeof window } }); if (typeof window !== 'undefined') { const event = new CustomEvent('nitrogen-modules', { detail: { modules: Object.fromEntries(Nitrogen.modules), }, }); if (window?.nitrogen?.parentInit) { window.dispatchEvent(event); } else { window.addEventListener('nitrogen-initialized', () => { window.dispatchEvent(event); }); } } } } export const nitrogen = new Nitrogen();