refactor: add typed decoder plugin runtime
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
"use strict";
|
||||
const decoders = /* @__PURE__ */ new Map();
|
||||
const queued = /* @__PURE__ */ new Map();
|
||||
const MAX_QUEUED_ACTIONS_PER_DECODER = 512;
|
||||
function enqueue(id, action) {
|
||||
const actions = queued.get(id) ?? [];
|
||||
actions.push(action);
|
||||
if (actions.length > MAX_QUEUED_ACTIONS_PER_DECODER) actions.splice(0, actions.length - MAX_QUEUED_ACTIONS_PER_DECODER);
|
||||
queued.set(id, actions);
|
||||
}
|
||||
function deliver(plugin, action) {
|
||||
if (action.kind === "message" && plugin.onMessage) {
|
||||
plugin.onMessage(action.payload);
|
||||
return true;
|
||||
}
|
||||
if (action.kind === "batch" && plugin.onBatch) {
|
||||
plugin.onBatch(action.payload);
|
||||
return true;
|
||||
}
|
||||
if (action.kind === "restore" && plugin.restore) {
|
||||
plugin.restore(action.payload);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
function dispatchOrQueue(id, action) {
|
||||
const plugin = decoders.get(id);
|
||||
if (!plugin) {
|
||||
enqueue(id, action);
|
||||
return false;
|
||||
}
|
||||
if (!deliver(plugin, action)) {
|
||||
if (action.kind === "batch" && plugin.onMessage) {
|
||||
for (const message of action.payload) plugin.onMessage(message);
|
||||
return true;
|
||||
}
|
||||
if (action.kind === "restore" && plugin.onBatch) {
|
||||
plugin.onBatch(action.payload);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
const runtime = {
|
||||
registerDecoder(plugin) {
|
||||
if (decoders.has(plugin.id)) throw new Error(`Decoder plugin already registered: ${plugin.id}`);
|
||||
const erased = plugin;
|
||||
decoders.set(plugin.id, erased);
|
||||
const pending = queued.get(plugin.id) ?? [];
|
||||
queued.delete(plugin.id);
|
||||
for (const action of pending) deliver(erased, action);
|
||||
return () => {
|
||||
if (decoders.get(plugin.id) === erased) decoders.delete(plugin.id);
|
||||
};
|
||||
},
|
||||
dispatch: (id, message) => dispatchOrQueue(id, { kind: "message", payload: message }),
|
||||
dispatchBatch: (id, messages) => dispatchOrQueue(id, { kind: "batch", payload: messages }),
|
||||
restore: (id, messages) => dispatchOrQueue(id, { kind: "restore", payload: messages }),
|
||||
reset(id) {
|
||||
const plugin = decoders.get(id);
|
||||
if (!plugin?.reset) return false;
|
||||
plugin.reset();
|
||||
return true;
|
||||
},
|
||||
resetAll() {
|
||||
for (const plugin of decoders.values()) plugin.reset?.();
|
||||
},
|
||||
prune(id) {
|
||||
const plugin = decoders.get(id);
|
||||
if (!plugin?.prune) return false;
|
||||
plugin.prune();
|
||||
return true;
|
||||
},
|
||||
clearQueued() {
|
||||
queued.clear();
|
||||
},
|
||||
hasDecoder: (id) => decoders.has(id)
|
||||
};
|
||||
window.trxPluginRuntime = runtime;
|
||||
Reference in New Issue
Block a user