n8n
Version:
n8n Workflow Automation Tool
144 lines • 5.27 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.interceptResponseWrites = interceptResponseWrites;
exports.createStructuredChunkAggregator = createStructuredChunkAggregator;
const uuid_1 = require("uuid");
function interceptResponseWrites(res, transform) {
const originalWrite = res.write.bind(res);
const originalEnd = res.end.bind(res);
const defaultEncoding = 'utf8';
let writeChain = Promise.resolve();
const toText = (data, enc) => Buffer.isBuffer(data) ? data.toString(enc ?? defaultEncoding) : String(data);
function write(chunk, encodingOrCallback, callbackFn) {
const inputText = toText(chunk, typeof encodingOrCallback === 'string' ? encodingOrCallback : undefined);
writeChain = writeChain
.then(async () => await transform(inputText))
.then((outputText) => {
if (!encodingOrCallback) {
originalWrite(outputText);
}
else if (typeof encodingOrCallback === 'function') {
originalWrite(outputText, encodingOrCallback);
}
else {
originalWrite(outputText, encodingOrCallback, callbackFn);
}
})
.catch((error) => {
const originalCb = typeof encodingOrCallback === 'function' ? encodingOrCallback : callbackFn;
if (originalCb) {
originalCb(error);
}
});
return true;
}
function end(chunkOrCallback, encodingOrCallback, callbackFn) {
void writeChain.then(() => {
if (!chunkOrCallback) {
originalEnd();
}
else if (typeof chunkOrCallback === 'function') {
originalEnd(chunkOrCallback);
}
else if (!encodingOrCallback) {
originalEnd(chunkOrCallback);
}
else if (typeof encodingOrCallback === 'function') {
originalEnd(chunkOrCallback, encodingOrCallback);
}
else {
originalEnd(chunkOrCallback, encodingOrCallback, callbackFn);
}
});
return res;
}
res.write = write;
res.end = end;
return res;
}
const keyOf = (m) => `${m.nodeId}|${m.runIndex}|${m.itemIndex}`;
function createStructuredChunkAggregator(initialPreviousMessageId, retryOfMessageId, handlers = {}) {
const { onBegin, onItem, onEnd, onError, onCancel } = handlers;
const activeByKey = new Map();
let cancelled = false;
let previousMessageId = initialPreviousMessageId;
const startNew = async () => {
const message = {
id: (0, uuid_1.v4)(),
previousMessageId,
retryOfMessageId: retryOfMessageId && previousMessageId === initialPreviousMessageId
? retryOfMessageId
: null,
content: '',
createdAt: new Date(),
updatedAt: new Date(),
status: 'running',
};
previousMessageId = message.id;
await onBegin?.(message);
return message;
};
const ensureMessage = async (key) => {
let message = activeByKey.get(key);
if (!message) {
message = await startNew();
activeByKey.set(key, message);
}
return message;
};
const ingest = async (chunk) => {
if (cancelled) {
return null;
}
if (chunk.type === 'keepalive') {
return null;
}
const { type, content, metadata } = chunk;
const key = keyOf(metadata);
if (type === 'begin') {
if (activeByKey.has(key)) {
throw new Error(`Duplicate begin for key ${key}`);
}
const message = await startNew();
activeByKey.set(key, message);
return message;
}
if (type === 'item') {
const message = await ensureMessage(key);
if (typeof content === 'string' && content.length) {
message.content += content;
await onItem?.(message, content);
}
return message;
}
if (type === 'end') {
const message = await ensureMessage(key);
message.status = 'success';
message.updatedAt = new Date();
activeByKey.delete(key);
await onEnd?.(message);
return message;
}
const message = await ensureMessage(key);
message.status = 'error';
message.updatedAt = new Date();
if (typeof content === 'string') {
message.content = (message.content ? message.content + '\n\n' : '') + content;
}
activeByKey.delete(key);
await onError?.(message, content);
return message;
};
const cancelAll = async () => {
cancelled = true;
const messages = Array.from(activeByKey.values());
activeByKey.clear();
for (const message of messages) {
message.status = 'cancelled';
message.updatedAt = new Date();
await onCancel?.(message);
}
};
return { ingest, cancelAll };
}
//# sourceMappingURL=stream-capturer.js.map