From a279e3238b5c18389e2cb40f19e6b537aa8772a4 Mon Sep 17 00:00:00 2001 From: pemontto Date: Tue, 12 Apr 2022 08:02:13 +1000 Subject: [PATCH 1/6] =?UTF-8?q?=E2=9C=A8=20Add=20push=20and=20pop=20operat?= =?UTF-8?q?ions?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/nodes-base/nodes/Redis/Redis.node.ts | 186 +++++++++++++++++- 1 file changed, 184 insertions(+), 2 deletions(-) diff --git a/packages/nodes-base/nodes/Redis/Redis.node.ts b/packages/nodes-base/nodes/Redis/Redis.node.ts index 4978f90b96c36..03900b1856cad 100644 --- a/packages/nodes-base/nodes/Redis/Redis.node.ts +++ b/packages/nodes-base/nodes/Redis/Redis.node.ts @@ -73,6 +73,16 @@ export class Redis implements INodeType { value: 'publish', description: 'Publish message to redis channel.', }, + { + name: 'Push', + value: 'push', + description: 'Push data to a redis list', + }, + { + name: 'Pop', + value: 'pop', + description: 'Pop data from a redis list', + }, ], default: 'info', description: 'The operation to perform.', @@ -265,7 +275,20 @@ export class Redis implements INodeType { required: true, description: 'The key pattern for the keys to return.', }, - + { + displayName: 'Get Values', + name: 'getValues', + type: 'boolean', + displayOptions: { + show: { + operation: [ + 'keys', + ], + }, + }, + default: true, + description: 'Get the value of matching keys', + }, // ---------------------------------- // set // ---------------------------------- @@ -411,6 +434,117 @@ export class Redis implements INodeType { required: true, description: 'Data to publish.', }, + // ---------------------------------- + // push/pop + // ---------------------------------- + { + displayName: 'List', + name: 'list', + type: 'string', + displayOptions: { + show: { + operation: [ + 'push', + 'pop', + ], + }, + }, + default: '', + required: true, + description: 'Name of the list in Redis.', + }, + { + displayName: 'Data', + name: 'messageData', + type: 'string', + displayOptions: { + show: { + operation: [ + 'push', + ], + }, + }, + typeOptions: { + alwaysOpenEditWindow: true, + }, + default: '', + required: true, + description: 'Data to push', + }, + { + displayName: 'Tail', + name: 'tail', + type: 'boolean', + displayOptions: { + show: { + operation: [ + 'push', + 'pop', + ], + }, + }, + default: false, + description: 'Operate on data at the tail of the list', + }, + { + displayName: 'Overwrite', + name: 'overwrite', + type: 'boolean', + displayOptions: { + show: { + operation: [ + 'pop', + ], + }, + }, + default: false, + description: 'Overwrite item data with returned data', + }, + { + displayName: 'Name', + name: 'propertyName', + type: 'string', + displayOptions: { + show: { + operation: [ + 'pop', + ], + overwrite: [ + false, + ], + }, + }, + default: 'data', + required: false, + description: 'Optional name of the property to write received data to. Supports dot-notation. Example: "data.person[0].name"', + }, + { + displayName: 'Options', + name: 'options', + type: 'collection', + displayOptions: { + show: { + operation: [ + 'pop', + ], + overwrite: [ + false, + ], + }, + }, + placeholder: 'Add Option', + default: {}, + options: [ + { + displayName: 'Dot Notation', + name: 'dotNotation', + type: 'boolean', + default: true, + description: `

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} }.

If that is not intended this can be deactivated, it will then set { "a.b": value } instead.

