json-joy
Version:
Collection of libraries for building collaborative editing apps.
128 lines (127 loc) • 3.61 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.OnNewFanOut = exports.MapFanOut = exports.MicrotaskBufferFanOut = exports.MergeFanOut = void 0;
const fanout_1 = require("thingies/lib/fanout");
/**
* Merges multiple fanouts into a single fanout. The merged fanout emits the
* same data as the source fanouts.
*/
class MergeFanOut extends fanout_1.FanOut {
constructor(fanouts) {
super();
this.fanouts = fanouts;
this.unsubs = [];
}
listen(listener) {
if (!this.listeners.size)
this.unsubs = this.fanouts.map((fanout) => fanout.listen((data) => this.emit(data)));
const unsub = super.listen(listener);
return () => {
unsub();
if (!this.listeners.size) {
for (const unsub of this.unsubs)
unsub();
this.unsubs = [];
}
};
}
}
exports.MergeFanOut = MergeFanOut;
/**
* Buffers data from a fanout and emits the buffered data once per microtask.
*/
class MicrotaskBufferFanOut extends fanout_1.FanOut {
constructor(source) {
super();
this.source = source;
this.buffer = [];
this.unsub = undefined;
}
listen(listener) {
if (!this.unsub) {
this.unsub = this.source.listen((data) => {
const buffer = this.buffer;
if (!buffer.length) {
queueMicrotask(() => {
this.emit(buffer);
this.buffer = [];
});
}
buffer.push(data);
});
}
const unsub = super.listen(listener);
return () => {
unsub();
if (!this.listeners.size)
this.clear();
};
}
clear() {
this.listeners.clear();
this.buffer = [];
this.unsub?.();
this.unsub = undefined;
}
}
exports.MicrotaskBufferFanOut = MicrotaskBufferFanOut;
/**
* Maps the data from a fanout using a mapper function.
*/
class MapFanOut extends fanout_1.FanOut {
constructor(source, mapper) {
super();
this.source = source;
this.mapper = mapper;
this.unsub = undefined;
}
listen(listener) {
if (!this.unsub)
this.unsub = this.source.listen((data) => this.emit(this.mapper(data)));
const unsub = super.listen(listener);
return () => {
unsub();
if (!this.listeners.size)
this.clear();
};
}
clear() {
this.listeners.clear();
this.unsub?.();
this.unsub = undefined;
}
}
exports.MapFanOut = MapFanOut;
/**
* Emits only when the source fanout emits a new value. The first value is
* emitted immediately.
*/
class OnNewFanOut extends fanout_1.FanOut {
constructor(source, last = undefined) {
super();
this.source = source;
this.last = last;
this.unsub = undefined;
}
listen(listener) {
if (!this.unsub) {
this.unsub = this.source.listen((data) => {
if (this.last !== data)
this.emit((this.last = data));
});
}
const unsub = super.listen(listener);
return () => {
unsub();
if (!this.listeners.size)
this.clear();
};
}
clear() {
this.listeners.clear();
this.last = undefined;
this.unsub?.();
this.unsub = undefined;
}
}
exports.OnNewFanOut = OnNewFanOut;