Initial release v1.0.0 — Nextcloud Collabora Node-RED sidecar

This commit is contained in:
Hannes Ahlin
2026-08-22 14:56:38 +02:00
commit 9e5b0b6f83
37 changed files with 2035 additions and 0 deletions
+146
View File
@@ -0,0 +1,146 @@
'use strict';
const { getConfig, setError, setSuccess, clearStatus, pickMsgField } = require('../lib/utils');
const { ocsRequest } = require('../lib/ocs');
const bridge = require('../lib/bridge');
const { resolveFileId } = bridge;
const { webdavGet, webdavPut } = require('../lib/webdav');
const { convertTo } = require('../lib/collabora');
const {
resolveDestNcPath,
assertSafeDestination,
contentTypeForFormat,
normalizeNcPath
} = require('../lib/utils');
module.exports = function (RED) {
function NcOfficeNode(config) {
RED.nodes.createNode(this, config);
const node = this;
node.configNode = RED.nodes.getNode(config.config);
node.operation = config.operation || 'templates:list';
node.on('input', async (msg, send, done) => {
send = send || function () { node.send.apply(node, arguments); };
done = done || function (err) { if (err) { node.error(err, msg); } };
clearStatus(node);
try {
const cfg = getConfig(node);
const op = msg.operation || node.operation;
let result;
switch (op) {
case 'templates:list': {
const type = pickMsgField(msg, 'templateType') || 'document';
result = await ocsRequest(cfg, {
method: 'GET',
path: `/ocs/v2.php/apps/richdocuments/api/v1/templates/${type}`
});
msg.payload = result.data;
break;
}
case 'templates:create': {
result = await ocsRequest(cfg, {
method: 'POST',
path: '/ocs/v2.php/apps/richdocuments/api/v1/templates/new',
body: {
templateId: msg.templateId,
fileName: msg.fileName || msg.destName,
templatePath: msg.templatePath
}
});
msg.payload = result.data;
break;
}
case 'template:extractFields': {
const fileId = await resolveFileId(cfg, msg);
result = await ocsRequest(cfg, {
method: 'GET',
path: `/ocs/v2.php/apps/richdocuments/api/v1/template/fields/extract/${fileId}`
});
msg.fileId = fileId;
msg.payload = result.data;
break;
}
case 'template:fillFields': {
const fileId = await resolveFileId(cfg, msg);
const fields = msg.fields || msg.transform;
const body = { fields };
if (msg.destNcPath) {
body.destination = normalizeNcPath(msg.destNcPath).replace(/^\//, '');
}
result = await ocsRequest(cfg, {
method: 'POST',
path: `/ocs/v2.php/apps/richdocuments/api/v1/template/fields/fill/${fileId}`,
body
});
msg.fileId = fileId;
msg.payload = result.data;
break;
}
case 'document:direct': {
const fileId = await resolveFileId(cfg, msg);
result = await ocsRequest(cfg, {
method: 'POST',
path: '/ocs/v2.php/apps/richdocuments/api/v1/document',
body: { fileid: fileId }
});
msg.fileId = fileId;
msg.editorUrl = result.data?.url || result.data;
msg.payload = { url: msg.editorUrl, fileId };
break;
}
case 'document:public': {
if (!msg.shareToken) {
throw new Error('document:public kräver msg.shareToken');
}
result = await ocsRequest(cfg, {
method: 'POST',
path: '/ocs/v2.php/apps/richdocuments/api/v1/document',
body: { shareToken: msg.shareToken }
});
msg.editorUrl = result.data?.url || result.data;
msg.payload = { url: msg.editorUrl };
break;
}
case 'files:convert': {
const format = (pickMsgField(msg, 'format') || 'pdf').toLowerCase();
const source = msg.ncPath
? await webdavGet(cfg, msg.ncPath)
: { buffer: Buffer.from(msg.payload), filename: msg.filename || 'file.bin' };
const converted = await convertTo(cfg, {
buffer: source.buffer,
filename: source.filename,
format
});
const dest = assertSafeDestination(resolveDestNcPath(msg, msg.ncPath, format), msg);
const put = await webdavPut(cfg, dest, converted.buffer, contentTypeForFormat(format));
msg.destNcPath = put.destNcPath;
msg.payload = converted.buffer;
msg.format = format;
break;
}
case 'assets:create': {
const link = await bridge.createAssetLink(cfg, msg);
msg.assetUrl = link.assetUrl;
msg.payload = { assetUrl: link.assetUrl, ncPath: link.ncPath };
break;
}
default:
throw new Error(`Okänd nc-office operation: ${op}`);
}
setSuccess(node, msg, op);
send(msg);
done();
} catch (err) {
setError(node, msg, err);
send(msg);
done(err);
}
});
}
RED.nodes.registerType('nc-office', NcOfficeNode);
};