2021-01-12 03:40:49 -08:00
import {
IExecuteFunctions ,
} from 'n8n-core' ;
import {
IDataObject ,
ILoadOptionsFunctions ,
INodeExecutionData ,
INodeParameters ,
INodePropertyOptions ,
INodeType ,
INodeTypeDescription ,
2021-04-16 09:33:36 -07:00
NodeOperationError ,
2021-01-12 03:40:49 -08:00
} from 'n8n-workflow' ;
import {
createDatapoint ,
deleteDatapoint ,
getAllDatapoints ,
updateDatapoint
} from './Beeminder.node.functions' ;
import {
beeminderApiRequest ,
} from './GenericFunctions' ;
2022-04-08 14:32:08 -07:00
import moment from 'moment-timezone' ;
2021-01-12 03:40:49 -08:00
export class Beeminder implements INodeType {
description : INodeTypeDescription = {
displayName : 'Beeminder' ,
name : 'beeminder' ,
group : [ 'output' ] ,
version : 1 ,
description : 'Consume Beeminder API' ,
subtitle : '={{$parameter["operation"] + ": " + $parameter["resource"]}}' ,
defaults : {
name : 'Beeminder' ,
} ,
icon : 'file:beeminder.png' ,
inputs : [ 'main' ] ,
outputs : [ 'main' ] ,
credentials : [
{
name : 'beeminderApi' ,
required : true ,
} ,
] ,
properties : [
{
displayName : 'Resource' ,
name : 'resource' ,
type : 'options' ,
2022-05-20 14:47:24 -07:00
noDataExpression : true ,
2021-01-12 03:40:49 -08:00
required : true ,
options : [
{
name : 'Datapoint' ,
value : 'datapoint' ,
} ,
] ,
default : 'datapoint' ,
} ,
{
displayName : 'Operation' ,
name : 'operation' ,
type : 'options' ,
2022-05-20 14:47:24 -07:00
noDataExpression : true ,
2021-01-12 03:40:49 -08:00
options : [
{
name : 'Create' ,
value : 'create' ,
2022-05-06 14:01:25 -07:00
description : 'Create datapoint for goal' ,
2021-01-12 03:40:49 -08:00
} ,
{
name : 'Delete' ,
value : 'delete' ,
2022-05-06 14:01:25 -07:00
description : 'Delete a datapoint' ,
2021-01-12 03:40:49 -08:00
} ,
{
name : 'Get All' ,
value : 'getAll' ,
2022-05-06 14:01:25 -07:00
description : 'Get all datapoints for a goal' ,
2021-01-12 03:40:49 -08:00
} ,
{
name : 'Update' ,
value : 'update' ,
2022-05-06 14:01:25 -07:00
description : 'Update a datapoint' ,
2021-01-12 03:40:49 -08:00
} ,
] ,
default : 'create' ,
required : true ,
} ,
{
2022-06-03 10:23:49 -07:00
displayName : 'Goal Name or ID' ,
2021-01-12 03:40:49 -08:00
name : 'goalName' ,
type : 'options' ,
typeOptions : {
loadOptionsMethod : 'getGoals' ,
} ,
displayOptions : {
show : {
resource : [
'datapoint' ,
] ,
} ,
} ,
default : '' ,
2022-06-03 10:23:49 -07:00
description : 'The name of the goal. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/nodes/expressions.html#expressions">expression</a>.' ,
2021-01-12 03:40:49 -08:00
required : true ,
} ,
{
displayName : 'Return All' ,
name : 'returnAll' ,
type : 'boolean' ,
displayOptions : {
show : {
operation : [
'getAll' ,
] ,
resource : [
'datapoint' ,
] ,
} ,
} ,
default : false ,
2022-05-06 14:01:25 -07:00
description : 'Whether to return all results or only up to a given limit' ,
2021-01-12 03:40:49 -08:00
} ,
{
displayName : 'Limit' ,
name : 'limit' ,
type : 'number' ,
displayOptions : {
show : {
operation : [
'getAll' ,
] ,
resource : [
'datapoint' ,
] ,
returnAll : [
false ,
] ,
} ,
} ,
typeOptions : {
minValue : 1 ,
maxValue : 300 ,
} ,
default : 30 ,
2022-05-06 14:01:25 -07:00
description : 'Max number of results to return' ,
2021-01-12 03:40:49 -08:00
} ,
{
displayName : 'Value' ,
name : 'value' ,
type : 'number' ,
default : 1 ,
placeholder : '' ,
2022-05-06 14:01:25 -07:00
description : 'Datapoint value to send' ,
2021-01-12 03:40:49 -08:00
displayOptions : {
show : {
resource : [
'datapoint' ,
] ,
operation : [
'create' ,
] ,
} ,
} ,
required : true ,
} ,
{
displayName : 'Datapoint ID' ,
name : 'datapointId' ,
type : 'string' ,
default : '' ,
displayOptions : {
show : {
operation : [
'update' ,
'delete' ,
] ,
} ,
} ,
required : true ,
} ,
{
displayName : 'Additional Fields' ,
name : 'additionalFields' ,
type : 'collection' ,
placeholder : 'Add Field' ,
default : { } ,
displayOptions : {
show : {
resource : [
'datapoint' ,
] ,
operation : [
'create' ,
] ,
} ,
} ,
options : [
{
displayName : 'Comment' ,
name : 'comment' ,
type : 'string' ,
default : '' ,
} ,
{
displayName : 'Timestamp' ,
name : 'timestamp' ,
type : 'dateTime' ,
default : '' ,
placeholder : '' ,
2022-05-06 14:01:25 -07:00
description : 'Defaults to "now" if none is passed in, or the existing timestamp if the datapoint is being updated rather than created' ,
2021-01-12 03:40:49 -08:00
} ,
{
displayName : 'Request ID' ,
name : 'requestId' ,
type : 'string' ,
default : '' ,
placeholder : '' ,
2022-05-06 14:01:25 -07:00
description : 'String to uniquely identify a datapoint' ,
2021-01-12 03:40:49 -08:00
} ,
] ,
} ,
{
displayName : 'Options' ,
name : 'options' ,
type : 'collection' ,
placeholder : 'Add field' ,
default : { } ,
displayOptions : {
show : {
resource : [
'datapoint' ,
] ,
operation : [
'getAll' ,
] ,
} ,
} ,
options : [
{
displayName : 'Sort' ,
name : 'sort' ,
type : 'string' ,
default : 'id' ,
placeholder : '' ,
2022-05-06 14:01:25 -07:00
description : 'Attribute to sort on' ,
2021-01-12 03:40:49 -08:00
} ,
] ,
} ,
{
displayName : 'Update Fields' ,
name : 'updateFields' ,
type : 'collection' ,
placeholder : 'Add Field' ,
default : { } ,
displayOptions : {
show : {
resource : [
'datapoint' ,
] ,
operation : [
'update' ,
] ,
} ,
} ,
options : [
{
displayName : 'Value' ,
name : 'value' ,
type : 'number' ,
default : 1 ,
placeholder : '' ,
2022-05-06 14:01:25 -07:00
description : 'Datapoint value to send' ,
2021-01-12 03:40:49 -08:00
} ,
{
displayName : 'Comment' ,
name : 'comment' ,
type : 'string' ,
default : '' ,
} ,
{
displayName : 'Timestamp' ,
name : 'timestamp' ,
type : 'dateTime' ,
default : '' ,
placeholder : '' ,
2022-05-06 14:01:25 -07:00
description : 'Defaults to "now" if none is passed in, or the existing timestamp if the datapoint is being updated rather than created' ,
2021-01-12 03:40:49 -08:00
} ,
] ,
} ,
] ,
} ;
methods = {
loadOptions : {
// Get all the available groups to display them to user so that he can
// select them easily
async getGoals ( this : ILoadOptionsFunctions ) : Promise < INodePropertyOptions [ ] > {
2021-08-20 09:57:30 -07:00
const credentials = await this . getCredentials ( 'beeminderApi' ) ;
2021-01-12 03:40:49 -08:00
const endpoint = ` /users/ ${ credentials . user } /goals.json ` ;
const returnData : INodePropertyOptions [ ] = [ ] ;
const goals = await beeminderApiRequest . call ( this , 'GET' , endpoint ) ;
for ( const goal of goals ) {
returnData . push ( {
name : goal.slug ,
value : goal.slug ,
} ) ;
}
return returnData ;
} ,
} ,
} ;
async execute ( this : IExecuteFunctions ) : Promise < INodeExecutionData [ ] [ ] > {
const items = this . getInputData ( ) ;
const returnData : IDataObject [ ] = [ ] ;
2022-04-22 09:29:51 -07:00
const length = items . length ;
2021-01-12 03:40:49 -08:00
const timezone = this . getTimezone ( ) ;
const resource = this . getNodeParameter ( 'resource' , 0 ) as string ;
const operation = this . getNodeParameter ( 'operation' , 0 ) as string ;
let results ;
for ( let i = 0 ; i < length ; i ++ ) {
2021-07-19 23:58:54 -07:00
try {
if ( resource === 'datapoint' ) {
const goalName = this . getNodeParameter ( 'goalName' , i ) as string ;
if ( operation === 'create' ) {
const value = this . getNodeParameter ( 'value' , i ) as number ;
const options = this . getNodeParameter ( 'additionalFields' , i ) as INodeParameters ;
const data : IDataObject = {
value ,
goalName ,
} ;
Object . assign ( data , options ) ;
2021-01-12 03:40:49 -08:00
2021-07-19 23:58:54 -07:00
if ( data . timestamp ) {
data . timestamp = moment . tz ( data . timestamp , timezone ) . unix ( ) ;
}
results = await createDatapoint . call ( this , data ) ;
2021-01-12 03:40:49 -08:00
}
2021-07-19 23:58:54 -07:00
else if ( operation === 'getAll' ) {
const returnAll = this . getNodeParameter ( 'returnAll' , i ) as boolean ;
const options = this . getNodeParameter ( 'options' , i ) as INodeParameters ;
const data : IDataObject = {
goalName ,
} ;
Object . assign ( data , options ) ;
2021-01-12 03:40:49 -08:00
2021-07-19 23:58:54 -07:00
if ( returnAll === false ) {
data . count = this . getNodeParameter ( 'limit' , 0 ) as number ;
}
2021-01-12 03:40:49 -08:00
2021-07-19 23:58:54 -07:00
results = await getAllDatapoints . call ( this , data ) ;
}
else if ( operation === 'update' ) {
const datapointId = this . getNodeParameter ( 'datapointId' , i ) as string ;
const options = this . getNodeParameter ( 'updateFields' , i ) as INodeParameters ;
const data : IDataObject = {
goalName ,
datapointId ,
} ;
Object . assign ( data , options ) ;
if ( data . timestamp ) {
data . timestamp = moment . tz ( data . timestamp , timezone ) . unix ( ) ;
}
results = await updateDatapoint . call ( this , data ) ;
}
else if ( operation === 'delete' ) {
const datapointId = this . getNodeParameter ( 'datapointId' , i ) as string ;
const data : IDataObject = {
goalName ,
datapointId ,
} ;
results = await deleteDatapoint . call ( this , data ) ;
2021-01-12 03:40:49 -08:00
}
}
2021-07-19 23:58:54 -07:00
} catch ( error ) {
if ( this . continueOnFail ( ) ) {
returnData . push ( { error : error.message } ) ;
continue ;
2021-01-12 03:40:49 -08:00
}
2021-07-19 23:58:54 -07:00
throw error ;
2021-01-12 03:40:49 -08:00
}
if ( Array . isArray ( results ) ) {
returnData . push . apply ( returnData , results as IDataObject [ ] ) ;
} else {
returnData . push ( results as IDataObject ) ;
}
}
return [ this . helpers . returnJsonArray ( returnData ) ] ;
}
}