n8n-nodes-tibber
Version:
n8n node to access Tibber API data
498 lines (496 loc) • 17.4 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.TibberNode = void 0;
const n8n_workflow_1 = require("n8n-workflow");
class TibberNode {
constructor() {
this.description = {
displayName: 'Tibber',
name: 'tibber',
icon: 'file:tibber.svg',
group: ['transform'],
version: 1,
subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
description: 'Consume Tibber API',
defaults: {
name: 'Tibber',
},
// n8n node connection types
inputs: ['main'],
outputs: ['main'],
credentials: [
{
name: 'tibberApi',
required: true,
},
],
properties: [
{
displayName: 'Resource',
name: 'resource',
type: 'options',
noDataExpression: true,
options: [
{
name: 'Home',
value: 'home',
},
],
default: 'home',
},
{
displayName: 'Operation',
name: 'operation',
type: 'options',
noDataExpression: true,
displayOptions: {
show: {
resource: [
'home',
],
},
},
options: [
{
name: 'Get',
value: 'get',
description: 'Get home data',
action: 'Get home data',
},
{
name: 'Get Consumption',
value: 'getConsumption',
description: 'Get consumption data',
action: 'Get consumption data',
},
{
name: 'Get Price',
value: 'getPrice',
description: 'Get price information',
action: 'Get price information',
},
],
default: 'get',
},
{
displayName: 'Home ID',
name: 'homeId',
type: 'string',
default: '',
displayOptions: {
show: {
resource: [
'home',
],
operation: [
'getConsumption',
'getPrice',
],
},
},
description: 'The ID of the home to get data for',
},
{
displayName: 'Resolution',
name: 'resolution',
type: 'options',
displayOptions: {
show: {
resource: [
'home',
],
operation: [
'getConsumption',
],
},
},
options: [
{
name: 'Hourly',
value: 'HOURLY',
},
{
name: 'Daily',
value: 'DAILY',
},
{
name: 'Weekly',
value: 'WEEKLY',
},
{
name: 'Monthly',
value: 'MONTHLY',
},
{
name: 'Annual',
value: 'ANNUAL',
},
],
default: 'HOURLY',
description: 'The resolution of consumption data',
},
{
displayName: 'Last N Hours',
name: 'lastHours',
type: 'number',
displayOptions: {
show: {
resource: [
'home',
],
operation: [
'getConsumption',
],
resolution: [
'HOURLY',
],
},
},
default: 24,
description: 'Get consumption data for the last N hours',
},
{
displayName: 'Last N Days',
name: 'lastDays',
type: 'number',
displayOptions: {
show: {
resource: [
'home',
],
operation: [
'getConsumption',
],
resolution: [
'DAILY',
],
},
},
default: 7,
description: 'Get consumption data for the last N days',
},
{
displayName: 'Last N Weeks',
name: 'lastWeeks',
type: 'number',
displayOptions: {
show: {
resource: [
'home',
],
operation: [
'getConsumption',
],
resolution: [
'WEEKLY',
],
},
},
default: 4,
description: 'Get consumption data for the last N weeks',
},
{
displayName: 'Last N Months',
name: 'lastMonths',
type: 'number',
displayOptions: {
show: {
resource: [
'home',
],
operation: [
'getConsumption',
],
resolution: [
'MONTHLY',
],
},
},
default: 12,
description: 'Get consumption data for the last N months',
},
{
displayName: 'Last N Years',
name: 'lastYears',
type: 'number',
displayOptions: {
show: {
resource: [
'home',
],
operation: [
'getConsumption',
],
resolution: [
'ANNUAL',
],
},
},
default: 3,
description: 'Get consumption data for the last N years',
},
],
};
}
async execute() {
var _a, _b, _c;
const items = this.getInputData();
const returnData = [];
const resource = this.getNodeParameter('resource', 0);
const operation = this.getNodeParameter('operation', 0);
// Get credentials
const credentials = await this.getCredentials('tibberApi');
const apiToken = credentials.apiToken;
// 1) Dynamic import of ESM module from CJS context
const { GraphQLClient } = (await Promise.resolve().then(() => __importStar(require('graphql-request'))));
// 2) Define endpoint BEFORE you use it
const endpoint = 'https://api.tibber.com/v1-beta/gql';
// 3) Create client
const client = new GraphQLClient(endpoint, {
headers: { Authorization: `Bearer ${apiToken}` },
});
// 4) Use a plain string for the GraphQL query (no gql tag needed)
const query = /* GraphQL */ `
query Viewer {
viewer {
name
}
}
`;
// 5) Make the request
const data = await client.request(query);
try {
// Execute operations based on resource and operation
if (resource === 'home') {
if (operation === 'get') {
// Get homes data
const query = `
{
viewer {
homes {
id
address {
address1
address2
address3
city
postalCode
country
latitude
longitude
}
appNickname
size
type
primaryHeatingSource
hasVentilationSystem
timeZone
meteringPointData {
consumptionEan
gridCompany
gridAreaCode
priceAreaCode
productionEan
}
owner {
id
firstName
lastName
contactInfo {
email
mobile
}
}
features {
realTimeConsumptionEnabled
}
currentSubscription {
id
status
validFrom
validTo
statusReason
}
}
}
}
`;
const response = await client.request(query);
// Return all homes data
for (const home of response.viewer.homes) {
returnData.push({
json: home,
pairedItem: 0,
});
}
}
else if (operation === 'getConsumption') {
const homeId = this.getNodeParameter('homeId', 0);
const resolution = this.getNodeParameter('resolution', 0);
let lastN;
let lastField = 'hours'; // Default value
// Set the appropriate last field based on resolution
if (resolution === 'HOURLY') {
lastN = this.getNodeParameter('lastHours', 0);
lastField = 'hours';
}
else if (resolution === 'DAILY') {
lastN = this.getNodeParameter('lastDays', 0);
lastField = 'days';
}
else if (resolution === 'WEEKLY') {
lastN = this.getNodeParameter('lastWeeks', 0);
lastField = 'weeks';
}
else if (resolution === 'MONTHLY') {
lastN = this.getNodeParameter('lastMonths', 0);
lastField = 'months';
}
else if (resolution === 'ANNUAL') {
lastN = this.getNodeParameter('lastYears', 0);
lastField = 'years';
}
else {
// Fallback
lastN = 24;
}
const query = `
{
viewer {
home(id: "${homeId}") {
consumption(resolution: ${resolution}, last: ${lastN}) {
nodes {
from
to
cost
unitPrice
unitPriceVAT
consumption
consumptionUnit
}
}
}
}
}
`;
const response = await client.request(query);
if (response.viewer.home) {
const consumptionData = {
homeId,
resolution,
[`last${lastField.charAt(0).toUpperCase() + lastField.slice(1)}`]: lastN,
consumption: response.viewer.home.consumption.nodes,
};
returnData.push({
json: consumptionData,
pairedItem: 0,
});
}
else {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Home with ID ${homeId} not found`);
}
}
else if (operation === 'getPrice') {
const homeId = this.getNodeParameter('homeId', 0);
const query = `
{
viewer {
home(id: "${homeId}") {
currentSubscription {
priceInfo {
current {
total
energy
tax
startsAt
level
currency
}
today {
total
energy
tax
startsAt
level
currency
}
tomorrow {
total
energy
tax
startsAt
level
currency
}
}
}
}
}
}
`;
const response = await client.request(query);
if (response.viewer.home) {
const priceData = {
homeId,
priceInfo: response.viewer.home.currentSubscription.priceInfo,
};
returnData.push({
json: priceData,
pairedItem: 0,
});
}
else {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Home with ID ${homeId} not found`);
}
}
}
return [returnData];
}
catch (error) {
// Handle GraphQL errors
if (error instanceof Error) {
const errorObject = error;
if ((_c = (_b = (_a = errorObject.response) === null || _a === void 0 ? void 0 : _a.errors) === null || _b === void 0 ? void 0 : _b[0]) === null || _c === void 0 ? void 0 : _c.message) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Tibber API error: ${errorObject.response.errors[0].message}`);
}
throw new n8n_workflow_1.NodeOperationError(this.getNode(), errorObject.message);
}
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'An unknown error occurred');
}
}
}
exports.TibberNode = TibberNode;
//# sourceMappingURL=Tibber.node.js.map