mirror of
https://github.com/node-red/node-red.git
synced 2025-03-01 10:36:34 +00:00
Merge branch 'master' into dev
This commit is contained in:
@@ -17,6 +17,7 @@
|
||||
var clone = require("clone");
|
||||
var log = require("../../log");
|
||||
var memory = require("./memory");
|
||||
var util = require("../../util");
|
||||
|
||||
var settings;
|
||||
|
||||
@@ -209,104 +210,131 @@ function createContext(id,seed) {
|
||||
insertSeedValues = function(keys,values) {
|
||||
if (!Array.isArray(keys)) {
|
||||
if (values[0] === undefined) {
|
||||
values[0] = seed[keys];
|
||||
values[0] = util.getObjectProperty(seed,keys);
|
||||
}
|
||||
} else {
|
||||
for (var i=0;i<keys.length;i++) {
|
||||
if (values[i] === undefined) {
|
||||
values[i] = seed[keys[i]];
|
||||
values[i] = util.getObjectProperty(seed,keys[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Object.defineProperties(obj, {
|
||||
get: {
|
||||
value: function(key, storage, callback) {
|
||||
var context;
|
||||
|
||||
obj.get = function(key, storage, callback) {
|
||||
var context;
|
||||
if (!storage && !callback) {
|
||||
context = stores["_"];
|
||||
} else {
|
||||
if (typeof storage === 'function') {
|
||||
callback = storage;
|
||||
storage = "_";
|
||||
}
|
||||
if (callback && typeof callback !== 'function'){
|
||||
throw new Error("Callback must be a function");
|
||||
}
|
||||
context = getContextStorage(storage);
|
||||
}
|
||||
if (callback) {
|
||||
if (!seed) {
|
||||
context.get(scope,key,callback);
|
||||
} else {
|
||||
context.get(scope,key,function() {
|
||||
if (arguments[0]) {
|
||||
callback(arguments[0]);
|
||||
return;
|
||||
if (!callback && typeof storage === 'function') {
|
||||
callback = storage;
|
||||
storage = undefined;
|
||||
}
|
||||
if (callback && typeof callback !== 'function'){
|
||||
throw new Error("Callback must be a function");
|
||||
}
|
||||
|
||||
if (!Array.isArray(key)) {
|
||||
var keyParts = util.parseContextStore(key);
|
||||
key = keyParts.key;
|
||||
if (!storage) {
|
||||
storage = keyParts.store || "_";
|
||||
}
|
||||
var results = Array.prototype.slice.call(arguments,[1]);
|
||||
insertSeedValues(key,results);
|
||||
// Put the err arg back
|
||||
results.unshift(undefined);
|
||||
callback.apply(null,results);
|
||||
});
|
||||
}
|
||||
} else {
|
||||
// No callback, attempt to do this synchronously
|
||||
var results = context.get(scope,key);
|
||||
if (seed) {
|
||||
if (Array.isArray(key)) {
|
||||
insertSeedValues(key,results);
|
||||
} else if (results === undefined){
|
||||
results = seed[key];
|
||||
} else {
|
||||
if (!storage) {
|
||||
storage = "_";
|
||||
}
|
||||
}
|
||||
context = getContextStorage(storage);
|
||||
|
||||
if (callback) {
|
||||
if (!seed) {
|
||||
context.get(scope,key,callback);
|
||||
} else {
|
||||
context.get(scope,key,function() {
|
||||
if (arguments[0]) {
|
||||
callback(arguments[0]);
|
||||
return;
|
||||
}
|
||||
var results = Array.prototype.slice.call(arguments,[1]);
|
||||
insertSeedValues(key,results);
|
||||
// Put the err arg back
|
||||
results.unshift(undefined);
|
||||
callback.apply(null,results);
|
||||
});
|
||||
}
|
||||
} else {
|
||||
// No callback, attempt to do this synchronously
|
||||
var results = context.get(scope,key);
|
||||
if (seed) {
|
||||
if (Array.isArray(key)) {
|
||||
insertSeedValues(key,results);
|
||||
} else if (results === undefined){
|
||||
results = util.getObjectProperty(seed,key);
|
||||
}
|
||||
}
|
||||
return results;
|
||||
}
|
||||
}
|
||||
},
|
||||
set: {
|
||||
value: function(key, value, storage, callback) {
|
||||
var context;
|
||||
|
||||
if (!callback && typeof storage === 'function') {
|
||||
callback = storage;
|
||||
storage = undefined;
|
||||
}
|
||||
if (callback && typeof callback !== 'function'){
|
||||
throw new Error("Callback must be a function");
|
||||
}
|
||||
|
||||
if (!Array.isArray(key)) {
|
||||
var keyParts = util.parseContextStore(key);
|
||||
key = keyParts.key;
|
||||
if (!storage) {
|
||||
storage = keyParts.store || "_";
|
||||
}
|
||||
} else {
|
||||
if (!storage) {
|
||||
storage = "_";
|
||||
}
|
||||
}
|
||||
context = getContextStorage(storage);
|
||||
|
||||
context.set(scope, key, value, callback);
|
||||
}
|
||||
},
|
||||
keys: {
|
||||
value: function(storage, callback) {
|
||||
var context;
|
||||
if (!storage && !callback) {
|
||||
context = stores["_"];
|
||||
} else {
|
||||
if (typeof storage === 'function') {
|
||||
callback = storage;
|
||||
storage = "_";
|
||||
}
|
||||
if (callback && typeof callback !== 'function') {
|
||||
throw new Error("Callback must be a function");
|
||||
}
|
||||
context = getContextStorage(storage);
|
||||
}
|
||||
if (seed) {
|
||||
if (callback) {
|
||||
context.keys(scope, function(err,keys) {
|
||||
callback(err,Array.from(new Set(seedKeys.concat(keys)).keys()));
|
||||
});
|
||||
} else {
|
||||
var keys = context.keys(scope);
|
||||
return Array.from(new Set(seedKeys.concat(keys)).keys())
|
||||
}
|
||||
} else {
|
||||
return context.keys(scope, callback);
|
||||
}
|
||||
}
|
||||
return results;
|
||||
}
|
||||
};
|
||||
obj.set = function(key, value, storage, callback) {
|
||||
var context;
|
||||
if (!storage && !callback) {
|
||||
context = stores["_"];
|
||||
} else {
|
||||
if (typeof storage === 'function') {
|
||||
callback = storage;
|
||||
storage = "_";
|
||||
}
|
||||
if (callback && typeof callback !== 'function') {
|
||||
throw new Error("Callback must be a function");
|
||||
}
|
||||
context = getContextStorage(storage);
|
||||
}
|
||||
context.set(scope, key, value, callback);
|
||||
};
|
||||
obj.keys = function(storage, callback) {
|
||||
var context;
|
||||
if (!storage && !callback) {
|
||||
context = stores["_"];
|
||||
} else {
|
||||
if (typeof storage === 'function') {
|
||||
callback = storage;
|
||||
storage = "_";
|
||||
}
|
||||
if (callback && typeof callback !== 'function') {
|
||||
throw new Error("Callback must be a function");
|
||||
}
|
||||
context = getContextStorage(storage);
|
||||
}
|
||||
if (seed) {
|
||||
if (callback) {
|
||||
context.keys(scope, function(err,keys) {
|
||||
callback(err,Array.from(new Set(seedKeys.concat(keys)).keys()));
|
||||
});
|
||||
} else {
|
||||
var keys = context.keys(scope);
|
||||
return Array.from(new Set(seedKeys.concat(keys)).keys())
|
||||
}
|
||||
} else {
|
||||
return context.keys(scope, callback);
|
||||
}
|
||||
};
|
||||
});
|
||||
return obj;
|
||||
}
|
||||
|
||||
@@ -320,9 +348,13 @@ function getContext(localId,flowId) {
|
||||
}
|
||||
var newContext = createContext(contextId);
|
||||
if (flowId) {
|
||||
newContext.flow = getContext(flowId);
|
||||
Object.defineProperty(newContext, 'flow', {
|
||||
value: getContext(flowId)
|
||||
});
|
||||
}
|
||||
newContext.global = contexts['global'];
|
||||
Object.defineProperty(newContext, 'global', {
|
||||
value: contexts['global']
|
||||
})
|
||||
contexts[contextId] = newContext;
|
||||
return newContext;
|
||||
}
|
||||
|
@@ -140,6 +140,7 @@ function stringify(value) {
|
||||
function LocalFileSystem(config){
|
||||
this.config = config;
|
||||
this.storageBaseDir = getBasePath(this.config);
|
||||
this.writePromise = Promise.resolve();
|
||||
if (config.hasOwnProperty('cache')?config.cache:true) {
|
||||
this.cache = MemoryStore({});
|
||||
}
|
||||
@@ -213,12 +214,13 @@ LocalFileSystem.prototype.open = function(){
|
||||
}
|
||||
|
||||
LocalFileSystem.prototype.close = function(){
|
||||
if (this.cache && this._flushPendingWrites) {
|
||||
var self = this;
|
||||
if (this.cache && this._pendingWriteTimeout) {
|
||||
clearTimeout(this._pendingWriteTimeout);
|
||||
delete this._pendingWriteTimeout;
|
||||
return this._flushPendingWrites();
|
||||
this.flushInterval = 0;
|
||||
}
|
||||
return Promise.resolve();
|
||||
return this.writePromise;
|
||||
}
|
||||
|
||||
LocalFileSystem.prototype.get = function(scope, key, callback) {
|
||||
@@ -230,14 +232,31 @@ LocalFileSystem.prototype.get = function(scope, key, callback) {
|
||||
}
|
||||
var storagePath = getStoragePath(this.storageBaseDir ,scope);
|
||||
loadFile(storagePath + ".json").then(function(data){
|
||||
var value;
|
||||
if(data){
|
||||
data = JSON.parse(data);
|
||||
if (!Array.isArray(key)) {
|
||||
callback(null, util.getObjectProperty(data,key));
|
||||
try {
|
||||
value = util.getObjectProperty(data,key);
|
||||
} catch(err) {
|
||||
if (err.code === "INVALID_EXPR") {
|
||||
throw err;
|
||||
}
|
||||
value = undefined;
|
||||
}
|
||||
callback(null, value);
|
||||
} else {
|
||||
var results = [undefined];
|
||||
for (var i=0;i<key.length;i++) {
|
||||
results.push(util.getObjectProperty(data,key[i]))
|
||||
try {
|
||||
value = util.getObjectProperty(data,key[i]);
|
||||
} catch(err) {
|
||||
if (err.code === "INVALID_EXPR") {
|
||||
throw err;
|
||||
}
|
||||
value = undefined;
|
||||
}
|
||||
results.push(value)
|
||||
}
|
||||
callback.apply(null,results);
|
||||
}
|
||||
@@ -260,15 +279,17 @@ LocalFileSystem.prototype.set = function(scope, key, value, callback) {
|
||||
return;
|
||||
} else {
|
||||
this._pendingWriteTimeout = setTimeout(function() {
|
||||
self._flushPendingWrites.call(self).catch(function(err) {
|
||||
log.error(log._("context.localfilesystem.error-write",{message:err.toString()}))
|
||||
self.writePromise = self.writePromise.then(function(){
|
||||
return self._flushPendingWrites.call(self).catch(function(err) {
|
||||
log.error(log._("context.localfilesystem.error-write",{message:err.toString()}));
|
||||
});
|
||||
});
|
||||
}, this.flushInterval);
|
||||
}
|
||||
} else if (callback && typeof callback !== 'function') {
|
||||
throw new Error("Callback must be a function");
|
||||
} else {
|
||||
loadFile(storagePath + ".json").then(function(data){
|
||||
self.writePromise = self.writePromise.then(function() { return loadFile(storagePath + ".json") }).then(function(data){
|
||||
var obj = data ? JSON.parse(data) : {}
|
||||
if (!Array.isArray(key)) {
|
||||
key = [key];
|
||||
|
@@ -32,7 +32,14 @@ Memory.prototype._getOne = function(scope, key) {
|
||||
var value;
|
||||
var error;
|
||||
if(this.data[scope]){
|
||||
value = util.getObjectProperty(this.data[scope], key);
|
||||
try {
|
||||
value = util.getObjectProperty(this.data[scope], key);
|
||||
} catch(err) {
|
||||
if (err.code === "INVALID_EXPR") {
|
||||
throw err;
|
||||
}
|
||||
value = undefined;
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
@@ -130,13 +130,19 @@ function compareObjects(obj1,obj2) {
|
||||
return true;
|
||||
}
|
||||
|
||||
function createError(code, message) {
|
||||
var e = new Error(message);
|
||||
e.code = code;
|
||||
return e;
|
||||
}
|
||||
|
||||
function normalisePropertyExpression(str) {
|
||||
// This must be kept in sync with validatePropertyExpression
|
||||
// in editor/js/ui/utils.js
|
||||
|
||||
var length = str.length;
|
||||
if (length === 0) {
|
||||
throw new Error("Invalid property expression: zero-length");
|
||||
throw createError("INVALID_EXPR","Invalid property expression: zero-length");
|
||||
}
|
||||
var parts = [];
|
||||
var start = 0;
|
||||
@@ -149,14 +155,14 @@ function normalisePropertyExpression(str) {
|
||||
if (!inString) {
|
||||
if (c === "'" || c === '"') {
|
||||
if (i != start) {
|
||||
throw new Error("Invalid property expression: unexpected "+c+" at position "+i);
|
||||
throw createError("INVALID_EXPR","Invalid property expression: unexpected "+c+" at position "+i);
|
||||
}
|
||||
inString = true;
|
||||
quoteChar = c;
|
||||
start = i+1;
|
||||
} else if (c === '.') {
|
||||
if (i===0) {
|
||||
throw new Error("Invalid property expression: unexpected . at position 0");
|
||||
throw createError("INVALID_EXPR","Invalid property expression: unexpected . at position 0");
|
||||
}
|
||||
if (start != i) {
|
||||
v = str.substring(start,i);
|
||||
@@ -167,57 +173,57 @@ function normalisePropertyExpression(str) {
|
||||
}
|
||||
}
|
||||
if (i===length-1) {
|
||||
throw new Error("Invalid property expression: unterminated expression");
|
||||
throw createError("INVALID_EXPR","Invalid property expression: unterminated expression");
|
||||
}
|
||||
// Next char is first char of an identifier: a-z 0-9 $ _
|
||||
if (!/[a-z0-9\$\_]/i.test(str[i+1])) {
|
||||
throw new Error("Invalid property expression: unexpected "+str[i+1]+" at position "+(i+1));
|
||||
throw createError("INVALID_EXPR","Invalid property expression: unexpected "+str[i+1]+" at position "+(i+1));
|
||||
}
|
||||
start = i+1;
|
||||
} else if (c === '[') {
|
||||
if (i === 0) {
|
||||
throw new Error("Invalid property expression: unexpected "+c+" at position "+i);
|
||||
throw createError("INVALID_EXPR","Invalid property expression: unexpected "+c+" at position "+i);
|
||||
}
|
||||
if (start != i) {
|
||||
parts.push(str.substring(start,i));
|
||||
}
|
||||
if (i===length-1) {
|
||||
throw new Error("Invalid property expression: unterminated expression");
|
||||
throw createError("INVALID_EXPR","Invalid property expression: unterminated expression");
|
||||
}
|
||||
// Next char is either a quote or a number
|
||||
if (!/["'\d]/.test(str[i+1])) {
|
||||
throw new Error("Invalid property expression: unexpected "+str[i+1]+" at position "+(i+1));
|
||||
throw createError("INVALID_EXPR","Invalid property expression: unexpected "+str[i+1]+" at position "+(i+1));
|
||||
}
|
||||
start = i+1;
|
||||
inBox = true;
|
||||
} else if (c === ']') {
|
||||
if (!inBox) {
|
||||
throw new Error("Invalid property expression: unexpected "+c+" at position "+i);
|
||||
throw createError("INVALID_EXPR","Invalid property expression: unexpected "+c+" at position "+i);
|
||||
}
|
||||
if (start != i) {
|
||||
v = str.substring(start,i);
|
||||
if (/^\d+$/.test(v)) {
|
||||
parts.push(parseInt(v));
|
||||
} else {
|
||||
throw new Error("Invalid property expression: unexpected array expression at position "+start);
|
||||
throw createError("INVALID_EXPR","Invalid property expression: unexpected array expression at position "+start);
|
||||
}
|
||||
}
|
||||
start = i+1;
|
||||
inBox = false;
|
||||
} else if (c === ' ') {
|
||||
throw new Error("Invalid property expression: unexpected ' ' at position "+i);
|
||||
throw createError("INVALID_EXPR","Invalid property expression: unexpected ' ' at position "+i);
|
||||
}
|
||||
} else {
|
||||
if (c === quoteChar) {
|
||||
if (i-start === 0) {
|
||||
throw new Error("Invalid property expression: zero-length string at position "+start);
|
||||
throw createError("INVALID_EXPR","Invalid property expression: zero-length string at position "+start);
|
||||
}
|
||||
parts.push(str.substring(start,i));
|
||||
// If inBox, next char must be a ]. Otherwise it may be [ or .
|
||||
if (inBox && !/\]/.test(str[i+1])) {
|
||||
throw new Error("Invalid property expression: unexpected array expression at position "+start);
|
||||
throw createError("INVALID_EXPR","Invalid property expression: unexpected array expression at position "+start);
|
||||
} else if (!inBox && i+1!==length && !/[\[\.]/.test(str[i+1])) {
|
||||
throw new Error("Invalid property expression: unexpected "+str[i+1]+" expression at position "+(i+1));
|
||||
throw createError("INVALID_EXPR","Invalid property expression: unexpected "+str[i+1]+" expression at position "+(i+1));
|
||||
}
|
||||
start = i+1;
|
||||
inString = false;
|
||||
@@ -226,7 +232,7 @@ function normalisePropertyExpression(str) {
|
||||
|
||||
}
|
||||
if (inBox || inString) {
|
||||
throw new Error("Invalid property expression: unterminated expression");
|
||||
throw new createError("INVALID_EXPR","Invalid property expression: unterminated expression");
|
||||
}
|
||||
if (start < length) {
|
||||
parts.push(str.substring(start));
|
||||
|
Reference in New Issue
Block a user