function validateNodeProperty(node,definition,property,value) {
        var valid = true;
        // Check for $(env-var) and consider it valid
        if (/^\$\([a-zA-Z_][a-zA-Z0-9_]*\)$/.test(value)) {
            return true;
        }
        // Check for ${env-var} and consider it valid
        if (/^\$\{[a-zA-Z_][a-zA-Z0-9_]*\}$/.test(value)) {
            return true;
        }
        var label = null;
        if (("label" in definition[property]) &&
            ((typeof definition[property].label) == "string")) {
            label = definition[property].label;
        }
        if ("required" in definition[property] && definition[property].required) {
            valid = value !== "";
            if (!valid && label) {
                return RED._("validator.errors.missing-required-prop", {
                    prop: label
                });
            }
        }
        if (valid && "validate" in definition[property]) {
            if (definition[property].hasOwnProperty("required") &&
                definition[property].required === false) {
                if (value === "") {
                    return true;
                }
            }
            try {
                var opt = {};
                if (label) {
                    opt.label = label;
                }
                valid = definition[property].validate.call(node,value, opt);
                // If the validator takes two arguments, it is a 3.x validator that
                // can return a String to mean 'invalid' and provide a reason
                if ((definition[property].validate.length === 2) &&
                    ((typeof valid) === "string") || Array.isArray(valid)) {
                    return valid;
                } else {
                    // Otherwise, a 2.x returns a truth-like/false-like value that
                    // we should cooerce to a boolean.
                    valid = !!valid
                }
            } catch(err) {
                console.log("Validation error:",node.type,node.id,"property: "+property,"value:",value,err);
                return RED._("validator.errors.validation-error", {
                    prop: property,
                    node: node.type,
                    id: node.id,
                    error: err.message
                });
            }
        } else if (valid) {
            if (definition[property].hasOwnProperty("required") && definition[property].required === false) {
                if (value === "") {
                    return true;
                }
            }
            // If the validator is not provided in node property => Check if the input has a validator
            if ("category" in node._def) {
                const isConfig = node._def.category === "config";
                const prefix = isConfig ? "node-config-input" : "node-input";
                const input = $("#"+prefix+"-"+property);
                const isTypedInput = input.length > 0 && input.next(".red-ui-typedInput-container").length > 0;
                if (isTypedInput) {
                    valid = input.typedInput("validate", { returnErrorMessage: true });
                    if (typeof valid === "string") {
                        return label ? label + ": " + valid : valid;
                    }
                }
            }
        }
        if (valid && definition[property].type && RED.nodes.getType(definition[property].type) && !("validate" in definition[property])) {
            if (!value || value == "_ADD_") {
                valid = definition[property].hasOwnProperty("required") && !definition[property].required;
                if (!valid && label) {
                    return RED._("validator.errors.missing-required-prop", {
                        prop: label
                    });
                }
            } else {
                var configNode = RED.nodes.node(value);
                if (configNode) {
                    if ((configNode.valid == null) || configNode.valid) {
                        return true;
                    }
                    if (label) {
                        return RED._("validator.errors.invalid-config", {
                            prop: label
                        });
                    }
                }
                else {
                    if (label) {
                        return RED._("validator.errors.missing-config", {
                            prop: label
                        });
                    }
                }
                return false;
            }
        }
        return valid;
    }
Validate a individual node property
@param node - the node being validated
@param definition - the node property definitions (either def.defaults or def.creds)
@param property - the property name being validated
@param value - the property value being validated
@returns {boolean|string} whether the node proprty is valid. `true`: valid `false|String`: invalid