@nitrogenbuilder/client-core
Version:
Nitrogen Builder Core Client
127 lines (108 loc) • 3.57 kB
text/typescript
import type {
BuilderModule,
ComponentSettings,
Module,
} from '@nitrogenbuilder/types';
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) {
console.log(
'getting Nitrogen.moduleData, ' + moduleId,
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
// TODO: Replace module.props with a modified props that includes the dynamicData. Same logic as in the <NitrogenRenderer /> component.
const data = await Nitrogen.moduleDataFetchers.get(moduleName)!(
module.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);
}
console.log('Nitrogen.modules', Nitrogen.modules, 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();