arch(sprint1): drive widget registry from manifest

This commit is contained in:
sdarbinyan
2026-07-03 02:07:12 +04:00
parent 8132c1a535
commit 8d47920fa3
3 changed files with 93 additions and 15 deletions

View File

@@ -1,16 +1,59 @@
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable, map, of } from 'rxjs';
import { catchError } from 'rxjs/operators';
import { HeroWidgetComponent, FooterNavigationWidgetComponent, ProductCarouselWidgetComponent } from '../ui';
import { RegisteredWidget } from '../contracts/widget-component.contract';
import { WidgetRegistryService } from './widget-registry.service';
interface WidgetManifestItem {
type: string;
version: string;
componentKey: string;
enabled?: boolean;
}
interface WidgetManifest {
widgets: WidgetManifestItem[];
}
const APPROVED_WIDGET_COMPONENTS: Record<string, RegisteredWidget['component']> = {
'hero': HeroWidgetComponent,
'footer-navigation': FooterNavigationWidgetComponent,
'product-carousel': ProductCarouselWidgetComponent
};
@Injectable({ providedIn: 'root' })
export class WidgetRegistryBootstrapService {
constructor(private readonly registry: WidgetRegistryService) {}
private readonly manifestUrl = '/assets/mock/bootstrap/widget-manifest.json';
registerDefaults(): void {
this.registry.registerMany([
{ type: 'hero', version: '1.0.0', component: HeroWidgetComponent },
{ type: 'footer-navigation', version: '1.0.0', component: FooterNavigationWidgetComponent },
{ type: 'product-carousel', version: '1.0.0', component: ProductCarouselWidgetComponent }
]);
constructor(
private readonly registry: WidgetRegistryService,
private readonly http: HttpClient
) {}
registerFromManifest(): Observable<void> {
return this.http.get<WidgetManifest>(this.manifestUrl).pipe(
map((manifest) => {
const widgets = (manifest.widgets ?? [])
.filter((item) => item.enabled !== false)
.map((item): RegisteredWidget | null => {
const component = APPROVED_WIDGET_COMPONENTS[item.componentKey];
if (!component) {
return null;
}
return {
type: item.type,
version: item.version,
component
};
})
.filter((item): item is RegisteredWidget => item !== null);
this.registry.registerMany(widgets);
}),
catchError(() => of(undefined))
);
}
}