vanilla-native-federation
Version:
A lightweight **runtime micro frontend orchestrator** that loads micro frontends built with native federation into any web page. It can cache dependencies across page reloads, making it perfect for traditional server-rendered hosts (PHP, Java, Rails, etc.
8 lines (7 loc) • 7.37 kB
Source Map (JSON)
{
"version": 3,
"sources": ["../../src/lib/2.app/flows/registry/setup-registry.ts"],
"sourcesContent": ["import type {\n NFEventConsumer,\n NFEventData,\n NFEventProvider,\n NFEventUnsubscribe,\n} from '../../../1.domain/registry/event.contract';\nimport type { ForManagingEvents } from 'lib/2.app/driver-ports/registry/for-managing-events.port';\nimport type { NFEventRegistryConfig } from 'lib/2.app/config/registry.contract';\n\nexport function createRegistry(opts: NFEventRegistryConfig): ForManagingEvents {\n // resources\n const resources = new Map<string, unknown>();\n const pending = new Map<string, Set<NFEventConsumer<any>>>();\n\n // events\n const events = new Map<string, NFEventData[]>();\n const listeners = new Map<string, Set<NFEventConsumer<NFEventData<any>>>>();\n const recentlyUsedEvents = new Set<string>();\n\n const REMOVE_EVENTS = Math.ceil(opts.maxEvents * opts.removePercentage);\n\n /**\n * RESOURCE: Register a resource by name. If the resource is a provider function, it is\n * invoked to obtain the actual resource. All callbacks waiting for this\n * resource via `onReady` are invoked once the resource is registered.\n */\n const register = async <T>(type: string, resource: T | NFEventProvider<T>): Promise<void> => {\n const value =\n typeof resource === 'function' ? await (resource as NFEventProvider<T>)() : resource;\n\n resources.set(type, value);\n\n const callbacks = pending.get(type);\n if (callbacks) {\n pending.delete(type);\n callbacks.forEach(cb => cb(value));\n }\n };\n\n /**\n * RESOURCE: Subscribe to the readiness of a resource. If the resource is already\n * registered, the callback is invoked immediately. Otherwise, the callback\n * is invoked once the resource is registered.\n */\n const onReady = <T>(type: string, callback: NFEventConsumer<T>): NFEventUnsubscribe => {\n const existing = resources.get(type);\n if (existing !== undefined) {\n callback(existing as T);\n return () => {};\n }\n\n let callbacks = pending.get(type);\n if (!callbacks) {\n callbacks = new Set();\n pending.set(type, callbacks);\n }\n callbacks.add(callback);\n\n return () => {\n callbacks!.delete(callback);\n if (callbacks!.size === 0) {\n pending.delete(type);\n }\n };\n };\n\n /**\n * EVENT: Subscribe to events of a specific type. The callback is invoked for all\n * past events of that type, and for all future events.\n */\n const on = <T>(type: string, callback: NFEventConsumer<NFEventData<T>>): NFEventUnsubscribe => {\n const history = events.get(type);\n const historyCopy = history ? [...history] : null;\n\n let typeListeners = listeners.get(type);\n if (!typeListeners) {\n typeListeners = new Set();\n listeners.set(type, typeListeners);\n }\n typeListeners.add(callback);\n\n if (historyCopy && historyCopy.length > 0) {\n queueMicrotask(() => {\n historyCopy.forEach(event => callback(event));\n });\n }\n\n return () => {\n typeListeners!.delete(callback);\n if (typeListeners!.size === 0) {\n listeners.delete(type);\n }\n };\n };\n\n /**\n * Emit an event of a specific type with associated data. The event is stored\n * in the history for that type, and all listeners subscribed to that type are\n * invoked with the new event. If the number of stored events exceeds\n * the maximum, the oldest events are removed based on the configured\n * removal percentage. If the number of event types exceeds the maximum,\n * the oldest event type and its history are removed.\n */\n const emit = <T>(type: string, data: T): void => {\n const event: NFEventData<T> = {\n data,\n timestamp: Date.now(),\n };\n\n recentlyUsedEvents.delete(type);\n recentlyUsedEvents.add(type);\n\n if (recentlyUsedEvents.size > opts.maxStreams) {\n const oldest = recentlyUsedEvents.values().next().value;\n if (oldest) {\n recentlyUsedEvents.delete(oldest);\n events.delete(oldest);\n }\n }\n\n let history = events.get(type) || [];\n history.push(event);\n\n if (history.length > opts.maxEvents) {\n history = history.slice(-(opts.maxEvents - REMOVE_EVENTS));\n }\n\n events.set(type, history);\n\n const typeListeners = listeners.get(type);\n if (typeListeners && typeListeners.size > 0) {\n typeListeners.forEach(listener => listener(event));\n }\n };\n\n const clear = (type?: string): void => {\n if (type) {\n // Clear event-related data\n events.delete(type);\n listeners.delete(type);\n\n // Clear resource-related data\n resources.delete(type);\n pending.delete(type);\n\n recentlyUsedEvents.delete(type);\n } else {\n // Clear all data\n events.clear();\n listeners.clear();\n pending.clear();\n resources.clear();\n recentlyUsedEvents.clear();\n }\n };\n\n return () => ({\n register,\n onReady,\n emit,\n on,\n clear,\n });\n}\n"],
"mappings": "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",
"names": []
}