1
0
mirror of https://github.com/node-red/node-red.git synced 2023-10-10 13:36:53 +02:00

Merge pull request #3205 from node-red/dev

Node-RED 2.1.0
This commit is contained in:
Nick O'Leary 2021-10-21 09:13:09 +01:00 committed by GitHub
commit fa51b06c46
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
196 changed files with 25299 additions and 4511 deletions

View File

@ -1,3 +1,93 @@
#### 2.1.0: Milestone Release
Editor
- Position popover properly on a scrolled page
- Fixes from 2.1.0-beta.2 (#3202) @knolleary
Nodes
- Link Out: Fix saving link out node links (#3201) @knolleary
- Switch: Refix #3170 - copy switch rule type when adding new rule
- TCP Request: Add string option to TCP request node output (#3204) @dceejay
#### 2.1.0-beta.2: Beta Release
Editor
- Fix switching projects (#3199) @knolleary
- Use locale setting when installing/enabling node (#3198) @knolleary
- Do not show projects-wecome dialog until welcome tour completes (#3197) @knolleary
- Fix converting selection to subflow (#3196) @knolleary
- Avoid conflicts with native browser cmd-ctrl type shortcuts (#3195) @knolleary
- Ensure message tools stay attached to top-level entry in Debug/Context (#3186) @knolleary
- Ensure tab state updates properly when toggling enable state (#3175) @knolleary
- Improve handling of long labels in TreeList (#3176) @knolleary
- Shift-click tab scroll arrows to jump to start/end (#3177) @knolleary
Runtime
- Update package dependencies
- Update to latest node-red-admin
Nodes
- Dynamic MQTT connections (#3189)
- Link: Filter out Link Out Return nodes in Link In edit dialog Fixes #3187
- Link: Fix link call label (#3200) @knolleary
- Debug: Redesign debug filter options and make them persistant (#3183) @knolleary
- Inject: Widen Inject interval box for >1 digit (#3184) @knolleary
- Switch: Fix rule focus when switch 'otherwise' rule is used (#3185) @knolleary
#### 2.1.0-beta.1: Beta Release
Editor
- Add Tour Guide component (#3136) @knolleary
- Allow tabs to be hidden (#3120) @knolleary
- Add align actions to editor (#3110) @knolleary
- Add support of environment variable for tab & group (#3112) @HiroyasuNishiyama
- Add autoComplete widget and add to TypedInput for msg. props (#3171) @knolleary
- Render node documentation to node-red style guide when written in markdown. (#3169) @Steve-Mcl
- Allow colouring of tab icon svg (#3140) @harmonic7
- Restore tab selection after merging conflicts (#3151) @GerwinvBeek
- Fix serving of theme files on Windows (#3154) @knolleary
- Ensure config-node select inherits width properly from input (#3155) @knolleary
- Do better remembering TypedInput values whilst switching types (#3159) @knolleary
- Update monaco to 0.28.1 (#3153) @knolleary
- Improve themeing of tourGuide (#3161) @knolleary
- Allow a node to specify a filter for the config nodes it can pick from (#3160) @knolleary
- Allow RED.notify.update to modify any notification setting (#3163) @knolleary
- Fix typo in ko editor.json Fixes #3119
- Improve RED.actions api to ensure actions cannot be overridden
- Ensure treeList row has suitable min-height when no content Fixes #3109
- Refactor edit dialogs to use separate edit panes
- Ensure type select button is not focussable when TypedInput only has one type
- Place close tab link in front of fade
Runtime
- Improve error reporting with oauth login strategies (#3148) @knolleary
- Add allowUpdate feature to externalModules.palette (#3143) @knolleary
- Improve node install error reporting (#3158) @knolleary
- Improve unit test coverage (#3168) @knolleary
- Allow coreNodesDir to be set to false (#3149) @hardillb
- Update package dependencies
- uncaughtException debug improvements (#3146) @renatojuniorrs
Nodes
- Change: Add option to deep-clone properties in Change node (#3156) @knolleary
- Delay: Add push to front of rate limit queue. (#3069) @dceejay
- File: Add paletteLabel to file nodes to make read/write more obvious (#3157) @knolleary
- HTTP Request: Extend HTTP request node to log detailed timing information (#3116) @k-toumura
- HTTP Response: Fix sizing of HTTP Response header fields (#3164) @knolleary
- Join: Support for msg.restartTimeout (#3121) @magma1447
- Link Call: Add Link Call node (#3152) @knolleary
- Switch: Copy previous rule type when adding rule to switch node (#3170) @knolleary
- Delay node: add option to send intermediate messages on separate output (#3166) @knolleary
- Typo in http request set method translation (#3173) @mailsvb
#### 2.0.6: Maintenance Release
Editor

View File

@ -162,7 +162,7 @@ module.exports = function(grunt) {
"packages/node_modules/@node-red/editor-client/src/js/ui/common/stack.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/common/typedInput.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/common/toggleButton.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/common/colorPicker.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/common/autoComplete.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/actions.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/deploy.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/diff.js",
@ -182,6 +182,7 @@ module.exports = function(grunt) {
"packages/node_modules/@node-red/editor-client/src/js/ui/tab-context.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/palette-editor.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/editor.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/editors/panes/*.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/editors/*.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/editors/code-editors/*.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/event-log.js",
@ -199,7 +200,8 @@ module.exports = function(grunt) {
"packages/node_modules/@node-red/editor-client/src/js/ui/projects/projectSettings.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/projects/projectUserSettings.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/projects/tab-versionControl.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/touch/radialMenu.js"
"packages/node_modules/@node-red/editor-client/src/js/ui/touch/radialMenu.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/tour/*.js"
],
dest: "packages/node_modules/@node-red/editor-client/public/red/red.js"
},
@ -326,6 +328,12 @@ module.exports = function(grunt) {
],
tasks: ['jsonlint:keymaps','copy:build']
},
tours: {
files: [
'packages/node_modules/@node-red/editor-client/src/tours/**/*.js'
],
tasks: ['copy:build']
},
misc: {
files: [
'CHANGELOG.md'
@ -423,6 +431,12 @@ module.exports = function(grunt) {
src: '**',
expand: true,
dest: 'packages/node_modules/@node-red/editor-client/public/vendor/ace/'
},
{
cwd: 'packages/node_modules/@node-red/editor-client/src/tours',
src: '**',
expand: true,
dest: 'packages/node_modules/@node-red/editor-client/public/red/tours/'
}
]
}

View File

@ -1,6 +1,6 @@
{
"name": "node-red",
"version": "2.0.6",
"version": "2.1.0",
"description": "Low-code programming for event-driven applications",
"homepage": "http://nodered.org",
"license": "Apache-2.0",
@ -26,9 +26,9 @@
}
],
"dependencies": {
"acorn": "8.4.1",
"acorn-walk": "8.1.1",
"ajv": "8.6.2",
"acorn": "8.5.0",
"acorn-walk": "8.2.0",
"ajv": "8.6.3",
"async-mutex": "0.3.2",
"basic-auth": "2.0.1",
"bcryptjs": "2.4.3",
@ -40,7 +40,7 @@
"cookie-parser": "1.4.5",
"cors": "2.8.5",
"cronosjs": "1.7.1",
"denque": "1.5.0",
"denque": "2.0.1",
"express": "4.17.1",
"express-session": "1.17.2",
"form-data": "4.0.0",
@ -48,9 +48,9 @@
"fs.notify": "0.0.4",
"got": "11.8.2",
"hash-sum": "2.0.0",
"hpagent": "^0.1.2",
"hpagent": "0.1.2",
"https-proxy-agent": "5.0.0",
"i18next": "20.3.2",
"i18next": "21.3.1",
"iconv-lite": "0.6.3",
"is-utf8": "0.2.1",
"js-yaml": "3.14.1",
@ -64,18 +64,18 @@
"mqtt": "4.2.8",
"multer": "1.4.3",
"mustache": "4.2.0",
"node-red-admin": "^2.2.0",
"node-red-admin": "^2.2.1",
"nopt": "5.0.0",
"oauth2orize": "1.11.0",
"on-headers": "1.0.2",
"passport": "0.4.1",
"passport": "0.5.0",
"passport-http-bearer": "1.0.1",
"passport-oauth2-client-password": "0.1.2",
"raw-body": "2.4.1",
"semver": "7.3.5",
"tar": "6.1.11",
"tough-cookie": "4.0.0",
"uglify-js": "3.14.1",
"uglify-js": "3.14.2",
"uuid": "8.3.2",
"ws": "7.5.1",
"xml2js": "0.4.23"
@ -84,7 +84,7 @@
"bcrypt": "5.0.1"
},
"devDependencies": {
"dompurify": "2.3.1",
"dompurify": "2.3.3",
"grunt": "1.4.1",
"grunt-chmod": "~1.1.1",
"grunt-cli": "~1.4.3",
@ -93,7 +93,7 @@
"grunt-contrib-compress": "2.0.0",
"grunt-contrib-concat": "~1.0.1",
"grunt-contrib-copy": "~1.0.0",
"grunt-contrib-jshint": "3.0.0",
"grunt-contrib-jshint": "3.1.1",
"grunt-contrib-uglify": "5.0.1",
"grunt-contrib-watch": "~1.1.0",
"grunt-jsdoc": "2.4.1",
@ -104,16 +104,16 @@
"grunt-sass": "~3.1.0",
"grunt-simple-mocha": "~0.4.1",
"grunt-simple-nyc": "^3.0.1",
"i18next-http-backend": "1.2.6",
"i18next-http-backend": "1.3.1",
"jquery-i18next": "1.2.1",
"jsdoc-nr-template": "github:node-red/jsdoc-nr-template",
"marked": "2.1.3",
"marked": "3.0.7",
"minami": "1.2.3",
"mocha": "9.1.1",
"mocha": "9.1.2",
"node-red-node-test-helper": "^0.2.7",
"nodemon": "2.0.12",
"nodemon": "2.0.13",
"proxy": "^1.0.2",
"sass": "1.39.0",
"sass": "1.43.2",
"should": "13.2.3",
"sinon": "11.1.2",
"stoppable": "^1.1.0",

View File

@ -199,8 +199,12 @@ function genericStrategy(adminApp,strategy) {
passport.use(new strategy.strategy(options, verify));
adminApp.get('/auth/strategy',
passport.authenticate(strategy.name, {session:false, failureRedirect: settings.httpAdminRoot }),
completeGenerateStrategyAuth
passport.authenticate(strategy.name, {session:false,
failureMessage: true,
failureRedirect: settings.httpAdminRoot
}),
completeGenerateStrategyAuth,
handleStrategyError
);
var callbackMethodFunc = adminApp.get;
@ -208,8 +212,13 @@ function genericStrategy(adminApp,strategy) {
callbackMethodFunc = adminApp.post;
}
callbackMethodFunc.call(adminApp,'/auth/strategy/callback',
passport.authenticate(strategy.name, {session:false, failureRedirect: settings.httpAdminRoot }),
completeGenerateStrategyAuth
passport.authenticate(strategy.name, {
session:false,
failureMessage: true,
failureRedirect: settings.httpAdminRoot
}),
completeGenerateStrategyAuth,
handleStrategyError
);
}
@ -219,6 +228,13 @@ function completeGenerateStrategyAuth(req,res) {
// Successful authentication, redirect home.
res.redirect(settings.httpAdminRoot + '?access_token='+tokens.accessToken);
}
function handleStrategyError(err, req, res, next) {
if (res.headersSent) {
return next(err)
}
log.audit({event: "auth.login.fail.oauth",error:err.toString()});
res.redirect(settings.httpAdminRoot + '?session_message='+err.toString());
}
module.exports = {
init: init,

View File

@ -18,14 +18,6 @@ var apiUtils = require("../util");
var express = require("express");
var runtimeAPI;
function getUsername(userObj) {
var username = '__default';
if ( userObj && userObj.name ) {
username = userObj.name;
}
return username;
}
module.exports = {
init: function(_runtimeAPI) {
runtimeAPI = _runtimeAPI;

View File

@ -24,15 +24,18 @@ var defaultContext = {
page: {
title: "Node-RED",
favicon: "favicon.ico",
tabicon: "red/images/node-red-icon-black.svg"
tabicon: {
icon: "red/images/node-red-icon-black.svg",
colour: "#8f0000"
}
},
header: {
title: "Node-RED",
image: "red/images/node-red.svg"
},
asset: {
red: (process.env.NODE_ENV == "development")? "red/red.js":"red/red.min.js",
main: (process.env.NODE_ENV == "development")? "red/main.js":"red/main.min.js",
red: "red/red.min.js",
main: "red/main.min.js",
vendorMonaco: ""
}
};
@ -74,7 +77,7 @@ function serveFilesFromTheme(themeValue, themeApp, directory, baseDirectory) {
let fullPath = array[i];
if (baseDirectory) {
fullPath = path.resolve(baseDirectory,array[i]);
if (fullPath.indexOf(baseDirectory) !== 0) {
if (fullPath.indexOf(path.resolve(baseDirectory)) !== 0) {
continue;
}
}
@ -91,6 +94,10 @@ module.exports = {
init: function(settings, _runtimeAPI) {
runtimeAPI = _runtimeAPI;
themeContext = clone(defaultContext);
if (process.env.NODE_ENV == "development") {
themeContext.asset.red = "red/red.js";
themeContext.asset.main = "red/main.js";
}
themeSettings = null;
theme = settings.editorTheme || {};
themeContext.asset.vendorMonaco = ((theme.codeEditor || {}).lib === "monaco") ? "vendor/monaco/monaco-bootstrap.js" : "";
@ -123,9 +130,13 @@ module.exports = {
}
if (theme.page.tabicon) {
url = serveFile(themeApp,"/tabicon/",theme.page.tabicon)
let icon = theme.page.tabicon.icon || theme.page.tabicon
url = serveFile(themeApp,"/tabicon/", icon)
if (url) {
themeContext.page.tabicon = url;
themeContext.page.tabicon.icon = url;
}
if (theme.page.tabicon.colour) {
themeContext.page.tabicon.colour = theme.page.tabicon.colour
}
}
@ -246,6 +257,9 @@ module.exports = {
theme.page = theme.page || {_:{}}
theme.page._.scripts = scriptFiles.concat(theme.page._.scripts || [])
}
if(theme.codeEditor) {
theme.codeEditor.options = Object.assign({}, themePlugin.monacoOptions, theme.codeEditor.options);
}
}
activeThemeInitialised = true;
}

View File

@ -91,7 +91,16 @@ module.exports = {
},
editor: async function(req,res) {
res.send(Mustache.render(editorTemplate,await theme.context()));
let sessionMessages;
if (req.session && req.session.messages) {
sessionMessages = JSON.stringify(req.session.messages);
delete req.session.messages
}
res.send(Mustache.render(editorTemplate,{
sessionMessages,
...await theme.context()
}));
},
editorResources: express.static(path.join(editorClientDir,'public'))
};

View File

@ -1,6 +1,6 @@
{
"name": "@node-red/editor-api",
"version": "2.0.6",
"version": "2.1.0",
"license": "Apache-2.0",
"main": "./lib/index.js",
"repository": {
@ -16,8 +16,8 @@
}
],
"dependencies": {
"@node-red/util": "2.0.6",
"@node-red/editor-client": "2.0.6",
"@node-red/util": "2.1.0",
"@node-red/editor-client": "2.1.0",
"bcryptjs": "2.4.3",
"body-parser": "1.19.0",
"clone": "2.1.2",
@ -31,7 +31,7 @@
"oauth2orize": "1.11.0",
"passport-http-bearer": "1.0.1",
"passport-oauth2-client-password": "0.1.2",
"passport": "0.4.1",
"passport": "0.5.0",
"ws": "7.5.1"
},
"optionalDependencies": {

View File

@ -53,8 +53,15 @@
"confirmDelete": "Confirm delete",
"delete": "Are you sure you want to delete '__label__'?",
"dropFlowHere": "Drop the flow here",
"addFlow": "Add Flow",
"listFlows": "List Flows",
"addFlow": "Add flow",
"addFlowToRight": "Add flow to the right",
"hideFlow": "Hide flow",
"hideOtherFlows": "Hide other flows",
"showAllFlows": "Show all flows",
"hideAllFlows": "Hide all flows",
"showLastHiddenFlow": "Show last hidden flow",
"listFlows": "List flows",
"listSubflows": "List subflows",
"status": "Status",
"enabled": "Enabled",
"disabled":"Disabled",
@ -105,6 +112,7 @@
"editPalette":"Manage palette",
"other": "Other",
"showTips": "Show tips",
"showWelcomeTours": "Show guided tours for new versions",
"help": "Node-RED website",
"projects": "Projects",
"projects-new": "New",
@ -116,7 +124,20 @@
"groupSelection": "Group selection",
"ungroupSelection": "Ungroup selection",
"groupMergeSelection": "Merge selection",
"groupRemoveSelection": "Remove from group"
"groupRemoveSelection": "Remove from group",
"arrange":"Arrange",
"alignLeft":"Align to left",
"alignCenter":"Align to center",
"alignRight":"Align to right",
"alignTop":"Align to top",
"alignMiddle":"Align to middle",
"alignBottom":"Align to bottom",
"distributeHorizontally":"Distribute horizontally",
"distributeVertically":"Distribute vertically",
"moveToBack":"Move to back",
"moveToFront":"Move to front",
"moveBackwards":"Move backwards",
"moveForwards":"Move forwards"
}
},
"actions": {
@ -450,8 +471,9 @@
"unassigned": "Unassigned",
"global": "global",
"workspace": "workspace",
"selectAll": "Select all nodes",
"selectAllConnected": "Select all connected nodes",
"selectAll": "Select all",
"selectNone": "Select none",
"selectAllConnected": "Select connected",
"addRemoveNode": "Add/remove node from selection",
"editSelected": "Edit selected node",
"deleteSelected": "Delete selected nodes or link",
@ -464,7 +486,10 @@
"copyNode": "Copy selected nodes",
"cutNode": "Cut selected nodes",
"pasteNode": "Paste nodes",
"undoChange": "Undo the last change performed",
"copyGroupStyle": "Copy group style",
"pasteGroupStyle": "Paste group style",
"undoChange": "Undo",
"redoChange": "Redo",
"searchBox": "Open search box",
"managePalette": "Manage palette",
"actionList":"Action list"
@ -519,7 +544,8 @@
"nodeEnabled_plural": "Nodes enabled:",
"nodeDisabled": "Node disabled:",
"nodeDisabled_plural": "Nodes disabled:",
"nodeUpgraded": "Node module __module__ upgraded to version __version__"
"nodeUpgraded": "Node module __module__ upgraded to version __version__",
"unknownNodeRegistered": "Error loading node: <ul><li>__type__<br>__error__</li></ul>"
},
"editor": {
"title": "Manage palette",
@ -1108,6 +1134,10 @@
"preview": "UI Preview",
"defaultValue": "Default value"
},
"tourGuide": {
"start": "Start",
"next": "Next"
},
"languages" : {
"de": "German",
"en-US": "English",

View File

@ -1,6 +1,6 @@
{
"name": "@node-red/editor-client",
"version": "2.0.6",
"version": "2.1.0",
"license": "Apache-2.0",
"repository": {
"type": "git",

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" height="512" width="512"><g transform="translate(0 -540.36)"><path fill="#8f0000" color="#000" d="M0 540.36h512v392H0z"/><rect ry="0" height="108.23" width="500.23" stroke="#fff" y="938.25" x="5.89" stroke-width="11.77" fill="#fff"/><path style="text-decoration-color:#000;isolation:auto;mix-blend-mode:normal;solid-color:#000;block-progression:tb;text-decoration-line:none;white-space:normal;text-indent:0;text-transform:none;text-decoration-style:solid" d="M122.88 305.82a4.46 4.46 0 0 0-4.38 4.42v.78c-2.23.1-4.04.54-5.33 1.43a10.5 10.5 0 0 0-3.18 3.87c-.71 1.3-1.3 2.41-2.15 3.2-.72.66-1.8 1.12-3.45 1.32a4.37 4.37 0 0 0-4.3-3.95H82.91a4.43 4.43 0 0 0-4.42 4.35v4.24a4.43 4.43 0 0 0 4.42 4.36h17.16a4.4 4.4 0 0 0 4.4-4.36v-1.6c9.72.14 12.46 2.6 15.59 5.33 3 2.62 6.66 5.38 15.43 5.5v.73a4.49 4.49 0 0 0 4.46 4.38h17.09c2.38 0 4.45-2 4.45-4.38v-4.24a4.49 4.49 0 0 0-4.45-4.38h-17.1c-2.38 0-4.45 2-4.45 4.38v.58c-8.1-.06-10.48-2.15-13.5-4.79-2.5-2.19-5.64-4.58-11.94-5.58 1.17-1.18 1.88-2.52 2.51-3.66.68-1.23 1.29-2.2 2.27-2.88.76-.52 1.98-.84 3.66-.94v.55c0 2.39 2 4.34 4.38 4.34h17.24a4.39 4.39 0 0 0 4.38-4.34v-4.24c0-2.38-2-4.42-4.38-4.42zm0 3h17.24c.8 0 1.38.62 1.38 1.42v4.24c0 .81-.57 1.34-1.38 1.34h-17.24c-.8 0-1.38-.53-1.38-1.34v-4.24c0-.8.57-1.42 1.38-1.42zm-39.96 11.02h17.16c.81 0 1.42.6 1.42 1.4v4.24c0 .81-.61 1.41-1.42 1.41H82.92c-.8 0-1.42-.6-1.42-1.4v-4.25c0-.8.61-1.4 1.42-1.4zm57.04 9.98h17.09c.8 0 1.45.57 1.45 1.38v4.17c0 .8-.65 1.45-1.45 1.45h-17.1c-.8 0-1.45-.65-1.45-1.45v-4.17c0-.8.65-1.38 1.46-1.38z" fill="#fff" color="#000" transform="matrix(4 0 0 4 -162 -450.91)"/><g fill="#8f0000"><path d="M91 954.34v8.45l-8 1.45v60.07H69.03l-28.53-47.1-.5.05v37.2l8 1.44v8.41H19v-8.4l7.45-1.45v-50.22L19 962.79v-8.46h21.48l28.37 47.1.15-.04v-37.15l-7-1.45v-8.45h29zM95 997.83q0-11.63 6.49-19.03 6.53-7.45 18.02-7.45 11.53 0 18.02 7.4 6.54 7.4 6.54 19.08v1q0 11.74-6.54 19.14-6.49 7.35-17.93 7.35-11.58 0-18.11-7.35-6.5-7.4-6.5-19.13v-1.01zm14.03 1q0 7.12 2.5 11.45 2.5 4.28 8.08 4.28 5.43 0 7.93-4.33 2.54-4.33 2.54-11.4v-1q0-6.92-2.54-11.3-2.55-4.37-8.03-4.37t-7.98 4.37-2.5 11.3v1zM184.48 1017.96a17.15 17.15 0 0 1-5.82 5.48 15.17 15.17 0 0 1-7.59 1.88c-6.4 0-11.4-2.35-14.95-7.03-3.52-4.67-5.13-10.86-5.13-18.55v-1c0-8.21 1.62-14.83 5.18-19.86 3.56-5.03 8.56-7.54 15-7.54 2.6 0 4.93.57 7.01 1.73a17.94 17.94 0 0 1 5.81 4.8v-18.64l-8-1.45v-8.46h22v65.13l6 1.44v8.43h-18.45l-1.06-6.36zm-19.49-18.22c0 4.55.63 8.14 2.14 10.77 1.54 2.6 4.04 3.9 7.5 3.9 2.05 0 3.83-.43 5.33-1.26 1.5-.83 3.07-2.03 4.03-3.6v-22.06a11.27 11.27 0 0 0-4.03-3.85 9.62 9.62 0 0 0-5.24-1.4c-3.43 0-5.92 1.53-7.5 4.57s-2.23 7.02-2.23 11.92v1.01zM233.7 1025.28c-7.5 0-13.5-2.4-17.98-7.21-4.48-4.81-6.73-10.91-6.73-18.32v-1.92c0-7.72 2.12-14.08 6.35-19.08 4.26-5 9.96-7.46 17.1-7.43 7.03 0 12.47 2.1 16.35 6.33a23.46 23.46 0 0 1 6.2 17.15v7.52h-31.43l-.1.41c.26 3.43 1.4 6.25 3.41 8.46 2.05 2.21 4.83 3.32 8.32 3.32 3.1 0 5.69-.3 7.74-.91 2.05-.64 4.29-1.64 6.73-2.98l3.8 8.65a27.59 27.59 0 0 1-8.37 4.28 35.28 35.28 0 0 1-11.4 1.73zm-1.25-43.16c-2.6 0-4.65.99-6.15 2.98s-2.44 4.6-2.8 7.83l.15.4H241v-1.41c0-2.98-.84-5.35-2.25-7.11-1.37-1.8-3.47-2.7-6.3-2.7zM291.99 1000.32h-27v-11h27zM331.88 954.34c7.95 0 14.18 1.82 18.7 5.47 4.52 3.63 6.4 8.64 6.4 15.05 0 3.52-.57 6.58-2.46 9.18-1.89 2.6-4.66 4.7-8.31 6.3 4.13 1.21 7.1 3.25 8.89 6.1a19.02 19.02 0 0 1 2.89 10.52v3.56c0 1.54.15 2.74.76 3.6.6.84 1.62 1.34 3.03 1.5l1.2.24v8.46h-6.73c-4.58 0-7.8-1.24-9.66-3.7s-2.6-5.66-2.6-9.57v-3.99c0-3.4-1.1-6.05-2.93-7.98-1.8-1.95-4.34-2.98-7.64-3.07H322v18.45l7 1.44v8.42h-29v-8.42l8-1.44v-50.22l-8-1.44v-8.46h31.89zm-9.95 30.85h9.71c3.91 0 6.84-.83 8.8-2.5s2.93-4.07 2.93-7.2c0-3.15-.98-5.65-2.93-7.5-1.92-1.9-4.78-2.84-8.56-2.84h-9.9v20.04zM412.99 993.32h-23v20h22.21l.63-8h10.2v18.99H368v-8.42l8-1.44v-50.22l-8-1.44v-8.47h54.95v19h-10.3l-.63-8H390v17h23v11zM462.48 954.36c8.55 0 15.6 2.71 21.14 8.19 5.55 5.45 8.36 12.42 8.36 20.98v11.58c0 8.59-2.81 15.63-8.36 21.08-5.54 5.41-12.59 8.12-21.14 8.12h-31.5v-8.41l7-1.52v-50.22l-7-1.37v-8.43l7.46-.08 24.04.08zm-10.5 10.76v48.4l9.77.02c5.03.02 8.98-1.7 11.83-5.1 2.85-3.39 4.4-7.8 4.4-13.28v-11.68c0-5.42-1.55-9.84-4.4-13.24-2.85-3.4-6.8-5.1-11.83-5.1l-9.77-.02z"/></g></g></svg>

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

@ -558,11 +558,22 @@ RED.history = (function() {
} else if (ev.t == "reorder") {
inverseEv = {
t: 'reorder',
order: RED.nodes.getWorkspaceOrder(),
dirty: RED.nodes.dirty()
};
if (ev.order) {
RED.workspaces.order(ev.order);
if (ev.workspaces) {
inverseEv.workspaces = {
from: ev.workspaces.to,
to: ev.workspaces.from
}
RED.workspaces.order(ev.workspaces.from);
}
if (ev.nodes) {
inverseEv.nodes = {
z: ev.nodes.z,
from: ev.nodes.to,
to: ev.nodes.from
}
RED.nodes.setNodeOrder(ev.nodes.z,ev.nodes.from);
}
} else if (ev.t == "createGroup") {
inverseEv = {
@ -658,6 +669,8 @@ RED.history = (function() {
push: function(ev) {
undoHistory.push(ev);
redoHistory = [];
RED.menu.setDisabled("menu-item-edit-undo", false);
RED.menu.setDisabled("menu-item-edit-redo", true);
},
pop: function() {
var ev = undoHistory.pop();
@ -665,6 +678,8 @@ RED.history = (function() {
if (rev) {
redoHistory.push(rev);
}
RED.menu.setDisabled("menu-item-edit-undo", undoHistory.length === 0);
RED.menu.setDisabled("menu-item-edit-redo", redoHistory.length === 0);
},
peek: function() {
return undoHistory[undoHistory.length-1];
@ -672,6 +687,8 @@ RED.history = (function() {
clear: function() {
undoHistory = [];
redoHistory = [];
RED.menu.setDisabled("menu-item-edit-undo", true);
RED.menu.setDisabled("menu-item-edit-redo", true);
},
redo: function() {
var ev = redoHistory.pop();
@ -681,6 +698,8 @@ RED.history = (function() {
undoHistory.push(uev);
}
}
RED.menu.setDisabled("menu-item-edit-undo", undoHistory.length === 0);
RED.menu.setDisabled("menu-item-edit-redo", redoHistory.length === 0);
}
}

View File

@ -27,6 +27,7 @@ RED.i18n = (function() {
apiRootUrl = options.apiRootUrl||"";
var preferredLanguage = localStorage.getItem("editor-language") || detectLanguage();
var opts = {
compatibilityJSON: 'v3',
backend: {
loadPath: apiRootUrl+'locales/__ns__?lng=__lng__',
},

View File

@ -25,7 +25,9 @@
"ctrl-alt-o": "core:open-project",
"ctrl-g v": "core:show-version-control-tab",
"ctrl-shift-l": "core:show-event-log",
"ctrl-shift-p":"core:show-action-list"
"ctrl-shift-p":"core:show-action-list",
"alt-w": "core:hide-flow",
"alt-shift-w": "core:show-last-hidden-flow"
},
"red-ui-sidebar-node-config": {
"backspace": "core:delete-config-selection",
@ -77,6 +79,15 @@
"right": "core:go-to-nearest-node-on-right",
"left": "core:go-to-nearest-node-on-left",
"up": "core:go-to-nearest-node-above",
"down": "core:go-to-nearest-node-below"
"down": "core:go-to-nearest-node-below",
"alt-a g": "core:align-selection-to-grid",
"alt-a l": "core:align-selection-to-left",
"alt-a r": "core:align-selection-to-right",
"alt-a t": "core:align-selection-to-top",
"alt-a b": "core:align-selection-to-bottom",
"alt-a m": "core:align-selection-to-middle",
"alt-a c": "core:align-selection-to-center",
"alt-a h": "core:distribute-selection-horizontally",
"alt-a v": "core:distribute-selection-vertically"
}
}

View File

@ -16,8 +16,6 @@
RED.nodes = (function() {
var node_defs = {};
var nodes = {};
var nodeTabMap = {};
var linkTabMap = {};
var configNodes = {};
@ -41,6 +39,7 @@ RED.nodes = (function() {
RED.events.emit("workspace:dirty",{dirty:dirty});
}
// The registry holds information about all node types.
var registry = (function() {
var moduleList = {};
var nodeList = [];
@ -53,7 +52,8 @@ RED.nodes = (function() {
defaults: {
label: {value:""},
disabled: {value: false},
info: {value: ""}
info: {value: ""},
env: {value: []}
}
};
@ -142,9 +142,21 @@ RED.nodes = (function() {
RED.events.emit("registry:node-set-disabled",ns);
},
registerNodeType: function(nt,def) {
nodeDefinitions[nt] = def;
def.type = nt;
if (nt.substring(0,8) != "subflow:") {
if (!nodeSets[typeToId[nt]]) {
var error = "";
var fullType = nt;
if (RED._loadingModule) {
fullType = "["+RED._loadingModule+"] "+nt;
if (nodeSets[RED._loadingModule]) {
error = nodeSets[RED._loadingModule].err || "";
} else {
error = "Unknown error";
}
}
RED.notify(RED._("palette.event.unknownNodeRegistered",{type:fullType, error:error}), "error");
return;
}
def.set = nodeSets[typeToId[nt]];
nodeSets[typeToId[nt]].added = true;
nodeSets[typeToId[nt]].enabled = true;
@ -167,9 +179,13 @@ RED.nodes = (function() {
}
return result;
}
// TODO: too tightly coupled into palette UI
}
def.type = nt;
nodeDefinitions[nt] = def;
if (def.defaults) {
for (var d in def.defaults) {
if (def.defaults.hasOwnProperty(d)) {
@ -209,6 +225,285 @@ RED.nodes = (function() {
return exports;
})();
// allNodes holds information about the Flow nodes.
var allNodes = (function() {
var nodes = {};
var tabMap = {};
var api = {
addTab: function(id) {
tabMap[id] = [];
},
hasTab: function(z) {
return tabMap.hasOwnProperty(z)
},
removeTab: function(id) {
delete tabMap[id];
},
addNode: function(n) {
nodes[n.id] = n;
if (tabMap.hasOwnProperty(n.z)) {
tabMap[n.z].push(n);
} else {
console.warn("Node added to unknown tab/subflow:",n);
tabMap["_"] = tabMap["_"] || [];
tabMap["_"].push(n);
}
},
removeNode: function(n) {
delete nodes[n.id]
if (tabMap.hasOwnProperty(n.z)) {
var i = tabMap[n.z].indexOf(n);
if (i > -1) {
tabMap[n.z].splice(i,1);
}
}
},
hasNode: function(id) {
return nodes.hasOwnProperty(id);
},
getNode: function(id) {
return nodes[id]
},
moveNode: function(n, newZ) {
api.removeNode(n);
n.z = newZ;
api.addNode(n)
},
moveNodesForwards: function(nodes) {
var result = [];
if (!Array.isArray(nodes)) {
nodes = [nodes]
}
// Can only do this for nodes on the same tab.
// Use nodes[0] to get the z
var tabNodes = tabMap[nodes[0].z];
var toMove = new Set(nodes.filter(function(n) { return n.type !== "group" && n.type !== "subflow" }));
var moved = new Set();
for (var i = tabNodes.length-1; i >= 0; i--) {
if (toMove.size === 0) {
break;
}
var n = tabNodes[i];
if (toMove.has(n)) {
// This is a node to move.
if (i < tabNodes.length-1 && !moved.has(tabNodes[i+1])) {
// Remove from current position
tabNodes.splice(i,1);
// Add it back one position higher
tabNodes.splice(i+1,0,n);
n._reordered = true;
result.push(n);
}
toMove.delete(n);
moved.add(n);
}
}
if (result.length > 0) {
RED.events.emit('nodes:reorder',{
z: nodes[0].z,
nodes: result
});
}
return result;
},
moveNodesBackwards: function(nodes) {
var result = [];
if (!Array.isArray(nodes)) {
nodes = [nodes]
}
// Can only do this for nodes on the same tab.
// Use nodes[0] to get the z
var tabNodes = tabMap[nodes[0].z];
var toMove = new Set(nodes.filter(function(n) { return n.type !== "group" && n.type !== "subflow" }));
var moved = new Set();
for (var i = 0; i < tabNodes.length; i++) {
if (toMove.size === 0) {
break;
}
var n = tabNodes[i];
if (toMove.has(n)) {
// This is a node to move.
if (i > 0 && !moved.has(tabNodes[i-1])) {
// Remove from current position
tabNodes.splice(i,1);
// Add it back one position lower
tabNodes.splice(i-1,0,n);
n._reordered = true;
result.push(n);
}
toMove.delete(n);
moved.add(n);
}
}
if (result.length > 0) {
RED.events.emit('nodes:reorder',{
z: nodes[0].z,
nodes: result
});
}
return result;
},
moveNodesToFront: function(nodes) {
var result = [];
if (!Array.isArray(nodes)) {
nodes = [nodes]
}
// Can only do this for nodes on the same tab.
// Use nodes[0] to get the z
var tabNodes = tabMap[nodes[0].z];
var toMove = new Set(nodes.filter(function(n) { return n.type !== "group" && n.type !== "subflow" }));
var target = tabNodes.length-1;
for (var i = tabNodes.length-1; i >= 0; i--) {
if (toMove.size === 0) {
break;
}
var n = tabNodes[i];
if (toMove.has(n)) {
// This is a node to move.
if (i < target) {
// Remove from current position
tabNodes.splice(i,1);
tabNodes.splice(target,0,n);
n._reordered = true;
result.push(n);
}
target--;
toMove.delete(n);
}
}
if (result.length > 0) {
RED.events.emit('nodes:reorder',{
z: nodes[0].z,
nodes: result
});
}
return result;
},
moveNodesToBack: function(nodes) {
var result = [];
if (!Array.isArray(nodes)) {
nodes = [nodes]
}
// Can only do this for nodes on the same tab.
// Use nodes[0] to get the z
var tabNodes = tabMap[nodes[0].z];
var toMove = new Set(nodes.filter(function(n) { return n.type !== "group" && n.type !== "subflow" }));
var target = 0;
for (var i = 0; i < tabNodes.length; i++) {
if (toMove.size === 0) {
break;
}
var n = tabNodes[i];
if (toMove.has(n)) {
// This is a node to move.
if (i > target) {
// Remove from current position
tabNodes.splice(i,1);
// Add it back one position lower
tabNodes.splice(target,0,n);
n._reordered = true;
result.push(n);
}
target++;
toMove.delete(n);
}
}
if (result.length > 0) {
RED.events.emit('nodes:reorder',{
z: nodes[0].z,
nodes: result
});
}
return result;
},
getNodes: function(z) {
return tabMap[z];
},
clear: function() {
nodes = {};
tabMap = {};
},
eachNode: function(cb) {
var nodeList,i,j;
for (i in subflows) {
if (subflows.hasOwnProperty(i)) {
nodeList = tabMap[i];
for (j = 0; j < nodeList.length; j++) {
if (cb(nodeList[j]) === false) {
return;
}
}
}
}
for (i = 0; i < workspacesOrder.length; i++) {
nodeList = tabMap[workspacesOrder[i]];
for (j = 0; j < nodeList.length; j++) {
if (cb(nodeList[j]) === false) {
return;
}
}
}
// Flow nodes that do not have a valid tab/subflow
if (tabMap["_"]) {
nodeList = tabMap["_"];
for (j = 0; j < nodeList.length; j++) {
if (cb(nodeList[j]) === false) {
return;
}
}
}
},
filterNodes: function(filter) {
var result = [];
var searchSet = null;
var doZFilter = false;
if (filter.hasOwnProperty("z")) {
if (tabMap.hasOwnProperty(filter.z)) {
searchSet = tabMap[filter.z];
} else {
doZFilter = true;
}
}
var objectLookup = false;
if (searchSet === null) {
searchSet = Object.keys(nodes);
objectLookup = true;
}
for (var n=0;n<searchSet.length;n++) {
var node = searchSet[n];
if (objectLookup) {
node = nodes[node];
}
if (filter.hasOwnProperty("type") && node.type !== filter.type) {
continue;
}
if (doZFilter && node.z !== filter.z) {
continue;
}
result.push(node);
}
return result;
},
getNodeOrder: function(z) {
return tabMap[z].map(function(n) { return n.id })
},
setNodeOrder: function(z, order) {
var orderMap = {};
order.forEach(function(id,i) {
orderMap[id] = i;
})
tabMap[z].sort(function(A,B) {
A._reordered = true;
B._reordered = true;
return orderMap[A.id] - orderMap[B.id];
})
}
}
return api;
})()
function getID() {
var bytes = [];
for (var i=0;i<8;i++) {
@ -294,15 +589,10 @@ RED.nodes = (function() {
});
n.i = nextId+1;
}
nodes[n.id] = n;
allNodes.addNode(n);
if (!nodeLinks[n.id]) {
nodeLinks[n.id] = {in:[],out:[]};
}
if (nodeTabMap[n.z]) {
nodeTabMap[n.z][n.id] = n;
} else {
console.warn("Node added to unknown tab/subflow:",n);
}
}
RED.events.emit('nodes:add',n);
}
@ -330,10 +620,8 @@ RED.nodes = (function() {
function getNode(id) {
if (id in configNodes) {
return configNodes[id];
} else if (id in nodes) {
return nodes[id];
}
return null;
return allNodes.getNode(id);
}
function removeNode(id) {
@ -345,13 +633,10 @@ RED.nodes = (function() {
delete configNodes[id];
RED.events.emit('nodes:remove',node);
RED.workspaces.refresh();
} else if (id in nodes) {
node = nodes[id];
delete nodes[id]
} else if (allNodes.hasNode(id)) {
node = allNodes.getNode(id);
allNodes.removeNode(node);
delete nodeLinks[id];
if (nodeTabMap[node.z]) {
delete nodeTabMap[node.z][node.id];
}
removedLinks = links.filter(function(l) { return (l.source === node) || (l.target === node); });
removedLinks.forEach(removeLink);
var updatedConfigNode = false;
@ -409,40 +694,54 @@ RED.nodes = (function() {
return {links:removedLinks,nodes:removedNodes};
}
function moveNodesForwards(nodes) {
return allNodes.moveNodesForwards(nodes);
}
function moveNodesBackwards(nodes) {
return allNodes.moveNodesBackwards(nodes);
}
function moveNodesToFront(nodes) {
return allNodes.moveNodesToFront(nodes);
}
function moveNodesToBack(nodes) {
return allNodes.moveNodesToBack(nodes);
}
function getNodeOrder(z) {
return allNodes.getNodeOrder(z);
}
function setNodeOrder(z, order) {
allNodes.setNodeOrder(z,order);
}
function moveNodeToTab(node, z) {
if (node.type === "group") {
moveGroupToTab(node,z);
return;
}
if (nodeTabMap[node.z]) {
delete nodeTabMap[node.z][node.id];
}
if (!nodeTabMap[z]) {
nodeTabMap[z] = {};
}
nodeTabMap[z][node.id] = node;
var oldZ = node.z;
allNodes.moveNode(node,z);
var nl = nodeLinks[node.id];
if (nl) {
nl.in.forEach(function(l) {
var idx = linkTabMap[node.z].indexOf(l);
var idx = linkTabMap[oldZ].indexOf(l);
if (idx != -1) {
linkTabMap[node.z].splice(idx, 1);
linkTabMap[oldZ].splice(idx, 1);
}
if ((l.source.z === z) && linkTabMap[z]) {
linkTabMap[z].push(l);
}
});
nl.out.forEach(function(l) {
var idx = linkTabMap[node.z].indexOf(l);
var idx = linkTabMap[oldZ].indexOf(l);
if (idx != -1) {
linkTabMap[node.z].splice(idx, 1);
linkTabMap[oldZ].splice(idx, 1);
}
if ((l.target.z === z) && linkTabMap[z]) {
linkTabMap[z].push(l);
}
});
}
node.z = z;
RED.events.emit("nodes:change",node);
}
function moveGroupToTab(group, z) {
@ -482,7 +781,7 @@ RED.nodes = (function() {
function addWorkspace(ws,targetIndex) {
workspaces[ws.id] = ws;
nodeTabMap[ws.id] = {};
allNodes.addTab(ws.id);
linkTabMap[ws.id] = [];
ws._def = RED.nodes.getType('tab');
@ -506,21 +805,16 @@ RED.nodes = (function() {
var removedGroups = [];
if (ws) {
delete workspaces[id];
delete nodeTabMap[id];
allNodes.removeTab(id);
delete linkTabMap[id];
workspacesOrder.splice(workspacesOrder.indexOf(id),1);
var i;
var node;
// TODO: this should use nodeTabMap
for (i in nodes) {
if (nodes.hasOwnProperty(i)) {
node = nodes[i];
if (node.z == id) {
removedNodes.push(node);
}
}
if (allNodes.hasTab(id)) {
removedNodes = allNodes.getNodes(id).slice()
}
for(i in configNodes) {
for (i in configNodes) {
if (configNodes.hasOwnProperty(i)) {
node = configNodes[i];
if (node.z == id) {
@ -572,7 +866,7 @@ RED.nodes = (function() {
sf.name = subflowName;
}
subflows[sf.id] = sf;
nodeTabMap[sf.id] = {};
allNodes.addTab(sf.id);
linkTabMap[sf.id] = [];
RED.nodes.registerType("subflow:"+sf.id, {
@ -591,18 +885,18 @@ RED.nodes = (function() {
inputLabels: function(i) { return sf.inputLabels?sf.inputLabels[i]:null },
outputLabels: function(i) { return sf.outputLabels?sf.outputLabels[i]:null },
oneditprepare: function() {
RED.subflow.buildEditForm("subflow",this);
RED.subflow.buildPropertiesForm(this);
if (this.type !== 'subflow') {
// A subflow instance node
RED.subflow.buildEditForm("subflow",this);
} else {
// A subflow template node
RED.subflow.buildEditForm("subflow-template", this);
}
},
oneditresize: function(size) {
// var rows = $(".dialog-form>div:not(.node-input-env-container-row)");
var height = size.height;
// for (var i=0; i<rows.size(); i++) {
// height -= $(rows[i]).outerHeight(true);
// }
// var editorRow = $("#dialog-form>div.node-input-env-container-row");
// height -= (parseInt(editorRow.css("marginTop"))+parseInt(editorRow.css("marginBottom")));
$("ol.red-ui-editor-subflow-env-list").editableList('height',height);
if (this.type === 'subflow') {
$("#node-input-env-container").editableList('height',size.height - 80);
}
},
set:{
module: "node-red"
@ -618,27 +912,24 @@ RED.nodes = (function() {
function removeSubflow(sf) {
if (subflows[sf.id]) {
delete subflows[sf.id];
delete nodeTabMap[sf.id];
allNodes.removeTab(sf.id);
registry.removeNodeType("subflow:"+sf.id);
RED.events.emit("subflows:remove",sf);
}
}
function subflowContains(sfid,nodeid) {
for (var i in nodes) {
if (nodes.hasOwnProperty(i)) {
var node = nodes[i];
if (node.z === sfid) {
var m = /^subflow:(.+)$/.exec(node.type);
if (m) {
if (m[1] === nodeid) {
return true;
} else {
var result = subflowContains(m[1],nodeid);
if (result) {
return true;
}
}
var sfNodes = allNodes.getNodes(sfid);
for (var i = 0; i<sfNodes.length; i++) {
var node = sfNodes[i];
var m = /^subflow:(.+)$/.exec(node.type);
if (m) {
if (m[1] === nodeid) {
return true;
} else {
var result = subflowContains(m[1],nodeid);
if (result) {
return true;
}
}
}
@ -681,7 +972,13 @@ RED.nodes = (function() {
}
function convertWorkspace(n) {
function convertWorkspace(n,opts) {
var exportCreds = true;
if (opts) {
if (opts.hasOwnProperty("credentials")) {
exportCreds = opts.credentials;
}
}
var node = {};
node.id = n.id;
node.type = n.type;
@ -690,6 +987,23 @@ RED.nodes = (function() {
node[d] = n[d];
}
}
if (exportCreds) {
var credentialSet = {};
if (n.credentials) {
for (var tabCred in n.credentials) {
if (n.credentials.hasOwnProperty(tabCred)) {
if (!n.credentials._ ||
n.credentials["has_"+tabCred] != n.credentials._["has_"+tabCred] ||
(n.credentials["has_"+tabCred] && n.credentials[tabCred])) {
credentialSet[tabCred] = n.credentials[tabCred];
}
}
}
if (Object.keys(credentialSet).length > 0) {
node.credentials = credentialSet;
}
}
}
return node;
}
/**
@ -710,7 +1024,7 @@ RED.nodes = (function() {
}
if (n.type === 'tab') {
return convertWorkspace(n);
return convertWorkspace(n, { credentials: exportCreds });
}
var node = {};
node.id = n.id;
@ -739,8 +1053,10 @@ RED.nodes = (function() {
}
if (exportCreds) {
var credentialSet = {};
if (/^subflow:/.test(node.type) && n.credentials) {
// A subflow instance node can have arbitrary creds
if ((/^subflow:/.test(node.type) ||
(node.type === "group")) &&
n.credentials) {
// A subflow instance/group node can have arbitrary creds
for (var sfCred in n.credentials) {
if (n.credentials.hasOwnProperty(sfCred)) {
if (!n.credentials._ ||
@ -824,8 +1140,8 @@ RED.nodes = (function() {
}
}
if ((!n._def.defaults || !n._def.defaults.hasOwnProperty("l")) && n.hasOwnProperty('l')) {
var isLink = /^link (in|out)$/.test(node.type);
if (isLink == n.l) {
var showLabel = n._def.hasOwnProperty("showLabel")?n._def.showLabel:true;
if (showLabel != n.l) {
node.l = n.l;
}
}
@ -934,11 +1250,15 @@ RED.nodes = (function() {
function createExportableSubflow(id) {
var sf = getSubflow(id);
var nodeSet = [sf];
var sfNodeIds = Object.keys(nodeTabMap[sf.id]||{});
for (var i=0, l=sfNodeIds.length; i<l; i++) {
nodeSet.push(nodeTabMap[sf.id][sfNodeIds[i]]);
var nodeSet;
var sfNodes = allNodes.getNodes(sf.id);
if (sfNodes) {
nodeSet = sfNodes.slice();
nodeSet.unshift(sf);
} else {
nodeSet = [sf];
}
console.log(nodeSet);
return createExportableNodeSet(nodeSet);
}
/**
@ -965,12 +1285,9 @@ RED.nodes = (function() {
if (!exportedSubflows[subflowId]) {
exportedSubflows[subflowId] = true;
var subflow = getSubflow(subflowId);
var subflowSet = [subflow];
RED.nodes.eachNode(function(n) {
if (n.z == subflowId) {
subflowSet.push(n);
}
});
var subflowSet = allNodes.getNodes(subflowId).slice();
subflowSet.unshift(subflow);
RED.nodes.eachConfig(function(n) {
if (n.z == subflowId) {
subflowSet.push(n);
@ -1030,7 +1347,7 @@ RED.nodes = (function() {
var i;
for (i=0;i<workspacesOrder.length;i++) {
if (workspaces[workspacesOrder[i]].type == "tab") {
nns.push(convertWorkspace(workspaces[workspacesOrder[i]]));
nns.push(convertWorkspace(workspaces[workspacesOrder[i]], opts));
}
}
for (i in subflows) {
@ -1048,11 +1365,9 @@ RED.nodes = (function() {
nns.push(convertNode(configNodes[i], opts));
}
}
for (i in nodes) {
if (nodes.hasOwnProperty(i)) {
nns.push(convertNode(nodes[i], opts));
}
}
RED.nodes.eachNode(function(n) {
nns.push(convertNode(n, opts));
})
return nns;
}
@ -1149,7 +1464,7 @@ RED.nodes = (function() {
var nodeZ = n.z || "__global__";
imported.zMap[nodeZ] = imported.zMap[nodeZ] || [];
imported.zMap[nodeZ].push(n)
if (nodes[n.id] || configNodes[n.id] || workspaces[n.id] || subflows[n.id] || groups[n.id]) {
if (allNodes.hasNode(n.id) || configNodes[n.id] || workspaces[n.id] || subflows[n.id] || groups[n.id]) {
imported.conflicted[n.id] = n;
}
})
@ -1157,7 +1472,6 @@ RED.nodes = (function() {
}
/**
* Replace the provided nodes.
* This must contain complete Subflow defs or complete Flow Tabs.
@ -1316,7 +1630,7 @@ RED.nodes = (function() {
if (!options.generateIds) {
if (!options.importMap[id]) {
// No conflict resolution for this node
var existing = nodes[id] || configNodes[id] || workspaces[id] || subflows[id] || groups[id];
var existing = allNodes.getNode(id) || configNodes[id] || workspaces[id] || subflows[id] || groups[id];
if (existing) {
existingNodes.push({existing:existing, imported:n});
}
@ -1387,7 +1701,8 @@ RED.nodes = (function() {
type: "tab",
disabled: false,
label: RED._("clipboard.recoveredNodes"),
info: RED._("clipboard.recoveredNodesInfo")
info: RED._("clipboard.recoveredNodesInfo"),
env: []
}
addWorkspace(recoveryWorkspace);
RED.workspaces.add(recoveryWorkspace);
@ -1518,7 +1833,7 @@ RED.nodes = (function() {
// Add a tab if there isn't one there already
if (defaultWorkspace == null) {
defaultWorkspace = { type:"tab", id:getID(), disabled: false, info:"", label:RED._('workspace.defaultName',{number:1})};
defaultWorkspace = { type:"tab", id:getID(), disabled: false, info:"", label:RED._('workspace.defaultName',{number:1}), env:[]};
addWorkspace(defaultWorkspace);
RED.workspaces.add(defaultWorkspace);
new_workspaces.push(defaultWorkspace);
@ -1979,32 +2294,9 @@ RED.nodes = (function() {
// TODO: supports filter.z|type
function filterNodes(filter) {
var result = [];
var searchSet = null;
var doZFilter = false;
if (filter.hasOwnProperty("z")) {
if (nodeTabMap.hasOwnProperty(filter.z)) {
searchSet = Object.keys(nodeTabMap[filter.z]);
} else {
doZFilter = true;
}
}
if (searchSet === null) {
searchSet = Object.keys(nodes);
}
for (var n=0;n<searchSet.length;n++) {
var node = nodes[searchSet[n]];
if (filter.hasOwnProperty("type") && node.type !== filter.type) {
continue;
}
if (doZFilter && node.z !== filter.z) {
continue;
}
result.push(node);
}
return result;
return allNodes.filterNodes(filter);
}
function filterLinks(filter) {
var result = [];
var candidateLinks = [];
@ -2092,9 +2384,7 @@ RED.nodes = (function() {
}
function clear() {
nodes = {};
links = [];
nodeTabMap = {};
linkTabMap = {};
nodeLinks = {};
configNodes = {};
@ -2114,6 +2404,8 @@ RED.nodes = (function() {
initialLoad = null;
workspaces = {};
allNodes.clear();
RED.nodes.dirty(false);
RED.view.redraw(true, true);
RED.palette.refresh();
@ -2186,10 +2478,7 @@ RED.nodes = (function() {
if (configNodes.hasOwnProperty(n.id)) {
delete configNodes[n.id];
} else {
delete nodes[n.id];
if (nodeTabMap[n.z]) {
delete nodeTabMap[n.z][n.id];
}
allNodes.removeNode(n);
}
reimportList.push(convertNode(n));
RED.events.emit('nodes:remove',n);
@ -2246,6 +2535,13 @@ RED.nodes = (function() {
remove: removeNode,
clear: clear,
moveNodesForwards: moveNodesForwards,
moveNodesBackwards: moveNodesBackwards,
moveNodesToFront: moveNodesToFront,
moveNodesToBack: moveNodesToBack,
getNodeOrder: getNodeOrder,
setNodeOrder: setNodeOrder,
moveNodeToTab: moveNodeToTab,
addLink: addLink,
@ -2265,16 +2561,10 @@ RED.nodes = (function() {
addGroup: addGroup,
removeGroup: removeGroup,
group: function(id) { return groups[id] },
groups: function(z) { return groupsByZ[z]||[] },
groups: function(z) { return groupsByZ[z]?groupsByZ[z].slice():[] },
eachNode: function(cb) {
for (var id in nodes) {
if (nodes.hasOwnProperty(id)) {
if (cb(nodes[id]) === false) {
break;
}
}
}
allNodes.eachNode(cb);
},
eachLink: function(cb) {
for (var l=0;l<links.length;l++) {

View File

@ -201,6 +201,7 @@ var RED = (function() {
RED.projects.refresh(function(activeProject) {
loadFlows(function() {
RED.sidebar.info.refresh()
var showProjectWelcome = false;
if (!activeProject) {
// Projects enabled but no active project
RED.menu.setDisabled('menu-item-projects-open',true);
@ -208,10 +209,10 @@ var RED = (function() {
if (activeProject === false) {
// User previously decline the migration to projects.
} else { // null/undefined
RED.projects.showStartup();
showProjectWelcome = true;
}
}
completeLoad();
completeLoad(showProjectWelcome);
});
});
} else {
@ -251,6 +252,9 @@ var RED = (function() {
if (/^#flow\/.+$/.test(currentHash)) {
RED.workspaces.show(currentHash.substring(6),true);
}
if (RED.workspaces.active() === 0 && RED.workspaces.count() > 0) {
RED.workspaces.show(RED.nodes.getWorkspaceOrder()[0])
}
} catch(err) {
console.warn(err);
RED.notify(
@ -267,7 +271,7 @@ var RED = (function() {
});
}
function completeLoad() {
function completeLoad(showProjectWelcome) {
var persistentNotifications = {};
RED.comms.subscribe("notification/#",function(topic,msg) {
var parts = topic.split("/");
@ -477,8 +481,17 @@ var RED = (function() {
RED.nodes.addNodeSet(m);
addedTypes = addedTypes.concat(m.types);
RED.i18n.loadNodeCatalog(id, function() {
$.get('nodes/'+id, function(data) {
appendNodeConfig(data);
var lang = localStorage.getItem("editor-language")||RED.i18n.detectLanguage();
$.ajax({
headers: {
"Accept":"text/html",
"Accept-Language": lang
},
cache: false,
url: 'nodes/'+id,
success: function(data) {
appendNodeConfig(data);
}
});
});
});
@ -505,10 +518,19 @@ var RED = (function() {
typeList = "<ul><li>"+msg.types.map(RED.utils.sanitize).join("</li><li>")+"</li></ul>";
RED.notify(RED._("palette.event.nodeEnabled", {count:msg.types.length})+typeList,"success");
} else {
$.get('nodes/'+msg.id, function(data) {
appendNodeConfig(data);
typeList = "<ul><li>"+msg.types.map(RED.utils.sanitize).join("</li><li>")+"</li></ul>";
RED.notify(RED._("palette.event.nodeAdded", {count:msg.types.length})+typeList,"success");
var lang = localStorage.getItem("editor-language")||RED.i18n.detectLanguage();
$.ajax({
headers: {
"Accept":"text/html",
"Accept-Language": lang
},
cache: false,
url: 'nodes/'+msg.id,
success: function(data) {
appendNodeConfig(data);
typeList = "<ul><li>"+msg.types.map(RED.utils.sanitize).join("</li><li>")+"</li></ul>";
RED.notify(RED._("palette.event.nodeAdded", {count:msg.types.length})+typeList,"success");
}
});
}
}
@ -535,19 +557,24 @@ var RED = (function() {
setTimeout(function() {
loader.end();
checkFirstRun(function() {
if (showProjectWelcome) {
RED.projects.showStartup();
}
});
},100);
}
function showAbout() {
$.get('red/about', function(data) {
// data will be strictly markdown. Any HTML should be escaped.
data = RED.utils.sanitize(data);
var aboutHeader = '<div style="text-align:center;">'+
'<img width="50px" src="red/images/node-red-icon.svg" />'+
'</div>';
RED.sidebar.help.set(aboutHeader+RED.utils.renderMarkdown(data));
});
function checkFirstRun(done) {
if (RED.settings.theme("tours") === false) {
done();
return;
}
if (!RED.settings.get("editor.view.view-show-welcome-tours", true)) {
done();
return;
}
RED.actions.invoke("core:show-welcome-tour", RED.settings.get("editor.tours.welcome"), done);
}
function buildMainMenu() {
@ -559,6 +586,22 @@ var RED = (function() {
{id:"menu-item-projects-settings",label:RED._("menu.label.projects-settings"),disabled:false,onselect:"core:show-project-settings"}
]});
}
menuOptions.push({id:"menu-item-edit-menu", label:"Edit", options: [
{id: "menu-item-edit-undo", label:RED._("keyboard.undoChange"), disabled: true, onselect: "core:undo"},
{id: "menu-item-edit-redo", label:RED._("keyboard.redoChange"), disabled: true, onselect: "core:redo"},
null,
{id: "menu-item-edit-cut", label:RED._("keyboard.cutNode"), onselect: "core:cut-selection-to-internal-clipboard"},
{id: "menu-item-edit-copy", label:RED._("keyboard.copyNode"), onselect: "core:copy-selection-to-internal-clipboard"},
{id: "menu-item-edit-paste", label:RED._("keyboard.pasteNode"), disabled: true, onselect: "core:paste-from-internal-clipboard"},
null,
{id: "menu-item-edit-copy-group-style", label:RED._("keyboard.copyGroupStyle"), onselect: "core:copy-group-style"},
{id: "menu-item-edit-paste-group-style", label:RED._("keyboard.pasteGroupStyle"), disabled: true, onselect: "core:paste-group-style"},
null,
{id: "menu-item-edit-select-all", label:RED._("keyboard.selectAll"), onselect: "core:select-all-nodes"},
{id: "menu-item-edit-select-connected", label:RED._("keyboard.selectAllConnected"), onselect: "core:select-connected-nodes"},
{id: "menu-item-edit-select-none", label:RED._("keyboard.selectNone"), onselect: "core:select-none"}
]});
menuOptions.push({id:"menu-item-view-menu",label:RED._("menu.label.view.view"),options:[
{id:"menu-item-palette",label:RED._("menu.label.palette.show"),toggle:true,onselect:"core:toggle-palette", selected: true},
{id:"menu-item-sidebar",label:RED._("menu.label.sidebar.show"),toggle:true,onselect:"core:toggle-sidebar", selected: true},
@ -566,6 +609,25 @@ var RED = (function() {
{id:"menu-item-action-list",label:RED._("keyboard.actionList"),onselect:"core:show-action-list"},
null
]});
menuOptions.push({id:"menu-item-arrange-menu", label:RED._("menu.label.arrange"), options: [
{id: "menu-item-view-tools-move-to-back", label:RED._("menu.label.moveToBack"), disabled: true, onselect: "core:move-selection-to-back"},
{id: "menu-item-view-tools-move-to-front", label:RED._("menu.label.moveToFront"), disabled: true, onselect: "core:move-selection-to-front"},
{id: "menu-item-view-tools-move-backwards", label:RED._("menu.label.moveBackwards"), disabled: true, onselect: "core:move-selection-backwards"},
{id: "menu-item-view-tools-move-forwards", label:RED._("menu.label.moveForwards"), disabled: true, onselect: "core:move-selection-forwards"},
null,
{id: "menu-item-view-tools-align-left", label:RED._("menu.label.alignLeft"), disabled: true, onselect: "core:align-selection-to-left"},
{id: "menu-item-view-tools-align-center", label:RED._("menu.label.alignCenter"), disabled: true, onselect: "core:align-selection-to-center"},
{id: "menu-item-view-tools-align-right", label:RED._("menu.label.alignRight"), disabled: true, onselect: "core:align-selection-to-right"},
null,
{id: "menu-item-view-tools-align-top", label:RED._("menu.label.alignTop"), disabled: true, onselect: "core:align-selection-to-top"},
{id: "menu-item-view-tools-align-middle", label:RED._("menu.label.alignMiddle"), disabled: true, onselect: "core:align-selection-to-middle"},
{id: "menu-item-view-tools-align-bottom", label:RED._("menu.label.alignBottom"), disabled: true, onselect: "core:align-selection-to-bottom"},
null,
{id: "menu-item-view-tools-distribute-horizontally", label:RED._("menu.label.distributeHorizontally"), disabled: true, onselect: "core:distribute-selection-horizontally"},
{id: "menu-item-view-tools-distribute-veritcally", label:RED._("menu.label.distributeVertically"), disabled: true, onselect: "core:distribute-selection-vertically"}
]});
menuOptions.push(null);
if (RED.settings.theme("menu.menu-item-import-library", true)) {
menuOptions.push({id: "menu-item-import", label: RED._("menu.label.import"), onselect: "core:show-import-dialog"});
@ -626,7 +688,6 @@ var RED = (function() {
RED.user.init();
RED.notifications.init();
RED.library.init();
RED.keyboard.init();
RED.palette.init();
RED.eventLog.init();
@ -655,16 +716,13 @@ var RED = (function() {
RED.deploy.init(RED.settings.theme("deployButton",null));
buildMainMenu();
RED.keyboard.init(buildMainMenu);
RED.nodes.init();
RED.comms.connect();
$("#red-ui-main-container").show();
RED.actions.add("core:show-about", showAbout);
loadPluginList();
}

View File

@ -19,7 +19,6 @@ RED.settings = (function () {
var loadedSettings = {};
var userSettings = {};
var settingsDirty = false;
var pendingSave;
var hasLocalStorage = function () {
@ -220,6 +219,16 @@ RED.settings = (function () {
return defaultValue;
}
}
function getLocal(key) {
return localStorage.getItem(key)
}
function setLocal(key, value) {
localStorage.setItem(key, value);
}
function removeLocal(key) {
localStorage.removeItem(key)
}
return {
init: init,
@ -228,6 +237,9 @@ RED.settings = (function () {
set: set,
get: get,
remove: remove,
theme: theme
theme: theme,
setLocal: setLocal,
getLocal: getLocal,
removeLocal: removeLocal
}
})();

View File

@ -4,6 +4,12 @@ RED.actions = (function() {
}
function addAction(name,handler) {
if (typeof handler !== 'function') {
throw new Error("Action handler not a function");
}
if (actions[name]) {
throw new Error("Cannot override existing action");
}
actions[name] = handler;
}
function removeAction(name) {
@ -12,9 +18,11 @@ RED.actions = (function() {
function getAction(name) {
return actions[name];
}
function invokeAction(name,args) {
function invokeAction() {
var args = Array.prototype.slice.call(arguments);
var name = args.shift();
if (actions.hasOwnProperty(name)) {
actions[name](args);
actions[name].apply(null, args);
}
}
function listActions() {

View File

@ -498,6 +498,13 @@ RED.clipboard = (function() {
$("#red-ui-clipboard-dialog-import-text").on("keyup", validateImport);
$("#red-ui-clipboard-dialog-import-text").on('paste',function() { setTimeout(validateImport,10)});
if (RED.workspaces.active() === 0) {
$("#red-ui-clipboard-dialog-import-opt-current").addClass('disabled').removeClass("selected");
$("#red-ui-clipboard-dialog-import-opt-new").addClass("selected");
} else {
$("#red-ui-clipboard-dialog-import-opt-current").removeClass('disabled').addClass("selected");
$("#red-ui-clipboard-dialog-import-opt-new").removeClass("selected");
}
$("#red-ui-clipboard-dialog-import-opt > a").on("click", function(evt) {
evt.preventDefault();
if ($(this).hasClass('disabled') || $(this).hasClass('selected')) {
@ -611,9 +618,6 @@ RED.clipboard = (function() {
activeLibraries[tabId] = browser;
})
$("#red-ui-clipboard-dialog-tab-library-name").on("keyup", validateExportFilename);
$("#red-ui-clipboard-dialog-tab-library-name").on('paste',function() { setTimeout(validateExportFilename,10)});
$("#red-ui-clipboard-dialog-export").button("enable");
@ -636,7 +640,6 @@ RED.clipboard = (function() {
label: RED._("editor.types.json")
});
var previewList = $("#red-ui-clipboard-dialog-export-tab-clipboard-preview-list").css({position:"absolute",top:0,right:0,bottom:0,left:0}).treeList({
data: []
})
@ -738,16 +741,22 @@ RED.clipboard = (function() {
$("#red-ui-clipboard-dialog-export").hide();
$("#red-ui-clipboard-dialog-import-conflict").hide();
var selection = RED.workspaces.selection();
if (selection.length > 0) {
$("#red-ui-clipboard-dialog-export-rng-selected").trigger("click");
if (RED.workspaces.active() === 0) {
$("#red-ui-clipboard-dialog-export-rng-selected").addClass('disabled').removeClass('selected');
$("#red-ui-clipboard-dialog-export-rng-flow").addClass('disabled').removeClass('selected');
$("#red-ui-clipboard-dialog-export-rng-full").trigger("click");
} else {
selection = RED.view.selection();
if (selection.nodes) {
var selection = RED.workspaces.selection();
if (selection.length > 0) {
$("#red-ui-clipboard-dialog-export-rng-selected").trigger("click");
} else {
$("#red-ui-clipboard-dialog-export-rng-selected").addClass('disabled').removeClass('selected');
$("#red-ui-clipboard-dialog-export-rng-flow").trigger("click");
selection = RED.view.selection();
if (selection.nodes) {
$("#red-ui-clipboard-dialog-export-rng-selected").trigger("click");
} else {
$("#red-ui-clipboard-dialog-export-rng-selected").addClass('disabled').removeClass('selected');
$("#red-ui-clipboard-dialog-export-rng-flow").trigger("click");
}
}
}
if (format === "red-ui-clipboard-dialog-export-fmt-full") {

View File

@ -0,0 +1,115 @@
(function($) {
/**
* Attach to an <input type="text"> to provide auto-complete
*
* $("#node-red-text").autoComplete({
* search: function(value) { return ['a','b','c'] }
* })
*
* options:
*
* search : function(value, [done])
* A function that is passed the current contents of the input whenever
* it changes.
* The function must either return auto-complete options, or pass them
* to the optional 'done' parameter.
* If the function signature includes 'done', it must be used
*
* The auto-complete options should be an array of objects in the form:
* {
* value: String : the value to insert if selected
* label: String|DOM Element : the label to display in the dropdown.
* }
*
*/
$.widget( "nodered.autoComplete", {
_create: function() {
var that = this;
this.completionMenuShown = false;
this.options.search = this.options.search || function() { return [] }
this.element.addClass("red-ui-autoComplete")
this.element.on("keydown.red-ui-autoComplete", function(evt) {
if ((evt.keyCode === 13 || evt.keyCode === 9) && that.completionMenuShown) {
var opts = that.menu.options();
that.element.val(opts[0].value);
that.menu.hide();
evt.preventDefault();
}
})
this.element.on("keyup.red-ui-autoComplete", function(evt) {
if (evt.keyCode === 13 || evt.keyCode === 9 || evt.keyCode === 27) {
// ENTER / TAB / ESCAPE
return
}
if (evt.keyCode === 8 || evt.keyCode === 46) {
// Delete/Backspace
if (!that.completionMenuShown) {
return;
}
}
that._updateCompletions(this.value);
});
},
_showCompletionMenu: function(completions) {
if (this.completionMenuShown) {
return;
}
this.menu = RED.popover.menu({
tabSelect: true,
width: 300,
maxHeight: 200,
class: "red-ui-autoComplete-container",
options: completions,
onselect: (opt) => { this.element.val(opt.value); this.element.focus() },
onclose: () => { this.completionMenuShown = false; delete this.menu; this.element.focus()}
});
this.menu.show({
target: this.element
})
this.completionMenuShown = true;
},
_updateCompletions: function(val) {
var that = this;
if (val.trim() === "") {
if (this.completionMenuShown) {
this.menu.hide();
}
return;
}
function displayResults(completions,requestId) {
if (requestId && requestId !== that.pendingRequest) {
// This request has been superseded
return
}
if (!completions || completions.length === 0) {
if (that.completionMenuShown) {
that.menu.hide();
}
return
}
if (that.completionMenuShown) {
that.menu.options(completions);
} else {
that._showCompletionMenu(completions);
}
}
if (this.options.search.length === 2) {
var requestId = 1+Math.floor(Math.random()*10000);
this.pendingRequest = requestId;
this.options.search(val,function(completions) { displayResults(completions,requestId);})
} else {
displayResults(this.options.search(val))
}
},
_destroy: function() {
this.element.removeClass("red-ui-autoComplete")
this.element.off("keydown.red-ui-autoComplete")
this.element.off("keyup.red-ui-autoComplete")
if (this.completionMenuShown) {
this.menu.hide();
}
}
});
})(jQuery);

View File

@ -82,12 +82,19 @@ RED.menu = (function() {
linkContent += '<span class="red-ui-menu-label-container"><span class="red-ui-menu-label">'+opt.label+'</span>'+
'<span class="red-ui-menu-sublabel">'+opt.sublabel+'</span></span>'
} else {
linkContent += '<span class="red-ui-menu-label">'+opt.label+'</span>'
linkContent += '<span class="red-ui-menu-label"><span>'+opt.label+'</span></span>'
}
linkContent += '</a>';
var link = $(linkContent).appendTo(item);
opt.link = link;
if (typeof opt.onselect === 'string') {
var shortcut = RED.keyboard.getShortcut(opt.onselect);
if (shortcut && shortcut.key) {
opt.shortcutSpan = $('<span class="red-ui-popover-key">'+RED.keyboard.formatKey(shortcut.key, true)+'</span>').appendTo(link.find(".red-ui-menu-label"));
}
}
menuItems[opt.id] = opt;
@ -276,6 +283,22 @@ RED.menu = (function() {
}
}
function refreshShortcuts() {
for (var id in menuItems) {
if (menuItems.hasOwnProperty(id)) {
var opt = menuItems[id];
if (typeof opt.onselect === "string" && opt.shortcutSpan) {
opt.shortcutSpan.remove();
delete opt.shortcutSpan;
var shortcut = RED.keyboard.getShortcut(opt.onselect);
if (shortcut && shortcut.key) {
opt.shortcutSpan = $('<span class="red-ui-popover-key">'+RED.keyboard.formatKey(shortcut.key, true)+'</span>').appendTo(opt.link.find(".red-ui-menu-label"));
}
}
}
}
}
return {
init: createMenu,
setSelected: setSelected,
@ -284,6 +307,7 @@ RED.menu = (function() {
setDisabled: setDisabled,
addItem: addItem,
removeItem: removeItem,
setAction: setAction
setAction: setAction,
refreshShortcuts: refreshShortcuts
}
})();

View File

@ -13,24 +13,138 @@
* See the License for the specific language governing permissions and
* limitations under the License.
**/
/*
* RED.popover.create(options) - create a popover callout box
* RED.popover.tooltip(target,content, action) - add a tooltip to an element
* RED.popover.menu(options) - create a dropdown menu
* RED.popover.panel(content) - create a dropdown container element
*/
/*
* RED.popover.create(options)
*
* options
* - target : DOM element - the element to target with the popover
* - direction : string - position of the popover relative to target
* 'top', 'right'(default), 'bottom', 'left', 'inset-[top,right,bottom,left]'
* - trigger : string - what triggers the popover to be displayed
* 'hover' - display when hovering the target
* 'click' - display when target is clicked
* 'modal' - hmm not sure, need to find where we use that mode
* - content : string|function - contents of the popover. If a string, handled
* as raw HTML, so take care.
* If a function, can return a String to be added
* as text (not HTML), or a DOM element to append
* - delay : object - sets show/hide delays after mouseover/out events
* { show: 750, hide: 50 }
* - autoClose : number - delay before closing the popover in some cases
* if trigger is click - delay after mouseout
* else if trigger not hover/modal - delay after showing
* - width : number - width of popover, default 'auto'
* - maxWidth : number - max width of popover, default 'auto'
* - size : string - scale of popover. 'default', 'small'
* - offset : number - px offset from target
* - tooltip : boolean - if true, clicking on popover closes it
* - class : string - optional css class to apply to popover
* - interactive : if trigger is 'hover' and this is set to true, allow the mouse
* to move over the popover without hiding it.
*
* Returns the popover object with the following properties/functions:
* properties:
* - element : DOM element - the popover dom element
* functions:
* - setContent(content) - change the popover content. This only works if the
* popover is not currently displayed. It does not
* change the content of a visible popover.
* - open(instant) - show the popover. If 'instant' is true, don't fade in
* - close(instant) - hide the popover. If 'instant' is true, don't fade out
* - move(options) - move the popover. The options parameter can take many
* of the options detailed above including:
* target,direction,content,width,offset
* Other settings probably won't work because we haven't needed to change them
*/
/*
* RED.popover.tooltip(target,content, action)
*
* - target : DOM element - the element to apply the tooltip to
* - content : string - the text of the tooltip
* - action : string - *optional* the name of an Action this tooltip is tied to
* For example, it 'target' is a button that triggers a particular action.
* The tooltip will include the keyboard shortcut for the action
* if one is defined
*
*/
/*
* RED.popover.menu(options)
*
* options
* - options : array - list of menu options - see below for format
* - width : number - width of the menu. Default: 'auto'
* - class : string - class to apply to the menu container
* - maxHeight : number - maximum height of menu before scrolling items. Default: none
* - onselect : function(item) - called when a menu item is selected, if that item doesn't
* have its own onselect function
* - onclose : function(cancelled) - called when the menu is closed
* - disposeOnClose : boolean - by default, the menu is discarded when it closes
* and mustbe rebuilt to redisplay. Setting this to 'false'
* keeps the menu on the DOM so it can be shown again.
*
* Menu Options array:
* [
* label : string|DOM element - the label of the item. Can be custom DOM element
* onselect : function - called when the item is selected
* ]
*
* Returns the menu object with the following functions:
*
* - options([menuItems]) - if menuItems is undefined, returns the current items.
* otherwise, sets the current menu items
* - show(opts) - shows the menu. `opts` is an object of options. See RED.popover.panel.show(opts)
* for the full list of options. In most scenarios, this just needs:
* - target : DOM element - the element to display the menu below
* - hide(cancelled) - hide the menu
*/
/*
* RED.popover.panel(content)
* Create a UI panel that can be displayed relative to any target element.
* Handles auto-closing when mouse clicks outside the panel
*
* - 'content' - DOM element to display in the panel
*
* Returns the panel object with the following functions:
*
* properties:
* - container : DOM element - the panel element
*
* functions:
* - show(opts) - show the panel.
* opts:
* - onclose : function - called when the panel closes
* - closeButton : DOM element - if the panel is closeable by a click of a button,
* by providing a reference to it here, we can
* handle the events properly to hide the panel
* - target : DOM element - the element to display the panel relative to
* - align : string - should the panel align to the left or right edge of target
* default: 'right'
* - offset : Array - px offset to apply from the target. [width, height]
* - dispose : boolean - whether the panel should be removed from DOM when hidden
* default: true
* - hide(dispose) - hide the panel.
*/
RED.popover = (function() {
var deltaSizes = {
"default": {
top: 10,
topTop: 30,
leftRight: 17,
leftLeft: 25,
leftBottom: 8,
leftTop: 11
x: 12,
y: 12
},
"small": {
top: 6,
topTop: 20,
leftRight: 8,
leftLeft: 26,
leftBottom: 8,
leftTop: 9
x:8,
y:8
}
}
function createPopover(options) {
@ -41,7 +155,9 @@ RED.popover = (function() {
var delay = options.delay || { show: 750, hide: 50 };
var autoClose = options.autoClose;
var width = options.width||"auto";
var maxWidth = options.maxWidth;
var size = options.size||"default";
var popupOffset = options.offset || 0;
if (!deltaSizes[size]) {
throw new Error("Invalid RED.popover size value:",size);
}
@ -49,6 +165,8 @@ RED.popover = (function() {
var timer = null;
var active;
var div;
var contentDiv;
var currentStyle;
var openPopup = function(instant) {
if (active) {
@ -58,6 +176,10 @@ RED.popover = (function() {
return;
}
div = $('<div class="red-ui-popover"></div>');
if (options.class) {
div.addClass(options.class);
}
contentDiv = $('<div class="red-ui-popover-content">').appendTo(div);
if (size !== "default") {
div.addClass("red-ui-popover-size-"+size);
}
@ -67,71 +189,23 @@ RED.popover = (function() {
return;
}
if (typeof result === 'string') {
div.text(result);
contentDiv.text(result);
} else {
div.append(result);
contentDiv.append(result);
}
} else {
div.html(content);
}
if (width !== "auto") {
div.width(width);
contentDiv.html(content);
}
div.appendTo("body");
var targetPos = target.offset();
var targetWidth = target.outerWidth();
var targetHeight = target.outerHeight();
var divHeight = div.height();
var divWidth = div.width();
var paddingRight = 10;
movePopup({target,direction,width,maxWidth});
var viewportTop = $(window).scrollTop();
var viewportLeft = $(window).scrollLeft();
var viewportBottom = viewportTop + $(window).height();
var viewportRight = viewportLeft + $(window).width();
var top = 0;
var left = 0;
var d = direction;
if (d === 'right') {
top = targetPos.top+targetHeight/2-divHeight/2-deltaSizes[size].top;
left = targetPos.left+targetWidth+deltaSizes[size].leftRight;
} else if (d === 'left') {
top = targetPos.top+targetHeight/2-divHeight/2-deltaSizes[size].top;
left = targetPos.left-deltaSizes[size].leftLeft-divWidth;
} else if (d === 'bottom') {
top = targetPos.top+targetHeight+deltaSizes[size].top;
left = targetPos.left+targetWidth/2-divWidth/2 - deltaSizes[size].leftBottom;
if (left < 0) {
d = "right";
top = targetPos.top+targetHeight/2-divHeight/2-deltaSizes[size].top;
left = targetPos.left+targetWidth+deltaSizes[size].leftRight;
} else if (left+divWidth+paddingRight > viewportRight) {
d = "left";
top = targetPos.top+targetHeight/2-divHeight/2-deltaSizes[size].top;
left = targetPos.left-deltaSizes[size].leftLeft-divWidth;
if (top+divHeight+targetHeight/2 + 5 > viewportBottom) {
top -= (top+divHeight+targetHeight/2 - viewportBottom + 5)
}
} else if (top+divHeight > viewportBottom) {
d = 'top';
top = targetPos.top-deltaSizes[size].topTop-divHeight;
left = targetPos.left+targetWidth/2-divWidth/2 - deltaSizes[size].leftTop;
}
} else if (d === 'top') {
top = targetPos.top-deltaSizes[size].topTop-divHeight;
left = targetPos.left+targetWidth/2-divWidth/2 - deltaSizes[size].leftTop;
if (top < 0) {
d = 'bottom';
top = targetPos.top+targetHeight+deltaSizes[size].top;
left = targetPos.left+targetWidth/2-divWidth/2 - deltaSizes[size].leftBottom;
}
}
div.addClass('red-ui-popover-'+d).css({top: top, left: left});
if (existingPopover) {
existingPopover.close(true);
}
target.data("red-ui-popover",res)
if (options.trigger !== 'manual') {
target.data("red-ui-popover",res)
}
if (options.tooltip) {
div.on("mousedown", function(evt) {
closePopup(true);
@ -161,6 +235,104 @@ RED.popover = (function() {
}
}
}
var movePopup = function(options) {
target = options.target || target;
direction = options.direction || direction || "right";
popupOffset = options.offset || popupOffset;
var transition = options.transition;
var width = options.width||"auto";
div.width(width);
if (options.maxWidth) {
div.css("max-width",options.maxWidth)
} else {
div.css("max-width", 'auto');
}
var targetPos = target[0].getBoundingClientRect();
var targetHeight = targetPos.height;
var targetWidth = targetPos.width;
var divHeight = div.outerHeight();
var divWidth = div.outerWidth();
var paddingRight = 10;
var viewportTop = $(window).scrollTop();
var viewportLeft = $(window).scrollLeft();
var viewportBottom = viewportTop + $(window).height();
var viewportRight = viewportLeft + $(window).width();
var top = 0;
var left = 0;
if (direction === 'right') {
top = targetPos.top+targetHeight/2-divHeight/2;
left = targetPos.left+targetWidth+deltaSizes[size].x+popupOffset;
} else if (direction === 'left') {
top = targetPos.top+targetHeight/2-divHeight/2;
left = targetPos.left-deltaSizes[size].x-divWidth-popupOffset;
} else if (direction === 'bottom') {
top = targetPos.top+targetHeight+deltaSizes[size].y+popupOffset;
left = targetPos.left+targetWidth/2-divWidth/2;
if (left < 0) {
direction = "right";
top = targetPos.top+targetHeight/2-divHeight/2;
left = targetPos.left+targetWidth+deltaSizes[size].x+popupOffset;
} else if (left+divWidth+paddingRight > viewportRight) {
direction = "left";
top = targetPos.top+targetHeight/2-divHeight/2;
left = targetPos.left-deltaSizes[size].x-divWidth-popupOffset;
if (top+divHeight+targetHeight/2 + 5 > viewportBottom) {
top -= (top+divHeight+targetHeight/2 - viewportBottom + 5)
}
} else if (top+divHeight > viewportBottom) {
direction = 'top';
top = targetPos.top-deltaSizes[size].y-divHeight-popupOffset;
left = targetPos.left+targetWidth/2-divWidth/2;
}
} else if (direction === 'top') {
top = targetPos.top-deltaSizes[size].y-divHeight-popupOffset;
left = targetPos.left+targetWidth/2-divWidth/2;
if (top < 0) {
direction = 'bottom';
top = targetPos.top+targetHeight+deltaSizes[size].y+popupOffset;
left = targetPos.left+targetWidth/2-divWidth/2;
}
} else if (/inset/.test(direction)) {
top = targetPos.top + targetHeight/2 - divHeight/2;
left = targetPos.left + targetWidth/2 - divWidth/2;
if (/bottom/.test(direction)) {
top = targetPos.top + targetHeight - divHeight-popupOffset;
}
if (/top/.test(direction)) {
top = targetPos.top+popupOffset;
}
if (/left/.test(direction)) {
left = targetPos.left+popupOffset;
}
if (/right/.test(direction)) {
left = targetPos.left + targetWidth - divWidth-popupOffset;
}
}
if (currentStyle) {
div.removeClass(currentStyle);
}
if (transition) {
div.css({
"transition": "0.6s ease",
"transition-property": "top,left,right,bottom"
})
}
currentStyle = 'red-ui-popover-'+direction;
div.addClass(currentStyle).css({top: top, left: left});
if (transition) {
setTimeout(function() {
div.css({
"transition": "none"
});
},600);
}
}
var closePopup = function(instant) {
$(document).off('mousedown.red-ui-popover');
if (!active) {
@ -236,8 +408,10 @@ RED.popover = (function() {
},autoClose);
}
var res = {
get element() { return div },
setContent: function(_content) {
content = _content;
return res;
},
open: function (instant) {
@ -249,6 +423,10 @@ RED.popover = (function() {
active = false;
closePopup(instant);
return res;
},
move: function(options) {
movePopup(options);
return
}
}
return res;
@ -258,18 +436,17 @@ RED.popover = (function() {
return {
create: createPopover,
tooltip: function(target,content, action) {
var label = content;
if (action) {
label = function() {
var label = content;
var label = function() {
var label = content;
if (action) {
var shortcut = RED.keyboard.getShortcut(action);
if (shortcut && shortcut.key) {
label = $('<span>'+content+' <span class="red-ui-popover-key">'+RED.keyboard.formatKey(shortcut.key, true)+'</span></span>');
}
return label;
}
return label;
}
return RED.popover.create({
var popover = RED.popover.create({
tooltip: true,
target:target,
trigger: "hover",
@ -278,6 +455,14 @@ RED.popover = (function() {
content: label,
delay: { show: 750, hide: 50 }
});
popover.setContent = function(newContent) {
content = newContent;
}
popover.setAction = function(newAction) {
action = newAction;
}
return popover;
},
menu: function(options) {
var list = $('<ul class="red-ui-menu"></ul>');
@ -286,20 +471,47 @@ RED.popover = (function() {
}
var menuOptions = options.options || [];
var first;
menuOptions.forEach(function(opt) {
var item = $('<li>').appendTo(list);
var link = $('<a href="#"></a>').text(opt.label).appendTo(item);
link.on("click", function(evt) {
evt.preventDefault();
if (opt.onselect) {
opt.onselect();
}
menu.hide();
})
if (!first) { first = link}
})
var container = RED.popover.panel(list);
if (options.width) {
container.container.width(options.width);
}
if (options.class) {
container.container.addClass(options.class);
}
if (options.maxHeight) {
container.container.css({
"max-height": options.maxHeight,
"overflow-y": 'auto'
})
}
var menu = {
options: function(opts) {
if (opts === undefined) {
return menuOptions
}
menuOptions = opts || [];
list.empty();
menuOptions.forEach(function(opt) {
var item = $('<li>').appendTo(list);
var link = $('<a href="#"></a>').appendTo(item);
if (typeof opt.label == "string") {
link.text(opt.label)
} else if (opt.label){
opt.label.appendTo(link);
}
link.on("click", function(evt) {
evt.preventDefault();
if (opt.onselect) {
opt.onselect();
} else if (options.onselect) {
options.onselect(opt);
}
menu.hide();
})
if (!first) { first = link}
})
},
show: function(opts) {
$(document).on("keydown.red-ui-menu", function(evt) {
var currentItem = list.find(":focus").parent();
@ -333,6 +545,11 @@ RED.popover = (function() {
// ESCAPE
evt.preventDefault();
menu.hide(true);
} else if (evt.keyCode === 9 && options.tabSelect) {
// TAB - with tabSelect enabled
evt.preventDefault();
currentItem.find("a").trigger("click");
}
evt.stopPropagation();
})
@ -352,6 +569,7 @@ RED.popover = (function() {
}
}
}
menu.options(menuOptions);
return menu;
},
panel: function(content) {
@ -380,12 +598,12 @@ RED.popover = (function() {
var pos = target.offset();
var targetWidth = target.width();
var targetHeight = target.height();
var targetHeight = target.outerHeight();
var panelHeight = panel.height();
var panelWidth = panel.width();
var top = (targetHeight+pos.top) + offset[1];
if (top+panelHeight > $(window).height()) {
if (top+panelHeight-$(document).scrollTop() > $(window).height()) {
top -= (top+panelHeight)-$(window).height() + 5;
}
if (top < 0) {

View File

@ -38,6 +38,7 @@ RED.tabs = (function() {
if (options.vertical) {
wrapper.addClass("red-ui-tabs-vertical");
}
if (options.addButton) {
wrapper.addClass("red-ui-tabs-add");
var addButton = $('<div class="red-ui-tab-button red-ui-tabs-add"><a href="#"><i class="fa fa-plus"></i></a></div>').appendTo(wrapper);
@ -75,6 +76,8 @@ RED.tabs = (function() {
});
}
if (options.searchButton) {
// This is soft-deprecated as we don't use this in the core anymore
// We no use the `menu` option to provide a drop-down list of actions
wrapper.addClass("red-ui-tabs-search");
var searchButton = $('<div class="red-ui-tab-button red-ui-tabs-search"><a href="#"><i class="fa fa-list-ul"></i></a></div>').appendTo(wrapper);
searchButton.find('a').on("click", function(evt) {
@ -94,6 +97,50 @@ RED.tabs = (function() {
}
}
if (options.menu) {
wrapper.addClass("red-ui-tabs-menu");
var menuButton = $('<div class="red-ui-tab-button red-ui-tabs-menu"><a href="#"><i class="fa fa-caret-down"></i></a></div>').appendTo(wrapper);
var menuButtonLink = menuButton.find('a')
var menuOpen = false;
var menu;
menuButtonLink.on("click", function(evt) {
evt.stopPropagation();
evt.preventDefault();
if (menuOpen) {
menu.remove();
menuOpen = false;
return;
}
menuOpen = true;
var menuOptions = [];
if (typeof options.searchButton === 'function') {
menuOptions = options.menu()
} else if (Array.isArray(options.menu)) {
menuOptions = options.menu;
}
menu = RED.menu.init({options: menuOptions});
menu.attr("id",options.id+"-menu");
menu.css({
position: "absolute"
})
menu.appendTo("body");
var elementPos = menuButton.offset();
menu.css({
top: (elementPos.top+menuButton.height()-2)+"px",
left: (elementPos.left - menu.width() + menuButton.width())+"px"
})
$(".red-ui-menu.red-ui-menu-dropdown").hide();
$(document).on("click.red-ui-tabmenu", function(evt) {
$(document).off("click.red-ui-tabmenu");
menuOpen = false;
menu.remove();
});
menu.show();
})
}
var scrollLeft;
var scrollRight;
@ -117,9 +164,9 @@ RED.tabs = (function() {
}
})
scrollLeft = $('<div class="red-ui-tab-button red-ui-tab-scroll red-ui-tab-scroll-left"><a href="#" style="display:none;"><i class="fa fa-caret-left"></i></a></div>').appendTo(wrapper).find("a");
scrollLeft.on('mousedown',function(evt) { scrollEventHandler(evt,'-=150') }).on('click',function(evt){ evt.preventDefault();});
scrollLeft.on('mousedown',function(evt) {scrollEventHandler(evt, evt.shiftKey?('-='+scrollContainer.scrollLeft()):'-=150') }).on('click',function(evt){ evt.preventDefault();});
scrollRight = $('<div class="red-ui-tab-button red-ui-tab-scroll red-ui-tab-scroll-right"><a href="#" style="display:none;"><i class="fa fa-caret-right"></i></a></div>').appendTo(wrapper).find("a");
scrollRight.on('mousedown',function(evt) { scrollEventHandler(evt,'+=150') }).on('click',function(evt){ evt.preventDefault();});
scrollRight.on('mousedown',function(evt) { scrollEventHandler(evt,evt.shiftKey?('+='+(scrollContainer[0].scrollWidth - scrollContainer.width()-scrollContainer.scrollLeft())):'+=150') }).on('click',function(evt){ evt.preventDefault();});
}
if (options.collapsible) {
@ -337,6 +384,12 @@ RED.tabs = (function() {
if (link.length === 0) {
return;
}
if (link.parent().hasClass("hide-tab")) {
link.parent().removeClass("hide-tab").removeClass("hide");
if (options.onshow) {
options.onshow(tabs[link.attr('href').slice(1)])
}
}
if (!link.parent().hasClass("active")) {
ul.children().removeClass("active");
ul.children().css({"transition": "width 100ms"});
@ -362,13 +415,13 @@ RED.tabs = (function() {
}
}
function activatePreviousTab() {
var previous = ul.find("li.active").prev();
var previous = findPreviousVisibleTab();
if (previous.length > 0) {
activateTab(previous.find("a"));
}
}
function activateNextTab() {
var next = ul.find("li.active").next();
var next = findNextVisibleTab();
if (next.length > 0) {
activateTab(next.find("a"));
}
@ -378,7 +431,9 @@ RED.tabs = (function() {
if (options.vertical) {
return;
}
var tabs = ul.find("li.red-ui-tab");
var allTabs = ul.find("li.red-ui-tab");
var tabs = allTabs.filter(":not(.hide-tab)");
var hiddenTabs = allTabs.filter(".hide-tab");
var width = wrapper.width();
var tabCount = tabs.length;
var tabWidth;
@ -446,6 +501,7 @@ RED.tabs = (function() {
// }
tabs.css({width:currentTabWidth});
hiddenTabs.css({width:"0px"});
if (tabWidth < 50) {
// ul.find(".red-ui-tab-close").hide();
ul.find(".red-ui-tab-icon").hide();
@ -486,24 +542,104 @@ RED.tabs = (function() {
}
var li = ul.find("a[href='#"+id+"']").parent();
if (li.hasClass("active")) {
var tab = li.prev();
var tab = findPreviousVisibleTab(li);
if (tab.length === 0) {
tab = li.next();
tab = findNextVisibleTab(li);
}
if (tab.length > 0) {
activateTab(tab.find("a"));
} else {
if (options.onchange) {
options.onchange(null);
}
}
activateTab(tab.find("a"));
}
li.remove();
if (tabs[id].pinned) {
pinnedTabsCount--;
li.one("transitionend", function(evt) {
li.remove();
if (tabs[id].pinned) {
pinnedTabsCount--;
}
if (options.onremove) {
options.onremove(tabs[id]);
}
delete tabs[id];
updateTabWidths();
if (collapsibleMenu) {
collapsibleMenu.remove();
collapsibleMenu = null;
}
})
li.addClass("hide-tab");
li.width(0);
}
function findPreviousVisibleTab(li) {
if (!li) {
li = ul.find("li.active").parent();
}
if (options.onremove) {
options.onremove(tabs[id]);
var previous = li.prev();
while(previous.length > 0 && previous.hasClass("hide-tab")) {
previous = previous.prev();
}
delete tabs[id];
updateTabWidths();
if (collapsibleMenu) {
collapsibleMenu.remove();
collapsibleMenu = null;
return previous;
}
function findNextVisibleTab(li) {
if (!li) {
li = ul.find("li.active").parent();
}
var next = ul.find("li.active").next();
while(next.length > 0 && next.hasClass("hide-tab")) {
next = next.next();
}
return next;
}
function showTab(id) {
if (tabs[id]) {
var li = ul.find("a[href='#"+id+"']").parent();
if (li.hasClass("hide-tab")) {
li.removeClass("hide-tab").removeClass("hide");
if (ul.find("li.red-ui-tab:not(.hide-tab)").length === 1) {
activateTab(li.find("a"))
}
updateTabWidths();
if (options.onshow) {
options.onshow(tabs[id])
}
}
}
}
function hideTab(id) {
if (tabs[id]) {
var li = ul.find("a[href='#"+id+"']").parent();
if (!li.hasClass("hide-tab")) {
if (li.hasClass("active")) {
var tab = findPreviousVisibleTab(li);
if (tab.length === 0) {
tab = findNextVisibleTab(li);
}
if (tab.length > 0) {
activateTab(tab.find("a"));
} else {
if (options.onchange) {
options.onchange(null);
}
}
}
li.removeClass("active");
li.one("transitionend", function(evt) {
li.addClass("hide");
updateTabWidths();
if (options.onhide) {
options.onhide(tabs[id])
}
setTimeout(function() {
updateScroll()
},200)
})
li.addClass("hide-tab");
li.css({width:0})
}
}
}
@ -663,7 +799,6 @@ RED.tabs = (function() {
link.on("click", function(evt) { evt.preventDefault(); })
link.on("dblclick", function(evt) { evt.stopPropagation(); evt.preventDefault(); })
$('<span class="red-ui-tabs-fade"></span>').appendTo(li);
if (tab.closeable) {
@ -675,6 +810,15 @@ RED.tabs = (function() {
removeTab(tab.id);
});
}
if (tab.hideable) {
li.addClass("red-ui-tabs-closeable")
var closeLink = $("<a/>",{href:"#",class:"red-ui-tab-close"}).appendTo(li);
closeLink.append('<i class="fa fa-times" />');
closeLink.on("click",function(event) {
event.preventDefault();
hideTab(tab.id);
});
}
var badges = $('<span class="red-ui-tabs-badges"></span>').appendTo(li);
if (options.onselect) {
@ -682,11 +826,11 @@ RED.tabs = (function() {
$('<i class="red-ui-tabs-badge-selected fa fa-check-circle"></i>').appendTo(badges);
}
link.attr("title",tab.label);
if (options.onadd) {
options.onadd(tab);
}
link.attr("title",tab.label);
if (ul.find("li.red-ui-tab").length == 1) {
activateTab(link);
}
@ -787,7 +931,7 @@ RED.tabs = (function() {
previousTab: activatePreviousTab,
resize: updateTabWidths,
count: function() {
return ul.find("li.red-ui-tab").length;
return ul.find("li.red-ui-tab:not(.hide)").length;
},
activeIndex: function() {
return ul.find("li.active").index()
@ -795,6 +939,9 @@ RED.tabs = (function() {
contains: function(id) {
return ul.find("a[href='#"+id+"']").length > 0;
},
showTab: showTab,
hideTab: hideTab,
renameTab: function(id,label) {
tabs[id].label = label;
var tab = ul.find("a[href='#"+id+"']");
@ -802,7 +949,20 @@ RED.tabs = (function() {
tab.find("span.red-ui-text-bidi-aware").text(label).attr('dir', RED.text.bidi.resolveBaseTextDir(label));
updateTabWidths();
},
listTabs: function() {
return $.makeArray(ul.children().map(function() { return $(this).data('tabId');}));
},
selection: getSelection,
clearSelection: function() {
if (options.onselect) {
var selection = ul.find("li.red-ui-tab.selected");
if (selection.length > 0) {
selection.removeClass("selected");
selectionChanged();
}
}
},
order: function(order) {
preferredOrder = order;
var existingTabOrder = $.makeArray(ul.children().map(function() { return $(this).data('tabId');}));

View File

@ -24,6 +24,9 @@
* - rootSortable: boolean - if 'sortable' is set, then setting this to
* false, prevents items being sorted to the
* top level of the tree
* - autoSelect: boolean - default true - triggers item selection when navigating
* list by keyboard. If the list has checkboxed items
* you probably want to set this to false
*
* methods:
* - data(items) - clears existing items and replaces with new data
@ -41,6 +44,7 @@
* sublabel: 'Local', // a sub-label for the item
* icon: 'fa fa-rocket', // (optional) icon for the item
* checkbox: true/false, // (optional) if present, display checkbox accordingly
* radio: 'group-name', // (optional) if present, display radio box - using group-name to set radio group
* selected: true/false, // (optional) whether the item is selected or not
* children: [] | function(done,item) // (optional) an array of child items, or a function
* // that will call the `done` callback with an array
@ -49,6 +53,7 @@
* deferBuild: true/false, // don't build any ui elements for the item's children
* until it is expanded by the user.
* element: // custom dom element to use for the item - ignored if `label` is set
* collapsible: true/false, // prevent a parent item from being collapsed. default true.
* }
* ]
*
@ -89,77 +94,99 @@
$.widget( "nodered.treeList", {
_create: function() {
var that = this;
var autoSelect = true;
if (that.options.autoSelect === false) {
autoSelect = false;
}
this.element.addClass('red-ui-treeList');
this.element.attr("tabIndex",0);
var wrapper = $('<div>',{class:'red-ui-treeList-container'}).appendTo(this.element);
this.element.on('keydown', function(evt) {
var selected = that._topList.find(".selected").parent().data('data');
if (!selected && (evt.keyCode === 40 || evt.keyCode === 38)) {
that.select(that._data[0]);
var focussed = that._topList.find(".focus").parent().data('data');
if (!focussed && (evt.keyCode === 40 || evt.keyCode === 38)) {
if (that._data[0]) {
if (autoSelect) {
that.select(that._data[0]);
} else {
that._topList.find(".focus").removeClass("focus")
}
that._data[0].treeList.label.addClass('focus')
}
return;
}
var target;
switch(evt.keyCode) {
case 32: // SPACE
case 13: // ENTER
if (evt.altKey || evt.ctrlKey || evt.metaKey || evt.shiftKey) {
return
}
evt.preventDefault();
evt.stopPropagation();
if (selected.children) {
if (selected.treeList.container.hasClass("expanded")) {
selected.treeList.collapse()
if (focussed.checkbox) {
focussed.treeList.checkbox.trigger("click");
} else if (focussed.radio) {
focussed.treeList.radio.trigger("click");
} else if (focussed.children) {
if (focussed.treeList.container.hasClass("expanded")) {
focussed.treeList.collapse()
} else {
selected.treeList.expand()
focussed.treeList.expand()
}
} else {
that._trigger("confirm",null,selected)
that._trigger("confirm",null,focussed)
}
break;
case 37: // LEFT
evt.preventDefault();
evt.stopPropagation();
if (selected.children&& selected.treeList.container.hasClass("expanded")) {
selected.treeList.collapse()
} else if (selected.parent) {
target = selected.parent;
if (focussed.children&& focussed.treeList.container.hasClass("expanded")) {
focussed.treeList.collapse()
} else if (focussed.parent) {
target = focussed.parent;
}
break;
case 38: // UP
evt.preventDefault();
evt.stopPropagation();
target = that._getPreviousSibling(selected);
target = that._getPreviousSibling(focussed);
if (target) {
target = that._getLastDescendant(target);
}
if (!target && selected.parent) {
target = selected.parent;
if (!target && focussed.parent) {
target = focussed.parent;
}
break;
case 39: // RIGHT
evt.preventDefault();
evt.stopPropagation();
if (selected.children) {
if (!selected.treeList.container.hasClass("expanded")) {
selected.treeList.expand()
if (focussed.children) {
if (!focussed.treeList.container.hasClass("expanded")) {
focussed.treeList.expand()
}
}
break
case 40: //DOWN
evt.preventDefault();
evt.stopPropagation();
if (selected.children && Array.isArray(selected.children) && selected.children.length > 0 && selected.treeList.container.hasClass("expanded")) {
target = selected.children[0];
if (focussed.children && Array.isArray(focussed.children) && focussed.children.length > 0 && focussed.treeList.container.hasClass("expanded")) {
target = focussed.children[0];
} else {
target = that._getNextSibling(selected);
while (!target && selected.parent) {
selected = selected.parent;
target = that._getNextSibling(selected);
target = that._getNextSibling(focussed);
while (!target && focussed.parent) {
focussed = focussed.parent;
target = that._getNextSibling(focussed);
}
}
break
}
if (target) {
that.select(target);
if (autoSelect) {
that.select(target);
} else {
that._topList.find(".focus").removeClass("focus")
}
target.treeList.label.addClass('focus')
}
});
this._data = [];
@ -462,6 +489,9 @@
container.addClass("expanded");
}
item.treeList.collapse = function() {
if (item.collapsible === false) {
return
}
if (!item.children) {
return;
}
@ -532,10 +562,11 @@
}).appendTo(label)
}
var labelPaddingWidth = (item.gutter?item.gutter.width()+2:0)+(depth*20);
// var labelPaddingWidth = (item.gutter ? item.gutter[0].offsetWidth + 2 : 0) + (depth * 20)
// var labelPaddingWidth = (item.gutter?item.gutter.width()+2:0)+(depth*20);
var labelPaddingWidth = (item.gutter ? item.gutter[0].offsetWidth + 2 : 0) + (depth * 20)
item.treeList.labelPadding = $('<span>').css({
display: "inline-block",
"flex-shrink": 0,
width: labelPaddingWidth+'px'
}).appendTo(label);
@ -581,7 +612,7 @@
// Already a parent because we've got the angle-right icon
return;
}
$('<i class="fa fa-angle-right" />').appendTo(treeListIcon);
$('<i class="fa fa-angle-right" />').toggleClass("hide",item.collapsible === false).appendTo(treeListIcon);
treeListIcon.on("click.red-ui-treeList-expand", function(e) {
e.stopPropagation();
e.preventDefault();
@ -632,6 +663,46 @@
label.on("click", function(e) {
e.stopPropagation();
cb.trigger("click");
that._topList.find(".focus").removeClass("focus")
label.addClass('focus')
})
}
item.treeList.select = function(v) {
if (v !== item.selected) {
cb.trigger("click");
}
}
item.treeList.checkbox = cb;
selectWrapper.appendTo(label)
} else if (item.radio) {
var selectWrapper = $('<span class="red-ui-treeList-icon"></span>');
var cb = $('<input class="red-ui-treeList-radio" type="radio">').prop('name', item.radio).prop('checked',item.selected).appendTo(selectWrapper);
cb.on('click', function(e) {
e.stopPropagation();
});
cb.on('change', function(e) {
item.selected = this.checked;
that._selected.forEach(function(selectedItem) {
if (selectedItem.radio === item.radio) {
selectedItem.treeList.label.removeClass("selected");
selectedItem.selected = false;
that._selected.delete(selectedItem);
}
})
if (item.selected) {
that._selected.add(item);
} else {
that._selected.delete(item);
}
label.toggleClass("selected",this.checked);
that._trigger("select",e,item);
})
if (!item.children) {
label.on("click", function(e) {
e.stopPropagation();
cb.trigger("click");
that._topList.find(".focus").removeClass("focus")
label.addClass('focus')
})
}
item.treeList.select = function(v) {
@ -640,6 +711,7 @@
}
}
selectWrapper.appendTo(label)
item.treeList.radio = cb;
} else {
label.on("click", function(e) {
if (!that.options.multi) {
@ -647,10 +719,14 @@
}
label.addClass("selected");
that._selected.add(item);
that._topList.find(".focus").removeClass("focus")
label.addClass('focus')
that._trigger("select",e,item)
})
label.on("dblclick", function(e) {
that._topList.find(".focus").removeClass("focus")
label.addClass('focus')
if (!item.children) {
that._trigger("confirm",e,item);
}
@ -798,6 +874,9 @@
if (item.treeList.label) {
item.treeList.label.addClass("selected");
}
that._topList.find(".focus").removeClass("focus");
if (triggerEvent !== false) {
this._trigger("select",null,item)
}
@ -805,6 +884,9 @@
clearSelection: function() {
this._selected.forEach(function(item) {
item.selected = false;
if (item.treeList.checkbox) {
item.treeList.checkbox.prop('checked',false)
}
if (item.treeList.label) {
item.treeList.label.removeClass("selected")
}

View File

@ -53,8 +53,88 @@
}
return icon;
}
var autoComplete = function(options) {
return function(val) {
var matches = [];
options.forEach(opt => {
let v = opt.value;
var i = v.toLowerCase().indexOf(val.toLowerCase());
if (i > -1) {
var pre = v.substring(0,i);
var matchedVal = v.substring(i,i+val.length);
var post = v.substring(i+val.length)
var el = $('<div/>',{style:"white-space:nowrap; overflow: hidden; flex-grow:1"});
$('<span/>').text(pre).appendTo(el);
$('<span/>',{style:"font-weight: bold"}).text(matchedVal).appendTo(el);
$('<span/>').text(post).appendTo(el);
var element = $('<div>',{style: "display: flex"});
el.appendTo(element);
if (opt.source) {
$('<div>').css({
"font-size": "0.8em"
}).text(opt.source.join(",")).appendTo(element);
}
matches.push({
value: v,
label: element,
i:i
})
}
})
matches.sort(function(A,B){return A.i-B.i})
return matches;
}
}
// This is a hand-generated list of completions for the core nodes (based on the node help html).
var msgCompletions = [
{ value: "payload" },
{ value: "req", source: ["http in"]},
{ value: "req.body", source: ["http in"]},
{ value: "req.headers", source: ["http in"]},
{ value: "req.query", source: ["http in"]},
{ value: "req.params", source: ["http in"]},
{ value: "req.cookies", source: ["http in"]},
{ value: "req.files", source: ["http in"]},
{ value: "complete", source: ["join"] },
{ value: "contentType", source: ["mqtt"] },
{ value: "cookies", source: ["http in","http request"] },
{ value: "correlationData", source: ["mqtt"] },
{ value: "delay", source: ["delay","trigger"] },
{ value: "encoding", source: ["file"] },
{ value: "error", source: ["catch"] },
{ value: "filename", source: ["file","file in"] },
{ value: "flush", source: ["delay"] },
{ value: "followRedirects", source: ["http request"] },
{ value: "headers", source: ["http in"," http request"] },
{ value: "kill", source: ["exec"] },
{ value: "messageExpiryInterval", source: ["mqtt"] },
{ value: "method", source: ["http-request"] },
{ value: "options", source: ["xml"] },
{ value: "parts", source: ["split","join"] },
{ value: "pid", source: ["exec"] },
{ value: "qos", source: ["mqtt"] },
{ value: "rate", source: ["delay"] },
{ value: "rejectUnauthorized", source: ["http request"] },
{ value: "requestTimeout", source: ["http request"] },
{ value: "reset", source: ["delay","trigger","join","rbe"] },
{ value: "responseTopic", source: ["mqtt"] },
{ value: "restartTimeout", source: ["join"] },
{ value: "retain", source: ["mqtt"] },
{ value: "select", source: ["html"] },
{ value: "statusCode", source: ["http in"] },
{ value: "template", source: ["template"] },
{ value: "toFront", source: ["delay"] },
{ value: "topic", source: ["inject","mqtt","rbe"] },
{ value: "url", source: ["http request"] },
{ value: "userProperties", source: ["mqtt"] }
]
var allOptions = {
msg: {value:"msg",label:"msg.",validate:RED.utils.validatePropertyExpression},
msg: {value:"msg",label:"msg.",validate:RED.utils.validatePropertyExpression, autoComplete: autoComplete(msgCompletions)},
flow: {value:"flow",label:"flow.",hasValue:true,
options:[],
validate:RED.utils.validatePropertyExpression,
@ -265,6 +345,47 @@
}
}
};
// For a type with options, check value is a valid selection
// If !opt.multiple, returns the valid option object
// if opt.multiple, returns an array of valid option objects
// If not valid, returns null;
function isOptionValueValid(opt, currentVal) {
if (!opt.multiple) {
for (var i=0;i<opt.options.length;i++) {
op = opt.options[i];
if (typeof op === "string" && op === currentVal) {
return {value:currentVal}
} else if (op.value === currentVal) {
return op;
}
}
} else {
// Check to see if value is a valid csv of
// options.
var currentValues = {};
var selected = [];
currentVal.split(",").forEach(function(v) {
if (v) {
currentValues[v] = true;
}
});
for (var i=0;i<opt.options.length;i++) {
op = opt.options[i];
var val = typeof op === "string" ? op : op.value;
if (currentValues.hasOwnProperty(val)) {
delete currentValues[val];
selected.push(typeof op === "string" ? {value:op} : op.value)
}
}
if (!$.isEmptyObject(currentValues)) {
return null;
}
return selected
}
}
var nlsd = false;
$.widget( "nodered.typedInput", {
@ -328,6 +449,8 @@
});
this.defaultInputType = this.input.attr('type');
// Used to remember selections per-type to restore them when switching between types
this.oldValues = {};
this.uiSelect.addClass("red-ui-typedInput-container");
@ -380,6 +503,9 @@
that.element.trigger('paste',evt);
});
this.input.on('keydown', function(evt) {
if (that.typeMap[that.propertyType].autoComplete) {
return
}
if (evt.keyCode >= 37 && evt.keyCode <= 40) {
evt.stopPropagation();
}
@ -428,6 +554,7 @@
this.optionExpandButton = $('<button tabindex="0" class="red-ui-typedInput-option-expand" style="display:inline-block"></button>').appendTo(this.uiSelect);
this.optionExpandButtonIcon = $('<i class="red-ui-typedInput-icon fa fa-ellipsis-h"></i>').appendTo(this.optionExpandButton);
this.type(this.options.default||this.typeList[0].value);
}catch(err) {
console.log(err.stack);
@ -579,7 +706,7 @@
var height = relativeTo.height();
var menuHeight = menu.height();
var top = (height+pos.top);
if (top+menuHeight > $(window).height()) {
if (top+menuHeight-$(document).scrollTop() > $(window).height()) {
top -= (top+menuHeight)-$(window).height()+5;
}
if (top < 0) {
@ -688,8 +815,10 @@
});
if (this.typeList.length < 2) {
this.selectTrigger.attr("tabindex", -1)
this.selectTrigger.on("mousedown.red-ui-typedInput-focus-block", function(evt) { evt.preventDefault(); })
} else {
this.selectTrigger.attr("tabindex", 0)
this.selectTrigger.off("mousedown.red-ui-typedInput-focus-block")
}
this.selectTrigger.toggleClass("disabled", this.typeList.length === 1);
this.selectTrigger.find(".fa-caret-down").toggle(this.typeList.length > 1)
@ -703,6 +832,11 @@
this.propertyType = null;
this.type(currentType);
}
if (this.typeList.length === 1 && !this.typeList[0].icon && (!this.typeList[0].label || this.typeList[0].showLabel === false)) {
this.selectTrigger.hide()
} else {
this.selectTrigger.show()
}
},
width: function(desiredWidth) {
this.uiWidth = desiredWidth;
@ -765,8 +899,51 @@
return this.propertyType;
} else {
var that = this;
var previousValue = null;
var opt = this.typeMap[type];
if (opt && this.propertyType !== type) {
// If previousType is !null, then this is a change of the type, rather than the initialisation
var previousType = this.typeMap[this.propertyType];
var typeChanged = !!previousType;
previousValue = this.input.val();
if (typeChanged) {
if (previousType.options && opt.hasValue !== true) {
this.oldValues[previousType.value] = previousValue;
} else if (previousType.hasValue === false) {
this.oldValues[previousType.value] = previousValue;
} else {
this.oldValues["_"] = previousValue;
}
if ((opt.options && opt.hasValue !== true) || opt.hasValue === false) {
if (this.oldValues.hasOwnProperty(opt.value)) {
this.input.val(this.oldValues[opt.value]);
} else {
// No old value for the option type.
// It is possible code has called 'value' then 'type'
// to set the selected option. This is what the Inject/Switch/Change
// nodes did before 2.1.
// So we need to be careful to not reset the value if it is a valid option.
var validOptions = isOptionValueValid(opt,previousValue);
if (previousValue && validOptions) {
this.input.val(previousValue);
} else {
if (typeof opt.default === "string") {
this.input.val(opt.default);
} else if (Array.isArray(opt.default)) {
this.input.val(opt.default.join(","))
} else {
this.input.val("");
}
}
}
} else {
this.input.val(this.oldValues.hasOwnProperty("_")?this.oldValues["_"]:(opt.default||""))
}
if (previousType.autoComplete) {
this.input.autoComplete("destroy");
}
}
this.propertyType = type;
if (this.typeField) {
this.typeField.val(type);
@ -836,22 +1013,12 @@
var op;
if (!opt.hasValue) {
var validValue = false;
var currentVal = this.input.val();
// Check the value is valid for the available options
var validValues = isOptionValueValid(opt,this.input.val());
if (!opt.multiple) {
for (var i=0;i<opt.options.length;i++) {
op = opt.options[i];
if (typeof op === "string" && op === currentVal) {
that._updateOptionSelectLabel({value:currentVal});
validValue = true;
break;
} else if (op.value === currentVal) {
that._updateOptionSelectLabel(op);
validValue = true;
break;
}
}
if (!validValue) {
if (validValues) {
that._updateOptionSelectLabel(validValues)
} else {
op = opt.options[0];
if (typeof op === "string") {
this.value(op);
@ -862,22 +1029,13 @@
}
}
} else {
// Check to see if value is a valid csv of
// options.
var currentValues = {};
currentVal.split(",").forEach(function(v) {
if (v) {
currentValues[v] = true;
}
});
for (var i=0;i<opt.options.length;i++) {
op = opt.options[i];
delete currentValues[op.value||op];
}
if (!$.isEmptyObject(currentValues)) {
// Invalid, set to default/empty
this.value((opt.default||[]).join(","));
if (!validValues) {
validValues = (opt.default || []).map(function(v) {
return typeof v === "string"?v:v.value
});
this.value(validValues.join(","));
}
that._updateOptionSelectLabel(validValues);
}
} else {
var selectedOption = this.optionValue||opt.options[0];
@ -938,8 +1096,6 @@
this.input.attr('type',this.defaultInputType)
}
if (opt.hasValue === false) {
this.oldValue = this.input.val();
this.input.val("");
this.elementDiv.hide();
this.valueLabelContainer.hide();
} else if (opt.valueLabel) {
@ -952,12 +1108,13 @@
this.elementDiv.hide();
opt.valueLabel.call(this,this.valueLabelContainer,this.input.val());
} else {
if (this.oldValue !== undefined) {
this.input.val(this.oldValue);
delete this.oldValue;
}
this.valueLabelContainer.hide();
this.elementDiv.show();
if (opt.autoComplete) {
this.input.autoComplete({
search: opt.autoComplete
})
}
}
if (this.optionExpandButton) {
if (opt.expand) {
@ -1042,6 +1199,9 @@
},
disabled: function() {
return this.uiSelect.attr("disabled") === "disabled";
},
focus: function() {
this.input.focus();
}
});
})(jQuery);

View File

@ -1376,6 +1376,7 @@ RED.diff = (function() {
function mergeDiff(diff) {
//console.log(diff);
var selectedTab = RED.workspaces.active();
var appliedDiff = applyDiff(diff);
var newConfig = appliedDiff.config;
@ -1426,6 +1427,7 @@ RED.diff = (function() {
RED.view.redraw(true);
RED.palette.refresh();
RED.workspaces.refresh();
RED.workspaces.show(selectedTab, true);
RED.sidebar.config.refresh();
}

File diff suppressed because it is too large Load Diff

View File

@ -54,6 +54,7 @@ RED.editor.codeEditor.monaco = (function() {
var initialised = false;
const type = "monaco";
const monacoThemes = ["vs","vs-dark","hc-black"]; //TODO: consider setting hc-black autmatically based on acessability?
let userSelectedTheme;
//TODO: get from externalModules.js For now this is enough for feature parity with ACE (and then some).
const knownModules = {
@ -181,19 +182,35 @@ RED.editor.codeEditor.monaco = (function() {
var editorSettings = RED.editor.codeEditor.settings || {};
var editorOptions = editorSettings.options || {};
if (editorOptions.theme) {
if (!monacoThemes.includes(editorOptions.theme)) {
var customTheme = 'vendor/monaco/dist/theme/' + editorOptions.theme + '.json';
$.get(customTheme, function (theme) {
monacoThemes.push(editorOptions.theme);//add to list of loaded themes
if ((theme.rules && Array.isArray(theme.rules)) || theme.colors) {
monaco.editor.defineTheme(editorOptions.theme, theme);
monaco.editor.setTheme(editorOptions.theme);
//if editorOptions.theme is an object (set in theme.js context()), use the plugin theme name as the monaco theme name
//if editorOptions.theme is a string, it should be the name of a pre-set theme, load that
try {
const addTheme = function (themeThemeName, theme) {
if ((theme.rules && Array.isArray(theme.rules)) || theme.colors) {
monacoThemes.push(themeThemeName); //add to list of loaded themes
monaco.editor.defineTheme(themeThemeName, theme);
monaco.editor.setTheme(themeThemeName);
userSelectedTheme = themeThemeName;
}
};
if (editorOptions.theme) {
if (typeof editorOptions.theme == "object" && RED.settings.editorTheme.theme) {
let themeThemeName = editorOptions.theme.name || RED.settings.editorTheme.theme;
addTheme(themeThemeName, editorOptions.theme);
} else if (typeof editorOptions.theme == "string") {
let themeThemeName = editorOptions.theme;
if (!monacoThemes.includes(themeThemeName)) {
$.get('vendor/monaco/dist/theme/' + themeThemeName + '.json', function (theme) {
addTheme(themeThemeName, theme);
});
}
});
}
}
} catch (error) {
console.warn(error);
}
//Helper function to simplify snippet setup
function createMonacoCompletionItem(label, insertText, documentation, range, kind) {
if (Array.isArray(documentation)) { documentation = documentation.join("\n"); }
@ -653,6 +670,8 @@ RED.editor.codeEditor.monaco = (function() {
noSyntaxValidation: false,
diagnosticCodesToIgnore: [
1108, //return not inside function
1375, //'await' expressions are only allowed at the top level of a file when that file is a module
1378, //Top-level 'await' expressions are only allowed when the 'module' option is set to 'esnext' or 'system', and the 'target' option is set to 'es2017' or higher
//2304, //Cannot find name - this one is heavy handed and prevents user seeing stupid errors. Would provide better ACE feature parity (i.e. no need for declaration of vars) but misses lots of errors. Lets be bold & leave it out!
2307, //Cannot find module 'xxx' or its corresponding type declarations
2322, //Type 'unknown' is not assignable to type 'string'
@ -742,6 +761,10 @@ RED.editor.codeEditor.monaco = (function() {
var editorOptions = $.extend({}, editorSettings.options, options);
editorOptions.language = convertAceModeToMonacoLang(options.mode);
if(userSelectedTheme) {
editorOptions.theme = userSelectedTheme;//use user selected theme for this session
}
//by default, set javascript editors to text mode.
//when element becomes visible, it will be (re) set to javascript mode
//this is to ensure multiple editors sharing the model dont present its
@ -1167,7 +1190,10 @@ RED.editor.codeEditor.monaco = (function() {
return { row: p.lineNumber-1, column: p.column-1 };
}
ed.setTheme = monaco.editor.setTheme;
ed.setTheme = function(theme) {
monaco.editor.setTheme(theme);
userSelectedTheme = theme;//remember users choice for this session
}
ed.on = function (name, cb) {
switch (name) {

View File

@ -1,4 +1,4 @@
RED.colorPicker = (function() {
RED.editor.colorPicker = RED.colorPicker = (function() {
function create(options) {
var color = options.value;

View File

@ -0,0 +1,616 @@
RED.editor.envVarList = (function() {
var currentLocale = 'en-US';
var DEFAULT_ENV_TYPE_LIST = ['str','num','bool','json','bin','env'];
var DEFAULT_ENV_TYPE_LIST_INC_CRED = ['str','num','bool','json','bin','env','cred'];
/**
* Create env var edit interface
* @param container - container
* @param node - subflow node
*/
function buildPropertiesList(envContainer, node) {
var isTemplateNode = (node.type === "subflow");
envContainer
.css({
'min-height':'150px',
'min-width':'450px'
})
.editableList({
header: isTemplateNode?$('<div><div><div></div><div data-i18n="common.label.name"></div><div data-i18n="editor-tab.defaultValue"></div><div></div></div></div>'):undefined,
addItem: function(container, i, opt) {
// If this is an instance node, these are properties unique to
// this instance - ie opt.parent will not be defined.
if (isTemplateNode) {
container.addClass("red-ui-editor-subflow-env-editable")
}
var envRow = $('<div/>').appendTo(container);
var nameField = null;
var valueField = null;
nameField = $('<input/>', {
class: "node-input-env-name",
type: "text",
placeholder: RED._("common.label.name")
}).attr("autocomplete","disable").appendTo(envRow).val(opt.name);
valueField = $('<input/>',{
style: "width:100%",
class: "node-input-env-value",
type: "text",
}).attr("autocomplete","disable").appendTo(envRow)
valueField.typedInput({default:'str',types:isTemplateNode?DEFAULT_ENV_TYPE_LIST:DEFAULT_ENV_TYPE_LIST_INC_CRED});
valueField.typedInput('type', opt.type);
if (opt.type === "cred") {
if (opt.value) {
valueField.typedInput('value', opt.value);
} else if (node.credentials && node.credentials[opt.name]) {
valueField.typedInput('value', node.credentials[opt.name]);
} else if (node.credentials && node.credentials['has_'+opt.name]) {
valueField.typedInput('value', "__PWRD__");
} else {
valueField.typedInput('value', "");
}
} else {
valueField.typedInput('value', opt.value);
}
opt.nameField = nameField;
opt.valueField = valueField;
var actionButton = $('<a/>',{href:"#",class:"red-ui-editableList-item-remove red-ui-button red-ui-button-small"}).appendTo(envRow);
$('<i/>',{class:"fa "+(opt.parent?"fa-reply":"fa-remove")}).appendTo(actionButton);
var removeTip = RED.popover.tooltip(actionButton,RED._("subflow.env.remove"));
actionButton.on("click", function(evt) {
evt.preventDefault();
removeTip.close();
container.parent().addClass("red-ui-editableList-item-deleting")
container.fadeOut(300, function() {
envContainer.editableList('removeItem',opt);
});
});
if (isTemplateNode) {
// Add the UI customisation row
// if `opt.ui` does not exist, then apply defaults. If these
// defaults do not change then they will get stripped off
// before saving.
if (opt.type === 'cred') {
opt.ui = opt.ui || {
icon: "",
type: "cred"
}
opt.ui.type = "cred";
} else {
opt.ui = opt.ui || {
icon: "",
type: "input",
opts: {types:DEFAULT_ENV_TYPE_LIST}
}
}
opt.ui.label = opt.ui.label || {};
opt.ui.type = opt.ui.type || "input";
var uiRow = $('<div/>').appendTo(container).hide();
// save current info for reverting on cancel
// var copy = $.extend(true, {}, ui);
$('<a href="#"><i class="fa fa-angle-right"></a>').prependTo(envRow).on("click", function (evt) {
evt.preventDefault();
if ($(this).hasClass('expanded')) {
uiRow.slideUp();
$(this).removeClass('expanded');
} else {
uiRow.slideDown();
$(this).addClass('expanded');
}
});
buildEnvEditRow(uiRow, opt.ui, nameField, valueField);
nameField.trigger('change');
}
},
sortable: ".red-ui-editableList-item-handle",
removable: false
});
var parentEnv = {};
var envList = [];
if (/^subflow:/.test(node.type)) {
var subflowDef = RED.nodes.subflow(node.type.substring(8));
if (subflowDef.env) {
subflowDef.env.forEach(function(env) {
var item = {
name:env.name,
parent: {
type: env.type,
value: env.value,
ui: env.ui
}
}
envList.push(item);
parentEnv[env.name] = item;
})
}
}
if (node.env) {
for (var i = 0; i < node.env.length; i++) {
var env = node.env[i];
if (parentEnv.hasOwnProperty(env.name)) {
parentEnv[env.name].type = env.type;
parentEnv[env.name].value = env.value;
} else {
envList.push({
name: env.name,
type: env.type,
value: env.value,
ui: env.ui
});
}
}
}
envList.forEach(function(env) {
if (env.parent && env.parent.ui && env.parent.ui.type === 'hide') {
return;
}
if (!isTemplateNode && env.parent) {
return;
}
envContainer.editableList('addItem', JSON.parse(JSON.stringify(env)));
});
}
/**
* Create UI edit interface for environment variable
* @param container - container
* @param env - env var definition
* @param nameField - name field of env var
* @param valueField - value field of env var
*/
function buildEnvEditRow(container, ui, nameField, valueField) {
container.addClass("red-ui-editor-subflow-env-ui-row")
var topRow = $('<div></div>').appendTo(container);
$('<div></div>').appendTo(topRow);
$('<div>').text(RED._("editor.icon")).appendTo(topRow);
$('<div>').text(RED._("editor.label")).appendTo(topRow);
$('<div>').text(RED._("editor.inputType")).appendTo(topRow);
var row = $('<div></div>').appendTo(container);
$('<div><i class="red-ui-editableList-item-handle fa fa-bars"></i></div>').appendTo(row);
var typeOptions = {
'input': {types:DEFAULT_ENV_TYPE_LIST},
'select': {opts:[]},
'spinner': {},
'cred': {}
};
if (ui.opts) {
typeOptions[ui.type] = ui.opts;
} else {
// Pick up the default values if not otherwise provided
ui.opts = typeOptions[ui.type];
}
var iconCell = $('<div></div>').appendTo(row);
var iconButton = $('<a href="#"></a>').appendTo(iconCell);
iconButton.on("click", function(evt) {
evt.preventDefault();
var icon = ui.icon || "";
var iconPath = (icon ? RED.utils.separateIconPath(icon) : {});
RED.editor.iconPicker.show(iconButton, null, iconPath, true, function (newIcon) {
iconButton.empty();
var path = newIcon || "";
var newPath = RED.utils.separateIconPath(path);
if (newPath) {
$('<i class="fa"></i>').addClass(newPath.file).appendTo(iconButton);
}
ui.icon = path;
});
})
if (ui.icon) {
var newPath = RED.utils.separateIconPath(ui.icon);
$('<i class="fa '+newPath.file+'"></i>').appendTo(iconButton);
}
var labelCell = $('<div></div>').appendTo(row);
var label = ui.label && ui.label[currentLocale] || "";
var labelInput = $('<input type="text">').val(label).appendTo(labelCell);
ui.labelField = labelInput;
labelInput.on('change', function(evt) {
ui.label = ui.label || {};
var val = $(this).val().trim();
if (val === "") {
delete ui.label[currentLocale];
} else {
ui.label[currentLocale] = val;
}
})
var labelIcon = $('<span class="red-ui-editor-subflow-env-lang-icon"><i class="fa fa-language"></i></span>').appendTo(labelCell);
RED.popover.tooltip(labelIcon,function() {
var langs = Object.keys(ui.label);
var content = $("<div>");
if (langs.indexOf(currentLocale) === -1) {
langs.push(currentLocale);
langs.sort();
}
langs.forEach(function(l) {
var row = $('<div>').appendTo(content);
$('<span>').css({display:"inline-block",width:"120px"}).text(RED._("languages."+l)+(l===currentLocale?"*":"")).appendTo(row);
$('<span>').text(ui.label[l]||"").appendTo(row);
});
return content;
})
nameField.on('change',function(evt) {
labelInput.attr("placeholder",$(this).val())
});
var inputCell = $('<div></div>').appendTo(row);
var inputCellInput = $('<input type="text">').css("width","100%").appendTo(inputCell);
if (ui.type === "input") {
inputCellInput.val(ui.opts.types.join(","));
}
var checkbox;
var selectBox;
inputCellInput.typedInput({
types: [
{
value:"input",
label:RED._("editor.inputs.input"), icon:"fa fa-i-cursor",showLabel:false,multiple:true,options:[
{value:"str",label:RED._("editor.types.str"),icon:"red/images/typedInput/az.svg"},
{value:"num",label:RED._("editor.types.num"),icon:"red/images/typedInput/09.svg"},
{value:"bool",label:RED._("editor.types.bool"),icon:"red/images/typedInput/bool.svg"},
{value:"json",label:RED._("editor.types.json"),icon:"red/images/typedInput/json.svg"},
{value: "bin",label: RED._("editor.types.bin"),icon: "red/images/typedInput/bin.svg"},
{value: "env",label: RED._("editor.types.env"),icon: "red/images/typedInput/env.svg"},
{value: "cred",label: RED._("editor.types.cred"),icon: "fa fa-lock"}
],
default: DEFAULT_ENV_TYPE_LIST,
valueLabel: function(container,value) {
container.css("padding",0);
var innerContainer = $('<div class="red-ui-editor-subflow-env-input-type"></div>').appendTo(container);
var input = $('<div class="placeholder-input">').appendTo(innerContainer);
$('<span><i class="fa fa-i-cursor"></i></span>').appendTo(input);
if (value.length) {
value.forEach(function(v) {
if (!/^fa /.test(v.icon)) {
$('<img>',{src:v.icon,style:"max-width:14px; padding: 0 3px; margin-top:-4px; margin-left: 1px"}).appendTo(input);
} else {
var s = $('<span>',{style:"max-width:14px; padding: 0 3px; margin-top:-4px; margin-left: 1px"}).appendTo(input);
$("<i>",{class: v.icon}).appendTo(s);
}
})
} else {
$('<span class="red-ui-editor-subflow-env-input-type-placeholder"></span>').text(RED._("editor.selectType")).appendTo(input);
}
}
},
{
value: "cred",
label: RED._("typedInput.type.cred"), icon:"fa fa-lock", showLabel: false,
valueLabel: function(container,value) {
container.css("padding",0);
var innerContainer = $('<div class="red-ui-editor-subflow-env-input-type">').css({
"border-top-right-radius": "4px",
"border-bottom-right-radius": "4px"
}).appendTo(container);
$('<div class="placeholder-input">').html("&bull;&bull;&bull;&bull;&bull;&bull;&bull;&bull;").appendTo(innerContainer);
}
},
{
value:"select",
label:RED._("editor.inputs.select"), icon:"fa fa-tasks",showLabel:false,
valueLabel: function(container,value) {
container.css("padding","0");
selectBox = $('<select></select>').appendTo(container);
if (ui.opts && Array.isArray(ui.opts.opts)) {
ui.opts.opts.forEach(function(o) {
var label = lookupLabel(o.l, o.l["en-US"]||o.v, currentLocale);
// $('<option>').val((o.t||'str')+":"+o.v).text(label).appendTo(selectBox);
$('<option>').val(o.v).text(label).appendTo(selectBox);
})
}
selectBox.on('change', function(evt) {
var v = selectBox.val();
// var parts = v.split(":");
// var t = parts.shift();
// v = parts.join(":");
//
// valueField.typedInput("type",'str')
valueField.typedInput("value",v)
});
selectBox.val(valueField.typedInput("value"));
// selectBox.val(valueField.typedInput('type')+":"+valueField.typedInput("value"));
},
expand: {
icon: "fa-caret-down",
minWidth: 400,
content: function(container) {
var content = $('<div class="red-ui-editor-subflow-ui-edit-panel">').appendTo(container);
var optList = $('<ol>').appendTo(content).editableList({
header:$("<div><div>"+RED._("editor.select.label")+"</div><div>"+RED._("editor.select.value")+"</div></div>"),
addItem: function(row,index,itemData) {
var labelDiv = $('<div>').appendTo(row);
var label = lookupLabel(itemData.l, "", currentLocale);
itemData.label = $('<input type="text">').val(label).appendTo(labelDiv);
itemData.label.on('keydown', function(evt) {
if (evt.keyCode === 13) {
itemData.input.focus();
evt.preventDefault();
}
});
var labelIcon = $('<span class="red-ui-editor-subflow-env-lang-icon"><i class="fa fa-language"></i></span>').appendTo(labelDiv);
RED.popover.tooltip(labelIcon,function() {
return currentLocale;
})
itemData.input = $('<input type="text">').val(itemData.v).appendTo(row);
// Problem using a TI here:
// - this is in a popout panel
// - clicking the expand button in the TI will close the parent edit tray
// and open the type editor.
// - but it leaves the popout panel over the top.
// - there is no way to get back to the popout panel after closing the type editor
//.typedInput({default:itemData.t||'str', types:DEFAULT_ENV_TYPE_LIST});
itemData.input.on('keydown', function(evt) {
if (evt.keyCode === 13) {
// Enter or Tab
var index = optList.editableList('indexOf',itemData);
var length = optList.editableList('length');
if (index + 1 === length) {
var newItem = {};
optList.editableList('addItem',newItem);
setTimeout(function() {
if (newItem.label) {
newItem.label.focus();
}
},100)
} else {
var nextItem = optList.editableList('getItemAt',index+1);
if (nextItem.label) {
nextItem.label.focus()
}
}
evt.preventDefault();
}
});
},
sortable: true,
removable: true,
height: 160
})
if (ui.opts.opts.length > 0) {
ui.opts.opts.forEach(function(o) {
optList.editableList('addItem',$.extend(true,{},o))
})
} else {
optList.editableList('addItem',{})
}
return {
onclose: function() {
var items = optList.editableList('items');
var vals = [];
items.each(function (i,el) {
var data = el.data('data');
var l = data.label.val().trim();
var v = data.input.val();
// var t = data.input.typedInput('type');
// var v = data.input.typedInput('value');
if (l.length > 0) {
data.l = data.l || {};
data.l[currentLocale] = l;
}
data.v = v;
if (l.length > 0 || v.length > 0) {
var val = {l:data.l,v:data.v};
// if (t !== 'str') {
// val.t = t;
// }
vals.push(val);
}
});
ui.opts.opts = vals;
inputCellInput.typedInput('value',Date.now())
}
}
}
}
},
{
value:"checkbox",
label:RED._("editor.inputs.checkbox"), icon:"fa fa-check-square-o",showLabel:false,
valueLabel: function(container,value) {
container.css("padding",0);
checkbox = $('<input type="checkbox">').appendTo(container);
checkbox.on('change', function(evt) {
valueField.typedInput('value',$(this).prop('checked')?"true":"false");
})
checkbox.prop('checked',valueField.typedInput('value')==="true");
}
},
{
value:"spinner",
label:RED._("editor.inputs.spinner"), icon:"fa fa-sort-numeric-asc", showLabel:false,
valueLabel: function(container,value) {
container.css("padding",0);
var innerContainer = $('<div class="red-ui-editor-subflow-env-input-type"></div>').appendTo(container);
var input = $('<div class="placeholder-input">').appendTo(innerContainer);
$('<span><i class="fa fa-sort-numeric-asc"></i></span>').appendTo(input);
var min = ui.opts && ui.opts.min;
var max = ui.opts && ui.opts.max;
var label = "";
if (min !== undefined && max !== undefined) {
label = Math.min(min,max)+" - "+Math.max(min,max);
} else if (min !== undefined) {
label = "> "+min;
} else if (max !== undefined) {
label = "< "+max;
}
$('<span>').css("margin-left","15px").text(label).appendTo(input);
},
expand: {
icon: "fa-caret-down",
content: function(container) {
var content = $('<div class="red-ui-editor-subflow-ui-edit-panel">').appendTo(container);
content.css("padding","8px 5px")
var min = ui.opts.min;
var max = ui.opts.max;
var minInput = $('<input type="number" style="margin-bottom:0; width:60px">');
minInput.val(min);
var maxInput = $('<input type="number" style="margin-bottom:0; width:60px">');
maxInput.val(max);
$('<div class="form-row" style="margin-bottom:3px"><label>'+RED._("editor.spinner.min")+'</label></div>').append(minInput).appendTo(content);
$('<div class="form-row" style="margin-bottom:0"><label>'+RED._("editor.spinner.max")+'</label></div>').append(maxInput).appendTo(content);
return {
onclose: function() {
var min = minInput.val().trim();
var max = maxInput.val().trim();
if (min !== "") {
ui.opts.min = parseInt(min);
} else {
delete ui.opts.min;
}
if (max !== "") {
ui.opts.max = parseInt(max);
} else {
delete ui.opts.max;
}
inputCellInput.typedInput('value',Date.now())
}
}
}
}
},
{
value:"none",
label:RED._("editor.inputs.none"), icon:"fa fa-times",hasValue:false
},
{
value:"hide",
label:RED._("editor.inputs.hidden"), icon:"fa fa-ban",hasValue:false
}
],
default: 'none'
}).on("typedinputtypechange", function(evt,type) {
ui.type = $(this).typedInput("type");
ui.opts = typeOptions[ui.type];
if (ui.type === 'input') {
// In the case of 'input' type, the typedInput uses the multiple-option
// mode. Its value needs to be set to a comma-separately list of the
// selected options.
inputCellInput.typedInput('value',ui.opts.types.join(","))
} else {
// No other type cares about `value`, but doing this will
// force a refresh of the label now that `ui.opts` has
// been updated.
inputCellInput.typedInput('value',Date.now())
}
switch (ui.type) {
case 'input':
valueField.typedInput('types',ui.opts.types);
break;
case 'select':
valueField.typedInput('types',['str']);
break;
case 'checkbox':
valueField.typedInput('types',['bool']);
break;
case 'spinner':
valueField.typedInput('types',['num']);
break;
case 'cred':
valueField.typedInput('types',['cred']);
break;
default:
valueField.typedInput('types',DEFAULT_ENV_TYPE_LIST)
}
if (ui.type === 'checkbox') {
valueField.typedInput('type','bool');
} else if (ui.type === 'spinner') {
valueField.typedInput('type','num');
}
if (ui.type !== 'checkbox') {
checkbox = null;
}
}).on("change", function(evt,type) {
if (ui.type === 'input') {
var types = inputCellInput.typedInput('value');
ui.opts.types = (types === "") ? ["str"] : types.split(",");
valueField.typedInput('types',ui.opts.types);
}
});
valueField.on("change", function(evt) {
if (checkbox) {
checkbox.prop('checked',$(this).typedInput('value')==="true")
}
})
// Set the input to the right type. This will trigger the 'typedinputtypechange'
// event handler (just above ^^) to update the value if needed
inputCellInput.typedInput('type',ui.type)
}
function setLocale(l, list) {
currentLocale = l;
if (list) {
var items = list.editableList("items");
items.each(function (i, item) {
var entry = $(this).data('data');
var labelField = entry.ui.labelField;
labelField.val(lookupLabel(entry.ui.label, "", currentLocale));
if (labelField.timeout) {
clearTimeout(labelField.timeout);
delete labelField.timeout;
}
labelField.addClass("input-updated");
labelField.timeout = setTimeout(function() {
delete labelField.timeout
labelField.removeClass("input-updated");
},3000);
});
}
}
/**
* Lookup text for specific locale
* @param labels - dict of labels
* @param defaultLabel - fallback label if not found
* @param locale - target locale
* @returns {string} text for specified locale
*/
function lookupLabel(labels, defaultLabel, locale) {
if (labels) {
if (labels[locale]) {
return labels[locale];
}
if (locale) {
var lang = locale.substring(0, 2);
if (labels[lang]) {
return labels[lang];
}
}
}
return defaultLabel;
}
return {
create: buildPropertiesList,
setLocale: setLocale,
lookupLabel: lookupLabel,
DEFAULT_ENV_TYPE_LIST: DEFAULT_ENV_TYPE_LIST,
DEFAULT_ENV_TYPE_LIST_INC_CRED: DEFAULT_ENV_TYPE_LIST_INC_CRED
}
})();

View File

@ -0,0 +1,99 @@
RED.editor.iconPicker = (function() {
function showIconPicker(container, backgroundColor, iconPath, faOnly, done) {
var picker = $('<div class="red-ui-icon-picker">');
var searchDiv = $("<div>",{class:"red-ui-search-container"}).appendTo(picker);
searchInput = $('<input type="text">').attr("placeholder",RED._("editor.searchIcons")).appendTo(searchDiv).searchBox({
delay: 50,
change: function() {
var searchTerm = $(this).val().trim();
if (searchTerm === "") {
iconList.find(".red-ui-icon-list-module").show();
iconList.find(".red-ui-icon-list-icon").show();
} else {
iconList.find(".red-ui-icon-list-module").hide();
iconList.find(".red-ui-icon-list-icon").each(function(i,n) {
if ($(n).data('icon').indexOf(searchTerm) === -1) {
$(n).hide();
} else {
$(n).show();
}
});
}
}
});
var row = $('<div>').appendTo(picker);
var iconList = $('<div class="red-ui-icon-list">').appendTo(picker);
var metaRow = $('<div class="red-ui-icon-meta"></div>').appendTo(picker);
var summary = $('<span>').appendTo(metaRow);
var resetButton = $('<button type="button" class="red-ui-button red-ui-button-small">'+RED._("editor.useDefault")+'</button>').appendTo(metaRow).on("click", function(e) {
e.preventDefault();
iconPanel.hide();
done(null);
});
if (!backgroundColor && faOnly) {
iconList.addClass("red-ui-icon-list-dark");
}
setTimeout(function() {
var iconSets = RED.nodes.getIconSets();
Object.keys(iconSets).forEach(function(moduleName) {
if (faOnly && (moduleName !== "font-awesome")) {
return;
}
var icons = iconSets[moduleName];
if (icons.length > 0) {
// selectIconModule.append($("<option></option>").val(moduleName).text(moduleName));
var header = $('<div class="red-ui-icon-list-module"></div>').text(moduleName).appendTo(iconList);
$('<i class="fa fa-cube"></i>').prependTo(header);
icons.forEach(function(icon) {
var iconDiv = $('<div>',{class:"red-ui-icon-list-icon"}).appendTo(iconList);
var nodeDiv = $('<div>',{class:"red-ui-search-result-node"}).appendTo(iconDiv);
var icon_url = RED.settings.apiRootUrl+"icons/"+moduleName+"/"+icon;
iconDiv.data('icon',icon_url);
if (backgroundColor) {
nodeDiv.css({
'backgroundColor': backgroundColor
});
var borderColor = RED.utils.getDarkerColor(backgroundColor);
if (borderColor !== backgroundColor) {
nodeDiv.css('border-color',borderColor)
}
}
var iconContainer = $('<div/>',{class:"red-ui-palette-icon-container"}).appendTo(nodeDiv);
RED.utils.createIconElement(icon_url, iconContainer, true);
if (iconPath.module === moduleName && iconPath.file === icon) {
iconDiv.addClass("selected");
}
iconDiv.on("mouseover", function() {
summary.text(icon);
})
iconDiv.on("mouseout", function() {
summary.html("&nbsp;");
})
iconDiv.on("click", function() {
iconPanel.hide();
done(moduleName+"/"+icon);
})
})
}
});
setTimeout(function() {
spinner.remove();
},50);
},300);
var spinner = RED.utils.addSpinnerOverlay(iconList,true);
var iconPanel = RED.popover.panel(picker);
iconPanel.show({
target: container
})
picker.slideDown(100);
searchInput.trigger("focus");
}
return {
show: showIconPicker
}
})();

View File

@ -0,0 +1,517 @@
;(function() {
RED.editor.registerEditPane("editor-tab-appearance", function(node) {
return {
label: RED._("editor-tab.appearance"),
name: RED._("editor-tab.appearance"),
iconClass: "fa fa-object-group",
create: function(container) {
this.content = container;
buildAppearanceForm(this.content,node);
if (node.type === 'subflow') {
this.defaultIcon = "node-red/subflow.svg";
} else {
var iconPath = RED.utils.getDefaultNodeIcon(node._def,node);
this.defaultIcon = iconPath.module+"/"+iconPath.file;
if (node.icon && node.icon !== this.defaultIcon) {
this.isDefaultIcon = false;
} else {
this.isDefaultIcon = true;
}
}
},
resize: function(size) {
},
close: function() {
},
show: function() {
refreshLabelForm(this.content, node);
},
apply: function(editState) {
if (updateLabels(node, editState.changes, editState.outputMap)) {
editState.changed = true;
}
if (!node._def.defaults || !node._def.defaults.hasOwnProperty("icon")) {
var icon = $("#red-ui-editor-node-icon").val()||""
if (!this.isDefaultIcon) {
if (icon !== node.icon) {
editState.changes.icon = node.icon;
node.icon = icon;
editState.changed = true;
}
} else {
if (icon !== "" && icon !== this.defaultIcon) {
editState.changes.icon = node.icon;
node.icon = icon;
editState.changed = true;
} else {
var iconPath = RED.utils.getDefaultNodeIcon(node._def, node);
var currentDefaultIcon = iconPath.module+"/"+iconPath.file;
if (this.defaultIcon !== currentDefaultIcon) {
editState.changes.icon = node.icon;
node.icon = currentDefaultIcon;
editState.changed = true;
}
}
}
}
if (node.type === "subflow") {
var newCategory = $("#subflow-appearance-input-category").val().trim();
if (newCategory === "_custom_") {
newCategory = $("#subflow-appearance-input-custom-category").val().trim();
if (newCategory === "") {
newCategory = node.category;
}
}
if (newCategory === 'subflows') {
newCategory = '';
}
if (newCategory != node.category) {
editState.changes['category'] = node.category;
node.category = newCategory;
editState.changed = true;
}
var oldColor = node.color;
var newColor = $("#red-ui-editor-node-color").val();
if (oldColor !== newColor) {
editState.changes.color = node.color;
node.color = newColor;
editState.changed = true;
RED.utils.clearNodeColorCache();
if (node.type === "subflow") {
var nodeDefinition = RED.nodes.getType(
"subflow:" + node.id
);
nodeDefinition["color"] = newColor;
}
}
}
var showLabel = node._def.hasOwnProperty("showLabel")?node._def.showLabel:true;
if (!$("#node-input-show-label").prop('checked')) {
// Not checked - hide label
if (showLabel) {
// Default to show label
if (node.l !== false) {
editState.changes.l = node.l
editState.changed = true;
}
node.l = false;
} else {
// Node has showLabel:false (eg link nodes)
if (node.hasOwnProperty('l') && node.l) {
editState.changes.l = node.l
editState.changed = true;
}
delete node.l;
}
} else {
// Checked - show label
if (showLabel) {
// Default to show label
if (node.hasOwnProperty('l') && !node.l) {
editState.changes.l = node.l
editState.changed = true;
}
delete node.l;
} else {
if (!node.l) {
editState.changes.l = node.l
editState.changed = true;
}
node.l = true;
}
}
}
}
});
function buildAppearanceForm(container,node) {
var dialogForm = $('<form class="dialog-form form-horizontal" autocomplete="off"></form>').appendTo(container);
var i,row;
if (node.type === "subflow") {
var categoryRow = $("<div/>", {
class: "form-row"
}).appendTo(dialogForm);
$("<label/>", {
for: "subflow-appearance-input-category",
"data-i18n": "editor:subflow.category"
}).appendTo(categoryRow);
var categorySelector = $("<select/>", {
id: "subflow-appearance-input-category"
}).css({
width: "250px"
}).appendTo(categoryRow);
$("<input/>", {
type: "text",
id: "subflow-appearance-input-custom-category"
}).css({
display: "none",
"margin-left": "10px",
width: "calc(100% - 250px)"
}).appendTo(categoryRow);
var categories = RED.palette.getCategories();
categories.sort(function(A,B) {
return A.label.localeCompare(B.label);
})
categories.forEach(function(cat) {
categorySelector.append($("<option/>").val(cat.id).text(cat.label));
})
categorySelector.append($("<option/>").attr('disabled',true).text("---"));
categorySelector.append($("<option/>").val("_custom_").text(RED._("palette.addCategory")));
$("#subflow-appearance-input-category").on("change", function() {
var val = $(this).val();
if (val === "_custom_") {
$("#subflow-appearance-input-category").width(120);
$("#subflow-appearance-input-custom-category").show();
} else {
$("#subflow-appearance-input-category").width(250);
$("#subflow-appearance-input-custom-category").hide();
}
})
$("#subflow-appearance-input-category").val(node.category||"subflows");
var userCount = 0;
var subflowType = "subflow:"+node.id;
// RED.nodes.eachNode(function(n) {
// if (n.type === subflowType) {
// userCount++;
// }
// });
$("#red-ui-editor-subflow-user-count")
.text(RED._("subflow.subflowInstances", {count:node.instances.length})).show();
}
$('<div class="form-row">'+
'<label for="node-input-show-label-btn" data-i18n="editor.label"></label>'+
'<span style="margin-right: 2px;"/>'+
'<input type="checkbox" id="node-input-show-label"/>'+
'</div>').appendTo(dialogForm);
$("#node-input-show-label").toggleButton({
enabledLabel: RED._("editor.show"),
disabledLabel: RED._("editor.hide")
})
if (!node.hasOwnProperty("l")) {
// Show label unless def.showLabel set to false
node.l = node._def.hasOwnProperty("showLabel")?node._def.showLabel:true;
}
$("#node-input-show-label").prop("checked",node.l).trigger("change");
if (node.type === "subflow") {
// subflow template can select its color
var color = node.color ? node.color : "#DDAA99";
var colorRow = $("<div/>", {
class: "form-row"
}).appendTo(dialogForm);
$("<label/>").text(RED._("editor.color")).appendTo(colorRow);
var recommendedColors = [
"#DDAA99",
"#3FADB5", "#87A980", "#A6BBCF",
"#AAAA66", "#C0C0C0", "#C0DEED",
"#C7E9C0", "#D7D7A0", "#D8BFD8",
"#DAC4B4", "#DEB887", "#DEBD5C",
"#E2D96E", "#E6E0F8", "#E7E7AE",
"#E9967A", "#F3B567", "#FDD0A2",
"#FDF0C2", "#FFAAAA", "#FFCC66",
"#FFF0F0", "#FFFFFF"
]
RED.editor.colorPicker.create({
id: "red-ui-editor-node-color",
value: color,
palette: recommendedColors,
sortPalette: function (a, b) {return a.l - b.l;}
}).appendTo(colorRow);
$("#red-ui-editor-node-color").on('change', function(ev) {
// Horribly out of scope...
var colour = $(this).val();
nodeDiv.css('backgroundColor',colour);
var borderColor = RED.utils.getDarkerColor(colour);
if (borderColor !== colour) {
nodeDiv.css('border-color',borderColor)
}
})
}
// If a node has icon property in defaults, the icon of the node cannot be modified. (e.g, ui_button node in dashboard)
if ((!node._def.defaults || !node._def.defaults.hasOwnProperty("icon"))) {
var iconRow = $('<div class="form-row"></div>').appendTo(dialogForm);
$('<label data-i18n="editor.settingIcon">').appendTo(iconRow);
var iconButton = $('<button type="button" class="red-ui-button red-ui-editor-node-appearance-button">').appendTo(iconRow);
$('<i class="fa fa-caret-down"></i>').appendTo(iconButton);
var nodeDiv = $('<div>',{class:"red-ui-search-result-node"}).appendTo(iconButton);
var colour = RED.utils.getNodeColor(node.type, node._def);
var icon_url = RED.utils.getNodeIcon(node._def,node);
nodeDiv.css('backgroundColor',colour);
var borderColor = RED.utils.getDarkerColor(colour);
if (borderColor !== colour) {
nodeDiv.css('border-color',borderColor)
}
var iconContainer = $('<div/>',{class:"red-ui-palette-icon-container"}).appendTo(nodeDiv);
RED.utils.createIconElement(icon_url, iconContainer, true);
iconButton.on("click", function(e) {
e.preventDefault();
var iconPath;
var icon = $("#red-ui-editor-node-icon").val()||"";
if (icon) {
iconPath = RED.utils.separateIconPath(icon);
} else {
iconPath = RED.utils.getDefaultNodeIcon(node._def, node);
}
var backgroundColor = RED.utils.getNodeColor(node.type, node._def);
if (node.type === "subflow") {
backgroundColor = $("#red-ui-editor-node-color").val();
}
RED.editor.iconPicker.show(iconButton,backgroundColor,iconPath,false,function(newIcon) {
$("#red-ui-editor-node-icon").val(newIcon||"");
var icon_url = RED.utils.getNodeIcon(node._def,{type:node.type,icon:newIcon});
RED.utils.createIconElement(icon_url, iconContainer, true);
});
});
RED.popover.tooltip(iconButton, function() {
return $("#red-ui-editor-node-icon").val() || RED._("editor.default");
})
$('<input type="hidden" id="red-ui-editor-node-icon">').val(node.icon).appendTo(iconRow);
}
$('<div class="form-row"><span data-i18n="editor.portLabels"></span></div>').appendTo(dialogForm);
var inputCount = node.inputs || node._def.inputs || 0;
var outputCount = node.outputs || node._def.outputs || 0;
if (node.type === 'subflow') {
inputCount = node.in.length;
outputCount = node.out.length;
}
var inputLabels = node.inputLabels || [];
var outputLabels = node.outputLabels || [];
var inputPlaceholder = node._def.inputLabels?RED._("editor.defaultLabel"):RED._("editor.noDefaultLabel");
var outputPlaceholder = node._def.outputLabels?RED._("editor.defaultLabel"):RED._("editor.noDefaultLabel");
$('<div class="form-row"><span style="margin-left: 50px;" data-i18n="editor.labelInputs"></span><div id="red-ui-editor-node-label-form-inputs"></div></div>').appendTo(dialogForm);
var inputsDiv = $("#red-ui-editor-node-label-form-inputs");
if (inputCount > 0) {
for (i=0;i<inputCount;i++) {
buildLabelRow("input",i,inputLabels[i],inputPlaceholder).appendTo(inputsDiv);
}
} else {
buildLabelRow().appendTo(inputsDiv);
}
$('<div class="form-row"><span style="margin-left: 50px;" data-i18n="editor.labelOutputs"></span><div id="red-ui-editor-node-label-form-outputs"></div></div>').appendTo(dialogForm);
var outputsDiv = $("#red-ui-editor-node-label-form-outputs");
if (outputCount > 0) {
for (i=0;i<outputCount;i++) {
buildLabelRow("output",i,outputLabels[i],outputPlaceholder).appendTo(outputsDiv);
}
} else {
buildLabelRow().appendTo(outputsDiv);
}
}
function refreshLabelForm(container,node) {
var inputPlaceholder = node._def.inputLabels?RED._("editor.defaultLabel"):RED._("editor.noDefaultLabel");
var outputPlaceholder = node._def.outputLabels?RED._("editor.defaultLabel"):RED._("editor.noDefaultLabel");
var inputsDiv = $("#red-ui-editor-node-label-form-inputs");
var outputsDiv = $("#red-ui-editor-node-label-form-outputs");
var inputCount;
var formInputs = $("#node-input-inputs").val();
if (formInputs === undefined) {
if (node.type === 'subflow') {
inputCount = node.in.length;
} else {
inputCount = node.inputs || node._def.inputs || 0;
}
} else {
inputCount = Math.min(1,Math.max(0,parseInt(formInputs)));
if (isNaN(inputCount)) {
inputCount = 0;
}
}
var children = inputsDiv.children();
var childCount = children.length;
if (childCount === 1 && $(children[0]).hasClass('red-ui-editor-node-label-form-none')) {
childCount--;
}
if (childCount < inputCount) {
if (childCount === 0) {
// remove the 'none' placeholder
$(children[0]).remove();
}
for (i = childCount;i<inputCount;i++) {
buildLabelRow("input",i,"",inputPlaceholder).appendTo(inputsDiv);
}
} else if (childCount > inputCount) {
for (i=inputCount;i<childCount;i++) {
$(children[i]).remove();
}
if (inputCount === 0) {
buildLabelRow().appendTo(inputsDiv);
}
}
var outputCount;
var i;
var formOutputs = $("#node-input-outputs").val();
if (formOutputs === undefined) {
if (node.type === 'subflow') {
outputCount = node.out.length;
} else {
inputCount = node.outputs || node._def.outputs || 0;
}
} else if (isNaN(formOutputs)) {
var outputMap = JSON.parse(formOutputs);
var keys = Object.keys(outputMap);
children = outputsDiv.children();
childCount = children.length;
if (childCount === 1 && $(children[0]).hasClass('red-ui-editor-node-label-form-none')) {
childCount--;
}
outputCount = 0;
var rows = [];
keys.forEach(function(p) {
var row = $("#red-ui-editor-node-label-form-output-"+p).parent();
if (row.length === 0 && outputMap[p] !== -1) {
if (childCount === 0) {
$(children[0]).remove();
childCount = -1;
}
row = buildLabelRow("output",p,"",outputPlaceholder);
} else {
row.detach();
}
if (outputMap[p] !== -1) {
outputCount++;
rows.push({i:parseInt(outputMap[p]),r:row});
}
});
rows.sort(function(A,B) {
return A.i-B.i;
})
rows.forEach(function(r,i) {
r.r.find("label").text((i+1)+".");
r.r.appendTo(outputsDiv);
})
if (rows.length === 0) {
buildLabelRow("output",i,"").appendTo(outputsDiv);
} else {
}
} else {
outputCount = Math.max(0,parseInt(formOutputs));
}
children = outputsDiv.children();
childCount = children.length;
if (childCount === 1 && $(children[0]).hasClass('red-ui-editor-node-label-form-none')) {
childCount--;
}
if (childCount < outputCount) {
if (childCount === 0) {
// remove the 'none' placeholder
$(children[0]).remove();
}
for (i = childCount;i<outputCount;i++) {
buildLabelRow("output",i,"").appendTo(outputsDiv);
}
} else if (childCount > outputCount) {
for (i=outputCount;i<childCount;i++) {
$(children[i]).remove();
}
if (outputCount === 0) {
buildLabelRow().appendTo(outputsDiv);
}
}
}
function buildLabelRow(type, index, value, placeHolder) {
var result = $('<div>',{class:"red-ui-editor-node-label-form-row"});
if (type === undefined) {
$('<span>').text(RED._("editor.noDefaultLabel")).appendTo(result);
result.addClass("red-ui-editor-node-label-form-none");
} else {
result.addClass("");
var id = "red-ui-editor-node-label-form-"+type+"-"+index;
$('<label>',{for:id}).text((index+1)+".").appendTo(result);
var input = $('<input>',{type:"text",id:id, placeholder: placeHolder}).val(value).appendTo(result);
var clear = $('<button type="button" class="red-ui-button red-ui-button-small"><i class="fa fa-times"></i></button>').appendTo(result);
clear.on("click", function(evt) {
evt.preventDefault();
input.val("");
})
}
return result;
}
function updateLabels(node, changes, outputMap) {
var inputLabels = $("#red-ui-editor-node-label-form-inputs").children().find("input");
var outputLabels = $("#red-ui-editor-node-label-form-outputs").children().find("input");
var hasNonBlankLabel = false;
var changed = false;
var newValue = inputLabels.map(function() {
var v = $(this).val();
hasNonBlankLabel = hasNonBlankLabel || v!== "";
return v;
}).toArray().slice(0,node.inputs);
if ((node.inputLabels === undefined && hasNonBlankLabel) ||
(node.inputLabels !== undefined && JSON.stringify(newValue) !== JSON.stringify(node.inputLabels))) {
changes.inputLabels = node.inputLabels;
node.inputLabels = newValue;
changed = true;
}
hasNonBlankLabel = false;
newValue = new Array(node.outputs);
outputLabels.each(function() {
var index = $(this).attr('id').substring("red-ui-editor-node-label-form-output-".length);
if (outputMap && outputMap.hasOwnProperty(index)) {
index = parseInt(outputMap[index]);
if (index === -1) {
return;
}
}
var v = $(this).val();
hasNonBlankLabel = hasNonBlankLabel || v!== "";
newValue[index] = v;
});
if ((node.outputLabels === undefined && hasNonBlankLabel) ||
(node.outputLabels !== undefined && JSON.stringify(newValue) !== JSON.stringify(node.outputLabels))) {
changes.outputLabels = node.outputLabels;
node.outputLabels = newValue;
changed = true;
}
return changed;
}
})();

View File

@ -0,0 +1,70 @@
;(function() {
RED.editor.registerEditPane("editor-tab-description", function(node) {
return {
label: RED._("editor-tab.description"),
name: RED._("editor-tab.description"),
iconClass: "fa fa-file-text-o",
create: function(container) {
this.editor = buildDescriptionForm(container,node);
RED.e = this.editor;
},
resize: function(size) {
this.editor.resize();
},
close: function() {
this.editor.destroy();
this.editor = null;
},
show: function() {
this.editor.focus();
},
apply: function(editState) {
var oldInfo = node.info;
var newInfo = this.editor.getValue();
if (!!oldInfo) {
// Has existing info property
if (newInfo.trim() === "") {
// New value is blank - remove the property
editState.changed = true;
editState.changes.info = oldInfo;
delete node.info;
} else if (newInfo !== oldInfo) {
// New value is different
editState.changed = true;
editState.changes.info = oldInfo;
node.info = newInfo;
}
} else {
// No existing info
if (newInfo.trim() !== "") {
// New value is not blank
editState.changed = true;
editState.changes.info = undefined;
node.info = newInfo;
}
}
}
}
});
function buildDescriptionForm(container,node) {
var dialogForm = $('<form class="dialog-form form-horizontal" autocomplete="off"></form>').appendTo(container);
var toolbarRow = $('<div></div>').appendTo(dialogForm);
var row = $('<div class="form-row node-text-editor-row" style="position:relative; padding-top: 4px; height: 100%"></div>').appendTo(dialogForm);
var editorId = "node-info-input-info-editor-"+Math.floor(1000*Math.random());
$('<div style="height: 100%" class="node-text-editor" id="'+editorId+'" ></div>').appendTo(row);
var nodeInfoEditor = RED.editor.createEditor({
id: editorId,
mode: 'ace/mode/markdown',
value: ""
});
if (node.info) {
nodeInfoEditor.getSession().setValue(node.info, -1);
}
node.infoEditor = nodeInfoEditor;
return nodeInfoEditor;
}
})();

View File

@ -0,0 +1,69 @@
;(function() {
RED.editor.registerEditPane("editor-tab-envProperties", function(node) {
return {
label: RED._("editor-tab.envProperties"),
name: RED._("editor-tab.envProperties"),
iconClass: "fa fa-list",
create: function(container) {
var form = $('<form class="dialog-form form-horizontal"></form>').appendTo(container);
var listContainer = $('<div class="form-row node-input-env-container-row"></div>').appendTo(form);
this.list = $('<ol></ol>').appendTo(listContainer);
RED.editor.envVarList.create(this.list, node);
},
resize: function(size) {
this.list.editableList('height',size.height);
},
close: function() {
},
apply: function(editState) {
var old_env = node.env;
var new_env = [];
if (/^subflow:/.test(node.type)) {
new_env = RED.subflow.exportSubflowInstanceEnv(node);
}
// Get the values from the Properties table tab
var items = this.list.editableList('items');
items.each(function (i,el) {
var data = el.data('data');
var item;
if (data.nameField && data.valueField) {
item = {
name: data.nameField.val(),
value: data.valueField.typedInput("value"),
type: data.valueField.typedInput("type")
}
if (item.name.trim() !== "") {
new_env.push(item);
}
}
});
if (new_env && new_env.length > 0) {
new_env.forEach(function(prop) {
if (prop.type === "cred") {
node.credentials = node.credentials || {_:{}};
node.credentials[prop.name] = prop.value;
node.credentials['has_'+prop.name] = (prop.value !== "");
if (prop.value !== '__PWRD__') {
editState.changed = true;
}
delete prop.value;
}
});
}
if (!isSameObj(old_env, new_env)) {
node.env = new_env;
editState.changes.env = node.env;
editState.changed = true;
}
}
}
});
function isSameObj(env0, env1) {
return (JSON.stringify(env0) === JSON.stringify(env1));
}
})();

View File

@ -0,0 +1,60 @@
;(function() {
RED.editor.registerEditPane("editor-tab-flow-properties", function(node) {
return {
label: RED._("editor-tab.properties"),
name: RED._("editor-tab.properties"),
iconClass: "fa fa-cog",
create: function(container) {
var dialogForm = $('<form id="dialog-form" class="form-horizontal"></form>').appendTo(container);
$('<div class="form-row">'+
'<label for="node-input-name" data-i18n="[append]editor:common.label.name"><i class="fa fa-tag"></i> </label>'+
'<input type="text" id="node-input-name" data-i18n="[placeholder]common.label.name">'+
'</div>').appendTo(dialogForm);
var row = $('<div class="form-row node-text-editor-row">'+
'<label for="node-input-info" data-i18n="editor:workspace.info" style="width:300px;"></label>'+
'<div style="min-height:150px;" class="node-text-editor" id="node-input-info"></div>'+
'</div>').appendTo(dialogForm);
this.tabflowEditor = RED.editor.createEditor({
id: 'node-input-info',
mode: 'ace/mode/markdown',
value: ""
});
$('<input type="text" style="display: none;" />').prependTo(dialogForm);
dialogForm.on("submit", function(e) { e.preventDefault();});
$("#node-input-name").val(node.label);
RED.text.bidi.prepareInput($("#node-input-name"));
this.tabflowEditor.getSession().setValue(node.info || "", -1);
},
resize: function(size) {
$("#node-input-info").css("height", (size.height-70)+"px");
this.tabflowEditor.resize();
},
close: function() {
this.tabflowEditor.destroy();
},
apply: function(editState) {
var label = $( "#node-input-name" ).val();
if (node.label != label) {
editState.changes.label = node.label;
editState.changed = true;
node.label = label;
}
var info = this.tabflowEditor.getValue();
if (node.info !== info) {
editState.changes.info = node.info;
editState.changed = true;
node.info = info;
}
$("#red-ui-tab-"+(node.id.replace(".","-"))).toggleClass('red-ui-workspace-disabled',!!node.disabled);
$("#red-ui-workspace").toggleClass("red-ui-workspace-disabled",!!node.disabled);
}
}
});
})();

View File

@ -0,0 +1,181 @@
;(function() {
RED.editor.registerEditPane("editor-tab-properties", function(node) {
return {
label: RED._("editor-tab.properties"),
name: RED._("editor-tab.properties"),
iconClass: "fa fa-cog",
create: function(container) {
var nodeType = node.type;
if (node.type === "subflow") {
nodeType = "subflow-template";
} else if (node.type.substring(0,8) == "subflow:") {
nodeType = "subflow";
}
var i18nNamespace;
if (node._def.set.module === "node-red") {
i18nNamespace = "node-red";
} else {
i18nNamespace = node._def.set.id;
}
var formStyle = "dialog-form";
this.inputClass = "node-input";
if (node._def.category === "config" && nodeType !== "group") {
this.inputClass = "node-config-input";
formStyle = "node-config-dialog-edit-form";
}
RED.editor.buildEditForm(container,formStyle,nodeType,i18nNamespace,node);
},
resize: function(size) {
if (node && node._def.oneditresize) {
try {
node._def.oneditresize.call(node,size);
} catch(err) {
console.log("oneditresize",node.id,node.type,err.toString());
}
}
},
close: function() {
},
apply: function(editState) {
var newValue;
var d;
if (node._def.defaults) {
for (d in node._def.defaults) {
if (node._def.defaults.hasOwnProperty(d)) {
var input = $("#"+this.inputClass+"-"+d);
if (input.attr('type') === "checkbox") {
newValue = input.prop('checked');
} else if (input.prop("nodeName") === "select" && input.attr("multiple") === "multiple") {
// An empty select-multiple box returns null.
// Need to treat that as an empty array.
newValue = input.val();
if (newValue == null) {
newValue = [];
}
} else if ("format" in node._def.defaults[d] && node._def.defaults[d].format !== "" && input[0].nodeName === "DIV") {
newValue = input.text();
} else {
newValue = input.val();
}
if (newValue != null) {
if (d === "outputs") {
if (newValue.trim() === "") {
continue;
}
if (isNaN(newValue)) {
editState.outputMap = JSON.parse(newValue);
var outputCount = 0;
var outputsChanged = false;
var keys = Object.keys(editState.outputMap);
keys.forEach(function(p) {
if (isNaN(p)) {
// New output;
outputCount ++;
delete editState.outputMap[p];
} else {
editState.outputMap[p] = editState.outputMap[p]+"";
if (editState.outputMap[p] !== "-1") {
outputCount++;
if (editState.outputMap[p] !== p) {
// Output moved
outputsChanged = true;
} else {
delete editState.outputMap[p];
}
} else {
// Output removed
outputsChanged = true;
}
}
});
newValue = outputCount;
if (outputsChanged) {
editState.changed = true;
}
} else {
newValue = parseInt(newValue);
}
}
if (node._def.defaults[d].type) {
if (newValue == "_ADD_") {
newValue = "";
}
}
if (node[d] != newValue) {
if (node._def.defaults[d].type) {
// Change to a related config node
var configNode = RED.nodes.node(node[d]);
if (configNode) {
var users = configNode.users;
users.splice(users.indexOf(node),1);
RED.events.emit("nodes:change",configNode);
}
configNode = RED.nodes.node(newValue);
if (configNode) {
configNode.users.push(node);
RED.events.emit("nodes:change",configNode);
}
}
editState.changes[d] = node[d];
node[d] = newValue;
editState.changed = true;
}
}
}
}
}
if (node._def.credentials) {
var credDefinition = node._def.credentials;
var credsChanged = updateNodeCredentials(node,credDefinition,this.inputClass);
editState.changed = editState.changed || credsChanged;
}
}
}
});
/**
* Update the node credentials from the edit form
* @param node - the node containing the credentials
* @param credDefinition - definition of the credentials
* @param prefix - prefix of the input fields
* @return {boolean} whether anything has changed
*/
function updateNodeCredentials(node, credDefinition, prefix) {
var changed = false;
if (!node.credentials) {
node.credentials = {_:{}};
} else if (!node.credentials._) {
node.credentials._ = {};
}
for (var cred in credDefinition) {
if (credDefinition.hasOwnProperty(cred)) {
var input = $("#" + prefix + '-' + cred);
if (input.length > 0) {
var value = input.val();
if (credDefinition[cred].type == 'password') {
node.credentials['has_' + cred] = (value !== "");
if (value == '__PWRD__') {
continue;
}
changed = true;
}
node.credentials[cred] = value;
if (value != node.credentials._[cred]) {
changed = true;
}
}
}
}
return changed;
}
})();

View File

@ -0,0 +1,179 @@
(function() {
var _subflowModulePaneTemplate = '<form class="dialog-form form-horizontal" autocomplete="off">'+
'<div class="form-row">'+
'<label for="subflow-input-module-module" data-i18n="[append]editor:subflow.module"><i class="fa fa-cube"></i> </label>'+
'<input style="width: calc(100% - 110px)" type="text" id="subflow-input-module-module" data-i18n="[placeholder]common.label.name">'+
'</div>'+
'<div class="form-row">'+
'<label for="subflow-input-module-type" data-i18n="[append]editor:subflow.type"> </label>'+
'<input style="width: calc(100% - 110px)" type="text" id="subflow-input-module-type">'+
'</div>'+
'<div class="form-row">'+
'<label for="subflow-input-module-version" data-i18n="[append]editor:subflow.version"></label>'+
'<input style="width: calc(100% - 110px)" type="text" id="subflow-input-module-version" data-i18n="[placeholder]editor:subflow.versionPlaceholder">'+
'</div>'+
'<div class="form-row">'+
'<label for="subflow-input-module-desc" data-i18n="[append]editor:subflow.desc"></label>'+
'<input style="width: calc(100% - 110px)" type="text" id="subflow-input-module-desc">'+
'</div>'+
'<div class="form-row">'+
'<label for="subflow-input-module-license" data-i18n="[append]editor:subflow.license"></label>'+
'<input style="width: calc(100% - 110px)" type="text" id="subflow-input-module-license">'+
'</div>'+
'<div class="form-row">'+
'<label for="subflow-input-module-author" data-i18n="[append]editor:subflow.author"></label>'+
'<input style="width: calc(100% - 110px)" type="text" id="subflow-input-module-author" data-i18n="[placeholder]editor:subflow.authorPlaceholder">'+
'</div>'+
'<div class="form-row">'+
'<label for="subflow-input-module-keywords" data-i18n="[append]editor:subflow.keys"></label>'+
'<input style="width: calc(100% - 110px)" type="text" id="subflow-input-module-keywords" data-i18n="[placeholder]editor:subflow.keysPlaceholder">'+
'</div>'+
'</form>';
RED.editor.registerEditPane("editor-tab-subflow-module", function(node) {
return {
label: RED._("editor-tab.module"),
name: RED._("editor-tab.module"),
iconClass: "fa fa-cube",
create: function(container) {
buildModuleForm(container, node);
},
resize: function(size) {
},
close: function() {
},
apply: function(editState) {
var newMeta = exportSubflowModuleProperties(node);
if (!isSameObj(node.meta,newMeta)) {
editState.changes.meta = node.meta;
node.meta = newMeta;
editState.changed = true;
}
}
}
});
function isSameObj(env0, env1) {
return (JSON.stringify(env0) === JSON.stringify(env1));
}
function setupInputValidation(input,validator) {
var errorTip;
var validateTimeout;
var validateFunction = function() {
if (validateTimeout) {
return;
}
validateTimeout = setTimeout(function() {
var error = validator(input.val());
// if (!error && errorTip) {
// errorTip.close();
// errorTip = null;
// } else if (error && !errorTip) {
// errorTip = RED.popover.create({
// tooltip: true,
// target:input,
// size: "small",
// direction: "bottom",
// content: error,
// }).open();
// }
input.toggleClass("input-error",!!error);
validateTimeout = null;
})
}
input.on("change keyup paste", validateFunction);
}
function buildModuleForm(container, node) {
$(_subflowModulePaneTemplate).appendTo(container);
var moduleProps = node.meta || {};
[
'module',
'type',
'version',
'author',
'desc',
'keywords',
'license'
].forEach(function(property) {
$("#subflow-input-module-"+property).val(moduleProps[property]||"")
})
$("#subflow-input-module-type").attr("placeholder",node.id);
setupInputValidation($("#subflow-input-module-module"), function(newValue) {
newValue = newValue.trim();
var isValid = newValue.length < 215;
isValid = isValid && !/^[._]/.test(newValue);
isValid = isValid && !/[A-Z]/.test(newValue);
if (newValue !== encodeURIComponent(newValue)) {
var m = /^@([^\/]+)\/([^\/]+)$/.exec(newValue);
if (m) {
isValid = isValid && (m[1] === encodeURIComponent(m[1]) && m[2] === encodeURIComponent(m[2]))
} else {
isValid = false;
}
}
return isValid?"":"Invalid module name"
})
setupInputValidation($("#subflow-input-module-version"), function(newValue) {
newValue = newValue.trim();
var isValid = newValue === "" ||
/^(\d|[1-9]\d*)\.(\d|[1-9]\d*)\.(\d|[1-9]\d*)(-(0|[1-9A-Za-z-][0-9A-Za-z-]*|[0-9]*[A-Za-z-][0-9A-Za-z-]*)(\.(0|[1-9A-Za-z-][0-9A-Za-z-]*|[0-9]*[A-Za-z-][0-9A-Za-z-]*))*)?(\+[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?$/.test(newValue);
return isValid?"":"Invalid version number"
})
var licenses = ["none", "Apache-2.0", "BSD-3-Clause", "BSD-2-Clause", "GPL-2.0", "GPL-3.0", "MIT", "MPL-2.0", "CDDL-1.0", "EPL-2.0"];
var typedLicenses = {
types: licenses.map(function(l) {
return {
value: l,
label: l === "none" ? RED._("editor:subflow.licenseNone") : l,
hasValue: false
};
})
}
typedLicenses.types.push({
value:"_custom_", label:RED._("editor:subflow.licenseOther"), icon:"red/images/typedInput/az.svg"
})
if (!moduleProps.license) {
typedLicenses.default = "none";
} else if (licenses.indexOf(moduleProps.license) > -1) {
typedLicenses.default = moduleProps.license;
} else {
typedLicenses.default = "_custom_";
}
$("#subflow-input-module-license").typedInput(typedLicenses)
}
function exportSubflowModuleProperties(node) {
var value;
var moduleProps = {};
[
'module',
'type',
'version',
'author',
'desc',
'keywords'
].forEach(function(property) {
value = $("#subflow-input-module-"+property).val().trim();
if (value) {
moduleProps[property] = value;
}
})
var selectedLicenseType = $("#subflow-input-module-license").typedInput("type");
if (selectedLicenseType === '_custom_') {
value = $("#subflow-input-module-license").val();
if (value) {
moduleProps.license = value;
}
} else if (selectedLicenseType !== "none") {
moduleProps.license = selectedLicenseType;
}
return moduleProps;
}
})();

View File

@ -87,16 +87,18 @@ RED.group = (function() {
"label-position": "nw"
};
var groupDef = {
defaults:{
name:{value:""},
style:{value:{label:true}},
nodes:{value:[]}
nodes:{value:[]},
env: {value:[]},
},
category: "config",
oneditprepare: function() {
var style = this.style || {};
RED.colorPicker.create({
RED.editor.colorPicker.create({
id:"node-input-style-stroke",
value: style.stroke || defaultGroupStyle.stroke || "#a4a4a4",
palette: colorPalette,
@ -107,7 +109,7 @@ RED.group = (function() {
none: true,
opacity: style.hasOwnProperty('stroke-opacity')?style['stroke-opacity']:(defaultGroupStyle.hasOwnProperty('stroke-opacity')?defaultGroupStyle['stroke-opacity']:1.0)
}).appendTo("#node-input-row-style-stroke");
RED.colorPicker.create({
RED.editor.colorPicker.create({
id:"node-input-style-fill",
value: style.fill || defaultGroupStyle.fill ||"none",
palette: colorPalette,
@ -124,7 +126,7 @@ RED.group = (function() {
value:style["label-position"] || "nw"
}).appendTo("#node-input-row-style-label-position");
RED.colorPicker.create({
RED.editor.colorPicker.create({
id:"node-input-style-color",
value: style.color || defaultGroupStyle.color ||"#a4a4a4",
palette: colorPalette,
@ -144,7 +146,6 @@ RED.group = (function() {
})
$("#node-input-style-label").prop("checked", this.style.label)
$("#node-input-style-label").trigger("change");
},
oneditresize: function(size) {
},
@ -183,7 +184,9 @@ RED.group = (function() {
var activateUngroup = false;
var activateMerge = false;
var activateRemove = false;
var singleGroupSelected = false;
if (activateGroup) {
singleGroupSelected = selection.nodes.length === 1 && selection.nodes[0].type === 'group';
selection.nodes.forEach(function (n) {
if (n.type === "group") {
activateUngroup = true;
@ -200,6 +203,8 @@ RED.group = (function() {
RED.menu.setDisabled("menu-item-group-ungroup", !activateUngroup);
RED.menu.setDisabled("menu-item-group-merge", !activateMerge);
RED.menu.setDisabled("menu-item-group-remove", !activateRemove);
RED.menu.setDisabled("menu-item-edit-copy-group-style", !singleGroupSelected);
RED.menu.setDisabled("menu-item-edit-paste-group-style", !activateUngroup);
});
RED.actions.add("core:group-selection", function() { groupSelection() })
@ -252,6 +257,7 @@ RED.group = (function() {
if (selection.nodes && selection.nodes.length === 1 && selection.nodes[0].type === 'group') {
groupStyleClipboard = JSON.parse(JSON.stringify(selection.nodes[0].style));
RED.notify(RED._("clipboard.groupStyleCopied"),{id:"clipboard"})
RED.menu.setDisabled("menu-item-edit-paste-group-style", false)
}
}
function pasteGroupStyle() {

View File

@ -131,7 +131,7 @@ RED.keyboard = (function() {
return mergedKeymap;
}
function init() {
function init(done) {
// Migrate from pre-0.18
migrateOldKeymap();
@ -164,6 +164,7 @@ RED.keyboard = (function() {
}
}
}
done();
});
RED.userSettings.add({
@ -174,6 +175,9 @@ RED.keyboard = (function() {
setTimeout(function() {
$("#red-ui-settings-tab-keyboard-filter").trigger("focus");
},200);
},
close: function() {
RED.menu.refreshShortcuts();
}
})
}
@ -239,7 +243,13 @@ RED.keyboard = (function() {
function resolveKeyEvent(evt) {
var slot = partialState||handlers;
if (evt.ctrlKey || evt.metaKey) {
// We cheat with MacOS CMD key and consider it the same as Ctrl.
// That means we don't have to have separate keymaps for different OS.
// It mostly works.
// One exception is shortcuts that include both Cmd and Ctrl. We don't
// support them - but we need to make sure we don't block browser-specific
// shortcuts (such as Cmd-Ctrl-F for fullscreen).
if ((evt.ctrlKey || evt.metaKey) && (evt.ctrlKey !== evt.metaKey)) {
slot = slot.ctrl;
}
if (slot && evt.shiftKey) {

View File

@ -536,7 +536,7 @@ RED.library = (function() {
// evt.preventDefault();
// var icon = libraryFields['icon'].input.val() || "";
// var iconPath = (icon ? RED.utils.separateIconPath(icon) : {});
// RED.editor.showIconPicker(iconButton, null, iconPath, true, function (newIcon) {
// RED.editor.iconPicker.show(iconButton, null, iconPath, true, function (newIcon) {
// iconButton.empty();
// var path = newIcon || "";
// var newPath = RED.utils.separateIconPath(path);

View File

@ -45,6 +45,22 @@ RED.notifications = (function() {
var persistentNotifications = {};
var shade = (function() {
var shadeUsers = 0;
return {
show: function() {
shadeUsers++;
$("#red-ui-full-shade").show();
},
hide: function() {
shadeUsers--;
if (shadeUsers === 0) {
$("#red-ui-full-shade").hide();
}
}
}
})();
var currentNotifications = [];
var c = 0;
function notify(msg,type,fixed,timeout) {
@ -54,6 +70,10 @@ RED.notifications = (function() {
fixed = options.fixed;
timeout = options.timeout;
type = options.type;
} else {
options.type = type;
options.fixed = fixed;
options.timeout = options.timeout;
}
if (options.id && persistentNotifications.hasOwnProperty(options.id)) {
@ -62,7 +82,7 @@ RED.notifications = (function() {
}
if (options.modal) {
$("#red-ui-full-shade").show();
shade.show();
}
if (currentNotifications.length > 4) {
@ -79,6 +99,8 @@ RED.notifications = (function() {
var n = document.createElement("div");
n.id="red-ui-notification-"+c;
n.className = "red-ui-notification";
n.options = options;
n.fixed = fixed;
if (type) {
n.className = "red-ui-notification red-ui-notification-"+type;
@ -115,7 +137,6 @@ RED.notifications = (function() {
})
}
$("#red-ui-notifications").append(n);
if (!RED.notifications.hide) {
$(n).slideDown(300);
@ -141,8 +162,8 @@ RED.notifications = (function() {
} else {
nn.parentNode.removeChild(nn);
}
if (options.modal) {
$("#red-ui-full-shade").hide();
if (nn.options.modal) {
shade.hide();
}
};
})();
@ -173,7 +194,7 @@ RED.notifications = (function() {
n.update = (function() {
var nn = n;
return function(msg,options) {
return function(msg,newOptions) {
if (typeof msg === "string") {
if (!/<p>/i.test(msg)) {
msg = "<p>"+msg+"</p>";
@ -182,16 +203,31 @@ RED.notifications = (function() {
} else {
$(nn).empty().append(msg);
}
var timeout;
if (typeof options === 'number') {
timeout = options;
} else if (options !== undefined) {
if (!options.fixed) {
timeout = options.timeout || 5000;
var newTimeout;
if (typeof newOptions === 'number') {
newTimeout = newOptions;
nn.options.timeout = newTimeout;
} else if (newOptions !== undefined) {
if (!options.modal && newOptions.modal) {
nn.options.modal = true;
shade.show();
} else if (options.modal && newOptions.modal === false) {
nn.options.modal = false;
shade.hide();
}
if (options.buttons) {
var newType = newOptions.hasOwnProperty('type')?newOptions.type:type;
if (newType) {
n.className = "red-ui-notification red-ui-notification-"+newType;
}
if (!fixed || newOptions.fixed === false) {
newTimeout = (newOptions.hasOwnProperty('timeout')?newOptions.timeout:timeout)||5000;
}
if (newOptions.buttons) {
var buttonSet = $('<div style="margin-top: 20px;" class="ui-dialog-buttonset"></div>').appendTo(nn)
options.buttons.forEach(function(buttonDef) {
newOptions.buttons.forEach(function(buttonDef) {
var b = $('<button>').text(buttonDef.text).on("click", buttonDef.click).appendTo(buttonSet);
if (buttonDef.id) {
b.attr('id',buttonDef.id);
@ -202,15 +238,22 @@ RED.notifications = (function() {
})
}
}
if (timeout !== undefined && timeout > 0) {
$(nn).off("click.red-ui-notification-close");
if (newTimeout !== undefined && newTimeout > 0) {
window.clearTimeout(nn.timeoutid);
nn.timeoutid = window.setTimeout(nn.close,timeout);
nn.timeoutid = window.setTimeout(nn.close,newTimeout);
setTimeout(function() {
$(nn).on("click.red-ui-notification-close", function() {
nn.close();
window.clearTimeout(nn.timeoutid);
});
},50);
} else {
window.clearTimeout(nn.timeoutid);
}
if (nn.hidden) {
nn.showNotification();
} else if (!options || !options.silent){
} else if (!newOptions || !newOptions.silent){
$(nn).addClass("red-ui-notification-shake-horizontal");
setTimeout(function() {
$(nn).removeClass("red-ui-notification-shake-horizontal");
@ -221,7 +264,7 @@ RED.notifications = (function() {
})();
if (!fixed) {
$(n).on("click", (function() {
$(n).on("click.red-ui-notification-close", (function() {
var nn = n;
return function() {
nn.close();

View File

@ -333,7 +333,10 @@ RED.palette.editor = (function() {
nodeEntry.versionSpan.html(moduleInfo.version+' <i class="fa fa-long-arrow-right"></i> '+moduleInfo.pending_version).appendTo(nodeEntry.metaRow)
nodeEntry.updateButton.text(RED._('palette.editor.updated')).addClass('disabled').css('display', 'inline-block');
} else if (loadedIndex.hasOwnProperty(module)) {
if (semVerCompare(loadedIndex[module].version,moduleInfo.version) > 0) {
if (updateAllowed &&
semVerCompare(loadedIndex[module].version,moduleInfo.version) > 0 &&
RED.utils.checkModuleAllowed(module,null,updateAllowList,updateDenyList)
) {
nodeEntry.updateButton.show();
nodeEntry.updateButton.text(RED._('palette.editor.update',{version:loadedIndex[module].version}));
} else {
@ -484,6 +487,9 @@ RED.palette.editor = (function() {
var installAllowList = ['*'];
var installDenyList = [];
var updateAllowed = true;
var updateAllowList = ['*'];
var updateDenyList = [];
function init() {
if (RED.settings.get('externalModules.palette.allowInstall', true) === false) {
@ -498,6 +504,17 @@ RED.palette.editor = (function() {
installAllowList = RED.utils.parseModuleList(installAllowList);
installDenyList = RED.utils.parseModuleList(installDenyList);
var settingsUpdateAllowList = RED.settings.get("externalModules.palette.allowUpdateList")
var settingsUpdateDenyList = RED.settings.get("externalModules.palette.denyUpdateList")
if (settingsUpdateAllowList || settingsUpdateDenyList) {
updateAllowList = settingsUpdateAllowList;
updateDenyList = settingsUpdateDenyList;
}
updateAllowList = RED.utils.parseModuleList(updateAllowList);
updateDenyList = RED.utils.parseModuleList(updateDenyList);
updateAllowed = RED.settings.get("externalModules.palette.allowUpdate",true);
createSettingsPane();
RED.userSettings.add({

View File

@ -2387,6 +2387,7 @@ RED.projects = (function() {
return {
init: init,
showStartup: function() {
console.warn("showStartup")
if (!RED.user.hasPermission("projects.write")) {
RED.notify(RED._("user.errors.notAuthorized"),"error");
return;

View File

@ -16,8 +16,6 @@
RED.subflow = (function() {
var currentLocale = "en-US";
var _subflowEditTemplate = '<script type="text/x-red" data-template-name="subflow">'+
'<div class="form-row">'+
'<label for="node-input-name" data-i18n="[append]editor:common.label.name"><i class="fa fa-tag"></i> </label>'+
@ -37,7 +35,7 @@ RED.subflow = (function() {
'<div id="subflow-env-tabs-content">'+
'<div id="subflow-env-tab-edit">'+
'<div class="form-row node-input-env-container-row" id="subflow-input-edit-ui">'+
'<ol class="red-ui-editor-subflow-env-list" id="node-input-env-container"></ol>'+
'<ol id="node-input-env-container"></ol>'+
'<div class="node-input-env-locales-row"><i class="fa fa-language"></i> <select id="subflow-input-env-locale"></select></div>'+
'</div>'+
'</div>'+
@ -47,37 +45,6 @@ RED.subflow = (function() {
'</div>'+
'</script>';
var _subflowModulePaneTemplate = '<form class="dialog-form form-horizontal" autocomplete="off">'+
'<div class="form-row">'+
'<label for="subflow-input-module-module" data-i18n="[append]editor:subflow.module"><i class="fa fa-cube"></i> </label>'+
'<input style="width: calc(100% - 110px)" type="text" id="subflow-input-module-module" data-i18n="[placeholder]common.label.name">'+
'</div>'+
'<div class="form-row">'+
'<label for="subflow-input-module-type" data-i18n="[append]editor:subflow.type"> </label>'+
'<input style="width: calc(100% - 110px)" type="text" id="subflow-input-module-type">'+
'</div>'+
'<div class="form-row">'+
'<label for="subflow-input-module-version" data-i18n="[append]editor:subflow.version"></label>'+
'<input style="width: calc(100% - 110px)" type="text" id="subflow-input-module-version" data-i18n="[placeholder]editor:subflow.versionPlaceholder">'+
'</div>'+
'<div class="form-row">'+
'<label for="subflow-input-module-desc" data-i18n="[append]editor:subflow.desc"></label>'+
'<input style="width: calc(100% - 110px)" type="text" id="subflow-input-module-desc">'+
'</div>'+
'<div class="form-row">'+
'<label for="subflow-input-module-license" data-i18n="[append]editor:subflow.license"></label>'+
'<input style="width: calc(100% - 110px)" type="text" id="subflow-input-module-license">'+
'</div>'+
'<div class="form-row">'+
'<label for="subflow-input-module-author" data-i18n="[append]editor:subflow.author"></label>'+
'<input style="width: calc(100% - 110px)" type="text" id="subflow-input-module-author" data-i18n="[placeholder]editor:subflow.authorPlaceholder">'+
'</div>'+
'<div class="form-row">'+
'<label for="subflow-input-module-keywords" data-i18n="[append]editor:subflow.keys"></label>'+
'<input style="width: calc(100% - 110px)" type="text" id="subflow-input-module-keywords" data-i18n="[placeholder]editor:subflow.keysPlaceholder">'+
'</div>'+
'</form>';
function findAvailableSubflowIOPosition(subflow,isInput) {
var pos = {x:50,y:30};
if (!isInput) {
@ -909,7 +876,6 @@ RED.subflow = (function() {
* Create interface for controlling env var UI definition
*/
function buildEnvControl(envList,node) {
var tabs = RED.tabs.create({
id: "subflow-env-tabs",
onchange: function(tab) {
@ -950,588 +916,11 @@ RED.subflow = (function() {
locales.val(locale);
locales.on("change", function() {
currentLocale = $(this).val();
var items = $("#node-input-env-container").editableList("items");
items.each(function (i, item) {
var entry = $(this).data('data');
var labelField = entry.ui.labelField;
labelField.val(lookupLabel(entry.ui.label, "", currentLocale));
if (labelField.timeout) {
clearTimeout(labelField.timeout);
delete labelField.timeout;
}
labelField.addClass("input-updated");
labelField.timeout = setTimeout(function() {
delete labelField.timeout
labelField.removeClass("input-updated");
},3000);
});
RED.editor.envVarList.setLocale($(this).val(), $("#node-input-env-container"));
});
RED.editor.envVarList.setLocale(locale);
}
var DEFAULT_ENV_TYPE_LIST = ['str','num','bool','json','bin','env'];
var DEFAULT_ENV_TYPE_LIST_INC_CRED = ['str','num','bool','json','bin','env','cred'];
/**
* Create env var edit interface
* @param container - container
* @param node - subflow node
*/
function buildPropertiesList(envContainer, node) {
var isTemplateNode = (node.type === "subflow");
if (isTemplateNode) {
buildEnvControl(envContainer, node);
}
envContainer
.css({
'min-height':'150px',
'min-width':'450px'
})
.editableList({
header: isTemplateNode?$('<div><div><div></div><div data-i18n="common.label.name"></div><div data-i18n="editor-tab.defaultValue"></div><div></div></div></div>'):undefined,
addItem: function(container, i, opt) {
// If this is an instance node, these are properties unique to
// this instance - ie opt.parent will not be defined.
if (isTemplateNode) {
container.addClass("red-ui-editor-subflow-env-editable")
}
var envRow = $('<div/>').appendTo(container);
var nameField = null;
var valueField = null;
nameField = $('<input/>', {
class: "node-input-env-name",
type: "text",
placeholder: RED._("common.label.name")
}).attr("autocomplete","disable").appendTo(envRow).val(opt.name);
valueField = $('<input/>',{
style: "width:100%",
class: "node-input-env-value",
type: "text",
}).attr("autocomplete","disable").appendTo(envRow)
valueField.typedInput({default:'str',types:isTemplateNode?DEFAULT_ENV_TYPE_LIST:DEFAULT_ENV_TYPE_LIST_INC_CRED});
valueField.typedInput('type', opt.type);
if (opt.type === "cred") {
if (opt.value) {
valueField.typedInput('value', opt.value);
} else if (node.credentials && node.credentials[opt.name]) {
valueField.typedInput('value', node.credentials[opt.name]);
} else if (node.credentials && node.credentials['has_'+opt.name]) {
valueField.typedInput('value', "__PWRD__");
} else {
valueField.typedInput('value', "");
}
} else {
valueField.typedInput('value', opt.value);
}
opt.nameField = nameField;
opt.valueField = valueField;
var actionButton = $('<a/>',{href:"#",class:"red-ui-editableList-item-remove red-ui-button red-ui-button-small"}).appendTo(envRow);
$('<i/>',{class:"fa "+(opt.parent?"fa-reply":"fa-remove")}).appendTo(actionButton);
var removeTip = RED.popover.tooltip(actionButton,RED._("subflow.env.remove"));
actionButton.on("click", function(evt) {
evt.preventDefault();
removeTip.close();
container.parent().addClass("red-ui-editableList-item-deleting")
container.fadeOut(300, function() {
envContainer.editableList('removeItem',opt);
});
});
if (isTemplateNode) {
// Add the UI customisation row
// if `opt.ui` does not exist, then apply defaults. If these
// defaults do not change then they will get stripped off
// before saving.
if (opt.type === 'cred') {
opt.ui = opt.ui || {
icon: "",
type: "cred"
}
opt.ui.type = "cred";
} else {
opt.ui = opt.ui || {
icon: "",
type: "input",
opts: {types:DEFAULT_ENV_TYPE_LIST}
}
}
opt.ui.label = opt.ui.label || {};
opt.ui.type = opt.ui.type || "input";
var uiRow = $('<div/>').appendTo(container).hide();
// save current info for reverting on cancel
// var copy = $.extend(true, {}, ui);
$('<a href="#"><i class="fa fa-angle-right"></a>').prependTo(envRow).on("click", function (evt) {
evt.preventDefault();
if ($(this).hasClass('expanded')) {
uiRow.slideUp();
$(this).removeClass('expanded');
} else {
uiRow.slideDown();
$(this).addClass('expanded');
}
});
buildEnvEditRow(uiRow, opt.ui, nameField, valueField);
nameField.trigger('change');
}
},
sortable: ".red-ui-editableList-item-handle",
removable: false
});
var parentEnv = {};
var envList = [];
if (/^subflow:/.test(node.type)) {
var subflowDef = RED.nodes.subflow(node.type.substring(8));
if (subflowDef.env) {
subflowDef.env.forEach(function(env) {
var item = {
name:env.name,
parent: {
type: env.type,
value: env.value,
ui: env.ui
}
}
envList.push(item);
parentEnv[env.name] = item;
})
}
}
if (node.env) {
for (var i = 0; i < node.env.length; i++) {
var env = node.env[i];
if (parentEnv.hasOwnProperty(env.name)) {
parentEnv[env.name].type = env.type;
parentEnv[env.name].value = env.value;
} else {
envList.push({
name: env.name,
type: env.type,
value: env.value,
ui: env.ui
});
}
}
}
envList.forEach(function(env) {
if (env.parent && env.parent.ui && env.parent.ui.type === 'hide') {
return;
}
if (!isTemplateNode && env.parent) {
return;
}
envContainer.editableList('addItem', JSON.parse(JSON.stringify(env)));
});
}
/**
* Create UI edit interface for environment variable
* @param container - container
* @param env - env var definition
* @param nameField - name field of env var
* @param valueField - value field of env var
*/
function buildEnvEditRow(container, ui, nameField, valueField) {
container.addClass("red-ui-editor-subflow-env-ui-row")
var topRow = $('<div></div>').appendTo(container);
$('<div></div>').appendTo(topRow);
$('<div>').text(RED._("editor.icon")).appendTo(topRow);
$('<div>').text(RED._("editor.label")).appendTo(topRow);
$('<div>').text(RED._("editor.inputType")).appendTo(topRow);
var row = $('<div></div>').appendTo(container);
$('<div><i class="red-ui-editableList-item-handle fa fa-bars"></i></div>').appendTo(row);
var typeOptions = {
'input': {types:DEFAULT_ENV_TYPE_LIST},
'select': {opts:[]},
'spinner': {},
'cred': {}
};
if (ui.opts) {
typeOptions[ui.type] = ui.opts;
} else {
// Pick up the default values if not otherwise provided
ui.opts = typeOptions[ui.type];
}
var iconCell = $('<div></div>').appendTo(row);
var iconButton = $('<a href="#"></a>').appendTo(iconCell);
iconButton.on("click", function(evt) {
evt.preventDefault();
var icon = ui.icon || "";
var iconPath = (icon ? RED.utils.separateIconPath(icon) : {});
RED.editor.showIconPicker(iconButton, null, iconPath, true, function (newIcon) {
iconButton.empty();
var path = newIcon || "";
var newPath = RED.utils.separateIconPath(path);
if (newPath) {
$('<i class="fa"></i>').addClass(newPath.file).appendTo(iconButton);
}
ui.icon = path;
});
})
if (ui.icon) {
var newPath = RED.utils.separateIconPath(ui.icon);
$('<i class="fa '+newPath.file+'"></i>').appendTo(iconButton);
}
var labelCell = $('<div></div>').appendTo(row);
var label = ui.label && ui.label[currentLocale] || "";
var labelInput = $('<input type="text">').val(label).appendTo(labelCell);
ui.labelField = labelInput;
labelInput.on('change', function(evt) {
ui.label = ui.label || {};
var val = $(this).val().trim();
if (val === "") {
delete ui.label[currentLocale];
} else {
ui.label[currentLocale] = val;
}
})
var labelIcon = $('<span class="red-ui-editor-subflow-env-lang-icon"><i class="fa fa-language"></i></span>').appendTo(labelCell);
RED.popover.tooltip(labelIcon,function() {
var langs = Object.keys(ui.label);
var content = $("<div>");
if (langs.indexOf(currentLocale) === -1) {
langs.push(currentLocale);
langs.sort();
}
langs.forEach(function(l) {
var row = $('<div>').appendTo(content);
$('<span>').css({display:"inline-block",width:"120px"}).text(RED._("languages."+l)+(l===currentLocale?"*":"")).appendTo(row);
$('<span>').text(ui.label[l]||"").appendTo(row);
});
return content;
})
nameField.on('change',function(evt) {
labelInput.attr("placeholder",$(this).val())
});
var inputCell = $('<div></div>').appendTo(row);
var inputCellInput = $('<input type="text">').css("width","100%").appendTo(inputCell);
if (ui.type === "input") {
inputCellInput.val(ui.opts.types.join(","));
}
var checkbox;
var selectBox;
inputCellInput.typedInput({
types: [
{
value:"input",
label:RED._("editor.inputs.input"), icon:"fa fa-i-cursor",showLabel:false,multiple:true,options:[
{value:"str",label:RED._("editor.types.str"),icon:"red/images/typedInput/az.svg"},
{value:"num",label:RED._("editor.types.num"),icon:"red/images/typedInput/09.svg"},
{value:"bool",label:RED._("editor.types.bool"),icon:"red/images/typedInput/bool.svg"},
{value:"json",label:RED._("editor.types.json"),icon:"red/images/typedInput/json.svg"},
{value: "bin",label: RED._("editor.types.bin"),icon: "red/images/typedInput/bin.svg"},
{value: "env",label: RED._("editor.types.env"),icon: "red/images/typedInput/env.svg"},
{value: "cred",label: RED._("editor.types.cred"),icon: "fa fa-lock"}
],
default: DEFAULT_ENV_TYPE_LIST,
valueLabel: function(container,value) {
container.css("padding",0);
var innerContainer = $('<div class="red-ui-editor-subflow-env-input-type"></div>').appendTo(container);
var input = $('<div class="placeholder-input">').appendTo(innerContainer);
$('<span><i class="fa fa-i-cursor"></i></span>').appendTo(input);
if (value.length) {
value.forEach(function(v) {
if (!/^fa /.test(v.icon)) {
$('<img>',{src:v.icon,style:"max-width:14px; padding: 0 3px; margin-top:-4px; margin-left: 1px"}).appendTo(input);
} else {
var s = $('<span>',{style:"max-width:14px; padding: 0 3px; margin-top:-4px; margin-left: 1px"}).appendTo(input);
$("<i>",{class: v.icon}).appendTo(s);
}
})
} else {
$('<span class="red-ui-editor-subflow-env-input-type-placeholder"></span>').text(RED._("editor.selectType")).appendTo(input);
}
}
},
{
value: "cred",
label: RED._("typedInput.type.cred"), icon:"fa fa-lock", showLabel: false,
valueLabel: function(container,value) {
container.css("padding",0);
var innerContainer = $('<div class="red-ui-editor-subflow-env-input-type">').css({
"border-top-right-radius": "4px",
"border-bottom-right-radius": "4px"
}).appendTo(container);
$('<div class="placeholder-input">').html("&bull;&bull;&bull;&bull;&bull;&bull;&bull;&bull;").appendTo(innerContainer);
}
},
{
value:"select",
label:RED._("editor.inputs.select"), icon:"fa fa-tasks",showLabel:false,
valueLabel: function(container,value) {
container.css("padding","0");
selectBox = $('<select></select>').appendTo(container);
if (ui.opts && Array.isArray(ui.opts.opts)) {
ui.opts.opts.forEach(function(o) {
var label = lookupLabel(o.l, o.l["en-US"]||o.v, currentLocale);
// $('<option>').val((o.t||'str')+":"+o.v).text(label).appendTo(selectBox);
$('<option>').val(o.v).text(label).appendTo(selectBox);
})
}
selectBox.on('change', function(evt) {
var v = selectBox.val();
// var parts = v.split(":");
// var t = parts.shift();
// v = parts.join(":");
//
// valueField.typedInput("type",'str')
valueField.typedInput("value",v)
});
selectBox.val(valueField.typedInput("value"));
// selectBox.val(valueField.typedInput('type')+":"+valueField.typedInput("value"));
},
expand: {
icon: "fa-caret-down",
minWidth: 400,
content: function(container) {
var content = $('<div class="red-ui-editor-subflow-ui-edit-panel">').appendTo(container);
var optList = $('<ol>').appendTo(content).editableList({
header:$("<div><div>"+RED._("editor.select.label")+"</div><div>"+RED._("editor.select.value")+"</div></div>"),
addItem: function(row,index,itemData) {
var labelDiv = $('<div>').appendTo(row);
var label = lookupLabel(itemData.l, "", currentLocale);
itemData.label = $('<input type="text">').val(label).appendTo(labelDiv);
itemData.label.on('keydown', function(evt) {
if (evt.keyCode === 13) {
itemData.input.focus();
evt.preventDefault();
}
});
var labelIcon = $('<span class="red-ui-editor-subflow-env-lang-icon"><i class="fa fa-language"></i></span>').appendTo(labelDiv);
RED.popover.tooltip(labelIcon,function() {
return currentLocale;
})
itemData.input = $('<input type="text">').val(itemData.v).appendTo(row);
// Problem using a TI here:
// - this is in a popout panel
// - clicking the expand button in the TI will close the parent edit tray
// and open the type editor.
// - but it leaves the popout panel over the top.
// - there is no way to get back to the popout panel after closing the type editor
//.typedInput({default:itemData.t||'str', types:DEFAULT_ENV_TYPE_LIST});
itemData.input.on('keydown', function(evt) {
if (evt.keyCode === 13) {
// Enter or Tab
var index = optList.editableList('indexOf',itemData);
var length = optList.editableList('length');
if (index + 1 === length) {
var newItem = {};
optList.editableList('addItem',newItem);
setTimeout(function() {
if (newItem.label) {
newItem.label.focus();
}
},100)
} else {
var nextItem = optList.editableList('getItemAt',index+1);
if (nextItem.label) {
nextItem.label.focus()
}
}
evt.preventDefault();
}
});
},
sortable: true,
removable: true,
height: 160
})
if (ui.opts.opts.length > 0) {
ui.opts.opts.forEach(function(o) {
optList.editableList('addItem',$.extend(true,{},o))
})
} else {
optList.editableList('addItem',{})
}
return {
onclose: function() {
var items = optList.editableList('items');
var vals = [];
items.each(function (i,el) {
var data = el.data('data');
var l = data.label.val().trim();
var v = data.input.val();
// var t = data.input.typedInput('type');
// var v = data.input.typedInput('value');
if (l.length > 0) {
data.l = data.l || {};
data.l[currentLocale] = l;
}
data.v = v;
if (l.length > 0 || v.length > 0) {
var val = {l:data.l,v:data.v};
// if (t !== 'str') {
// val.t = t;
// }
vals.push(val);
}
});
ui.opts.opts = vals;
inputCellInput.typedInput('value',Date.now())
}
}
}
}
},
{
value:"checkbox",
label:RED._("editor.inputs.checkbox"), icon:"fa fa-check-square-o",showLabel:false,
valueLabel: function(container,value) {
container.css("padding",0);
checkbox = $('<input type="checkbox">').appendTo(container);
checkbox.on('change', function(evt) {
valueField.typedInput('value',$(this).prop('checked')?"true":"false");
})
checkbox.prop('checked',valueField.typedInput('value')==="true");
}
},
{
value:"spinner",
label:RED._("editor.inputs.spinner"), icon:"fa fa-sort-numeric-asc", showLabel:false,
valueLabel: function(container,value) {
container.css("padding",0);
var innerContainer = $('<div class="red-ui-editor-subflow-env-input-type"></div>').appendTo(container);
var input = $('<div class="placeholder-input">').appendTo(innerContainer);
$('<span><i class="fa fa-sort-numeric-asc"></i></span>').appendTo(input);
var min = ui.opts && ui.opts.min;
var max = ui.opts && ui.opts.max;
var label = "";
if (min !== undefined && max !== undefined) {
label = Math.min(min,max)+" - "+Math.max(min,max);
} else if (min !== undefined) {
label = "> "+min;
} else if (max !== undefined) {
label = "< "+max;
}
$('<span>').css("margin-left","15px").text(label).appendTo(input);
},
expand: {
icon: "fa-caret-down",
content: function(container) {
var content = $('<div class="red-ui-editor-subflow-ui-edit-panel">').appendTo(container);
content.css("padding","8px 5px")
var min = ui.opts.min;
var max = ui.opts.max;
var minInput = $('<input type="number" style="margin-bottom:0; width:60px">');
minInput.val(min);
var maxInput = $('<input type="number" style="margin-bottom:0; width:60px">');
maxInput.val(max);
$('<div class="form-row" style="margin-bottom:3px"><label>'+RED._("editor.spinner.min")+'</label></div>').append(minInput).appendTo(content);
$('<div class="form-row" style="margin-bottom:0"><label>'+RED._("editor.spinner.max")+'</label></div>').append(maxInput).appendTo(content);
return {
onclose: function() {
var min = minInput.val().trim();
var max = maxInput.val().trim();
if (min !== "") {
ui.opts.min = parseInt(min);
} else {
delete ui.opts.min;
}
if (max !== "") {
ui.opts.max = parseInt(max);
} else {
delete ui.opts.max;
}
inputCellInput.typedInput('value',Date.now())
}
}
}
}
},
{
value:"none",
label:RED._("editor.inputs.none"), icon:"fa fa-times",hasValue:false
},
{
value:"hide",
label:RED._("editor.inputs.hidden"), icon:"fa fa-ban",hasValue:false
}
],
default: 'none'
}).on("typedinputtypechange", function(evt,type) {
ui.type = $(this).typedInput("type");
ui.opts = typeOptions[ui.type];
if (ui.type === 'input') {
// In the case of 'input' type, the typedInput uses the multiple-option
// mode. Its value needs to be set to a comma-separately list of the
// selected options.
inputCellInput.typedInput('value',ui.opts.types.join(","))
} else {
// No other type cares about `value`, but doing this will
// force a refresh of the label now that `ui.opts` has
// been updated.
inputCellInput.typedInput('value',Date.now())
}
switch (ui.type) {
case 'input':
valueField.typedInput('types',ui.opts.types);
break;
case 'select':
valueField.typedInput('types',['str']);
break;
case 'checkbox':
valueField.typedInput('types',['bool']);
break;
case 'spinner':
valueField.typedInput('types',['num']);
break;
case 'cred':
valueField.typedInput('types',['cred']);
break;
default:
valueField.typedInput('types',DEFAULT_ENV_TYPE_LIST)
}
if (ui.type === 'checkbox') {
valueField.typedInput('type','bool');
} else if (ui.type === 'spinner') {
valueField.typedInput('type','num');
}
if (ui.type !== 'checkbox') {
checkbox = null;
}
}).on("change", function(evt,type) {
if (ui.type === 'input') {
var types = inputCellInput.typedInput('value');
ui.opts.types = (types === "") ? ["str"] : types.split(",");
valueField.typedInput('types',ui.opts.types);
}
});
valueField.on("change", function(evt) {
if (checkbox) {
checkbox.prop('checked',$(this).typedInput('value')==="true")
}
})
// Set the input to the right type. This will trigger the 'typedinputtypechange'
// event handler (just above ^^) to update the value if needed
inputCellInput.typedInput('type',ui.type)
}
function buildEnvUIRow(row, tenv, ui, node) {
ui.label = ui.label||{};
@ -1540,7 +929,7 @@ RED.subflow = (function() {
ui.opts = {};
} else if (!ui.type) {
ui.type = "input";
ui.opts = {types:DEFAULT_ENV_TYPE_LIST}
ui.opts = { types: RED.editor.envVarList.DEFAULT_ENV_TYPE_LIST }
} else {
if (!ui.opts) {
ui.opts = (ui.type === "select") ? {opts:[]} : {};
@ -1549,7 +938,7 @@ RED.subflow = (function() {
var labels = ui.label || {};
var locale = RED.i18n.lang();
var labelText = lookupLabel(labels, labels["en-US"]||tenv.name, locale);
var labelText = RED.editor.envVarList.lookupLabel(labels, labels["en-US"]||tenv.name, locale);
var label = $('<label>').appendTo(row);
$('<span>&nbsp;</span>').appendTo(row);
var labelContainer = $('<span></span>').appendTo(label);
@ -1602,7 +991,7 @@ RED.subflow = (function() {
input = $('<select>').css('width','70%').appendTo(row);
if (ui.opts.opts) {
ui.opts.opts.forEach(function(o) {
$('<option>').val(o.v).text(lookupLabel(o.l, o.l['en-US']||o.v, locale)).appendTo(input);
$('<option>').val(o.v).text(RED.editor.envVarList.lookupLabel(o.l, o.l['en-US']||o.v, locale)).appendTo(input);
})
}
input.val(val.value);
@ -1668,9 +1057,8 @@ RED.subflow = (function() {
* @param uiContainer - container for UI
* @param envList - env var definitions of template
*/
function buildEnvUI(uiContainer, envList,node) {
function buildEnvUI(uiContainer, envList, node) {
uiContainer.empty();
var elementID = 0;
for (var i = 0; i < envList.length; i++) {
var tenv = envList[i];
if (tenv.ui && tenv.ui.type === 'hide') {
@ -1678,8 +1066,6 @@ RED.subflow = (function() {
}
var row = $("<div/>", { class: "form-row" }).appendTo(uiContainer);
buildEnvUIRow(row,tenv, tenv.ui || {}, node);
// console.log(ui);
}
}
// buildEnvUI
@ -1715,7 +1101,7 @@ RED.subflow = (function() {
// icon: "",
// label: {},
// type: "input",
// opts: {types:DEFAULT_ENV_TYPE_LIST}
// opts: {types:RED.editor.envVarList.DEFAULT_ENV_TYPE_LIST}
// }
if (!ui.icon) {
delete ui.icon;
@ -1725,7 +1111,7 @@ RED.subflow = (function() {
}
switch (ui.type) {
case "input":
if (JSON.stringify(ui.opts) === JSON.stringify({types:DEFAULT_ENV_TYPE_LIST})) {
if (JSON.stringify(ui.opts) === JSON.stringify({types:RED.editor.envVarList.DEFAULT_ENV_TYPE_LIST})) {
// This is the default input config. Delete it as it will
// be applied automatically
delete ui.type;
@ -1841,7 +1227,6 @@ RED.subflow = (function() {
function exportSubflowInstanceEnv(node) {
var env = [];
// First, get the values for the SubflowTemplate defined properties
// - these are the ones with custom UI elements
var parentEnv = getSubflowInstanceParentEnv(node);
@ -1853,7 +1238,7 @@ RED.subflow = (function() {
ui.type = "cred";
} else {
ui.type = "input";
ui.opts = {types:DEFAULT_ENV_TYPE_LIST}
ui.opts = {types:RED.editor.envVarList.DEFAULT_ENV_TYPE_LIST}
}
} else {
ui.opts = ui.opts || {};
@ -1893,22 +1278,6 @@ RED.subflow = (function() {
}
}
})
// Second, get the values from the Properties table tab
var items = $('#red-ui-editor-subflow-env-list').editableList('items');
items.each(function (i,el) {
var data = el.data('data');
var item;
if (data.nameField && data.valueField) {
item = {
name: data.nameField.val(),
value: data.valueField.typedInput("value"),
type: data.valueField.typedInput("type")
}
if (item.name.trim() !== "") {
env.push(item);
}
}
});
return env;
}
@ -1916,164 +1285,18 @@ RED.subflow = (function() {
return 'node-input-subflow-env-'+name.replace(/[^a-z0-9-_]/ig,"_");
}
/**
* Lookup text for specific locale
* @param labels - dict of labels
* @param defaultLabel - fallback label if not found
* @param locale - target locale
* @returns {string} text for specified locale
*/
function lookupLabel(labels, defaultLabel, locale) {
if (labels) {
if (labels[locale]) {
return labels[locale];
}
if (locale) {
var lang = locale.substring(0, 2);
if (labels[lang]) {
return labels[lang];
}
}
}
return defaultLabel;
}
// Called by subflow.oneditprepare for both instances and templates
function buildEditForm(type,node) {
if (type === "subflow-template") {
buildPropertiesList($('#node-input-env-container'), node);
// This is the tabbed UI that offers the env list - with UI options
// plus the preview tab
buildEnvControl($('#node-input-env-container'), node);
RED.editor.envVarList.create($('#node-input-env-container'), node);
} else if (type === "subflow") {
// This gets called by the subflow type `oneditprepare` function
// registered in nodes.js#addSubflow()
// This is the rendered version of the subflow env var list
buildEnvUI($("#subflow-input-ui"), getSubflowInstanceParentEnv(node), node);
}
}
function buildPropertiesForm(node) {
var container = $('#editor-subflow-envProperties-content');
var form = $('<form class="dialog-form form-horizontal"></form>').appendTo(container);
var listContainer = $('<div class="form-row node-input-env-container-row"></div>').appendTo(form);
var list = $('<ol id="red-ui-editor-subflow-env-list" class="red-ui-editor-subflow-env-list"></ol>').appendTo(listContainer);
buildPropertiesList(list, node);
}
function setupInputValidation(input,validator) {
var errorTip;
var validateTimeout;
var validateFunction = function() {
if (validateTimeout) {
return;
}
validateTimeout = setTimeout(function() {
var error = validator(input.val());
// if (!error && errorTip) {
// errorTip.close();
// errorTip = null;
// } else if (error && !errorTip) {
// errorTip = RED.popover.create({
// tooltip: true,
// target:input,
// size: "small",
// direction: "bottom",
// content: error,
// }).open();
// }
input.toggleClass("input-error",!!error);
validateTimeout = null;
})
}
input.on("change keyup paste", validateFunction);
}
function buildModuleForm(container, node) {
$(_subflowModulePaneTemplate).appendTo(container);
var moduleProps = node.meta || {};
[
'module',
'type',
'version',
'author',
'desc',
'keywords',
'license'
].forEach(function(property) {
$("#subflow-input-module-"+property).val(moduleProps[property]||"")
})
$("#subflow-input-module-type").attr("placeholder",node.id);
setupInputValidation($("#subflow-input-module-module"), function(newValue) {
newValue = newValue.trim();
var isValid = newValue.length < 215;
isValid = isValid && !/^[._]/.test(newValue);
isValid = isValid && !/[A-Z]/.test(newValue);
if (newValue !== encodeURIComponent(newValue)) {
var m = /^@([^\/]+)\/([^\/]+)$/.exec(newValue);
if (m) {
isValid = isValid && (m[1] === encodeURIComponent(m[1]) && m[2] === encodeURIComponent(m[2]))
} else {
isValid = false;
}
}
return isValid?"":"Invalid module name"
})
setupInputValidation($("#subflow-input-module-version"), function(newValue) {
newValue = newValue.trim();
var isValid = newValue === "" ||
/^(\d|[1-9]\d*)\.(\d|[1-9]\d*)\.(\d|[1-9]\d*)(-(0|[1-9A-Za-z-][0-9A-Za-z-]*|[0-9]*[A-Za-z-][0-9A-Za-z-]*)(\.(0|[1-9A-Za-z-][0-9A-Za-z-]*|[0-9]*[A-Za-z-][0-9A-Za-z-]*))*)?(\+[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?$/.test(newValue);
return isValid?"":"Invalid version number"
})
var licenses = ["none", "Apache-2.0", "BSD-3-Clause", "BSD-2-Clause", "GPL-2.0", "GPL-3.0", "MIT", "MPL-2.0", "CDDL-1.0", "EPL-2.0"];
var typedLicenses = {
types: licenses.map(function(l) {
return {
value: l,
label: l === "none" ? RED._("editor:subflow.licenseNone") : l,
hasValue: false
};
})
}
typedLicenses.types.push({
value:"_custom_", label:RED._("editor:subflow.licenseOther"), icon:"red/images/typedInput/az.svg"
})
if (!moduleProps.license) {
typedLicenses.default = "none";
} else if (licenses.indexOf(moduleProps.license) > -1) {
typedLicenses.default = moduleProps.license;
} else {
typedLicenses.default = "_custom_";
}
$("#subflow-input-module-license").typedInput(typedLicenses)
}
function exportSubflowModuleProperties(node) {
var value;
var moduleProps = {};
[
'module',
'type',
'version',
'author',
'desc',
'keywords'
].forEach(function(property) {
value = $("#subflow-input-module-"+property).val().trim();
if (value) {
moduleProps[property] = value;
}
})
var selectedLicenseType = $("#subflow-input-module-license").typedInput("type");
if (selectedLicenseType === '_custom_') {
value = $("#subflow-input-module-license").val();
if (value) {
moduleProps.license = value;
}
} else if (selectedLicenseType !== "none") {
moduleProps.license = selectedLicenseType;
}
return moduleProps;
}
return {
init: init,
@ -2085,14 +1308,9 @@ RED.subflow = (function() {
removeOutput: removeSubflowOutput,
removeStatus: removeSubflowStatus,
buildEditForm: buildEditForm,
buildPropertiesForm: buildPropertiesForm,
buildModuleForm: buildModuleForm,
exportSubflowTemplateEnv: exportEnvList,
exportSubflowInstanceEnv: exportSubflowInstanceEnv,
exportSubflowModuleProperties: exportSubflowModuleProperties
exportSubflowInstanceEnv: exportSubflowInstanceEnv
}
})();

View File

@ -229,7 +229,7 @@ RED.sidebar.config = (function() {
var globalConfigNodes = [];
var configList = {};
RED.nodes.eachConfig(function(cn) {
if (cn.z) {//} == RED.workspaces.active()) {
if (cn.z) {
configList[cn.z.replace(/\./g,"-")] = configList[cn.z.replace(/\./g,"-")]||[];
configList[cn.z.replace(/\./g,"-")].push(cn);
} else if (!cn.z) {

View File

@ -25,7 +25,6 @@ RED.sidebar.help = (function() {
var tocPanel;
var helpIndex = {};
function resizeStack() {
var h = $(content).parent().height() - toolbar.outerHeight();
panels.resize(h)
@ -93,9 +92,28 @@ RED.sidebar.help = (function() {
$('<span class="red-ui-help-info-none">'+RED._("sidebar.help.noHelp")+'</span>').appendTo(helpSection);
treeList = $("<div>").css({width: "100%"}).appendTo(tocPanel).treeList({data: []})
var pendingContentLoad;
treeList.on('treelistselect', function(e,item) {
pendingContentLoad = item;
if (item.nodeType) {
showHelp(item.nodeType);
showNodeTypeHelp(item.nodeType);
} else if (item.content) {
helpSection.empty();
if (typeof item.content === "string") {
setInfoText(item.label, item.content);
} else if (typeof item.content === "function") {
if (item.content.length === 0) {
setInfoText(item.label, item.content());
} else {
setInfoText(item.label, '<div class="red-ui-component-spinner red-ui-component-spinner-contain"><img src="red/images/spin.svg" /></div>',helpSection)
item.content(function(content) {
if (pendingContentLoad === item) {
helpSection.empty();
setInfoText(item.label, content);
}
})
}
}
}
})
@ -174,21 +192,28 @@ RED.sidebar.help = (function() {
var moduleNames = Object.keys(modules);
moduleNames.sort();
var helpData = [{
var nodeHelp = {
label: RED._("sidebar.help.nodeHelp"),
children: [],
expanded: true
}]
}
var helpData = [
{
id: 'changelog',
label: "Node-RED v"+RED.settings.version,
content: getChangelog
},
nodeHelp
]
var subflows = RED.nodes.registry.getNodeTypes().filter(function(t) {return /subflow/.test(t)});
if (subflows.length > 0) {
helpData[0].children.push({
nodeHelp.children.push({
label: RED._("menu.label.subflows"),
children: []
})
subflows.forEach(function(nodeType) {
var sf = RED.nodes.getType(nodeType);
helpData[0].children[0].children.push({
nodeHelp.children[0].children.push({
id:"node-type:"+nodeType,
nodeType: nodeType,
subflowLabel: sf.label().toLowerCase(),
@ -218,7 +243,7 @@ RED.sidebar.help = (function() {
nodeTypes.sort(function(A,B) {
return A.nodeType.localeCompare(B.nodeType)
})
helpData[0].children.push({
nodeHelp.children.push({
id: moduleName,
icon: "fa fa-cube",
label: moduleName,
@ -244,7 +269,7 @@ RED.sidebar.help = (function() {
return div;
}
function showHelp(nodeType) {
function showNodeTypeHelp(nodeType) {
helpSection.empty();
var helpText;
var title;
@ -265,7 +290,7 @@ RED.sidebar.help = (function() {
}
}
}
setInfoText(title, helpText, helpSection);
setInfoText(title, helpText);
var ratio = panels.ratio();
if (ratio > 0.7) {
@ -282,7 +307,7 @@ RED.sidebar.help = (function() {
}
if (type) {
// hideTOC();
showHelp(type);
showNodeTypeHelp(type);
}
resizeStack();
}
@ -298,11 +323,12 @@ RED.sidebar.help = (function() {
return el;
}
function setInfoText(title, infoText,target) {
function setInfoText(title, infoText) {
helpSection.empty();
if (title) {
$("<h1>",{class:"red-ui-help-title"}).text(title).appendTo(target);
$("<h1>",{class:"red-ui-help-title"}).text(title).appendTo(helpSection);
}
var info = addTargetToExternalLinks($('<div class="red-ui-help"><span class="red-ui-text-bidi-aware" dir=\"'+RED.text.bidi.resolveBaseTextDir(infoText)+'">'+infoText+'</span></div>')).appendTo(target);
var info = addTargetToExternalLinks($('<div class="red-ui-help"><span class="red-ui-text-bidi-aware" dir=\"'+RED.text.bidi.resolveBaseTextDir(infoText)+'">'+infoText+'</span></div>')).appendTo(helpSection);
info.find(".red-ui-text-bidi-aware").contents().filter(function() { return this.nodeType === 3 && this.textContent.trim() !== "" }).wrap( "<span></span>" );
var foldingHeader = "H3";
info.find(foldingHeader).wrapInner('<a class="red-ui-help-info-header expanded" href="#"></a>')
@ -316,12 +342,12 @@ RED.sidebar.help = (function() {
}
$(this).toggleClass('expanded',!isExpanded);
})
target.parent().scrollTop(0);
helpSection.parent().scrollTop(0);
}
function set(html,title) {
$(helpSection).empty();
setInfoText(title,html,helpSection);
setInfoText(title,html);
hideTOC();
show();
}
@ -336,13 +362,91 @@ RED.sidebar.help = (function() {
if (node.type === "subflow" && node.direction) {
// ignore subflow virtual ports
} else if (node.type !== 'group'){
showHelp(node.type);
showNodeTypeHelp(node.type);
}
}
}
}
RED.events.on("view:selection-changed",refreshSelection);
function getChangelog(done) {
$.get('red/about', function(data) {
// data will be strictly markdown. Any HTML should be escaped.
data = RED.utils.sanitize(data);
RED.tourGuide.load("./tours/welcome.js", function(err, tour) {
var tourHeader = '<div><img width="50px" src="red/images/node-red-icon.svg" /></div>';
if (tour) {
var currentVersionParts = RED.settings.version.split(".");
var tourVersionParts = tour.version.split(".");
if (tourVersionParts[0] === currentVersionParts[0] && tourVersionParts[1] === currentVersionParts[1]) {
tourHeader = '<div><button type="button" onclick="RED.actions.invoke(\'core:show-welcome-tour\')" class="red-ui-button">Take a tour</button></div>'
}
}
var aboutHeader = '<div style="text-align:center;">'+tourHeader+'</div>'
done(aboutHeader+RED.utils.renderMarkdown(data))
});
});
}
function showAbout() {
treeList.treeList("show","changelog")
treeList.treeList("select","changelog");
show();
}
function showWelcomeTour(lastSeenVersion, done) {
done = done || function() {};
RED.tourGuide.load("./tours/welcome.js", function(err, tour) {
if (err) {
console.warn("Failed to load welcome tour",err);
done()
return;
}
var currentVersionParts = RED.settings.version.split(".");
var tourVersionParts = tour.version.split(".");
// Only display the tour if its MAJ.MIN versions the current version
// This means if we update MAJ/MIN without updating the tour, the old tour won't get shown
if (tourVersionParts[0] !== currentVersionParts[0] || tourVersionParts[1] !== currentVersionParts[1]) {
done()
return;
}
if (lastSeenVersion) {
// Previously displayed a welcome tour.
if (lastSeenVersion === RED.settings.version) {
// Exact match - don't show the tour
done()
return;
}
var lastSeenParts = lastSeenVersion.split(".");
if (currentVersionParts[0] < lastSeenParts[0] || (currentVersionParts[0] === lastSeenParts[0] && currentVersionParts[1] < lastSeenParts[1])) {
// Running an *older* version than last displayed tour.
done()
return;
}
if (currentVersionParts[0] === lastSeenParts[0] && currentVersionParts[1] === lastSeenParts[1]) {
if (lastSeenParts.length === 3 && currentVersionParts.length === 3) {
// Matching non-beta MAJ.MIN - don't repeat tour
done()
return;
}
if (currentVersionParts.length === 4 && (lastSeenParts.length === 3 || currentVersionParts[3] < lastSeenParts[3])) {
// Running an *older* beta than last displayed tour.
done()
return
}
}
}
RED.tourGuide.run("./tours/welcome.js", function(err) {
RED.settings.set("editor.tours.welcome", RED.settings.version)
done()
})
})
}
RED.actions.add("core:show-about", showAbout);
RED.actions.add("core:show-welcome-tour", showWelcomeTour);
return {
init: init,
show: show,

View File

@ -122,11 +122,20 @@ RED.sidebar.info.outliner = (function() {
})
RED.popover.tooltip(triggerButton,RED._("sidebar.info.triggerAction"));
}
// $('<button type="button" class="red-ui-info-outline-item-control-reveal red-ui-button red-ui-button-small"><i class="fa fa-eye"></i></button>').appendTo(controls).on("click",function(evt) {
// evt.preventDefault();
// evt.stopPropagation();
// RED.view.reveal(n.id);
// })
if (n.type === "tab") {
var toggleVisibleButton = $('<button type="button" class="red-ui-info-outline-item-control-hide red-ui-button red-ui-button-small"><i class="fa fa-eye"></i><i class="fa fa-eye-slash"></i></button>').appendTo(controls).on("click",function(evt) {
evt.preventDefault();
evt.stopPropagation();
var isHidden = !div.hasClass("red-ui-info-outline-item-hidden");
div.toggleClass("red-ui-info-outline-item-hidden",isHidden);
if (isHidden) {
RED.workspaces.hide(n.id);
} else {
RED.workspaces.show(n.id, null, true);
}
});
}
if (n.type !== 'subflow') {
var toggleButton = $('<button type="button" class="red-ui-info-outline-item-control-disable red-ui-button red-ui-button-small"><i class="fa fa-circle-thin"></i><i class="fa fa-ban"></i></button>').appendTo(controls).on("click",function(evt) {
evt.preventDefault();
@ -278,11 +287,11 @@ RED.sidebar.info.outliner = (function() {
var node = RED.nodes.node(item.id) || RED.nodes.group(item.id);
if (node) {
if (node.type === 'group' || node._def.category !== "config") {
RED.view.select({nodes:[node]})
// RED.view.select({nodes:[node]})
} else if (node._def.category === "config") {
RED.sidebar.info.refresh(node);
} else {
RED.view.select({nodes:[]})
// RED.view.select({nodes:[]})
}
}
})
@ -311,18 +320,33 @@ RED.sidebar.info.outliner = (function() {
RED.events.on("nodes:add",onNodeAdd);
RED.events.on("nodes:remove",onObjectRemove);
RED.events.on("nodes:change",onNodeChange);
// RED.events.on("nodes:reorder",onNodesReorder);
RED.events.on("groups:add",onNodeAdd);
RED.events.on("groups:remove",onObjectRemove);
RED.events.on("groups:change",onNodeChange);
RED.events.on("workspace:clear", onWorkspaceClear)
RED.events.on("workspace:show", onWorkspaceShow);
RED.events.on("workspace:hide", onWorkspaceHide);
RED.events.on("workspace:clear", onWorkspaceClear);
return container;
}
function onWorkspaceClear() {
treeList.treeList('data',getFlowData());
}
function onWorkspaceShow(event) {
var existingObject = objects[event.workspace];
if (existingObject) {
existingObject.element.removeClass("red-ui-info-outline-item-hidden")
}
}
function onWorkspaceHide(event) {
var existingObject = objects[event.workspace];
if (existingObject) {
existingObject.element.addClass("red-ui-info-outline-item-hidden")
}
}
function onFlowAdd(ws) {
objects[ws.id] = {
id: ws.id,
@ -369,6 +393,21 @@ RED.sidebar.info.outliner = (function() {
return indexMap[A.id] - indexMap[B.id]
})
}
// function onNodesReorder(event) {
// //
// var nodes = RED.nodes.getNodeOrder(event.z);
// var indexMap = {};
// nodes.forEach(function(id,index) {
// indexMap[id] = index;
// })
// var existingObject = objects[event.z];
// existingObject.treeList.sortChildren(function(A,B) {
// if (A.children && !B.children) { return -1 }
// if (!A.children && B.children) { return 1 }
// if (A.children && B.children) { return -1 }
// return indexMap[A.id] - indexMap[B.id]
// })
// }
function onSubflowAdd(sf) {
objects[sf.id] = {
id: sf.id,

View File

@ -180,6 +180,10 @@ RED.sidebar.info = (function() {
if (node === null) {
RED.sidebar.info.outliner.select(null);
propertiesPanelHeaderIcon.empty();
propertiesPanelHeaderLabel.text("");
propertiesPanelHeaderReveal.hide();
propertiesPanelHeaderHelp.hide();
return;
} else if (Array.isArray(node)) {
// Multiple things selected

View File

@ -0,0 +1,434 @@
RED.tourGuide = (function() {
var activeListeners = [];
var shade;
var focus;
var popover;
var stepContent;
var targetElement;
var fullscreen;
var tourCache = {};
function run(tourPath, done) {
done = done || function(err) {
if (err) {
console.error(err);
}
};
loadTour(tourPath, function(err, tour) {
if (err) {
console.warn("Error loading tour:",err);
return;
}
runTour(tour, done);
})
}
function loadTour(tourPath, done) {
if (tourCache[tourPath]) {
done(null, tourCache[tourPath]);
} else {
/* jshint ignore:start */
// jshint<2.13 doesn't support dynamic imports. Once grunt-contrib-jshint
// has been updated with the new jshint, we can stop ignoring this block
import(tourPath).then(function(module) {
tourCache[tourPath] = module.default;
done(null, tourCache[tourPath]);
}).catch(function(err) {
done(err);
})
/* jshint ignore:end */
}
}
function repositionFocus() {
if (targetElement) {
if (!fullscreen) {
var pos = targetElement[0].getBoundingClientRect();
var dimension = Math.max(50, Math.max(pos.width,pos.height)*1.5);
focus.css({
left: (pos.left+pos.width/2)+"px",
top: (pos.top+pos.height/2)+"px",
width: (2*dimension)+"px",
height: (2*dimension)+"px"
})
var flush = focus[0].offsetHeight; // Flush CSS changes
focus.addClass("transition");
focus.css({
width: dimension+"px",
height: dimension+"px"
})
} else {
focus.css({
left: ($(window).width()/2)+"px",
top: ($(window).height()/2)+"px",
width: "0px",
height: "0px"
})
}
if (popover) {
popover.move({
target: targetElement,
})
}
}
}
function runTour(tour, done) {
shade = $('<div class="red-ui-tourGuide-shade"></div>').appendTo(document.body);
focus = $('<div class="red-ui-tourGuide-shade-focus"></div>').appendTo(shade);
// var resizeTimer;
//
$(window).on("resize.red-ui-tourGuide", function() {
repositionFocus();
})
var i = 0;
var state = {
index: 0,
count: tour.steps.length
};
function endTour(err) {
$(window).off("resize.red-ui-tourGuide");
$(document).off('keydown.red-ui-tourGuide');
if (popover) {
popover.close();
}
stepContent = null;
popover = null;
shade.remove();
shade = null;
done(err);
}
function runStep(carryOn) {
if (carryOn === false) {
endTour(false);
return;
}
if (i === tour.steps.length) {
endTour();
return
}
state.index = i;
// console.log("TOUR STEP",i+1,"OF",tour.steps.length)
try {
runTourStep(tour.steps[i++], state, runStep)
} catch(err) {
endTour(err);
return;
}
}
runStep();
}
function clearListeners() {
activeListeners.forEach(function(listener) {
if (listener.type === "dom-event") {
listener.target[0].removeEventListener(listener.event,listener.listener,listener.opts);
} else if (listener.type === "nr-event") {
RED.events.off(listener.event, listener.listener)
}
})
activeListeners = [];
}
function prepareStep(step, state, done) {
if (step.prepare) {
if (step.prepare.length === 0) {
step.prepare.call(state);
} else {
if (popover) {
popover.element.hide();
if (!fullscreen) {
fullscreen = true;
repositionFocus()
}
}
step.prepare.call(state, function() {
if (popover) {
popover.element.show();
}
done();
})
return;
}
}
done();
}
function completeStep(step, state, done) {
function finish() {
clearListeners();
setTimeout(function() {
done();
},0)
}
if (step.complete) {
if (step.complete.length === 0) {
step.complete.call(state);
} else {
if (popover) {
popover.element.hide();
if (!fullscreen) {
fullscreen = true;
repositionFocus()
}
}
step.complete.call(state, function() {
if (popover) {
popover.element.show();
}
finish();
})
return;
}
}
finish();
}
function getLocaleText(property) {
if (typeof property === 'string') {
return property;
}
var currentLang = RED.i18n.lang() || 'en-US';
var availableLangs = Object.keys(property);
return property[currentLang]||property['en-US']||property[availableLangs[0]]
}
function runTourStep(step, state, done) {
shade.fadeIn();
prepareStep(step, state, function() {
var zIndex;
var direction = step.direction || "bottom";
fullscreen = false;
if (typeof step.element === "string") {
targetElement = $(step.element)
} else if (typeof step.element === "function") {
targetElement = step.element.call(state);
} else if (!step.element) {
targetElement = $(".red-ui-editor")
fullscreen = true;
direction = "inset";
} else {
targetElement = step.element;
}
if (targetElement.length === 0) {
targetElement = null;
shade.hide();
throw new Error("Element not found")
}
if ($(window).width() < 400) {
targetElement = $(".red-ui-editor");
fullscreen = true;
direction = "inset";
}
zIndex = targetElement.css("z-index");
if (!fullscreen && (step.interactive || step.wait)) {
targetElement.css("z-index",2002);
}
repositionFocus();
if (!stepContent) {
stepContent = $('<div style="position:relative"></div>');
} else {
stepContent.empty();
}
$('<button type="button" class="red-ui-button red-ui-button-small" style="float: right; margin-top: -4px; margin-right: -4px;"><i class="fa fa-times"></i></button>').appendTo(stepContent).click(function(evt) {
evt.preventDefault();
completeStep(step, state, function() {
done(false);
});
})
var stepDescription = $('<div class="red-ui-tourGuide-popover-description"></div>').appendTo(stepContent);
if (step.titleIcon) {
$('<h2><i class="'+step.titleIcon+'"></i></h2>').appendTo(stepDescription);
}
if (step.title) {
$('<h2>').text(getLocaleText(step.title)).appendTo(stepDescription);
}
$('<div>').css("text-align","left").html(getLocaleText(step.description)).appendTo(stepDescription);
var stepToolbar = $('<div>',{class:"red-ui-tourGuide-toolbar"}).appendTo(stepContent);
// var breadcrumbs = $('<div>',{class:"red-ui-tourGuide-breadcrumbs"}).appendTo(stepToolbar);
// var bcStart = Math.max(0,state.index - 3);
// var bcEnd = Math.min(state.count, bcStart + 7);
// if (bcEnd === state.count) {
// bcStart = Math.max(0,bcEnd - 7);
// }
// for (var i = bcStart; i < bcEnd; i++) {
// var bullet = $('<i class="fa"></i>').addClass(i===state.index ? "fa-circle":"fa-circle-o").appendTo(breadcrumbs);
// if (i === bcStart) {
// if (i > 1) {
// bullet.css("font-size", "3px");
// } else if (i === 1) {
// bullet.css("font-size", "4px");
// }
// } else if (i === bcStart + 1) {
// if (i > 2) {
// bullet.css("font-size", "4px");
// }
// }
// if (i === bcEnd - 1) {
// if (i < state.count - 2) {
// bullet.css("font-size", "3px");
// } else if (i === state.count - 2) {
// bullet.css("font-size", "4px");
// }
// } else if (i === bcEnd - 2) {
// if (i < state.count - 3) {
// bullet.css("font-size", "4px");
// }
// }
// // if (i === bcEnd - 1) {
// // if (i < state.count - 2) {
// // bullet.css("font-size", "3px");
// // } else if (i === state.count - 2) {
// // bullet.css("font-size", "4px");
// // }
// // }
// }
$('<small>').text((state.index+1)+"/"+state.count).appendTo(stepToolbar)
var nextButton;
if (fullscreen || !step.wait) {
nextButton = $('<button type="button" class="red-ui-button" style="position: absolute; right:0;bottom:0;"></button>').appendTo(stepToolbar).one('click',function(evt) {
evt.preventDefault();
stepEventListener();
});
if (state.index === state.count - 1) {
$('<span></span>').text(RED._("common.label.close")).appendTo(nextButton);
} else if (state.index === 0) {
$('<span>start</span>').text(RED._("tourGuide.start")).appendTo(nextButton);
$('<span style="margin-left: 6px"><i class="fa fa-chevron-right"></i></span>').appendTo(nextButton);
} else if (state.index < state.count-1) {
$('<span></span>').text(RED._("tourGuide.next")).appendTo(nextButton);
$('<span style="margin-left: 6px"><i class="fa fa-chevron-right"></i></span>').appendTo(nextButton);
}
}
var width = step.width;
if (fullscreen) {
width = 500;
}
var maxWidth = Math.min($(window).width()-10,Math.max(width || 0, 300));
if (!popover) {
popover = RED.popover.create({
target: targetElement,
width: width || "auto",
maxWidth: maxWidth+"px",
direction: direction,
class: "red-ui-tourGuide-popover"+(fullscreen?" ":""),
trigger: "manual",
content: stepContent
}).open();
}
$(document).off('keydown.red-ui-tourGuide');
$(document).on('keydown.red-ui-tourGuide', function(evt) {
if (evt.key === "Escape" || evt.key === "Esc") {
evt.preventDefault();
evt.stopPropagation();
completeStep(step, state, function() {
done(false);
});
}
})
popover.element.toggleClass("red-ui-tourGuide-popover-full",!!fullscreen);
popover.move({
target: targetElement,
width: width || "auto",
maxWidth: maxWidth+"px",
direction: direction,
})
if (nextButton) {
setTimeout(function() {
nextButton.focus();
},100);
}
var isSVG = targetElement[0] instanceof SVGElement;
if (step.fallback) {
focus.one("mouseenter", function(evt) {
setTimeout(function() {
focus.css({
width: (4*dimension)+"px",
height: (4*dimension)+"px"
})
shade.fadeOut();
popover.move({
target: $(".red-ui-editor"),
direction: step.fallback,
offset: 10,
transition: true
})
// popover.element.addClass('red-ui-tourGuide-popover-bounce');
},isSVG?0:500);
})
}
var stepEventListener = function() {
focus.removeClass("transition");
targetElement.css("z-index",zIndex);
completeStep(step, state, done);
}
if (step.wait) {
if (step.wait.type === "dom-event") {
var eventTarget = targetElement;
if (step.wait.element) {
if (typeof step.wait.element === "string") {
eventTarget = $(step.wait.element);
} else if (typeof step.wait.element === "function") {
eventTarget = step.wait.element.call(state);
}
}
var listener = {
type: step.wait.type,
target: eventTarget,
event: step.wait.event,
listener: function() {
stepEventListener();
},
opts: { once: true }
}
activeListeners.push(listener)
eventTarget[0].addEventListener(listener.event,listener.listener,listener.opts)
} else if (step.wait.type === "nr-event") {
var listener = {
type: step.wait.type,
event: step.wait.event,
listener: function() {
if (step.wait.filter) {
if (!step.wait.filter.apply(state,arguments)) {
return;
}
}
stepEventListener();
}
}
activeListeners.push(listener);
RED.events.on(listener.event,listener.listener);
}
}
})
}
return {
load: loadTour,
run: run,
reset: function() {
RED.settings.set("editor.tours.welcome",'');
}
}
})();

View File

@ -139,7 +139,8 @@ RED.userSettings = (function() {
{
title: "menu.label.other",
options: [
{setting:"view-show-tips",oldSettings:"menu-menu-item-show-tips",label:"menu.label.showTips",toggle:true,default:true,onchange:"core:toggle-show-tips"}
{setting:"view-show-tips",oldSettings:"menu-menu-item-show-tips",label:"menu.label.showTips",toggle:true,default:true,onchange:"core:toggle-show-tips"},
{setting:"view-show-welcome-tours",label:"menu.label.showWelcomeTours",toggle:true,default:true}
]
}
];

View File

@ -22,8 +22,82 @@ RED.utils = (function() {
return renderMarkdown(txt);
}
_marked.setOptions({
renderer: new _marked.Renderer(),
const descriptionList = {
name: 'descriptionList',
level: 'block', // Is this a block-level or inline-level tokenizer?
start(src) {
if (!src) { return null; }
let m = src.match(/:[^:\n]/);
return m && m.index; // Hint to Marked.js to stop and check for a match
},
tokenizer(src, tokens) {
if (!src) { return null; }
const rule = /^(?::[^:\n]+:[^:\n]*(?:\n|$))+/; // Regex for the complete token
const match = rule.exec(src);
if (match) {
return { // Token to generate
type: 'descriptionList', // Should match "name" above
raw: match[0], // Text to consume from the source
text: match[0].trim(), // Additional custom properties
tokens: this.lexer.inlineTokens(match[0].trim()) // inlineTokens to process **bold**, *italics*, etc.
};
}
},
renderer(token) {
return `<dl class="message-properties">${this.parser.parseInline(token.tokens)}\n</dl>`; // parseInline to turn child tokens into HTML
}
};
const description = {
name: 'description',
level: 'inline', // Is this a block-level or inline-level tokenizer?
start(src) {
if (!src) { return null; }
let m = src.match(/:/);
return m && m.index; // Hint to Marked.js to stop and check for a match
},
tokenizer(src, tokens) {
if (!src) { return null; }
const rule = /^:([^:\n]+)\(([^:\n]+)\).*?:([^:\n]*)(?:\n|$)/; // Regex for the complete token
const match = rule.exec(src);
if (match) {
return { // Token to generate
type: 'description', // Should match "name" above
raw: match[0], // Text to consume from the source
dt: this.lexer.inlineTokens(match[1].trim()), // Additional custom properties
types: this.lexer.inlineTokens(match[2].trim()),
dd: this.lexer.inlineTokens(match[3].trim()),
};
}
},
renderer(token) {
return `\n<dt>${this.parser.parseInline(token.dt)}<span class="property-type">${this.parser.parseInline(token.types)}</span></dt><dd>${this.parser.parseInline(token.dd)}</dd>`;
},
childTokens: ['dt', 'dd'], // Any child tokens to be visited by walkTokens
walkTokens(token) { // Post-processing on the completed token tree
if (token.type === 'strong') {
token.text += ' walked';
}
}
};
const renderer = new window._marked.Renderer();
//override list creation - add node-ports to order lists
renderer.list = function (body, ordered, start) {
let addClass = /dl.*?class.*?message-properties.*/.test(body);
if (addClass && ordered) {
return '<ol class="node-ports">' + body + '</ol>';
} else if (ordered) {
return '<ol>' + body + '</ol>';
} else {
return '<ul>' + body + '</ul>'
}
}
window._marked.setOptions({
renderer: renderer,
gfm: true,
tables: true,
breaks: false,
@ -32,6 +106,8 @@ RED.utils = (function() {
smartypants: false
});
window._marked.use({extensions: [descriptionList, description] } );
function renderMarkdown(txt) {
var rendered = _marked(txt);
var cleaned = DOMPurify.sanitize(rendered, {SAFE_FOR_JQUERY: true})
@ -487,7 +563,8 @@ RED.utils = (function() {
expandPaths: expandPaths,
ontoggle: ontoggle,
exposeApi: exposeApi,
tools: tools
// tools: tools // Do not pass tools down as we
// keep them attached to the top-level header
}
).appendTo(row);
}
@ -516,7 +593,8 @@ RED.utils = (function() {
expandPaths: expandPaths,
ontoggle: ontoggle,
exposeApi: exposeApi,
tools: tools
// tools: tools // Do not pass tools down as we
// keep them attached to the top-level header
}
).appendTo(row);
}
@ -571,7 +649,8 @@ RED.utils = (function() {
expandPaths: expandPaths,
ontoggle: ontoggle,
exposeApi: exposeApi,
tools: tools
// tools: tools // Do not pass tools down as we
// keep them attached to the top-level header
}
).appendTo(row);
}

View File

@ -159,15 +159,15 @@ RED.view.tools = (function() {
nodes.forEach(function(n) {
var modified = false;
var oldValue = n.l === undefined?true:n.l;
var isLink = /^link (in|out)$/.test(n._def.type);
var showLabel = n._def.hasOwnProperty("showLabel")?n._def.showLabel:true;
if (labelShown) {
if (n.l === false || (isLink && !n.hasOwnProperty('l'))) {
if (n.l === false || (!showLabel && !n.hasOwnProperty('l'))) {
n.l = true;
modified = true;
}
} else {
if ((!isLink && (!n.hasOwnProperty('l') || n.l === true)) || (isLink && n.l === true) ) {
if ((showLabel && (!n.hasOwnProperty('l') || n.l === true)) || (!showLabel && n.l === true) ) {
n.l = false;
modified = true;
}
@ -427,18 +427,309 @@ RED.view.tools = (function() {
}
}
}
}
function alignSelectionToEdge(direction) {
var selection = RED.view.selection();
if (selection.nodes && selection.nodes.length > 1) {
var changedNodes = [];
var bounds = {
minX: Number.MAX_SAFE_INTEGER,
minY: Number.MAX_SAFE_INTEGER,
maxX: Number.MIN_SAFE_INTEGER,
maxY: Number.MIN_SAFE_INTEGER
}
selection.nodes.forEach(function(n) {
if (n.type === "group") {
bounds.minX = Math.min(bounds.minX, n.x);
bounds.minY = Math.min(bounds.minY, n.y);
bounds.maxX = Math.max(bounds.maxX, n.x + n.w);
bounds.maxY = Math.max(bounds.maxY, n.y + n.h);
} else {
bounds.minX = Math.min(bounds.minX, n.x - n.w/2);
bounds.minY = Math.min(bounds.minY, n.y - n.h/2);
bounds.maxX = Math.max(bounds.maxX, n.x + n.w/2);
bounds.maxY = Math.max(bounds.maxY, n.y + n.h/2);
}
});
bounds.midX = bounds.minX + (bounds.maxX - bounds.minX)/2;
bounds.midY = bounds.minY + (bounds.maxY - bounds.minY)/2;
selection.nodes.forEach(function(n) {
var targetX;
var targetY;
var isGroup = n.type==="group";
switch(direction) {
case 'top':
targetX = n.x;
targetY = bounds.minY + (isGroup?0:(n.h/2));
break;
case 'bottom':
targetX = n.x;
targetY = bounds.maxY - (isGroup?n.h:(n.h/2));
break;
case 'left':
targetX = bounds.minX + (isGroup?0:(n.w/2));
targetY = n.y;
break;
case 'right':
targetX = bounds.maxX - (isGroup?n.w:(n.w/2));
targetY = n.y;
break;
case 'middle':
targetX = n.x;
targetY = bounds.midY - (isGroup?n.h/2:0)
break;
case 'center':
targetX = bounds.midX - (isGroup?n.w/2:0)
targetY = n.y;
break;
}
if (n.x !== targetX || n.y !== targetY) {
if (!isGroup) {
changedNodes.push({
n:n,
ox: n.x,
oy: n.y,
moved: n.moved
});
n.x = targetX;
n.y = targetY;
n.dirty = true;
n.moved = true;
} else {
var groupNodes = RED.group.getNodes(n, true);
var deltaX = n.x - targetX;
var deltaY = n.y - targetY;
groupNodes.forEach(function(gn) {
if (gn.type !== "group" ) {
changedNodes.push({
n:gn,
ox: gn.x,
oy: gn.y,
moved: gn.moved
});
gn.x = gn.x - deltaX;
gn.y = gn.y - deltaY;
gn.dirty = true;
gn.moved = true;
}
})
}
}
});
if (changedNodes.length > 0) {
RED.history.push({t:"move",nodes:changedNodes,dirty:RED.nodes.dirty()});
RED.nodes.dirty(true);
RED.view.redraw(true);
}
}
}
function distributeSelection(direction) {
var selection = RED.view.selection();
if (selection.nodes && selection.nodes.length > 2) {
var changedNodes = [];
var bounds = {
minX: Number.MAX_SAFE_INTEGER,
minY: Number.MAX_SAFE_INTEGER,
maxX: Number.MIN_SAFE_INTEGER,
maxY: Number.MIN_SAFE_INTEGER
}
var startAnchors = [];
var endAnchors = [];
selection.nodes.forEach(function(n) {
var nx,ny;
if (n.type === "group") {
nx = n.x + n.w/2;
ny = n.y + n.h/2;
} else {
nx = n.x;
ny = n.y;
}
if (direction === "h") {
if (nx < bounds.minX) {
startAnchors = [];
bounds.minX = nx;
}
if (nx === bounds.minX) {
startAnchors.push(n);
}
if (nx > bounds.maxX) {
endAnchors = [];
bounds.maxX = nx;
}
if (nx === bounds.maxX) {
endAnchors.push(n);
}
} else {
if (ny < bounds.minY) {
startAnchors = [];
bounds.minY = ny;
}
if (ny === bounds.minY) {
startAnchors.push(n);
}
if (ny > bounds.maxY) {
endAnchors = [];
bounds.maxY = ny;
}
if (ny === bounds.maxY) {
endAnchors.push(n);
}
}
});
var startAnchor = startAnchors[0];
var endAnchor = endAnchors[0];
var nodeSpace = 0;
var nodesToMove = selection.nodes.filter(function(n) {
if (n.id !== startAnchor.id && n.id !== endAnchor.id) {
nodeSpace += direction === 'h'?n.w:n.h;
return true;
}
return false;
}).sort(function(A,B) {
if (direction === 'h') {
return A.x - B.x
} else {
return A.y - B.y
}
})
var saX = startAnchor.x + startAnchor.w/2;
var saY = startAnchor.y + startAnchor.h/2;
if (startAnchor.type === "group") {
saX = startAnchor.x + startAnchor.w;
saY = startAnchor.y + startAnchor.h;
}
var eaX = endAnchor.x;
var eaY = endAnchor.y;
if (endAnchor.type !== "group") {
eaX -= endAnchor.w/2;
eaY -= endAnchor.h/2;
}
var spaceToFill = direction === 'h'?(eaX - saX - nodeSpace): (eaY - saY - nodeSpace);
var spaceBetweenNodes = spaceToFill / (nodesToMove.length + 1);
var tx = saX;
var ty = saY;
while(nodesToMove.length > 0) {
if (direction === 'h') {
tx += spaceBetweenNodes;
} else {
ty += spaceBetweenNodes;
}
var nextNode = nodesToMove.shift();
var isGroup = nextNode.type==="group";
var nx = nextNode.x;
var ny = nextNode.y;
if (!isGroup) {
tx += nextNode.w/2;
ty += nextNode.h/2;
}
if ((direction === 'h' && nx !== tx) || (direction === 'v' && ny !== ty)) {
if (!isGroup) {
changedNodes.push({
n:nextNode,
ox: nextNode.x,
oy: nextNode.y,
moved: nextNode.moved
});
if (direction === 'h') {
nextNode.x = tx;
} else {
nextNode.y = ty;
}
nextNode.dirty = true;
nextNode.moved = true;
} else {
var groupNodes = RED.group.getNodes(nextNode, true);
var deltaX = direction === 'h'? nx - tx : 0;
var deltaY = direction === 'v'? ny - ty : 0;
groupNodes.forEach(function(gn) {
if (gn.type !== "group" ) {
changedNodes.push({
n:gn,
ox: gn.x,
oy: gn.y,
moved: gn.moved
});
gn.x = gn.x - deltaX;
gn.y = gn.y - deltaY;
gn.dirty = true;
gn.moved = true;
}
})
}
}
if (isGroup) {
tx += nextNode.w;
ty += nextNode.h;
} else {
tx += nextNode.w/2;
ty += nextNode.h/2;
}
}
if (changedNodes.length > 0) {
RED.history.push({t:"move",nodes:changedNodes,dirty:RED.nodes.dirty()});
RED.nodes.dirty(true);
RED.view.redraw(true);
}
}
}
function reorderSelection(dir) {
var selection = RED.view.selection();
if (selection.nodes) {
var nodesToMove = [];
selection.nodes.forEach(function(n) {
if (n.type === "group") {
nodesToMove = nodesToMove.concat(RED.group.getNodes(n, true).filter(function(n) {
return n.type !== "group";
}))
} else if (n.type !== "subflow"){
nodesToMove.push(n);
}
})
if (nodesToMove.length > 0) {
var z = nodesToMove[0].z;
var existingOrder = RED.nodes.getNodeOrder(z);
var movedNodes;
if (dir === "forwards") {
movedNodes = RED.nodes.moveNodesForwards(nodesToMove);
} else if (dir === "backwards") {
movedNodes = RED.nodes.moveNodesBackwards(nodesToMove);
} else if (dir === "front") {
movedNodes = RED.nodes.moveNodesToFront(nodesToMove);
} else if (dir === "back") {
movedNodes = RED.nodes.moveNodesToBack(nodesToMove);
}
if (movedNodes.length > 0) {
var newOrder = RED.nodes.getNodeOrder(z);
RED.history.push({t:"reorder",nodes:{z:z,from:existingOrder,to:newOrder},dirty:RED.nodes.dirty()});
RED.nodes.dirty(true);
RED.view.redraw(true);
}
}
}
}
return {
init: function() {
RED.actions.add("core:show-selected-node-labels", function() { setSelectedNodeLabelState(true); })
RED.actions.add("core:hide-selected-node-labels", function() { setSelectedNodeLabelState(false); })
RED.actions.add("core:align-selection-to-grid", alignToGrid);
RED.actions.add("core:scroll-view-up", function() { RED.view.scroll(0,-RED.view.gridSize());});
RED.actions.add("core:scroll-view-right", function() { RED.view.scroll(RED.view.gridSize(),0);});
RED.actions.add("core:scroll-view-down", function() { RED.view.scroll(0,RED.view.gridSize());});
@ -454,6 +745,12 @@ RED.view.tools = (function() {
RED.actions.add("core:move-selection-down", function() { moveSelection(0,1);});
RED.actions.add("core:move-selection-left", function() { moveSelection(-1,0);});
RED.actions.add("core:move-selection-forwards", function() { reorderSelection('forwards') })
RED.actions.add("core:move-selection-backwards", function() { reorderSelection('backwards') })
RED.actions.add("core:move-selection-to-front", function() { reorderSelection('front') })
RED.actions.add("core:move-selection-to-back", function() { reorderSelection('back') })
RED.actions.add("core:step-selection-up", function() { moveSelection(0,-RED.view.gridSize());});
RED.actions.add("core:step-selection-right", function() { moveSelection(RED.view.gridSize(),0);});
RED.actions.add("core:step-selection-down", function() { moveSelection(0,RED.view.gridSize());});
@ -474,6 +771,20 @@ RED.view.tools = (function() {
RED.actions.add("core:go-to-nearest-node-on-right", function() { gotoNearestNode('right')})
RED.actions.add("core:go-to-nearest-node-above", function() { gotoNearestNode('up') })
RED.actions.add("core:go-to-nearest-node-below", function() { gotoNearestNode('down') })
RED.actions.add("core:align-selection-to-grid", alignToGrid);
RED.actions.add("core:align-selection-to-left", function() { alignSelectionToEdge('left') })
RED.actions.add("core:align-selection-to-right", function() { alignSelectionToEdge('right') })
RED.actions.add("core:align-selection-to-top", function() { alignSelectionToEdge('top') })
RED.actions.add("core:align-selection-to-bottom", function() { alignSelectionToEdge('bottom') })
RED.actions.add("core:align-selection-to-middle", function() { alignSelectionToEdge('middle') })
RED.actions.add("core:align-selection-to-center", function() { alignSelectionToEdge('center') })
RED.actions.add("core:distribute-selection-horizontally", function() { distributeSelection('h') })
RED.actions.add("core:distribute-selection-vertically", function() { distributeSelection('v') })
// RED.actions.add("core:add-node", function() { addNode() })
},
/**

View File

@ -345,8 +345,8 @@ RED.view = (function() {
activeSubflow = RED.nodes.subflow(event.workspace);
RED.menu.setDisabled("menu-item-workspace-edit", activeSubflow);
RED.menu.setDisabled("menu-item-workspace-delete",RED.workspaces.count() == 1 || activeSubflow);
RED.menu.setDisabled("menu-item-workspace-edit", activeSubflow || event.workspace === 0);
RED.menu.setDisabled("menu-item-workspace-delete",event.workspace === 0 || RED.workspaces.count() == 1 || activeSubflow);
if (workspaceScrollPositions[event.workspace]) {
chart.scrollLeft(workspaceScrollPositions[event.workspace].left);
@ -413,7 +413,7 @@ RED.view = (function() {
var nn = result.node;
var showLabel = RED.utils.getMessageProperty(RED.settings.get('editor'),"view.view-node-show-label");
if (showLabel !== undefined && !/^link (in|out)$/.test(nn._def.type) && !nn._def.defaults.hasOwnProperty("l")) {
if (showLabel !== undefined && (nn._def.hasOwnProperty("showLabel")?nn._def.showLabel:true) && !nn._def.defaults.hasOwnProperty("l")) {
nn.l = showLabel;
}
@ -501,6 +501,28 @@ RED.view = (function() {
RED.actions.add("core:copy-selection-to-internal-clipboard",copySelection);
RED.actions.add("core:cut-selection-to-internal-clipboard",function(){copySelection();deleteSelection();});
RED.actions.add("core:paste-from-internal-clipboard",function(){importNodes(clipboard,{generateIds: true});});
RED.events.on("view:selection-changed", function(selection) {
var hasSelection = (selection.nodes && selection.nodes.length > 0);
var hasMultipleSelection = hasSelection && selection.nodes.length > 1;
RED.menu.setDisabled("menu-item-edit-cut",!hasSelection);
RED.menu.setDisabled("menu-item-edit-copy",!hasSelection);
RED.menu.setDisabled("menu-item-edit-select-connected",!hasSelection);
RED.menu.setDisabled("menu-item-view-tools-move-to-back",!hasSelection);
RED.menu.setDisabled("menu-item-view-tools-move-to-front",!hasSelection);
RED.menu.setDisabled("menu-item-view-tools-move-backwards",!hasSelection);
RED.menu.setDisabled("menu-item-view-tools-move-forwards",!hasSelection);
RED.menu.setDisabled("menu-item-view-tools-align-left",!hasMultipleSelection);
RED.menu.setDisabled("menu-item-view-tools-align-center",!hasMultipleSelection);
RED.menu.setDisabled("menu-item-view-tools-align-right",!hasMultipleSelection);
RED.menu.setDisabled("menu-item-view-tools-align-top",!hasMultipleSelection);
RED.menu.setDisabled("menu-item-view-tools-align-middle",!hasMultipleSelection);
RED.menu.setDisabled("menu-item-view-tools-align-bottom",!hasMultipleSelection);
RED.menu.setDisabled("menu-item-view-tools-distribute-horizontally",!hasMultipleSelection);
RED.menu.setDisabled("menu-item-view-tools-distribute-veritcally",!hasMultipleSelection);
})
RED.actions.add("core:delete-selection",deleteSelection);
RED.actions.add("core:edit-selected-node",editSelection);
RED.actions.add("core:go-to-selection",function() {
@ -653,24 +675,33 @@ RED.view = (function() {
function updateActiveNodes() {
var activeWorkspace = RED.workspaces.active();
if (activeWorkspace !== 0) {
activeNodes = RED.nodes.filterNodes({z:activeWorkspace});
activeNodes.forEach(function(n,i) {
n._index = i;
})
activeLinks = RED.nodes.filterLinks({
source:{z:activeWorkspace},
target:{z:activeWorkspace}
});
activeNodes = RED.nodes.filterNodes({z:activeWorkspace});
activeGroups = RED.nodes.groups(activeWorkspace)||[];
activeGroups.forEach(function(g, i) {
g._index = i;
if (g.g) {
g._root = g.g;
g._depth = 1;
} else {
g._root = g.id;
g._depth = 0;
}
});
} else {
activeNodes = [];
activeLinks = [];
activeGroups = [];
}
activeLinks = RED.nodes.filterLinks({
source:{z:activeWorkspace},
target:{z:activeWorkspace}
});
activeGroups = RED.nodes.groups(activeWorkspace)||[];
activeGroups.forEach(function(g) {
if (g.g) {
g._root = g.g;
g._depth = 1;
} else {
g._root = g.id;
g._depth = 0;
}
});
var changed = false;
do {
changed = false;
@ -695,7 +726,8 @@ RED.view = (function() {
if (a._root === b._root) {
return a._depth - b._depth;
} else {
return a._root.localeCompare(b._root);
// return a._root.localeCompare(b._root);
return a._index - b._index;
}
});
@ -704,7 +736,8 @@ RED.view = (function() {
if (a._root === b._root) {
return a._depth - b._depth;
} else {
return a._root.localeCompare(b._root);
return a._index - b._index;
// return a._root.localeCompare(b._root);
}
})
}
@ -1055,7 +1088,7 @@ RED.view = (function() {
nn.x = point[0];
nn.y = point[1];
var showLabel = RED.utils.getMessageProperty(RED.settings.get('editor'),"view.view-node-show-label");
if (showLabel !== undefined && !/^link (in|out)$/.test(nn._def.type) && !nn._def.defaults.hasOwnProperty("l")) {
if (showLabel !== undefined && (nn._def.hasOwnProperty("showLabel")?nn._def.showLabel:true) && !nn._def.defaults.hasOwnProperty("l")) {
nn.l = showLabel;
}
if (quickAddLink) {
@ -1939,93 +1972,94 @@ RED.view = (function() {
function updateSelection() {
var selection = {};
var activeWorkspace = RED.workspaces.active();
var workspaceSelection = RED.workspaces.selection();
if (workspaceSelection.length === 0) {
selection = getSelection();
activeLinks = RED.nodes.filterLinks({
source:{z:activeWorkspace},
target:{z:activeWorkspace}
});
var tabOrder = RED.nodes.getWorkspaceOrder();
var currentLinks = activeLinks;
var addedLinkLinks = {};
activeFlowLinks = [];
var activeLinkNodeIds = Object.keys(activeLinkNodes);
activeLinkNodeIds.forEach(function(n) {
activeLinkNodes[n].dirty = true;
})
activeLinkNodes = {};
for (var i=0;i<movingSet.length();i++) {
var msn = movingSet.get(i);
if ((msn.n.type === "link out" || msn.n.type === "link in") &&
(msn.n.z === activeWorkspace)) {
var linkNode = msn.n;
activeLinkNodes[linkNode.id] = linkNode;
var offFlowLinks = {};
linkNode.links.forEach(function(id) {
var target = RED.nodes.node(id);
if (target) {
if (linkNode.type === "link out") {
if (target.z === linkNode.z) {
if (!addedLinkLinks[linkNode.id+":"+target.id]) {
activeLinks.push({
source:linkNode,
sourcePort:0,
target: target,
link: true
});
addedLinkLinks[linkNode.id+":"+target.id] = true;
activeLinkNodes[target.id] = target;
target.dirty = true;
if (activeWorkspace !== 0) {
if (workspaceSelection.length === 0) {
selection = getSelection();
activeLinks = RED.nodes.filterLinks({
source:{z:activeWorkspace},
target:{z:activeWorkspace}
});
var tabOrder = RED.nodes.getWorkspaceOrder();
var currentLinks = activeLinks;
var addedLinkLinks = {};
activeFlowLinks = [];
var activeLinkNodeIds = Object.keys(activeLinkNodes);
activeLinkNodeIds.forEach(function(n) {
activeLinkNodes[n].dirty = true;
})
activeLinkNodes = {};
for (var i=0;i<movingSet.length();i++) {
var msn = movingSet.get(i);
if (((msn.n.type === "link out" && msn.n.mode !== 'return') || msn.n.type === "link in") &&
(msn.n.z === activeWorkspace)) {
var linkNode = msn.n;
activeLinkNodes[linkNode.id] = linkNode;
var offFlowLinks = {};
linkNode.links.forEach(function(id) {
var target = RED.nodes.node(id);
if (target) {
if (linkNode.type === "link out") {
if (target.z === linkNode.z) {
if (!addedLinkLinks[linkNode.id+":"+target.id]) {
activeLinks.push({
source:linkNode,
sourcePort:0,
target: target,
link: true
});
addedLinkLinks[linkNode.id+":"+target.id] = true;
activeLinkNodes[target.id] = target;
target.dirty = true;
}
} else {
offFlowLinks[target.z] = offFlowLinks[target.z]||[];
offFlowLinks[target.z].push(target);
}
} else {
offFlowLinks[target.z] = offFlowLinks[target.z]||[];
offFlowLinks[target.z].push(target);
}
} else {
if (target.z === linkNode.z) {
if (!addedLinkLinks[target.id+":"+linkNode.id]) {
activeLinks.push({
source:target,
sourcePort:0,
target: linkNode,
link: true
});
addedLinkLinks[target.id+":"+linkNode.id] = true;
activeLinkNodes[target.id] = target;
target.dirty = true;
if (target.z === linkNode.z) {
if (!addedLinkLinks[target.id+":"+linkNode.id]) {
activeLinks.push({
source:target,
sourcePort:0,
target: linkNode,
link: true
});
addedLinkLinks[target.id+":"+linkNode.id] = true;
activeLinkNodes[target.id] = target;
target.dirty = true;
}
} else {
offFlowLinks[target.z] = offFlowLinks[target.z]||[];
offFlowLinks[target.z].push(target);
}
} else {
offFlowLinks[target.z] = offFlowLinks[target.z]||[];
offFlowLinks[target.z].push(target);
}
}
}
});
var offFlows = Object.keys(offFlowLinks);
// offFlows.sort(function(A,B) {
// return tabOrder.indexOf(A) - tabOrder.indexOf(B);
// });
if (offFlows.length > 0) {
activeFlowLinks.push({
refresh: Math.floor(Math.random()*10000),
node: linkNode,
links: offFlowLinks//offFlows.map(function(i) { return {id:i,links:offFlowLinks[i]};})
});
var offFlows = Object.keys(offFlowLinks);
// offFlows.sort(function(A,B) {
// return tabOrder.indexOf(A) - tabOrder.indexOf(B);
// });
if (offFlows.length > 0) {
activeFlowLinks.push({
refresh: Math.floor(Math.random()*10000),
node: linkNode,
links: offFlowLinks//offFlows.map(function(i) { return {id:i,links:offFlowLinks[i]};})
});
}
}
}
if (activeFlowLinks.length === 0 && selected_link !== null && selected_link.link) {
activeLinks.push(selected_link);
activeLinkNodes[selected_link.source.id] = selected_link.source;
selected_link.source.dirty = true;
activeLinkNodes[selected_link.target.id] = selected_link.target;
selected_link.target.dirty = true;
}
} else {
selection.flows = workspaceSelection;
}
if (activeFlowLinks.length === 0 && selected_link !== null && selected_link.link) {
activeLinks.push(selected_link);
activeLinkNodes[selected_link.source.id] = selected_link.source;
selected_link.source.dirty = true;
activeLinkNodes[selected_link.target.id] = selected_link.target;
selected_link.target.dirty = true;
}
} else {
selection.flows = workspaceSelection;
}
var selectionJSON = activeWorkspace+":"+JSON.stringify(selection,function(key,value) {
if (key === 'nodes' || key === 'flows') {
@ -2332,6 +2366,7 @@ RED.view = (function() {
}
}
clipboard = JSON.stringify(nns);
RED.menu.setDisabled("menu-item-edit-paste", false);
if (nodeCount > 0) {
RED.notify(RED._("clipboard.nodeCopied",{count:nodeCount}),{id:"clipboard"});
} else if (groupCount > 0) {
@ -3807,7 +3842,6 @@ RED.view = (function() {
.attr("class", "red-ui-flow-node red-ui-flow-node-group")
.classed("red-ui-flow-subflow", activeSubflow != null);
nodeEnter.each(function(d,i) {
this.__outputs__ = [];
this.__inputs__ = [];
@ -3953,7 +3987,12 @@ RED.view = (function() {
RED.hooks.trigger("viewAddNode",{node:d,el:this})
});
var nodesReordered = false;
node.each(function(d,i) {
if (d._reordered) {
nodesReordered = true;
delete d._reordered;
}
if (d.dirty) {
var self = this;
var thisNode = d3.select(this);
@ -3967,10 +4006,10 @@ RED.view = (function() {
var labelParts;
if (d.resize || this.__hideLabel__ !== hideLabel || this.__label__ !== label || this.__outputs__.length !== d.outputs) {
labelParts = getLabelParts(label, "red-ui-flow-node-label");
this.__label__ = label;
if (labelParts.lines.length !== this.__labelLineCount__) {
if (labelParts.lines.length !== this.__labelLineCount__ || this.__label__ !== label) {
d.resize = true;
}
this.__label__ = label;
this.__labelLineCount__ = labelParts.lines.length;
if (hideLabel) {
@ -4101,7 +4140,7 @@ RED.view = (function() {
}
var numOutputs = d.outputs;
if (isLink && d.type === "link out") {
if (showAllLinkPorts===PORT_TYPE_OUTPUT || activeLinkNodes[d.id]) {
if (d.mode !== "return" && (showAllLinkPorts===PORT_TYPE_OUTPUT || activeLinkNodes[d.id])) {
numOutputs = 1;
} else {
numOutputs = 0;
@ -4261,6 +4300,13 @@ RED.view = (function() {
RED.hooks.trigger("viewRedrawNode",{node:d,el:this})
});
if (nodesReordered) {
node.sort(function(a,b) {
return a._index - b._index;
})
}
var link = linkLayer.selectAll(".red-ui-flow-link").data(
activeLinks,
function(d) {
@ -4499,7 +4545,7 @@ RED.view = (function() {
if (a._root === b._root) {
return a._depth - b._depth;
} else {
return a._root.localeCompare(b._root);
return a._index - b._index;
}
})
}

View File

@ -21,21 +21,46 @@ RED.workspaces = (function() {
var workspaceIndex = 0;
var viewStack = [];
var hideStack = [];
var viewStackPos = 0;
function addToViewStack(id) {
if (viewStackPos !== viewStack.length) {
viewStack.splice(viewStackPos);
}
viewStack.push(id);
viewStackPos = viewStack.length;
// console.warn("addToViewStack",id,viewStack);
}
function removeFromHideStack(id) {
hideStack = hideStack.filter(function(v) {
if (v === id) {
return false;
} else if (Array.isArray(v)) {
var i = v.indexOf(id);
if (i > -1) {
v.splice(i,1);
}
if (v.length === 0) {
return false;
}
return true
}
return true;
})
}
function addWorkspace(ws,skipHistoryEntry,targetIndex) {
if (ws) {
if (!ws.closeable) {
ws.hideable = true;
}
workspace_tabs.addTab(ws,targetIndex);
var hiddenTabs = JSON.parse(RED.settings.getLocal("hiddenTabs")||"{}");
if (hiddenTabs[ws.id]) {
workspace_tabs.hideTab(ws.id);
}
workspace_tabs.resize();
} else {
var tabId = RED.nodes.id();
@ -43,7 +68,15 @@ RED.workspaces = (function() {
workspaceIndex += 1;
} while ($("#red-ui-workspace-tabs a[title='"+RED._('workspace.defaultName',{number:workspaceIndex})+"']").size() !== 0);
ws = {type:"tab",id:tabId,disabled: false,info:"",label:RED._('workspace.defaultName',{number:workspaceIndex})};
ws = {
type: "tab",
id: tabId,
disabled: false,
info: "",
label: RED._('workspace.defaultName',{number:workspaceIndex}),
env: [],
hideable: true
};
RED.nodes.addWorkspace(ws,targetIndex);
workspace_tabs.addTab(ws,targetIndex);
workspace_tabs.activateTab(tabId);
@ -55,6 +88,7 @@ RED.workspaces = (function() {
RED.view.focus();
return ws;
}
function deleteWorkspace(ws) {
if (workspaceTabCount === 1) {
return;
@ -78,165 +112,9 @@ RED.workspaces = (function() {
if (subflow) {
RED.editor.editSubflow(subflow);
}
return;
} else {
RED.editor.editFlow(workspace);
}
RED.view.state(RED.state.EDITING);
var tabflowEditor;
var trayOptions = {
title: RED._("workspace.editFlow",{name:RED.utils.sanitize(workspace.label)}),
buttons: [
{
id: "node-dialog-delete",
class: 'leftButton'+((workspaceTabCount === 1)?" disabled":""),
text: RED._("common.label.delete"), //'<i class="fa fa-trash"></i>',
click: function() {
deleteWorkspace(workspace);
RED.tray.close();
}
},
{
id: "node-dialog-cancel",
text: RED._("common.label.cancel"),
click: function() {
RED.tray.close();
}
},
{
id: "node-dialog-ok",
class: "primary",
text: RED._("common.label.done"),
click: function() {
var label = $( "#node-input-name" ).val();
var changed = false;
var changes = {};
if (workspace.label != label) {
changes.label = workspace.label;
changed = true;
workspace.label = label;
workspace_tabs.renameTab(workspace.id,label);
}
var disabled = $("#node-input-disabled").prop("checked");
if (workspace.disabled !== disabled) {
changes.disabled = workspace.disabled;
changed = true;
workspace.disabled = disabled;
}
var info = tabflowEditor.getValue();
if (workspace.info !== info) {
changes.info = workspace.info;
changed = true;
workspace.info = info;
}
$("#red-ui-tab-"+(workspace.id.replace(".","-"))).toggleClass('red-ui-workspace-disabled',!!workspace.disabled);
$("#red-ui-workspace").toggleClass("red-ui-workspace-disabled",!!workspace.disabled);
if (changed) {
var historyEvent = {
t: "edit",
changes:changes,
node: workspace,
dirty: RED.nodes.dirty()
}
workspace.changed = true;
RED.history.push(historyEvent);
RED.nodes.dirty(true);
RED.sidebar.config.refresh();
if (changes.hasOwnProperty('disabled')) {
RED.nodes.eachNode(function(n) {
if (n.z === workspace.id) {
n.dirty = true;
}
});
RED.view.redraw();
}
RED.events.emit("flows:change",workspace);
}
RED.tray.close();
}
}
],
resize: function(dimensions) {
var rows = $("#dialog-form>div:not(.node-text-editor-row)");
var editorRow = $("#dialog-form>div.node-text-editor-row");
var height = $("#dialog-form").height();
for (var i=0; i<rows.size(); i++) {
height -= $(rows[i]).outerHeight(true);
}
height -= (parseInt($("#dialog-form").css("marginTop"))+parseInt($("#dialog-form").css("marginBottom")));
$(".node-text-editor").css("height",height+"px");
tabflowEditor.resize();
},
open: function(tray) {
var trayFooter = tray.find(".red-ui-tray-footer");
var trayBody = tray.find('.red-ui-tray-body');
var trayFooterLeft = $('<div class="red-ui-tray-footer-left"></div>').appendTo(trayFooter)
var dialogForm = $('<form id="dialog-form" class="form-horizontal"></form>').appendTo(trayBody);
$('<div class="form-row">'+
'<label for="node-input-name" data-i18n="[append]editor:common.label.name"><i class="fa fa-tag"></i> </label>'+
'<input type="text" id="node-input-name" data-i18n="[placeholder]common.label.name">'+
'</div>').appendTo(dialogForm);
if (!workspace.hasOwnProperty("disabled")) {
workspace.disabled = false;
}
$('<input id="node-input-disabled" type="checkbox">').prop("checked",workspace.disabled).appendTo(trayFooterLeft).toggleButton({
enabledIcon: "fa-circle-thin",
disabledIcon: "fa-ban",
invertState: true
})
var row = $('<div class="form-row node-text-editor-row">'+
'<label for="node-input-info" data-i18n="editor:workspace.info" style="width:300px;"></label>'+
'<div style="min-height:250px;" class="node-text-editor" id="node-input-info"></div>'+
'</div>').appendTo(dialogForm);
tabflowEditor = RED.editor.createEditor({
id: 'node-input-info',
mode: 'ace/mode/markdown',
value: ""
});
$('#node-info-input-info-expand').on("click", function(e) {
e.preventDefault();
var value = tabflowEditor.getValue();
RED.editor.editMarkdown({
value: value,
width: "Infinity",
cursor: tabflowEditor.getCursorPosition(),
complete: function(v,cursor) {
tabflowEditor.setValue(v, -1);
tabflowEditor.gotoLine(cursor.row+1,cursor.column,false);
setTimeout(function() {
tabflowEditor.focus();
},300);
}
})
});
$('<input type="text" style="display: none;" />').prependTo(dialogForm);
dialogForm.on("submit", function(e) { e.preventDefault();});
$("#node-input-name").val(workspace.label);
RED.text.bidi.prepareInput($("#node-input-name"));
tabflowEditor.getSession().setValue(workspace.info || "", -1);
dialogForm.i18n();
},
close: function() {
if (RED.view.state() != RED.state.IMPORT_DRAGGING) {
RED.view.state(RED.state.DEFAULT);
}
var selection = RED.view.selection();
if (!selection.nodes && !selection.links && workspace.id === activeWorkspace) {
RED.sidebar.info.refresh(workspace);
}
tabflowEditor.destroy();
}
}
RED.tray.show(trayOptions);
}
@ -249,11 +127,18 @@ RED.workspaces = (function() {
var event = {
old: activeWorkspace
}
activeWorkspace = tab.id;
if (tab) {
$("#red-ui-workspace-chart").show();
activeWorkspace = tab.id;
window.location.hash = 'flow/'+tab.id;
$("#red-ui-workspace").toggleClass("red-ui-workspace-disabled",!!tab.disabled);
} else {
$("#red-ui-workspace-chart").hide();
activeWorkspace = 0;
window.location.hash = '';
}
event.workspace = activeWorkspace;
RED.events.emit("workspace:change",event);
window.location.hash = 'flow/'+tab.id;
$("#red-ui-workspace").toggleClass("red-ui-workspace-disabled",!!tab.disabled);
RED.sidebar.config.refresh();
RED.view.focus();
},
@ -278,7 +163,7 @@ RED.workspaces = (function() {
if (tab.disabled) {
$("#red-ui-tab-"+(tab.id.replace(".","-"))).addClass('red-ui-workspace-disabled');
}
RED.menu.setDisabled("menu-item-workspace-delete",workspaceTabCount <= 1);
RED.menu.setDisabled("menu-item-workspace-delete",activeWorkspace === 0 || workspaceTabCount <= 1);
if (workspaceTabCount === 1) {
showWorkspace();
}
@ -286,14 +171,23 @@ RED.workspaces = (function() {
onremove: function(tab) {
if (tab.type === "tab") {
workspaceTabCount--;
} else {
hideStack.push(tab.id);
}
RED.menu.setDisabled("menu-item-workspace-delete",workspaceTabCount <= 1);
RED.menu.setDisabled("menu-item-workspace-delete",activeWorkspace === 0 || workspaceTabCount <= 1);
if (workspaceTabCount === 0) {
hideWorkspace();
}
},
onreorder: function(oldOrder, newOrder) {
RED.history.push({t:'reorder',order:oldOrder,dirty:RED.nodes.dirty()});
RED.history.push({
t:'reorder',
workspaces: {
from:oldOrder,
to:newOrder
},
dirty:RED.nodes.dirty()
});
RED.nodes.dirty(true);
setWorkspaceOrder(newOrder);
},
@ -312,12 +206,67 @@ RED.workspaces = (function() {
$(".red-ui-sidebar-shade").show();
}
},
onhide: function(tab) {
hideStack.push(tab.id);
RED.events.emit("workspace:hide",{workspace: tab.id})
},
onshow: function(tab) {
removeFromHideStack(tab.id);
RED.events.emit("workspace:show",{workspace: tab.id})
},
minimumActiveTabWidth: 150,
scrollable: true,
addButton: "core:add-flow",
addButtonCaption: RED._("workspace.addFlow"),
searchButton: "core:list-flows",
searchButtonCaption: RED._("workspace.listFlows")
menu: [
{
id:"red-ui-tabs-menu-option-search-flows",
label: RED._("workspace.listFlows"),
onselect: "core:list-flows"
},
{
id:"red-ui-tabs-menu-option-search-subflows",
label: RED._("workspace.listSubflows"),
onselect: "core:list-subflows"
},
null,
{
id:"red-ui-tabs-menu-option-add-flow",
label: RED._("workspace.addFlow"),
onselect: "core:add-flow"
},
{
id:"red-ui-tabs-menu-option-add-flow-right",
label: RED._("workspace.addFlowToRight"),
onselect: "core:add-flow-to-right"
},
null,
{
id:"red-ui-tabs-menu-option-add-hide-flows",
label: RED._("workspace.hideFlow"),
onselect: "core:hide-flow"
},
{
id:"red-ui-tabs-menu-option-add-hide-other-flows",
label: RED._("workspace.hideOtherFlows"),
onselect: "core:hide-other-flows"
},
{
id:"red-ui-tabs-menu-option-add-show-all-flows",
label: RED._("workspace.showAllFlows"),
onselect: "core:show-all-flows"
},
{
id:"red-ui-tabs-menu-option-add-hide-all-flows",
label: RED._("workspace.hideAllFlows"),
onselect: "core:hide-all-flows"
},
{
id:"red-ui-tabs-menu-option-add-show-last-flow",
label: RED._("workspace.showLastHiddenFlow"),
onselect: "core:show-last-hidden-flow"
}
]
});
workspaceTabCount = 0;
}
@ -368,15 +317,102 @@ RED.workspaces = (function() {
});
RED.actions.add("core:add-flow",function(opts) { addWorkspace(undefined,undefined,opts?opts.index:undefined)});
RED.actions.add("core:add-flow-to-right",function(opts) { addWorkspace(undefined,undefined,workspace_tabs.activeIndex()+1)});
RED.actions.add("core:edit-flow",editWorkspace);
RED.actions.add("core:remove-flow",removeWorkspace);
RED.actions.add("core:enable-flow",enableWorkspace);
RED.actions.add("core:disable-flow",disableWorkspace);
RED.actions.add("core:hide-flow", function() {
var selection = workspace_tabs.selection();
if (selection.length === 0) {
selection = [{id:activeWorkspace}]
}
var hiddenTabs = [];
selection.forEach(function(ws) {
RED.workspaces.hide(ws.id);
hideStack.pop();
hiddenTabs.push(ws.id);
})
if (hiddenTabs.length > 0) {
hideStack.push(hiddenTabs);
}
workspace_tabs.clearSelection();
})
RED.actions.add("core:hide-other-flows", function() {
var selection = workspace_tabs.selection();
if (selection.length === 0) {
selection = [{id:activeWorkspace}]
}
var selected = new Set(selection.map(function(ws) { return ws.id }))
var currentTabs = workspace_tabs.listTabs();
var hiddenTabs = [];
currentTabs.forEach(function(id) {
if (!selected.has(id)) {
RED.workspaces.hide(id);
hideStack.pop();
hiddenTabs.push(id);
}
})
if (hiddenTabs.length > 0) {
hideStack.push(hiddenTabs);
}
})
RED.actions.add("core:hide-all-flows", function() {
var currentTabs = workspace_tabs.listTabs();
currentTabs.forEach(function(id) {
RED.workspaces.hide(id);
hideStack.pop();
})
if (currentTabs.length > 0) {
hideStack.push(currentTabs);
}
workspace_tabs.clearSelection();
})
RED.actions.add("core:show-all-flows", function() {
var currentTabs = workspace_tabs.listTabs();
currentTabs.forEach(function(id) {
RED.workspaces.show(id, null, true)
})
})
// RED.actions.add("core:toggle-flows", function() {
// var currentTabs = workspace_tabs.listTabs();
// var visibleCount = workspace_tabs.count();
// currentTabs.forEach(function(id) {
// if (visibleCount === 0) {
// RED.workspaces.show(id)
// } else {
// RED.workspaces.hide(id)
// }
// })
// })
RED.actions.add("core:show-last-hidden-flow", function() {
var id = hideStack.pop();
if (id) {
if (typeof id === 'string') {
RED.workspaces.show(id);
} else {
var last = id.pop();
id.forEach(function(i) {
RED.workspaces.show(i, null, true);
})
setTimeout(function() {
RED.workspaces.show(last);
},150)
}
}
})
RED.actions.add("core:list-flows",function() {
RED.actions.invoke("core:search","type:tab ");
})
RED.actions.add("core:list-subflows",function() {
RED.actions.invoke("core:search","type:subflow ");
})
RED.actions.add("core:go-to-previous-location", function() {
if (viewStackPos > 0) {
if (viewStackPos === viewStack.length) {
@ -392,8 +428,6 @@ RED.workspaces = (function() {
RED.workspaces.show(viewStack[++viewStackPos],true);
}
})
hideWorkspace();
}
@ -416,7 +450,7 @@ RED.workspaces = (function() {
var changes = { disabled: workspace.disabled };
workspace.disabled = disabled;
$("#red-ui-tab-"+(workspace.id.replace(".","-"))).toggleClass('red-ui-workspace-disabled',!!workspace.disabled);
if (id === activeWorkspace) {
if (id || activeWorkspace) {
$("#red-ui-workspace").toggleClass("red-ui-workspace-disabled",!!workspace.disabled);
}
var historyEvent = {
@ -445,7 +479,6 @@ RED.workspaces = (function() {
}
}
function removeWorkspace(ws) {
if (!ws) {
deleteWorkspace(RED.nodes.workspace(activeWorkspace));
@ -474,7 +507,10 @@ RED.workspaces = (function() {
return {
init: init,
add: addWorkspace,
// remove: remove workspace without editor history etc
remove: removeWorkspace,
// delete: remove workspace and update editor history
delete: deleteWorkspace,
order: setWorkspaceOrder,
edit: editWorkspace,
contains: function(id) {
@ -489,7 +525,18 @@ RED.workspaces = (function() {
selection: function() {
return workspace_tabs.selection();
},
show: function(id,skipStack) {
hide: function(id) {
if (!id) {
id = activeWorkspace;
}
if (workspace_tabs.contains(id)) {
workspace_tabs.hideTab(id);
var hiddenTabs = JSON.parse(RED.settings.getLocal("hiddenTabs")||"{}");
hiddenTabs[id] = true;
RED.settings.setLocal("hiddenTabs",JSON.stringify(hiddenTabs));
}
},
show: function(id,skipStack,unhideOnly) {
if (!workspace_tabs.contains(id)) {
var sf = RED.nodes.subflow(id);
if (sf) {
@ -498,14 +545,22 @@ RED.workspaces = (function() {
null,
workspace_tabs.activeIndex()+1
);
removeFromHideStack(id);
} else {
return;
}
}
if (!skipStack && activeWorkspace !== id) {
addToViewStack(activeWorkspace)
if (unhideOnly) {
workspace_tabs.showTab(id);
} else {
if (!skipStack && activeWorkspace !== id) {
addToViewStack(activeWorkspace)
}
workspace_tabs.activateTab(id);
}
workspace_tabs.activateTab(id);
var hiddenTabs = JSON.parse(RED.settings.getLocal("hiddenTabs")||"{}");
delete hiddenTabs[id];
RED.settings.setLocal("hiddenTabs",JSON.stringify(hiddenTabs));
},
refresh: function() {
RED.nodes.eachWorkspace(function(ws) {

View File

@ -21,10 +21,10 @@ RED.user = (function() {
opts = {};
}
var dialog = $('<div id="node-dialog-login" class="hide">'+
'<div style="display: inline-block;width: 250px; vertical-align: top; margin-right: 10px; margin-bottom: 20px;"><img id="node-dialog-login-image" src=""/></div>'+
'<div style="display: inline-block; width: 250px; vertical-align: bottom; margin-left: 10px; margin-bottom: 20px;">'+
'<form id="node-dialog-login-fields" class="form-horizontal" style="margin-bottom: 0px;"></form>'+
var dialog = $('<div id="node-dialog-login" class="hide" style="display: flex; align-items: flex-end;">'+
'<div style="width: 250px; flex-grow: 0;"><img id="node-dialog-login-image" src=""/></div>'+
'<div style="flex-grow: 1;">'+
'<form id="node-dialog-login-fields" class="form-horizontal" style="margin-bottom: 0px; margin-left:20px;"></form>'+
'</div>'+
'</div>');
@ -76,7 +76,7 @@ RED.user = (function() {
}
row.appendTo("#node-dialog-login-fields");
}
$('<div class="form-row" style="text-align: right; margin-top: 10px;"><span id="node-dialog-login-failed" style="line-height: 2em;float:left;" class="hide">'+RED._("user.loginFailed")+'</span><img src="red/images/spin.svg" style="height: 30px; margin-right: 10px; " class="login-spinner hide"/>'+
$('<div class="form-row" style="text-align: right; margin-top: 10px;"><span id="node-dialog-login-failed" style="line-height: 2em;float:left;color:var(--red-ui-text-color-error);" class="hide">'+RED._("user.loginFailed")+'</span><img src="red/images/spin.svg" style="height: 30px; margin-right: 10px; " class="login-spinner hide"/>'+
(opts.cancelable?'<a href="#" id="node-dialog-login-cancel" class="red-ui-button" style="margin-right: 20px;" tabIndex="'+(i+1)+'">'+RED._("common.label.cancel")+'</a>':'')+
'<input type="submit" id="node-dialog-login-submit" class="red-ui-button" style="width: auto;" tabIndex="'+(i+2)+'" value="'+RED._("user.login")+'"></div>').appendTo("#node-dialog-login-fields");
@ -121,6 +121,24 @@ RED.user = (function() {
i = 0;
for (;i<data.prompts.length;i++) {
var field = data.prompts[i];
var sessionMessage = /[?&]session_message=(.*?)(?:$|&)/.exec(window.location.search);
if (sessionMessage) {
RED.sessionMessages = RED.sessionMessages || [];
RED.sessionMessages.push(sessionMessage[1]);
if (history.pushState) {
var newurl = window.location.protocol+"//"+window.location.host+window.location.pathname
window.history.replaceState({ path: newurl }, "", newurl);
} else {
window.location.search = "";
}
}
if (RED.sessionMessages) {
var sessionMessages = $("<div/>",{class:"form-row",style:"text-align: center"}).appendTo("#node-dialog-login-fields");
RED.sessionMessages.forEach(function (msg) {
$('<div>').css("color","var(--red-ui-text-color-error)").text(msg).appendTo(sessionMessages);
});
delete RED.sessionMessages;
}
var row = $("<div/>",{class:"form-row",style:"text-align: center"}).appendTo("#node-dialog-login-fields");
var loginButton = $('<a href="#" class="red-ui-button"></a>',{style: "padding: 10px"}).appendTo(row).on("click", function() {
@ -152,7 +170,7 @@ RED.user = (function() {
});
}
var loginImageSrc = data.image || "red/images/node-red-256.png";
var loginImageSrc = data.image || "red/images/node-red-256.svg";
$("#node-dialog-login-image").load(function() {
dialog.dialog("open");

View File

@ -140,8 +140,8 @@ $workspace-button-color-focus-outline: $form-input-focus-color;
$shade-color: rgba(160,160,160,0.5);
$popover-background: #333;
$popover-border: $popover-background;
$popover-color: #eee;
$popover-button-border-color: #bbb;
$popover-button-border-color-hover: #666;
@ -295,6 +295,9 @@ $group-default-stroke: #999;
$group-default-stroke-opacity: 1;
$group-default-label-color: #a4a4a4;
$tourGuide-border: #c56c6c;
$tourGuide-heading-color: #c56c6c;
// Deprecated
$text-color-green: $text-color-success;
$info-text-code-color: $text-color-code;

View File

@ -43,12 +43,24 @@
border-bottom: 1px solid $secondary-border-color;
box-shadow: 0 2px 6px $shadow;
}
.red-ui-debug-filter-row {
.red-ui-nodeList {
margin: 10px 0;
#red-ui-sidebar-debug-filter-node-list-row {
.red-ui-treeList-label.disabled {
font-style: italic;
color: $secondary-text-color-disabled;
}
.red-ui-treeList-label {
&.selected, &.selected .red-ui-treeList-sublabel-text {
background: inherit;
}
&.selected, &.selected .red-ui-treeList-sublabel-text {
background: inherit;
}
&.focus, &.focus .red-ui-treeList-sublabel-text {
background: $list-item-background-hover !important;
}
}
}
.red-ui-debug-msg {
position: relative;
border-bottom: 1px solid $debug-message-border;

View File

@ -19,7 +19,7 @@
font-size: $primary-font-size;
position: absolute;
top: 100%;
width: 200px;
width: 230px;
left: 0;
z-index: 1000;
display: none;
@ -46,7 +46,7 @@
& > li > a,
& > li > a:focus {
display: block;
padding: 4px 0 4px 32px;
padding: 4px 12px 4px 32px;
clear: both;
font-weight: normal;
line-height: 20px;
@ -68,6 +68,10 @@
& > .disabled > a:hover,
& > .disabled > a:focus {
color: $menuDisabledColor;
.red-ui-popover-key {
color: $menuDisabledColor;
border-color: $menuDisabledColor;
}
}
& > .disabled > a:hover,
@ -83,6 +87,7 @@
max-width: 14px;
}
.fa {
float: left;
width: 20px;
margin-left: -25px;
margin-top: 3px;
@ -102,6 +107,20 @@
display: none;
}
}
.red-ui-menu-label {
display: flex;
& > :first-child {
flex-grow: 1
}
}
.red-ui-popover-key {
border: none;
padding: 0;
font-size: 13px;
// float: right;
color: $menuColor;
border-color: $menuColor;
}
}
}
@ -113,6 +132,7 @@
.red-ui-menu-dropdown > li > a:hover,
.red-ui-menu-dropdown > li.open > a,
.red-ui-menu-dropdown > li > a:focus,
.red-ui-menu-dropdown-submenu:hover > a,
.red-ui-menu-dropdown-submenu:focus > a {
@ -129,6 +149,7 @@
margin-top: -6px;
margin-left: -1px;
}
&.open > .red-ui-menu-dropdown,
&:hover > .red-ui-menu-dropdown {
display: block;
}
@ -209,4 +230,4 @@ ul.red-ui-menu:not(.red-ui-menu-dropdown) {
}
}
}
}

View File

@ -191,14 +191,17 @@
margin-top: 0;
li a {
color: $header-menu-color;
padding: 3px 40px;
padding: 3px 10px 3px 40px;
img {
max-width: 100%;
margin-right: 10px;
padding: 4px;
border: 3px solid transparent;
}
.red-ui-popover-key {
color: $header-menu-color-disabled !important;
border-color: $header-menu-color-disabled !important;
}
&.active img {
border: 3px solid $header-menu-item-border-active;
}
@ -211,7 +214,6 @@
}
span.red-ui-menu-label {
font-size: 14px;
display: inline-block;
text-indent: 0px;
}
span.red-ui-menu-sublabel {
@ -222,6 +224,7 @@
}
}
> li > a:hover,
> li.open > a,
> li > a:focus,
> li:hover > a,
> li:focus > a {

View File

@ -137,10 +137,10 @@
padding: 0;
border: 1px solid $form-input-border-color;
}
.ui-spinner input {
.ui-spinner input[type=text] {
background: $form-input-background;
margin: 0 17px 0 0;
padding: 6px;
padding: 8px;
border: none;
border-top-right-radius: 0px;
border-bottom-right-radius: 0px;

View File

@ -19,19 +19,23 @@
display: none;
position: absolute;
width: auto;
padding: 10px;
padding: 2px;
height: auto;
background: $popover-background;
color: $popover-color;
background: var(--red-ui-popover-border);
color: var(--red-ui-popover-color);
border-radius: 4px;
z-index: 1000;
font-family: $primary-font;
font-size: 14px;
line-height: 1.4em;
@include component-shadow;
border-color: $popover-background;
border-color: var(--red-ui-popover-border);
}
.red-ui-popover-content {
padding: 8px;
border-radius: 2px;
background: var(--red-ui-popover-background);
}
.red-ui-popover:after, .red-ui-popover:before {
border: solid transparent;
content: " ";
@ -61,26 +65,26 @@
.red-ui-popover.red-ui-popover-right:after {
border-color: transparent;
border-right-color: $popover-background;
border-right-color: var(--red-ui-popover-border);
border-width: 10px;
margin-top: -10px;
}
.red-ui-popover.red-ui-popover-right:before {
border-color: transparent;
border-right-color: $popover-background;
border-right-color: var(--red-ui-popover-border);
border-width: 11px;
margin-top: -11px;
}
.red-ui-popover.red-ui-popover-left:after {
border-color: transparent;
border-left-color: $popover-background;
border-left-color: var(--red-ui-popover-border);
border-width: 10px;
margin-top: -10px;
}
.red-ui-popover.red-ui-popover-left:before {
border-color: transparent;
border-left-color: $popover-background;
border-left-color: var(--red-ui-popover-border);
border-width: 11px;
margin-top: -11px;
}
@ -88,26 +92,26 @@
.red-ui-popover.red-ui-popover-bottom:after {
border-color: transparent;
border-bottom-color: $popover-background;
border-bottom-color: var(--red-ui-popover-border);
border-width: 10px;
margin-left: -10px;
}
.red-ui-popover.red-ui-popover-bottom:before {
border-color: transparent;
border-bottom-color: $popover-background;
border-bottom-color: var(--red-ui-popover-border);
border-width: 11px;
margin-left: -11px;
}
.red-ui-popover.red-ui-popover-top:after {
border-color: transparent;
border-top-color: $popover-background;
border-top-color: var(--red-ui-popover-border);
border-width: 10px;
margin-left: -10px;
}
.red-ui-popover.red-ui-popover-top:before {
border-color: transparent;
border-top-color: $popover-background;
border-top-color: var(--red-ui-popover-border);
border-width: 11px;
margin-left: -11px;
}
@ -116,9 +120,10 @@
.red-ui-popover-size-small {
font-size: 12px;
padding: 5px 7px;
line-height: 1.8em;
.red-ui-popover-content {
padding: 1px 4px;
}
&.red-ui-popover-right:after, &.red-ui-popover-left:after {
border-width: 7px;
margin-top: -7px;
@ -143,7 +148,7 @@
font-size: 11px;
font-family: $monospace-font;
margin-left: 3px;
border: 1px solid $popover-color;
border: 1px solid var(--red-ui-popover-color);
border-radius:3px;
padding: 1px 2px;
}
@ -152,8 +157,8 @@
.red-ui-popover button.red-ui-button {
&:not(.primary) {
border-color: $popover-button-border-color;
background: $popover-background;
color: $popover-color !important;
background: var(--red-ui-popover-background);
color: var(--red-ui-popover-color) !important;
}
&:not(.primary):not(.disabled):not(.ui-button-disabled):hover {
border-color: $popover-button-border-color-hover;

View File

@ -73,13 +73,13 @@
.red-ui-projects-dialog-screen-start {
.red-ui-projects-dialog-screen-start-hero {
text-align: center;
font-size: 2em;
font-size: 1.4em;
padding: 10px;
min-height: 60px;
min-height: 40px;
color: $primary-text-color;
}
.red-ui-projects-dialog-screen-start-body {
min-height: 400px;
min-height: 300px;
line-height: 1.6em;
p {
font-size: 1.1em;
@ -92,7 +92,7 @@
}
button.red-ui-button.red-ui-projects-dialog-button {
width: calc(50% - 80px);
margin: 20px;
margin: 10px 20px;
height: auto;
line-height: 2em;
padding: 10px;

View File

@ -61,6 +61,7 @@
@import "ui/common/checkboxSet";
@import "ui/common/stack";
@import "ui/common/treeList";
@import "ui/common/autoComplete";
@import "dragdrop";
@ -69,3 +70,5 @@
@import "debug";
@import "radialMenu";
@import "tourGuide";

View File

@ -16,6 +16,7 @@
.red-ui-sidebar-info {
height: 100%;
overflow: hidden;
}
.red-ui-sidebar-info hr {
margin: 10px 0;
@ -212,6 +213,9 @@ div.red-ui-info-table {
border: none;
}
}
p {
display: inline;
}
}
.red-ui-help-info-header {
i {
@ -230,7 +234,26 @@ div.red-ui-info-table {
}
}
}
table {
border-collapse: collapse;
border: 1px solid var(--red-ui-secondary-border-color);
margin : 8px 0 8px 0;
min-width : 300px;
overflow : hidden;
}
table thead tr {
background-color: var(--red-ui-primary-background); //$primary-text-color;
border-bottom: 1px solid var(--red-ui-secondary-border-color);
color: var(--red-ui-header-text-color);
text-align: left;
}
table th,
table td {
padding: 6px 8px;
}
table tbody tr:nth-of-type(even) {
background-color: var(--red-ui-tertiary-background); //$primary-background;
}
}
.red-ui-sidebar-info-stack {
height: 100%;
@ -411,16 +434,19 @@ div.red-ui-info-table {
}
.red-ui-info-outline-item-controls {
position: absolute;
top:0;
bottom: 0;
right: 0px;
padding: 2px 3px 0 1px;
top:1px;
bottom: 1px;
right: 1px;
padding: 1px 2px 0 1px;
text-align: right;
background: $list-item-background;
.red-ui-treeList-label:hover & {
background: $list-item-background-hover;
}
.red-ui-treeList-label.focus & {
background: $list-item-background-hover;
}
.red-ui-treeList-label.selected & {
background: $list-item-background-selected;
}
@ -435,6 +461,12 @@ div.red-ui-info-table {
border: none;
background: none;
}
.fa-circle-thin {
display: none;
}
.fa-eye {
display: none;
}
}
.red-ui-info-outline-item-control-reveal,
.red-ui-info-outline-item-control-action {
@ -446,7 +478,17 @@ div.red-ui-info-table {
display: inline-block;
}
}
.fa-eye-slash {
display: none;
}
.red-ui-info-outline-item.red-ui-info-outline-item-hidden & {
.fa-eye-slash {
display: inline-block;
}
.fa-eye {
display: none;
}
}
.fa-ban {
display: none;
}

View File

@ -21,6 +21,9 @@
height: 35px;
box-sizing: border-box;
.hide-tab {
transition: width 0.1s ease-in;
}
.red-ui-tabs-scroll-container {
height: 60px;
overflow-x: scroll;
@ -142,13 +145,18 @@
padding-right: 21px;
}
&.red-ui-tabs-add {
padding-right: 35px;
padding-right: 29px;
}
&.red-ui-tabs-add.red-ui-tabs-scrollable {
padding-right: 59px;
padding-right: 53px;
}
&.red-ui-tabs-add.red-ui-tabs-menu.red-ui-tabs-scrollable,
&.red-ui-tabs-add.red-ui-tabs-search.red-ui-tabs-scrollable {
padding-right: 95px;
padding-right: 83px;
}
&.red-ui-tabs-add.red-ui-tabs-search.red-ui-tabs-menu.red-ui-tabs-scrollable {
padding-right: 113px;
}
&.red-ui-tabs-collapsible {
@ -232,13 +240,14 @@
a {
@include workspace-button;
line-height: 32px;
height: 32px;
width: 32px;
line-height: 30px;
height: 28px;
width: 28px;
margin-left: 2px;
margin-right: 2px;
margin-top: 3px;
margin-right:3px;
margin-left:3px;
border: 1px solid $primary-border-color;
margin-bottom: 3px;
border: none;
z-index: 2;
}
}
@ -280,6 +289,8 @@
border-left: none;
border-right: none;
border-top: none;
border-bottom: 1px solid $primary-border-color;
line-height: 34px;
}
}
.red-ui-tab-scroll-left {
@ -296,15 +307,30 @@
}
.red-ui-tabs.red-ui-tabs-add .red-ui-tab-scroll-right {
right: 38px;
right: 32px;
}
.red-ui-tabs.red-ui-tabs-add.red-ui-tabs-menu .red-ui-tab-scroll-right,
.red-ui-tabs.red-ui-tabs-add.red-ui-tabs-search .red-ui-tab-scroll-right {
right: 76px;
right: 64px;
}
.red-ui-tabs.red-ui-tabs-add.red-ui-tabs-menu .red-ui-tabs-add,
.red-ui-tabs.red-ui-tabs-add.red-ui-tabs-search .red-ui-tabs-add {
right: 38px;
right: 32px;
}
.red-ui-tabs.red-ui-tabs-add.red-ui-tabs-search.red-ui-tabs-menu {
.red-ui-tab-scroll-right {
right: 96px;
}
.red-ui-tabs-add {
right: 64px;
}
.red-ui-tabs-search {
right: 32px;
}
}
.red-ui-tabs-fade {
position: absolute;
bottom: 0;

View File

@ -0,0 +1,118 @@
.red-ui-tourGuide-shade {
position: absolute;
top:0;
left:0;
bottom:0;
right:0;
z-index: 2000;
overflow: hidden;
}
.red-ui-tourGuide-shade-focus {
display: block;
width: 100px;
height: 100px;
position: absolute;
z-index: 2001;
transform: translate(-50%, -50%);
border-radius: 50%;
border: 2px solid var(--red-ui-tourGuide-border);
&.transition {
transition: 0.4s ease;
transition-property: width,height;
}
&::before {
content: '';
position: absolute;
width: 100%;
height: 100%;
border-radius: 50%;
border: solid 6000px var(--red-ui-shade-color);
margin-left: -6000px;
margin-top: -6000px;
pointer-events: none;
}
}
.red-ui-popover.red-ui-tourGuide-popover {
z-index: 2003;
--red-ui-popover-background: var(--red-ui-secondary-background);
--red-ui-popover-border: var(--red-ui-tourGuide-border);
--red-ui-popover-color: var(--red-ui-primary-text-color);
.red-ui-popover-content {
h2 {
text-align: center;
margin-top: 0px;
line-height: 1.2em;
color: var(--red-ui-tourGuide-heading-color);
i.fa {
font-size: 1.5em
}
}
}
}
.red-ui-tourGuide-toolbar {
min-height: 36px;
position: relative;
display: flex;
align-items: flex-end;
}
.red-ui-tourGuide-breadcrumbs {
flex-grow: 1;
display: flex;
align-items: center;
justify-content: center;
font-size: 6px;
& > div {
display: inline-block;
}
i {
line-height: 16px;
margin: 0 3px;
}
}
.red-ui-tourGuide-popover-description {
padding: 10px 20px 5px;
}
.red-ui-tourGuide-popover-full {
.red-ui-tourGuide-popover-description {
padding: 20px 40px 10px;
text-align: center;
}
}
.red-ui-popover.red-ui-tourGuide-popover button.red-ui-button {
&:not(.primary) {
background: var(--red-ui-secondary-background);
color: var(--red-ui-primary-text-color) !important;
}
&:not(.primary):not(.disabled):not(.ui-button-disabled):hover {
border-color: $popover-button-border-color-hover;
}
}
// .red-ui-tourGuide-popover-bounce {
// animation: 10s ease-in 5s infinite both red-ui-tourGuide-popover-bounce;
// }
// // @keyframes *must* be on multiple lines so build-custom-theme can filter them out
// @keyframes red-ui-tourGuide-popover-bounce {
// 0%,
// 10%,
// 100% {
// -webkit-transform: translateY(0);
// transform: translateY(0);
// }
// 2%,8% {
// -webkit-transform: translateY(-5px);
// transform: translateY(-5px);
// }
// 5% {
// -webkit-transform: translateY(5px);
// transform: translateY(5px);
// }
// }

View File

@ -0,0 +1,5 @@
.red-ui-autoComplete-container {
&.red-ui-popover-panel {
border-top: none;
}
}

View File

@ -89,18 +89,27 @@
color: $list-item-color;
text-decoration: none;
}
&.focus, &.focus .red-ui-treeList-sublabel-text {
background: $list-item-background-hover;
outline: 1px solid $form-input-focus-color !important;
outline-offset: -1px;
color: $list-item-color;
}
&.selected, &.selected .red-ui-treeList-sublabel-text {
background: $list-item-background-selected;
outline: none;
color: $list-item-color;
}
input.red-ui-treeList-checkbox {
input.red-ui-treeList-checkbox,
input.red-ui-treeList-radio {
margin: 0;
}
}
.red-ui-treeList-label-text {
margin-left: 4px;
overflow: hidden;
text-overflow: ellipsis;
&:empty {
min-height: 20px;
}
@ -120,6 +129,7 @@
.red-ui-treeList-icon {
display: inline-block;
flex-shrink: 0;
width: 20px;
text-align: center;
}

View File

@ -81,7 +81,8 @@
z-index: 2000;
a {
padding: 6px 18px 6px 6px;
display: block;
display: flex;
align-items: center;
border-bottom: 1px solid $secondary-border-color;
color: $form-text-color;
&:hover {
@ -98,7 +99,7 @@
background: $workspace-button-background-active;
}
input[type="checkbox"] {
margin-right: 6px;
margin: 0 6px 0 0;
}
}
.red-ui-typedInput-icon {

View File

@ -81,12 +81,18 @@
--red-ui-node-status-changed-border: #{$node-status-changed-border};
--red-ui-node-status-changed-background: #{$node-status-changed-background};
--red-ui-node-border: #{$node-border};
--red-ui-node-port-background:#{$node-port-background};
--red-ui-node-label-color: #{$node-label-color};
--red-ui-node-selected-color: #{$node-selected-color};
--red-ui-port-selected-color: #{$port-selected-color};
--red-ui-popover-background: #{$popover-background};
--red-ui-popover-border: #{$popover-border};
--red-ui-popover-color: #{$popover-color};
--red-ui-tourGuide-border: #{$tourGuide-border};
--red-ui-tourGuide-heading-color: #{$tourGuide-heading-color};
}

View File

@ -0,0 +1,80 @@
export default {
steps: [
{
title: "Create your first flow",
width: 400,
description: 'This tutorial will guide you through creating your first flow',
nextButton: 'start'
},
{
element: "#red-ui-workspace .red-ui-tab-button.red-ui-tabs-add",
description: 'To add a new tab, click the <i class="fa fa-plus"></i> button',
wait: {
type: "dom-event",
event: "click",
element: "#red-ui-workspace .red-ui-tab-button.red-ui-tabs-add a"
},
},
{
element: '.red-ui-palette-node[data-palette-type="inject"]',
direction: 'right',
description: 'The palette lists all of the nodes available to use. Drag a new Inject node into the workspace.',
fallback: 'inset-bottom-right',
wait: {
type: "nr-event",
event: "nodes:add",
filter: function(event) {
if (event.type === "inject") {
this.injectNode = event;
return true;
}
return false
}
},
complete: function() {
$('.red-ui-palette-node[data-palette-type="inject"]').css("z-index","auto");
}
},
{
element: '.red-ui-palette-node[data-palette-type="debug"]',
direction: 'right',
description: 'Next, drag a new Debug node into the workspace.',
fallback: 'inset-bottom-right',
wait: {
type: "nr-event",
event: "nodes:add",
filter: function(event) {
if (event.type === "debug") {
this.debugNode = event;
return true;
}
return false
}
},
complete: function() {
$('.red-ui-palette-node[data-palette-type="debug"]').css("z-index","auto");
},
},
{
element: function() { return $("#"+this.injectNode.id+" .red-ui-flow-port") },
description: 'Add a wire from the output of the Inject node to the input of the Debug node',
fallback: 'inset-bottom-right',
wait: {
type: "nr-event",
event: "links:add",
filter: function(event) {
return event.source.id === this.injectNode.id && event.target.id === this.debugNode.id;
}
},
},
{
element: "#red-ui-header-button-deploy",
description: 'Deploy your changes so the flow is active in the runtime',
width: 200,
wait: {
type: "dom-event",
event: "click"
},
}
]
}

View File

@ -0,0 +1,151 @@
export default {
version: "2.1.0",
steps: [
{
titleIcon: "fa fa-map-o",
title: { "en-US": "Welcome to Node-RED 2.1!" },
description: { "en-US": "Let's take a moment to discover the new features in this release." }
},
{
title: { "en-US": "A new Tour Guide" },
description: { "en-US": "<p>First, as you've already found, we now have this tour of new features. We'll only show the tour the first time you open the editor for each new version of Node-RED.</p>"+
"<p>You can choose not to see this tour in the future by disabling it under the View tab of User Settings.</p>" }
},
{
title: { "en-US": "New Edit menu" },
prepare() {
$("#red-ui-header-button-sidemenu").trigger("click");
$("#menu-item-edit-menu").parent().addClass("open")
},
complete() {
$("#menu-item-edit-menu").parent().removeClass("open")
},
element: "#menu-item-edit-menu-submenu",
interactive: false,
direction: "left",
description: { "en-US": "<p>The main menu has been updated with a new 'Edit' section. This includes all of the familar options, like cut/paste and undo/redo.</p>"+
"<p>The menu now displays keyboard shortcuts for the options.</p>" }
},
{
title: { "en-US": "Arranging nodes" },
prepare() {
$("#red-ui-header-button-sidemenu").trigger("click");
$("#menu-item-arrange-menu").parent().addClass("open")
},
complete() {
$("#menu-item-arrange-menu").parent().removeClass("open")
},
element: "#menu-item-arrange-menu-submenu",
interactive: false,
direction: "left",
description: { "en-US": "<p>The new 'Arrange' section of the menu provides new options to help arrange your nodes. You can align them to a common edge, spread them out evenly or change their order.</p>" },
},
{
title: { "en-US": "Hiding tabs" },
element: "#red-ui-workspace-tabs > li.active",
description: { "en-US": '<p>Tabs can now be hidden by clicking their <i class="fa fa-times"></i> icon.</p><p>The Info Sidebar will still list all of your tabs, and tell you which ones are currently hidden.' },
interactive: false,
prepare() {
$("#red-ui-workspace-tabs > li.active .red-ui-tab-close").css("display","block");
},
complete() {
$("#red-ui-workspace-tabs > li.active .red-ui-tab-close").css("display","");
}
},
{
title: { "en-US": "Tab menu" },
element: "#red-ui-workspace-tabs-menu",
description: { "en-US": '<p>The new tab menu also provides lots of new options for your tabs.</p>' },
interactive: false,
direction: "left",
prepare() {
$("#red-ui-workspace > .red-ui-tabs > .red-ui-tabs-menu a").trigger("click");
},
complete() {
$(document).trigger("click");
}
},
{
title: { "en-US": "Flow and Group level environment variables" },
element: "#red-ui-workspace-tabs > li.active",
interactive: false,
description: { "en-US": "<p>Flows and Groups can now have their own environment variables that can be referenced by nodes inside them.</p>" },
},
{
prepare(done) {
RED.editor.editFlow(RED.nodes.workspace(RED.workspaces.active()),"editor-tab-envProperties");
setTimeout(done,700);
},
element: "#red-ui-tab-editor-tab-envProperties-link-button",
description: { "en-US": "<p>Their edit dialogs have a new Environment Variables section.</p>" },
},
{
element: ".node-input-env-container-row",
direction: "left",
description: { "en-US": '<p>The environment variables are listed in this table and new ones can be added by clicking the <i class="fa fa-plus"></i> button.</p>' },
complete(done) {
$("#node-dialog-cancel").trigger("click");
setTimeout(done,500);
}
},
{
title: {"en-US":"Link Call node added"},
prepare(done) {
this.paletteWasClosed = $("#red-ui-main-container").hasClass("red-ui-palette-closed");
RED.actions.invoke("core:toggle-palette",true)
$('[data-palette-type="link call"]')[0].scrollIntoView({block:"center"})
setTimeout(done,100);
},
element: '[data-palette-type="link call"]',
direction: "right",
description: { "en-US": '<p>The <code>Link Call</code> node lets you call another flow that begins with a <code>Link In</code> node and get the result back when the message reaches a <code>Link Out</code> node.</p>' },
},
{
title: {"en-US":"MQTT nodes support dynamic connections"},
prepare(done) {
$('[data-palette-type="mqtt out"]')[0].scrollIntoView({block:"center"})
setTimeout(done,100);
},
element: '[data-palette-type="mqtt out"]',
direction: "right",
description: { "en-US": '<p>The <code>MQTT</code> nodes now support creating their connections and subscriptions dynamically.</p>' },
},
{
title: {"en-US":"File nodes renamed"},
prepare(done) {
$('[data-palette-type="file"]')[0].scrollIntoView({block:"center"})
setTimeout(done,100);
},
complete() {
if (this.paletteWasClosed) {
RED.actions.invoke("core:toggle-palette",false)
}
},
element: '[data-palette-type="file"]',
direction: "right",
description: { "en-US": '<p>The file nodes have been renamed to make it clearer which node does what.</p>' },
},
{
title: {"en-US":"Deep copy option on Change node"},
prepare(done) {
var def = RED.nodes.getType('change')
RED.editor.edit({id:"test",type:"change",rules:[{t:'set',p:'payload',pt:'msg', tot:'msg',to:"anotherProperty"}],_def:def, _:def._})
setTimeout(done,700);
},
complete(done) {
$("#node-dialog-cancel").trigger("click");
setTimeout(done,500);
},
element: function() {
return $(".node-input-rule-property-deepCopy").next()
},
description: { "en-US": '<p>The Set rule has a new option to create a deep copy of the value. This ensures a complete copy is made, rather than using a reference.</p>' },
},
{
title: { "en-US": "And that's not all..." },
description: { "en-US": "<p>There are many more smaller changes, including:</p><ul><li>Auto-complete suggestions in the <code>msg</code> TypedInput.</li><li>Support for <code>msg.resetTimeout</code> in the <code>Join</code> node.</li><li>Pushing messages to the front of the queue in the <code>Delay</code> node's rate limiting mode.</li><li>An optional second output on the <code>Delay</code> node for rate limited messages.</li></ul>" }
}
]
}

View File

@ -1,5 +1,5 @@
/* NOTE: Do not edit directly! This file is generated using \`npm run update-types\` in https://github.com/Steve-Mcl/monaco-editor-esm-i18n */
/* NOTE: Do not edit directly! This file is generated using `npm run update-types` in https://github.com/node-red/nr-monaco-build */
interface NodeMessage {

View File

@ -1,5 +1,5 @@
/* NOTE: Do not edit directly! This file is generated using \`npm run update-types\` in https://github.com/Steve-Mcl/monaco-editor-esm-i18n */
/* NOTE: Do not edit directly! This file is generated using `npm run update-types` in https://github.com/node-red/nr-monaco-build */
/*

View File

@ -0,0 +1,127 @@
/* NOTE: Do not edit directly! This file is generated using `npm run update-types` in https://github.com/node-red/nr-monaco-build */
declare module 'assert' {
/** An alias of `assert.ok()`. */
function assert(value: any, message?: string | Error): asserts value;
namespace assert {
class AssertionError extends Error {
actual: any;
expected: any;
operator: string;
generatedMessage: boolean;
code: 'ERR_ASSERTION';
constructor(options?: {
/** If provided, the error message is set to this value. */
message?: string | undefined;
/** The `actual` property on the error instance. */
actual?: any;
/** The `expected` property on the error instance. */
expected?: any;
/** The `operator` property on the error instance. */
operator?: string | undefined;
/** If provided, the generated stack trace omits frames before this function. */
// tslint:disable-next-line:ban-types
stackStartFn?: Function | undefined;
});
}
class CallTracker {
calls(exact?: number): () => void;
calls<Func extends (...args: any[]) => any>(fn?: Func, exact?: number): Func;
report(): CallTrackerReportInformation[];
verify(): void;
}
interface CallTrackerReportInformation {
message: string;
/** The actual number of times the function was called. */
actual: number;
/** The number of times the function was expected to be called. */
expected: number;
/** The name of the function that is wrapped. */
operator: string;
/** A stack trace of the function. */
stack: object;
}
type AssertPredicate = RegExp | (new () => object) | ((thrown: any) => boolean) | object | Error;
function fail(message?: string | Error): never;
/** @deprecated since v10.0.0 - use fail([message]) or other assert functions instead. */
function fail(
actual: any,
expected: any,
message?: string | Error,
operator?: string,
// tslint:disable-next-line:ban-types
stackStartFn?: Function,
): never;
function ok(value: any, message?: string | Error): asserts value;
/** @deprecated since v9.9.0 - use strictEqual() instead. */
function equal(actual: any, expected: any, message?: string | Error): void;
/** @deprecated since v9.9.0 - use notStrictEqual() instead. */
function notEqual(actual: any, expected: any, message?: string | Error): void;
/** @deprecated since v9.9.0 - use deepStrictEqual() instead. */
function deepEqual(actual: any, expected: any, message?: string | Error): void;
/** @deprecated since v9.9.0 - use notDeepStrictEqual() instead. */
function notDeepEqual(actual: any, expected: any, message?: string | Error): void;
function strictEqual<T>(actual: any, expected: T, message?: string | Error): asserts actual is T;
function notStrictEqual(actual: any, expected: any, message?: string | Error): void;
function deepStrictEqual<T>(actual: any, expected: T, message?: string | Error): asserts actual is T;
function notDeepStrictEqual(actual: any, expected: any, message?: string | Error): void;
function throws(block: () => any, message?: string | Error): void;
function throws(block: () => any, error: AssertPredicate, message?: string | Error): void;
function doesNotThrow(block: () => any, message?: string | Error): void;
function doesNotThrow(block: () => any, error: AssertPredicate, message?: string | Error): void;
function ifError(value: any): asserts value is null | undefined;
function rejects(block: (() => Promise<any>) | Promise<any>, message?: string | Error): Promise<void>;
function rejects(
block: (() => Promise<any>) | Promise<any>,
error: AssertPredicate,
message?: string | Error,
): Promise<void>;
function doesNotReject(block: (() => Promise<any>) | Promise<any>, message?: string | Error): Promise<void>;
function doesNotReject(
block: (() => Promise<any>) | Promise<any>,
error: AssertPredicate,
message?: string | Error,
): Promise<void>;
function match(value: string, regExp: RegExp, message?: string | Error): void;
function doesNotMatch(value: string, regExp: RegExp, message?: string | Error): void;
const strict: Omit<
typeof assert,
| 'equal'
| 'notEqual'
| 'deepEqual'
| 'notDeepEqual'
| 'ok'
| 'strictEqual'
| 'deepStrictEqual'
| 'ifError'
| 'strict'
> & {
(value: any, message?: string | Error): asserts value;
equal: typeof strictEqual;
notEqual: typeof notStrictEqual;
deepEqual: typeof deepStrictEqual;
notDeepEqual: typeof notDeepStrictEqual;
// Mapped types and assertion functions are incompatible?
// TS2775: Assertions require every name in the call target
// to be declared with an explicit type annotation.
ok: typeof ok;
strictEqual: typeof strictEqual;
deepStrictEqual: typeof deepStrictEqual;
ifError: typeof ifError;
strict: typeof strict;
};
}
export = assert;
}

View File

@ -0,0 +1,229 @@
/* NOTE: Do not edit directly! This file is generated using `npm run update-types` in https://github.com/node-red/nr-monaco-build */
/**
* Async Hooks module: https://nodejs.org/api/async_hooks.html
*/
declare module 'async_hooks' {
/**
* Returns the asyncId of the current execution context.
*/
function executionAsyncId(): number;
/**
* The resource representing the current execution.
* Useful to store data within the resource.
*
* Resource objects returned by `executionAsyncResource()` are most often internal
* Node.js handle objects with undocumented APIs. Using any functions or properties
* on the object is likely to crash your application and should be avoided.
*
* Using `executionAsyncResource()` in the top-level execution context will
* return an empty object as there is no handle or request object to use,
* but having an object representing the top-level can be helpful.
*/
function executionAsyncResource(): object;
/**
* Returns the ID of the resource responsible for calling the callback that is currently being executed.
*/
function triggerAsyncId(): number;
interface HookCallbacks {
/**
* Called when a class is constructed that has the possibility to emit an asynchronous event.
* @param asyncId a unique ID for the async resource
* @param type the type of the async resource
* @param triggerAsyncId the unique ID of the async resource in whose execution context this async resource was created
* @param resource reference to the resource representing the async operation, needs to be released during destroy
*/
init?(asyncId: number, type: string, triggerAsyncId: number, resource: object): void;
/**
* When an asynchronous operation is initiated or completes a callback is called to notify the user.
* The before callback is called just before said callback is executed.
* @param asyncId the unique identifier assigned to the resource about to execute the callback.
*/
before?(asyncId: number): void;
/**
* Called immediately after the callback specified in before is completed.
* @param asyncId the unique identifier assigned to the resource which has executed the callback.
*/
after?(asyncId: number): void;
/**
* Called when a promise has resolve() called. This may not be in the same execution id
* as the promise itself.
* @param asyncId the unique id for the promise that was resolve()d.
*/
promiseResolve?(asyncId: number): void;
/**
* Called after the resource corresponding to asyncId is destroyed
* @param asyncId a unique ID for the async resource
*/
destroy?(asyncId: number): void;
}
interface AsyncHook {
/**
* Enable the callbacks for a given AsyncHook instance. If no callbacks are provided enabling is a noop.
*/
enable(): this;
/**
* Disable the callbacks for a given AsyncHook instance from the global pool of AsyncHook callbacks to be executed. Once a hook has been disabled it will not be called again until enabled.
*/
disable(): this;
}
/**
* Registers functions to be called for different lifetime events of each async operation.
* @param options the callbacks to register
* @return an AsyncHooks instance used for disabling and enabling hooks
*/
function createHook(options: HookCallbacks): AsyncHook;
interface AsyncResourceOptions {
/**
* The ID of the execution context that created this async event.
* @default executionAsyncId()
*/
triggerAsyncId?: number | undefined;
/**
* Disables automatic `emitDestroy` when the object is garbage collected.
* This usually does not need to be set (even if `emitDestroy` is called
* manually), unless the resource's `asyncId` is retrieved and the
* sensitive API's `emitDestroy` is called with it.
* @default false
*/
requireManualDestroy?: boolean | undefined;
}
/**
* The class AsyncResource was designed to be extended by the embedder's async resources.
* Using this users can easily trigger the lifetime events of their own resources.
*/
class AsyncResource {
/**
* AsyncResource() is meant to be extended. Instantiating a
* new AsyncResource() also triggers init. If triggerAsyncId is omitted then
* async_hook.executionAsyncId() is used.
* @param type The type of async event.
* @param triggerAsyncId The ID of the execution context that created
* this async event (default: `executionAsyncId()`), or an
* AsyncResourceOptions object (since 9.3)
*/
constructor(type: string, triggerAsyncId?: number|AsyncResourceOptions);
/**
* Binds the given function to the current execution context.
* @param fn The function to bind to the current execution context.
* @param type An optional name to associate with the underlying `AsyncResource`.
*/
static bind<Func extends (...args: any[]) => any>(fn: Func, type?: string): Func & { asyncResource: AsyncResource };
/**
* Binds the given function to execute to this `AsyncResource`'s scope.
* @param fn The function to bind to the current `AsyncResource`.
*/
bind<Func extends (...args: any[]) => any>(fn: Func): Func & { asyncResource: AsyncResource };
/**
* Call the provided function with the provided arguments in the
* execution context of the async resource. This will establish the
* context, trigger the AsyncHooks before callbacks, call the function,
* trigger the AsyncHooks after callbacks, and then restore the original
* execution context.
* @param fn The function to call in the execution context of this
* async resource.
* @param thisArg The receiver to be used for the function call.
* @param args Optional arguments to pass to the function.
*/
runInAsyncScope<This, Result>(fn: (this: This, ...args: any[]) => Result, thisArg?: This, ...args: any[]): Result;
/**
* Call AsyncHooks destroy callbacks.
*/
emitDestroy(): this;
/**
* @return the unique ID assigned to this AsyncResource instance.
*/
asyncId(): number;
/**
* @return the trigger ID for this AsyncResource instance.
*/
triggerAsyncId(): number;
}
/**
* When having multiple instances of `AsyncLocalStorage`, they are independent
* from each other. It is safe to instantiate this class multiple times.
*/
class AsyncLocalStorage<T> {
/**
* This method disables the instance of `AsyncLocalStorage`. All subsequent calls
* to `asyncLocalStorage.getStore()` will return `undefined` until
* `asyncLocalStorage.run()` is called again.
*
* When calling `asyncLocalStorage.disable()`, all current contexts linked to the
* instance will be exited.
*
* Calling `asyncLocalStorage.disable()` is required before the
* `asyncLocalStorage` can be garbage collected. This does not apply to stores
* provided by the `asyncLocalStorage`, as those objects are garbage collected
* along with the corresponding async resources.
*
* This method is to be used when the `asyncLocalStorage` is not in use anymore
* in the current process.
*/
disable(): void;
/**
* This method returns the current store. If this method is called outside of an
* asynchronous context initialized by calling `asyncLocalStorage.run`, it will
* return `undefined`.
*/
getStore(): T | undefined;
/**
* This methods runs a function synchronously within a context and return its
* return value. The store is not accessible outside of the callback function or
* the asynchronous operations created within the callback.
*
* Optionally, arguments can be passed to the function. They will be passed to the
* callback function.
*
* I the callback function throws an error, it will be thrown by `run` too. The
* stacktrace will not be impacted by this call and the context will be exited.
*/
// TODO: Apply generic vararg once available
run<R>(store: T, callback: (...args: any[]) => R, ...args: any[]): R;
/**
* This methods runs a function synchronously outside of a context and return its
* return value. The store is not accessible within the callback function or the
* asynchronous operations created within the callback.
*
* Optionally, arguments can be passed to the function. They will be passed to the
* callback function.
*
* If the callback function throws an error, it will be thrown by `exit` too. The
* stacktrace will not be impacted by this call and the context will be
* re-entered.
*/
// TODO: Apply generic vararg once available
exit<R>(callback: (...args: any[]) => R, ...args: any[]): R;
/**
* Calling `asyncLocalStorage.enterWith(store)` will transition into the context
* for the remainder of the current synchronous execution and will persist
* through any following asynchronous calls.
*/
enterWith(store: T): void;
}
}

View File

@ -1 +1,25 @@
declare module'node:buffer'{export*from'buffer';}declare module'buffer'{export const INSPECT_MAX_BYTES:number;export const kMaxLength:number;export const kStringMaxLength:number;export const constants:{MAX_LENGTH:number;MAX_STRING_LENGTH:number;};const BuffType:typeof Buffer;export type TranscodeEncoding="ascii"|"utf8"|"utf16le"|"ucs2"|"latin1"|"binary";export function transcode(source:Uint8Array,fromEnc:TranscodeEncoding,toEnc:TranscodeEncoding):Buffer;export const SlowBuffer:{new(size:number):Buffer;prototype:Buffer;};export{BuffType as Buffer};}
/* NOTE: Do not edit directly! This file is generated using `npm run update-types` in https://github.com/node-red/nr-monaco-build */
declare module 'buffer' {
export const INSPECT_MAX_BYTES: number;
export const kMaxLength: number;
export const kStringMaxLength: number;
export const constants: {
MAX_LENGTH: number;
MAX_STRING_LENGTH: number;
};
const BuffType: typeof Buffer;
export type TranscodeEncoding = "ascii" | "utf8" | "utf16le" | "ucs2" | "latin1" | "binary";
export function transcode(source: Uint8Array, fromEnc: TranscodeEncoding, toEnc: TranscodeEncoding): Buffer;
export const SlowBuffer: {
/** @deprecated since v6.0.0, use `Buffer.allocUnsafeSlow()` */
new(size: number): Buffer;
prototype: Buffer;
};
export { BuffType as Buffer };
}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,265 @@
/* NOTE: Do not edit directly! This file is generated using `npm run update-types` in https://github.com/node-red/nr-monaco-build */
declare module 'cluster' {
import * as child from 'child_process';
import EventEmitter = require('events');
import * as net from 'net';
// interfaces
interface ClusterSettings {
execArgv?: string[] | undefined; // default: process.execArgv
exec?: string | undefined;
args?: string[] | undefined;
silent?: boolean | undefined;
stdio?: any[] | undefined;
uid?: number | undefined;
gid?: number | undefined;
inspectPort?: number | (() => number) | undefined;
}
interface Address {
address: string;
port: number;
addressType: number | "udp4" | "udp6"; // 4, 6, -1, "udp4", "udp6"
}
class Worker extends EventEmitter {
id: number;
process: child.ChildProcess;
send(message: child.Serializable, sendHandle?: child.SendHandle, callback?: (error: Error | null) => void): boolean;
kill(signal?: string): void;
destroy(signal?: string): void;
disconnect(): void;
isConnected(): boolean;
isDead(): boolean;
exitedAfterDisconnect: boolean;
/**
* events.EventEmitter
* 1. disconnect
* 2. error
* 3. exit
* 4. listening
* 5. message
* 6. online
*/
addListener(event: string, listener: (...args: any[]) => void): this;
addListener(event: "disconnect", listener: () => void): this;
addListener(event: "error", listener: (error: Error) => void): this;
addListener(event: "exit", listener: (code: number, signal: string) => void): this;
addListener(event: "listening", listener: (address: Address) => void): this;
addListener(event: "message", listener: (message: any, handle: net.Socket | net.Server) => void): this; // the handle is a net.Socket or net.Server object, or undefined.
addListener(event: "online", listener: () => void): this;
emit(event: string | symbol, ...args: any[]): boolean;
emit(event: "disconnect"): boolean;
emit(event: "error", error: Error): boolean;
emit(event: "exit", code: number, signal: string): boolean;
emit(event: "listening", address: Address): boolean;
emit(event: "message", message: any, handle: net.Socket | net.Server): boolean;
emit(event: "online"): boolean;
on(event: string, listener: (...args: any[]) => void): this;
on(event: "disconnect", listener: () => void): this;
on(event: "error", listener: (error: Error) => void): this;
on(event: "exit", listener: (code: number, signal: string) => void): this;
on(event: "listening", listener: (address: Address) => void): this;
on(event: "message", listener: (message: any, handle: net.Socket | net.Server) => void): this; // the handle is a net.Socket or net.Server object, or undefined.
on(event: "online", listener: () => void): this;
once(event: string, listener: (...args: any[]) => void): this;
once(event: "disconnect", listener: () => void): this;
once(event: "error", listener: (error: Error) => void): this;
once(event: "exit", listener: (code: number, signal: string) => void): this;
once(event: "listening", listener: (address: Address) => void): this;
once(event: "message", listener: (message: any, handle: net.Socket | net.Server) => void): this; // the handle is a net.Socket or net.Server object, or undefined.
once(event: "online", listener: () => void): this;
prependListener(event: string, listener: (...args: any[]) => void): this;
prependListener(event: "disconnect", listener: () => void): this;
prependListener(event: "error", listener: (error: Error) => void): this;
prependListener(event: "exit", listener: (code: number, signal: string) => void): this;
prependListener(event: "listening", listener: (address: Address) => void): this;
prependListener(event: "message", listener: (message: any, handle: net.Socket | net.Server) => void): this; // the handle is a net.Socket or net.Server object, or undefined.
prependListener(event: "online", listener: () => void): this;
prependOnceListener(event: string, listener: (...args: any[]) => void): this;
prependOnceListener(event: "disconnect", listener: () => void): this;
prependOnceListener(event: "error", listener: (error: Error) => void): this;
prependOnceListener(event: "exit", listener: (code: number, signal: string) => void): this;
prependOnceListener(event: "listening", listener: (address: Address) => void): this;
prependOnceListener(event: "message", listener: (message: any, handle: net.Socket | net.Server) => void): this; // the handle is a net.Socket or net.Server object, or undefined.
prependOnceListener(event: "online", listener: () => void): this;
}
interface Cluster extends EventEmitter {
Worker: Worker;
disconnect(callback?: () => void): void;
fork(env?: any): Worker;
isMaster: boolean;
isWorker: boolean;
schedulingPolicy: number;
settings: ClusterSettings;
setupMaster(settings?: ClusterSettings): void;
worker?: Worker | undefined;
workers?: NodeJS.Dict<Worker> | undefined;
readonly SCHED_NONE: number;
readonly SCHED_RR: number;
/**
* events.EventEmitter
* 1. disconnect
* 2. exit
* 3. fork
* 4. listening
* 5. message
* 6. online
* 7. setup
*/
addListener(event: string, listener: (...args: any[]) => void): this;
addListener(event: "disconnect", listener: (worker: Worker) => void): this;
addListener(event: "exit", listener: (worker: Worker, code: number, signal: string) => void): this;
addListener(event: "fork", listener: (worker: Worker) => void): this;
addListener(event: "listening", listener: (worker: Worker, address: Address) => void): this;
addListener(event: "message", listener: (worker: Worker, message: any, handle: net.Socket | net.Server) => void): this; // the handle is a net.Socket or net.Server object, or undefined.
addListener(event: "online", listener: (worker: Worker) => void): this;
addListener(event: "setup", listener: (settings: ClusterSettings) => void): this;
emit(event: string | symbol, ...args: any[]): boolean;
emit(event: "disconnect", worker: Worker): boolean;
emit(event: "exit", worker: Worker, code: number, signal: string): boolean;
emit(event: "fork", worker: Worker): boolean;
emit(event: "listening", worker: Worker, address: Address): boolean;
emit(event: "message", worker: Worker, message: any, handle: net.Socket | net.Server): boolean;
emit(event: "online", worker: Worker): boolean;
emit(event: "setup", settings: ClusterSettings): boolean;
on(event: string, listener: (...args: any[]) => void): this;
on(event: "disconnect", listener: (worker: Worker) => void): this;
on(event: "exit", listener: (worker: Worker, code: number, signal: string) => void): this;
on(event: "fork", listener: (worker: Worker) => void): this;
on(event: "listening", listener: (worker: Worker, address: Address) => void): this;
on(event: "message", listener: (worker: Worker, message: any, handle: net.Socket | net.Server) => void): this; // the handle is a net.Socket or net.Server object, or undefined.
on(event: "online", listener: (worker: Worker) => void): this;
on(event: "setup", listener: (settings: ClusterSettings) => void): this;
once(event: string, listener: (...args: any[]) => void): this;
once(event: "disconnect", listener: (worker: Worker) => void): this;
once(event: "exit", listener: (worker: Worker, code: number, signal: string) => void): this;
once(event: "fork", listener: (worker: Worker) => void): this;
once(event: "listening", listener: (worker: Worker, address: Address) => void): this;
once(event: "message", listener: (worker: Worker, message: any, handle: net.Socket | net.Server) => void): this; // the handle is a net.Socket or net.Server object, or undefined.
once(event: "online", listener: (worker: Worker) => void): this;
once(event: "setup", listener: (settings: ClusterSettings) => void): this;
prependListener(event: string, listener: (...args: any[]) => void): this;
prependListener(event: "disconnect", listener: (worker: Worker) => void): this;
prependListener(event: "exit", listener: (worker: Worker, code: number, signal: string) => void): this;
prependListener(event: "fork", listener: (worker: Worker) => void): this;
prependListener(event: "listening", listener: (worker: Worker, address: Address) => void): this;
prependListener(event: "message", listener: (worker: Worker, message: any, handle: net.Socket | net.Server) => void): this; // the handle is a net.Socket or net.Server object, or undefined.
prependListener(event: "online", listener: (worker: Worker) => void): this;
prependListener(event: "setup", listener: (settings: ClusterSettings) => void): this;
prependOnceListener(event: string, listener: (...args: any[]) => void): this;
prependOnceListener(event: "disconnect", listener: (worker: Worker) => void): this;
prependOnceListener(event: "exit", listener: (worker: Worker, code: number, signal: string) => void): this;
prependOnceListener(event: "fork", listener: (worker: Worker) => void): this;
prependOnceListener(event: "listening", listener: (worker: Worker, address: Address) => void): this;
// the handle is a net.Socket or net.Server object, or undefined.
prependOnceListener(event: "message", listener: (worker: Worker, message: any, handle: net.Socket | net.Server) => void): this;
prependOnceListener(event: "online", listener: (worker: Worker) => void): this;
prependOnceListener(event: "setup", listener: (settings: ClusterSettings) => void): this;
}
const SCHED_NONE: number;
const SCHED_RR: number;
function disconnect(callback?: () => void): void;
function fork(env?: any): Worker;
const isMaster: boolean;
const isWorker: boolean;
let schedulingPolicy: number;
const settings: ClusterSettings;
function setupMaster(settings?: ClusterSettings): void;
const worker: Worker;
const workers: NodeJS.Dict<Worker>;
/**
* events.EventEmitter
* 1. disconnect
* 2. exit
* 3. fork
* 4. listening
* 5. message
* 6. online
* 7. setup
*/
function addListener(event: string, listener: (...args: any[]) => void): Cluster;
function addListener(event: "disconnect", listener: (worker: Worker) => void): Cluster;
function addListener(event: "exit", listener: (worker: Worker, code: number, signal: string) => void): Cluster;
function addListener(event: "fork", listener: (worker: Worker) => void): Cluster;
function addListener(event: "listening", listener: (worker: Worker, address: Address) => void): Cluster;
// the handle is a net.Socket or net.Server object, or undefined.
function addListener(event: "message", listener: (worker: Worker, message: any, handle: net.Socket | net.Server) => void): Cluster;
function addListener(event: "online", listener: (worker: Worker) => void): Cluster;
function addListener(event: "setup", listener: (settings: ClusterSettings) => void): Cluster;
function emit(event: string | symbol, ...args: any[]): boolean;
function emit(event: "disconnect", worker: Worker): boolean;
function emit(event: "exit", worker: Worker, code: number, signal: string): boolean;
function emit(event: "fork", worker: Worker): boolean;
function emit(event: "listening", worker: Worker, address: Address): boolean;
function emit(event: "message", worker: Worker, message: any, handle: net.Socket | net.Server): boolean;
function emit(event: "online", worker: Worker): boolean;
function emit(event: "setup", settings: ClusterSettings): boolean;
function on(event: string, listener: (...args: any[]) => void): Cluster;
function on(event: "disconnect", listener: (worker: Worker) => void): Cluster;
function on(event: "exit", listener: (worker: Worker, code: number, signal: string) => void): Cluster;
function on(event: "fork", listener: (worker: Worker) => void): Cluster;
function on(event: "listening", listener: (worker: Worker, address: Address) => void): Cluster;
function on(event: "message", listener: (worker: Worker, message: any, handle: net.Socket | net.Server) => void): Cluster; // the handle is a net.Socket or net.Server object, or undefined.
function on(event: "online", listener: (worker: Worker) => void): Cluster;
function on(event: "setup", listener: (settings: ClusterSettings) => void): Cluster;
function once(event: string, listener: (...args: any[]) => void): Cluster;
function once(event: "disconnect", listener: (worker: Worker) => void): Cluster;
function once(event: "exit", listener: (worker: Worker, code: number, signal: string) => void): Cluster;
function once(event: "fork", listener: (worker: Worker) => void): Cluster;
function once(event: "listening", listener: (worker: Worker, address: Address) => void): Cluster;
function once(event: "message", listener: (worker: Worker, message: any, handle: net.Socket | net.Server) => void): Cluster; // the handle is a net.Socket or net.Server object, or undefined.
function once(event: "online", listener: (worker: Worker) => void): Cluster;
function once(event: "setup", listener: (settings: ClusterSettings) => void): Cluster;
function removeListener(event: string, listener: (...args: any[]) => void): Cluster;
function removeAllListeners(event?: string): Cluster;
function setMaxListeners(n: number): Cluster;
function getMaxListeners(): number;
function listeners(event: string): Function[];
function listenerCount(type: string): number;
function prependListener(event: string, listener: (...args: any[]) => void): Cluster;
function prependListener(event: "disconnect", listener: (worker: Worker) => void): Cluster;
function prependListener(event: "exit", listener: (worker: Worker, code: number, signal: string) => void): Cluster;
function prependListener(event: "fork", listener: (worker: Worker) => void): Cluster;
function prependListener(event: "listening", listener: (worker: Worker, address: Address) => void): Cluster;
// the handle is a net.Socket or net.Server object, or undefined.
function prependListener(event: "message", listener: (worker: Worker, message: any, handle: net.Socket | net.Server) => void): Cluster;
function prependListener(event: "online", listener: (worker: Worker) => void): Cluster;
function prependListener(event: "setup", listener: (settings: ClusterSettings) => void): Cluster;
function prependOnceListener(event: string, listener: (...args: any[]) => void): Cluster;
function prependOnceListener(event: "disconnect", listener: (worker: Worker) => void): Cluster;
function prependOnceListener(event: "exit", listener: (worker: Worker, code: number, signal: string) => void): Cluster;
function prependOnceListener(event: "fork", listener: (worker: Worker) => void): Cluster;
function prependOnceListener(event: "listening", listener: (worker: Worker, address: Address) => void): Cluster;
// the handle is a net.Socket or net.Server object, or undefined.
function prependOnceListener(event: "message", listener: (worker: Worker, message: any, handle: net.Socket | net.Server) => void): Cluster;
function prependOnceListener(event: "online", listener: (worker: Worker) => void): Cluster;
function prependOnceListener(event: "setup", listener: (settings: ClusterSettings) => void): Cluster;
function eventNames(): string[];
}

View File

@ -1 +1,136 @@
declare module'node:console'{export=console;}declare module'console'{import{InspectOptions}from'node:util';global{interface Console{Console:NodeJS.ConsoleConstructor;assert(value:any,message?:string,...optionalParams:any[]):void;clear():void;count(label?:string):void;countReset(label?:string):void;debug(message?:any,...optionalParams:any[]):void;dir(obj:any,options?:InspectOptions):void;dirxml(...data:any[]):void;error(message?:any,...optionalParams:any[]):void;group(...label:any[]):void;groupCollapsed(...label:any[]):void;groupEnd():void;info(message?:any,...optionalParams:any[]):void;log(message?:any,...optionalParams:any[]):void;table(tabularData:any,properties?:ReadonlyArray<string>):void;time(label?:string):void;timeEnd(label?:string):void;timeLog(label?:string,...data:any[]):void;trace(message?:any,...optionalParams:any[]):void;warn(message?:any,...optionalParams:any[]):void;profile(label?:string):void;profileEnd(label?:string):void;timeStamp(label?:string):void;}var console:Console;namespace NodeJS{interface ConsoleConstructorOptions{stdout:WritableStream;stderr?:WritableStream;ignoreErrors?:boolean;colorMode?:boolean|'auto';inspectOptions?:InspectOptions;}interface ConsoleConstructor{prototype:Console;new(stdout:WritableStream,stderr?:WritableStream,ignoreErrors?:boolean):Console;new(options:ConsoleConstructorOptions):Console;}interface Global{console:typeof console;}}}export=console;}
/* NOTE: Do not edit directly! This file is generated using `npm run update-types` in https://github.com/node-red/nr-monaco-build */
declare module 'console' {
import { InspectOptions } from 'util';
global {
// This needs to be global to avoid TS2403 in case lib.dom.d.ts is present in the same build
interface Console {
Console: NodeJS.ConsoleConstructor;
/**
* A simple assertion test that verifies whether `value` is truthy.
* If it is not, an `AssertionError` is thrown.
* If provided, the error `message` is formatted using `util.format()` and used as the error message.
*/
assert(value: any, message?: string, ...optionalParams: any[]): void;
/**
* When `stdout` is a TTY, calling `console.clear()` will attempt to clear the TTY.
* When `stdout` is not a TTY, this method does nothing.
*/
clear(): void;
/**
* Maintains an internal counter specific to `label` and outputs to `stdout` the number of times `console.count()` has been called with the given `label`.
*/
count(label?: string): void;
/**
* Resets the internal counter specific to `label`.
*/
countReset(label?: string): void;
/**
* The `console.debug()` function is an alias for {@link console.log}.
*/
debug(message?: any, ...optionalParams: any[]): void;
/**
* Uses {@link util.inspect} on `obj` and prints the resulting string to `stdout`.
* This function bypasses any custom `inspect()` function defined on `obj`.
*/
dir(obj: any, options?: InspectOptions): void;
/**
* This method calls {@link console.log} passing it the arguments received. Please note that this method does not produce any XML formatting
*/
dirxml(...data: any[]): void;
/**
* Prints to `stderr` with newline.
*/
error(message?: any, ...optionalParams: any[]): void;
/**
* Increases indentation of subsequent lines by two spaces.
* If one or more `label`s are provided, those are printed first without the additional indentation.
*/
group(...label: any[]): void;
/**
* The `console.groupCollapsed()` function is an alias for {@link console.group}.
*/
groupCollapsed(...label: any[]): void;
/**
* Decreases indentation of subsequent lines by two spaces.
*/
groupEnd(): void;
/**
* The {@link console.info} function is an alias for {@link console.log}.
*/
info(message?: any, ...optionalParams: any[]): void;
/**
* Prints to `stdout` with newline.
*/
log(message?: any, ...optionalParams: any[]): void;
/**
* This method does not display anything unless used in the inspector.
* Prints to `stdout` the array `array` formatted as a table.
*/
table(tabularData: any, properties?: ReadonlyArray<string>): void;
/**
* Starts a timer that can be used to compute the duration of an operation. Timers are identified by a unique `label`.
*/
time(label?: string): void;
/**
* Stops a timer that was previously started by calling {@link console.time} and prints the result to `stdout`.
*/
timeEnd(label?: string): void;
/**
* For a timer that was previously started by calling {@link console.time}, prints the elapsed time and other `data` arguments to `stdout`.
*/
timeLog(label?: string, ...data: any[]): void;
/**
* Prints to `stderr` the string 'Trace :', followed by the {@link util.format} formatted message and stack trace to the current position in the code.
*/
trace(message?: any, ...optionalParams: any[]): void;
/**
* The {@link console.warn} function is an alias for {@link console.error}.
*/
warn(message?: any, ...optionalParams: any[]): void;
// --- Inspector mode only ---
/**
* This method does not display anything unless used in the inspector.
* Starts a JavaScript CPU profile with an optional label.
*/
profile(label?: string): void;
/**
* This method does not display anything unless used in the inspector.
* Stops the current JavaScript CPU profiling session if one has been started and prints the report to the Profiles panel of the inspector.
*/
profileEnd(label?: string): void;
/**
* This method does not display anything unless used in the inspector.
* Adds an event with the label `label` to the Timeline panel of the inspector.
*/
timeStamp(label?: string): void;
}
var console: Console;
namespace NodeJS {
interface ConsoleConstructorOptions {
stdout: WritableStream;
stderr?: WritableStream | undefined;
ignoreErrors?: boolean | undefined;
colorMode?: boolean | 'auto' | undefined;
inspectOptions?: InspectOptions | undefined;
}
interface ConsoleConstructor {
prototype: Console;
new(stdout: WritableStream, stderr?: WritableStream, ignoreErrors?: boolean): Console;
new(options: ConsoleConstructorOptions): Console;
}
interface Global {
console: typeof console;
}
}
}
export = console;
}

File diff suppressed because one or more lines are too long

View File

@ -1 +1,144 @@
declare module'node:dgram'{export*from'dgram';}declare module'dgram'{import{AddressInfo}from'node:net';import*as dns from'node:dns';import EventEmitter=require('node:events');interface RemoteInfo{address:string;family:'IPv4'|'IPv6';port:number;size:number;}interface BindOptions{port?:number;address?:string;exclusive?:boolean;fd?:number;}type SocketType="udp4"|"udp6";interface SocketOptions{type:SocketType;reuseAddr?:boolean;ipv6Only?:boolean;recvBufferSize?:number;sendBufferSize?:number;lookup?:(hostname:string,options:dns.LookupOneOptions,callback:(err:NodeJS.ErrnoException|null,address:string,family:number)=>void)=>void;}function createSocket(type:SocketType,callback?:(msg:Buffer,rinfo:RemoteInfo)=>void):Socket;function createSocket(options:SocketOptions,callback?:(msg:Buffer,rinfo:RemoteInfo)=>void):Socket;class Socket extends EventEmitter{addMembership(multicastAddress:string,multicastInterface?:string):void;address():AddressInfo;bind(port?:number,address?:string,callback?:()=>void):void;bind(port?:number,callback?:()=>void):void;bind(callback?:()=>void):void;bind(options:BindOptions,callback?:()=>void):void;close(callback?:()=>void):void;connect(port:number,address?:string,callback?:()=>void):void;connect(port:number,callback:()=>void):void;disconnect():void;dropMembership(multicastAddress:string,multicastInterface?:string):void;getRecvBufferSize():number;getSendBufferSize():number;ref():this;remoteAddress():AddressInfo;send(msg:string|Uint8Array|ReadonlyArray<any>,port?:number,address?:string,callback?:(error:Error|null,bytes:number)=>void):void;send(msg:string|Uint8Array|ReadonlyArray<any>,port?:number,callback?:(error:Error|null,bytes:number)=>void):void;send(msg:string|Uint8Array|ReadonlyArray<any>,callback?:(error:Error|null,bytes:number)=>void):void;send(msg:string|Uint8Array,offset:number,length:number,port?:number,address?:string,callback?:(error:Error|null,bytes:number)=>void):void;send(msg:string|Uint8Array,offset:number,length:number,port?:number,callback?:(error:Error|null,bytes:number)=>void):void;send(msg:string|Uint8Array,offset:number,length:number,callback?:(error:Error|null,bytes:number)=>void):void;setBroadcast(flag:boolean):void;setMulticastInterface(multicastInterface:string):void;setMulticastLoopback(flag:boolean):void;setMulticastTTL(ttl:number):void;setRecvBufferSize(size:number):void;setSendBufferSize(size:number):void;setTTL(ttl:number):void;unref():this;addSourceSpecificMembership(sourceAddress:string,groupAddress:string,multicastInterface?:string):void;dropSourceSpecificMembership(sourceAddress:string,groupAddress:string,multicastInterface?:string):void;addListener(event:string,listener:(...args:any[])=>void):this;addListener(event:"close",listener:()=>void):this;addListener(event:"connect",listener:()=>void):this;addListener(event:"error",listener:(err:Error)=>void):this;addListener(event:"listening",listener:()=>void):this;addListener(event:"message",listener:(msg:Buffer,rinfo:RemoteInfo)=>void):this;emit(event:string|symbol,...args:any[]):boolean;emit(event:"close"):boolean;emit(event:"connect"):boolean;emit(event:"error",err:Error):boolean;emit(event:"listening"):boolean;emit(event:"message",msg:Buffer,rinfo:RemoteInfo):boolean;on(event:string,listener:(...args:any[])=>void):this;on(event:"close",listener:()=>void):this;on(event:"connect",listener:()=>void):this;on(event:"error",listener:(err:Error)=>void):this;on(event:"listening",listener:()=>void):this;on(event:"message",listener:(msg:Buffer,rinfo:RemoteInfo)=>void):this;once(event:string,listener:(...args:any[])=>void):this;once(event:"close",listener:()=>void):this;once(event:"connect",listener:()=>void):this;once(event:"error",listener:(err:Error)=>void):this;once(event:"listening",listener:()=>void):this;once(event:"message",listener:(msg:Buffer,rinfo:RemoteInfo)=>void):this;prependListener(event:string,listener:(...args:any[])=>void):this;prependListener(event:"close",listener:()=>void):this;prependListener(event:"connect",listener:()=>void):this;prependListener(event:"error",listener:(err:Error)=>void):this;prependListener(event:"listening",listener:()=>void):this;prependListener(event:"message",listener:(msg:Buffer,rinfo:RemoteInfo)=>void):this;prependOnceListener(event:string,listener:(...args:any[])=>void):this;prependOnceListener(event:"close",listener:()=>void):this;prependOnceListener(event:"connect",listener:()=>void):this;prependOnceListener(event:"error",listener:(err:Error)=>void):this;prependOnceListener(event:"listening",listener:()=>void):this;prependOnceListener(event:"message",listener:(msg:Buffer,rinfo:RemoteInfo)=>void):this;}}
/* NOTE: Do not edit directly! This file is generated using `npm run update-types` in https://github.com/node-red/nr-monaco-build */
declare module 'dgram' {
import { AddressInfo } from 'net';
import * as dns from 'dns';
import EventEmitter = require('events');
interface RemoteInfo {
address: string;
family: 'IPv4' | 'IPv6';
port: number;
size: number;
}
interface BindOptions {
port?: number | undefined;
address?: string | undefined;
exclusive?: boolean | undefined;
fd?: number | undefined;
}
type SocketType = "udp4" | "udp6";
interface SocketOptions {
type: SocketType;
reuseAddr?: boolean | undefined;
/**
* @default false
*/
ipv6Only?: boolean | undefined;
recvBufferSize?: number | undefined;
sendBufferSize?: number | undefined;
lookup?: ((hostname: string, options: dns.LookupOneOptions, callback: (err: NodeJS.ErrnoException | null, address: string, family: number) => void) => void) | undefined;
}
function createSocket(type: SocketType, callback?: (msg: Buffer, rinfo: RemoteInfo) => void): Socket;
function createSocket(options: SocketOptions, callback?: (msg: Buffer, rinfo: RemoteInfo) => void): Socket;
class Socket extends EventEmitter {
addMembership(multicastAddress: string, multicastInterface?: string): void;
address(): AddressInfo;
bind(port?: number, address?: string, callback?: () => void): void;
bind(port?: number, callback?: () => void): void;
bind(callback?: () => void): void;
bind(options: BindOptions, callback?: () => void): void;
close(callback?: () => void): void;
connect(port: number, address?: string, callback?: () => void): void;
connect(port: number, callback: () => void): void;
disconnect(): void;
dropMembership(multicastAddress: string, multicastInterface?: string): void;
getRecvBufferSize(): number;
getSendBufferSize(): number;
ref(): this;
remoteAddress(): AddressInfo;
send(msg: string | Uint8Array | ReadonlyArray<any>, port?: number, address?: string, callback?: (error: Error | null, bytes: number) => void): void;
send(msg: string | Uint8Array | ReadonlyArray<any>, port?: number, callback?: (error: Error | null, bytes: number) => void): void;
send(msg: string | Uint8Array | ReadonlyArray<any>, callback?: (error: Error | null, bytes: number) => void): void;
send(msg: string | Uint8Array, offset: number, length: number, port?: number, address?: string, callback?: (error: Error | null, bytes: number) => void): void;
send(msg: string | Uint8Array, offset: number, length: number, port?: number, callback?: (error: Error | null, bytes: number) => void): void;
send(msg: string | Uint8Array, offset: number, length: number, callback?: (error: Error | null, bytes: number) => void): void;
setBroadcast(flag: boolean): void;
setMulticastInterface(multicastInterface: string): void;
setMulticastLoopback(flag: boolean): void;
setMulticastTTL(ttl: number): void;
setRecvBufferSize(size: number): void;
setSendBufferSize(size: number): void;
setTTL(ttl: number): void;
unref(): this;
/**
* Tells the kernel to join a source-specific multicast channel at the given
* `sourceAddress` and `groupAddress`, using the `multicastInterface` with the
* `IP_ADD_SOURCE_MEMBERSHIP` socket option.
* If the `multicastInterface` argument
* is not specified, the operating system will choose one interface and will add
* membership to it.
* To add membership to every available interface, call
* `socket.addSourceSpecificMembership()` multiple times, once per interface.
*/
addSourceSpecificMembership(sourceAddress: string, groupAddress: string, multicastInterface?: string): void;
/**
* Instructs the kernel to leave a source-specific multicast channel at the given
* `sourceAddress` and `groupAddress` using the `IP_DROP_SOURCE_MEMBERSHIP`
* socket option. This method is automatically called by the kernel when the
* socket is closed or the process terminates, so most apps will never have
* reason to call this.
*
* If `multicastInterface` is not specified, the operating system will attempt to
* drop membership on all valid interfaces.
*/
dropSourceSpecificMembership(sourceAddress: string, groupAddress: string, multicastInterface?: string): void;
/**
* events.EventEmitter
* 1. close
* 2. connect
* 3. error
* 4. listening
* 5. message
*/
addListener(event: string, listener: (...args: any[]) => void): this;
addListener(event: "close", listener: () => void): this;
addListener(event: "connect", listener: () => void): this;
addListener(event: "error", listener: (err: Error) => void): this;
addListener(event: "listening", listener: () => void): this;
addListener(event: "message", listener: (msg: Buffer, rinfo: RemoteInfo) => void): this;
emit(event: string | symbol, ...args: any[]): boolean;
emit(event: "close"): boolean;
emit(event: "connect"): boolean;
emit(event: "error", err: Error): boolean;
emit(event: "listening"): boolean;
emit(event: "message", msg: Buffer, rinfo: RemoteInfo): boolean;
on(event: string, listener: (...args: any[]) => void): this;
on(event: "close", listener: () => void): this;
on(event: "connect", listener: () => void): this;
on(event: "error", listener: (err: Error) => void): this;
on(event: "listening", listener: () => void): this;
on(event: "message", listener: (msg: Buffer, rinfo: RemoteInfo) => void): this;
once(event: string, listener: (...args: any[]) => void): this;
once(event: "close", listener: () => void): this;
once(event: "connect", listener: () => void): this;
once(event: "error", listener: (err: Error) => void): this;
once(event: "listening", listener: () => void): this;
once(event: "message", listener: (msg: Buffer, rinfo: RemoteInfo) => void): this;
prependListener(event: string, listener: (...args: any[]) => void): this;
prependListener(event: "close", listener: () => void): this;
prependListener(event: "connect", listener: () => void): this;
prependListener(event: "error", listener: (err: Error) => void): this;
prependListener(event: "listening", listener: () => void): this;
prependListener(event: "message", listener: (msg: Buffer, rinfo: RemoteInfo) => void): this;
prependOnceListener(event: string, listener: (...args: any[]) => void): this;
prependOnceListener(event: "close", listener: () => void): this;
prependOnceListener(event: "connect", listener: () => void): this;
prependOnceListener(event: "error", listener: (err: Error) => void): this;
prependOnceListener(event: "listening", listener: () => void): this;
prependOnceListener(event: "message", listener: (msg: Buffer, rinfo: RemoteInfo) => void): this;
}
}

File diff suppressed because one or more lines are too long

View File

@ -1 +1,27 @@
declare module'node:domain'{export*from'domain';}declare module'domain'{import EventEmitter=require('node:events');global{namespace NodeJS{interface Domain extends EventEmitter{run<T>(fn:(...args:any[])=>T,...args:any[]):T;add(emitter:EventEmitter|Timer):void;remove(emitter:EventEmitter|Timer):void;bind<T extends Function>(cb:T):T;intercept<T extends Function>(cb:T):T;}}}interface Domain extends NodeJS.Domain{}class Domain extends EventEmitter{members:Array<EventEmitter|NodeJS.Timer>;enter():void;exit():void;}function create():Domain;}
/* NOTE: Do not edit directly! This file is generated using `npm run update-types` in https://github.com/node-red/nr-monaco-build */
declare module 'domain' {
import EventEmitter = require('events');
global {
namespace NodeJS {
interface Domain extends EventEmitter {
run<T>(fn: (...args: any[]) => T, ...args: any[]): T;
add(emitter: EventEmitter | Timer): void;
remove(emitter: EventEmitter | Timer): void;
bind<T extends Function>(cb: T): T;
intercept<T extends Function>(cb: T): T;
}
}
}
interface Domain extends NodeJS.Domain {}
class Domain extends EventEmitter {
members: Array<EventEmitter | NodeJS.Timer>;
enter(): void;
exit(): void;
}
function create(): Domain;
}

View File

@ -1 +1,81 @@
declare module'node:events'{import EventEmitter=require('events');export=EventEmitter;}declare module'events'{interface EventEmitterOptions{captureRejections?:boolean;}interface NodeEventTarget{once(event:string|symbol,listener:(...args:any[])=>void):this;}interface DOMEventTarget{addEventListener(event:string,listener:(...args:any[])=>void,opts?:{once:boolean}):any;}interface EventEmitter extends NodeJS.EventEmitter{}class EventEmitter{constructor(options?:EventEmitterOptions);static once(emitter:NodeEventTarget,event:string|symbol):Promise<any[]>;static once(emitter:DOMEventTarget,event:string):Promise<any[]>;static on(emitter:NodeJS.EventEmitter,event:string):AsyncIterableIterator<any>;static listenerCount(emitter:NodeJS.EventEmitter,event:string|symbol):number;static readonly errorMonitor:unique symbol;static readonly captureRejectionSymbol:unique symbol;static captureRejections:boolean;static defaultMaxListeners:number;}import internal=require('events');namespace EventEmitter{export{internal as EventEmitter};}global{namespace NodeJS{interface EventEmitter{addListener(event:string|symbol,listener:(...args:any[])=>void):this;on(event:string|symbol,listener:(...args:any[])=>void):this;once(event:string|symbol,listener:(...args:any[])=>void):this;removeListener(event:string|symbol,listener:(...args:any[])=>void):this;off(event:string|symbol,listener:(...args:any[])=>void):this;removeAllListeners(event?:string|symbol):this;setMaxListeners(n:number):this;getMaxListeners():number;listeners(event:string|symbol):Function[];rawListeners(event:string|symbol):Function[];emit(event:string|symbol,...args:any[]):boolean;listenerCount(event:string|symbol):number;prependListener(event:string|symbol,listener:(...args:any[])=>void):this;prependOnceListener(event:string|symbol,listener:(...args:any[])=>void):this;eventNames():Array<string|symbol>;}}}export=EventEmitter;}
/* NOTE: Do not edit directly! This file is generated using `npm run update-types` in https://github.com/node-red/nr-monaco-build */
declare module 'events' {
interface EventEmitterOptions {
/**
* Enables automatic capturing of promise rejection.
*/
captureRejections?: boolean | undefined;
}
interface NodeEventTarget {
once(event: string | symbol, listener: (...args: any[]) => void): this;
}
interface DOMEventTarget {
addEventListener(event: string, listener: (...args: any[]) => void, opts?: { once: boolean }): any;
}
interface EventEmitter extends NodeJS.EventEmitter {}
class EventEmitter {
constructor(options?: EventEmitterOptions);
static once(emitter: NodeEventTarget, event: string | symbol): Promise<any[]>;
static once(emitter: DOMEventTarget, event: string): Promise<any[]>;
static on(emitter: NodeJS.EventEmitter, event: string): AsyncIterableIterator<any>;
/** @deprecated since v4.0.0 */
static listenerCount(emitter: NodeJS.EventEmitter, event: string | symbol): number;
/**
* This symbol shall be used to install a listener for only monitoring `'error'`
* events. Listeners installed using this symbol are called before the regular
* `'error'` listeners are called.
*
* Installing a listener using this symbol does not change the behavior once an
* `'error'` event is emitted, therefore the process will still crash if no
* regular `'error'` listener is installed.
*/
static readonly errorMonitor: unique symbol;
static readonly captureRejectionSymbol: unique symbol;
/**
* Sets or gets the default captureRejection value for all emitters.
*/
// TODO: These should be described using static getter/setter pairs:
static captureRejections: boolean;
static defaultMaxListeners: number;
}
import internal = require('events');
namespace EventEmitter {
// Should just be `export { EventEmitter }`, but that doesn't work in TypeScript 3.4
export { internal as EventEmitter };
}
global {
namespace NodeJS {
interface EventEmitter {
addListener(event: string | symbol, listener: (...args: any[]) => void): this;
on(event: string | symbol, listener: (...args: any[]) => void): this;
once(event: string | symbol, listener: (...args: any[]) => void): this;
removeListener(event: string | symbol, listener: (...args: any[]) => void): this;
off(event: string | symbol, listener: (...args: any[]) => void): this;
removeAllListeners(event?: string | symbol): this;
setMaxListeners(n: number): this;
getMaxListeners(): number;
listeners(event: string | symbol): Function[];
rawListeners(event: string | symbol): Function[];
emit(event: string | symbol, ...args: any[]): boolean;
listenerCount(event: string | symbol): number;
// Added in Node 6...
prependListener(event: string | symbol, listener: (...args: any[]) => void): this;
prependOnceListener(event: string | symbol, listener: (...args: any[]) => void): this;
eventNames(): Array<string | symbol>;
}
}
}
export = EventEmitter;
}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,568 @@
/* NOTE: Do not edit directly! This file is generated using `npm run update-types` in https://github.com/node-red/nr-monaco-build */
declare module 'fs/promises' {
import {
Stats,
BigIntStats,
StatOptions,
WriteVResult,
ReadVResult,
PathLike,
RmDirOptions,
RmOptions,
MakeDirectoryOptions,
Dirent,
OpenDirOptions,
Dir,
BaseEncodingOptions,
BufferEncodingOption,
OpenMode,
Mode,
} from 'fs';
interface FileHandle {
/**
* Gets the file descriptor for this file handle.
*/
readonly fd: number;
/**
* Asynchronously append data to a file, creating the file if it does not exist. The underlying file will _not_ be closed automatically.
* The `FileHandle` must have been opened for appending.
* @param data The data to write. If something other than a `Buffer` or `Uint8Array` is provided, the value is coerced to a string.
* @param options Either the encoding for the file, or an object optionally specifying the encoding, file mode, and flag.
* If `encoding` is not supplied, the default of `'utf8'` is used.
* If `mode` is not supplied, the default of `0o666` is used.
* If `mode` is a string, it is parsed as an octal integer.
* If `flag` is not supplied, the default of `'a'` is used.
*/
appendFile(data: string | Uint8Array, options?: BaseEncodingOptions & { mode?: Mode | undefined, flag?: OpenMode | undefined } | BufferEncoding | null): Promise<void>;
/**
* Asynchronous fchown(2) - Change ownership of a file.
*/
chown(uid: number, gid: number): Promise<void>;
/**
* Asynchronous fchmod(2) - Change permissions of a file.
* @param mode A file mode. If a string is passed, it is parsed as an octal integer.
*/
chmod(mode: Mode): Promise<void>;
/**
* Asynchronous fdatasync(2) - synchronize a file's in-core state with storage device.
*/
datasync(): Promise<void>;
/**
* Asynchronous fsync(2) - synchronize a file's in-core state with the underlying storage device.
*/
sync(): Promise<void>;
/**
* Asynchronously reads data from the file.
* The `FileHandle` must have been opened for reading.
* @param buffer The buffer that the data will be written to.
* @param offset The offset in the buffer at which to start writing.
* @param length The number of bytes to read.
* @param position The offset from the beginning of the file from which data should be read. If `null`, data will be read from the current position.
*/
read<TBuffer extends Uint8Array>(buffer: TBuffer, offset?: number | null, length?: number | null, position?: number | null): Promise<{ bytesRead: number, buffer: TBuffer }>;
/**
* Asynchronously reads the entire contents of a file. The underlying file will _not_ be closed automatically.
* The `FileHandle` must have been opened for reading.
* @param options An object that may contain an optional flag.
* If a flag is not provided, it defaults to `'r'`.
*/
readFile(options?: { encoding?: null | undefined, flag?: OpenMode | undefined } | null): Promise<Buffer>;
/**
* Asynchronously reads the entire contents of a file. The underlying file will _not_ be closed automatically.
* The `FileHandle` must have been opened for reading.
* @param options An object that may contain an optional flag.
* If a flag is not provided, it defaults to `'r'`.
*/
readFile(options: { encoding: BufferEncoding, flag?: OpenMode | undefined } | BufferEncoding): Promise<string>;
/**
* Asynchronously reads the entire contents of a file. The underlying file will _not_ be closed automatically.
* The `FileHandle` must have been opened for reading.
* @param options An object that may contain an optional flag.
* If a flag is not provided, it defaults to `'r'`.
*/
readFile(options?: BaseEncodingOptions & { flag?: OpenMode | undefined } | BufferEncoding | null): Promise<string | Buffer>;
/**
* Asynchronous fstat(2) - Get file status.
*/
stat(opts?: StatOptions & { bigint?: false | undefined }): Promise<Stats>;
stat(opts: StatOptions & { bigint: true }): Promise<BigIntStats>;
stat(opts?: StatOptions): Promise<Stats | BigIntStats>;
/**
* Asynchronous ftruncate(2) - Truncate a file to a specified length.
* @param len If not specified, defaults to `0`.
*/
truncate(len?: number): Promise<void>;
/**
* Asynchronously change file timestamps of the file.
* @param atime The last access time. If a string is provided, it will be coerced to number.
* @param mtime The last modified time. If a string is provided, it will be coerced to number.
*/
utimes(atime: string | number | Date, mtime: string | number | Date): Promise<void>;
/**
* Asynchronously writes `buffer` to the file.
* The `FileHandle` must have been opened for writing.
* @param buffer The buffer that the data will be written to.
* @param offset The part of the buffer to be written. If not supplied, defaults to `0`.
* @param length The number of bytes to write. If not supplied, defaults to `buffer.length - offset`.
* @param position The offset from the beginning of the file where this data should be written. If not supplied, defaults to the current position.
*/
write<TBuffer extends Uint8Array>(buffer: TBuffer, offset?: number | null, length?: number | null, position?: number | null): Promise<{ bytesWritten: number, buffer: TBuffer }>;
/**
* Asynchronously writes `string` to the file.
* The `FileHandle` must have been opened for writing.
* It is unsafe to call `write()` multiple times on the same file without waiting for the `Promise`
* to be resolved (or rejected). For this scenario, `fs.createWriteStream` is strongly recommended.
* @param string A string to write.
* @param position The offset from the beginning of the file where this data should be written. If not supplied, defaults to the current position.
* @param encoding The expected string encoding.
*/
write(data: string | Uint8Array, position?: number | null, encoding?: BufferEncoding | null): Promise<{ bytesWritten: number, buffer: string }>;
/**
* Asynchronously writes data to a file, replacing the file if it already exists. The underlying file will _not_ be closed automatically.
* The `FileHandle` must have been opened for writing.
* It is unsafe to call `writeFile()` multiple times on the same file without waiting for the `Promise` to be resolved (or rejected).
* @param data The data to write. If something other than a `Buffer` or `Uint8Array` is provided, the value is coerced to a string.
* @param options Either the encoding for the file, or an object optionally specifying the encoding, file mode, and flag.
* If `encoding` is not supplied, the default of `'utf8'` is used.
* If `mode` is not supplied, the default of `0o666` is used.
* If `mode` is a string, it is parsed as an octal integer.
* If `flag` is not supplied, the default of `'w'` is used.
*/
writeFile(data: string | Uint8Array, options?: BaseEncodingOptions & { mode?: Mode | undefined, flag?: OpenMode | undefined } | BufferEncoding | null): Promise<void>;
/**
* See `fs.writev` promisified version.
*/
writev(buffers: ReadonlyArray<NodeJS.ArrayBufferView>, position?: number): Promise<WriteVResult>;
/**
* See `fs.readv` promisified version.
*/
readv(buffers: ReadonlyArray<NodeJS.ArrayBufferView>, position?: number): Promise<ReadVResult>;
/**
* Asynchronous close(2) - close a `FileHandle`.
*/
close(): Promise<void>;
}
/**
* Asynchronously tests a user's permissions for the file specified by path.
* @param path A path to a file or directory. If a URL is provided, it must use the `file:` protocol.
* URL support is _experimental_.
*/
function access(path: PathLike, mode?: number): Promise<void>;
/**
* Asynchronously copies `src` to `dest`. By default, `dest` is overwritten if it already exists.
* Node.js makes no guarantees about the atomicity of the copy operation.
* If an error occurs after the destination file has been opened for writing, Node.js will attempt
* to remove the destination.
* @param src A path to the source file.
* @param dest A path to the destination file.
* @param flags An optional integer that specifies the behavior of the copy operation. The only
* supported flag is `fs.constants.COPYFILE_EXCL`, which causes the copy operation to fail if
* `dest` already exists.
*/
function copyFile(src: PathLike, dest: PathLike, flags?: number): Promise<void>;
/**
* Asynchronous open(2) - open and possibly create a file.
* @param path A path to a file. If a URL is provided, it must use the `file:` protocol.
* @param mode A file mode. If a string is passed, it is parsed as an octal integer. If not
* supplied, defaults to `0o666`.
*/
function open(path: PathLike, flags: string | number, mode?: Mode): Promise<FileHandle>;
/**
* Asynchronously reads data from the file referenced by the supplied `FileHandle`.
* @param handle A `FileHandle`.
* @param buffer The buffer that the data will be written to.
* @param offset The offset in the buffer at which to start writing.
* @param length The number of bytes to read.
* @param position The offset from the beginning of the file from which data should be read. If
* `null`, data will be read from the current position.
*/
function read<TBuffer extends Uint8Array>(
handle: FileHandle,
buffer: TBuffer,
offset?: number | null,
length?: number | null,
position?: number | null,
): Promise<{ bytesRead: number, buffer: TBuffer }>;
/**
* Asynchronously writes `buffer` to the file referenced by the supplied `FileHandle`.
* It is unsafe to call `fsPromises.write()` multiple times on the same file without waiting for the `Promise`
* to be resolved (or rejected). For this scenario, `fs.createWriteStream` is strongly recommended.
* @param handle A `FileHandle`.
* @param buffer The buffer that the data will be written to.
* @param offset The part of the buffer to be written. If not supplied, defaults to `0`.
* @param length The number of bytes to write. If not supplied, defaults to `buffer.length - offset`.
* @param position The offset from the beginning of the file where this data should be written. If not supplied, defaults to the current position.
*/
function write<TBuffer extends Uint8Array>(
handle: FileHandle,
buffer: TBuffer,
offset?: number | null,
length?: number | null, position?: number | null): Promise<{ bytesWritten: number, buffer: TBuffer }>;
/**
* Asynchronously writes `string` to the file referenced by the supplied `FileHandle`.
* It is unsafe to call `fsPromises.write()` multiple times on the same file without waiting for the `Promise`
* to be resolved (or rejected). For this scenario, `fs.createWriteStream` is strongly recommended.
* @param handle A `FileHandle`.
* @param string A string to write.
* @param position The offset from the beginning of the file where this data should be written. If not supplied, defaults to the current position.
* @param encoding The expected string encoding.
*/
function write(handle: FileHandle, string: string, position?: number | null, encoding?: BufferEncoding | null): Promise<{ bytesWritten: number, buffer: string }>;
/**
* Asynchronous rename(2) - Change the name or location of a file or directory.
* @param oldPath A path to a file. If a URL is provided, it must use the `file:` protocol.
* URL support is _experimental_.
* @param newPath A path to a file. If a URL is provided, it must use the `file:` protocol.
* URL support is _experimental_.
*/
function rename(oldPath: PathLike, newPath: PathLike): Promise<void>;
/**
* Asynchronous truncate(2) - Truncate a file to a specified length.
* @param path A path to a file. If a URL is provided, it must use the `file:` protocol.
* @param len If not specified, defaults to `0`.
*/
function truncate(path: PathLike, len?: number): Promise<void>;
/**
* Asynchronous ftruncate(2) - Truncate a file to a specified length.
* @param handle A `FileHandle`.
* @param len If not specified, defaults to `0`.
*/
function ftruncate(handle: FileHandle, len?: number): Promise<void>;
/**
* Asynchronous rmdir(2) - delete a directory.
* @param path A path to a file. If a URL is provided, it must use the `file:` protocol.
*/
function rmdir(path: PathLike, options?: RmDirOptions): Promise<void>;
/**
* Asynchronously removes files and directories (modeled on the standard POSIX `rm` utility).
*/
function rm(path: PathLike, options?: RmOptions): Promise<void>;
/**
* Asynchronous fdatasync(2) - synchronize a file's in-core state with storage device.
* @param handle A `FileHandle`.
*/
function fdatasync(handle: FileHandle): Promise<void>;
/**
* Asynchronous fsync(2) - synchronize a file's in-core state with the underlying storage device.
* @param handle A `FileHandle`.
*/
function fsync(handle: FileHandle): Promise<void>;
/**
* Asynchronous mkdir(2) - create a directory.
* @param path A path to a file. If a URL is provided, it must use the `file:` protocol.
* @param options Either the file mode, or an object optionally specifying the file mode and whether parent folders
* should be created. If a string is passed, it is parsed as an octal integer. If not specified, defaults to `0o777`.
*/
function mkdir(path: PathLike, options: MakeDirectoryOptions & { recursive: true; }): Promise<string | undefined>;
/**
* Asynchronous mkdir(2) - create a directory.
* @param path A path to a file. If a URL is provided, it must use the `file:` protocol.
* @param options Either the file mode, or an object optionally specifying the file mode and whether parent folders
* should be created. If a string is passed, it is parsed as an octal integer. If not specified, defaults to `0o777`.
*/
function mkdir(path: PathLike, options?: Mode | (MakeDirectoryOptions & { recursive?: false | undefined; }) | null): Promise<void>;
/**
* Asynchronous mkdir(2) - create a directory.
* @param path A path to a file. If a URL is provided, it must use the `file:` protocol.
* @param options Either the file mode, or an object optionally specifying the file mode and whether parent folders
* should be created. If a string is passed, it is parsed as an octal integer. If not specified, defaults to `0o777`.
*/
function mkdir(path: PathLike, options?: Mode | MakeDirectoryOptions | null): Promise<string | undefined>;
/**
* Asynchronous readdir(3) - read a directory.
* @param path A path to a file. If a URL is provided, it must use the `file:` protocol.
* @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used.
*/
function readdir(path: PathLike, options?: BaseEncodingOptions & { withFileTypes?: false | undefined } | BufferEncoding | null): Promise<string[]>;
/**
* Asynchronous readdir(3) - read a directory.
* @param path A path to a file. If a URL is provided, it must use the `file:` protocol.
* @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used.
*/
function readdir(path: PathLike, options: { encoding: "buffer"; withFileTypes?: false | undefined } | "buffer"): Promise<Buffer[]>;
/**
* Asynchronous readdir(3) - read a directory.
* @param path A path to a file. If a URL is provided, it must use the `file:` protocol.
* @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used.
*/
function readdir(path: PathLike, options?: BaseEncodingOptions & { withFileTypes?: false | undefined } | BufferEncoding | null): Promise<string[] | Buffer[]>;
/**
* Asynchronous readdir(3) - read a directory.
* @param path A path to a file. If a URL is provided, it must use the `file:` protocol.
* @param options If called with `withFileTypes: true` the result data will be an array of Dirent.
*/
function readdir(path: PathLike, options: BaseEncodingOptions & { withFileTypes: true }): Promise<Dirent[]>;
/**
* Asynchronous readlink(2) - read value of a symbolic link.
* @param path A path to a file. If a URL is provided, it must use the `file:` protocol.
* @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used.
*/
function readlink(path: PathLike, options?: BaseEncodingOptions | BufferEncoding | null): Promise<string>;
/**
* Asynchronous readlink(2) - read value of a symbolic link.
* @param path A path to a file. If a URL is provided, it must use the `file:` protocol.
* @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used.
*/
function readlink(path: PathLike, options: BufferEncodingOption): Promise<Buffer>;
/**
* Asynchronous readlink(2) - read value of a symbolic link.
* @param path A path to a file. If a URL is provided, it must use the `file:` protocol.
* @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used.
*/
function readlink(path: PathLike, options?: BaseEncodingOptions | string | null): Promise<string | Buffer>;
/**
* Asynchronous symlink(2) - Create a new symbolic link to an existing file.
* @param target A path to an existing file. If a URL is provided, it must use the `file:` protocol.
* @param path A path to the new symlink. If a URL is provided, it must use the `file:` protocol.
* @param type May be set to `'dir'`, `'file'`, or `'junction'` (default is `'file'`) and is only available on Windows (ignored on other platforms).
* When using `'junction'`, the `target` argument will automatically be normalized to an absolute path.
*/
function symlink(target: PathLike, path: PathLike, type?: string | null): Promise<void>;
/**
* Asynchronous lstat(2) - Get file status. Does not dereference symbolic links.
* @param path A path to a file. If a URL is provided, it must use the `file:` protocol.
*/
function lstat(path: PathLike, opts?: StatOptions & { bigint?: false | undefined }): Promise<Stats>;
function lstat(path: PathLike, opts: StatOptions & { bigint: true }): Promise<BigIntStats>;
function lstat(path: PathLike, opts?: StatOptions): Promise<Stats | BigIntStats>;
/**
* Asynchronous stat(2) - Get file status.
* @param path A path to a file. If a URL is provided, it must use the `file:` protocol.
*/
function stat(path: PathLike, opts?: StatOptions & { bigint?: false | undefined }): Promise<Stats>;
function stat(path: PathLike, opts: StatOptions & { bigint: true }): Promise<BigIntStats>;
function stat(path: PathLike, opts?: StatOptions): Promise<Stats | BigIntStats>;
/**
* Asynchronous link(2) - Create a new link (also known as a hard link) to an existing file.
* @param existingPath A path to a file. If a URL is provided, it must use the `file:` protocol.
* @param newPath A path to a file. If a URL is provided, it must use the `file:` protocol.
*/
function link(existingPath: PathLike, newPath: PathLike): Promise<void>;
/**
* Asynchronous unlink(2) - delete a name and possibly the file it refers to.
* @param path A path to a file. If a URL is provided, it must use the `file:` protocol.
*/
function unlink(path: PathLike): Promise<void>;
/**
* Asynchronous fchmod(2) - Change permissions of a file.
* @param handle A `FileHandle`.
* @param mode A file mode. If a string is passed, it is parsed as an octal integer.
*/
function fchmod(handle: FileHandle, mode: Mode): Promise<void>;
/**
* Asynchronous chmod(2) - Change permissions of a file.
* @param path A path to a file. If a URL is provided, it must use the `file:` protocol.
* @param mode A file mode. If a string is passed, it is parsed as an octal integer.
*/
function chmod(path: PathLike, mode: Mode): Promise<void>;
/**
* Asynchronous lchmod(2) - Change permissions of a file. Does not dereference symbolic links.
* @param path A path to a file. If a URL is provided, it must use the `file:` protocol.
* @param mode A file mode. If a string is passed, it is parsed as an octal integer.
*/
function lchmod(path: PathLike, mode: Mode): Promise<void>;
/**
* Asynchronous lchown(2) - Change ownership of a file. Does not dereference symbolic links.
* @param path A path to a file. If a URL is provided, it must use the `file:` protocol.
*/
function lchown(path: PathLike, uid: number, gid: number): Promise<void>;
/**
* Changes the access and modification times of a file in the same way as `fsPromises.utimes()`,
* with the difference that if the path refers to a symbolic link, then the link is not
* dereferenced: instead, the timestamps of the symbolic link itself are changed.
* @param path A path to a file. If a URL is provided, it must use the `file:` protocol.
* @param atime The last access time. If a string is provided, it will be coerced to number.
* @param mtime The last modified time. If a string is provided, it will be coerced to number.
*/
function lutimes(path: PathLike, atime: string | number | Date, mtime: string | number | Date): Promise<void>;
/**
* Asynchronous fchown(2) - Change ownership of a file.
* @param handle A `FileHandle`.
*/
function fchown(handle: FileHandle, uid: number, gid: number): Promise<void>;
/**
* Asynchronous chown(2) - Change ownership of a file.
* @param path A path to a file. If a URL is provided, it must use the `file:` protocol.
*/
function chown(path: PathLike, uid: number, gid: number): Promise<void>;
/**
* Asynchronously change file timestamps of the file referenced by the supplied path.
* @param path A path to a file. If a URL is provided, it must use the `file:` protocol.
* @param atime The last access time. If a string is provided, it will be coerced to number.
* @param mtime The last modified time. If a string is provided, it will be coerced to number.
*/
function utimes(path: PathLike, atime: string | number | Date, mtime: string | number | Date): Promise<void>;
/**
* Asynchronously change file timestamps of the file referenced by the supplied `FileHandle`.
* @param handle A `FileHandle`.
* @param atime The last access time. If a string is provided, it will be coerced to number.
* @param mtime The last modified time. If a string is provided, it will be coerced to number.
*/
function futimes(handle: FileHandle, atime: string | number | Date, mtime: string | number | Date): Promise<void>;
/**
* Asynchronous realpath(3) - return the canonicalized absolute pathname.
* @param path A path to a file. If a URL is provided, it must use the `file:` protocol.
* @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used.
*/
function realpath(path: PathLike, options?: BaseEncodingOptions | BufferEncoding | null): Promise<string>;
/**
* Asynchronous realpath(3) - return the canonicalized absolute pathname.
* @param path A path to a file. If a URL is provided, it must use the `file:` protocol.
* @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used.
*/
function realpath(path: PathLike, options: BufferEncodingOption): Promise<Buffer>;
/**
* Asynchronous realpath(3) - return the canonicalized absolute pathname.
* @param path A path to a file. If a URL is provided, it must use the `file:` protocol.
* @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used.
*/
function realpath(path: PathLike, options?: BaseEncodingOptions | BufferEncoding | null): Promise<string | Buffer>;
/**
* Asynchronously creates a unique temporary directory.
* Generates six random characters to be appended behind a required `prefix` to create a unique temporary directory.
* @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used.
*/
function mkdtemp(prefix: string, options?: BaseEncodingOptions | BufferEncoding | null): Promise<string>;
/**
* Asynchronously creates a unique temporary directory.
* Generates six random characters to be appended behind a required `prefix` to create a unique temporary directory.
* @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used.
*/
function mkdtemp(prefix: string, options: BufferEncodingOption): Promise<Buffer>;
/**
* Asynchronously creates a unique temporary directory.
* Generates six random characters to be appended behind a required `prefix` to create a unique temporary directory.
* @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used.
*/
function mkdtemp(prefix: string, options?: BaseEncodingOptions | BufferEncoding | null): Promise<string | Buffer>;
/**
* Asynchronously writes data to a file, replacing the file if it already exists.
* It is unsafe to call `fsPromises.writeFile()` multiple times on the same file without waiting for the `Promise` to be resolved (or rejected).
* @param path A path to a file. If a URL is provided, it must use the `file:` protocol.
* URL support is _experimental_.
* If a `FileHandle` is provided, the underlying file will _not_ be closed automatically.
* @param data The data to write. If something other than a `Buffer` or `Uint8Array` is provided, the value is coerced to a string.
* @param options Either the encoding for the file, or an object optionally specifying the encoding, file mode, and flag.
* If `encoding` is not supplied, the default of `'utf8'` is used.
* If `mode` is not supplied, the default of `0o666` is used.
* If `mode` is a string, it is parsed as an octal integer.
* If `flag` is not supplied, the default of `'w'` is used.
*/
function writeFile(
path: PathLike | FileHandle,
data: string | Uint8Array,
options?: BaseEncodingOptions & { mode?: Mode | undefined, flag?: OpenMode | undefined } | BufferEncoding | null
): Promise<void>;
/**
* Asynchronously append data to a file, creating the file if it does not exist.
* @param file A path to a file. If a URL is provided, it must use the `file:` protocol.
* URL support is _experimental_.
* If a `FileHandle` is provided, the underlying file will _not_ be closed automatically.
* @param data The data to write. If something other than a `Buffer` or `Uint8Array` is provided, the value is coerced to a string.
* @param options Either the encoding for the file, or an object optionally specifying the encoding, file mode, and flag.
* If `encoding` is not supplied, the default of `'utf8'` is used.
* If `mode` is not supplied, the default of `0o666` is used.
* If `mode` is a string, it is parsed as an octal integer.
* If `flag` is not supplied, the default of `'a'` is used.
*/
function appendFile(
path: PathLike | FileHandle,
data: string | Uint8Array,
options?: BaseEncodingOptions & { mode?: Mode | undefined, flag?: OpenMode | undefined } | BufferEncoding | null
): Promise<void>;
/**
* Asynchronously reads the entire contents of a file.
* @param path A path to a file. If a URL is provided, it must use the `file:` protocol.
* If a `FileHandle` is provided, the underlying file will _not_ be closed automatically.
* @param options An object that may contain an optional flag.
* If a flag is not provided, it defaults to `'r'`.
*/
function readFile(path: PathLike | FileHandle, options?: { encoding?: null | undefined, flag?: OpenMode | undefined } | null): Promise<Buffer>;
/**
* Asynchronously reads the entire contents of a file.
* @param path A path to a file. If a URL is provided, it must use the `file:` protocol.
* If a `FileHandle` is provided, the underlying file will _not_ be closed automatically.
* @param options An object that may contain an optional flag.
* If a flag is not provided, it defaults to `'r'`.
*/
function readFile(path: PathLike | FileHandle, options: { encoding: BufferEncoding, flag?: OpenMode | undefined } | BufferEncoding): Promise<string>;
/**
* Asynchronously reads the entire contents of a file.
* @param path A path to a file. If a URL is provided, it must use the `file:` protocol.
* If a `FileHandle` is provided, the underlying file will _not_ be closed automatically.
* @param options An object that may contain an optional flag.
* If a flag is not provided, it defaults to `'r'`.
*/
function readFile(path: PathLike | FileHandle, options?: BaseEncodingOptions & { flag?: OpenMode | undefined } | BufferEncoding | null): Promise<string | Buffer>;
function opendir(path: string, options?: OpenDirOptions): Promise<Dir>;
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,961 @@
/* NOTE: Do not edit directly! This file is generated using `npm run update-types` in https://github.com/node-red/nr-monaco-build */
declare module 'http2' {
import EventEmitter = require('events');
import * as fs from 'fs';
import * as net from 'net';
import * as stream from 'stream';
import * as tls from 'tls';
import * as url from 'url';
import {
IncomingHttpHeaders as Http1IncomingHttpHeaders,
OutgoingHttpHeaders,
IncomingMessage,
ServerResponse,
} from 'http';
export { OutgoingHttpHeaders } from 'http';
export interface IncomingHttpStatusHeader {
":status"?: number | undefined;
}
export interface IncomingHttpHeaders extends Http1IncomingHttpHeaders {
":path"?: string | undefined;
":method"?: string | undefined;
":authority"?: string | undefined;
":scheme"?: string | undefined;
}
// Http2Stream
export interface StreamPriorityOptions {
exclusive?: boolean | undefined;
parent?: number | undefined;
weight?: number | undefined;
silent?: boolean | undefined;
}
export interface StreamState {
localWindowSize?: number | undefined;
state?: number | undefined;
localClose?: number | undefined;
remoteClose?: number | undefined;
sumDependencyWeight?: number | undefined;
weight?: number | undefined;
}
export interface ServerStreamResponseOptions {
endStream?: boolean | undefined;
waitForTrailers?: boolean | undefined;
}
export interface StatOptions {
offset: number;
length: number;
}
export interface ServerStreamFileResponseOptions {
statCheck?(stats: fs.Stats, headers: OutgoingHttpHeaders, statOptions: StatOptions): void | boolean;
waitForTrailers?: boolean | undefined;
offset?: number | undefined;
length?: number | undefined;
}
export interface ServerStreamFileResponseOptionsWithError extends ServerStreamFileResponseOptions {
onError?(err: NodeJS.ErrnoException): void;
}
export interface Http2Stream extends stream.Duplex {
readonly aborted: boolean;
readonly bufferSize: number;
readonly closed: boolean;
readonly destroyed: boolean;
/**
* Set the true if the END_STREAM flag was set in the request or response HEADERS frame received,
* indicating that no additional data should be received and the readable side of the Http2Stream will be closed.
*/
readonly endAfterHeaders: boolean;
readonly id?: number | undefined;
readonly pending: boolean;
readonly rstCode: number;
readonly sentHeaders: OutgoingHttpHeaders;
readonly sentInfoHeaders?: OutgoingHttpHeaders[] | undefined;
readonly sentTrailers?: OutgoingHttpHeaders | undefined;
readonly session: Http2Session;
readonly state: StreamState;
close(code?: number, callback?: () => void): void;
priority(options: StreamPriorityOptions): void;
setTimeout(msecs: number, callback?: () => void): void;
sendTrailers(headers: OutgoingHttpHeaders): void;
addListener(event: "aborted", listener: () => void): this;
addListener(event: "close", listener: () => void): this;
addListener(event: "data", listener: (chunk: Buffer | string) => void): this;
addListener(event: "drain", listener: () => void): this;
addListener(event: "end", listener: () => void): this;
addListener(event: "error", listener: (err: Error) => void): this;
addListener(event: "finish", listener: () => void): this;
addListener(event: "frameError", listener: (frameType: number, errorCode: number) => void): this;
addListener(event: "pipe", listener: (src: stream.Readable) => void): this;
addListener(event: "unpipe", listener: (src: stream.Readable) => void): this;
addListener(event: "streamClosed", listener: (code: number) => void): this;
addListener(event: "timeout", listener: () => void): this;
addListener(event: "trailers", listener: (trailers: IncomingHttpHeaders, flags: number) => void): this;
addListener(event: "wantTrailers", listener: () => void): this;
addListener(event: string | symbol, listener: (...args: any[]) => void): this;
emit(event: "aborted"): boolean;
emit(event: "close"): boolean;
emit(event: "data", chunk: Buffer | string): boolean;
emit(event: "drain"): boolean;
emit(event: "end"): boolean;
emit(event: "error", err: Error): boolean;
emit(event: "finish"): boolean;
emit(event: "frameError", frameType: number, errorCode: number): boolean;
emit(event: "pipe", src: stream.Readable): boolean;
emit(event: "unpipe", src: stream.Readable): boolean;
emit(event: "streamClosed", code: number): boolean;
emit(event: "timeout"): boolean;
emit(event: "trailers", trailers: IncomingHttpHeaders, flags: number): boolean;
emit(event: "wantTrailers"): boolean;
emit(event: string | symbol, ...args: any[]): boolean;
on(event: "aborted", listener: () => void): this;
on(event: "close", listener: () => void): this;
on(event: "data", listener: (chunk: Buffer | string) => void): this;
on(event: "drain", listener: () => void): this;
on(event: "end", listener: () => void): this;
on(event: "error", listener: (err: Error) => void): this;
on(event: "finish", listener: () => void): this;
on(event: "frameError", listener: (frameType: number, errorCode: number) => void): this;
on(event: "pipe", listener: (src: stream.Readable) => void): this;
on(event: "unpipe", listener: (src: stream.Readable) => void): this;
on(event: "streamClosed", listener: (code: number) => void): this;
on(event: "timeout", listener: () => void): this;
on(event: "trailers", listener: (trailers: IncomingHttpHeaders, flags: number) => void): this;
on(event: "wantTrailers", listener: () => void): this;
on(event: string | symbol, listener: (...args: any[]) => void): this;
once(event: "aborted", listener: () => void): this;
once(event: "close", listener: () => void): this;
once(event: "data", listener: (chunk: Buffer | string) => void): this;
once(event: "drain", listener: () => void): this;
once(event: "end", listener: () => void): this;
once(event: "error", listener: (err: Error) => void): this;
once(event: "finish", listener: () => void): this;
once(event: "frameError", listener: (frameType: number, errorCode: number) => void): this;
once(event: "pipe", listener: (src: stream.Readable) => void): this;
once(event: "unpipe", listener: (src: stream.Readable) => void): this;
once(event: "streamClosed", listener: (code: number) => void): this;
once(event: "timeout", listener: () => void): this;
once(event: "trailers", listener: (trailers: IncomingHttpHeaders, flags: number) => void): this;
once(event: "wantTrailers", listener: () => void): this;
once(event: string | symbol, listener: (...args: any[]) => void): this;
prependListener(event: "aborted", listener: () => void): this;
prependListener(event: "close", listener: () => void): this;
prependListener(event: "data", listener: (chunk: Buffer | string) => void): this;
prependListener(event: "drain", listener: () => void): this;
prependListener(event: "end", listener: () => void): this;
prependListener(event: "error", listener: (err: Error) => void): this;
prependListener(event: "finish", listener: () => void): this;
prependListener(event: "frameError", listener: (frameType: number, errorCode: number) => void): this;
prependListener(event: "pipe", listener: (src: stream.Readable) => void): this;
prependListener(event: "unpipe", listener: (src: stream.Readable) => void): this;
prependListener(event: "streamClosed", listener: (code: number) => void): this;
prependListener(event: "timeout", listener: () => void): this;
prependListener(event: "trailers", listener: (trailers: IncomingHttpHeaders, flags: number) => void): this;
prependListener(event: "wantTrailers", listener: () => void): this;
prependListener(event: string | symbol, listener: (...args: any[]) => void): this;
prependOnceListener(event: "aborted", listener: () => void): this;
prependOnceListener(event: "close", listener: () => void): this;
prependOnceListener(event: "data", listener: (chunk: Buffer | string) => void): this;
prependOnceListener(event: "drain", listener: () => void): this;
prependOnceListener(event: "end", listener: () => void): this;
prependOnceListener(event: "error", listener: (err: Error) => void): this;
prependOnceListener(event: "finish", listener: () => void): this;
prependOnceListener(event: "frameError", listener: (frameType: number, errorCode: number) => void): this;
prependOnceListener(event: "pipe", listener: (src: stream.Readable) => void): this;
prependOnceListener(event: "unpipe", listener: (src: stream.Readable) => void): this;
prependOnceListener(event: "streamClosed", listener: (code: number) => void): this;
prependOnceListener(event: "timeout", listener: () => void): this;
prependOnceListener(event: "trailers", listener: (trailers: IncomingHttpHeaders, flags: number) => void): this;
prependOnceListener(event: "wantTrailers", listener: () => void): this;
prependOnceListener(event: string | symbol, listener: (...args: any[]) => void): this;
}
export interface ClientHttp2Stream extends Http2Stream {
addListener(event: "continue", listener: () => {}): this;
addListener(event: "headers", listener: (headers: IncomingHttpHeaders & IncomingHttpStatusHeader, flags: number) => void): this;
addListener(event: "push", listener: (headers: IncomingHttpHeaders, flags: number) => void): this;
addListener(event: "response", listener: (headers: IncomingHttpHeaders & IncomingHttpStatusHeader, flags: number) => void): this;
addListener(event: string | symbol, listener: (...args: any[]) => void): this;
emit(event: "continue"): boolean;
emit(event: "headers", headers: IncomingHttpHeaders & IncomingHttpStatusHeader, flags: number): boolean;
emit(event: "push", headers: IncomingHttpHeaders, flags: number): boolean;
emit(event: "response", headers: IncomingHttpHeaders & IncomingHttpStatusHeader, flags: number): boolean;
emit(event: string | symbol, ...args: any[]): boolean;
on(event: "continue", listener: () => {}): this;
on(event: "headers", listener: (headers: IncomingHttpHeaders & IncomingHttpStatusHeader, flags: number) => void): this;
on(event: "push", listener: (headers: IncomingHttpHeaders, flags: number) => void): this;
on(event: "response", listener: (headers: IncomingHttpHeaders & IncomingHttpStatusHeader, flags: number) => void): this;
on(event: string | symbol, listener: (...args: any[]) => void): this;
once(event: "continue", listener: () => {}): this;
once(event: "headers", listener: (headers: IncomingHttpHeaders & IncomingHttpStatusHeader, flags: number) => void): this;
once(event: "push", listener: (headers: IncomingHttpHeaders, flags: number) => void): this;
once(event: "response", listener: (headers: IncomingHttpHeaders & IncomingHttpStatusHeader, flags: number) => void): this;
once(event: string | symbol, listener: (...args: any[]) => void): this;
prependListener(event: "continue", listener: () => {}): this;
prependListener(event: "headers", listener: (headers: IncomingHttpHeaders & IncomingHttpStatusHeader, flags: number) => void): this;
prependListener(event: "push", listener: (headers: IncomingHttpHeaders, flags: number) => void): this;
prependListener(event: "response", listener: (headers: IncomingHttpHeaders & IncomingHttpStatusHeader, flags: number) => void): this;
prependListener(event: string | symbol, listener: (...args: any[]) => void): this;
prependOnceListener(event: "continue", listener: () => {}): this;
prependOnceListener(event: "headers", listener: (headers: IncomingHttpHeaders & IncomingHttpStatusHeader, flags: number) => void): this;
prependOnceListener(event: "push", listener: (headers: IncomingHttpHeaders, flags: number) => void): this;
prependOnceListener(event: "response", listener: (headers: IncomingHttpHeaders & IncomingHttpStatusHeader, flags: number) => void): this;
prependOnceListener(event: string | symbol, listener: (...args: any[]) => void): this;
}
export interface ServerHttp2Stream extends Http2Stream {
readonly headersSent: boolean;
readonly pushAllowed: boolean;
additionalHeaders(headers: OutgoingHttpHeaders): void;
pushStream(headers: OutgoingHttpHeaders, callback?: (err: Error | null, pushStream: ServerHttp2Stream, headers: OutgoingHttpHeaders) => void): void;
pushStream(headers: OutgoingHttpHeaders, options?: StreamPriorityOptions, callback?: (err: Error | null, pushStream: ServerHttp2Stream, headers: OutgoingHttpHeaders) => void): void;
respond(headers?: OutgoingHttpHeaders, options?: ServerStreamResponseOptions): void;
respondWithFD(fd: number | fs.promises.FileHandle, headers?: OutgoingHttpHeaders, options?: ServerStreamFileResponseOptions): void;
respondWithFile(path: string, headers?: OutgoingHttpHeaders, options?: ServerStreamFileResponseOptionsWithError): void;
}
// Http2Session
export interface Settings {
headerTableSize?: number | undefined;
enablePush?: boolean | undefined;
initialWindowSize?: number | undefined;
maxFrameSize?: number | undefined;
maxConcurrentStreams?: number | undefined;
maxHeaderListSize?: number | undefined;
enableConnectProtocol?: boolean | undefined;
}
export interface ClientSessionRequestOptions {
endStream?: boolean | undefined;
exclusive?: boolean | undefined;
parent?: number | undefined;
weight?: number | undefined;
waitForTrailers?: boolean | undefined;
}
export interface SessionState {
effectiveLocalWindowSize?: number | undefined;
effectiveRecvDataLength?: number | undefined;
nextStreamID?: number | undefined;
localWindowSize?: number | undefined;
lastProcStreamID?: number | undefined;
remoteWindowSize?: number | undefined;
outboundQueueSize?: number | undefined;
deflateDynamicTableSize?: number | undefined;
inflateDynamicTableSize?: number | undefined;
}
export interface Http2Session extends EventEmitter {
readonly alpnProtocol?: string | undefined;
readonly closed: boolean;
readonly connecting: boolean;
readonly destroyed: boolean;
readonly encrypted?: boolean | undefined;
readonly localSettings: Settings;
readonly originSet?: string[] | undefined;
readonly pendingSettingsAck: boolean;
readonly remoteSettings: Settings;
readonly socket: net.Socket | tls.TLSSocket;
readonly state: SessionState;
readonly type: number;
close(callback?: () => void): void;
destroy(error?: Error, code?: number): void;
goaway(code?: number, lastStreamID?: number, opaqueData?: NodeJS.ArrayBufferView): void;
ping(callback: (err: Error | null, duration: number, payload: Buffer) => void): boolean;
ping(payload: NodeJS.ArrayBufferView, callback: (err: Error | null, duration: number, payload: Buffer) => void): boolean;
ref(): void;
setLocalWindowSize(windowSize: number): void;
setTimeout(msecs: number, callback?: () => void): void;
settings(settings: Settings): void;
unref(): void;
addListener(event: "close", listener: () => void): this;
addListener(event: "error", listener: (err: Error) => void): this;
addListener(event: "frameError", listener: (frameType: number, errorCode: number, streamID: number) => void): this;
addListener(event: "goaway", listener: (errorCode: number, lastStreamID: number, opaqueData: Buffer) => void): this;
addListener(event: "localSettings", listener: (settings: Settings) => void): this;
addListener(event: "ping", listener: () => void): this;
addListener(event: "remoteSettings", listener: (settings: Settings) => void): this;
addListener(event: "timeout", listener: () => void): this;
addListener(event: string | symbol, listener: (...args: any[]) => void): this;
emit(event: "close"): boolean;
emit(event: "error", err: Error): boolean;
emit(event: "frameError", frameType: number, errorCode: number, streamID: number): boolean;
emit(event: "goaway", errorCode: number, lastStreamID: number, opaqueData: Buffer): boolean;
emit(event: "localSettings", settings: Settings): boolean;
emit(event: "ping"): boolean;
emit(event: "remoteSettings", settings: Settings): boolean;
emit(event: "timeout"): boolean;
emit(event: string | symbol, ...args: any[]): boolean;
on(event: "close", listener: () => void): this;
on(event: "error", listener: (err: Error) => void): this;
on(event: "frameError", listener: (frameType: number, errorCode: number, streamID: number) => void): this;
on(event: "goaway", listener: (errorCode: number, lastStreamID: number, opaqueData: Buffer) => void): this;
on(event: "localSettings", listener: (settings: Settings) => void): this;
on(event: "ping", listener: () => void): this;
on(event: "remoteSettings", listener: (settings: Settings) => void): this;
on(event: "timeout", listener: () => void): this;
on(event: string | symbol, listener: (...args: any[]) => void): this;
once(event: "close", listener: () => void): this;
once(event: "error", listener: (err: Error) => void): this;
once(event: "frameError", listener: (frameType: number, errorCode: number, streamID: number) => void): this;
once(event: "goaway", listener: (errorCode: number, lastStreamID: number, opaqueData: Buffer) => void): this;
once(event: "localSettings", listener: (settings: Settings) => void): this;
once(event: "ping", listener: () => void): this;
once(event: "remoteSettings", listener: (settings: Settings) => void): this;
once(event: "timeout", listener: () => void): this;
once(event: string | symbol, listener: (...args: any[]) => void): this;
prependListener(event: "close", listener: () => void): this;
prependListener(event: "error", listener: (err: Error) => void): this;
prependListener(event: "frameError", listener: (frameType: number, errorCode: number, streamID: number) => void): this;
prependListener(event: "goaway", listener: (errorCode: number, lastStreamID: number, opaqueData: Buffer) => void): this;
prependListener(event: "localSettings", listener: (settings: Settings) => void): this;
prependListener(event: "ping", listener: () => void): this;
prependListener(event: "remoteSettings", listener: (settings: Settings) => void): this;
prependListener(event: "timeout", listener: () => void): this;
prependListener(event: string | symbol, listener: (...args: any[]) => void): this;
prependOnceListener(event: "close", listener: () => void): this;
prependOnceListener(event: "error", listener: (err: Error) => void): this;
prependOnceListener(event: "frameError", listener: (frameType: number, errorCode: number, streamID: number) => void): this;
prependOnceListener(event: "goaway", listener: (errorCode: number, lastStreamID: number, opaqueData: Buffer) => void): this;
prependOnceListener(event: "localSettings", listener: (settings: Settings) => void): this;
prependOnceListener(event: "ping", listener: () => void): this;
prependOnceListener(event: "remoteSettings", listener: (settings: Settings) => void): this;
prependOnceListener(event: "timeout", listener: () => void): this;
prependOnceListener(event: string | symbol, listener: (...args: any[]) => void): this;
}
export interface ClientHttp2Session extends Http2Session {
request(headers?: OutgoingHttpHeaders, options?: ClientSessionRequestOptions): ClientHttp2Stream;
addListener(event: "altsvc", listener: (alt: string, origin: string, stream: number) => void): this;
addListener(event: "origin", listener: (origins: string[]) => void): this;
addListener(event: "connect", listener: (session: ClientHttp2Session, socket: net.Socket | tls.TLSSocket) => void): this;
addListener(event: "stream", listener: (stream: ClientHttp2Stream, headers: IncomingHttpHeaders & IncomingHttpStatusHeader, flags: number) => void): this;
addListener(event: string | symbol, listener: (...args: any[]) => void): this;
emit(event: "altsvc", alt: string, origin: string, stream: number): boolean;
emit(event: "origin", origins: ReadonlyArray<string>): boolean;
emit(event: "connect", session: ClientHttp2Session, socket: net.Socket | tls.TLSSocket): boolean;
emit(event: "stream", stream: ClientHttp2Stream, headers: IncomingHttpHeaders & IncomingHttpStatusHeader, flags: number): boolean;
emit(event: string | symbol, ...args: any[]): boolean;
on(event: "altsvc", listener: (alt: string, origin: string, stream: number) => void): this;
on(event: "origin", listener: (origins: string[]) => void): this;
on(event: "connect", listener: (session: ClientHttp2Session, socket: net.Socket | tls.TLSSocket) => void): this;
on(event: "stream", listener: (stream: ClientHttp2Stream, headers: IncomingHttpHeaders & IncomingHttpStatusHeader, flags: number) => void): this;
on(event: string | symbol, listener: (...args: any[]) => void): this;
once(event: "altsvc", listener: (alt: string, origin: string, stream: number) => void): this;
once(event: "origin", listener: (origins: string[]) => void): this;
once(event: "connect", listener: (session: ClientHttp2Session, socket: net.Socket | tls.TLSSocket) => void): this;
once(event: "stream", listener: (stream: ClientHttp2Stream, headers: IncomingHttpHeaders & IncomingHttpStatusHeader, flags: number) => void): this;
once(event: string | symbol, listener: (...args: any[]) => void): this;
prependListener(event: "altsvc", listener: (alt: string, origin: string, stream: number) => void): this;
prependListener(event: "origin", listener: (origins: string[]) => void): this;
prependListener(event: "connect", listener: (session: ClientHttp2Session, socket: net.Socket | tls.TLSSocket) => void): this;
prependListener(event: "stream", listener: (stream: ClientHttp2Stream, headers: IncomingHttpHeaders & IncomingHttpStatusHeader, flags: number) => void): this;
prependListener(event: string | symbol, listener: (...args: any[]) => void): this;
prependOnceListener(event: "altsvc", listener: (alt: string, origin: string, stream: number) => void): this;
prependOnceListener(event: "origin", listener: (origins: string[]) => void): this;
prependOnceListener(event: "connect", listener: (session: ClientHttp2Session, socket: net.Socket | tls.TLSSocket) => void): this;
prependOnceListener(event: "stream", listener: (stream: ClientHttp2Stream, headers: IncomingHttpHeaders & IncomingHttpStatusHeader, flags: number) => void): this;
prependOnceListener(event: string | symbol, listener: (...args: any[]) => void): this;
}
export interface AlternativeServiceOptions {
origin: number | string | url.URL;
}
export interface ServerHttp2Session extends Http2Session {
readonly server: Http2Server | Http2SecureServer;
altsvc(alt: string, originOrStream: number | string | url.URL | AlternativeServiceOptions): void;
origin(...args: Array<string | url.URL | { origin: string }>): void;
addListener(event: "connect", listener: (session: ServerHttp2Session, socket: net.Socket | tls.TLSSocket) => void): this;
addListener(event: "stream", listener: (stream: ServerHttp2Stream, headers: IncomingHttpHeaders, flags: number) => void): this;
addListener(event: string | symbol, listener: (...args: any[]) => void): this;
emit(event: "connect", session: ServerHttp2Session, socket: net.Socket | tls.TLSSocket): boolean;
emit(event: "stream", stream: ServerHttp2Stream, headers: IncomingHttpHeaders, flags: number): boolean;
emit(event: string | symbol, ...args: any[]): boolean;
on(event: "connect", listener: (session: ServerHttp2Session, socket: net.Socket | tls.TLSSocket) => void): this;
on(event: "stream", listener: (stream: ServerHttp2Stream, headers: IncomingHttpHeaders, flags: number) => void): this;
on(event: string | symbol, listener: (...args: any[]) => void): this;
once(event: "connect", listener: (session: ServerHttp2Session, socket: net.Socket | tls.TLSSocket) => void): this;
once(event: "stream", listener: (stream: ServerHttp2Stream, headers: IncomingHttpHeaders, flags: number) => void): this;
once(event: string | symbol, listener: (...args: any[]) => void): this;
prependListener(event: "connect", listener: (session: ServerHttp2Session, socket: net.Socket | tls.TLSSocket) => void): this;
prependListener(event: "stream", listener: (stream: ServerHttp2Stream, headers: IncomingHttpHeaders, flags: number) => void): this;
prependListener(event: string | symbol, listener: (...args: any[]) => void): this;
prependOnceListener(event: "connect", listener: (session: ServerHttp2Session, socket: net.Socket | tls.TLSSocket) => void): this;
prependOnceListener(event: "stream", listener: (stream: ServerHttp2Stream, headers: IncomingHttpHeaders, flags: number) => void): this;
prependOnceListener(event: string | symbol, listener: (...args: any[]) => void): this;
}
// Http2Server
export interface SessionOptions {
maxDeflateDynamicTableSize?: number | undefined;
maxSessionMemory?: number | undefined;
maxHeaderListPairs?: number | undefined;
maxOutstandingPings?: number | undefined;
maxSendHeaderBlockLength?: number | undefined;
paddingStrategy?: number | undefined;
peerMaxConcurrentStreams?: number | undefined;
settings?: Settings | undefined;
selectPadding?(frameLen: number, maxFrameLen: number): number;
createConnection?(authority: url.URL, option: SessionOptions): stream.Duplex;
}
export interface ClientSessionOptions extends SessionOptions {
maxReservedRemoteStreams?: number | undefined;
createConnection?: ((authority: url.URL, option: SessionOptions) => stream.Duplex) | undefined;
protocol?: 'http:' | 'https:' | undefined;
}
export interface ServerSessionOptions extends SessionOptions {
Http1IncomingMessage?: typeof IncomingMessage | undefined;
Http1ServerResponse?: typeof ServerResponse | undefined;
Http2ServerRequest?: typeof Http2ServerRequest | undefined;
Http2ServerResponse?: typeof Http2ServerResponse | undefined;
}
export interface SecureClientSessionOptions extends ClientSessionOptions, tls.ConnectionOptions { }
export interface SecureServerSessionOptions extends ServerSessionOptions, tls.TlsOptions { }
export interface ServerOptions extends ServerSessionOptions { }
export interface SecureServerOptions extends SecureServerSessionOptions {
allowHTTP1?: boolean | undefined;
origins?: string[] | undefined;
}
export interface Http2Server extends net.Server {
addListener(event: "checkContinue", listener: (request: Http2ServerRequest, response: Http2ServerResponse) => void): this;
addListener(event: "request", listener: (request: Http2ServerRequest, response: Http2ServerResponse) => void): this;
addListener(event: "session", listener: (session: ServerHttp2Session) => void): this;
addListener(event: "sessionError", listener: (err: Error) => void): this;
addListener(event: "stream", listener: (stream: ServerHttp2Stream, headers: IncomingHttpHeaders, flags: number) => void): this;
addListener(event: "timeout", listener: () => void): this;
addListener(event: string | symbol, listener: (...args: any[]) => void): this;
emit(event: "checkContinue", request: Http2ServerRequest, response: Http2ServerResponse): boolean;
emit(event: "request", request: Http2ServerRequest, response: Http2ServerResponse): boolean;
emit(event: "session", session: ServerHttp2Session): boolean;
emit(event: "sessionError", err: Error): boolean;
emit(event: "stream", stream: ServerHttp2Stream, headers: IncomingHttpHeaders, flags: number): boolean;
emit(event: "timeout"): boolean;
emit(event: string | symbol, ...args: any[]): boolean;
on(event: "checkContinue", listener: (request: Http2ServerRequest, response: Http2ServerResponse) => void): this;
on(event: "request", listener: (request: Http2ServerRequest, response: Http2ServerResponse) => void): this;
on(event: "session", listener: (session: ServerHttp2Session) => void): this;
on(event: "sessionError", listener: (err: Error) => void): this;
on(event: "stream", listener: (stream: ServerHttp2Stream, headers: IncomingHttpHeaders, flags: number) => void): this;
on(event: "timeout", listener: () => void): this;
on(event: string | symbol, listener: (...args: any[]) => void): this;
once(event: "checkContinue", listener: (request: Http2ServerRequest, response: Http2ServerResponse) => void): this;
once(event: "request", listener: (request: Http2ServerRequest, response: Http2ServerResponse) => void): this;
once(event: "session", listener: (session: ServerHttp2Session) => void): this;
once(event: "sessionError", listener: (err: Error) => void): this;
once(event: "stream", listener: (stream: ServerHttp2Stream, headers: IncomingHttpHeaders, flags: number) => void): this;
once(event: "timeout", listener: () => void): this;
once(event: string | symbol, listener: (...args: any[]) => void): this;
prependListener(event: "checkContinue", listener: (request: Http2ServerRequest, response: Http2ServerResponse) => void): this;
prependListener(event: "request", listener: (request: Http2ServerRequest, response: Http2ServerResponse) => void): this;
prependListener(event: "session", listener: (session: ServerHttp2Session) => void): this;
prependListener(event: "sessionError", listener: (err: Error) => void): this;
prependListener(event: "stream", listener: (stream: ServerHttp2Stream, headers: IncomingHttpHeaders, flags: number) => void): this;
prependListener(event: "timeout", listener: () => void): this;
prependListener(event: string | symbol, listener: (...args: any[]) => void): this;
prependOnceListener(event: "checkContinue", listener: (request: Http2ServerRequest, response: Http2ServerResponse) => void): this;
prependOnceListener(event: "request", listener: (request: Http2ServerRequest, response: Http2ServerResponse) => void): this;
prependOnceListener(event: "session", listener: (session: ServerHttp2Session) => void): this;
prependOnceListener(event: "sessionError", listener: (err: Error) => void): this;
prependOnceListener(event: "stream", listener: (stream: ServerHttp2Stream, headers: IncomingHttpHeaders, flags: number) => void): this;
prependOnceListener(event: "timeout", listener: () => void): this;
prependOnceListener(event: string | symbol, listener: (...args: any[]) => void): this;
setTimeout(msec?: number, callback?: () => void): this;
}
export interface Http2SecureServer extends tls.Server {
addListener(event: "checkContinue", listener: (request: Http2ServerRequest, response: Http2ServerResponse) => void): this;
addListener(event: "request", listener: (request: Http2ServerRequest, response: Http2ServerResponse) => void): this;
addListener(event: "session", listener: (session: ServerHttp2Session) => void): this;
addListener(event: "sessionError", listener: (err: Error) => void): this;
addListener(event: "stream", listener: (stream: ServerHttp2Stream, headers: IncomingHttpHeaders, flags: number) => void): this;
addListener(event: "timeout", listener: () => void): this;
addListener(event: "unknownProtocol", listener: (socket: tls.TLSSocket) => void): this;
addListener(event: string | symbol, listener: (...args: any[]) => void): this;
emit(event: "checkContinue", request: Http2ServerRequest, response: Http2ServerResponse): boolean;
emit(event: "request", request: Http2ServerRequest, response: Http2ServerResponse): boolean;
emit(event: "session", session: ServerHttp2Session): boolean;
emit(event: "sessionError", err: Error): boolean;
emit(event: "stream", stream: ServerHttp2Stream, headers: IncomingHttpHeaders, flags: number): boolean;
emit(event: "timeout"): boolean;
emit(event: "unknownProtocol", socket: tls.TLSSocket): boolean;
emit(event: string | symbol, ...args: any[]): boolean;
on(event: "checkContinue", listener: (request: Http2ServerRequest, response: Http2ServerResponse) => void): this;
on(event: "request", listener: (request: Http2ServerRequest, response: Http2ServerResponse) => void): this;
on(event: "session", listener: (session: ServerHttp2Session) => void): this;
on(event: "sessionError", listener: (err: Error) => void): this;
on(event: "stream", listener: (stream: ServerHttp2Stream, headers: IncomingHttpHeaders, flags: number) => void): this;
on(event: "timeout", listener: () => void): this;
on(event: "unknownProtocol", listener: (socket: tls.TLSSocket) => void): this;
on(event: string | symbol, listener: (...args: any[]) => void): this;
once(event: "checkContinue", listener: (request: Http2ServerRequest, response: Http2ServerResponse) => void): this;
once(event: "request", listener: (request: Http2ServerRequest, response: Http2ServerResponse) => void): this;
once(event: "session", listener: (session: ServerHttp2Session) => void): this;
once(event: "sessionError", listener: (err: Error) => void): this;
once(event: "stream", listener: (stream: ServerHttp2Stream, headers: IncomingHttpHeaders, flags: number) => void): this;
once(event: "timeout", listener: () => void): this;
once(event: "unknownProtocol", listener: (socket: tls.TLSSocket) => void): this;
once(event: string | symbol, listener: (...args: any[]) => void): this;
prependListener(event: "checkContinue", listener: (request: Http2ServerRequest, response: Http2ServerResponse) => void): this;
prependListener(event: "request", listener: (request: Http2ServerRequest, response: Http2ServerResponse) => void): this;
prependListener(event: "session", listener: (session: ServerHttp2Session) => void): this;
prependListener(event: "sessionError", listener: (err: Error) => void): this;
prependListener(event: "stream", listener: (stream: ServerHttp2Stream, headers: IncomingHttpHeaders, flags: number) => void): this;
prependListener(event: "timeout", listener: () => void): this;
prependListener(event: "unknownProtocol", listener: (socket: tls.TLSSocket) => void): this;
prependListener(event: string | symbol, listener: (...args: any[]) => void): this;
prependOnceListener(event: "checkContinue", listener: (request: Http2ServerRequest, response: Http2ServerResponse) => void): this;
prependOnceListener(event: "request", listener: (request: Http2ServerRequest, response: Http2ServerResponse) => void): this;
prependOnceListener(event: "session", listener: (session: ServerHttp2Session) => void): this;
prependOnceListener(event: "sessionError", listener: (err: Error) => void): this;
prependOnceListener(event: "stream", listener: (stream: ServerHttp2Stream, headers: IncomingHttpHeaders, flags: number) => void): this;
prependOnceListener(event: "timeout", listener: () => void): this;
prependOnceListener(event: "unknownProtocol", listener: (socket: tls.TLSSocket) => void): this;
prependOnceListener(event: string | symbol, listener: (...args: any[]) => void): this;
setTimeout(msec?: number, callback?: () => void): this;
}
export class Http2ServerRequest extends stream.Readable {
constructor(stream: ServerHttp2Stream, headers: IncomingHttpHeaders, options: stream.ReadableOptions, rawHeaders: ReadonlyArray<string>);
readonly aborted: boolean;
readonly authority: string;
readonly connection: net.Socket | tls.TLSSocket;
readonly complete: boolean;
readonly headers: IncomingHttpHeaders;
readonly httpVersion: string;
readonly httpVersionMinor: number;
readonly httpVersionMajor: number;
readonly method: string;
readonly rawHeaders: string[];
readonly rawTrailers: string[];
readonly scheme: string;
readonly socket: net.Socket | tls.TLSSocket;
readonly stream: ServerHttp2Stream;
readonly trailers: IncomingHttpHeaders;
readonly url: string;
setTimeout(msecs: number, callback?: () => void): void;
read(size?: number): Buffer | string | null;
addListener(event: "aborted", listener: (hadError: boolean, code: number) => void): this;
addListener(event: "close", listener: () => void): this;
addListener(event: "data", listener: (chunk: Buffer | string) => void): this;
addListener(event: "end", listener: () => void): this;
addListener(event: "readable", listener: () => void): this;
addListener(event: "error", listener: (err: Error) => void): this;
addListener(event: string | symbol, listener: (...args: any[]) => void): this;
emit(event: "aborted", hadError: boolean, code: number): boolean;
emit(event: "close"): boolean;
emit(event: "data", chunk: Buffer | string): boolean;
emit(event: "end"): boolean;
emit(event: "readable"): boolean;
emit(event: "error", err: Error): boolean;
emit(event: string | symbol, ...args: any[]): boolean;
on(event: "aborted", listener: (hadError: boolean, code: number) => void): this;
on(event: "close", listener: () => void): this;
on(event: "data", listener: (chunk: Buffer | string) => void): this;
on(event: "end", listener: () => void): this;
on(event: "readable", listener: () => void): this;
on(event: "error", listener: (err: Error) => void): this;
on(event: string | symbol, listener: (...args: any[]) => void): this;
once(event: "aborted", listener: (hadError: boolean, code: number) => void): this;
once(event: "close", listener: () => void): this;
once(event: "data", listener: (chunk: Buffer | string) => void): this;
once(event: "end", listener: () => void): this;
once(event: "readable", listener: () => void): this;
once(event: "error", listener: (err: Error) => void): this;
once(event: string | symbol, listener: (...args: any[]) => void): this;
prependListener(event: "aborted", listener: (hadError: boolean, code: number) => void): this;
prependListener(event: "close", listener: () => void): this;
prependListener(event: "data", listener: (chunk: Buffer | string) => void): this;
prependListener(event: "end", listener: () => void): this;
prependListener(event: "readable", listener: () => void): this;
prependListener(event: "error", listener: (err: Error) => void): this;
prependListener(event: string | symbol, listener: (...args: any[]) => void): this;
prependOnceListener(event: "aborted", listener: (hadError: boolean, code: number) => void): this;
prependOnceListener(event: "close", listener: () => void): this;
prependOnceListener(event: "data", listener: (chunk: Buffer | string) => void): this;
prependOnceListener(event: "end", listener: () => void): this;
prependOnceListener(event: "readable", listener: () => void): this;
prependOnceListener(event: "error", listener: (err: Error) => void): this;
prependOnceListener(event: string | symbol, listener: (...args: any[]) => void): this;
}
export class Http2ServerResponse extends stream.Writable {
constructor(stream: ServerHttp2Stream);
readonly connection: net.Socket | tls.TLSSocket;
readonly finished: boolean;
readonly headersSent: boolean;
readonly socket: net.Socket | tls.TLSSocket;
readonly stream: ServerHttp2Stream;
sendDate: boolean;
statusCode: number;
statusMessage: '';
addTrailers(trailers: OutgoingHttpHeaders): void;
end(callback?: () => void): void;
end(data: string | Uint8Array, callback?: () => void): void;
end(data: string | Uint8Array, encoding: BufferEncoding, callback?: () => void): void;
getHeader(name: string): string;
getHeaderNames(): string[];
getHeaders(): OutgoingHttpHeaders;
hasHeader(name: string): boolean;
removeHeader(name: string): void;
setHeader(name: string, value: number | string | ReadonlyArray<string>): void;
setTimeout(msecs: number, callback?: () => void): void;
write(chunk: string | Uint8Array, callback?: (err: Error) => void): boolean;
write(chunk: string | Uint8Array, encoding: BufferEncoding, callback?: (err: Error) => void): boolean;
writeContinue(): void;
writeHead(statusCode: number, headers?: OutgoingHttpHeaders): this;
writeHead(statusCode: number, statusMessage: string, headers?: OutgoingHttpHeaders): this;
createPushResponse(headers: OutgoingHttpHeaders, callback: (err: Error | null, res: Http2ServerResponse) => void): void;
addListener(event: "close", listener: () => void): this;
addListener(event: "drain", listener: () => void): this;
addListener(event: "error", listener: (error: Error) => void): this;
addListener(event: "finish", listener: () => void): this;
addListener(event: "pipe", listener: (src: stream.Readable) => void): this;
addListener(event: "unpipe", listener: (src: stream.Readable) => void): this;
addListener(event: string | symbol, listener: (...args: any[]) => void): this;
emit(event: "close"): boolean;
emit(event: "drain"): boolean;
emit(event: "error", error: Error): boolean;
emit(event: "finish"): boolean;
emit(event: "pipe", src: stream.Readable): boolean;
emit(event: "unpipe", src: stream.Readable): boolean;
emit(event: string | symbol, ...args: any[]): boolean;
on(event: "close", listener: () => void): this;
on(event: "drain", listener: () => void): this;
on(event: "error", listener: (error: Error) => void): this;
on(event: "finish", listener: () => void): this;
on(event: "pipe", listener: (src: stream.Readable) => void): this;
on(event: "unpipe", listener: (src: stream.Readable) => void): this;
on(event: string | symbol, listener: (...args: any[]) => void): this;
once(event: "close", listener: () => void): this;
once(event: "drain", listener: () => void): this;
once(event: "error", listener: (error: Error) => void): this;
once(event: "finish", listener: () => void): this;
once(event: "pipe", listener: (src: stream.Readable) => void): this;
once(event: "unpipe", listener: (src: stream.Readable) => void): this;
once(event: string | symbol, listener: (...args: any[]) => void): this;
prependListener(event: "close", listener: () => void): this;
prependListener(event: "drain", listener: () => void): this;
prependListener(event: "error", listener: (error: Error) => void): this;
prependListener(event: "finish", listener: () => void): this;
prependListener(event: "pipe", listener: (src: stream.Readable) => void): this;
prependListener(event: "unpipe", listener: (src: stream.Readable) => void): this;
prependListener(event: string | symbol, listener: (...args: any[]) => void): this;
prependOnceListener(event: "close", listener: () => void): this;
prependOnceListener(event: "drain", listener: () => void): this;
prependOnceListener(event: "error", listener: (error: Error) => void): this;
prependOnceListener(event: "finish", listener: () => void): this;
prependOnceListener(event: "pipe", listener: (src: stream.Readable) => void): this;
prependOnceListener(event: "unpipe", listener: (src: stream.Readable) => void): this;
prependOnceListener(event: string | symbol, listener: (...args: any[]) => void): this;
}
// Public API
export namespace constants {
const NGHTTP2_SESSION_SERVER: number;
const NGHTTP2_SESSION_CLIENT: number;
const NGHTTP2_STREAM_STATE_IDLE: number;
const NGHTTP2_STREAM_STATE_OPEN: number;
const NGHTTP2_STREAM_STATE_RESERVED_LOCAL: number;
const NGHTTP2_STREAM_STATE_RESERVED_REMOTE: number;
const NGHTTP2_STREAM_STATE_HALF_CLOSED_LOCAL: number;
const NGHTTP2_STREAM_STATE_HALF_CLOSED_REMOTE: number;
const NGHTTP2_STREAM_STATE_CLOSED: number;
const NGHTTP2_NO_ERROR: number;
const NGHTTP2_PROTOCOL_ERROR: number;
const NGHTTP2_INTERNAL_ERROR: number;
const NGHTTP2_FLOW_CONTROL_ERROR: number;
const NGHTTP2_SETTINGS_TIMEOUT: number;
const NGHTTP2_STREAM_CLOSED: number;
const NGHTTP2_FRAME_SIZE_ERROR: number;
const NGHTTP2_REFUSED_STREAM: number;
const NGHTTP2_CANCEL: number;
const NGHTTP2_COMPRESSION_ERROR: number;
const NGHTTP2_CONNECT_ERROR: number;
const NGHTTP2_ENHANCE_YOUR_CALM: number;
const NGHTTP2_INADEQUATE_SECURITY: number;
const NGHTTP2_HTTP_1_1_REQUIRED: number;
const NGHTTP2_ERR_FRAME_SIZE_ERROR: number;
const NGHTTP2_FLAG_NONE: number;
const NGHTTP2_FLAG_END_STREAM: number;
const NGHTTP2_FLAG_END_HEADERS: number;
const NGHTTP2_FLAG_ACK: number;
const NGHTTP2_FLAG_PADDED: number;
const NGHTTP2_FLAG_PRIORITY: number;
const DEFAULT_SETTINGS_HEADER_TABLE_SIZE: number;
const DEFAULT_SETTINGS_ENABLE_PUSH: number;
const DEFAULT_SETTINGS_INITIAL_WINDOW_SIZE: number;
const DEFAULT_SETTINGS_MAX_FRAME_SIZE: number;
const MAX_MAX_FRAME_SIZE: number;
const MIN_MAX_FRAME_SIZE: number;
const MAX_INITIAL_WINDOW_SIZE: number;
const NGHTTP2_DEFAULT_WEIGHT: number;
const NGHTTP2_SETTINGS_HEADER_TABLE_SIZE: number;
const NGHTTP2_SETTINGS_ENABLE_PUSH: number;
const NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS: number;
const NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE: number;
const NGHTTP2_SETTINGS_MAX_FRAME_SIZE: number;
const NGHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE: number;
const PADDING_STRATEGY_NONE: number;
const PADDING_STRATEGY_MAX: number;
const PADDING_STRATEGY_CALLBACK: number;
const HTTP2_HEADER_STATUS: string;
const HTTP2_HEADER_METHOD: string;
const HTTP2_HEADER_AUTHORITY: string;
const HTTP2_HEADER_SCHEME: string;
const HTTP2_HEADER_PATH: string;
const HTTP2_HEADER_ACCEPT_CHARSET: string;
const HTTP2_HEADER_ACCEPT_ENCODING: string;
const HTTP2_HEADER_ACCEPT_LANGUAGE: string;
const HTTP2_HEADER_ACCEPT_RANGES: string;
const HTTP2_HEADER_ACCEPT: string;
const HTTP2_HEADER_ACCESS_CONTROL_ALLOW_ORIGIN: string;
const HTTP2_HEADER_AGE: string;
const HTTP2_HEADER_ALLOW: string;
const HTTP2_HEADER_AUTHORIZATION: string;
const HTTP2_HEADER_CACHE_CONTROL: string;
const HTTP2_HEADER_CONNECTION: string;
const HTTP2_HEADER_CONTENT_DISPOSITION: string;
const HTTP2_HEADER_CONTENT_ENCODING: string;
const HTTP2_HEADER_CONTENT_LANGUAGE: string;
const HTTP2_HEADER_CONTENT_LENGTH: string;
const HTTP2_HEADER_CONTENT_LOCATION: string;
const HTTP2_HEADER_CONTENT_MD5: string;
const HTTP2_HEADER_CONTENT_RANGE: string;
const HTTP2_HEADER_CONTENT_TYPE: string;
const HTTP2_HEADER_COOKIE: string;
const HTTP2_HEADER_DATE: string;
const HTTP2_HEADER_ETAG: string;
const HTTP2_HEADER_EXPECT: string;
const HTTP2_HEADER_EXPIRES: string;
const HTTP2_HEADER_FROM: string;
const HTTP2_HEADER_HOST: string;
const HTTP2_HEADER_IF_MATCH: string;
const HTTP2_HEADER_IF_MODIFIED_SINCE: string;
const HTTP2_HEADER_IF_NONE_MATCH: string;
const HTTP2_HEADER_IF_RANGE: string;
const HTTP2_HEADER_IF_UNMODIFIED_SINCE: string;
const HTTP2_HEADER_LAST_MODIFIED: string;
const HTTP2_HEADER_LINK: string;
const HTTP2_HEADER_LOCATION: string;
const HTTP2_HEADER_MAX_FORWARDS: string;
const HTTP2_HEADER_PREFER: string;
const HTTP2_HEADER_PROXY_AUTHENTICATE: string;
const HTTP2_HEADER_PROXY_AUTHORIZATION: string;
const HTTP2_HEADER_RANGE: string;
const HTTP2_HEADER_REFERER: string;
const HTTP2_HEADER_REFRESH: string;
const HTTP2_HEADER_RETRY_AFTER: string;
const HTTP2_HEADER_SERVER: string;
const HTTP2_HEADER_SET_COOKIE: string;
const HTTP2_HEADER_STRICT_TRANSPORT_SECURITY: string;
const HTTP2_HEADER_TRANSFER_ENCODING: string;
const HTTP2_HEADER_TE: string;
const HTTP2_HEADER_UPGRADE: string;
const HTTP2_HEADER_USER_AGENT: string;
const HTTP2_HEADER_VARY: string;
const HTTP2_HEADER_VIA: string;
const HTTP2_HEADER_WWW_AUTHENTICATE: string;
const HTTP2_HEADER_HTTP2_SETTINGS: string;
const HTTP2_HEADER_KEEP_ALIVE: string;
const HTTP2_HEADER_PROXY_CONNECTION: string;
const HTTP2_METHOD_ACL: string;
const HTTP2_METHOD_BASELINE_CONTROL: string;
const HTTP2_METHOD_BIND: string;
const HTTP2_METHOD_CHECKIN: string;
const HTTP2_METHOD_CHECKOUT: string;
const HTTP2_METHOD_CONNECT: string;
const HTTP2_METHOD_COPY: string;
const HTTP2_METHOD_DELETE: string;
const HTTP2_METHOD_GET: string;
const HTTP2_METHOD_HEAD: string;
const HTTP2_METHOD_LABEL: string;
const HTTP2_METHOD_LINK: string;
const HTTP2_METHOD_LOCK: string;
const HTTP2_METHOD_MERGE: string;
const HTTP2_METHOD_MKACTIVITY: string;
const HTTP2_METHOD_MKCALENDAR: string;
const HTTP2_METHOD_MKCOL: string;
const HTTP2_METHOD_MKREDIRECTREF: string;
const HTTP2_METHOD_MKWORKSPACE: string;
const HTTP2_METHOD_MOVE: string;
const HTTP2_METHOD_OPTIONS: string;
const HTTP2_METHOD_ORDERPATCH: string;
const HTTP2_METHOD_PATCH: string;
const HTTP2_METHOD_POST: string;
const HTTP2_METHOD_PRI: string;
const HTTP2_METHOD_PROPFIND: string;
const HTTP2_METHOD_PROPPATCH: string;
const HTTP2_METHOD_PUT: string;
const HTTP2_METHOD_REBIND: string;
const HTTP2_METHOD_REPORT: string;
const HTTP2_METHOD_SEARCH: string;
const HTTP2_METHOD_TRACE: string;
const HTTP2_METHOD_UNBIND: string;
const HTTP2_METHOD_UNCHECKOUT: string;
const HTTP2_METHOD_UNLINK: string;
const HTTP2_METHOD_UNLOCK: string;
const HTTP2_METHOD_UPDATE: string;
const HTTP2_METHOD_UPDATEREDIRECTREF: string;
const HTTP2_METHOD_VERSION_CONTROL: string;
const HTTP_STATUS_CONTINUE: number;
const HTTP_STATUS_SWITCHING_PROTOCOLS: number;
const HTTP_STATUS_PROCESSING: number;
const HTTP_STATUS_OK: number;
const HTTP_STATUS_CREATED: number;
const HTTP_STATUS_ACCEPTED: number;
const HTTP_STATUS_NON_AUTHORITATIVE_INFORMATION: number;
const HTTP_STATUS_NO_CONTENT: number;
const HTTP_STATUS_RESET_CONTENT: number;
const HTTP_STATUS_PARTIAL_CONTENT: number;
const HTTP_STATUS_MULTI_STATUS: number;
const HTTP_STATUS_ALREADY_REPORTED: number;
const HTTP_STATUS_IM_USED: number;
const HTTP_STATUS_MULTIPLE_CHOICES: number;
const HTTP_STATUS_MOVED_PERMANENTLY: number;
const HTTP_STATUS_FOUND: number;
const HTTP_STATUS_SEE_OTHER: number;
const HTTP_STATUS_NOT_MODIFIED: number;
const HTTP_STATUS_USE_PROXY: number;
const HTTP_STATUS_TEMPORARY_REDIRECT: number;
const HTTP_STATUS_PERMANENT_REDIRECT: number;
const HTTP_STATUS_BAD_REQUEST: number;
const HTTP_STATUS_UNAUTHORIZED: number;
const HTTP_STATUS_PAYMENT_REQUIRED: number;
const HTTP_STATUS_FORBIDDEN: number;
const HTTP_STATUS_NOT_FOUND: number;
const HTTP_STATUS_METHOD_NOT_ALLOWED: number;
const HTTP_STATUS_NOT_ACCEPTABLE: number;
const HTTP_STATUS_PROXY_AUTHENTICATION_REQUIRED: number;
const HTTP_STATUS_REQUEST_TIMEOUT: number;
const HTTP_STATUS_CONFLICT: number;
const HTTP_STATUS_GONE: number;
const HTTP_STATUS_LENGTH_REQUIRED: number;
const HTTP_STATUS_PRECONDITION_FAILED: number;
const HTTP_STATUS_PAYLOAD_TOO_LARGE: number;
const HTTP_STATUS_URI_TOO_LONG: number;
const HTTP_STATUS_UNSUPPORTED_MEDIA_TYPE: number;
const HTTP_STATUS_RANGE_NOT_SATISFIABLE: number;
const HTTP_STATUS_EXPECTATION_FAILED: number;
const HTTP_STATUS_TEAPOT: number;
const HTTP_STATUS_MISDIRECTED_REQUEST: number;
const HTTP_STATUS_UNPROCESSABLE_ENTITY: number;
const HTTP_STATUS_LOCKED: number;
const HTTP_STATUS_FAILED_DEPENDENCY: number;
const HTTP_STATUS_UNORDERED_COLLECTION: number;
const HTTP_STATUS_UPGRADE_REQUIRED: number;
const HTTP_STATUS_PRECONDITION_REQUIRED: number;
const HTTP_STATUS_TOO_MANY_REQUESTS: number;
const HTTP_STATUS_REQUEST_HEADER_FIELDS_TOO_LARGE: number;
const HTTP_STATUS_UNAVAILABLE_FOR_LEGAL_REASONS: number;
const HTTP_STATUS_INTERNAL_SERVER_ERROR: number;
const HTTP_STATUS_NOT_IMPLEMENTED: number;
const HTTP_STATUS_BAD_GATEWAY: number;
const HTTP_STATUS_SERVICE_UNAVAILABLE: number;
const HTTP_STATUS_GATEWAY_TIMEOUT: number;
const HTTP_STATUS_HTTP_VERSION_NOT_SUPPORTED: number;
const HTTP_STATUS_VARIANT_ALSO_NEGOTIATES: number;
const HTTP_STATUS_INSUFFICIENT_STORAGE: number;
const HTTP_STATUS_LOOP_DETECTED: number;
const HTTP_STATUS_BANDWIDTH_LIMIT_EXCEEDED: number;
const HTTP_STATUS_NOT_EXTENDED: number;
const HTTP_STATUS_NETWORK_AUTHENTICATION_REQUIRED: number;
}
export function getDefaultSettings(): Settings;
export function getPackedSettings(settings: Settings): Buffer;
export function getUnpackedSettings(buf: Uint8Array): Settings;
export function createServer(onRequestHandler?: (request: Http2ServerRequest, response: Http2ServerResponse) => void): Http2Server;
export function createServer(options: ServerOptions, onRequestHandler?: (request: Http2ServerRequest, response: Http2ServerResponse) => void): Http2Server;
export function createSecureServer(onRequestHandler?: (request: Http2ServerRequest, response: Http2ServerResponse) => void): Http2SecureServer;
export function createSecureServer(options: SecureServerOptions, onRequestHandler?: (request: Http2ServerRequest, response: Http2ServerResponse) => void): Http2SecureServer;
export function connect(authority: string | url.URL, listener: (session: ClientHttp2Session, socket: net.Socket | tls.TLSSocket) => void): ClientHttp2Session;
export function connect(
authority: string | url.URL,
options?: ClientSessionOptions | SecureClientSessionOptions,
listener?: (session: ClientHttp2Session, socket: net.Socket | tls.TLSSocket) => void
): ClientHttp2Session;
}

View File

@ -0,0 +1,142 @@
/* NOTE: Do not edit directly! This file is generated using `npm run update-types` in https://github.com/node-red/nr-monaco-build */
declare module 'https' {
import { Duplex } from 'stream';
import * as tls from 'tls';
import * as http from 'http';
import { URL } from 'url';
type ServerOptions = tls.SecureContextOptions & tls.TlsOptions & http.ServerOptions;
type RequestOptions = http.RequestOptions & tls.SecureContextOptions & {
rejectUnauthorized?: boolean | undefined; // Defaults to true
servername?: string | undefined; // SNI TLS Extension
};
interface AgentOptions extends http.AgentOptions, tls.ConnectionOptions {
rejectUnauthorized?: boolean | undefined;
maxCachedSessions?: number | undefined;
}
class Agent extends http.Agent {
constructor(options?: AgentOptions);
options: AgentOptions;
}
interface Server extends http.Server {}
class Server extends tls.Server {
constructor(requestListener?: http.RequestListener);
constructor(options: ServerOptions, requestListener?: http.RequestListener);
addListener(event: string, listener: (...args: any[]) => void): this;
addListener(event: 'keylog', listener: (line: Buffer, tlsSocket: tls.TLSSocket) => void): this;
addListener(event: 'newSession', listener: (sessionId: Buffer, sessionData: Buffer, callback: (err: Error, resp: Buffer) => void) => void): this;
addListener(event: 'OCSPRequest', listener: (certificate: Buffer, issuer: Buffer, callback: (err: Error | null, resp: Buffer) => void) => void): this;
addListener(event: 'resumeSession', listener: (sessionId: Buffer, callback: (err: Error, sessionData: Buffer) => void) => void): this;
addListener(event: 'secureConnection', listener: (tlsSocket: tls.TLSSocket) => void): this;
addListener(event: 'tlsClientError', listener: (err: Error, tlsSocket: tls.TLSSocket) => void): this;
addListener(event: 'close', listener: () => void): this;
addListener(event: 'connection', listener: (socket: Duplex) => void): this;
addListener(event: 'error', listener: (err: Error) => void): this;
addListener(event: 'listening', listener: () => void): this;
addListener(event: 'checkContinue', listener: http.RequestListener): this;
addListener(event: 'checkExpectation', listener: http.RequestListener): this;
addListener(event: 'clientError', listener: (err: Error, socket: Duplex) => void): this;
addListener(event: 'connect', listener: (req: http.IncomingMessage, socket: Duplex, head: Buffer) => void): this;
addListener(event: 'request', listener: http.RequestListener): this;
addListener(event: 'upgrade', listener: (req: http.IncomingMessage, socket: Duplex, head: Buffer) => void): this;
emit(event: string, ...args: any[]): boolean;
emit(event: 'keylog', line: Buffer, tlsSocket: tls.TLSSocket): boolean;
emit(event: 'newSession', sessionId: Buffer, sessionData: Buffer, callback: (err: Error, resp: Buffer) => void): boolean;
emit(event: 'OCSPRequest', certificate: Buffer, issuer: Buffer, callback: (err: Error | null, resp: Buffer) => void): boolean;
emit(event: 'resumeSession', sessionId: Buffer, callback: (err: Error, sessionData: Buffer) => void): boolean;
emit(event: 'secureConnection', tlsSocket: tls.TLSSocket): boolean;
emit(event: 'tlsClientError', err: Error, tlsSocket: tls.TLSSocket): boolean;
emit(event: 'close'): boolean;
emit(event: 'connection', socket: Duplex): boolean;
emit(event: 'error', err: Error): boolean;
emit(event: 'listening'): boolean;
emit(event: 'checkContinue', req: http.IncomingMessage, res: http.ServerResponse): boolean;
emit(event: 'checkExpectation', req: http.IncomingMessage, res: http.ServerResponse): boolean;
emit(event: 'clientError', err: Error, socket: Duplex): boolean;
emit(event: 'connect', req: http.IncomingMessage, socket: Duplex, head: Buffer): boolean;
emit(event: 'request', req: http.IncomingMessage, res: http.ServerResponse): boolean;
emit(event: 'upgrade', req: http.IncomingMessage, socket: Duplex, head: Buffer): boolean;
on(event: string, listener: (...args: any[]) => void): this;
on(event: 'keylog', listener: (line: Buffer, tlsSocket: tls.TLSSocket) => void): this;
on(event: 'newSession', listener: (sessionId: Buffer, sessionData: Buffer, callback: (err: Error, resp: Buffer) => void) => void): this;
on(event: 'OCSPRequest', listener: (certificate: Buffer, issuer: Buffer, callback: (err: Error | null, resp: Buffer) => void) => void): this;
on(event: 'resumeSession', listener: (sessionId: Buffer, callback: (err: Error, sessionData: Buffer) => void) => void): this;
on(event: 'secureConnection', listener: (tlsSocket: tls.TLSSocket) => void): this;
on(event: 'tlsClientError', listener: (err: Error, tlsSocket: tls.TLSSocket) => void): this;
on(event: 'close', listener: () => void): this;
on(event: 'connection', listener: (socket: Duplex) => void): this;
on(event: 'error', listener: (err: Error) => void): this;
on(event: 'listening', listener: () => void): this;
on(event: 'checkContinue', listener: http.RequestListener): this;
on(event: 'checkExpectation', listener: http.RequestListener): this;
on(event: 'clientError', listener: (err: Error, socket: Duplex) => void): this;
on(event: 'connect', listener: (req: http.IncomingMessage, socket: Duplex, head: Buffer) => void): this;
on(event: 'request', listener: http.RequestListener): this;
on(event: 'upgrade', listener: (req: http.IncomingMessage, socket: Duplex, head: Buffer) => void): this;
once(event: string, listener: (...args: any[]) => void): this;
once(event: 'keylog', listener: (line: Buffer, tlsSocket: tls.TLSSocket) => void): this;
once(event: 'newSession', listener: (sessionId: Buffer, sessionData: Buffer, callback: (err: Error, resp: Buffer) => void) => void): this;
once(event: 'OCSPRequest', listener: (certificate: Buffer, issuer: Buffer, callback: (err: Error | null, resp: Buffer) => void) => void): this;
once(event: 'resumeSession', listener: (sessionId: Buffer, callback: (err: Error, sessionData: Buffer) => void) => void): this;
once(event: 'secureConnection', listener: (tlsSocket: tls.TLSSocket) => void): this;
once(event: 'tlsClientError', listener: (err: Error, tlsSocket: tls.TLSSocket) => void): this;
once(event: 'close', listener: () => void): this;
once(event: 'connection', listener: (socket: Duplex) => void): this;
once(event: 'error', listener: (err: Error) => void): this;
once(event: 'listening', listener: () => void): this;
once(event: 'checkContinue', listener: http.RequestListener): this;
once(event: 'checkExpectation', listener: http.RequestListener): this;
once(event: 'clientError', listener: (err: Error, socket: Duplex) => void): this;
once(event: 'connect', listener: (req: http.IncomingMessage, socket: Duplex, head: Buffer) => void): this;
once(event: 'request', listener: http.RequestListener): this;
once(event: 'upgrade', listener: (req: http.IncomingMessage, socket: Duplex, head: Buffer) => void): this;
prependListener(event: string, listener: (...args: any[]) => void): this;
prependListener(event: 'keylog', listener: (line: Buffer, tlsSocket: tls.TLSSocket) => void): this;
prependListener(event: 'newSession', listener: (sessionId: Buffer, sessionData: Buffer, callback: (err: Error, resp: Buffer) => void) => void): this;
prependListener(event: 'OCSPRequest', listener: (certificate: Buffer, issuer: Buffer, callback: (err: Error | null, resp: Buffer) => void) => void): this;
prependListener(event: 'resumeSession', listener: (sessionId: Buffer, callback: (err: Error, sessionData: Buffer) => void) => void): this;
prependListener(event: 'secureConnection', listener: (tlsSocket: tls.TLSSocket) => void): this;
prependListener(event: 'tlsClientError', listener: (err: Error, tlsSocket: tls.TLSSocket) => void): this;
prependListener(event: 'close', listener: () => void): this;
prependListener(event: 'connection', listener: (socket: Duplex) => void): this;
prependListener(event: 'error', listener: (err: Error) => void): this;
prependListener(event: 'listening', listener: () => void): this;
prependListener(event: 'checkContinue', listener: http.RequestListener): this;
prependListener(event: 'checkExpectation', listener: http.RequestListener): this;
prependListener(event: 'clientError', listener: (err: Error, socket: Duplex) => void): this;
prependListener(event: 'connect', listener: (req: http.IncomingMessage, socket: Duplex, head: Buffer) => void): this;
prependListener(event: 'request', listener: http.RequestListener): this;
prependListener(event: 'upgrade', listener: (req: http.IncomingMessage, socket: Duplex, head: Buffer) => void): this;
prependOnceListener(event: string, listener: (...args: any[]) => void): this;
prependOnceListener(event: 'keylog', listener: (line: Buffer, tlsSocket: tls.TLSSocket) => void): this;
prependOnceListener(event: 'newSession', listener: (sessionId: Buffer, sessionData: Buffer, callback: (err: Error, resp: Buffer) => void) => void): this;
prependOnceListener(event: 'OCSPRequest', listener: (certificate: Buffer, issuer: Buffer, callback: (err: Error | null, resp: Buffer) => void) => void): this;
prependOnceListener(event: 'resumeSession', listener: (sessionId: Buffer, callback: (err: Error, sessionData: Buffer) => void) => void): this;
prependOnceListener(event: 'secureConnection', listener: (tlsSocket: tls.TLSSocket) => void): this;
prependOnceListener(event: 'tlsClientError', listener: (err: Error, tlsSocket: tls.TLSSocket) => void): this;
prependOnceListener(event: 'close', listener: () => void): this;
prependOnceListener(event: 'connection', listener: (socket: Duplex) => void): this;
prependOnceListener(event: 'error', listener: (err: Error) => void): this;
prependOnceListener(event: 'listening', listener: () => void): this;
prependOnceListener(event: 'checkContinue', listener: http.RequestListener): this;
prependOnceListener(event: 'checkExpectation', listener: http.RequestListener): this;
prependOnceListener(event: 'clientError', listener: (err: Error, socket: Duplex) => void): this;
prependOnceListener(event: 'connect', listener: (req: http.IncomingMessage, socket: Duplex, head: Buffer) => void): this;
prependOnceListener(event: 'request', listener: http.RequestListener): this;
prependOnceListener(event: 'upgrade', listener: (req: http.IncomingMessage, socket: Duplex, head: Buffer) => void): this;
}
function createServer(requestListener?: http.RequestListener): Server;
function createServer(options: ServerOptions, requestListener?: http.RequestListener): Server;
function request(options: RequestOptions | string | URL, callback?: (res: http.IncomingMessage) => void): http.ClientRequest;
function request(url: string | URL, options: RequestOptions, callback?: (res: http.IncomingMessage) => void): http.ClientRequest;
function get(options: RequestOptions | string | URL, callback?: (res: http.IncomingMessage) => void): http.ClientRequest;
function get(url: string | URL, options: RequestOptions, callback?: (res: http.IncomingMessage) => void): http.ClientRequest;
let globalAgent: Agent;
}

View File

@ -0,0 +1,55 @@
/* NOTE: Do not edit directly! This file is generated using `npm run update-types` in https://github.com/node-red/nr-monaco-build */
declare module 'module' {
import { URL } from 'url';
namespace Module {
/**
* Updates all the live bindings for builtin ES Modules to match the properties of the CommonJS exports.
* It does not add or remove exported names from the ES Modules.
*/
function syncBuiltinESMExports(): void;
function findSourceMap(path: string, error?: Error): SourceMap;
interface SourceMapPayload {
file: string;
version: number;
sources: string[];
sourcesContent: string[];
names: string[];
mappings: string;
sourceRoot: string;
}
interface SourceMapping {
generatedLine: number;
generatedColumn: number;
originalSource: string;
originalLine: number;
originalColumn: number;
}
class SourceMap {
readonly payload: SourceMapPayload;
constructor(payload: SourceMapPayload);
findEntry(line: number, column: number): SourceMapping;
}
}
interface Module extends NodeModule {}
class Module {
static runMain(): void;
static wrap(code: string): string;
/**
* @deprecated Deprecated since: v12.2.0. Please use createRequire() instead.
*/
static createRequireFromPath(path: string): NodeRequire;
static createRequire(path: string | URL): NodeRequire;
static builtinModules: string[];
static Module: typeof Module;
constructor(id: string, parent?: Module);
}
export = Module;
}

File diff suppressed because one or more lines are too long

View File

@ -1 +1,242 @@
declare module'node:os'{export*from'os';}declare module'os'{interface CpuInfo{model:string;speed:number;times:{user:number;nice:number;sys:number;idle:number;irq:number;};}interface NetworkInterfaceBase{address:string;netmask:string;mac:string;internal:boolean;cidr:string|null;}interface NetworkInterfaceInfoIPv4 extends NetworkInterfaceBase{family:"IPv4";}interface NetworkInterfaceInfoIPv6 extends NetworkInterfaceBase{family:"IPv6";scopeid:number;}interface UserInfo<T>{username:T;uid:number;gid:number;shell:T;homedir:T;}type NetworkInterfaceInfo=NetworkInterfaceInfoIPv4|NetworkInterfaceInfoIPv6;function hostname():string;function loadavg():number[];function uptime():number;function freemem():number;function totalmem():number;function cpus():CpuInfo[];function type():string;function release():string;function networkInterfaces():NodeJS.Dict<NetworkInterfaceInfo[]>;function homedir():string;function userInfo(options:{encoding:'buffer'}):UserInfo<Buffer>;function userInfo(options?:{encoding:BufferEncoding}):UserInfo<string>;type SignalConstants={[key in NodeJS.Signals]:number;};namespace constants{const UV_UDP_REUSEADDR:number;namespace signals{}const signals:SignalConstants;namespace errno{const E2BIG:number;const EACCES:number;const EADDRINUSE:number;const EADDRNOTAVAIL:number;const EAFNOSUPPORT:number;const EAGAIN:number;const EALREADY:number;const EBADF:number;const EBADMSG:number;const EBUSY:number;const ECANCELED:number;const ECHILD:number;const ECONNABORTED:number;const ECONNREFUSED:number;const ECONNRESET:number;const EDEADLK:number;const EDESTADDRREQ:number;const EDOM:number;const EDQUOT:number;const EEXIST:number;const EFAULT:number;const EFBIG:number;const EHOSTUNREACH:number;const EIDRM:number;const EILSEQ:number;const EINPROGRESS:number;const EINTR:number;const EINVAL:number;const EIO:number;const EISCONN:number;const EISDIR:number;const ELOOP:number;const EMFILE:number;const EMLINK:number;const EMSGSIZE:number;const EMULTIHOP:number;const ENAMETOOLONG:number;const ENETDOWN:number;const ENETRESET:number;const ENETUNREACH:number;const ENFILE:number;const ENOBUFS:number;const ENODATA:number;const ENODEV:number;const ENOENT:number;const ENOEXEC:number;const ENOLCK:number;const ENOLINK:number;const ENOMEM:number;const ENOMSG:number;const ENOPROTOOPT:number;const ENOSPC:number;const ENOSR:number;const ENOSTR:number;const ENOSYS:number;const ENOTCONN:number;const ENOTDIR:number;const ENOTEMPTY:number;const ENOTSOCK:number;const ENOTSUP:number;const ENOTTY:number;const ENXIO:number;const EOPNOTSUPP:number;const EOVERFLOW:number;const EPERM:number;const EPIPE:number;const EPROTO:number;const EPROTONOSUPPORT:number;const EPROTOTYPE:number;const ERANGE:number;const EROFS:number;const ESPIPE:number;const ESRCH:number;const ESTALE:number;const ETIME:number;const ETIMEDOUT:number;const ETXTBSY:number;const EWOULDBLOCK:number;const EXDEV:number;const WSAEINTR:number;const WSAEBADF:number;const WSAEACCES:number;const WSAEFAULT:number;const WSAEINVAL:number;const WSAEMFILE:number;const WSAEWOULDBLOCK:number;const WSAEINPROGRESS:number;const WSAEALREADY:number;const WSAENOTSOCK:number;const WSAEDESTADDRREQ:number;const WSAEMSGSIZE:number;const WSAEPROTOTYPE:number;const WSAENOPROTOOPT:number;const WSAEPROTONOSUPPORT:number;const WSAESOCKTNOSUPPORT:number;const WSAEOPNOTSUPP:number;const WSAEPFNOSUPPORT:number;const WSAEAFNOSUPPORT:number;const WSAEADDRINUSE:number;const WSAEADDRNOTAVAIL:number;const WSAENETDOWN:number;const WSAENETUNREACH:number;const WSAENETRESET:number;const WSAECONNABORTED:number;const WSAECONNRESET:number;const WSAENOBUFS:number;const WSAEISCONN:number;const WSAENOTCONN:number;const WSAESHUTDOWN:number;const WSAETOOMANYREFS:number;const WSAETIMEDOUT:number;const WSAECONNREFUSED:number;const WSAELOOP:number;const WSAENAMETOOLONG:number;const WSAEHOSTDOWN:number;const WSAEHOSTUNREACH:number;const WSAENOTEMPTY:number;const WSAEPROCLIM:number;const WSAEUSERS:number;const WSAEDQUOT:number;const WSAESTALE:number;const WSAEREMOTE:number;const WSASYSNOTREADY:number;const WSAVERNOTSUPPORTED:number;const WSANOTINITIALISED:number;const WSAEDISCON:number;const WSAENOMORE:number;const WSAECANCELLED:number;const WSAEINVALIDPROCTABLE:number;const WSAEINVALIDPROVIDER:number;const WSAEPROVIDERFAILEDINIT:number;const WSASYSCALLFAILURE:number;const WSASERVICE_NOT_FOUND:number;const WSATYPE_NOT_FOUND:number;const WSA_E_NO_MORE:number;const WSA_E_CANCELLED:number;const WSAEREFUSED:number;}namespace priority{const PRIORITY_LOW:number;const PRIORITY_BELOW_NORMAL:number;const PRIORITY_NORMAL:number;const PRIORITY_ABOVE_NORMAL:number;const PRIORITY_HIGH:number;const PRIORITY_HIGHEST:number;}}function arch():string;function version():string;function platform():NodeJS.Platform;function tmpdir():string;const EOL:string;function endianness():"BE"|"LE";function getPriority(pid?:number):number;function setPriority(priority:number):void;function setPriority(pid:number,priority:number):void;}
/* NOTE: Do not edit directly! This file is generated using `npm run update-types` in https://github.com/node-red/nr-monaco-build */
declare module 'os' {
interface CpuInfo {
model: string;
speed: number;
times: {
user: number;
nice: number;
sys: number;
idle: number;
irq: number;
};
}
interface NetworkInterfaceBase {
address: string;
netmask: string;
mac: string;
internal: boolean;
cidr: string | null;
}
interface NetworkInterfaceInfoIPv4 extends NetworkInterfaceBase {
family: "IPv4";
}
interface NetworkInterfaceInfoIPv6 extends NetworkInterfaceBase {
family: "IPv6";
scopeid: number;
}
interface UserInfo<T> {
username: T;
uid: number;
gid: number;
shell: T;
homedir: T;
}
type NetworkInterfaceInfo = NetworkInterfaceInfoIPv4 | NetworkInterfaceInfoIPv6;
function hostname(): string;
function loadavg(): number[];
function uptime(): number;
function freemem(): number;
function totalmem(): number;
function cpus(): CpuInfo[];
function type(): string;
function release(): string;
function networkInterfaces(): NodeJS.Dict<NetworkInterfaceInfo[]>;
function homedir(): string;
function userInfo(options: { encoding: 'buffer' }): UserInfo<Buffer>;
function userInfo(options?: { encoding: BufferEncoding }): UserInfo<string>;
type SignalConstants = {
[key in NodeJS.Signals]: number;
};
namespace constants {
const UV_UDP_REUSEADDR: number;
namespace signals {}
const signals: SignalConstants;
namespace errno {
const E2BIG: number;
const EACCES: number;
const EADDRINUSE: number;
const EADDRNOTAVAIL: number;
const EAFNOSUPPORT: number;
const EAGAIN: number;
const EALREADY: number;
const EBADF: number;
const EBADMSG: number;
const EBUSY: number;
const ECANCELED: number;
const ECHILD: number;
const ECONNABORTED: number;
const ECONNREFUSED: number;
const ECONNRESET: number;
const EDEADLK: number;
const EDESTADDRREQ: number;
const EDOM: number;
const EDQUOT: number;
const EEXIST: number;
const EFAULT: number;
const EFBIG: number;
const EHOSTUNREACH: number;
const EIDRM: number;
const EILSEQ: number;
const EINPROGRESS: number;
const EINTR: number;
const EINVAL: number;
const EIO: number;
const EISCONN: number;
const EISDIR: number;
const ELOOP: number;
const EMFILE: number;
const EMLINK: number;
const EMSGSIZE: number;
const EMULTIHOP: number;
const ENAMETOOLONG: number;
const ENETDOWN: number;
const ENETRESET: number;
const ENETUNREACH: number;
const ENFILE: number;
const ENOBUFS: number;
const ENODATA: number;
const ENODEV: number;
const ENOENT: number;
const ENOEXEC: number;
const ENOLCK: number;
const ENOLINK: number;
const ENOMEM: number;
const ENOMSG: number;
const ENOPROTOOPT: number;
const ENOSPC: number;
const ENOSR: number;
const ENOSTR: number;
const ENOSYS: number;
const ENOTCONN: number;
const ENOTDIR: number;
const ENOTEMPTY: number;
const ENOTSOCK: number;
const ENOTSUP: number;
const ENOTTY: number;
const ENXIO: number;
const EOPNOTSUPP: number;
const EOVERFLOW: number;
const EPERM: number;
const EPIPE: number;
const EPROTO: number;
const EPROTONOSUPPORT: number;
const EPROTOTYPE: number;
const ERANGE: number;
const EROFS: number;
const ESPIPE: number;
const ESRCH: number;
const ESTALE: number;
const ETIME: number;
const ETIMEDOUT: number;
const ETXTBSY: number;
const EWOULDBLOCK: number;
const EXDEV: number;
const WSAEINTR: number;
const WSAEBADF: number;
const WSAEACCES: number;
const WSAEFAULT: number;
const WSAEINVAL: number;
const WSAEMFILE: number;
const WSAEWOULDBLOCK: number;
const WSAEINPROGRESS: number;
const WSAEALREADY: number;
const WSAENOTSOCK: number;
const WSAEDESTADDRREQ: number;
const WSAEMSGSIZE: number;
const WSAEPROTOTYPE: number;
const WSAENOPROTOOPT: number;
const WSAEPROTONOSUPPORT: number;
const WSAESOCKTNOSUPPORT: number;
const WSAEOPNOTSUPP: number;
const WSAEPFNOSUPPORT: number;
const WSAEAFNOSUPPORT: number;
const WSAEADDRINUSE: number;
const WSAEADDRNOTAVAIL: number;
const WSAENETDOWN: number;
const WSAENETUNREACH: number;
const WSAENETRESET: number;
const WSAECONNABORTED: number;
const WSAECONNRESET: number;
const WSAENOBUFS: number;
const WSAEISCONN: number;
const WSAENOTCONN: number;
const WSAESHUTDOWN: number;
const WSAETOOMANYREFS: number;
const WSAETIMEDOUT: number;
const WSAECONNREFUSED: number;
const WSAELOOP: number;
const WSAENAMETOOLONG: number;
const WSAEHOSTDOWN: number;
const WSAEHOSTUNREACH: number;
const WSAENOTEMPTY: number;
const WSAEPROCLIM: number;
const WSAEUSERS: number;
const WSAEDQUOT: number;
const WSAESTALE: number;
const WSAEREMOTE: number;
const WSASYSNOTREADY: number;
const WSAVERNOTSUPPORTED: number;
const WSANOTINITIALISED: number;
const WSAEDISCON: number;
const WSAENOMORE: number;
const WSAECANCELLED: number;
const WSAEINVALIDPROCTABLE: number;
const WSAEINVALIDPROVIDER: number;
const WSAEPROVIDERFAILEDINIT: number;
const WSASYSCALLFAILURE: number;
const WSASERVICE_NOT_FOUND: number;
const WSATYPE_NOT_FOUND: number;
const WSA_E_NO_MORE: number;
const WSA_E_CANCELLED: number;
const WSAEREFUSED: number;
}
namespace priority {
const PRIORITY_LOW: number;
const PRIORITY_BELOW_NORMAL: number;
const PRIORITY_NORMAL: number;
const PRIORITY_ABOVE_NORMAL: number;
const PRIORITY_HIGH: number;
const PRIORITY_HIGHEST: number;
}
}
function arch(): string;
/**
* Returns a string identifying the kernel version.
* On POSIX systems, the operating system release is determined by calling
* [uname(3)][]. On Windows, `pRtlGetVersion` is used, and if it is not available,
* `GetVersionExW()` will be used. See
* https://en.wikipedia.org/wiki/Uname#Examples for more information.
*/
function version(): string;
function platform(): NodeJS.Platform;
function tmpdir(): string;
const EOL: string;
function endianness(): "BE" | "LE";
/**
* Gets the priority of a process.
* Defaults to current process.
*/
function getPriority(pid?: number): number;
/**
* Sets the priority of the current process.
* @param priority Must be in range of -20 to 19
*/
function setPriority(priority: number): void;
/**
* Sets the priority of the process specified process.
* @param priority Must be in range of -20 to 19
*/
function setPriority(pid: number, priority: number): void;
}

View File

@ -1 +1,156 @@
declare module'node:path'{import path=require('path');export=path;}declare module'path'{namespace path{interface ParsedPath{root:string;dir:string;base:string;ext:string;name:string;}interface FormatInputPathObject{root?:string;dir?:string;base?:string;ext?:string;name?:string;}interface PlatformPath{normalize(p:string):string;join(...paths:string[]):string;resolve(...pathSegments:string[]):string;isAbsolute(p:string):boolean;relative(from:string,to:string):string;dirname(p:string):string;basename(p:string,ext?:string):string;extname(p:string):string;readonly sep:string;readonly delimiter:string;parse(p:string):ParsedPath;format(pP:FormatInputPathObject):string;toNamespacedPath(path:string):string;readonly posix:PlatformPath;readonly win32:PlatformPath;}}const path:path.PlatformPath;export=path;}
/* NOTE: Do not edit directly! This file is generated using `npm run update-types` in https://github.com/node-red/nr-monaco-build */
declare module 'path' {
namespace path {
/**
* A parsed path object generated by path.parse() or consumed by path.format().
*/
interface ParsedPath {
/**
* The root of the path such as '/' or 'c:\'
*/
root: string;
/**
* The full directory path such as '/home/user/dir' or 'c:\path\dir'
*/
dir: string;
/**
* The file name including extension (if any) such as 'index.html'
*/
base: string;
/**
* The file extension (if any) such as '.html'
*/
ext: string;
/**
* The file name without extension (if any) such as 'index'
*/
name: string;
}
interface FormatInputPathObject {
/**
* The root of the path such as '/' or 'c:\'
*/
root?: string | undefined;
/**
* The full directory path such as '/home/user/dir' or 'c:\path\dir'
*/
dir?: string | undefined;
/**
* The file name including extension (if any) such as 'index.html'
*/
base?: string | undefined;
/**
* The file extension (if any) such as '.html'
*/
ext?: string | undefined;
/**
* The file name without extension (if any) such as 'index'
*/
name?: string | undefined;
}
interface PlatformPath {
/**
* Normalize a string path, reducing '..' and '.' parts.
* When multiple slashes are found, they're replaced by a single one; when the path contains a trailing slash, it is preserved. On Windows backslashes are used.
*
* @param p string path to normalize.
*/
normalize(p: string): string;
/**
* Join all arguments together and normalize the resulting path.
* Arguments must be strings. In v0.8, non-string arguments were silently ignored. In v0.10 and up, an exception is thrown.
*
* @param paths paths to join.
*/
join(...paths: string[]): string;
/**
* The right-most parameter is considered {to}. Other parameters are considered an array of {from}.
*
* Starting from leftmost {from} parameter, resolves {to} to an absolute path.
*
* If {to} isn't already absolute, {from} arguments are prepended in right to left order,
* until an absolute path is found. If after using all {from} paths still no absolute path is found,
* the current working directory is used as well. The resulting path is normalized,
* and trailing slashes are removed unless the path gets resolved to the root directory.
*
* @param pathSegments string paths to join. Non-string arguments are ignored.
*/
resolve(...pathSegments: string[]): string;
/**
* Determines whether {path} is an absolute path. An absolute path will always resolve to the same location, regardless of the working directory.
*
* @param path path to test.
*/
isAbsolute(p: string): boolean;
/**
* Solve the relative path from {from} to {to}.
* At times we have two absolute paths, and we need to derive the relative path from one to the other. This is actually the reverse transform of path.resolve.
*/
relative(from: string, to: string): string;
/**
* Return the directory name of a path. Similar to the Unix dirname command.
*
* @param p the path to evaluate.
*/
dirname(p: string): string;
/**
* Return the last portion of a path. Similar to the Unix basename command.
* Often used to extract the file name from a fully qualified path.
*
* @param p the path to evaluate.
* @param ext optionally, an extension to remove from the result.
*/
basename(p: string, ext?: string): string;
/**
* Return the extension of the path, from the last '.' to end of string in the last portion of the path.
* If there is no '.' in the last portion of the path or the first character of it is '.', then it returns an empty string
*
* @param p the path to evaluate.
*/
extname(p: string): string;
/**
* The platform-specific file separator. '\\' or '/'.
*/
readonly sep: string;
/**
* The platform-specific file delimiter. ';' or ':'.
*/
readonly delimiter: string;
/**
* Returns an object from a path string - the opposite of format().
*
* @param pathString path to evaluate.
*/
parse(p: string): ParsedPath;
/**
* Returns a path string from an object - the opposite of parse().
*
* @param pathString path to evaluate.
*/
format(pP: FormatInputPathObject): string;
/**
* On Windows systems only, returns an equivalent namespace-prefixed path for the given path.
* If path is not a string, path will be returned without modifications.
* This method is meaningful only on Windows system.
* On POSIX systems, the method is non-operational and always returns path without modifications.
*/
toNamespacedPath(path: string): string;
/**
* Posix specific pathing.
* Same as parent object on posix.
*/
readonly posix: PlatformPath;
/**
* Windows specific pathing.
* Same as parent object on windows
*/
readonly win32: PlatformPath;
}
}
const path: path.PlatformPath;
export = path;
}

View File

@ -0,0 +1,274 @@
/* NOTE: Do not edit directly! This file is generated using `npm run update-types` in https://github.com/node-red/nr-monaco-build */
declare module 'perf_hooks' {
import { AsyncResource } from 'async_hooks';
type EntryType = 'node' | 'mark' | 'measure' | 'gc' | 'function' | 'http2' | 'http';
interface PerformanceEntry {
/**
* The total number of milliseconds elapsed for this entry.
* This value will not be meaningful for all Performance Entry types.
*/
readonly duration: number;
/**
* The name of the performance entry.
*/
readonly name: string;
/**
* The high resolution millisecond timestamp marking the starting time of the Performance Entry.
*/
readonly startTime: number;
/**
* The type of the performance entry.
* Currently it may be one of: 'node', 'mark', 'measure', 'gc', or 'function'.
*/
readonly entryType: EntryType;
/**
* When `performanceEntry.entryType` is equal to 'gc', `the performance.kind` property identifies
* the type of garbage collection operation that occurred.
* See perf_hooks.constants for valid values.
*/
readonly kind?: number | undefined;
/**
* When `performanceEntry.entryType` is equal to 'gc', the `performance.flags`
* property contains additional information about garbage collection operation.
* See perf_hooks.constants for valid values.
*/
readonly flags?: number | undefined;
}
interface PerformanceNodeTiming extends PerformanceEntry {
/**
* The high resolution millisecond timestamp at which the Node.js process completed bootstrap.
*/
readonly bootstrapComplete: number;
/**
* The high resolution millisecond timestamp at which the Node.js process completed bootstrapping.
* If bootstrapping has not yet finished, the property has the value of -1.
*/
readonly environment: number;
/**
* The high resolution millisecond timestamp at which the Node.js environment was initialized.
*/
readonly idleTime: number;
/**
* The high resolution millisecond timestamp of the amount of time the event loop has been idle
* within the event loop's event provider (e.g. `epoll_wait`). This does not take CPU usage
* into consideration. If the event loop has not yet started (e.g., in the first tick of the main script),
* the property has the value of 0.
*/
readonly loopExit: number;
/**
* The high resolution millisecond timestamp at which the Node.js event loop started.
* If the event loop has not yet started (e.g., in the first tick of the main script), the property has the value of -1.
*/
readonly loopStart: number;
/**
* The high resolution millisecond timestamp at which the V8 platform was initialized.
*/
readonly v8Start: number;
}
interface EventLoopUtilization {
idle: number;
active: number;
utilization: number;
}
interface Performance {
/**
* If name is not provided, removes all PerformanceMark objects from the Performance Timeline.
* If name is provided, removes only the named mark.
* @param name
*/
clearMarks(name?: string): void;
/**
* Creates a new PerformanceMark entry in the Performance Timeline.
* A PerformanceMark is a subclass of PerformanceEntry whose performanceEntry.entryType is always 'mark',
* and whose performanceEntry.duration is always 0.
* Performance marks are used to mark specific significant moments in the Performance Timeline.
* @param name
*/
mark(name?: string): void;
/**
* Creates a new PerformanceMeasure entry in the Performance Timeline.
* A PerformanceMeasure is a subclass of PerformanceEntry whose performanceEntry.entryType is always 'measure',
* and whose performanceEntry.duration measures the number of milliseconds elapsed since startMark and endMark.
*
* The startMark argument may identify any existing PerformanceMark in the the Performance Timeline, or may identify
* any of the timestamp properties provided by the PerformanceNodeTiming class. If the named startMark does not exist,
* then startMark is set to timeOrigin by default.
*
* The endMark argument must identify any existing PerformanceMark in the the Performance Timeline or any of the timestamp
* properties provided by the PerformanceNodeTiming class. If the named endMark does not exist, an error will be thrown.
* @param name
* @param startMark
* @param endMark
*/
measure(name: string, startMark?: string, endMark?: string): void;
/**
* An instance of the PerformanceNodeTiming class that provides performance metrics for specific Node.js operational milestones.
*/
readonly nodeTiming: PerformanceNodeTiming;
/**
* @return the current high resolution millisecond timestamp
*/
now(): number;
/**
* The timeOrigin specifies the high resolution millisecond timestamp from which all performance metric durations are measured.
*/
readonly timeOrigin: number;
/**
* Wraps a function within a new function that measures the running time of the wrapped function.
* A PerformanceObserver must be subscribed to the 'function' event type in order for the timing details to be accessed.
* @param fn
*/
timerify<T extends (...optionalParams: any[]) => any>(fn: T): T;
/**
* eventLoopUtilization is similar to CPU utilization except that it is calculated using high precision wall-clock time.
* It represents the percentage of time the event loop has spent outside the event loop's event provider (e.g. epoll_wait).
* No other CPU idle time is taken into consideration.
*
* @param util1 The result of a previous call to eventLoopUtilization()
* @param util2 The result of a previous call to eventLoopUtilization() prior to util1
*/
eventLoopUtilization(util1?: EventLoopUtilization, util2?: EventLoopUtilization): EventLoopUtilization;
}
interface PerformanceObserverEntryList {
/**
* @return a list of PerformanceEntry objects in chronological order with respect to performanceEntry.startTime.
*/
getEntries(): PerformanceEntry[];
/**
* @return a list of PerformanceEntry objects in chronological order with respect to performanceEntry.startTime
* whose performanceEntry.name is equal to name, and optionally, whose performanceEntry.entryType is equal to type.
*/
getEntriesByName(name: string, type?: EntryType): PerformanceEntry[];
/**
* @return Returns a list of PerformanceEntry objects in chronological order with respect to performanceEntry.startTime
* whose performanceEntry.entryType is equal to type.
*/
getEntriesByType(type: EntryType): PerformanceEntry[];
}
type PerformanceObserverCallback = (list: PerformanceObserverEntryList, observer: PerformanceObserver) => void;
class PerformanceObserver extends AsyncResource {
constructor(callback: PerformanceObserverCallback);
/**
* Disconnects the PerformanceObserver instance from all notifications.
*/
disconnect(): void;
/**
* Subscribes the PerformanceObserver instance to notifications of new PerformanceEntry instances identified by options.entryTypes.
* When options.buffered is false, the callback will be invoked once for every PerformanceEntry instance.
* Property buffered defaults to false.
* @param options
*/
observe(options: { entryTypes: ReadonlyArray<EntryType>; buffered?: boolean | undefined }): void;
}
namespace constants {
const NODE_PERFORMANCE_GC_MAJOR: number;
const NODE_PERFORMANCE_GC_MINOR: number;
const NODE_PERFORMANCE_GC_INCREMENTAL: number;
const NODE_PERFORMANCE_GC_WEAKCB: number;
const NODE_PERFORMANCE_GC_FLAGS_NO: number;
const NODE_PERFORMANCE_GC_FLAGS_CONSTRUCT_RETAINED: number;
const NODE_PERFORMANCE_GC_FLAGS_FORCED: number;
const NODE_PERFORMANCE_GC_FLAGS_SYNCHRONOUS_PHANTOM_PROCESSING: number;
const NODE_PERFORMANCE_GC_FLAGS_ALL_AVAILABLE_GARBAGE: number;
const NODE_PERFORMANCE_GC_FLAGS_ALL_EXTERNAL_MEMORY: number;
const NODE_PERFORMANCE_GC_FLAGS_SCHEDULE_IDLE: number;
}
const performance: Performance;
interface EventLoopMonitorOptions {
/**
* The sampling rate in milliseconds.
* Must be greater than zero.
* @default 10
*/
resolution?: number | undefined;
}
interface EventLoopDelayMonitor {
/**
* Enables the event loop delay sample timer. Returns `true` if the timer was started, `false` if it was already started.
*/
enable(): boolean;
/**
* Disables the event loop delay sample timer. Returns `true` if the timer was stopped, `false` if it was already stopped.
*/
disable(): boolean;
/**
* Resets the collected histogram data.
*/
reset(): void;
/**
* Returns the value at the given percentile.
* @param percentile A percentile value between 1 and 100.
*/
percentile(percentile: number): number;
/**
* A `Map` object detailing the accumulated percentile distribution.
*/
readonly percentiles: Map<number, number>;
/**
* The number of times the event loop delay exceeded the maximum 1 hour eventloop delay threshold.
*/
readonly exceeds: number;
/**
* The minimum recorded event loop delay.
*/
readonly min: number;
/**
* The maximum recorded event loop delay.
*/
readonly max: number;
/**
* The mean of the recorded event loop delays.
*/
readonly mean: number;
/**
* The standard deviation of the recorded event loop delays.
*/
readonly stddev: number;
}
function monitorEventLoopDelay(options?: EventLoopMonitorOptions): EventLoopDelayMonitor;
}

File diff suppressed because one or more lines are too long

View File

@ -1 +1,31 @@
declare module'node:querystring'{export*from'querystring';}declare module'querystring'{interface StringifyOptions{encodeURIComponent?:(str:string)=>string;}interface ParseOptions{maxKeys?:number;decodeURIComponent?:(str:string)=>string;}interface ParsedUrlQuery extends NodeJS.Dict<string|string[]>{}interface ParsedUrlQueryInput extends NodeJS.Dict<string|number|boolean|ReadonlyArray<string>|ReadonlyArray<number>|ReadonlyArray<boolean>|null>{}function stringify(obj?:ParsedUrlQueryInput,sep?:string,eq?:string,options?:StringifyOptions):string;function parse(str:string,sep?:string,eq?:string,options?:ParseOptions):ParsedUrlQuery;const encode:typeof stringify;const decode:typeof parse;function escape(str:string):string;function unescape(str:string):string;}
/* NOTE: Do not edit directly! This file is generated using `npm run update-types` in https://github.com/node-red/nr-monaco-build */
declare module 'querystring' {
interface StringifyOptions {
encodeURIComponent?: ((str: string) => string) | undefined;
}
interface ParseOptions {
maxKeys?: number | undefined;
decodeURIComponent?: ((str: string) => string) | undefined;
}
interface ParsedUrlQuery extends NodeJS.Dict<string | string[]> { }
interface ParsedUrlQueryInput extends NodeJS.Dict<string | number | boolean | ReadonlyArray<string> | ReadonlyArray<number> | ReadonlyArray<boolean> | null> {
}
function stringify(obj?: ParsedUrlQueryInput, sep?: string, eq?: string, options?: StringifyOptions): string;
function parse(str: string, sep?: string, eq?: string, options?: ParseOptions): ParsedUrlQuery;
/**
* The querystring.encode() function is an alias for querystring.stringify().
*/
const encode: typeof stringify;
/**
* The querystring.decode() function is an alias for querystring.parse().
*/
const decode: typeof parse;
function escape(str: string): string;
function unescape(str: string): string;
}

View File

@ -0,0 +1,173 @@
/* NOTE: Do not edit directly! This file is generated using `npm run update-types` in https://github.com/node-red/nr-monaco-build */
declare module 'readline' {
import EventEmitter = require('events');
interface Key {
sequence?: string | undefined;
name?: string | undefined;
ctrl?: boolean | undefined;
meta?: boolean | undefined;
shift?: boolean | undefined;
}
class Interface extends EventEmitter {
readonly terminal: boolean;
// Need direct access to line/cursor data, for use in external processes
// see: https://github.com/nodejs/node/issues/30347
/** The current input data */
readonly line: string;
/** The current cursor position in the input line */
readonly cursor: number;
/**
* NOTE: According to the documentation:
*
* > Instances of the `readline.Interface` class are constructed using the
* > `readline.createInterface()` method.
*
* @see https://nodejs.org/dist/latest-v10.x/docs/api/readline.html#readline_class_interface
*/
protected constructor(input: NodeJS.ReadableStream, output?: NodeJS.WritableStream, completer?: Completer | AsyncCompleter, terminal?: boolean);
/**
* NOTE: According to the documentation:
*
* > Instances of the `readline.Interface` class are constructed using the
* > `readline.createInterface()` method.
*
* @see https://nodejs.org/dist/latest-v10.x/docs/api/readline.html#readline_class_interface
*/
protected constructor(options: ReadLineOptions);
setPrompt(prompt: string): void;
prompt(preserveCursor?: boolean): void;
question(query: string, callback: (answer: string) => void): void;
pause(): this;
resume(): this;
close(): void;
write(data: string | Buffer, key?: Key): void;
/**
* Returns the real position of the cursor in relation to the input
* prompt + string. Long input (wrapping) strings, as well as multiple
* line prompts are included in the calculations.
*/
getCursorPos(): CursorPos;
/**
* events.EventEmitter
* 1. close
* 2. line
* 3. pause
* 4. resume
* 5. SIGCONT
* 6. SIGINT
* 7. SIGTSTP
*/
addListener(event: string, listener: (...args: any[]) => void): this;
addListener(event: "close", listener: () => void): this;
addListener(event: "line", listener: (input: string) => void): this;
addListener(event: "pause", listener: () => void): this;
addListener(event: "resume", listener: () => void): this;
addListener(event: "SIGCONT", listener: () => void): this;
addListener(event: "SIGINT", listener: () => void): this;
addListener(event: "SIGTSTP", listener: () => void): this;
emit(event: string | symbol, ...args: any[]): boolean;
emit(event: "close"): boolean;
emit(event: "line", input: string): boolean;
emit(event: "pause"): boolean;
emit(event: "resume"): boolean;
emit(event: "SIGCONT"): boolean;
emit(event: "SIGINT"): boolean;
emit(event: "SIGTSTP"): boolean;
on(event: string, listener: (...args: any[]) => void): this;
on(event: "close", listener: () => void): this;
on(event: "line", listener: (input: string) => void): this;
on(event: "pause", listener: () => void): this;
on(event: "resume", listener: () => void): this;
on(event: "SIGCONT", listener: () => void): this;
on(event: "SIGINT", listener: () => void): this;
on(event: "SIGTSTP", listener: () => void): this;
once(event: string, listener: (...args: any[]) => void): this;
once(event: "close", listener: () => void): this;
once(event: "line", listener: (input: string) => void): this;
once(event: "pause", listener: () => void): this;
once(event: "resume", listener: () => void): this;
once(event: "SIGCONT", listener: () => void): this;
once(event: "SIGINT", listener: () => void): this;
once(event: "SIGTSTP", listener: () => void): this;
prependListener(event: string, listener: (...args: any[]) => void): this;
prependListener(event: "close", listener: () => void): this;
prependListener(event: "line", listener: (input: string) => void): this;
prependListener(event: "pause", listener: () => void): this;
prependListener(event: "resume", listener: () => void): this;
prependListener(event: "SIGCONT", listener: () => void): this;
prependListener(event: "SIGINT", listener: () => void): this;
prependListener(event: "SIGTSTP", listener: () => void): this;
prependOnceListener(event: string, listener: (...args: any[]) => void): this;
prependOnceListener(event: "close", listener: () => void): this;
prependOnceListener(event: "line", listener: (input: string) => void): this;
prependOnceListener(event: "pause", listener: () => void): this;
prependOnceListener(event: "resume", listener: () => void): this;
prependOnceListener(event: "SIGCONT", listener: () => void): this;
prependOnceListener(event: "SIGINT", listener: () => void): this;
prependOnceListener(event: "SIGTSTP", listener: () => void): this;
[Symbol.asyncIterator](): AsyncIterableIterator<string>;
}
type ReadLine = Interface; // type forwarded for backwards compatibility
type Completer = (line: string) => CompleterResult;
type AsyncCompleter = (line: string, callback: (err?: null | Error, result?: CompleterResult) => void) => any;
type CompleterResult = [string[], string];
interface ReadLineOptions {
input: NodeJS.ReadableStream;
output?: NodeJS.WritableStream | undefined;
completer?: Completer | AsyncCompleter | undefined;
terminal?: boolean | undefined;
historySize?: number | undefined;
prompt?: string | undefined;
crlfDelay?: number | undefined;
removeHistoryDuplicates?: boolean | undefined;
escapeCodeTimeout?: number | undefined;
tabSize?: number | undefined;
}
function createInterface(input: NodeJS.ReadableStream, output?: NodeJS.WritableStream, completer?: Completer | AsyncCompleter, terminal?: boolean): Interface;
function createInterface(options: ReadLineOptions): Interface;
function emitKeypressEvents(stream: NodeJS.ReadableStream, readlineInterface?: Interface): void;
type Direction = -1 | 0 | 1;
interface CursorPos {
rows: number;
cols: number;
}
/**
* Clears the current line of this WriteStream in a direction identified by `dir`.
*/
function clearLine(stream: NodeJS.WritableStream, dir: Direction, callback?: () => void): boolean;
/**
* Clears this `WriteStream` from the current cursor down.
*/
function clearScreenDown(stream: NodeJS.WritableStream, callback?: () => void): boolean;
/**
* Moves this WriteStream's cursor to the specified position.
*/
function cursorTo(stream: NodeJS.WritableStream, x: number, y?: number, callback?: () => void): boolean;
/**
* Moves this WriteStream's cursor relative to its current position.
*/
function moveCursor(stream: NodeJS.WritableStream, dx: number, dy: number, callback?: () => void): boolean;
}

View File

@ -0,0 +1,358 @@
/* NOTE: Do not edit directly! This file is generated using `npm run update-types` in https://github.com/node-red/nr-monaco-build */
declare module 'stream' {
import EventEmitter = require('events');
class internal extends EventEmitter {
pipe<T extends NodeJS.WritableStream>(destination: T, options?: { end?: boolean | undefined; }): T;
}
namespace internal {
class Stream extends internal {
constructor(opts?: ReadableOptions);
}
interface ReadableOptions {
highWaterMark?: number | undefined;
encoding?: BufferEncoding | undefined;
objectMode?: boolean | undefined;
read?(this: Readable, size: number): void;
destroy?(this: Readable, error: Error | null, callback: (error: Error | null) => void): void;
autoDestroy?: boolean | undefined;
}
class Readable extends Stream implements NodeJS.ReadableStream {
/**
* A utility method for creating Readable Streams out of iterators.
*/
static from(iterable: Iterable<any> | AsyncIterable<any>, options?: ReadableOptions): Readable;
readable: boolean;
readonly readableEncoding: BufferEncoding | null;
readonly readableEnded: boolean;
readonly readableFlowing: boolean | null;
readonly readableHighWaterMark: number;
readonly readableLength: number;
readonly readableObjectMode: boolean;
destroyed: boolean;
constructor(opts?: ReadableOptions);
_read(size: number): void;
read(size?: number): any;
setEncoding(encoding: BufferEncoding): this;
pause(): this;
resume(): this;
isPaused(): boolean;
unpipe(destination?: NodeJS.WritableStream): this;
unshift(chunk: any, encoding?: BufferEncoding): void;
wrap(oldStream: NodeJS.ReadableStream): this;
push(chunk: any, encoding?: BufferEncoding): boolean;
_destroy(error: Error | null, callback: (error?: Error | null) => void): void;
destroy(error?: Error): void;
/**
* Event emitter
* The defined events on documents including:
* 1. close
* 2. data
* 3. end
* 4. error
* 5. pause
* 6. readable
* 7. resume
*/
addListener(event: "close", listener: () => void): this;
addListener(event: "data", listener: (chunk: any) => void): this;
addListener(event: "end", listener: () => void): this;
addListener(event: "error", listener: (err: Error) => void): this;
addListener(event: "pause", listener: () => void): this;
addListener(event: "readable", listener: () => void): this;
addListener(event: "resume", listener: () => void): this;
addListener(event: string | symbol, listener: (...args: any[]) => void): this;
emit(event: "close"): boolean;
emit(event: "data", chunk: any): boolean;
emit(event: "end"): boolean;
emit(event: "error", err: Error): boolean;
emit(event: "pause"): boolean;
emit(event: "readable"): boolean;
emit(event: "resume"): boolean;
emit(event: string | symbol, ...args: any[]): boolean;
on(event: "close", listener: () => void): this;
on(event: "data", listener: (chunk: any) => void): this;
on(event: "end", listener: () => void): this;
on(event: "error", listener: (err: Error) => void): this;
on(event: "pause", listener: () => void): this;
on(event: "readable", listener: () => void): this;
on(event: "resume", listener: () => void): this;
on(event: string | symbol, listener: (...args: any[]) => void): this;
once(event: "close", listener: () => void): this;
once(event: "data", listener: (chunk: any) => void): this;
once(event: "end", listener: () => void): this;
once(event: "error", listener: (err: Error) => void): this;
once(event: "pause", listener: () => void): this;
once(event: "readable", listener: () => void): this;
once(event: "resume", listener: () => void): this;
once(event: string | symbol, listener: (...args: any[]) => void): this;
prependListener(event: "close", listener: () => void): this;
prependListener(event: "data", listener: (chunk: any) => void): this;
prependListener(event: "end", listener: () => void): this;
prependListener(event: "error", listener: (err: Error) => void): this;
prependListener(event: "pause", listener: () => void): this;
prependListener(event: "readable", listener: () => void): this;
prependListener(event: "resume", listener: () => void): this;
prependListener(event: string | symbol, listener: (...args: any[]) => void): this;
prependOnceListener(event: "close", listener: () => void): this;
prependOnceListener(event: "data", listener: (chunk: any) => void): this;
prependOnceListener(event: "end", listener: () => void): this;
prependOnceListener(event: "error", listener: (err: Error) => void): this;
prependOnceListener(event: "pause", listener: () => void): this;
prependOnceListener(event: "readable", listener: () => void): this;
prependOnceListener(event: "resume", listener: () => void): this;
prependOnceListener(event: string | symbol, listener: (...args: any[]) => void): this;
removeListener(event: "close", listener: () => void): this;
removeListener(event: "data", listener: (chunk: any) => void): this;
removeListener(event: "end", listener: () => void): this;
removeListener(event: "error", listener: (err: Error) => void): this;
removeListener(event: "pause", listener: () => void): this;
removeListener(event: "readable", listener: () => void): this;
removeListener(event: "resume", listener: () => void): this;
removeListener(event: string | symbol, listener: (...args: any[]) => void): this;
[Symbol.asyncIterator](): AsyncIterableIterator<any>;
}
interface WritableOptions {
highWaterMark?: number | undefined;
decodeStrings?: boolean | undefined;
defaultEncoding?: BufferEncoding | undefined;
objectMode?: boolean | undefined;
emitClose?: boolean | undefined;
write?(this: Writable, chunk: any, encoding: BufferEncoding, callback: (error?: Error | null) => void): void;
writev?(this: Writable, chunks: Array<{ chunk: any, encoding: BufferEncoding }>, callback: (error?: Error | null) => void): void;
destroy?(this: Writable, error: Error | null, callback: (error: Error | null) => void): void;
final?(this: Writable, callback: (error?: Error | null) => void): void;
autoDestroy?: boolean | undefined;
}
class Writable extends Stream implements NodeJS.WritableStream {
readonly writable: boolean;
readonly writableEnded: boolean;
readonly writableFinished: boolean;
readonly writableHighWaterMark: number;
readonly writableLength: number;
readonly writableObjectMode: boolean;
readonly writableCorked: number;
destroyed: boolean;
constructor(opts?: WritableOptions);
_write(chunk: any, encoding: BufferEncoding, callback: (error?: Error | null) => void): void;
_writev?(chunks: Array<{ chunk: any, encoding: BufferEncoding }>, callback: (error?: Error | null) => void): void;
_destroy(error: Error | null, callback: (error?: Error | null) => void): void;
_final(callback: (error?: Error | null) => void): void;
write(chunk: any, cb?: (error: Error | null | undefined) => void): boolean;
write(chunk: any, encoding: BufferEncoding, cb?: (error: Error | null | undefined) => void): boolean;
setDefaultEncoding(encoding: BufferEncoding): this;
end(cb?: () => void): void;
end(chunk: any, cb?: () => void): void;
end(chunk: any, encoding: BufferEncoding, cb?: () => void): void;
cork(): void;
uncork(): void;
destroy(error?: Error): void;
/**
* Event emitter
* The defined events on documents including:
* 1. close
* 2. drain
* 3. error
* 4. finish
* 5. pipe
* 6. unpipe
*/
addListener(event: "close", listener: () => void): this;
addListener(event: "drain", listener: () => void): this;
addListener(event: "error", listener: (err: Error) => void): this;
addListener(event: "finish", listener: () => void): this;
addListener(event: "pipe", listener: (src: Readable) => void): this;
addListener(event: "unpipe", listener: (src: Readable) => void): this;
addListener(event: string | symbol, listener: (...args: any[]) => void): this;
emit(event: "close"): boolean;
emit(event: "drain"): boolean;
emit(event: "error", err: Error): boolean;
emit(event: "finish"): boolean;
emit(event: "pipe", src: Readable): boolean;
emit(event: "unpipe", src: Readable): boolean;
emit(event: string | symbol, ...args: any[]): boolean;
on(event: "close", listener: () => void): this;
on(event: "drain", listener: () => void): this;
on(event: "error", listener: (err: Error) => void): this;
on(event: "finish", listener: () => void): this;
on(event: "pipe", listener: (src: Readable) => void): this;
on(event: "unpipe", listener: (src: Readable) => void): this;
on(event: string | symbol, listener: (...args: any[]) => void): this;
once(event: "close", listener: () => void): this;
once(event: "drain", listener: () => void): this;
once(event: "error", listener: (err: Error) => void): this;
once(event: "finish", listener: () => void): this;
once(event: "pipe", listener: (src: Readable) => void): this;
once(event: "unpipe", listener: (src: Readable) => void): this;
once(event: string | symbol, listener: (...args: any[]) => void): this;
prependListener(event: "close", listener: () => void): this;
prependListener(event: "drain", listener: () => void): this;
prependListener(event: "error", listener: (err: Error) => void): this;
prependListener(event: "finish", listener: () => void): this;
prependListener(event: "pipe", listener: (src: Readable) => void): this;
prependListener(event: "unpipe", listener: (src: Readable) => void): this;
prependListener(event: string | symbol, listener: (...args: any[]) => void): this;
prependOnceListener(event: "close", listener: () => void): this;
prependOnceListener(event: "drain", listener: () => void): this;
prependOnceListener(event: "error", listener: (err: Error) => void): this;
prependOnceListener(event: "finish", listener: () => void): this;
prependOnceListener(event: "pipe", listener: (src: Readable) => void): this;
prependOnceListener(event: "unpipe", listener: (src: Readable) => void): this;
prependOnceListener(event: string | symbol, listener: (...args: any[]) => void): this;
removeListener(event: "close", listener: () => void): this;
removeListener(event: "drain", listener: () => void): this;
removeListener(event: "error", listener: (err: Error) => void): this;
removeListener(event: "finish", listener: () => void): this;
removeListener(event: "pipe", listener: (src: Readable) => void): this;
removeListener(event: "unpipe", listener: (src: Readable) => void): this;
removeListener(event: string | symbol, listener: (...args: any[]) => void): this;
}
interface DuplexOptions extends ReadableOptions, WritableOptions {
allowHalfOpen?: boolean | undefined;
readableObjectMode?: boolean | undefined;
writableObjectMode?: boolean | undefined;
readableHighWaterMark?: number | undefined;
writableHighWaterMark?: number | undefined;
writableCorked?: number | undefined;
read?(this: Duplex, size: number): void;
write?(this: Duplex, chunk: any, encoding: BufferEncoding, callback: (error?: Error | null) => void): void;
writev?(this: Duplex, chunks: Array<{ chunk: any, encoding: BufferEncoding }>, callback: (error?: Error | null) => void): void;
final?(this: Duplex, callback: (error?: Error | null) => void): void;
destroy?(this: Duplex, error: Error | null, callback: (error: Error | null) => void): void;
}
// Note: Duplex extends both Readable and Writable.
class Duplex extends Readable implements Writable {
readonly writable: boolean;
readonly writableEnded: boolean;
readonly writableFinished: boolean;
readonly writableHighWaterMark: number;
readonly writableLength: number;
readonly writableObjectMode: boolean;
readonly writableCorked: number;
allowHalfOpen: boolean;
constructor(opts?: DuplexOptions);
_write(chunk: any, encoding: BufferEncoding, callback: (error?: Error | null) => void): void;
_writev?(chunks: Array<{ chunk: any, encoding: BufferEncoding }>, callback: (error?: Error | null) => void): void;
_destroy(error: Error | null, callback: (error: Error | null) => void): void;
_final(callback: (error?: Error | null) => void): void;
write(chunk: any, encoding?: BufferEncoding, cb?: (error: Error | null | undefined) => void): boolean;
write(chunk: any, cb?: (error: Error | null | undefined) => void): boolean;
setDefaultEncoding(encoding: BufferEncoding): this;
end(cb?: () => void): void;
end(chunk: any, cb?: () => void): void;
end(chunk: any, encoding?: BufferEncoding, cb?: () => void): void;
cork(): void;
uncork(): void;
}
type TransformCallback = (error?: Error | null, data?: any) => void;
interface TransformOptions extends DuplexOptions {
read?(this: Transform, size: number): void;
write?(this: Transform, chunk: any, encoding: BufferEncoding, callback: (error?: Error | null) => void): void;
writev?(this: Transform, chunks: Array<{ chunk: any, encoding: BufferEncoding }>, callback: (error?: Error | null) => void): void;
final?(this: Transform, callback: (error?: Error | null) => void): void;
destroy?(this: Transform, error: Error | null, callback: (error: Error | null) => void): void;
transform?(this: Transform, chunk: any, encoding: BufferEncoding, callback: TransformCallback): void;
flush?(this: Transform, callback: TransformCallback): void;
}
class Transform extends Duplex {
constructor(opts?: TransformOptions);
_transform(chunk: any, encoding: BufferEncoding, callback: TransformCallback): void;
_flush(callback: TransformCallback): void;
}
class PassThrough extends Transform { }
interface FinishedOptions {
error?: boolean | undefined;
readable?: boolean | undefined;
writable?: boolean | undefined;
}
function finished(stream: NodeJS.ReadableStream | NodeJS.WritableStream | NodeJS.ReadWriteStream, options: FinishedOptions, callback: (err?: NodeJS.ErrnoException | null) => void): () => void;
function finished(stream: NodeJS.ReadableStream | NodeJS.WritableStream | NodeJS.ReadWriteStream, callback: (err?: NodeJS.ErrnoException | null) => void): () => void;
namespace finished {
function __promisify__(stream: NodeJS.ReadableStream | NodeJS.WritableStream | NodeJS.ReadWriteStream, options?: FinishedOptions): Promise<void>;
}
function pipeline<T extends NodeJS.WritableStream>(stream1: NodeJS.ReadableStream, stream2: T, callback?: (err: NodeJS.ErrnoException | null) => void): T;
function pipeline<T extends NodeJS.WritableStream>(stream1: NodeJS.ReadableStream, stream2: NodeJS.ReadWriteStream, stream3: T, callback?: (err: NodeJS.ErrnoException | null) => void): T;
function pipeline<T extends NodeJS.WritableStream>(
stream1: NodeJS.ReadableStream,
stream2: NodeJS.ReadWriteStream,
stream3: NodeJS.ReadWriteStream,
stream4: T,
callback?: (err: NodeJS.ErrnoException | null) => void,
): T;
function pipeline<T extends NodeJS.WritableStream>(
stream1: NodeJS.ReadableStream,
stream2: NodeJS.ReadWriteStream,
stream3: NodeJS.ReadWriteStream,
stream4: NodeJS.ReadWriteStream,
stream5: T,
callback?: (err: NodeJS.ErrnoException | null) => void,
): T;
function pipeline(
streams: ReadonlyArray<NodeJS.ReadableStream | NodeJS.WritableStream | NodeJS.ReadWriteStream>,
callback?: (err: NodeJS.ErrnoException | null) => void,
): NodeJS.WritableStream;
function pipeline(
stream1: NodeJS.ReadableStream,
stream2: NodeJS.ReadWriteStream | NodeJS.WritableStream,
...streams: Array<NodeJS.ReadWriteStream | NodeJS.WritableStream | ((err: NodeJS.ErrnoException | null) => void)>,
): NodeJS.WritableStream;
namespace pipeline {
function __promisify__(stream1: NodeJS.ReadableStream, stream2: NodeJS.WritableStream): Promise<void>;
function __promisify__(stream1: NodeJS.ReadableStream, stream2: NodeJS.ReadWriteStream, stream3: NodeJS.WritableStream): Promise<void>;
function __promisify__(stream1: NodeJS.ReadableStream, stream2: NodeJS.ReadWriteStream, stream3: NodeJS.ReadWriteStream, stream4: NodeJS.WritableStream): Promise<void>;
function __promisify__(
stream1: NodeJS.ReadableStream,
stream2: NodeJS.ReadWriteStream,
stream3: NodeJS.ReadWriteStream,
stream4: NodeJS.ReadWriteStream,
stream5: NodeJS.WritableStream,
): Promise<void>;
function __promisify__(streams: ReadonlyArray<NodeJS.ReadableStream | NodeJS.WritableStream | NodeJS.ReadWriteStream>): Promise<void>;
function __promisify__(
stream1: NodeJS.ReadableStream,
stream2: NodeJS.ReadWriteStream | NodeJS.WritableStream,
...streams: Array<NodeJS.ReadWriteStream | NodeJS.WritableStream>,
): Promise<void>;
}
interface Pipe {
close(): void;
hasRef(): boolean;
ref(): void;
unref(): void;
}
}
export = internal;
}

Some files were not shown because too many files have changed in this diff Show More