function ItoI(a) { return a; } function innerCreateMedium(defaults, middleware = ItoI) { let buffer = []; let assigned = false; const medium = { read() { if (assigned) { throw new Error('Sidecar: could not `read` from an `assigned` medium. `read` could be used only with `useMedium`.'); } if (buffer.length) { return buffer[buffer.length - 1]; } return defaults; }, useMedium(data) { const item = middleware(data, assigned); buffer.push(item); return () => { buffer = buffer.filter((x) => x !== item); }; }, assignSyncMedium(cb) { assigned = true; while (buffer.length) { const cbs = buffer; buffer = []; cbs.forEach(cb); } buffer = { push: (x) => cb(x), filter: () => buffer, }; }, assignMedium(cb) { assigned = true; let pendingQueue = []; if (buffer.length) { const cbs = buffer; buffer = []; cbs.forEach(cb); pendingQueue = buffer; } const executeQueue = () => { const cbs = pendingQueue; pendingQueue = []; cbs.forEach(cb); }; const cycle = () => Promise.resolve().then(executeQueue); cycle(); buffer = { push: (x) => { pendingQueue.push(x); cycle(); }, filter: (filter) => { pendingQueue = pendingQueue.filter(filter); return buffer; }, }; }, }; return medium; } export function createMedium(defaults, middleware = ItoI) { return innerCreateMedium(defaults, middleware); } // eslint-disable-next-line @typescript-eslint/ban-types export function createSidecarMedium(options = {}) { const medium = innerCreateMedium(null); medium.options = { async: true, ssr: false, ...options, }; return medium; }