@dwsouza Here is my solution for custom templates:
Create a new table in the existing db named workflows as below to store templates:
CREATE TABLE IF NOT EXISTS workflows (
id SERIAL NOT NULL,
name varchar NOT NULL,
createdAt timestamp,
user json,
description varchar
);
Create a node js service to serve the templates:
const express = require("express");
const cors = require("cors");
const { Client } = require("pg");
require("dotenv").config();
const app = express();
const port = 3000;
const corsOptions = {
origin: process.env.N8N_HOST_URL,
credentials: true,
};
app.use(cors(corsOptions));
app.use(express.json());
const templatesClient = new Client({
user: process.env.TEMPLATES_USERNAME,
host: process.env.TEMPLATES_HOST,
database: process.env.TEMPLATES_DATABASE,
password: process.env.TEMPLATES_PASSWORD,
port: process.env.TEMPLATES_PORT,
});
const lisClient = new Client({
user: process.env.LIS_USERNAME,
host: process.env.LIS_HOST,
database: process.env.LIS_DATABASE,
password: process.env.LIS_PASSWORD,
port: process.env.LIS_PORT,
});
templatesClient.connect(function (err) {
if (err) throw err;
console.log("templates postgres db conn established");
});
lisClient.connect(function (err) {
if (err) throw err;
console.log("lis workflows postgres db conn established");
});
app.get("/health", (req, res) => {
res.json({ status: "OK" });
});
app.get("/templates/workflows", (req, res) => {
templatesClient.query("SELECT * FROM workflows", (err, result) => {
if (err) {
console.log(err.stack);
} else {
res.json({ workflows: result.rows });
}
});
});
app.get("/templates/workflows/:id", async (req, res) => {
templatesClient.query(
`SELECT * FROM workflows WHERE id=${req.params.id}`,
(err, result) => {
if (err) {
console.log(err.stack);
} else {
let workflowResult = result.rows[0];
lisClient.query(
`SELECT nodes, connections FROM workflow_entity WHERE name = '${workflowResult.name}'`,
(err, innerResult) => {
if (err) {
console.log(err.stack);
} else {
workflowResult.workflow = {};
workflowResult.workflow.nodes = innerResult.rows[0].nodes;
workflowResult.workflow.connections =
innerResult.rows[0].connections;
res.json({ workflow: workflowResult });
}
}
);
}
}
);
});
app.get("/workflows/templates/:id", async (req, res) => {
templatesClient.query(
`SELECT * FROM workflows WHERE id=${req.params.id}`,
(err, result) => {
if (err) {
console.log(err.stack);
} else {
let workflowResult = result.rows[0];
lisClient.query(
`SELECT nodes, connections FROM workflow_entity WHERE name = '${workflowResult.name}'`,
(err, innerResult) => {
if (err) {
console.log(err.stack);
} else {
workflowResult.workflow = {};
workflowResult.workflow.nodes = innerResult.rows[0].nodes;
workflowResult.workflow.connections =
innerResult.rows[0].connections;
res.json(workflowResult);
}
}
);
}
}
);
});
app.post("/template", async (req, res) => {
const dateTime = new Date().toISOString();
templatesClient.query(
`INSERT INTO workflows (name, "createdAt", "user", description)
VALUES ('${req.body.name}', '${dateTime}', '{"username": "[email protected]"}', '${req.body.description}')`,
(err, result) => {
if (err) {
console.log(err.stack);
} else {
res.json({ status: `created ${req.body.name}` });
}
}
);
});
app.delete("/template/:name", async (req, res) => {
templatesClient.query(
`DELETE FROM workflows WHERE name = '${req.params.name}'`,
(err, result) => {
if (err) {
console.log(err.stack);
} else {
res.json({ status: `deleted ${req.params.name}` });
}
}
);
});
app.listen(port, () => {
console.log(`Templates API listening on port ${port}`);
});
I now use the same db as N8N to store this new workflows table so you can ignore the templates db connection (or in my case both the db connection env vars above point to the n8n db)
Set below env vars:
N8N_TEMPLATES_ENABLED=True
N8N_TEMPLATES_HOST={nodejs api uri}