2020-11-06 17:18:10 -08:00
import {
IPollFunctions ,
} from 'n8n-core' ;
import {
IDataObject ,
INodeExecutionData ,
INodeType ,
INodeTypeDescription ,
2021-04-16 09:33:36 -07:00
NodeOperationError ,
2020-11-06 17:18:10 -08:00
} from 'n8n-workflow' ;
import {
apiRequestAllItems ,
2021-02-04 06:43:48 -08:00
downloadRecordAttachments ,
2020-11-06 17:18:10 -08:00
} from './GenericFunctions' ;
import * as moment from 'moment' ;
export class AirtableTrigger implements INodeType {
description : INodeTypeDescription = {
displayName : 'Airtable Trigger' ,
name : 'airtableTrigger' ,
2020-11-25 05:09:29 -08:00
icon : 'file:airtable.svg' ,
2020-11-06 17:18:10 -08:00
group : [ 'trigger' ] ,
version : 1 ,
description : 'Starts the workflow when Airtable events occur' ,
subtitle : '={{$parameter["event"]}}' ,
defaults : {
name : 'Airtable Trigger' ,
} ,
credentials : [
{
name : 'airtableApi' ,
required : true ,
} ,
] ,
polling : true ,
inputs : [ ] ,
outputs : [ 'main' ] ,
properties : [
{
displayName : 'Base ID' ,
name : 'baseId' ,
type : 'string' ,
default : '' ,
required : true ,
2020-11-10 13:40:44 -08:00
description : 'The ID of this base.' ,
2020-11-06 17:18:10 -08:00
} ,
{
2020-11-10 13:40:44 -08:00
displayName : 'Table' ,
2020-11-06 17:18:10 -08:00
name : 'tableId' ,
type : 'string' ,
default : '' ,
2020-11-10 13:40:44 -08:00
description : 'The name of table to access.' ,
2020-11-06 17:18:10 -08:00
required : true ,
2020-11-10 13:40:44 -08:00
} ,
{
2020-11-06 17:18:10 -08:00
displayName : 'Trigger Field' ,
name : 'triggerField' ,
type : 'string' ,
default : '' ,
2021-11-25 09:10:06 -08:00
description : ` A Created Time or Last Modified Time field that will be used to sort records. If you do not have a Created Time or Last Modified Time field in your schema, please create one, because without this field trigger will not work correctly. ` ,
2020-11-06 17:18:10 -08:00
required : true ,
} ,
2021-02-04 06:43:48 -08:00
{
displayName : 'Download Attachments' ,
name : 'downloadAttachments' ,
type : 'boolean' ,
default : false ,
description : ` When set to true the attachment fields define in 'Download Fields' will be downloaded. ` ,
} ,
{
displayName : 'Download Fields' ,
name : 'downloadFieldNames' ,
type : 'string' ,
required : true ,
displayOptions : {
show : {
downloadAttachments : [
true ,
] ,
} ,
} ,
default : '' ,
description : ` Name of the fields of type 'attachment' that should be downloaded. Multiple ones can be defined separated by comma. Case sensitive. ` ,
} ,
2020-11-06 17:18:10 -08:00
{
displayName : 'Additional Fields' ,
name : 'additionalFields' ,
type : 'collection' ,
placeholder : 'Add Field' ,
default : { } ,
options : [
{
displayName : 'Fields' ,
name : 'fields' ,
type : 'string' ,
default : '' ,
2021-11-25 09:10:06 -08:00
description : ` Fields to be included in the response. Multiple ones can be set separated by comma. Example: <code>name, id</code>. By default just the trigger field will be included. ` ,
2020-11-06 17:18:10 -08:00
} ,
{
displayName : 'Formula' ,
name : 'formula' ,
type : 'string' ,
default : '' ,
2021-08-26 10:42:38 -07:00
description : ` Formulas may involve functions, numeric operations, logical operations, and text operations that operate on fields. More info <a href="https://support.airtable.com/hc/en-us/articles/203255215-Formula-Field-Reference">here</a>. ` ,
2020-11-06 17:18:10 -08:00
} ,
{
displayName : 'View ID' ,
name : 'viewId' ,
type : 'string' ,
default : '' ,
2020-11-24 12:07:28 -08:00
description : 'The name or ID of a view in the table. If set, only the records in that view will be returned.' ,
2020-11-06 17:18:10 -08:00
} ,
] ,
} ,
] ,
} ;
async poll ( this : IPollFunctions ) : Promise < INodeExecutionData [ ] [ ] | null > {
2021-02-04 06:43:48 -08:00
const downloadAttachments = this . getNodeParameter ( 'downloadAttachments' , 0 ) as boolean ;
2020-11-06 17:18:10 -08:00
const webhookData = this . getWorkflowStaticData ( 'node' ) ;
const qs : IDataObject = { } ;
const additionalFields = this . getNodeParameter ( 'additionalFields' ) as IDataObject ;
const base = this . getNodeParameter ( 'baseId' ) as string ;
const table = this . getNodeParameter ( 'tableId' ) as string ;
const triggerField = this . getNodeParameter ( 'triggerField' ) as string ;
const endpoint = ` ${ base } / ${ table } ` ;
const now = moment ( ) . utc ( ) . format ( ) ;
const startDate = webhookData . lastTimeChecked as string || now ;
const endDate = now ;
if ( additionalFields . viewId ) {
qs . view = additionalFields . viewId ;
}
if ( additionalFields . fields ) {
qs [ 'fields[]' ] = ( additionalFields . fields as string ) . split ( ',' ) ;
}
qs . filterByFormula = ` IS_AFTER({ ${ triggerField } }, DATETIME_PARSE(" ${ startDate } ", "YYYY-MM-DD HH:mm:ss")) ` ;
if ( additionalFields . formula ) {
qs . filterByFormula = ` AND( ${ qs . filterByFormula } , ${ additionalFields . formula } ) ` ;
}
2020-11-14 17:21:41 -08:00
if ( this . getMode ( ) === 'manual' ) {
delete qs . filterByFormula ;
qs . maxRecords = 1 ;
}
2020-11-06 17:18:10 -08:00
const { records } = await apiRequestAllItems . call ( this , 'GET' , endpoint , { } , qs ) ;
webhookData . lastTimeChecked = endDate ;
if ( Array . isArray ( records ) && records . length ) {
2020-11-24 10:58:49 -08:00
if ( this . getMode ( ) === 'manual' && records [ 0 ] . fields [ triggerField ] === undefined ) {
2021-04-16 09:33:36 -07:00
throw new NodeOperationError ( this . getNode ( ) , ` The Field " ${ triggerField } " does not exist. ` ) ;
2020-11-24 10:58:49 -08:00
}
2021-02-04 06:43:48 -08:00
if ( downloadAttachments === true ) {
const downloadFieldNames = ( this . getNodeParameter ( 'downloadFieldNames' , 0 ) as string ) . split ( ',' ) ;
const data = await downloadRecordAttachments . call ( this , records , downloadFieldNames ) ;
return [ data ] ;
}
2020-11-06 17:18:10 -08:00
return [ this . helpers . returnJsonArray ( records ) ] ;
}
return null ;
}
}