+ `, + }, + ], + }, ], }; @@ -558,7 +692,7 @@ export class Redis implements INodeType { resolve(this.prepareOutputData([{ json: convertInfoToObject(result as unknown as string) }])); client.quit(); - } else if (['delete', 'get', 'keys', 'set', 'incr', 'publish'].includes(operation)) { + } else if (['delete', 'get', 'keys', 'set', 'incr', 'publish', 'push', 'pop'].includes(operation)) { const items = this.getInputData(); const returnItems: INodeExecutionData[] = []; @@ -591,10 +725,16 @@ export class Redis implements INodeType { returnItems.push(item); } else if (operation === 'keys') { const keyPattern = this.getNodeParameter('keyPattern', itemIndex) as string; + const getValues = this.getNodeParameter('getValues', itemIndex, true) as boolean; const clientKeys = util.promisify(client.keys).bind(client); const keys = await clientKeys(keyPattern); + if (!getValues) { + returnItems.push({json: {'keys': keys}}); + continue; + } + const promises: { [key: string]: GenericValue; } = {}; @@ -635,6 +775,48 @@ export class Redis implements INodeType { const clientPublish = util.promisify(client.publish).bind(client); await clientPublish(channel, messageData); returnItems.push(items[itemIndex]); + } else if (operation === 'push'){ + 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.rpushx : client.lpushx; + const clientPush = util.promisify(action).bind(client); + + await clientPush(redisList, messageData); + + returnItems.push(items[itemIndex]); + } else if (operation === 'pop'){ + const redisList = this.getNodeParameter('list', itemIndex) as string; + const tail = this.getNodeParameter('tail', itemIndex, false) as boolean; + const overwrite = this.getNodeParameter('overwrite', itemIndex, false) as boolean; + const propertyName = this.getNodeParameter('propertyName', itemIndex, 'data') as string; + + const action = tail ? client.rpop : client.lpop; + const clientPush = util.promisify(action).bind(client); + const value = await clientPush(redisList); + + let valueJSON; + try { + valueJSON = JSON.parse(value); + } catch { + valueJSON = undefined; + } + if (overwrite) { + if (valueJSON) { + item = {json: valueJSON}; + } else { + item = {json: {data: value}}; + } + } else { + const options = this.getNodeParameter('options', itemIndex, {}) as IDataObject; + if (options.dotNotation === false) { + item.json[propertyName] = valueJSON ? valueJSON : value; + } else { + set(item.json, propertyName, valueJSON ? valueJSON : value); + } + } + returnItems.push(item); } } From 2a5150b9ca8c461bb2ff6816a62203fc653f0b7c Mon Sep 17 00:00:00 2001 From: Michael Kret Date: Tue, 10 May 2022 17:04:37 +0300 Subject: [PATCH 2/6] :zap: linter fixes --- packages/nodes-base/nodes/Redis/Redis.node.ts | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/packages/nodes-base/nodes/Redis/Redis.node.ts b/packages/nodes-base/nodes/Redis/Redis.node.ts index 56172ca677310..6d5b94cfa5d44 100644 --- a/packages/nodes-base/nodes/Redis/Redis.node.ts +++ b/packages/nodes-base/nodes/Redis/Redis.node.ts @@ -450,7 +450,7 @@ export class Redis implements INodeType { }, default: '', required: true, - description: 'Name of the list in Redis.', + description: 'Name of the list in Redis', }, { displayName: 'Data', @@ -469,6 +469,7 @@ export class Redis implements INodeType { default: '', required: true, description: 'Data to push', + hint: 'Value or a string of comma separated values', }, { displayName: 'Tail', @@ -514,7 +515,6 @@ export class Redis implements INodeType { }, }, default: 'data', - required: false, description: 'Optional name of the property to write received data to. Supports dot-notation. Example: "data.person[0].name"', }, { @@ -539,8 +539,7 @@ export class Redis implements INodeType { name: 'dotNotation', type: 'boolean', default: true, - description: `

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} }.

If that is not intended this can be deactivated, it will then set { "a.b": value } instead.

