@micro-frame/marko
Version:
A Marko tag for building SSR friendly micro frontends.
144 lines (143 loc) • 3.37 kB
JavaScript
var __defProp = Object.defineProperty;
var __markAsModule = (target) => __defProp(target, "__esModule", { value: true });
var __export = (target, all) => {
__markAsModule(target);
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
__export(exports, {
StreamSource: () => StreamSource,
createWritable: () => createWritable,
getSource: () => getSource
});
const kReadableByName = Symbol("stream-source");
class StreamSource {
constructor() {
this._slots = new Map();
this._invalidateHandlers = new Set();
this._closed = false;
}
getOrCreateSlot(id) {
if (this._slots.has(id)) {
return this._slots.get(id);
}
const newSlot = createWritable();
this._slots.set(id, newSlot);
return newSlot;
}
async run(parserIterator) {
while (true) {
const { value, done } = await parserIterator.next();
if (done)
break;
if (value === void 0) {
continue;
}
const [slotId, html, isDone] = value;
const slot = this.getOrCreateSlot(slotId);
slot.write(html);
isDone && slot.end();
}
this.close();
}
slot(id) {
return this._closed ? this._slots.get(id) : this.getOrCreateSlot(id);
}
close(err) {
this._closed = true;
this._slots.forEach((slot) => err ? slot.error(err) : slot.end());
}
onInvalidate(handler) {
this._invalidateHandlers.add(handler);
}
offInvalidate(handler) {
this._invalidateHandlers.delete(handler);
}
invalidate(newSrc) {
this._slots.clear();
this._closed = false;
for (const handler of this._invalidateHandlers) {
handler(newSrc);
}
}
}
function getSource(name, out) {
const global = typeof document === "object" ? window : out == null ? void 0 : out.global;
if (global === void 0) {
throw new Error("Server side out.global is missing.");
}
const store = global[kReadableByName] ?? (global[kReadableByName] = new Map());
if (store.has(name)) {
return store.get(name);
}
const streamSource = new StreamSource();
store.set(name, streamSource);
return streamSource;
}
function createWritable() {
let buf = "";
let done = false;
let error = void 0;
let pending = void 0;
return {
write(data) {
buf += data;
if (pending) {
pending.resolve();
pending = void 0;
}
},
end() {
done = true;
if (pending) {
pending.resolve();
pending = void 0;
}
},
error(reason) {
error = reason;
if (pending) {
pending.reject(reason);
pending = void 0;
}
},
async next() {
if (buf) {
const value = buf;
buf = "";
return {
value,
done: false
};
}
if (done) {
return {
value: void 0,
done: true
};
}
if (error) {
throw error;
}
await (pending = createDeferred());
return this.next();
}
};
}
function createDeferred() {
let resolve;
let reject;
const p = new Promise((_resolve, _reject) => {
resolve = _resolve;
reject = _reject;
});
p.resolve = resolve;
p.reject = reject;
return p;
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
StreamSource,
createWritable,
getSource
});