import { BrowserEventDispatcher } from '@wlindabla/event_dispatcher/browser'; import { CRUDPageType, APP_ENV } from './types.cjs'; import { SpaExtensionContextInterface, SpaRouterInterface, RouteResolverInterface, RequestMatcherInterface, HistoryManagerInterface, BindingManagerInterface } from './contracts.cjs'; import '@wlindabla/form_validator/utils'; import '@wlindabla/http_client'; import '@wlindabla/event_dispatcher'; /** * @wlindabla/sonata_spa — SpaKernelExtensionInterface & SpaExtensionContext * Extension system for SpaKernel — inspired by Sonata AdminExtension pattern. * Allows developers to extend the SPA kernel without inheriting from it. * @author AGBOKOUDJO Franck */ /** * Limited view of SpaKernel exposed to extensions. * * Inspired by Sonata's pattern of passing a dedicated mapper object * (FormMapper, ListMapper) instead of the full Admin instance. * Extensions receive only what they are allowed to touch — not the kernel itself. * * Available capabilities: * - Register subscribers on the event dispatcher * - Register binding managers * - Add custom route patterns to RouteResolver * - Add custom server-managed URL patterns to RequestMatcher * - Add custom CRUD event name mappings * - Navigate programmatically * - Read DOM references (container, content area) * - Read environment parameters * * @example * ```typescript * class MyExtension implements SpaKernelExtensionInterface { * registerSubscribers(context: SpaExtensionContext): void { * context.getDispatcher().addSubscriber(new MySubscriber()); * } * * registerBindingManagers(context: SpaExtensionContext): void { * context.registerBindingManager( * new MyBindingManager(context.getMainContainer(), context.getRouter()) * ); * } * * registerRoutePatterns(context: SpaExtensionContext): void { * context.addRoutePattern(/\/approval(\/)?(\?.*)?$/, 'approval'); * } * } * ``` */ declare class SpaExtensionContext implements SpaExtensionContextInterface { private readonly _dispatcher; private readonly _router; private readonly _routeResolver; private readonly _requestMatcher; private readonly _historyManager; private readonly _mainContainer; private readonly _mainContentArea; private readonly _mainContentHeader; private readonly _crudEventMap; private readonly _bindingManagerRegistry; /** * @internal — constructed by SpaKernel only. Not part of the public API. */ constructor(_dispatcher: BrowserEventDispatcher, _router: SpaRouterInterface, _routeResolver: RouteResolverInterface, _requestMatcher: RequestMatcherInterface, _historyManager: HistoryManagerInterface, _mainContainer: HTMLElement, _mainContentArea: HTMLElement, _mainContentHeader: HTMLElement | null, _crudEventMap: Map, _bindingManagerRegistry: (manager: BindingManagerInterface) => void); /** * Returns the shared BrowserEventDispatcher instance. * Use this to register subscribers or raw listeners. * * @example * ```typescript * context.getDispatcher().addSubscriber(new MySubscriber()); * context.getDispatcher().addListener(SpaEvents.DOM_READY, handler); * ``` */ getDispatcher(): BrowserEventDispatcher; /** * Returns the SpaRouter instance for programmatic navigation. * * @example * ```typescript * await context.getRouter().navigate('/admin/app/user/list'); * ``` */ getRouter(): SpaRouterInterface; /** * Programmatically navigate to a URL. * Shorthand for context.getRouter().navigate(url). * * @param url - The destination URL */ navigate(url: string): Promise; /** * Returns the RouteResolver instance. * Use this to resolve URLs to RouteMatch objects in your extension. */ getRouteResolver(): RouteResolverInterface; /** * Add a custom URL pattern to the RouteResolver. * The pattern is inserted at the beginning of the suffix map * so it takes precedence over built-in patterns. * * @param pattern - The RegExp to match against the URL pathname * @param pageType - The CRUDPageType (or custom string) to assign * * @example * ```typescript * // Add support for a custom /approval page type * context.addRoutePattern(/\/approval(\/)?(\?.*)?$/, 'approval'); * ``` */ addRoutePattern(pattern: RegExp, pageType: CRUDPageType | string): void; /** * Returns the RequestMatcher instance. */ getRequestMatcher(): RequestMatcherInterface; /** * Add a custom server-managed URL pattern. * URLs matching this pattern will trigger a full page reload * instead of SPA navigation. * * @param pattern - The RegExp to match against the URL * * @example * ```typescript * // Force full reload for /export URLs * context.addServerManagedUrl(/\/export(\?.*)?$/); * ``` */ addServerManagedUrl(pattern: RegExp): void; /** * Register a custom CRUD event name for a given page type. * The kernel uses this map in dispatchCrudEvent() to resolve * which event name to dispatch for a given RouteMatch. * * @param pageType - The custom page type (e.g. 'approval') * @param eventName - The event name constant (e.g. 'crud:approval') * * @example * ```typescript * context.addCrudEventName('approval', 'crud:approval'); * // Then listen: * context.getDispatcher().addListener('crud:approval', handler); * ``` */ addCrudEventName(pageType: string, eventName: string): void; /** * Register a custom BindingManager. * The kernel will call bind() immediately and rebind() after each DOM swap. * * @param manager - The BindingManager to register * * @example * ```typescript * context.registerBindingManager( * new MyBindingManager(context.getMainContainer(), context.getRouter()) * ); * ``` */ registerBindingManager(manager: BindingManagerInterface): void; /** * Returns the HistoryManager instance. * Use this to push or replace history entries from your extension. */ getHistoryManager(): HistoryManagerInterface; /** * Returns the main container element (wraps the full admin content area). */ getMainContainer(): HTMLElement; /** * Returns the main content area element (swapped on each navigation). */ getMainContentArea(): HTMLElement; /** * Returns the main content header element, or null if absent. * Not present on all pages (e.g. dashboard). */ getMainContentHeader(): HTMLElement | null; /** * Returns the current application environment. * Reads from SpaParameterBag — set by SpaKernel during construction. * * @returns 'prod' | 'dev' | 'test' */ getEnv(): APP_ENV; /** * Returns true when the application runs in debug mode. */ isDebug(): boolean; } export { SpaExtensionContext };