2022-08-17 08:50:24 -07:00
import { IExecuteFunctions } from 'n8n-core' ;
2020-11-18 22:47:26 -08:00
import {
IDataObject ,
ILoadOptionsFunctions ,
INodeExecutionData ,
INodePropertyOptions ,
INodeType ,
INodeTypeDescription ,
2021-04-16 09:33:36 -07:00
NodeApiError ,
NodeOperationError ,
2020-11-18 22:47:26 -08:00
} from 'n8n-workflow' ;
2022-08-17 08:50:24 -07:00
import { googleApiRequest , googleApiRequestAllItems } from './GenericFunctions' ;
2020-11-18 22:47:26 -08:00
2022-06-20 07:54:01 -07:00
export class GoogleFirebaseRealtimeDatabase implements INodeType {
2020-11-18 22:47:26 -08:00
description : INodeTypeDescription = {
2020-12-23 03:47:21 -08:00
displayName : 'Google Cloud Realtime Database' ,
2020-11-18 22:47:26 -08:00
name : 'googleFirebaseRealtimeDatabase' ,
2022-04-14 00:19:45 -07:00
icon : 'file:googleFirebaseRealtimeDatabase.svg' ,
2020-11-18 22:47:26 -08:00
group : [ 'input' ] ,
version : 1 ,
subtitle : '={{$parameter["operation"]}}' ,
description : 'Interact with Google Firebase - Realtime Database API' ,
defaults : {
name : 'Google Cloud Realtime Database' ,
} ,
inputs : [ 'main' ] ,
outputs : [ 'main' ] ,
credentials : [
{
name : 'googleFirebaseRealtimeDatabaseOAuth2Api' ,
} ,
] ,
properties : [
{
2022-06-03 10:23:49 -07:00
displayName : 'Project Name or ID' ,
2020-11-18 22:47:26 -08:00
name : 'projectId' ,
type : 'options' ,
default : '' ,
typeOptions : {
loadOptionsMethod : 'getProjects' ,
} ,
2022-08-17 08:50:24 -07:00
description :
'As displayed in firebase console URL. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code-examples/expressions/">expression</a>.' ,
2020-11-18 22:47:26 -08:00
required : true ,
} ,
{
displayName : 'Operation' ,
name : 'operation' ,
type : 'options' ,
2022-04-14 00:19:45 -07:00
noDataExpression : true ,
2020-11-18 22:47:26 -08:00
options : [
{
name : 'Create' ,
value : 'create' ,
description : 'Write data to a database' ,
2022-07-10 13:50:51 -07:00
action : 'Write data to a database' ,
2020-11-18 22:47:26 -08:00
} ,
{
name : 'Delete' ,
value : 'delete' ,
description : 'Delete data from a database' ,
2022-07-10 13:50:51 -07:00
action : 'Delete data from a database' ,
2020-11-18 22:47:26 -08:00
} ,
{
name : 'Get' ,
value : 'get' ,
description : 'Get a record from a database' ,
2022-07-10 13:50:51 -07:00
action : 'Get a record from a database' ,
2020-11-18 22:47:26 -08:00
} ,
{
name : 'Push' ,
value : 'push' ,
description : 'Append to a list of data' ,
2022-07-10 13:50:51 -07:00
action : 'Append to a list of data' ,
2020-11-18 22:47:26 -08:00
} ,
{
name : 'Update' ,
value : 'update' ,
description : 'Update item on a database' ,
2022-07-10 13:50:51 -07:00
action : 'Update item in a database' ,
2020-11-18 22:47:26 -08:00
} ,
] ,
default : 'create' ,
required : true ,
} ,
{
displayName : 'Object Path' ,
name : 'path' ,
type : 'string' ,
default : '' ,
2022-04-14 00:19:45 -07:00
placeholder : 'e.g. /app/users' ,
2022-05-20 14:47:24 -07:00
// eslint-disable-next-line n8n-nodes-base/node-param-description-miscased-json
2022-04-14 00:19:45 -07:00
description : 'Object path on database. Do not append .json.' ,
2020-11-18 22:47:26 -08:00
required : true ,
2022-04-14 00:19:45 -07:00
displayOptions : {
hide : {
2022-08-17 08:50:24 -07:00
operation : [ 'get' ] ,
2022-04-14 00:19:45 -07:00
} ,
} ,
} ,
{
displayName : 'Object Path' ,
name : 'path' ,
type : 'string' ,
default : '' ,
placeholder : 'e.g. /app/users' ,
2022-05-20 14:47:24 -07:00
// eslint-disable-next-line n8n-nodes-base/node-param-description-miscased-json
2022-04-14 00:19:45 -07:00
description : 'Object path on database. Do not append .json.' ,
hint : 'Leave blank to get a whole database object' ,
displayOptions : {
show : {
2022-08-17 08:50:24 -07:00
operation : [ 'get' ] ,
2022-04-14 00:19:45 -07:00
} ,
} ,
2020-11-18 22:47:26 -08:00
} ,
{
displayName : 'Columns / Attributes' ,
name : 'attributes' ,
type : 'string' ,
default : '' ,
displayOptions : {
show : {
2022-08-17 08:50:24 -07:00
operation : [ 'create' , 'push' , 'update' ] ,
2020-11-18 22:47:26 -08:00
} ,
} ,
description : 'Attributes to save' ,
required : true ,
placeholder : 'age, name, city' ,
} ,
] ,
} ;
methods = {
loadOptions : {
2022-08-17 08:50:24 -07:00
async getProjects ( this : ILoadOptionsFunctions ) : Promise < INodePropertyOptions [ ] > {
2020-11-18 22:47:26 -08:00
const projects = await googleApiRequestAllItems . call (
this ,
2022-04-14 00:19:45 -07:00
'' ,
2020-11-18 22:47:26 -08:00
'GET' ,
'results' ,
{ } ,
{ } ,
{ } ,
'https://firebase.googleapis.com/v1beta1/projects' ,
) ;
2022-04-14 00:19:45 -07:00
const returnData = projects
2022-08-17 08:50:24 -07:00
// select only realtime database projects
. filter (
( project : IDataObject ) = > ( project . resources as IDataObject ) . realtimeDatabaseInstance ,
)
. map ( ( project : IDataObject ) = > ( {
name : project.projectId ,
value : ( project . resources as IDataObject ) . realtimeDatabaseInstance ,
} ) ) as INodePropertyOptions [ ] ;
2022-04-14 00:19:45 -07:00
2020-11-18 22:47:26 -08:00
return returnData ;
} ,
} ,
} ;
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 ;
2020-11-18 22:47:26 -08:00
let responseData ;
const operation = this . getNodeParameter ( 'operation' , 0 ) as string ;
//https://firebase.google.com/docs/reference/rest/database
2022-08-17 08:50:24 -07:00
if (
[ 'push' , 'create' , 'update' ] . includes ( operation ) &&
items . length === 1 &&
Object . keys ( items [ 0 ] . json ) . length === 0
) {
2021-04-16 09:33:36 -07:00
throw new NodeOperationError ( this . getNode ( ) , ` The ${ operation } operation needs input data ` ) ;
2020-11-18 22:47:26 -08:00
}
for ( let i = 0 ; i < length ; i ++ ) {
2021-07-19 23:58:54 -07:00
try {
const projectId = this . getNodeParameter ( 'projectId' , i ) as string ;
2022-04-14 00:19:45 -07:00
2022-08-17 08:50:24 -07:00
let method = 'GET' ,
attributes = '' ;
2021-07-19 23:58:54 -07:00
const document : IDataObject = { } ;
if ( operation === 'create' ) {
method = 'PUT' ;
attributes = this . getNodeParameter ( 'attributes' , i ) as string ;
} else if ( operation === 'delete' ) {
method = 'DELETE' ;
} else if ( operation === 'get' ) {
method = 'GET' ;
} else if ( operation === 'push' ) {
method = 'POST' ;
attributes = this . getNodeParameter ( 'attributes' , i ) as string ;
} else if ( operation === 'update' ) {
method = 'PATCH' ;
attributes = this . getNodeParameter ( 'attributes' , i ) as string ;
}
2020-11-18 22:47:26 -08:00
2021-07-19 23:58:54 -07:00
if ( attributes ) {
2022-08-17 08:50:24 -07:00
const attributeList = attributes . split ( ',' ) . map ( ( el ) = > el . trim ( ) ) ;
2021-07-19 23:58:54 -07:00
attributeList . map ( ( attribute : string ) = > {
if ( items [ i ] . json . hasOwnProperty ( attribute ) ) {
document [ attribute ] = items [ i ] . json [ attribute ] ;
}
} ) ;
}
2020-11-18 22:47:26 -08:00
2021-07-19 23:58:54 -07:00
responseData = await googleApiRequest . call (
this ,
projectId ,
method ,
this . getNodeParameter ( 'path' , i ) as string ,
document ,
) ;
2020-11-18 22:47:26 -08:00
2021-07-19 23:58:54 -07:00
if ( responseData === null ) {
if ( operation === 'get' ) {
2022-08-17 08:50:24 -07:00
throw new NodeApiError ( this . getNode ( ) , responseData , {
message : ` Requested entity was not found. ` ,
} ) ;
2021-07-19 23:58:54 -07:00
} else if ( method === 'DELETE' ) {
responseData = { success : true } ;
}
2020-11-18 22:47:26 -08: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 ;
2020-11-18 22:47:26 -08:00
}
2022-08-30 08:55:33 -07:00
if ( typeof responseData === 'string' || typeof responseData === 'number' ) {
responseData = {
2022-08-17 08:50:24 -07:00
[ this . getNodeParameter ( 'path' , i ) as string ] : responseData ,
2022-08-30 08:55:33 -07:00
} ;
2020-11-18 22:47:26 -08:00
}
2022-08-30 08:55:33 -07:00
const executionData = this . helpers . constructExecutionMetaData (
this . helpers . returnJsonArray ( responseData ) ,
{ itemData : { item : i } } ,
) ;
returnData . push ( . . . executionData ) ;
2020-11-18 22:47:26 -08:00
}
2022-08-30 08:55:33 -07:00
return this . prepareOutputData ( returnData ) ;
2020-11-18 22:47:26 -08:00
}
}