2019-06-23 03:35:23 -07:00
import { IExecuteFunctions } from 'n8n-core' ;
import {
GenericValue ,
2022-09-01 05:29:15 -07:00
ICredentialDataDecryptedObject ,
ICredentialsDecrypted ,
ICredentialTestFunctions ,
2019-06-23 03:35:23 -07:00
IDataObject ,
2022-09-01 05:29:15 -07:00
INodeCredentialTestResult ,
2019-06-23 03:35:23 -07:00
INodeExecutionData ,
INodeType ,
INodeTypeDescription ,
2021-04-16 09:33:36 -07:00
NodeOperationError ,
2019-06-23 03:35:23 -07:00
} from 'n8n-workflow' ;
import { set } from 'lodash' ;
2022-04-08 14:32:08 -07:00
import redis from 'redis' ;
2019-06-23 03:35:23 -07:00
2022-04-08 14:32:08 -07:00
import util from 'util' ;
2019-06-23 03:35:23 -07:00
export class Redis implements INodeType {
description : INodeTypeDescription = {
displayName : 'Redis' ,
name : 'redis' ,
2021-03-25 09:10:02 -07:00
icon : 'file:redis.svg' ,
2019-06-23 03:35:23 -07:00
group : [ 'input' ] ,
version : 1 ,
2021-07-03 05:40:16 -07:00
description : 'Get, send and update data in Redis' ,
2019-06-23 03:35:23 -07:00
defaults : {
name : 'Redis' ,
} ,
inputs : [ 'main' ] ,
outputs : [ 'main' ] ,
credentials : [
{
name : 'redis' ,
required : true ,
2022-09-01 05:29:15 -07:00
testedBy : 'redisConnectionTest' ,
2020-10-22 06:46:03 -07:00
} ,
2019-06-23 03:35:23 -07:00
] ,
properties : [
{
displayName : 'Operation' ,
name : 'operation' ,
type : 'options' ,
2022-05-20 14:47:24 -07:00
noDataExpression : true ,
2019-06-23 03:35:23 -07:00
options : [
{
name : 'Delete' ,
value : 'delete' ,
2022-05-06 14:01:25 -07:00
description : 'Delete a key from Redis' ,
2022-07-10 13:50:51 -07:00
action : 'Delete a key from Redis' ,
2019-06-23 03:35:23 -07:00
} ,
{
name : 'Get' ,
value : 'get' ,
2022-05-06 14:01:25 -07:00
description : 'Get the value of a key from Redis' ,
2022-07-10 13:50:51 -07:00
action : 'Get the value of a key from Redis' ,
2019-06-23 03:35:23 -07:00
} ,
2021-05-07 16:33:14 -07:00
{
name : 'Increment' ,
value : 'incr' ,
description : 'Atomically increments a key by 1. Creates the key if it does not exist.' ,
2022-07-10 13:50:51 -07:00
action : 'Atomically increment a key by 1. Creates the key if it does not exist.' ,
2021-05-07 16:33:14 -07:00
} ,
2022-06-03 10:23:49 -07:00
{
name : 'Info' ,
value : 'info' ,
description : 'Returns generic information about the Redis instance' ,
2022-07-10 13:50:51 -07:00
action : 'Return generic information about the Redis instance' ,
2022-06-03 10:23:49 -07:00
} ,
2019-06-23 03:35:23 -07:00
{
name : 'Keys' ,
value : 'keys' ,
2022-05-06 14:01:25 -07:00
description : 'Returns all the keys matching a pattern' ,
2022-07-10 13:50:51 -07:00
action : 'Return all keys matching a pattern' ,
2019-06-23 03:35:23 -07:00
} ,
2022-07-09 23:12:18 -07:00
{
name : 'Pop' ,
value : 'pop' ,
description : 'Pop data from a redis list' ,
2022-07-13 01:38:12 -07:00
action : 'Pop data from a redis list' ,
2022-07-09 23:12:18 -07:00
} ,
2022-03-12 03:14:39 -08:00
{
name : 'Publish' ,
value : 'publish' ,
2022-05-06 14:01:25 -07:00
description : 'Publish message to redis channel' ,
2022-07-10 13:50:51 -07:00
action : 'Publish message to redis channel' ,
2022-03-12 03:14:39 -08:00
} ,
2022-07-09 23:12:18 -07:00
{
name : 'Push' ,
value : 'push' ,
description : 'Push data to a redis list' ,
2022-07-13 01:38:12 -07:00
action : 'Push data to a redis list' ,
2022-07-09 23:12:18 -07:00
} ,
2022-06-03 10:23:49 -07:00
{
name : 'Set' ,
value : 'set' ,
description : 'Set the value of a key in redis' ,
2022-07-10 13:50:51 -07:00
action : 'Set the value of a key in redis' ,
2022-06-03 10:23:49 -07:00
} ,
2019-06-23 03:35:23 -07:00
] ,
default : 'info' ,
} ,
// ----------------------------------
// get
// ----------------------------------
{
displayName : 'Name' ,
name : 'propertyName' ,
type : 'string' ,
displayOptions : {
show : {
2022-08-17 08:50:24 -07:00
operation : [ 'get' ] ,
2019-06-23 03:35:23 -07:00
} ,
} ,
default : 'propertyName' ,
required : true ,
2022-08-17 08:50:24 -07:00
description :
'Name of the property to write received data to. Supports dot-notation. Example: "data.person[0].name".' ,
2019-06-23 03:35:23 -07:00
} ,
{
displayName : 'Key' ,
name : 'key' ,
type : 'string' ,
displayOptions : {
show : {
2022-08-17 08:50:24 -07:00
operation : [ 'delete' ] ,
2019-06-23 03:35:23 -07:00
} ,
} ,
default : '' ,
required : true ,
2022-05-06 14:01:25 -07:00
description : 'Name of the key to delete from Redis' ,
2019-06-23 03:35:23 -07:00
} ,
{
displayName : 'Key' ,
name : 'key' ,
type : 'string' ,
displayOptions : {
show : {
2022-08-17 08:50:24 -07:00
operation : [ 'get' ] ,
2019-06-23 03:35:23 -07:00
} ,
} ,
default : '' ,
required : true ,
2022-05-06 14:01:25 -07:00
description : 'Name of the key to get from Redis' ,
2019-06-23 03:35:23 -07:00
} ,
{
displayName : 'Key Type' ,
name : 'keyType' ,
type : 'options' ,
displayOptions : {
show : {
2022-08-17 08:50:24 -07:00
operation : [ 'get' ] ,
2019-06-23 03:35:23 -07:00
} ,
} ,
options : [
{
name : 'Automatic' ,
value : 'automatic' ,
2022-05-06 14:01:25 -07:00
description : 'Requests the type before requesting the data (slower)' ,
2019-06-23 03:35:23 -07:00
} ,
{
name : 'Hash' ,
value : 'hash' ,
2022-08-17 08:50:24 -07:00
description : "Data in key is of type 'hash'" ,
2019-06-23 03:35:23 -07:00
} ,
{
name : 'List' ,
value : 'list' ,
2022-08-17 08:50:24 -07:00
description : "Data in key is of type 'lists'" ,
2019-06-23 03:35:23 -07:00
} ,
{
name : 'Sets' ,
value : 'sets' ,
2022-08-17 08:50:24 -07:00
description : "Data in key is of type 'sets'" ,
2022-06-03 10:23:49 -07:00
} ,
{
name : 'String' ,
value : 'string' ,
2022-08-17 08:50:24 -07:00
description : "Data in key is of type 'string'" ,
2019-06-23 03:35:23 -07:00
} ,
] ,
default : 'automatic' ,
2022-05-06 14:01:25 -07:00
description : 'The type of the key to get' ,
2019-06-23 03:35:23 -07:00
} ,
2020-05-05 06:52:47 -07:00
{
displayName : 'Options' ,
name : 'options' ,
type : 'collection' ,
displayOptions : {
show : {
2022-08-17 08:50:24 -07:00
operation : [ 'get' ] ,
2020-05-05 06:52:47 -07:00
} ,
} ,
placeholder : 'Add Option' ,
default : { } ,
options : [
{
displayName : 'Dot Notation' ,
name : 'dotNotation' ,
type : 'boolean' ,
default : true ,
2022-06-20 07:54:01 -07:00
// eslint-disable-next-line n8n-nodes-base/node-param-description-boolean-without-whether
2022-08-17 08:50:24 -07:00
description :
'<p>By default, dot-notation is used in property names. This means that "a.b" will set the property "b" underneath "a" so { "a": { "b": value} }.<p></p>If that is not intended this can be deactivated, it will then set { "a.b": value } instead.</p>.' ,
2020-05-05 06:52:47 -07:00
} ,
] ,
} ,
2021-05-07 16:33:14 -07:00
// ----------------------------------
// incr
// ----------------------------------
{
displayName : 'Key' ,
name : 'key' ,
type : 'string' ,
displayOptions : {
show : {
2022-08-17 08:50:24 -07:00
operation : [ 'incr' ] ,
2021-05-07 16:33:14 -07:00
} ,
} ,
default : '' ,
required : true ,
2022-05-06 14:01:25 -07:00
description : 'Name of the key to increment' ,
2021-05-07 16:33:14 -07:00
} ,
{
displayName : 'Expire' ,
name : 'expire' ,
type : 'boolean' ,
displayOptions : {
show : {
2022-08-17 08:50:24 -07:00
operation : [ 'incr' ] ,
2021-05-07 16:33:14 -07:00
} ,
} ,
default : false ,
2022-06-20 07:54:01 -07:00
description : 'Whether to set a timeout on key' ,
2021-05-07 16:33:14 -07:00
} ,
{
displayName : 'TTL' ,
name : 'ttl' ,
type : 'number' ,
typeOptions : {
minValue : 1 ,
} ,
displayOptions : {
show : {
2022-08-17 08:50:24 -07:00
operation : [ 'incr' ] ,
expire : [ true ] ,
2021-05-07 16:33:14 -07:00
} ,
} ,
default : 60 ,
2022-05-06 14:01:25 -07:00
description : 'Number of seconds before key expiration' ,
2021-05-07 16:33:14 -07:00
} ,
2019-06-23 03:35:23 -07:00
// ----------------------------------
// keys
// ----------------------------------
{
displayName : 'Key Pattern' ,
name : 'keyPattern' ,
type : 'string' ,
displayOptions : {
show : {
2022-08-17 08:50:24 -07:00
operation : [ 'keys' ] ,
2019-06-23 03:35:23 -07:00
} ,
} ,
default : '' ,
required : true ,
2022-05-06 14:01:25 -07:00
description : 'The key pattern for the keys to return' ,
2019-06-23 03:35:23 -07:00
} ,
2022-07-09 23:12:18 -07:00
{
displayName : 'Get Values' ,
name : 'getValues' ,
type : 'boolean' ,
displayOptions : {
show : {
2022-08-17 08:50:24 -07:00
operation : [ 'keys' ] ,
2022-07-09 23:12:18 -07:00
} ,
} ,
default : true ,
description : 'Whether to get the value of matching keys' ,
} ,
2019-06-23 03:35:23 -07:00
// ----------------------------------
// set
// ----------------------------------
{
displayName : 'Key' ,
name : 'key' ,
type : 'string' ,
displayOptions : {
show : {
2022-08-17 08:50:24 -07:00
operation : [ 'set' ] ,
2019-06-23 03:35:23 -07:00
} ,
} ,
default : '' ,
required : true ,
2022-05-06 14:01:25 -07:00
description : 'Name of the key to set in Redis' ,
2019-06-23 03:35:23 -07:00
} ,
{
displayName : 'Value' ,
name : 'value' ,
type : 'string' ,
displayOptions : {
show : {
2022-08-17 08:50:24 -07:00
operation : [ 'set' ] ,
2019-06-23 03:35:23 -07:00
} ,
} ,
default : '' ,
2022-05-06 14:01:25 -07:00
description : 'The value to write in Redis' ,
2019-06-23 03:35:23 -07:00
} ,
{
displayName : 'Key Type' ,
name : 'keyType' ,
type : 'options' ,
displayOptions : {
show : {
2022-08-17 08:50:24 -07:00
operation : [ 'set' ] ,
2019-06-23 03:35:23 -07:00
} ,
} ,
options : [
{
name : 'Automatic' ,
value : 'automatic' ,
2022-05-06 14:01:25 -07:00
description : 'Tries to figure out the type automatically depending on the data' ,
2019-06-23 03:35:23 -07:00
} ,
{
name : 'Hash' ,
value : 'hash' ,
2022-08-17 08:50:24 -07:00
description : "Data in key is of type 'hash'" ,
2019-06-23 03:35:23 -07:00
} ,
{
name : 'List' ,
value : 'list' ,
2022-08-17 08:50:24 -07:00
description : "Data in key is of type 'lists'" ,
2019-06-23 03:35:23 -07:00
} ,
{
name : 'Sets' ,
value : 'sets' ,
2022-08-17 08:50:24 -07:00
description : "Data in key is of type 'sets'" ,
2022-06-03 10:23:49 -07:00
} ,
{
name : 'String' ,
value : 'string' ,
2022-08-17 08:50:24 -07:00
description : "Data in key is of type 'string'" ,
2019-06-23 03:35:23 -07:00
} ,
] ,
default : 'automatic' ,
2022-05-06 14:01:25 -07:00
description : 'The type of the key to set' ,
2019-06-23 03:35:23 -07:00
} ,
2020-01-08 02:27:39 -08:00
{
displayName : 'Expire' ,
name : 'expire' ,
type : 'boolean' ,
2020-01-08 03:22:18 -08:00
displayOptions : {
show : {
2022-08-17 08:50:24 -07:00
operation : [ 'set' ] ,
2020-01-08 03:22:18 -08:00
} ,
} ,
2020-01-08 02:27:39 -08:00
default : false ,
2022-06-20 07:54:01 -07:00
description : 'Whether to set a timeout on key' ,
2020-01-08 02:27:39 -08:00
} ,
{
displayName : 'TTL' ,
name : 'ttl' ,
type : 'number' ,
typeOptions : {
minValue : 1 ,
} ,
displayOptions : {
show : {
2022-08-17 08:50:24 -07:00
operation : [ 'set' ] ,
expire : [ true ] ,
2020-01-08 02:27:39 -08:00
} ,
} ,
default : 60 ,
2022-05-06 14:01:25 -07:00
description : 'Number of seconds before key expiration' ,
2020-10-22 06:46:03 -07:00
} ,
2022-03-12 03:14:39 -08:00
// ----------------------------------
// publish
// ----------------------------------
{
displayName : 'Channel' ,
name : 'channel' ,
type : 'string' ,
displayOptions : {
show : {
2022-08-17 08:50:24 -07:00
operation : [ 'publish' ] ,
2022-03-12 03:14:39 -08:00
} ,
} ,
default : '' ,
required : true ,
2022-05-06 14:01:25 -07:00
description : 'Channel name' ,
2022-03-12 03:14:39 -08:00
} ,
{
displayName : 'Data' ,
name : 'messageData' ,
type : 'string' ,
displayOptions : {
show : {
2022-08-17 08:50:24 -07:00
operation : [ 'publish' ] ,
2022-03-12 03:14:39 -08:00
} ,
} ,
typeOptions : {
alwaysOpenEditWindow : true ,
} ,
default : '' ,
required : true ,
2022-05-06 14:01:25 -07:00
description : 'Data to publish' ,
2022-03-12 03:14:39 -08:00
} ,
2022-07-09 23:12:18 -07:00
// ----------------------------------
// push/pop
// ----------------------------------
{
displayName : 'List' ,
name : 'list' ,
type : 'string' ,
displayOptions : {
show : {
2022-08-17 08:50:24 -07:00
operation : [ 'push' , 'pop' ] ,
2022-07-09 23:12:18 -07:00
} ,
} ,
default : '' ,
required : true ,
description : 'Name of the list in Redis' ,
} ,
{
displayName : 'Data' ,
name : 'messageData' ,
type : 'string' ,
displayOptions : {
show : {
2022-08-17 08:50:24 -07:00
operation : [ 'push' ] ,
2022-07-09 23:12:18 -07:00
} ,
} ,
typeOptions : {
alwaysOpenEditWindow : true ,
} ,
default : '' ,
required : true ,
description : 'Data to push' ,
} ,
{
displayName : 'Tail' ,
name : 'tail' ,
type : 'boolean' ,
displayOptions : {
show : {
2022-08-17 08:50:24 -07:00
operation : [ 'push' , 'pop' ] ,
2022-07-09 23:12:18 -07:00
} ,
} ,
default : false ,
description : 'Whether to push or pop data from the end of the list' ,
} ,
{
displayName : 'Name' ,
name : 'propertyName' ,
type : 'string' ,
displayOptions : {
show : {
2022-08-17 08:50:24 -07:00
operation : [ 'pop' ] ,
2022-07-09 23:12:18 -07:00
} ,
} ,
default : 'propertyName' ,
2022-08-17 08:50:24 -07:00
description :
'Optional name of the property to write received data to. Supports dot-notation. Example: "data.person[0].name".' ,
2022-07-09 23:12:18 -07:00
} ,
{
displayName : 'Options' ,
name : 'options' ,
type : 'collection' ,
displayOptions : {
show : {
2022-08-17 08:50:24 -07:00
operation : [ 'pop' ] ,
2022-07-09 23:12:18 -07:00
} ,
} ,
placeholder : 'Add Option' ,
default : { } ,
options : [
{
displayName : 'Dot Notation' ,
name : 'dotNotation' ,
type : 'boolean' ,
default : true ,
// eslint-disable-next-line n8n-nodes-base/node-param-description-boolean-without-whether
2022-08-17 08:50:24 -07:00
description :
'<p>By default, dot-notation is used in property names. This means that "a.b" will set the property "b" underneath "a" so { "a": { "b": value} }.<p></p>If that is not intended this can be deactivated, it will then set { "a.b": value } instead.</p>.' ,
2022-07-09 23:12:18 -07:00
} ,
] ,
} ,
2020-10-22 06:46:03 -07:00
] ,
2019-06-23 03:35:23 -07:00
} ;
2022-09-01 05:29:15 -07:00
methods = {
credentialTest : {
async redisConnectionTest (
this : ICredentialTestFunctions ,
credential : ICredentialsDecrypted ,
) : Promise < INodeCredentialTestResult > {
const credentials = credential . data as ICredentialDataDecryptedObject ;
const redisOptions : redis.ClientOpts = {
host : credentials.host as string ,
port : credentials.port as number ,
db : credentials.database as number ,
} ;
if ( credentials . password ) {
redisOptions . password = credentials . password as string ;
}
try {
const client = await redis . createClient ( redisOptions ) ;
// tslint:disable-next-line: no-any
2022-11-08 06:28:21 -08:00
const _data = await new Promise ( ( resolve , reject ) : any = > {
2022-09-01 05:29:15 -07:00
client . on ( 'connect' , async ( ) = > {
client . ping ( 'ping' , ( error , pong ) = > {
if ( error ) reject ( error ) ;
resolve ( pong ) ;
client . quit ( ) ;
} ) ;
} ) ;
client . on ( 'error' , async ( err ) = > {
client . quit ( ) ;
reject ( err ) ;
} ) ;
} ) ;
} catch ( error ) {
return {
status : 'Error' ,
message : error.message ,
} ;
}
return {
status : 'OK' ,
message : 'Connection successful!' ,
} ;
} ,
} ,
} ;
2019-06-23 03:35:23 -07:00
execute ( this : IExecuteFunctions ) : Promise < INodeExecutionData [ ] [ ] > {
// Parses the given value in a number if it is one else returns a string
2020-05-05 06:52:47 -07:00
function getParsedValue ( value : string ) : string | number {
2019-06-23 03:35:23 -07:00
if ( value . match ( /^[\d\.]+$/ ) === null ) {
// Is a string
return value ;
} else {
// Is a number
return parseFloat ( value ) ;
}
}
// Converts the Redis Info String into an object
function convertInfoToObject ( stringData : string ) : IDataObject {
const returnData : IDataObject = { } ;
2020-05-05 06:52:47 -07:00
let key : string , value : string ;
2019-06-23 03:35:23 -07:00
for ( const line of stringData . split ( '\n' ) ) {
if ( [ '#' , '' ] . includes ( line . charAt ( 0 ) ) ) {
continue ;
}
[ key , value ] = line . split ( ':' ) ;
if ( key === undefined || value === undefined ) {
continue ;
}
value = value . trim ( ) ;
if ( value . includes ( '=' ) ) {
returnData [ key ] = { } ;
let key2 : string , value2 : string ;
for ( const keyValuePair of value . split ( ',' ) ) {
[ key2 , value2 ] = keyValuePair . split ( '=' ) ;
( returnData [ key ] as IDataObject ) [ key2 ] = getParsedValue ( value2 ) ;
}
} else {
returnData [ key ] = getParsedValue ( value ) ;
}
}
return returnData ;
}
async function getValue ( client : redis.RedisClient , keyName : string , type ? : string ) {
if ( type === undefined || type === 'automatic' ) {
// Request the type first
const clientType = util . promisify ( client . type ) . bind ( client ) ;
type = await clientType ( keyName ) ;
}
if ( type === 'string' ) {
const clientGet = util . promisify ( client . get ) . bind ( client ) ;
return await clientGet ( keyName ) ;
} else if ( type === 'hash' ) {
const clientHGetAll = util . promisify ( client . hgetall ) . bind ( client ) ;
return await clientHGetAll ( keyName ) ;
} else if ( type === 'list' ) {
const clientLRange = util . promisify ( client . lrange ) . bind ( client ) ;
return await clientLRange ( keyName , 0 , - 1 ) ;
} else if ( type === 'sets' ) {
const clientSMembers = util . promisify ( client . smembers ) . bind ( client ) ;
return await clientSMembers ( keyName ) ;
}
}
2022-08-17 08:50:24 -07:00
const setValue = async (
client : redis.RedisClient ,
keyName : string ,
value : string | number | object | string [ ] | number [ ] ,
expire : boolean ,
ttl : number ,
type ? : string ,
) = > {
2019-06-23 03:35:23 -07:00
if ( type === undefined || type === 'automatic' ) {
// Request the type first
if ( typeof value === 'string' ) {
type = 'string' ;
} else if ( Array . isArray ( value ) ) {
type = 'list' ;
} else if ( typeof value === 'object' ) {
type = 'hash' ;
} else {
2022-08-17 08:50:24 -07:00
throw new NodeOperationError (
this . getNode ( ) ,
'Could not identify the type to set. Please set it manually!' ,
) ;
2019-06-23 03:35:23 -07:00
}
}
if ( type === 'string' ) {
const clientSet = util . promisify ( client . set ) . bind ( client ) ;
2020-01-08 02:27:39 -08:00
await clientSet ( keyName , value . toString ( ) ) ;
2019-06-23 03:35:23 -07:00
} else if ( type === 'hash' ) {
const clientHset = util . promisify ( client . hset ) . bind ( client ) ;
for ( const key of Object . keys ( value ) ) {
2020-07-02 22:31:08 -07:00
// @ts-ignore
2019-06-23 03:35:23 -07:00
await clientHset ( keyName , key , ( value as IDataObject ) [ key ] ! . toString ( ) ) ;
}
} else if ( type === 'list' ) {
const clientLset = util . promisify ( client . lset ) . bind ( client ) ;
for ( let index = 0 ; index < ( value as string [ ] ) . length ; index ++ ) {
await clientLset ( keyName , index , ( value as IDataObject ) [ index ] ! . toString ( ) ) ;
}
}
2020-01-08 02:27:39 -08:00
if ( expire === true ) {
const clientExpire = util . promisify ( client . expire ) . bind ( client ) ;
await clientExpire ( keyName , ttl ) ;
}
return ;
2021-04-16 09:33:36 -07:00
} ;
2019-06-23 03:35:23 -07:00
2021-08-20 09:57:30 -07:00
return new Promise ( async ( resolve , reject ) = > {
2019-06-23 03:35:23 -07:00
// TODO: For array and object fields it should not have a "value" field it should
// have a parameter field for a path. Because it is not possible to set
// array, object via parameter directly (should maybe be possible?!?!)
// Should maybe have a parameter which is JSON.
2021-08-20 09:57:30 -07:00
const credentials = await this . getCredentials ( 'redis' ) ;
2019-06-23 03:35:23 -07:00
const redisOptions : redis.ClientOpts = {
host : credentials.host as string ,
port : credentials.port as number ,
2022-03-12 03:14:39 -08:00
db : credentials.database as number ,
2019-06-23 03:35:23 -07:00
} ;
if ( credentials . password ) {
redisOptions . password = credentials . password as string ;
}
const client = redis . createClient ( redisOptions ) ;
const operation = this . getNodeParameter ( 'operation' , 0 ) as string ;
client . on ( 'error' , ( err : Error ) = > {
2021-03-26 11:02:08 -07:00
client . quit ( ) ;
2019-06-23 03:35:23 -07:00
reject ( err ) ;
} ) ;
2022-11-08 06:28:21 -08:00
client . on ( 'ready' , async ( _err : Error | null ) = > {
2022-01-08 09:07:35 -08:00
client . select ( credentials . database as number ) ;
2021-04-30 13:38:51 -07:00
try {
if ( operation === 'info' ) {
const clientInfo = util . promisify ( client . info ) . bind ( client ) ;
const result = await clientInfo ( ) ;
2022-08-17 08:50:24 -07:00
resolve (
this . prepareOutputData ( [ { json : convertInfoToObject ( result as unknown as string ) } ] ) ,
) ;
2021-04-30 13:38:51 -07:00
client . quit ( ) ;
2022-08-17 08:50:24 -07:00
} else if (
[ 'delete' , 'get' , 'keys' , 'set' , 'incr' , 'publish' , 'push' , 'pop' ] . includes ( operation )
) {
2021-04-30 13:38:51 -07:00
const items = this . getInputData ( ) ;
const returnItems : INodeExecutionData [ ] = [ ] ;
let item : INodeExecutionData ;
for ( let itemIndex = 0 ; itemIndex < items . length ; itemIndex ++ ) {
item = { json : { } } ;
if ( operation === 'delete' ) {
const keyDelete = this . getNodeParameter ( 'key' , itemIndex ) as string ;
const clientDel = util . promisify ( client . del ) . bind ( client ) ;
// @ts-ignore
await clientDel ( keyDelete ) ;
returnItems . push ( items [ itemIndex ] ) ;
} else if ( operation === 'get' ) {
const propertyName = this . getNodeParameter ( 'propertyName' , itemIndex ) as string ;
const keyGet = this . getNodeParameter ( 'key' , itemIndex ) as string ;
const keyType = this . getNodeParameter ( 'keyType' , itemIndex ) as string ;
2022-08-17 08:50:24 -07:00
const value = ( await getValue ( client , keyGet , keyType ) ) || null ;
2021-04-30 13:38:51 -07:00
const options = this . getNodeParameter ( 'options' , itemIndex , { } ) as IDataObject ;
if ( options . dotNotation === false ) {
item . json [ propertyName ] = value ;
} else {
set ( item . json , propertyName , value ) ;
}
returnItems . push ( item ) ;
} else if ( operation === 'keys' ) {
const keyPattern = this . getNodeParameter ( 'keyPattern' , itemIndex ) as string ;
2022-07-09 23:12:18 -07:00
const getValues = this . getNodeParameter ( 'getValues' , itemIndex , true ) as boolean ;
2021-04-30 13:38:51 -07:00
const clientKeys = util . promisify ( client . keys ) . bind ( client ) ;
const keys = await clientKeys ( keyPattern ) ;
2022-07-09 23:12:18 -07:00
if ( ! getValues ) {
2022-08-17 08:50:24 -07:00
returnItems . push ( { json : { keys } } ) ;
2022-07-09 23:12:18 -07:00
continue ;
}
2021-04-30 13:38:51 -07:00
const promises : {
[ key : string ] : GenericValue ;
} = { } ;
for ( const keyName of keys ) {
promises [ keyName ] = await getValue ( client , keyName ) ;
}
for ( const keyName of keys ) {
item . json [ keyName ] = await promises [ keyName ] ;
}
returnItems . push ( item ) ;
} else if ( operation === 'set' ) {
const keySet = this . getNodeParameter ( 'key' , itemIndex ) as string ;
const value = this . getNodeParameter ( 'value' , itemIndex ) as string ;
const keyType = this . getNodeParameter ( 'keyType' , itemIndex ) as string ;
const expire = this . getNodeParameter ( 'expire' , itemIndex , false ) as boolean ;
const ttl = this . getNodeParameter ( 'ttl' , itemIndex , - 1 ) as number ;
await setValue ( client , keySet , value , expire , ttl , keyType ) ;
returnItems . push ( items [ itemIndex ] ) ;
2021-05-07 16:33:14 -07:00
} else if ( operation === 'incr' ) {
const keyIncr = this . getNodeParameter ( 'key' , itemIndex ) as string ;
const expire = this . getNodeParameter ( 'expire' , itemIndex , false ) as boolean ;
const ttl = this . getNodeParameter ( 'ttl' , itemIndex , - 1 ) as number ;
const clientIncr = util . promisify ( client . incr ) . bind ( client ) ;
// @ts-ignore
const incrementVal = await clientIncr ( keyIncr ) ;
if ( expire === true && ttl > 0 ) {
const clientExpire = util . promisify ( client . expire ) . bind ( client ) ;
await clientExpire ( keyIncr , ttl ) ;
}
2022-08-17 08:50:24 -07:00
returnItems . push ( { json : { [ keyIncr ] : incrementVal } } ) ;
} else if ( operation === 'publish' ) {
2022-03-12 03:14:39 -08:00
const channel = this . getNodeParameter ( 'channel' , itemIndex ) as string ;
const messageData = this . getNodeParameter ( 'messageData' , itemIndex ) as string ;
const clientPublish = util . promisify ( client . publish ) . bind ( client ) ;
await clientPublish ( channel , messageData ) ;
returnItems . push ( items [ itemIndex ] ) ;
2022-08-17 08:50:24 -07:00
} else if ( operation === 'push' ) {
2022-07-09 23:12:18 -07:00
const redisList = this . getNodeParameter ( 'list' , itemIndex ) as string ;
const messageData = this . getNodeParameter ( 'messageData' , itemIndex ) as string ;
const tail = this . getNodeParameter ( 'tail' , itemIndex , false ) as boolean ;
const action = tail ? client.RPUSH : client.LPUSH ;
const clientPush = util . promisify ( action ) . bind ( client ) ;
// @ts-ignore: typescript not understanding generic function signatures
await clientPush ( redisList , messageData ) ;
returnItems . push ( items [ itemIndex ] ) ;
2022-08-17 08:50:24 -07:00
} else if ( operation === 'pop' ) {
2022-07-09 23:12:18 -07:00
const redisList = this . getNodeParameter ( 'list' , itemIndex ) as string ;
const tail = this . getNodeParameter ( 'tail' , itemIndex , false ) as boolean ;
2022-08-17 08:50:24 -07:00
const propertyName = this . getNodeParameter (
'propertyName' ,
itemIndex ,
'propertyName' ,
) as string ;
2022-07-09 23:12:18 -07:00
const action = tail ? client.rpop : client.lpop ;
const clientPop = util . promisify ( action ) . bind ( client ) ;
const value = await clientPop ( redisList ) ;
let outputValue ;
try {
outputValue = JSON . parse ( value ) ;
} catch {
outputValue = value ;
}
const options = this . getNodeParameter ( 'options' , itemIndex , { } ) as IDataObject ;
if ( options . dotNotation === false ) {
item . json [ propertyName ] = outputValue ;
} else {
set ( item . json , propertyName , outputValue ) ;
}
returnItems . push ( item ) ;
2020-05-05 06:52:47 -07:00
}
2019-06-23 03:35:23 -07:00
}
2019-08-01 13:55:33 -07:00
2021-04-30 13:38:51 -07:00
client . quit ( ) ;
resolve ( this . prepareOutputData ( returnItems ) ) ;
}
} catch ( error ) {
reject ( error ) ;
2019-06-23 03:35:23 -07:00
}
} ) ;
} ) ;
}
}