Compare commits

..

25 Commits

Author SHA1 Message Date
Dave Conway-Jones
638d0d2f3f let icons be settable by loading from server endpoint 2023-10-23 19:09:39 +01:00
Nick O'Leary
eb940d6d57 Merge pull request #4367 from hlovdal/timer_testing_fix
Timer testing fix
2023-09-25 18:19:30 +01:00
Håkon Løvdal
9091935d77 Update variable names 2023-09-25 18:53:11 +02:00
Håkon Løvdal
34e8d2b051 Add workaround for timers triggering too early in test 2023-09-24 18:16:59 +02:00
Håkon Løvdal
0c2ab13c48 Print all delta values in case of error, not just the last value
Which might not even be the one triggering the error condition.
2023-09-24 18:16:59 +02:00
Håkon Løvdal
9489953a8f Introduce timeout constant 2023-09-24 18:16:59 +02:00
Nick O'Leary
cef3a01042 Merge pull request #4322 from node-red/prep4
Bump to 4.0.0-dev
2023-09-06 15:04:41 +01:00
Nick O'Leary
0c042abcab Bump to 4.0.0-dev 2023-09-06 14:45:45 +01:00
Nick O'Leary
a48c57dd17 Merge pull request #4321 from node-red/rel-310
Bump version and changelog for 3.1.0 release
2023-09-06 13:57:44 +01:00
Nick O'Leary
77b235655c Bump version and changelog 2023-09-05 21:29:20 +01:00
Nick O'Leary
8dc0261993 Merge pull request #4319 from Rotzbua/fix_duplicate
Fix duplicate declaration
2023-09-05 20:41:38 +01:00
Rotzbua
65d2ad68d3 Fix duplicate declaration 2023-09-05 19:02:39 +02:00
Nick O'Leary
52fde088e9 Merge pull request #4318 from node-red/4315-small-catalogs-fix
Default filter to All Catalogues and show nodes for small lists
2023-09-05 17:59:57 +01:00
Nick O'Leary
ab6d537c3e Default filter to All Catalogues and show nodes for small lists 2023-09-05 17:49:50 +01:00
Nick O'Leary
3a6078a56a Merge pull request #4317 from node-red/update-deps-31
Dependency updates
2023-09-05 17:21:06 +01:00
Nick O'Leary
b0c3fefcab Dependency updates 2023-09-05 17:16:05 +01:00
Nick O'Leary
2bc739194e Merge pull request #4316 from node-red/4221-handle-concurrent-write-file
Ensure storage/util.writeFile handles concurrent write attempts
2023-09-05 15:57:27 +01:00
Nick O'Leary
afb06e8c9a Update packages/node_modules/@node-red/runtime/lib/storage/localfilesystem/util.js 2023-09-05 15:11:47 +01:00
Nick O'Leary
2c1274ff76 Ensure storage/util.writeFile handles concurrent write attempts 2023-09-05 15:09:11 +01:00
Nick O'Leary
e18721a03e Merge pull request #4313 from Rotzbua/fix_https
Migrate http -> https for nodered.org
2023-09-05 14:20:32 +01:00
Rotzbua
aea32cc279 Migrate http -> https for nodered.org 2023-09-05 14:55:56 +02:00
Nick O'Leary
ce0feb2f42 Merge pull request #4310 from node-red/4206-ctrl-click-behaviour
Better distinguish between ctrl and meta keys on mac
2023-09-05 13:48:17 +01:00
Nick O'Leary
1f98d19f77 Merge pull request #4309 from node-red/pr_4265
Adding function timeout to settings file (#4265)
2023-09-05 11:44:41 +01:00
Nick O'Leary
9a934c941f Tidy up functionTimeout setting 2023-09-05 10:34:18 +01:00
Kilian Hertel
f7b64b101e adding function timeout to settings file
adding function timeout to settings file
2023-08-04 14:20:49 +02:00
32 changed files with 203 additions and 90 deletions

View File

@@ -1,4 +1,38 @@
#### 3.1.0-beta.4: Beta Release
#### 3.1.0: Milestone Release
Editor
- Default filter to All Catalogues and show nodes for small lists (#4318) @knolleary
- Better distinguish between ctrl and meta keys on mac (#4310) @knolleary
- Ensure junction appears when filtering quick-add list (#4297) @knolleary
- Update message catalogs for JSONata Expression editor (#4287) @kazuhitoyokoi
- Add tooltip to relevance sort button in user settings UI (#4288) @kazuhitoyokoi
- Capture workspace dirty state when quick-adding junction (#4283) @knolleary
- Add docs for $clone function (#4284) @knolleary
Runtime
- Dependency updates (#4317) @knolleary
- Ensure storage/util.writeFile handles concurrent write attempts (#4316) @knolleary
- Migrate http -> https for nodered.org (#4313) @Rotzbua
- Add Node 20 to GH Action test matrix (#4305) @Rotzbua
- Handle group-scoped nodes inside subflow (#4301) @knolleary
- Handle non-url-safe chars in context api (#4298) @knolleary
- Fix git pull operation in project feature (#4290) @kazuhitoyokoi
- Change linefeed codes in Korean message catalogs (#4286) @kazuhitoyokoi
- Fix file permissions of message catalogs (#4285) @kazuhitoyokoi
- Update tour (#4278) @knolleary
Nodes
- File: Fix handling in file nodes when number is specified as file name (#4267) @kazuhitoyokoi
- Function: Adding function timeout to settings file (#4265) (#4309) @knolleary
- Function: Fix function setup tab layout (#4299) @knolleary
- HTTP Request: Handle 204 in httprequest JSON (#4262) @sammachin
- JSON: Fix test cases of JSON node (#4275) @kazuhitoyokoi
- MQTT: Remove unnecessary check for clientid if autoUnsub set (#4302) @knolleary
##### 3.1.0-beta.4: Beta Release
Editor
@@ -28,7 +62,7 @@
- Fix delay node flush issue (#4203) @dceejay
- Update status and catch node labels in group mode (#4207) @Steve-Mcl
#### 3.1.0-beta.3: Beta Release
##### 3.1.0-beta.3: Beta Release
Editor
@@ -63,7 +97,7 @@ Nodes
- MQTT: Option to disable MQTT topic unsubscribe on disconnect (#4078) @flying7eleven
#### 3.1.0-beta.2: Beta Release
##### 3.1.0-beta.2: Beta Release
Editor
@@ -113,7 +147,7 @@ Nodes
- File Out: Fix extra newline append for multipart file write (#3915) @dceejay
- Add validators for complete and link call nodes (#4056) @kazuhitoyokoi
#### 3.1.0-beta.1: Beta Release
##### 3.1.0-beta.1: Beta Release
Editor

View File

@@ -1,16 +1,16 @@
# Node-RED
http://nodered.org
https://nodered.org
[![Build Status](https://github.com/node-red/node-red/actions/workflows/tests.yml/badge.svg?branch=master)](https://github.com/node-red/node-red/actions?query=branch%3Amaster)
Low-code programming for event-driven applications.
![Node-RED: Low-code programming for event-driven applications](http://nodered.org/images/node-red-screenshot.png)
![Node-RED: Low-code programming for event-driven applications](https://nodered.org/images/node-red-screenshot.png)
## Quick Start
Check out http://nodered.org/docs/getting-started/ for full instructions on getting
Check out https://nodered.org/docs/getting-started/ for full instructions on getting
started.
1. `sudo npm install -g --unsafe-perm node-red`
@@ -19,7 +19,7 @@ started.
## Getting Help
More documentation can be found [here](http://nodered.org/docs).
More documentation can be found [here](https://nodered.org/docs).
For further help, or general discussion, please use the [Node-RED Forum](https://discourse.nodered.org) or [slack team](https://nodered.org/slack).

View File

@@ -1,8 +1,8 @@
{
"name": "node-red",
"version": "3.1.0-beta.4",
"version": "4.0.0-dev",
"description": "Low-code programming for event-driven applications",
"homepage": "http://nodered.org",
"homepage": "https://nodered.org",
"license": "Apache-2.0",
"repository": {
"type": "git",
@@ -64,8 +64,8 @@
"mqtt": "4.3.7",
"multer": "1.4.5-lts.1",
"mustache": "4.2.0",
"node-red-admin": "^3.0.0",
"node-watch": "0.7.3",
"node-red-admin": "^3.1.0",
"node-watch": "0.7.4",
"nopt": "5.0.0",
"oauth2orize": "1.11.1",
"on-headers": "1.0.2",
@@ -73,16 +73,16 @@
"passport-http-bearer": "1.0.1",
"passport-oauth2-client-password": "0.1.2",
"raw-body": "2.5.2",
"semver": "7.5.0",
"semver": "7.5.4",
"tar": "6.1.13",
"tough-cookie": "4.1.2",
"tough-cookie": "4.1.3",
"uglify-js": "3.17.4",
"uuid": "9.0.0",
"ws": "7.5.6",
"xml2js": "0.6.0"
"xml2js": "0.6.2"
},
"optionalDependencies": {
"bcrypt": "5.1.0"
"bcrypt": "5.1.1"
},
"devDependencies": {
"dompurify": "2.4.1",

View File

@@ -1,6 +1,6 @@
{
"name": "@node-red/editor-api",
"version": "3.1.0-beta.4",
"version": "4.0.0-dev",
"license": "Apache-2.0",
"main": "./lib/index.js",
"repository": {
@@ -16,8 +16,8 @@
}
],
"dependencies": {
"@node-red/util": "3.1.0-beta.4",
"@node-red/editor-client": "3.1.0-beta.4",
"@node-red/util": "4.0.0-dev",
"@node-red/editor-client": "4.0.0-dev",
"bcryptjs": "2.4.3",
"body-parser": "1.20.2",
"clone": "2.1.2",

View File

@@ -1,6 +1,6 @@
{
"name": "@node-red/editor-client",
"version": "3.1.0-beta.4",
"version": "4.0.0-dev",
"license": "Apache-2.0",
"repository": {
"type": "git",

View File

@@ -731,7 +731,7 @@ var RED = (function() {
}
menuOptions.push({id:"menu-item-help",
label: RED.settings.theme("menu.menu-item-help.label",RED._("menu.label.help")),
href: RED.settings.theme("menu.menu-item-help.url","http://nodered.org/docs")
href: RED.settings.theme("menu.menu-item-help.url","https://nodered.org/docs")
});
menuOptions.push({id:"menu-item-node-red-version", label:"v"+RED.settings.version, onselect: "core:show-about" });

View File

@@ -494,6 +494,7 @@ RED.palette.editor = (function() {
// if there is only 1 catalog, hide the select
if (catalogEntries.length > 1) {
catalogSelection.prepend(`<option value="all">${RED._('palette.editor.allCatalogs')}</option>`)
catalogSelection.val('all')
catalogSelection.removeAttr('disabled') // permit the user to select a catalog
}
// refresh the searchInput counter and trigger a change
@@ -523,7 +524,7 @@ RED.palette.editor = (function() {
function refreshFilteredItems() {
packageList.editableList('empty');
var currentFilter = searchInput.searchBox('value').trim();
if (currentFilter === ""){
if (currentFilter === "" && loadedList.length > 20){
packageList.editableList('addItem',{count:loadedList.length})
return;
}
@@ -893,7 +894,7 @@ RED.palette.editor = (function() {
delay: 300,
change: function() {
var searchTerm = $(this).val().trim().toLowerCase();
if (searchTerm.length > 0) {
if (searchTerm.length > 0 || loadedList.length < 20) {
filteredList = loadedList.filter(function(m) {
return (m.index.indexOf(searchTerm) > -1);
}).map(function(f) { return {info:f}});

View File

@@ -101,7 +101,7 @@ RED.utils = (function() {
renderer.code = function (code, lang) {
if(lang === "mermaid") {
// mermaid diagram rendering
// mermaid diagram rendering
if (mermaidIsEnabled === undefined) {
if (RED.settings.markdownEditor &&
RED.settings.markdownEditor.mermaid) {
@@ -1118,6 +1118,22 @@ RED.utils = (function() {
if (def.category === 'subflows') {
return RED.settings.apiRootUrl+"icons/node-red/subflow.svg";
}
if (node?.type) {
// this regex might be too restrictive/specific but got to start somewhere
const re = new RegExp("^\/"+node.type+"\/icon\/.*\.svg$","i");
if (typeof def.icon === "function") {
try {
const di = def.icon.call(node);
if (re.test(di)) { return RED.settings.authTokensSuffix.replace(/-/,'/') + di; }
}
catch(e) { console.log("Bad Icon",e) }
}
else {
if (re.test(def.icon)) { return RED.settings.authTokensSuffix.replace(/-/,'/') + def.icon; }
}
}
return RED.settings.apiRootUrl+"icons/node-red/arrow-in.svg";
}

View File

@@ -366,7 +366,7 @@
name: {value:"_DEFAULT_"},
func: {value:"\nreturn msg;"},
outputs: {value:1},
timeout:{value:0},
timeout:{value:RED.settings.functionTimeout || 0},
noerr: {value:0,required:true,
validate: function(v, opt) {
if (!v) {

View File

@@ -521,7 +521,8 @@ module.exports = function(RED) {
RED.nodes.registerType("function",FunctionNode, {
dynamicModuleList: "libs",
settings: {
functionExternalModules: { value: true, exportable: true }
functionExternalModules: { value: true, exportable: true },
functionTimeout: { value:0, exportable: true }
}
});
RED.library.register("functions");

View File

@@ -24,7 +24,6 @@ module.exports = function(RED) {
"text/css":"string",
"text/html":"string",
"text/plain":"string",
"text/html":"string",
"application/json":"json",
"application/octet-stream":"buffer",
"application/pdf":"buffer",

View File

@@ -25,7 +25,7 @@
<p>Wenn ein promise-Objekt aus dem Start-Code zurückgegeben wird,
beginnt danach die reguläre Verarbeitung der Eingangsnachrichten.</p>
<h3>Details</h3>
<p>Siehe <a target="_blank" href="http://nodered.org/docs/writing-functions.html">Onlinedokumentation</a>
<p>Siehe <a target="_blank" href="https://nodered.org/docs/writing-functions.html">Onlinedokumentation</a>
für weitere Informationen zum Schreiben von Funktionen.</p>
<h4><b>Nachrichten senden</b></h4>
<p>Die Funktion kann die Nachrichten zurückgeben, die sie an die nächsten Nodes im Flow weitergeben möchte,

View File

@@ -26,7 +26,7 @@
<p>If the On Start code returns a Promise object, the node will not start handling messages
until the promise is resolved.</p>
<h3>Details</h3>
<p>See the <a target="_blank" href="http://nodered.org/docs/writing-functions.html">online documentation</a>
<p>See the <a target="_blank" href="https://nodered.org/docs/writing-functions.html">online documentation</a>
for more information on writing functions.</p>
<h4>Sending messages</h4>
<p>The function can either return the messages it wants to pass on to the next nodes

View File

@@ -26,7 +26,7 @@
<p>Si le code 'Au démarrage' renvoie un objet Promise (promesse), le noeud ne commencera pas à gérer les messages
jusqu'à ce que la promesse soit résolue.</p>
<h3>Détails</h3>
<p>Voir la <a target="_blank" href="http://nodered.org/docs/writing-functions.html">documentation en ligne</a>
<p>Voir la <a target="_blank" href="https://nodered.org/docs/writing-functions.html">documentation en ligne</a>
pour plus d'informations sur les fonctions d'écriture.</p>
<h4>Envoi de messages</h4>
<p>La fonction peut envoyer les messages qu'elle souhaite transmettre aux noeuds suivants

View File

@@ -22,7 +22,7 @@
<p><b>初期化処理</b><b></b></p>
<p>初期化処理タブの返却値としてPromiseオブジェクトを返却すると入力メッセージの処理を開始する前にその完了を待ちます</p>
<h3>詳細</h3>
<p>コードの書き方の詳細については<a target="_blank" href="http://nodered.org/docs/writing-functions.html">オンラインドキュメント</a></p>
<p>コードの書き方の詳細については<a target="_blank" href="https://nodered.org/docs/writing-functions.html">オンラインドキュメント</a></p>
<h4>メッセージの送信</h4>
<p>フロー内の次ノードにメッセージを渡すためにはメッセージを返却するか<code>node.send(messages)</code></p>
<p>返却/sendの対象は次のとおりです:</p>

View File

@@ -20,7 +20,7 @@
<p><code>msg</code><code>msg.payload</code> .</p>
<p>보통 코드는 메시지 오브젝트(혹은 여러 메시지 객체) 반환합니다.후속 플로우의 실행을 정지하고 싶은 경우에는, 오브젝트를 반환하지 않아도 상관없습니다.</p>
<h3>상세</h3>
<p>코드 쓰는 방식에 대한 자세한 내용은, <a target="_blank" href="http://nodered.org/docs/writing-functions.html">공식 홈페이지</a> .</p>
<p>코드 쓰는 방식에 대한 자세한 내용은, <a target="_blank" href="https://nodered.org/docs/writing-functions.html">공식 홈페이지</a> .</p>
<h4>메세지 송신</h4>
<p>플로우 내의 다음 노드에 메세지를 전달하기 위해서는, 메세지를 반환하거나, <code>node.send(messages)</code> .</p>
<p>반환/send 대상은 다음과 같습니다:</p>

View File

@@ -26,7 +26,7 @@
<p>Se o código <b>On Start</b> retornar um objeto do tipo promessa, o nó não começará a tratar as mensagens
até que a promessa seja resolvida.</p>
<h3>Detalhes</h3>
<p>Consulte a <a target="_blank" href="http://nodered.org/docs/writing-functions.html">documentação online</a>
<p>Consulte a <a target="_blank" href="https://nodered.org/docs/writing-functions.html">documentação online</a>
para obter maiores informações sobre funções de escrita.</p>
<h4>Enviando mensagens</h4>
<p>A função pode retornar as mensagens que deseja passar para os próximos nós

View File

@@ -36,7 +36,7 @@
<h3>Подробности</h3>
<p>
Смотрите <a target="_blank" href="http://nodered.org/docs/writing-functions.html">онлайн-документацию</a> для получения дополнительной информации по написанию функций.
Смотрите <a target="_blank" href="https://nodered.org/docs/writing-functions.html">онлайн-документацию</a> для получения дополнительной информации по написанию функций.
</p>
<h4>Отправка сообщений</h4>

View File

@@ -20,7 +20,7 @@
<p>通常<code>msg</code><code>msg.payload</code></p>
<p>该函数一般会返回一个消息对象或多个消息对象但也可以为了停止流而什么都不返回</p>
<h3>详细</h3>
<p>请参见<a target="_blank" href="http://nodered.org/docs/writing-functions.html">在线文档</a></p>
<p>请参见<a target="_blank" href="https://nodered.org/docs/writing-functions.html">在线文档</a></p>
<h4>传送消息</h4>
<p>要将消息传递到流中的下一个节点请返回消息或调用<code>node.send(messages)</code></p>
<p>它将返回/send:</p>

View File

@@ -20,7 +20,7 @@
<p>通常<code>msg</code><code>msg.payload</code></p>
<p>該函數一般會返回一個消息對象或多個消息對象但也可以爲了停止流程而什麽都不返回</p>
<h3>詳細</h3>
<p>請參見<a target="_blank" href="http://nodered.org/docs/writing-functions.html">在線文檔</a></p>
<p>請參見<a target="_blank" href="https://nodered.org/docs/writing-functions.html">在線文檔</a></p>
<h4>傳送消息</h4>
<p>要將消息傳遞到流程中的下一個節點請返回消息或調用<code>node.send(messages)</code></p>
<p>它將返回/send:</p>

View File

@@ -1,6 +1,6 @@
{
"name": "@node-red/nodes",
"version": "3.1.0-beta.4",
"version": "4.0.0-dev",
"license": "Apache-2.0",
"repository": {
"type": "git",
@@ -38,13 +38,13 @@
"mqtt": "4.3.7",
"multer": "1.4.5-lts.1",
"mustache": "4.2.0",
"node-watch": "0.7.3",
"node-watch": "0.7.4",
"on-headers": "1.0.2",
"raw-body": "2.5.2",
"tough-cookie": "4.1.2",
"tough-cookie": "4.1.3",
"uuid": "9.0.0",
"ws": "7.5.6",
"xml2js": "0.6.0",
"xml2js": "0.6.2",
"iconv-lite": "0.6.3"
}
}

View File

@@ -1,6 +1,6 @@
{
"name": "@node-red/registry",
"version": "3.1.0-beta.4",
"version": "4.0.0-dev",
"license": "Apache-2.0",
"main": "./lib/index.js",
"repository": {
@@ -16,10 +16,10 @@
}
],
"dependencies": {
"@node-red/util": "3.1.0-beta.4",
"@node-red/util": "4.0.0-dev",
"clone": "2.1.2",
"fs-extra": "11.1.1",
"semver": "7.5.0",
"semver": "7.5.4",
"tar": "6.1.13",
"uglify-js": "3.17.4"
}

View File

@@ -71,30 +71,30 @@ function readFile(path,backupPath,emptyResponse,type) {
});
}
const writeFileLocks = {}
module.exports = {
/**
* Write content to a file using UTF8 encoding.
* This forces a fsync before completing to ensure
* the write hits disk.
*/
writeFile: function(path,content,backupPath) {
var backupPromise;
if (backupPath && fs.existsSync(path)) {
backupPromise = fs.copy(path,backupPath);
} else {
backupPromise = Promise.resolve();
writeFile: async function(path,content,backupPath) {
if (!writeFileLocks[path]) {
writeFileLocks[path] = Promise.resolve()
}
const dirname = fspath.dirname(path);
const tempFile = `${path}.$$$`;
return backupPromise.then(() => {
if (backupPath) {
const result = writeFileLocks[path].then(async () => {
var backupPromise;
if (backupPath && fs.existsSync(path)) {
await fs.copy(path,backupPath);
log.trace(`utils.writeFile - copied ${path} TO ${backupPath}`)
}
return fs.ensureDir(dirname)
}).then(() => {
return new Promise(function(resolve,reject) {
const dirname = fspath.dirname(path);
const tempFile = `${path}.$$$`;
await fs.ensureDir(dirname)
await new Promise(function(resolve,reject) {
var stream = fs.createWriteStream(tempFile);
stream.on('open',function(fd) {
stream.write(content,'utf8',function() {
@@ -110,10 +110,11 @@ module.exports = {
log.warn(log._("storage.localfilesystem.fsync-fail",{path: tempFile, message: err.toString()}));
reject(err);
});
});
}).then(() => {
})
log.trace(`utils.writeFile - written content to ${tempFile}`)
return new Promise(function(resolve,reject) {
await new Promise(function(resolve,reject) {
fs.rename(tempFile,path,err => {
if (err) {
log.warn(log._("storage.localfilesystem.fsync-fail",{path: path, message: err.toString()}));
@@ -122,8 +123,10 @@ module.exports = {
log.trace(`utils.writeFile - renamed ${tempFile} to ${path}`)
resolve();
})
});
});
})
})
writeFileLocks[path] = result.catch(() => {})
return result
},
readFile: readFile,

View File

@@ -1,6 +1,6 @@
{
"name": "@node-red/runtime",
"version": "3.1.0-beta.4",
"version": "4.0.0-dev",
"license": "Apache-2.0",
"main": "./lib/index.js",
"repository": {
@@ -16,8 +16,8 @@
}
],
"dependencies": {
"@node-red/registry": "3.1.0-beta.4",
"@node-red/util": "3.1.0-beta.4",
"@node-red/registry": "4.0.0-dev",
"@node-red/util": "4.0.0-dev",
"async-mutex": "0.4.0",
"clone": "2.1.2",
"express": "4.18.2",

View File

@@ -1,6 +1,6 @@
{
"name": "@node-red/util",
"version": "3.1.0-beta.4",
"version": "4.0.0-dev",
"license": "Apache-2.0",
"repository": {
"type": "git",

View File

@@ -1,14 +1,14 @@
# Node-RED
http://nodered.org
https://nodered.org
Low-code programming for event-driven applications.
![Node-RED: Low-code programming for event-driven applications.](http://nodered.org/images/node-red-screenshot.png)
![Node-RED: Low-code programming for event-driven applications.](https://nodered.org/images/node-red-screenshot.png)
## Quick Start
Check out http://nodered.org/docs/getting-started/ for full instructions on getting
Check out https://nodered.org/docs/getting-started/ for full instructions on getting
started.
1. `sudo npm install -g --unsafe-perm node-red`
@@ -17,7 +17,7 @@ started.
## Getting Help
More documentation can be found [here](http://nodered.org/docs).
More documentation can be found [here](https://nodered.org/docs).
For further help, or general discussion, please use the [Node-RED Forum](https://discourse.nodered.org) or [slack team](https://nodered.org/slack).

View File

@@ -1,8 +1,8 @@
{
"name": "node-red",
"version": "3.1.0-beta.4",
"version": "4.0.0-dev",
"description": "Low-code programming for event-driven applications",
"homepage": "http://nodered.org",
"homepage": "https://nodered.org",
"license": "Apache-2.0",
"repository": {
"type": "git",
@@ -31,17 +31,17 @@
"flow"
],
"dependencies": {
"@node-red/editor-api": "3.1.0-beta.4",
"@node-red/runtime": "3.1.0-beta.4",
"@node-red/util": "3.1.0-beta.4",
"@node-red/nodes": "3.1.0-beta.4",
"@node-red/editor-api": "4.0.0-dev",
"@node-red/runtime": "4.0.0-dev",
"@node-red/util": "4.0.0-dev",
"@node-red/nodes": "4.0.0-dev",
"basic-auth": "2.0.1",
"bcryptjs": "2.4.3",
"express": "4.18.2",
"fs-extra": "11.1.1",
"node-red-admin": "^3.0.0",
"node-red-admin": "^3.1.0",
"nopt": "5.0.0",
"semver": "7.5.0"
"semver": "7.5.4"
},
"optionalDependencies": {
"bcrypt": "5.1.0"

View File

@@ -88,7 +88,7 @@ if (parsedArgs.help) {
console.log(" -?, --help show this help");
console.log(" admin <command> run an admin command");
console.log("");
console.log("Documentation can be found at http://nodered.org");
console.log("Documentation can be found at https://nodered.org");
process.exit();
}

View File

@@ -71,7 +71,7 @@ module.exports = {
******************************************************************************/
/** To password protect the Node-RED editor and admin API, the following
* property can be used. See http://nodered.org/docs/security.html for details.
* property can be used. See https://nodered.org/docs/security.html for details.
*/
//adminAuth: {
// type: "credentials",
@@ -120,7 +120,7 @@ module.exports = {
* including node-red-dashboard, or the static content (httpStatic), the
* following properties can be used.
* The `pass` field is a bcrypt hash of the password.
* See http://nodered.org/docs/security.html#generating-the-password-hash
* See https://nodered.org/docs/security.html#generating-the-password-hash
*/
//httpNodeAuth: {user:"user",pass:"$2a$08$zZWtXTja0fB1pzD4sHCMyOCMYz2Z6dNbM6tl8sJogENOMcxWV9DN."},
//httpStaticAuth: {user:"user",pass:"$2a$08$zZWtXTja0fB1pzD4sHCMyOCMYz2Z6dNbM6tl8sJogENOMcxWV9DN."},
@@ -444,6 +444,7 @@ module.exports = {
* - fileWorkingDirectory
* - functionGlobalContext
* - functionExternalModules
* - functionTimeout
* - nodeMessageBufferMaxLength
* - ui (for use with Node-RED Dashboard)
* - debugUseColors
@@ -468,6 +469,9 @@ module.exports = {
/** Allow the Function node to load additional npm modules directly */
functionExternalModules: true,
/** Default timeout, in seconds, for the Function node. 0 means no timeout is applied */
functionTimeout: 0,
/** The following property can be used to set predefined values in Global Context.
* This allows extra node modules to be made available with in Function node.
* For example, the following:

View File

@@ -1449,6 +1449,34 @@ describe('function node', function() {
});
});
it('check if default function timeout settings are recognized', function (done) {
RED.settings.functionTimeout = 0.01;
var flow = [{id: "n1",type: "function",timeout: RED.settings.functionTimeout,wires: [["n2"]],func: "while(1==1){};\nreturn msg;"}];
helper.load(functionNode, flow, function () {
var n1 = helper.getNode("n1");
n1.receive({ payload: "foo", topic: "bar" });
setTimeout(function () {
try {
helper.log().called.should.be.true();
var logEvents = helper.log().args.filter(function (evt) {
return evt[0].type == "function";
});
logEvents.should.have.length(1);
var msg = logEvents[0][0];
msg.should.have.property('level', helper.log().ERROR);
msg.should.have.property('id', 'n1');
msg.should.have.property('type', 'function');
should.equal(RED.settings.functionTimeout, 0.01);
should.equal(msg.msg.message, 'Script execution timed out after 10ms');
delete RED.settings.functionTimeout;
done();
} catch (err) {
done(err);
}
}, 500);
});
});
describe("finalize function", function() {
it('should execute', function(done) {
@@ -1690,9 +1718,13 @@ describe('function node', function() {
describe("init function", function() {
it('should delay handling messages until init completes', function(done) {
const timeoutMS = 200;
// Since helper.load uses process.nextTick timers might occasionally finish
// a couple of milliseconds too early, so give some leeway to the check.
const timeoutCheckMargin = 5;
var flow = [{id:"n1",type:"function",wires:[["n2"]],initialize: `
return new Promise((resolve,reject) => {
setTimeout(resolve,200)
setTimeout(resolve, ${timeoutMS});
})`,
func:"return msg;"
},
@@ -1705,9 +1737,10 @@ describe('function node', function() {
msg.delta = Date.now() - msg.payload;
receivedMsgs.push(msg)
if (receivedMsgs.length === 5) {
var errors = receivedMsgs.filter(msg => msg.delta < 200)
let deltas = receivedMsgs.map(msg => msg.delta);
var errors = deltas.filter(delta => delta < (timeoutMS - timeoutCheckMargin))
if (errors.length > 0) {
done(new Error(`Message received before init completed - was ${msg.delta} expected >300`))
done(new Error(`Message received before init completed - delta values ${JSON.stringify(deltas)} expected to be > ${timeoutMS - timeoutCheckMargin}`))
} else {
done();
}

View File

@@ -98,7 +98,7 @@ describe("api/editor/theme", function () {
},
header: {
title: "Test Header Title",
url: "http://nodered.org",
url: "https://nodered.org",
image: "/absolute/path/to/header/image" // or null to remove image
},
@@ -147,7 +147,7 @@ describe("api/editor/theme", function () {
context.page.tabicon.should.have.a.property("colour", "#8f008f")
context.should.have.a.property("header");
context.header.should.have.a.property("title", "Test Header Title");
context.header.should.have.a.property("url", "http://nodered.org");
context.header.should.have.a.property("url", "https://nodered.org");
context.header.should.have.a.property("image", "theme/header/image");
context.page.should.have.a.property("css");
context.page.css.should.have.lengthOf(1);

View File

@@ -14,11 +14,33 @@
* limitations under the License.
**/
var should = require("should");
var NR_TEST_UTILS = require("nr-test-utils");
var util = NR_TEST_UTILS.require("@node-red/runtime/lib/storage/localfilesystem/util");
const should = require("should");
const NR_TEST_UTILS = require("nr-test-utils");
const util = NR_TEST_UTILS.require("@node-red/runtime/lib/storage/localfilesystem/util");
const { mkdtemp, readFile } = require('fs/promises');
const { join } = require('path');
const { tmpdir } = require('os');
describe('storage/localfilesystem/util', function() {
describe('writeFile', function () {
it('manages concurrent calls to modify the same file', async function () {
const testDirectory = await mkdtemp(join(tmpdir(), 'nr-test-'));
const testFile = join(testDirectory, 'foo.txt')
const testBackupFile = testFile + '.$$$'
let counter = 0
const promises = [
util.writeFile(testFile, `update-${counter++}`, testBackupFile ),
util.writeFile(testFile, `update-${counter++}`, testBackupFile ),
util.writeFile(testFile, `update-${counter++}`, testBackupFile )
]
await Promise.all(promises)
const result = await readFile(testFile, { encoding: 'utf-8' })
result.should.equal('update-2')
})
})
describe('parseJSON', function() {
it('returns parsed JSON', function() {
var result = util.parseJSON('{"a":123}');