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.
111 lines (110 loc) • 3.09 kB
JavaScript
// src/lib/2.app/flows/registry/setup-registry.ts
function createRegistry(opts) {
const resources = /* @__PURE__ */ new Map();
const pending = /* @__PURE__ */ new Map();
const events = /* @__PURE__ */ new Map();
const listeners = /* @__PURE__ */ new Map();
const recentlyUsedEvents = /* @__PURE__ */ new Set();
const REMOVE_EVENTS = Math.ceil(opts.maxEvents * opts.removePercentage);
const register = async (type, resource) => {
const value = typeof resource === "function" ? await resource() : resource;
resources.set(type, value);
const callbacks = pending.get(type);
if (callbacks) {
pending.delete(type);
callbacks.forEach((cb) => cb(value));
}
};
const onReady = (type, callback) => {
const existing = resources.get(type);
if (existing !== void 0) {
callback(existing);
return () => {
};
}
let callbacks = pending.get(type);
if (!callbacks) {
callbacks = /* @__PURE__ */ new Set();
pending.set(type, callbacks);
}
callbacks.add(callback);
return () => {
callbacks.delete(callback);
if (callbacks.size === 0) {
pending.delete(type);
}
};
};
const on = (type, callback) => {
const history = events.get(type);
const historyCopy = history ? [...history] : null;
let typeListeners = listeners.get(type);
if (!typeListeners) {
typeListeners = /* @__PURE__ */ new Set();
listeners.set(type, typeListeners);
}
typeListeners.add(callback);
if (historyCopy && historyCopy.length > 0) {
queueMicrotask(() => {
historyCopy.forEach((event) => callback(event));
});
}
return () => {
typeListeners.delete(callback);
if (typeListeners.size === 0) {
listeners.delete(type);
}
};
};
const emit = (type, data) => {
const event = {
data,
timestamp: Date.now()
};
recentlyUsedEvents.delete(type);
recentlyUsedEvents.add(type);
if (recentlyUsedEvents.size > opts.maxStreams) {
const oldest = recentlyUsedEvents.values().next().value;
if (oldest) {
recentlyUsedEvents.delete(oldest);
events.delete(oldest);
}
}
let history = events.get(type) || [];
history.push(event);
if (history.length > opts.maxEvents) {
history = history.slice(-(opts.maxEvents - REMOVE_EVENTS));
}
events.set(type, history);
const typeListeners = listeners.get(type);
if (typeListeners && typeListeners.size > 0) {
typeListeners.forEach((listener) => listener(event));
}
};
const clear = (type) => {
if (type) {
events.delete(type);
listeners.delete(type);
resources.delete(type);
pending.delete(type);
recentlyUsedEvents.delete(type);
} else {
events.clear();
listeners.clear();
pending.clear();
resources.clear();
recentlyUsedEvents.clear();
}
};
return () => ({
register,
onReady,
emit,
on,
clear
});
}
export {
createRegistry
};
//# sourceMappingURL=registry.mjs.map