UNPKG

gold-sight

Version:

Test your code on realistic content, precisely

343 lines 11.6 kB
class EventBus { constructor(events = {}) { this.isEventBus = true; this.events = {}; this.overwrittenEvents = {}; this.emitOnceEvents = {}; this.events = events; } emit(name, ctx, payload) { if (!payload) payload = {}; const newEvent = { name, payload, uuidStack: ctx.eventUUIDs, funcData: ctx.funcData, eventUUID: ctx.eventUUID, }; let events = this.events[name]; if (!events) { events = this.events[name] = []; } events.push(newEvent); return newEvent; } emitOne(name, uuid, key, payload) { const exisitingEvents = filterEventsByPayload(this, "*", key); for (const [name, events] of Object.entries(this.events)) { this.events[name] = events.filter((event) => !exisitingEvents.includes(event)); } for (const event of exisitingEvents) { if (!this.overwrittenEvents[event.name]) { this.overwrittenEvents[event.name] = []; } this.overwrittenEvents[event.name].push(event); } if (!payload) payload = {}; payload = { ...payload, ...key }; return this.emit(name, uuid, payload); } emitOnce(name, ctx, payload) { let emitOnceEvents = this.emitOnceEvents[name]; if (!emitOnceEvents) this.emitOnceEvents[name] = emitOnceEvents = []; if (emitOnceEvents.find((event) => event.uuidStack.includes(ctx.eventUUID))) return null; emitOnceEvents.push({ name, payload, uuidStack: ctx.eventUUIDs, funcData: ctx.funcData, eventUUID: ctx.eventUUID, }); return this.emit(name, ctx, payload); } getAllEventsForUUID(uuid) { let events = Object.values(this.events).flat(); events = events.concat(Object.values(this.overwrittenEvents).flat()); return filterEventsByUUID(events, uuid, undefined, { includeRecursive: true, }); } filterEventsByName(name, options) { return filterEventsByName(this, name, options); } getEventByState(name, state, options) { return getEventByState(this, name, state, options); } getEventByPayload(name, payload, options) { return getEventByPayload(this, name, payload, options); } getEvent(name, payload, state, options) { return getEvent(this, name, payload, state, options); } getEventByUUID(name, uuid, funcData, options) { return getEventByUUID(this, name, uuid, funcData, options); } filterEventsByState(name, state, options) { return filterEventsByState(this, name, state, options); } filterEventsByPayload(name, payload, options) { return filterEventsByPayload(this, name, payload, options); } filterEvents(name, payload, state, options) { return filterEvents(this, name, payload, state, options); } } function getEventBus(args) { for (const arg of args) { if (arg?.isEventBus) return arg; if (typeof arg === "object") { if ("events" in arg) { return arg.events; } if ("eventBus" in arg) { return arg.eventBus; } if ("event" in arg) { return arg.event; } for (const value of Object.values(arg)) { if (value?.isEventBus) return value; } } } return null; } function getEventUUID(args) { for (const arg of args) { if (typeof arg === "object" && "eventUUID" in arg) { return arg.eventUUID; } } return undefined; } function getFuncData(args) { for (const arg of args) { if (typeof arg === "object" && "funcData" in arg) { return arg.funcData; } } } function getEventByState(eventBus, name, state, options) { const events = filterEventsByName(eventBus, name, options); const event = events.find((e) => { for (const key in state) { if (state[key] !== e.state[key]) { return false; } } return true; }); return event || null; } function getEventByPayload(eventBus, name, payload, options) { const events = filterEventsByName(eventBus, name, options); const event = events.find((e) => { for (const key in payload) { if (payload[key] !== e.payload[key]) { return false; } } return true; }); return event || null; } function getEvent(eventBus, name, payload, state, options) { const events = filterEventsByName(eventBus, name, options); const event = events.find((e) => { for (const key in state) { if (state[key] !== e.state[key]) { return false; } } for (const key in payload) { if (payload[key] !== e.payload[key]) { return false; } } return true; }); return event || null; } function getEventByUUID(eventBus, name, uuid, funcData, options) { let events = filterEventsByName(eventBus, name, options); events = events.filter((event) => event.uuidStack.includes(uuid)); if (funcData && !options?.includeRecursive) { events = filterRecursion(events, funcData); } return events[0] || null; } function filterRecursion(events, funcData) { const names = new Set([...events.map((e) => e.funcData.funcName)]); events = events.filter((e) => { return e.funcData.funcIndex >= funcData.funcIndex; }); let newEvents = []; for (const name of names) { newEvents = newEvents.concat(filterRecursionForName(events, name)); } return newEvents; } function filterRecursionForName(events, name) { events = events.filter((e) => e.funcData.funcName === name); // Helper function to check if stackB extends stackA (stackA is a prefix of stackB) const isExtension = (stackA, stackB) => { if (stackA.length >= stackB.length) return false; return stackA.every((uuid, index) => uuid === stackB[index]); }; // Filter out events that are recursive calls (their uuidStack extends another event's stack) const nonRecursiveEvents = events.filter((event) => { // Check if this event is a recursive call of another event const isRecursive = events.some((otherEvent) => { return (otherEvent !== event && otherEvent.funcData.funcIndex < event.funcData.funcIndex && isExtension(otherEvent.uuidStack, event.uuidStack)); }); return !isRecursive; }); return nonRecursiveEvents; } function filterEventsByState(eventBus, name, state, options) { const events = filterEventsByName(eventBus, name, options); return events.filter((event) => { for (const key in state) { if (state[key] !== event.state[key]) { return false; } } return true; }); } function filterEventsByPayload(eventBus, name, payload, options) { const events = filterEventsByName(eventBus, name, options); return events.filter((event) => { for (const key in payload) { if (payload[key] !== event.payload[key]) { return false; } } return true; }); } function filterEventsByUUID(events, uuid, funcData, options) { events = events.filter((event) => event.uuidStack.includes(uuid)); if (funcData && !options?.includeRecursive) events = filterRecursion(events, funcData); return events; } function filterEvents(eventBus, name, payload, state, options) { let events = filterEventsByName(eventBus, name, options); events = events.filter((event) => { for (const key in payload) { if (payload[key] !== event.payload[key]) { return false; } } return true; }); return events.filter((event) => { for (const key in state) { if (state[key] !== event.state[key]) { return false; } } return true; }); } function withEventBus(args, func) { const eventBus = getEventBus(args); if (!eventBus) { throw new Error("Event bus not found"); } return func(eventBus); } function withEvents(args, func) { const eventBus = getEventBus(args); const eventUUID = getEventUUID(args); const funcData = getFuncData(args); if (!eventBus) { throw new Error("Event bus not found"); } if (!eventUUID) { throw new Error("Event UUID not found"); } if (!funcData) { throw new Error("Function data not found"); } return func(eventBus, eventUUID, funcData); } function withEventNames(args, eventNames, func, options) { const eventBus = getEventBus(args); const eventUUID = getEventUUID(args); if (!eventBus) { throw new Error("Event bus not found"); } if (!eventUUID) { throw new Error("Event UUID not found"); } const funcData = getFuncData(args); const events = []; for (const eventName of eventNames) { events.push(...filterEventsByName(eventBus, eventName, options)); } // Fetch all events into a record keyed by their name const eventsMap = {}; const filteredEvents = filterEventsByUUID(events, eventUUID, funcData, options); for (const event of filteredEvents) { eventsMap[event.name] = event; } return func(eventsMap, eventBus, eventUUID); } function withEventNamesList(args, eventNames, func, options) { const eventBus = getEventBus(args); const eventUUID = getEventUUID(args); if (!eventBus) { throw new Error("Event bus not found"); } if (!eventUUID) { throw new Error("Event UUID not found"); } const funcData = getFuncData(args); const eventsMap = {}; const events = []; for (const eventName of eventNames) { eventsMap[eventName] = []; events.push(...filterEventsByName(eventBus, eventName, options)); } const filteredEvents = filterEventsByUUID(events, eventUUID, funcData, options); for (const event of filteredEvents) { eventsMap[event.name].push(event); } return func(eventsMap, eventBus, eventUUID); } function filterEventsByName(eventBus, name, options) { let events = name === "*" ? Object.values(eventBus.events).flat() : eventBus.events[name]; if (options?.includeOverwritten) { if (name === "*") events = events.concat(Object.values(eventBus.overwrittenEvents).flat()); else events = events.concat(eventBus.overwrittenEvents[name] || []); } if (!events) { return []; } return events; } function makeEventContext() { return { event: new EventBus(), eventUUID: "", eventUUIDs: [], funcData: undefined, }; } export { getEventBus, EventBus, getEventByState, getEventByPayload, getEvent, filterEventsByState, filterEventsByPayload, filterEvents, getEventUUID, getEventByUUID, filterEventsByUUID, withEventBus, withEvents, withEventNames, getFuncData, filterEventsByName, makeEventContext, withEventNamesList, filterRecursion, filterRecursionForName, }; //# sourceMappingURL=eventBus.js.map