2023-01-27 03:22:44 -08:00
import type {
2023-03-09 09:13:15 -08:00
IExecuteFunctions ,
2021-02-07 08:38:37 -08:00
IDataObject ,
INodeExecutionData ,
INodeType ,
INodeTypeDescription ,
} from 'n8n-workflow' ;
2023-01-27 03:22:44 -08:00
import { NodeOperationError } from 'n8n-workflow' ;
2021-02-07 08:38:37 -08:00
2023-10-10 08:36:20 -07:00
import { generatePairedItemData } from '../../utils/utilities' ;
2023-01-27 03:22:44 -08:00
import type { IRecord } from './GenericFunction' ;
import { apiRequest , apiRequestAllItems } from './GenericFunction' ;
2021-02-07 08:38:37 -08:00
export class Stackby implements INodeType {
description : INodeTypeDescription = {
displayName : 'Stackby' ,
name : 'stackby' ,
2022-06-20 07:54:01 -07:00
// eslint-disable-next-line n8n-nodes-base/node-class-description-icon-not-svg
2021-02-07 08:38:37 -08:00
icon : 'file:stackby.png' ,
group : [ 'transform' ] ,
version : 1 ,
2021-07-03 05:40:16 -07:00
description : 'Read, write, and delete data in Stackby' ,
2021-02-07 08:38:37 -08:00
defaults : {
name : 'Stackby' ,
} ,
inputs : [ 'main' ] ,
outputs : [ 'main' ] ,
credentials : [
{
name : 'stackbyApi' ,
required : true ,
} ,
] ,
properties : [
{
displayName : 'Operation' ,
name : 'operation' ,
type : 'options' ,
2022-05-20 14:47:24 -07:00
noDataExpression : true ,
2021-02-07 08:38:37 -08:00
options : [
{
name : 'Append' ,
value : 'append' ,
} ,
{
name : 'Delete' ,
value : 'delete' ,
} ,
{
name : 'List' ,
value : 'list' ,
} ,
{
name : 'Read' ,
value : 'read' ,
} ,
] ,
default : 'append' ,
placeholder : 'Action to perform' ,
} ,
// ----------------------------------
// All
// ----------------------------------
{
displayName : 'Stack ID' ,
name : 'stackId' ,
type : 'string' ,
default : '' ,
required : true ,
2022-05-06 14:01:25 -07:00
description : 'The ID of the stack to access' ,
2021-02-07 08:38:37 -08:00
} ,
{
displayName : 'Table' ,
name : 'table' ,
type : 'string' ,
default : '' ,
placeholder : 'Stories' ,
required : true ,
description : 'Enter Table Name' ,
} ,
// ----------------------------------
// read
// ----------------------------------
{
displayName : 'ID' ,
name : 'id' ,
type : 'string' ,
displayOptions : {
show : {
2022-08-17 08:50:24 -07:00
operation : [ 'read' , 'delete' ] ,
2021-02-07 08:38:37 -08:00
} ,
} ,
default : '' ,
required : true ,
2022-05-06 14:01:25 -07:00
description : 'ID of the record to return' ,
2021-02-07 08:38:37 -08:00
} ,
// ----------------------------------
// list
// ----------------------------------
{
displayName : 'Return All' ,
name : 'returnAll' ,
type : 'boolean' ,
displayOptions : {
show : {
2022-08-17 08:50:24 -07:00
operation : [ 'list' ] ,
2021-02-07 08:38:37 -08:00
} ,
} ,
default : true ,
2022-05-06 14:01:25 -07:00
description : 'Whether to return all results or only up to a given limit' ,
2021-02-07 08:38:37 -08:00
} ,
{
displayName : 'Limit' ,
name : 'limit' ,
type : 'number' ,
displayOptions : {
show : {
2022-08-17 08:50:24 -07:00
operation : [ 'list' ] ,
returnAll : [ false ] ,
2021-02-07 08:38:37 -08:00
} ,
} ,
typeOptions : {
minValue : 1 ,
maxValue : 1000 ,
} ,
default : 1000 ,
2022-05-06 14:01:25 -07:00
description : 'Max number of results to return' ,
2021-02-07 08:38:37 -08:00
} ,
{
displayName : 'Additional Fields' ,
name : 'additionalFields' ,
type : 'collection' ,
displayOptions : {
show : {
2022-08-17 08:50:24 -07:00
operation : [ 'list' ] ,
2021-02-07 08:38:37 -08:00
} ,
} ,
default : { } ,
placeholder : 'Add Field' ,
options : [
{
displayName : 'View' ,
name : 'view' ,
type : 'string' ,
default : '' ,
placeholder : 'All Stories' ,
2022-08-17 08:50:24 -07:00
description :
'The name or ID of a view in the Stories table. If set, only the records in that view will be returned. The records will be sorted according to the order of the view.' ,
2021-02-07 08:38:37 -08:00
} ,
] ,
} ,
// ----------------------------------
// append
// ----------------------------------
{
displayName : 'Columns' ,
name : 'columns' ,
type : 'string' ,
displayOptions : {
show : {
2022-08-17 08:50:24 -07:00
operation : [ 'append' ] ,
2021-02-07 08:38:37 -08:00
} ,
} ,
default : '' ,
required : true ,
placeholder : 'id,name,description' ,
2022-08-17 08:50:24 -07:00
description :
'Comma-separated list of the properties which should used as columns for the new rows' ,
2021-02-07 08:38:37 -08:00
} ,
] ,
} ;
async execute ( this : IExecuteFunctions ) : Promise < INodeExecutionData [ ] [ ] > {
const items = this . getInputData ( ) ;
2022-08-30 08:55:33 -07:00
const returnData : INodeExecutionData [ ] = [ ] ;
2022-04-22 09:29:51 -07:00
const length = items . length ;
2021-02-07 08:38:37 -08:00
let responseData ;
const qs : IDataObject = { } ;
2022-12-02 03:53:59 -08:00
const operation = this . getNodeParameter ( 'operation' , 0 ) ;
2021-02-07 08:38:37 -08:00
if ( operation === 'read' ) {
for ( let i = 0 ; i < length ; i ++ ) {
2021-07-19 23:58:54 -07:00
try {
const stackId = this . getNodeParameter ( 'stackId' , i ) as string ;
const table = encodeURI ( this . getNodeParameter ( 'table' , i ) as string ) ;
const rowIds = this . getNodeParameter ( 'id' , i ) as string ;
qs . rowIds = [ rowIds ] ;
responseData = await apiRequest . call ( this , 'GET' , ` /rowlist/ ${ stackId } / ${ table } ` , { } , qs ) ;
2022-08-17 08:50:24 -07:00
returnData . push . apply (
returnData ,
2023-02-27 19:39:43 -08:00
responseData . map ( ( data : any ) = > data . field ) as INodeExecutionData [ ] ,
2022-08-17 08:50:24 -07:00
) ;
2021-07-19 23:58:54 -07:00
} catch ( error ) {
if ( this . continueOnFail ( ) ) {
2022-08-30 08:55:33 -07:00
const executionErrorData = this . helpers . constructExecutionMetaData (
this . helpers . returnJsonArray ( { error : error.message } ) ,
{ itemData : { item : i } } ,
) ;
returnData . push ( . . . executionErrorData ) ;
2021-07-19 23:58:54 -07:00
continue ;
}
throw error ;
}
2021-02-07 08:38:37 -08:00
}
}
if ( operation === 'delete' ) {
for ( let i = 0 ; i < length ; i ++ ) {
2021-07-19 23:58:54 -07:00
try {
const stackId = this . getNodeParameter ( 'stackId' , i ) as string ;
const table = encodeURI ( this . getNodeParameter ( 'table' , i ) as string ) ;
const rowIds = this . getNodeParameter ( 'id' , i ) as string ;
qs . rowIds = [ rowIds ] ;
2021-02-07 08:38:37 -08:00
2022-08-17 08:50:24 -07:00
responseData = await apiRequest . call (
this ,
'DELETE' ,
` /rowdelete/ ${ stackId } / ${ table } ` ,
{ } ,
qs ,
) ;
2021-07-19 23:58:54 -07:00
responseData = responseData . records ;
2022-08-30 08:55:33 -07:00
const executionData = this . helpers . constructExecutionMetaData (
2023-02-27 19:39:43 -08:00
this . helpers . returnJsonArray ( responseData as IDataObject ) ,
2022-08-30 08:55:33 -07:00
{ itemData : { item : i } } ,
) ;
returnData . push ( . . . executionData ) ;
2021-07-19 23:58:54 -07:00
} catch ( error ) {
if ( this . continueOnFail ( ) ) {
2022-08-30 08:55:33 -07:00
const executionErrorData = this . helpers . constructExecutionMetaData (
this . helpers . returnJsonArray ( { error : error.message } ) ,
{ itemData : { item : i } } ,
) ;
returnData . push ( . . . executionErrorData ) ;
2021-07-19 23:58:54 -07:00
continue ;
}
throw error ;
}
2021-02-07 08:38:37 -08:00
}
}
if ( operation === 'append' ) {
2021-07-19 23:58:54 -07:00
try {
const records : { [ key : string ] : IRecord [ ] } = { } ;
let key = '' ;
for ( let i = 0 ; i < length ; i ++ ) {
const stackId = this . getNodeParameter ( 'stackId' , i ) as string ;
const table = encodeURI ( this . getNodeParameter ( 'table' , i ) as string ) ;
const columns = this . getNodeParameter ( 'columns' , i ) as string ;
2022-08-17 08:50:24 -07:00
const columnList = columns . split ( ',' ) . map ( ( column ) = > column . trim ( ) ) ;
2021-02-07 08:38:37 -08:00
2021-07-19 23:58:54 -07:00
const record : { [ key : string ] : any } = { } ;
for ( const column of columnList ) {
if ( items [ i ] . json [ column ] === undefined ) {
2022-08-17 08:50:24 -07:00
throw new NodeOperationError (
this . getNode ( ) ,
` Column ${ column } does not exist on input ` ,
{ itemIndex : i } ,
) ;
2021-07-19 23:58:54 -07:00
} else {
record [ column ] = items [ i ] . json [ column ] ;
}
}
key = ` ${ stackId } / ${ table } ` ;
if ( records [ key ] === undefined ) {
records [ key ] = [ ] ;
2021-02-07 08:38:37 -08:00
}
2021-07-19 23:58:54 -07:00
records [ key ] . push ( { field : record } ) ;
2021-02-07 08:38:37 -08:00
}
2022-12-02 12:54:28 -08:00
for ( const recordKey of Object . keys ( records ) ) {
responseData = await apiRequest . call ( this , 'POST' , ` /rowcreate/ ${ recordKey } ` , {
records : records [ recordKey ] ,
2022-08-17 08:50:24 -07:00
} ) ;
2021-02-07 08:38:37 -08:00
}
2022-08-17 08:50:24 -07:00
returnData . push . apply (
returnData ,
2023-02-27 19:39:43 -08:00
responseData . map ( ( data : any ) = > data . field ) as INodeExecutionData [ ] ,
2022-08-17 08:50:24 -07:00
) ;
2021-07-19 23:58:54 -07:00
} catch ( error ) {
if ( this . continueOnFail ( ) ) {
2023-10-10 08:36:20 -07:00
const itemData = generatePairedItemData ( items . length ) ;
2022-08-30 08:55:33 -07:00
const executionErrorData = this . helpers . constructExecutionMetaData (
this . helpers . returnJsonArray ( { error : error.message } ) ,
2023-10-10 08:36:20 -07:00
{ itemData } ,
2022-08-30 08:55:33 -07:00
) ;
returnData . push ( . . . executionErrorData ) ;
2021-07-19 23:58:54 -07:00
} else {
throw error ;
}
2021-02-07 08:38:37 -08:00
}
}
if ( operation === 'list' ) {
for ( let i = 0 ; i < length ; i ++ ) {
2021-07-19 23:58:54 -07:00
try {
const stackId = this . getNodeParameter ( 'stackId' , i ) as string ;
const table = encodeURI ( this . getNodeParameter ( 'table' , i ) as string ) ;
2022-11-18 05:31:38 -08:00
const returnAll = this . getNodeParameter ( 'returnAll' , 0 ) ;
2021-02-07 08:38:37 -08:00
2022-12-02 12:54:28 -08:00
const additionalFields = this . getNodeParameter ( 'additionalFields' , i , { } ) ;
2021-02-07 08:38:37 -08:00
2021-07-19 23:58:54 -07:00
if ( additionalFields . view ) {
qs . view = additionalFields . view ;
}
2021-02-07 08:38:37 -08:00
2022-12-02 12:54:28 -08:00
if ( returnAll ) {
2022-08-17 08:50:24 -07:00
responseData = await apiRequestAllItems . call (
this ,
'GET' ,
` /rowlist/ ${ stackId } / ${ table } ` ,
{ } ,
qs ,
) ;
2021-07-19 23:58:54 -07:00
} else {
2022-11-18 06:26:22 -08:00
qs . maxrecord = this . getNodeParameter ( 'limit' , 0 ) ;
2022-08-17 08:50:24 -07:00
responseData = await apiRequest . call (
this ,
'GET' ,
` /rowlist/ ${ stackId } / ${ table } ` ,
{ } ,
qs ,
) ;
2021-07-19 23:58:54 -07:00
}
2021-02-07 08:38:37 -08:00
2022-08-17 08:50:24 -07:00
returnData . push . apply (
returnData ,
2023-02-27 19:39:43 -08:00
responseData . map ( ( data : any ) = > data . field ) as INodeExecutionData [ ] ,
2022-08-17 08:50:24 -07:00
) ;
2021-07-19 23:58:54 -07:00
} catch ( error ) {
if ( this . continueOnFail ( ) ) {
2022-08-30 08:55:33 -07:00
const executionErrorData = this . helpers . constructExecutionMetaData (
this . helpers . returnJsonArray ( { error : error.message } ) ,
{ itemData : { item : i } } ,
) ;
returnData . push ( . . . executionErrorData ) ;
2021-07-19 23:58:54 -07:00
continue ;
}
throw error ;
}
2021-02-07 08:38:37 -08:00
}
}
2023-09-05 03:59:02 -07:00
return [ returnData ] ;
2021-02-07 08:38:37 -08:00
}
}