[feature request] 23-watch, enable configuration via context variables (global. / flow. / env.)

Currently the watch-list needs to be configured in the node editor. Would be nice to have the possibility to configure via a context variable to enable flow reuse without having to edit individual nodes.

Are the fields free text entry? If yes, you can use ${ENV_VAR}

https://nodered.org/docs/user-guide/environment-variables

Hi Steve, that's a good hint will check on this.
(although with my particular setup [node-red as a service within IOBroker] I'd need to access a global variable)
On the other hand would be just a few lines of code to add to use the typed input widget within the watch node editor giving all possibilities (str, env, flow, global):
(at least this works for me)

changes to 23-watch.html:
...

<script type="text/javascript">
    RED.nodes.registerType('watch',{
        category: 'storage',
        defaults: {
            name: {value:""},
            files: {value:"",required:true,
                    label:RED._("node-red:watch.label.files")},
                    // <!-- added to enable context setup -->
                    filesType: {value: "str"},
            recursive: {value:""}
        },
        color:"BurlyWood",
        inputs:0,
        outputs:1,
        icon: "watch.svg",
        label: function() {
            return this.name||this.files||this._("watch.watch");
        },
        labelStyle: function() {
            return this.name?"node_label_italic":"";
        },
        // <!-- added to enable context setup -->
        oneditprepare: function() {
            $("#node-input-files").typedInput({
                default: 'str',
                types: ['str','flow','global','env'],
                typeField: $("#node-input-filesType")
            });
        }
    });
</script>

...

changes to 23-watch.js:
...

function WatchNode(n) {
        RED.nodes.createNode(this,n);

        this.recursive = n.recursive || false;
        // added to enable context setup
        switch (n.filesType) {
            case "global":
                n.files = this.context().global.get(`${n.files}`);
                break;
            case "flow":
                n.files = this.context().flow.get(`${n.files}`);
                break;
            case "env":
                n.files = this.context().env.get(`${n.files}`);
            break;
        };
        this.files = (n.files || "").split(",");
        for (var f=0; f < this.files.length; f++) {
            this.files[f] = this.files[f].trim();
        }
        this.p = (this.files.length === 1) ? this.files[0] : JSON.stringify(this.files);
        const node = this;

        const watcher = watch(this.files, { recursive: this.recursive });

        watcher.on('change', function (event, fpath) {
            const file = path.basename(fpath)
            let stat;
            try {
                stat = fs.statSync(fpath);
            } catch(e) { }
            let type = "none";
            const msg = {
                payload:fpath,
                topic:node.p,
                file:file,
                filename:fpath,
                event: event
            };
            if (stat) {
                if (stat.isFile()) { type = "file"; msg.size = stat.size; }
                else if (stat.isBlockDevice()) { type = "blockdevice"; }
                else if (stat.isCharacterDevice()) { type = "characterdevice"; }
                else if (stat.isSocket()) { type = "socket"; }
                else if (stat.isFIFO()) { type = "fifo"; }
                else if (stat.isDirectory()) { type = "directory"; }
                else { type = "n/a"; }
            }
            msg.type = type;
            node.send(msg);
        });

        watcher.on('error', function (error) {
            const msg = { payload: "" };
            node.error(error,msg);
        });

        this.close = function() {
            watcher.close();
        }
    }

Using context variables would not be appropriate here as their value can change, but the watch node only picks up the value at the point in time the flow starts. We don't use context values for this type of static configuration anywhere else.

Adding support for the env type is certainly feasible, as env values are static. As Steve says, you can already make use of them via the syntax he shared, but adding a typed input to make it more explicit is doable.

OK, agreed. (In fact was expecting that kind of answer :wink: )
I'm using the same flow setup in multiple projects, reading a set of global variables from a config file at startup. So in my case those context variables will be static.

Maybe should contribute a 'dynamic' watch wich will close and restart the underlying fs.watch on configuration changes? With configuration check triggered by incoming msg or even new configuration coming in by msg?
I'm just not sure of consequences of configuration changes at a high msg rate. (which shouldn't occur if used in a reasonable way. But you never know)
Any thoughts?

If you did make it a typed input then you could add msg. as an option and if selected use that to add an input pin to the node so it could accept inputs. You are right to think about rates but hopefully you should not change what you are watching that rapidly... but you could check to see if the new value is same as old value (If for some reason they get sent in repeatedly) and ignore in that case... but... :person_shrugging:
Would be a good PR.

1 Like

Would you like to see a new node (e.g. node-red-contrib-dynwatch) or a enhanced core node?

A pr to node-red is my preference (everyone gains) but the choice is yours.

2 Likes

see commit ID
95480bc6feb64bac6e640f904da0c3c02e95480d
"configurable watch node"
not sure how to do a proper PR

Not sure where that code is
but this may help.
https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request

OK, see PR
configurable watch node #4986

Link to PR: configurable watch node by mschlgl · Pull Request #4986 · node-red/node-red · GitHub

@mschlgl please see the issues noted against the PR.

All resolved