- `, + description: '

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} }.

If that is not intended this can be deactivated, it will then set { "a.b": value } instead.

.', }, ], }, @@ -777,9 +776,7 @@ export class Redis implements INodeType { const action = tail ? client.rpushx : client.lpushx; const clientPush = util.promisify(action).bind(client); - - await clientPush(redisList, messageData); - + await clientPush(redisList, messageData.trim()); returnItems.push(items[itemIndex]); } else if (operation === 'pop'){ const redisList = this.getNodeParameter('list', itemIndex) as string; From 5172c865a738279ffe45f5067ac0536e7af312f8 Mon Sep 17 00:00:00 2001 From: Michael Kret Date: Tue, 10 May 2022 17:37:34 +0300 Subject: [PATCH 3/6] :zap: linter fixes --- packages/nodes-base/nodes/Redis/Redis.node.ts | 62 ++++++++++--------- 1 file changed, 32 insertions(+), 30 deletions(-) diff --git a/packages/nodes-base/nodes/Redis/Redis.node.ts b/packages/nodes-base/nodes/Redis/Redis.node.ts index 6d5b94cfa5d44..1d876810e99bc 100644 --- a/packages/nodes-base/nodes/Redis/Redis.node.ts +++ b/packages/nodes-base/nodes/Redis/Redis.node.ts @@ -37,6 +37,7 @@ export class Redis implements INodeType { displayName: 'Operation', name: 'operation', type: 'options', + noDataExpression: true, options: [ { name: 'Delete', @@ -48,25 +49,25 @@ export class Redis implements INodeType { value: 'get', description: 'Get the value of a key from Redis', }, - { - name: 'Info', - value: 'info', - description: 'Returns generic information about the Redis instance', - }, { name: 'Increment', value: 'incr', description: 'Atomically increments a key by 1. Creates the key if it does not exist.', }, + { + name: 'Info', + value: 'info', + description: 'Returns generic information about the Redis instance', + }, { name: 'Keys', value: 'keys', description: 'Returns all the keys matching a pattern', }, { - name: 'Set', - value: 'set', - description: 'Set the value of a key in redis', + name: 'Pop', + value: 'pop', + description: 'Pop data from a redis list', }, { name: 'Publish', @@ -79,13 +80,12 @@ export class Redis implements INodeType { description: 'Push data to a redis list', }, { - name: 'Pop', - value: 'pop', - description: 'Pop data from a redis list', + name: 'Set', + value: 'set', + description: 'Set the value of a key in redis', }, ], default: 'info', - description: 'The operation to perform.', }, // ---------------------------------- @@ -104,7 +104,7 @@ export class Redis implements INodeType { }, default: 'propertyName', required: true, - description: 'Name of the property to write received data to. Supports dot-notation. Example: "data.person[0].name"', + description: 'Name of the property to write received data to. Supports dot-notation. Example: "data.person[0].name".', }, { displayName: 'Key', @@ -158,11 +158,6 @@ export class Redis implements INodeType { value: 'hash', description: 'Data in key is of type "hash"', }, - { - name: 'String', - value: 'string', - description: 'Data in key is of type "string"', - }, { name: 'List', value: 'list', @@ -173,6 +168,11 @@ export class Redis implements INodeType { value: 'sets', description: 'Data in key is of type "sets"', }, + { + name: 'String', + value: 'string', + description: 'Data in key is of type "string"', + }, ], default: 'automatic', description: 'The type of the key to get', @@ -233,7 +233,7 @@ export class Redis implements INodeType { }, }, default: false, - description: 'Set a timeout on key?', + description: 'Whether to set a timeout on key?', }, { displayName: 'TTL', @@ -286,7 +286,7 @@ export class Redis implements INodeType { }, }, default: true, - description: 'Get the value of matching keys', + description: 'Whether to get the value of matching keys', }, // ---------------------------------- // set @@ -342,11 +342,6 @@ export class Redis implements INodeType { value: 'hash', description: 'Data in key is of type "hash"', }, - { - name: 'String', - value: 'string', - description: 'Data in key is of type "string"', - }, { name: 'List', value: 'list', @@ -357,6 +352,11 @@ export class Redis implements INodeType { value: 'sets', description: 'Data in key is of type "sets"', }, + { + name: 'String', + value: 'string', + description: 'Data in key is of type "string"', + }, ], default: 'automatic', description: 'The type of the key to set', @@ -374,7 +374,7 @@ export class Redis implements INodeType { }, }, default: false, - description: 'Set a timeout on key ?', + description: 'Whether to set a timeout on key?', }, { @@ -484,7 +484,7 @@ export class Redis implements INodeType { }, }, default: false, - description: 'Operate on data at the tail of the list', + description: 'Whether to operate on data at the tail of the list', }, { displayName: 'Overwrite', @@ -498,7 +498,7 @@ export class Redis implements INodeType { }, }, default: false, - description: 'Overwrite item data with returned data', + description: 'Whether to overwrite item data with returned data', }, { displayName: 'Name', @@ -515,7 +515,7 @@ export class Redis implements INodeType { }, }, default: 'data', - description: 'Optional name of the property to write received data to. Supports dot-notation. Example: "data.person[0].name"', + description: 'Optional name of the property to write received data to. Supports dot-notation. Example: "data.person[0].name".', }, { displayName: 'Options', @@ -776,7 +776,9 @@ export class Redis implements INodeType { const action = tail ? client.rpushx : client.lpushx; const clientPush = util.promisify(action).bind(client); - await clientPush(redisList, messageData.trim()); + + await clientPush(redisList, messageData); + throw Error; returnItems.push(items[itemIndex]); } else if (operation === 'pop'){ const redisList = this.getNodeParameter('list', itemIndex) as string; From ac4d37d3c39578bd941c22fa96979f6b387f3bb1 Mon Sep 17 00:00:00 2001 From: pemontto Date: Sun, 3 Jul 2022 23:03:35 +0100 Subject: [PATCH 4/6] =?UTF-8?q?=F0=9F=90=9B=20Fix=20errors=20and=20remove?= =?UTF-8?q?=20overwrite?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/nodes-base/nodes/Redis/Redis.node.ts | 51 ++++--------------- 1 file changed, 10 insertions(+), 41 deletions(-) diff --git a/packages/nodes-base/nodes/Redis/Redis.node.ts b/packages/nodes-base/nodes/Redis/Redis.node.ts index 1d876810e99bc..c1bbe2d21b3cd 100644 --- a/packages/nodes-base/nodes/Redis/Redis.node.ts +++ b/packages/nodes-base/nodes/Redis/Redis.node.ts @@ -484,21 +484,7 @@ export class Redis implements INodeType { }, }, default: false, - description: 'Whether to operate on data at the tail of the list', - }, - { - displayName: 'Overwrite', - name: 'overwrite', - type: 'boolean', - displayOptions: { - show: { - operation: [ - 'pop', - ], - }, - }, - default: false, - description: 'Whether to overwrite item data with returned data', + description: 'Whether to push or pop data from the end of the list', }, { displayName: 'Name', @@ -509,9 +495,6 @@ export class Redis implements INodeType { operation: [ 'pop', ], - overwrite: [ - false, - ], }, }, default: 'data', @@ -526,9 +509,6 @@ export class Redis implements INodeType { operation: [ 'pop', ], - overwrite: [ - false, - ], }, }, placeholder: 'Add Option', @@ -773,42 +753,31 @@ export class Redis implements INodeType { 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.rpushx : client.lpushx; + 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); - throw Error; returnItems.push(items[itemIndex]); } else if (operation === 'pop'){ const redisList = this.getNodeParameter('list', itemIndex) as string; const tail = this.getNodeParameter('tail', itemIndex, false) as boolean; - const overwrite = this.getNodeParameter('overwrite', itemIndex, false) as boolean; const propertyName = this.getNodeParameter('propertyName', itemIndex, 'data') as string; const action = tail ? client.rpop : client.lpop; const clientPush = util.promisify(action).bind(client); const value = await clientPush(redisList); - let valueJSON; + let outputValue; try { - valueJSON = JSON.parse(value); + outputValue = JSON.parse(value); } catch { - valueJSON = undefined; + outputValue = value; } - if (overwrite) { - if (valueJSON) { - item = {json: valueJSON}; - } else { - item = {json: {data: value}}; - } + const options = this.getNodeParameter('options', itemIndex, {}) as IDataObject; + if (options.dotNotation === false) { + item.json[propertyName] = outputValue; } else { - const options = this.getNodeParameter('options', itemIndex, {}) as IDataObject; - if (options.dotNotation === false) { - item.json[propertyName] = valueJSON ? valueJSON : value; - } else { - set(item.json, propertyName, valueJSON ? valueJSON : value); - } + set(item.json, propertyName, outputValue); } returnItems.push(item); } From 567e20eec0d2a95b9a0828bd5e00a70060d8020e Mon Sep 17 00:00:00 2001 From: pemontto Date: Tue, 5 Jul 2022 13:32:30 +0100 Subject: [PATCH 5/6] =?UTF-8?q?=F0=9F=90=9B=20Remove=20errant=20hint?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/nodes-base/nodes/Redis/Redis.node.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/nodes-base/nodes/Redis/Redis.node.ts b/packages/nodes-base/nodes/Redis/Redis.node.ts index d43d772662b2d..792bf4a1a7cb1 100644 --- a/packages/nodes-base/nodes/Redis/Redis.node.ts +++ b/packages/nodes-base/nodes/Redis/Redis.node.ts @@ -470,7 +470,6 @@ export class Redis implements INodeType { default: '', required: true, description: 'Data to push', - hint: 'Value or a string of comma separated values', }, { displayName: 'Tail', From 02489fb82bd48f3984d3398abd2ff4c0b407e152 Mon Sep 17 00:00:00 2001 From: ricardo Date: Tue, 5 Jul 2022 09:03:23 -0400 Subject: [PATCH 6/6] :zap: Small change --- packages/nodes-base/nodes/Redis/Redis.node.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/nodes-base/nodes/Redis/Redis.node.ts b/packages/nodes-base/nodes/Redis/Redis.node.ts index 792bf4a1a7cb1..5c3f474cf3c33 100644 --- a/packages/nodes-base/nodes/Redis/Redis.node.ts +++ b/packages/nodes-base/nodes/Redis/Redis.node.ts @@ -497,7 +497,7 @@ export class Redis implements INodeType { ], }, }, - default: 'data', + default: 'propertyName', description: 'Optional name of the property to write received data to. Supports dot-notation. Example: "data.person[0].name".', }, { @@ -762,11 +762,11 @@ export class Redis implements INodeType { } else if (operation === 'pop'){ const redisList = this.getNodeParameter('list', itemIndex) as string; const tail = this.getNodeParameter('tail', itemIndex, false) as boolean; - const propertyName = this.getNodeParameter('propertyName', itemIndex, 'data') as string; + const propertyName = this.getNodeParameter('propertyName', itemIndex, 'propertyName') as string; const action = tail ? client.rpop : client.lpop; - const clientPush = util.promisify(action).bind(client); - const value = await clientPush(redisList); + const clientPop = util.promisify(action).bind(client); + const value = await clientPop(redisList); let outputValue; try {