Compare commits

...

352 Commits

Author SHA1 Message Date
Nick O'Leary
813b457ba9 Add a node annotation if there info property set 2024-11-12 16:53:05 +00:00
Nick O'Leary
1d9586721e Merge pull request #4948 from node-red/pr_4935
Add a new `update available` widget to statusBar
2024-11-11 13:37:20 +00:00
Nick O'Leary
4ff748c1c1 Simplify error reporting 2024-11-08 16:46:19 +00:00
Nick O'Leary
99b3b65304 Merge pull request #4930 from node-red/monaco_0_52_0
Monaco Latest (0.52.0)
2024-11-08 15:44:44 +00:00
Nick O'Leary
a69a35aacf Separate catalogue refresh logic from UI creation 2024-11-08 15:29:03 +00:00
Nick O'Leary
d64fe36f6e Merge pull request #4937 from GogoVega/palette-queue
Add a queue while installing or removing a module from the Palette Manager
2024-11-08 13:45:51 +00:00
GogoVega
83c4ac5f65 Refresh the update status after all catalogs have been loaded
Co-authored-by: Nick O'Leary <nick.oleary@gmail.com>
2024-11-07 15:45:22 +01:00
GogoVega
69e4a02b28 Change icon, remove the widget color and ensure updateStatus is called on events 2024-11-07 15:32:06 +01:00
GogoVega
d048d2cf41 Fix update status after module updated 2024-10-30 22:36:14 +01:00
GogoVega
2f2162d531 startEvent must be called in the processQueue 2024-10-30 17:10:03 +01:00
GogoVega
245761ea03 Fix typo - bad tab to open 2024-10-30 16:09:26 +01:00
GogoVega
2b77590402 Add a queue while installing or removing a module 2024-10-30 15:54:42 +01:00
GogoVega
4248cb6205 Refresh status when registry changes + cleanup 2024-10-29 19:00:04 +01:00
GogoVega
48894d6a95 Add a new update available widget to statusBar 2024-10-29 15:36:49 +01:00
GogoVega
e5073cf374 Allow RED.statusBar to hide/show widget 2024-10-29 15:27:45 +01:00
Steve-Mcl
24c6f4d655 updates monaco to latest. Includes fix for action widget sizing 2024-10-28 11:03:29 +00:00
Nick O'Leary
83acc4836b Merge pull request #4768 from Rotzbua/fix_html_tags
fix(html): correct buggy html
2024-09-11 15:40:24 +01:00
Nick O'Leary
db51307e7f Merge branch 'dev' into fix_html_tags 2024-09-11 15:27:45 +01:00
Nick O'Leary
a2430b772b Merge pull request #4836 from node-red/update-dev
Update dev
2024-07-18 17:27:20 +01:00
Nick O'Leary
b3acd1a588 Merge branch 'master' into update-dev 2024-07-18 17:22:44 +01:00
Nick O'Leary
8af821d380 Merge pull request #4837 from node-red/knolleary-patch-1
Back off node 22.5
2024-07-18 17:22:32 +01:00
Nick O'Leary
97ee6c6745 Back off node 22.5 2024-07-18 17:17:50 +01:00
Nick O'Leary
b5fb15cd9b Merge pull request #4828 from GogoVega/fix-menu-selection
Fix menu to enable/disable selection when it's a group
2024-07-18 16:36:02 +01:00
Nick O'Leary
998219ae9a Merge pull request #4829 from node-red/Let-Batch-node-honour-parts-to-close-early
Let batch node terminate "early" if msg.parts set to end of sequence
2024-07-18 16:34:46 +01:00
Nick O'Leary
e8f0f80f65 Merge pull request #4835 from node-red/Fix-Split-Node-Name-Caps
Fix unintentional Capitalisation in Split node name
2024-07-18 16:33:48 +01:00
Nick O'Leary
45936285cc Bump dev to 4.1.0-beta.1 2024-07-18 16:32:12 +01:00
Dave Conway-Jones
ff35c46d5d Fix unintentianal Capitalisation in Split node
to close #4832
2024-07-16 14:37:16 +01:00
Dave Conway-Jones
05c924a9df Let batch node terminate "early" if msg.parts set to end of sequence
(ie index = count -1). Useful to close at end of files etc.
2024-07-04 15:09:55 +01:00
GogoVega
14ac309b6e Fix menu to enable/disable selection when it's a group 2024-07-02 11:38:56 +02:00
Nick O'Leary
29b128e5e0 Merge pull request #4825 from node-red/rel402
Bump for 4.0.2
2024-07-01 16:49:13 +01:00
Nick O'Leary
c0f1581370 Bump for 4.0.2 2024-07-01 16:38:28 +01:00
Nick O'Leary
9420a52ec7 Merge pull request #4818 from bonanitech/header-border
Use a more subtle border on the header
2024-07-01 12:52:09 +01:00
Mauricio Bonani
c113b3de13 Use a not-so-dark color for the header border 2024-07-01 06:18:17 -04:00
Mauricio Bonani
29058c163a Merge branch 'master' into header-border 2024-07-01 06:14:35 -04:00
Nick O'Leary
bb110ea230 Merge pull request #4824 from GogoVega/improve-french-translations
Improve the editor's French translations
2024-07-01 10:55:33 +01:00
Nick O'Leary
785f220cd8 Merge pull request #4821 from node-red/orphaned-monco-editors
Clean up orphaned editors
2024-07-01 10:48:49 +01:00
GogoVega
16570410a5 Improve French translations 2024-07-01 09:43:42 +02:00
GogoVega
8085eda431 Add missing French translations from v4 2024-06-30 22:27:38 +02:00
Steve-Mcl
6503498f0a Clean up orphaned editors
closes #4820
2024-06-29 18:14:54 +01:00
Nick O'Leary
da787a9993 Merge pull request #4812 from GogoVega/fix-required-prop
Fix node validation if the property is not required
2024-06-28 17:21:40 +01:00
Nick O'Leary
c873b57094 Merge pull request #4815 from node-red/update-cookie-auth
Allow auth cookie name to be customised
2024-06-28 16:58:36 +01:00
Nick O'Leary
93974ccd92 Merge pull request #4816 from node-red/4814-multiplayer-uncaught
Guard against undefined sessions in multiplayer
2024-06-28 16:58:25 +01:00
Nick O'Leary
d7aa792f97 Merge pull request #4817 from node-red/mermaid-caching
Ensure mermaid.min.js is cached properly between loads of the editor
2024-06-28 16:58:14 +01:00
Mauricio Bonani
375fa9da64 Use a more subtle border on the header 2024-06-28 09:51:23 -04:00
Nick O'Leary
28c41e17ad Ensure mermaid.min.js is cached properly between loads of the editor 2024-06-28 14:37:51 +01:00
Nick O'Leary
da3ad40968 Add more guards for undefined session 2024-06-28 14:19:18 +01:00
GogoVega
2464d9ad95 Check required prop for each case instead of top level 2024-06-28 14:15:51 +02:00
Nick O'Leary
011b47a108 Guard against undefined sessions in multiplayer 2024-06-28 11:41:05 +01:00
Nick O'Leary
ea747711c3 Allow auth cookie name to be customised 2024-06-28 10:24:51 +01:00
GogoVega
19a8fa09a8 Fix node validation if property is not required 2024-06-27 09:16:03 +02:00
Nick O'Leary
1b5b3f7f88 Merge pull request #4804 from node-red/rel401
Update for 4.0.1 release
2024-06-26 14:42:42 +01:00
Nick O'Leary
2123514c76 Update for 4.0.1 release 2024-06-26 14:38:28 +01:00
Nick O'Leary
379fbd7c7e Merge pull request #4803 from node-red/4798-include-groups-inflowapi
Ensure group nodes are properly exported in /flow api
2024-06-26 14:36:03 +01:00
Nick O'Leary
efdc1b1a1d Ensure group nodes are properly exported in /flow api 2024-06-26 14:30:33 +01:00
Nick O'Leary
52bbd82e18 Merge pull request #4802 from node-red/4801-fix-sf-instance-credentials
Ensure subflow instance credential property values are extracted
2024-06-26 11:57:31 +01:00
Nick O'Leary
20a9c051be Ensure subflow instance credential property values are extracted 2024-06-26 11:49:37 +01:00
Nick O'Leary
830e475969 Merge pull request #4800 from GogoVega/fix-config-select
Use `_ADD_` value for both `add new...` and `none` options
2024-06-26 10:51:39 +01:00
GogoVega
f75e2f221c Use _ADD_ value for add... and none options 2024-06-25 20:08:31 +02:00
Nick O'Leary
5a75440668 Merge pull request #4796 from node-red/Join-node-optional-use-of-parts
make using msg.parts optional in join node
2024-06-25 16:22:20 +01:00
Dave Conway-Jones
53d8b97fff join node - honour 3.x behaviour for old instances.
but don't use msg.parts for new instances in manual join mode unless set.
2024-06-25 12:57:09 +01:00
Nick O'Leary
c85667cc13 Merge pull request #4794 from node-red/4792-ui-proxy-fix
UI proxy should setup agents for both http_proxy and https_proxy
2024-06-25 10:56:44 +01:00
Dave Conway-Jones
1a8b37b4e3 make using msg.parts optional in join node 2024-06-24 21:05:00 +01:00
Steve-Mcl
40a2d90e08 remove .only 2024-06-24 20:06:22 +01:00
Steve-Mcl
ee269caa4a update and add tests to check correct proxy was returned for flow 2024-06-24 20:05:37 +01:00
Steve-Mcl
d820686e5a only initialise proxy if flow url is static 2024-06-24 20:04:26 +01:00
Steve-Mcl
aa2a585e00 should set https and http proxy agents for UI
closes #4792
2024-06-24 17:34:30 +01:00
Steve-Mcl
f9e6bccd46 Merge branch 'master' of github.com:node-red/node-red 2024-06-24 17:19:07 +01:00
Nick O'Leary
3230654ecd Merge pull request #4788 from GogoVega/fix-config-node-select
Fix the config node select value assignment
2024-06-24 16:59:16 +01:00
Gauthier Dandele
a5b53ee373 Fix the selected value if no config nodes available
Co-authored-by: Nick O'Leary <nick.oleary@gmail.com>
2024-06-24 17:37:28 +02:00
Nick O'Leary
ac420247ae Merge pull request #4786 from kazuhitoyokoi/master-addtooltip
Add tooltip for number of subflow instance on info tab
2024-06-24 16:25:54 +01:00
Steve-Mcl
61198bd7e3 Merge branch 'master' of github.com:node-red/node-red 2024-06-24 11:58:03 +01:00
GogoVega
9c511b6674 Revert the updateConfigNodeSelect changes 2024-06-24 12:39:22 +02:00
Nick O'Leary
9d054543a7 Merge pull request #4785 from kazuhitoyokoi/master-addjpn
Add Japanese translations for v4.0.0
2024-06-24 11:33:00 +01:00
Nick O'Leary
fc3ec2a0d7 Merge pull request #4791 from node-red/4787-revert-default-user-agent
Remove default user agent
2024-06-24 11:30:54 +01:00
Stephen McLaughlin
e7ef73222f Remove default user agent
closes #4787
2024-06-24 11:21:51 +01:00
GogoVega
6623e56a1e Fix setting of config node select value 2024-06-23 21:41:30 +02:00
Kazuhito Yokoi
582eca1877 Add tooltip for number of subflow instance on info tab 2024-06-23 20:59:26 +09:00
Kazuhito Yokoi
2783100f84 Add Japanese translations for v4.0.0 2024-06-23 20:48:34 +09:00
Rotzbua
8c5ddd68a4 fix(html): correct buggy html
- Merge "style" attribute
- Remove wrong end tag
- Remove trailing slash on void html elements
2024-06-22 22:38:24 +02:00
Nick O'Leary
cb0c484579 Merge branch 'dev' 2024-06-20 13:26:22 +01:00
Nick O'Leary
a1bf270ba6 Update tour version 2024-06-20 13:23:34 +01:00
Nick O'Leary
be5694f149 Merge pull request #4777 from node-red/rel400
Update for 4.0 final release
2024-06-20 11:53:56 +01:00
Nick O'Leary
4ff364e2c3 Reorder tour features 2024-06-20 11:45:23 +01:00
Nick O'Leary
2fa6f35873 Update for 4.0 final 2024-06-20 11:41:25 +01:00
Nick O'Leary
2a4fb7123d Merge pull request #4772 from node-red/rel3111
Bump for 3.1.11 release
2024-06-18 11:44:55 +01:00
Nick O'Leary
38a77d2b78 Bump for 3.1.11 release 2024-06-18 11:37:59 +01:00
Nick O'Leary
dc239db256 Merge pull request #4762 from node-red/Update-German-delay-node-translations
Add/Update German Translations for delay node
2024-06-17 16:07:20 +01:00
Nick O'Leary
a622d19ba7 Merge pull request #4761 from node-red/4759-add-httpStaticCors
Add `httpStaticCors`
2024-06-17 16:06:58 +01:00
Nick O'Leary
9842d9116c Merge pull request #4763 from node-red/bump-nr-admin
Update dependencies
2024-06-17 11:46:02 +01:00
Nick O'Leary
19ea8f8515 Update dependencies 2024-06-17 11:24:59 +01:00
Dave Conway-Jones
4ba3c937a8 Add/Update German Translations for delay node
To close #4748
2024-06-14 15:36:25 +01:00
Nick O'Leary
dbd3f0f85b Add httpStaticCors to default settings file 2024-06-14 15:21:02 +01:00
Nick O'Leary
48a2876c48 Add support for httpStaticCors 2024-06-14 15:18:40 +01:00
Nick O'Leary
10398b05d8 Merge pull request #4756 from node-red/sync-dev
Sync master to dev
2024-06-11 14:34:24 +01:00
Nick O'Leary
3a91fc17fd Merge branch 'master' into sync-dev 2024-06-11 10:14:01 +01:00
Nick O'Leary
02893d3e78 Merge pull request #4755 from node-red/rel3110
Bump for 3.1.10 release
2024-06-11 09:22:16 +01:00
Nick O'Leary
5124bc6bf8 Bump for 3.1.10 release 2024-06-10 21:14:20 +01:00
Nick O'Leary
3952a23ba3 Merge pull request #4747 from GogoVega/tooltip-input-validation
Add tooltip and message validation to `typedInput`
2024-06-10 20:44:34 +01:00
Nick O'Leary
1048b16f3c Merge pull request #4754 from node-red/4752-add-rewired-to-stoplist
Include rewired nodes when calculating Modified Flows stop list
2024-06-10 20:44:20 +01:00
Nick O'Leary
bbbbb1b1e0 Merge pull request #4753 from node-red/4751-fix-group-json
Fix clone of group env var properties
2024-06-10 20:42:49 +01:00
Nick O'Leary
14b452c996 Merge pull request #4750 from GogoVega/fix-4749
Fix losing links when importing a copy of links into a subflow
2024-06-10 20:42:36 +01:00
GogoVega
bb91a08939 Just move the block before the Id is updated 2024-06-10 18:28:30 +02:00
GogoVega
bffa923f05 Revert all changes for RED.popover 2024-06-10 18:02:28 +02:00
Nick O'Leary
526b3fda91 Include rewired nodes when calculating Modified Flows stop list 2024-06-10 16:56:49 +01:00
Nick O'Leary
27fc89ba33 Merge pull request #4744 from node-red/bcrypt-bump
Replace bcrypt with @node-rs/bcrypt
2024-06-10 16:16:19 +01:00
Nick O'Leary
d70b7ea924 Fix clone of group env var properties
Closes #4751
2024-06-10 16:15:06 +01:00
GogoVega
1d342a778d Fix new_nodes should be used instead of node_map 2024-06-05 14:12:35 +02:00
GogoVega
476016cbcc Fix node_map does not contain as key the new id of a copied node 2024-06-05 12:22:22 +02:00
GogoVega
bd2c020e84 My bad, options can be undefined 2024-06-03 21:11:13 +02:00
GogoVega
da7c7ede02 Fix a String value is an error, so return the value 2024-06-03 18:57:41 +02:00
GogoVega
34ed9c5cd8 Don't use the typedInput tooltip to get the validation message 2024-06-03 18:41:40 +02:00
Nick O'Leary
47dd08e74a Merge pull request #4746 from node-red/export-flow-save-view
Export Nodes dialog refinement
2024-06-03 16:11:22 +01:00
GogoVega
6aae50294f Cleanup + fix popover.getContent can be a function and apply #4450 changes 2024-06-02 20:16:10 +02:00
Steve-Mcl
ec2f6ec46f remember and restore active export view 2024-06-02 14:41:41 +01:00
Steve-Mcl
36805b6872 move export format button to main dialog 2024-06-02 14:41:15 +01:00
Steve-Mcl
d78cb2fec7 new common i18n message "format" 2024-06-02 12:10:30 +01:00
Nick O'Leary
51edb1ef19 Fix bcrypt.compare usage 2024-05-31 15:31:41 +01:00
Nick O'Leary
2ad3af1864 Replace bcrypt with @node-rs/bcrypt 2024-05-31 15:16:32 +01:00
Nick O'Leary
525d7356fe Merge pull request #4743 from node-red/rel400-b4
Update for 4-beta.4
2024-05-30 16:54:39 +01:00
Nick O'Leary
bdf37b0546 Update changelog 2024-05-30 16:50:02 +01:00
Nick O'Leary
0d330332f1 Merge pull request #4739 from Rotzbua/feat_build_fail
feat(grunt): fail if files are missing
2024-05-30 16:47:38 +01:00
Nick O'Leary
a5f290fd47 Merge pull request #4736 from Rotzbua/fix_pi_script
fix(node-red-pi): node-red not started by path
2024-05-30 16:47:25 +01:00
Nick O'Leary
46f4144172 Merge pull request #4735 from Rotzbua/fix_html_meta
fix(editor): remove trailing slash
2024-05-30 16:47:02 +01:00
Nick O'Leary
356e332f66 Merge pull request #4616 from Steve-Mcl/proxy-logiv-dev-v4
Perform Proxy logic more like cURL
2024-05-30 16:46:42 +01:00
Nick O'Leary
d16060bdd9 Merge pull request #4733 from Rotzbua/chore_remove_deprecated
fix: remove deprecated mqtt.js
2024-05-30 16:45:58 +01:00
Nick O'Leary
3aeb4bd868 Update dependencies 2024-05-30 16:43:33 +01:00
Stephen McLaughlin
b8bcab109a Merge branch 'dev' into proxy-logiv-dev-v4 2024-05-30 16:33:44 +01:00
Nick O'Leary
b94045fd86 Update packages/node_modules/node-red/settings.js 2024-05-30 16:32:21 +01:00
Nick O'Leary
87992823d5 Update for 4.0 final release 2024-05-30 16:12:56 +01:00
Nick O'Leary
93b914d4b0 Merge pull request #4740 from node-red/resyn-dev
Resync master to dev
2024-05-30 14:15:26 +01:00
Nick O'Leary
61b12f6bbe Merge pull request #3743 from bonanitech/fix-build-script
Ensure all CSS variables are in the output file
2024-05-30 13:43:25 +01:00
Nick O'Leary
d71b22412b Merge pull request #4734 from GogoVega/fix-sidebar-config
Fix the Sidebar Config is not refreshed after a deploy
2024-05-30 13:40:12 +01:00
Rotzbua
d115d6c241 feat(grunt): fail if files are missing 2024-05-30 14:35:55 +02:00
Stephen McLaughlin
e561efb5c5 Merge branch 'dev' into proxy-logiv-dev-v4 2024-05-30 11:44:53 +01:00
Nick O'Leary
e408c6b376 Merge pull request #4729 from GogoVega/fix-4728
Fix checkboxes are not updated when calling `typedInput("value", "")`
2024-05-30 10:32:27 +01:00
Rotzbua
cd95c63daf fix(node-red-pi): node-red not started by path
Double quote to prevent globbing and word splitting.
https://github.com/koalaman/shellcheck/wiki/SC2086
2024-05-30 01:53:51 +02:00
Rotzbua
bc6a4a20d2 fix(editor): remove trailing slash
html validator:
Info: Trailing slash on void elements has no effect and interacts badly with unquoted attribute values.
2024-05-30 01:42:16 +02:00
GogoVega
bf30c24e8e Fix the Sidebar Config is not refreshed after a deploy 2024-05-29 20:44:49 +02:00
Nick O'Leary
25205f7440 Merge pull request #4725 from node-red/monaco-0-49-0
Monaco-0-49-0
2024-05-29 17:37:46 +01:00
Stephen McLaughlin
6317420d4a Merge branch 'dev' into monaco-0-49-0 2024-05-29 11:14:33 +01:00
GogoVega
6c14ed0ef5 Revert and fix an undefined value returned instead of a false value 2024-05-28 22:08:42 +02:00
Rotzbua
f53bdc8257 fix: remove deprecated mqtt.js
deprecated since 2016 and node-red 0.13.4
2024-05-28 16:03:04 +02:00
Nick O'Leary
6d41ecdae0 Merge pull request #4716 from corentin-sodebo-voile/master
Fix panning with middle mouse button on windows 10/11
2024-05-28 10:28:57 +01:00
Nick O'Leary
7bd61f2c96 Merge pull request #4718 from node-red/4717-add-httpAdminCookieOptions
Add httpAdminCookieOptions
2024-05-28 10:15:46 +01:00
Nick O'Leary
76338d4d32 Merge pull request #4724 from Rotzbua/chore_isArray
chore: migrate deprecated `util.isArray`
2024-05-28 09:51:28 +01:00
Nick O'Leary
3f89bc2733 Merge pull request #4727 from kazuhitoyokoi/master-addjpn
Add Japanese translation for sidebar tooltip
2024-05-28 09:49:35 +01:00
Nick O'Leary
b9add237b2 Merge pull request #4726 from kazuhitoyokoi/dev-jpn
Add Japanese translations for 4.0.0-beta.3
2024-05-28 09:49:18 +01:00
Nick O'Leary
87a25df162 Merge pull request #4730 from GogoVega/translate-multiple-option-label
Translate the number of items selected in the options list
2024-05-28 09:49:03 +01:00
GogoVega
341f43610a Translate the number of items selected in the options list 2024-05-27 19:56:51 +02:00
GogoVega
67cdf3ef96 Fix checkboxes are not updated when calling typedInput("value", "") 2024-05-27 18:59:25 +02:00
Kazuhito Yokoi
cd98f448e9 Add Japanese translation for sidebar tooltip 2024-05-26 23:34:32 +09:00
Kazuhito Yokoi
b66af1c8e2 Fix typo 2024-05-26 23:00:52 +09:00
Kazuhito Yokoi
06bad61569 Add Japanese translations for 4.0.0-beta.3 2024-05-26 22:54:59 +09:00
Steve-Mcl
f58766eacf typo 2024-05-26 13:15:23 +01:00
Steve-Mcl
8e62b2a749 update monaco to latest 2024-05-26 13:15:10 +01:00
Rotzbua
9b86874c2d chore: migrate deprecated util.isArray
Deprecated: Use Array.isArray() instead.

Source: https://nodejs.org/docs/latest-v18.x/api/util.html#utilisarrayobject
2024-05-25 22:55:09 +02:00
Nick O'Leary
805ed593fb Apply httpAdminCookieOptions to session cookie 2024-05-23 17:01:48 +01:00
Nick O'Leary
c604ac2207 Allow session cookie options to be customised
Closes #4717
2024-05-23 16:56:43 +01:00
corentin-sodebo-voile
fac79fd068 Fix panning with middle mouse button on windows 10/11
Without preventDefault, when you try to drag the canvas with middle mouse button on Windows (e.g. in Chrome), the cursor change to a "scroll cursor" and the canvas scrolls endlessly instead of being dragged accurately.
2024-05-23 15:30:13 +02:00
Nick O'Leary
da97c5d558 Merge pull request #4715 from GogoVega/fix-validateNodeEditorProperty
Fix a checkbox should return a Boolean value and not the string `on`
2024-05-23 13:43:55 +01:00
Nick O'Leary
ae7b9fe62e Merge pull request #4714 from GogoVega/fix-4712
Deleting a grouped node should update the group
2024-05-23 13:43:26 +01:00
GogoVega
e52c2911da Fix a checkbox must return a boolean value and not on 2024-05-23 10:57:51 +02:00
GogoVega
ca37d1ec9d Merge branch 'dev' into tooltip-input-validation 2024-05-22 18:19:06 +02:00
Nick O'Leary
07a29ff779 Merge pull request #4711 from GogoVega/change-config-node-cursor
Change the Config Node cursor to `pointer`
2024-05-22 17:02:05 +01:00
Nick O'Leary
1b4a8ebe83 Merge branch 'master' into fix-4712 2024-05-22 17:01:29 +01:00
GogoVega
abf2eacf18 Revert and fix without using RED.group.removeFromGroup 2024-05-21 19:48:21 +02:00
Gauthier Dandele
f808f4e2e8 Apply suggestions from code review
Co-authored-by: Nick O'Leary <nick.oleary@gmail.com>
2024-05-21 19:01:57 +02:00
Nick O'Leary
ca33d6b799 Merge pull request #4713 from GogoVega/add-missing-sidebar-tooltips
Add missing tooltips to Sidebar
2024-05-21 17:15:52 +01:00
Nick O'Leary
3fd2d07c75 Merge pull request #4706 from node-red/4648-readonly-feedback
Show lock on deploy if user is read-only
2024-05-21 17:14:48 +01:00
Nick O'Leary
940740f15d Merge pull request #4710 from node-red/4704-node-edit-history
Allow nodes to return additional history entries in onEditSave
2024-05-21 17:10:23 +01:00
GogoVega
51208fcd0c Fix indexOf returns -1 2024-05-21 16:06:15 +02:00
GogoVega
707152d82f Deleting a grouped node should update the group 2024-05-21 15:07:26 +02:00
GogoVega
5538f6dd8a Add missing tooltips to Sidebar 2024-05-21 12:58:29 +02:00
GogoVega
d601e2caa4 Change the config node cursor to pointer 2024-05-21 11:37:01 +02:00
Nick O'Leary
46fdf56c79 Allow nodes to return additional history entries in onEditSave 2024-05-20 16:41:44 +01:00
Stephen McLaughlin
b76d692a65 Merge pull request #4707 from node-red/4569-cli-version
Add --version cli args
2024-05-17 17:36:41 +01:00
Nick O'Leary
6600910163 Add os details to --version output 2024-05-17 17:16:01 +01:00
Nick O'Leary
a6973bd7ed Add node.js version to --version output 2024-05-17 17:13:50 +01:00
Nick O'Leary
d58127730f Add --version cli arg 2024-05-17 17:10:37 +01:00
Nick O'Leary
5494c167fc Show lock on deploy if user is read-only 2024-05-17 17:04:08 +01:00
Nick O'Leary
c5ae0be7b1 Merge pull request #4705 from node-red/rel4b31
Bump for beta 4-beta3-1
2024-05-16 10:39:08 +01:00
Nick O'Leary
b653914ee0 Bump for beta3-1 repackage 2024-05-16 10:37:16 +01:00
Nick O'Leary
c107c5fc92 Merge pull request #4698 from node-red/rel4-beta3
Update for beta.3
2024-05-15 16:58:47 +01:00
Nick O'Leary
0980c03129 Merge pull request #4700 from GogoVega/addfrench-v4beta3
Add French translation of tour for 4.0.0-beta.3
2024-05-15 16:52:07 +01:00
GogoVega
f6c3fdc806 Add French translation of tour 2024-05-14 20:54:00 +02:00
Nick O'Leary
2c2628d816 Update changelog and tour 2024-05-14 17:44:26 +01:00
Nick O'Leary
56fe2801eb Merge branch 'master' into dev 2024-05-14 17:27:02 +01:00
Nick O'Leary
87b1ee9642 Bump package version 2024-05-14 17:24:28 +01:00
Nick O'Leary
e1c36d232b Merge pull request #4697 from node-red/sync-dev-2
Sync master branch to dev
2024-05-14 17:23:31 +01:00
Nick O'Leary
13ee8cec24 Merge branch 'master' into sync-dev-2 2024-05-14 17:22:42 +01:00
Nick O'Leary
a977b87cb3 Merge pull request #4692 from node-red/improve-conflict-handling
Improve background-deploy notification handling
2024-05-14 16:04:58 +01:00
Nick O'Leary
14dfb9aef8 Merge pull request #4695 from node-red/improve-merge-diff-view
Improve diff view display of nodes that have only moved
2024-05-14 16:04:27 +01:00
Nick O'Leary
d520cde57a Merge pull request #4314 from Rotzbua/remove_outdated_node_check
fix: remove outdated Node 11+ check
2024-05-14 13:54:15 +01:00
Nick O'Leary
70167d7d1d Merge pull request #4694 from Rotzbua/test_add_node_22
feat(ci): add new nodejs v22
2024-05-14 13:52:34 +01:00
Nick O'Leary
3389c8160b Handle group w/h properties as move rather than change 2024-05-14 13:51:52 +01:00
Nick O'Leary
c214710f8e Improve diff view display of nodes that have only moved 2024-05-14 13:35:05 +01:00
Nick O'Leary
ac6a4945cb Merge pull request #4690 from Rotzbua/fix_node_requirement
fix(node): increase required node >=18.5
2024-05-14 13:29:52 +01:00
Rotzbua
fd1a001a23 feat(ci): add new nodejs v22 2024-05-14 13:39:32 +02:00
Rotzbua
f3c561cd86 fix(node): increase required node >=18.5
Statement can be simplified by increasing the required minor version.
2024-05-14 12:27:38 +02:00
Nick O'Leary
4e33e785fb Handle multiple background deploys 2024-05-14 10:27:55 +01:00
Nick O'Leary
f55ee6e665 Merge pull request #4685 from node-red/4683-preserve-full-error-obj
Pass full error object in Function node and copy over cause property
2024-05-13 15:25:02 +01:00
Nick O'Leary
edc5e88d5a Merge pull request #4689 from Rotzbua/fix_workaroud_dns
fix(dns): remove outdated node check
2024-05-13 14:41:35 +01:00
Nick O'Leary
47bf166a6e Update packages/node_modules/node-red/lib/red.js 2024-05-13 14:41:24 +01:00
Nick O'Leary
cf26209790 Merge pull request #4688 from Rotzbua/remove_import_polyfill
fix(polyfill): remove import module polyfill
2024-05-13 14:39:33 +01:00
Nick O'Leary
e55ebde170 Merge pull request #4686 from Rotzbua/fix_typo
Fix typo
2024-05-13 14:38:35 +01:00
Nick O'Leary
a745ddc164 Fix linting 2024-05-13 14:33:35 +01:00
Nick O'Leary
18d0fa2259 Improve background conflict handling 2024-05-13 14:19:24 +01:00
Rotzbua
d706c9cb37 fix: remove outdated Node 11+ check 2024-05-12 22:51:05 +02:00
Rotzbua
20d2450cac fix(polyfill): remove import module polyfill
Was required for node <12.17.
2024-05-12 22:38:03 +02:00
Rotzbua
34345461f1 fix(dns): remove outdated node check
Add reference to issue for this workaround.
2024-05-12 22:25:39 +02:00
Rotzbua
aa372a1707 Fix typo in source code comment 2024-05-12 18:25:08 +02:00
Nick O'Leary
03648dc7e8 Update tests for changed function node low-level output 2024-05-09 17:25:47 +01:00
Nick O'Leary
66a667fe58 Pass full error object in Function node and copy over cause property
Fixes #4683
2024-05-09 16:48:51 +01:00
Nick O'Leary
1bb3a0eca5 Merge pull request #4534 from patlux/master
Replacing vm.createScript in favour of vm.Script
2024-05-09 15:19:45 +01:00
Nick O'Leary
0e0bba25c1 Merge pull request #4679 from node-red/use-rfdc
Use rfdc for cloning pure JSON values
2024-05-08 16:18:13 +01:00
Nick O'Leary
af701d65ac Merge pull request #4681 from GogoVega/addfrench-v4beta.2
Add French translations for 4.0.0-beta.2
2024-05-08 16:17:57 +01:00
Nick O'Leary
08927dfb55 Merge pull request #4684 from node-red/4363-autoLogin-redirect-loop
Avoid login loops when autoLogin enabled but login fails
2024-05-08 15:48:21 +01:00
Nick O'Leary
b27483de9c Avoid login loops when autoLogin enabled but login fails
Fixes #4363
2024-05-08 15:09:51 +01:00
GogoVega
b02f69b77a Add translations for 4.0.0-beta.2 2024-05-05 15:00:42 +02:00
Nick O'Leary
598b0c84ab Merge pull request #4657 from node-red/tab-close-middle-click
Hide workspace tab on middle mouse click
2024-05-03 16:59:28 +01:00
Nick O'Leary
22cc8da088 Apply suggestions from code review 2024-05-03 16:59:17 +01:00
Nick O'Leary
a70618cdef Merge pull request #4666 from node-red/multiplayer-2
[multiplayer] Add user presence indicators
2024-05-03 16:52:50 +01:00
Nick O'Leary
faf142cf66 Merge pull request #4676 from kazuhitoyokoi/dev-fixpulldependencies
Enable updating dependency node of package.json in project feature
2024-05-03 16:52:33 +01:00
Nick O'Leary
1a3cc06935 Use rfdc module for cloning when we know its pure JSON 2024-05-03 16:45:50 +01:00
Nick O'Leary
a712a9363b Merge pull request #4674 from kazuhitoyokoi/dev-addjpn
Add Japanese translations for 4.0.0-beta.2
2024-05-03 16:18:50 +01:00
Steve-Mcl
67e716466f handle middle click hide-tab in onclick handler 2024-04-29 20:14:45 +01:00
Steve-Mcl
3fae03da98 Merge branch 'dev' into tab-close-middle-click 2024-04-29 19:04:47 +01:00
Kazuhito Yokoi
361391ceb8 Load the latest project files when retrieving project information 2024-04-29 16:02:56 +09:00
Kazuhito Yokoi
bf0ca38350 Enable updating dependencies of package.json in project feature 2024-04-29 02:12:08 +09:00
Kazuhito Yokoi
437c28e2b8 Fix typos in welcome tour for 4.0.0-beta.2 2024-04-28 21:27:25 +09:00
Kazuhito Yokoi
c05d18ada1 Add Japanese translations for 4.0.0-beta.2 2024-04-28 21:22:15 +09:00
Nick O'Leary
cfb300ec06 Merge pull request #4672 from node-red/allow-blank-env-var-substitutions
Allow blank strings to be used for env var property substitutions
2024-04-24 23:37:23 +02:00
Nick O'Leary
236e668201 Allow blank strings to be used for env var property substitutions
Fixes #4663
2024-04-24 22:58:11 +02:00
Nick O'Leary
211d420fb2 Merge pull request #4667 from node-red/fix-subflow-property-undo
Fix undo of subflow env property edits
2024-04-23 23:45:46 +02:00
Nick O'Leary
c9b902c2b4 Merge pull request #4658 from node-red/fix-subflow-conf-type
Fix saving of conf-type properties in module packaged subflows
2024-04-23 23:45:29 +02:00
Nick O'Leary
b8ca4665c1 Merge pull request #4660 from JoshuaCWebDeveloper/patch-1
Fix three error typos in monaco.js
2024-04-23 23:45:16 +02:00
Nick O'Leary
ac8b1e19b7 Merge pull request #4662 from hardillb/timeout-npm-install
Add npm install timeout notification
2024-04-23 23:44:51 +02:00
Nick O'Leary
960af87fb0 Ensure subflow change state is cleared after deploy 2024-04-23 21:17:35 +02:00
Nick O'Leary
de7339ae97 Fix undo of subflow env property edits 2024-04-23 20:39:14 +02:00
Nick O'Leary
595933d046 Fix linting 2024-04-23 09:40:01 +02:00
Nick O'Leary
789426f80e Add user presence indication to tabs and nodes 2024-04-23 09:27:35 +02:00
Stephen McLaughlin
0995af62b6 Merge pull request #4664 from ZJvandeWeg/patch-3
docs: Add closing paragraph tag
2024-04-20 13:54:37 +01:00
Zeger-Jan van de Weg
c2e03a40b4 docs: Add closing paragraph tag
Minor change that only improves xpath parsing.
2024-04-20 14:20:59 +02:00
Ben Hardill
148e64c3da Update packages/node_modules/@node-red/editor-client/locales/en-US/editor.json
Co-authored-by: Nick O'Leary <nick.oleary@gmail.com>
2024-04-18 14:22:50 +01:00
Ben Hardill
c6289ebb2c Merge branch 'dev' into timeout-npm-install 2024-04-18 12:12:53 +01:00
Ben Hardill
5f4ece6813 Move translation 2024-04-18 11:47:49 +01:00
Ben Hardill
c990ec39d6 revert DELETE change 2024-04-18 11:35:51 +01:00
Ben Hardill
1fdc600ecd Add npm install timeout notification
part of https://github.com/node-red/node-red/issues/4622
2024-04-18 11:27:32 +01:00
Joshua Carter
c855050bcf Fix three error typos in monaco.js 2024-04-15 08:09:26 -07:00
Nick O'Leary
e354d2ce29 Fix saving of conf-type properties in module packaged subflows 2024-04-12 14:08:07 +01:00
Nick O'Leary
d218af8619 Merge branch 'master' into dev 2024-04-12 13:04:54 +01:00
Steve-Mcl
d938e5fb6b close tab on middle mouse click 2024-04-12 11:42:55 +01:00
Nick O'Leary
29ed5b2792 Merge pull request #4655 from node-red/rel319
Bump for 3.1.9 release
2024-04-11 19:22:24 +01:00
Nick O'Leary
e39216e65a Bump for 3.1.9 release 2024-04-11 19:15:46 +01:00
Nick O'Leary
7ac7f9b4c8 Merge pull request #4654 from node-red/fix-subflow-recursion-check
Prevent subflow being added to itself
2024-04-11 19:12:43 +01:00
Stephen McLaughlin
4709eb9d49 Merge pull request #4652 from node-red/fix-windows-spawn
Fix use of spawn on windows with cmd files
2024-04-11 17:51:13 +01:00
Nick O'Leary
c13b8266dd Prevent subflow being added to itself 2024-04-11 17:05:10 +01:00
Nick O'Leary
bd58431603 Fix use of spawn on windows with cmd files 2024-04-11 14:40:29 +01:00
Nick O'Leary
3075b82792 Add one more tour image 2024-04-05 11:18:17 +01:00
Nick O'Leary
240082481f Merge pull request #4646 from node-red/rel400b2
Bump for beta.2
2024-04-05 10:53:03 +01:00
Nick O'Leary
ea95552285 Bump for beta.2 2024-04-04 18:25:10 +01:00
Nick O'Leary
5358b06123 Merge pull request #4645 from node-red/fix-mp-tests
Add placeholder tests for multiplayer
2024-04-04 16:19:53 +01:00
Nick O'Leary
99391431da Add placeholder tests for multiplayer 2024-04-04 16:17:30 +01:00
Nick O'Leary
d396f50a9a Merge pull request #4627 from GogoVega/button-add-config-node
Separate the "add new config-node" option into a new (+) button
2024-04-04 16:11:52 +01:00
Nick O'Leary
affa8ea42b Apply suggestions from code review 2024-04-04 16:08:59 +01:00
Nick O'Leary
d711b01fe5 Merge pull request #4629 from node-red/multiplayer-1
Introduce multiplayer feature
2024-04-04 15:24:29 +01:00
Nick O'Leary
6e7fa6f921 Merge branch 'dev' into button-add-config-node 2024-04-03 14:02:40 +01:00
Nick O'Leary
343cde75a2 Merge pull request #4644 from node-red/resyn-dev
Resync recent fixes from master to dev
2024-04-03 14:02:17 +01:00
Nick O'Leary
2dc446e45b Merge branch 'dev' into resyn-dev 2024-04-03 13:57:10 +01:00
Nick O'Leary
884b7fa16a Merge pull request #4643 from node-red/fix-subflow-mod-config-select
Fix handling of subflow config-node select type in sf module
2024-04-03 13:54:41 +01:00
Nick O'Leary
173e065b68 Merge pull request #4639 from node-red/4638-fix-change-replace-bool
Fix change node handling of replacing with boolean
2024-04-02 20:07:01 +01:00
Nick O'Leary
9a3cb0b2b5 Merge pull request #4640 from node-red/fix-subflow-init-err
Guard refresh of unknown subflow
2024-04-02 20:06:47 +01:00
Nick O'Leary
6beae5a806 Merge pull request #4642 from node-red/4641-fix-subflow-module-debug-logging
Fix subflow module sending messages to debug sidebar
2024-04-02 20:06:31 +01:00
Nick O'Leary
66f4008bb8 Fix handling of subflow config-node select type in sf module 2024-04-02 20:01:48 +01:00
Nick O'Leary
a0636632a1 Fix subflow module sending messages to debug sidebar
Fixes #4641
2024-04-02 17:42:19 +01:00
Nick O'Leary
5dfa47ab6c Guard refresh of unknown subflow 2024-04-02 15:54:34 +01:00
Nick O'Leary
e9efe493f9 Remove only 2024-04-02 13:59:15 +01:00
Nick O'Leary
3bd782e62a Fix change node handling of replacing with boolean
Fixes #4638
2024-04-02 13:57:19 +01:00
Steve-Mcl
9b49cb2b50 Merge branch 'dev' into proxy-logiv-dev-v4 2024-03-31 16:49:28 +01:00
Nick O'Leary
963fe87f14 Merge pull request #4637 from node-red/tidy-up-palette-state
Ensure palette filter reapplies and clear up unknown categories
2024-03-28 15:36:05 +00:00
Nick O'Leary
ade4679e8c Merge pull request #4636 from node-red/rel318
Bump for 3.1.8
2024-03-28 15:23:07 +00:00
Nick O'Leary
40060a470b Merge pull request #4635 from node-red/sync-dev
Sync dev
2024-03-28 15:22:57 +00:00
Nick O'Leary
a6e8fbb54a Ensure palette filter reapplies and clear up unknown categories 2024-03-28 15:21:04 +00:00
Nick O'Leary
410b938442 Bump for 3.1.8 2024-03-28 15:02:02 +00:00
Nick O'Leary
ab7e9f94fa Merge branch 'dev' into sync-dev 2024-03-28 14:56:36 +00:00
Nick O'Leary
28e9ccd372 Merge pull request #4634 from node-red/pr_4623
Retain Palette categories collapsed and filter to localStorage
2024-03-28 14:53:15 +00:00
Nick O'Leary
9a66d9addd Merge pull request #4620 from node-red/pr_4387
Add support for plugin (only) modules to the palette manager
2024-03-28 14:35:33 +00:00
Nick O'Leary
8843bda477 Merge pull request #4628 from node-red/comms-updates
Comms API updates
2024-03-28 14:33:10 +00:00
Nick O'Leary
3278303eec Clear localStorage state on logout 2024-03-28 14:31:31 +00:00
Nick O'Leary
f5fd6e3a36 Rework palette state management 2024-03-28 14:23:39 +00:00
Gauthier Dandele
a173e8e70f Apply suggestions from code review
Co-authored-by: Nick O'Leary <nick.oleary@gmail.com>
2024-03-28 12:57:04 +01:00
Nick O'Leary
19dcc3a683 Merge pull request #4632 from node-red/4625-sf-env-err-handling
Add validation and error handling on subflow instance properties
2024-03-28 11:10:28 +00:00
Nick O'Leary
20d067c1ea Merge pull request #4633 from node-red/4617-hide-library-context-options
Hide import/export context menu if disabled in theme
2024-03-28 11:10:14 +00:00
Nick O'Leary
9526566799 Hide import/export context menu if disabled in theme 2024-03-28 11:00:10 +00:00
Nick O'Leary
0b9dd82c91 Merge pull request #4631 from node-red/4626-subflow-change-notification
Show change indicator on subflow tabs
2024-03-27 19:10:39 +00:00
Nick O'Leary
19213434f9 Add validation to subflow instance env properties 2024-03-27 19:08:25 +00:00
Nick O'Leary
014691346a Handle malformed env var values and log errors 2024-03-27 18:23:12 +00:00
Nick O'Leary
6738b95c29 Merge pull request #4630 from node-red/bump-express
Bump dependencies
2024-03-27 18:11:54 +00:00
Nick O'Leary
6a8230ec1e Show change icon on subflow tabs
Fixes #4626
2024-03-27 18:10:04 +00:00
Nick O'Leary
5679d264b6 Bump dependencies 2024-03-27 18:00:06 +00:00
Nick O'Leary
b20c5f3a8d Merge pull request #4621 from GogoVega/addfrench-v4
Add French translations for 4.0.0-beta.1
2024-03-27 17:48:07 +00:00
GogoVega
65d8872cea Separate the "add new config-node" option into a button 2024-03-27 14:59:49 +01:00
GogoVega
bffd1d61b2 Improve with error handling, storage cleanup and centralization in one object 2024-03-26 16:58:45 +01:00
GogoVega
4788b81220 Replace setTimeout with a listener 2024-03-26 13:05:38 +01:00
GogoVega
9a07fc03c6 Retain palette collapse and filter to localStorage 2024-03-25 20:47:55 +01:00
GogoVega
954f518030 Add French translations for 4.0.0-beta.1 2024-03-25 12:02:38 +01:00
GogoVega
9f8ff71757 Add French translations for TCP and CSV nodes 2024-03-25 11:58:35 +01:00
GogoVega
06dd59dc81 Add missing global-config translation 2024-03-25 10:51:12 +01:00
Nick O'Leary
37265cf4ef Merge pull request #4619 from node-red/4600-reset-workspace-index
Reset workspace index when clearing nodes
2024-03-21 17:38:39 +00:00
Nick O'Leary
2531a5283a Include module property in plugin metadata 2024-03-21 17:04:03 +00:00
Nick O'Leary
4cc1a5d846 Merge branch 'pr_4387' of github.com:node-red/node-red into pr_4387 2024-03-21 16:56:49 +00:00
Nick O'Leary
8a63275989 Merge pull request #4613 from kazuhitoyokoi/master-fixglobalconfig
Remove typo in global config
2024-03-21 16:54:01 +00:00
Nick O'Leary
2d3e5f4ce0 Fix linting 2024-03-21 16:43:47 +00:00
Nick O'Leary
5135545c6c Merge branch 'dev' into pr_4387 2024-03-21 16:41:24 +00:00
Nick O'Leary
fef93818c9 Ensure plugins api provides a filtered view 2024-03-21 16:37:05 +00:00
Nick O'Leary
7fc64a84e8 Bump test helper 2024-03-21 15:16:49 +00:00
Nick O'Leary
02f7cdd5aa Ensure all httpRequest test servers are ready before tests run 2024-03-21 15:03:37 +00:00
Nick O'Leary
d7dcceef60 Add debug for http tests 2024-03-21 11:32:29 +00:00
Nick O'Leary
ae5e1570ae Reset workspace index when clearing nodes
Fixes #4600
2024-03-21 11:14:34 +00:00
Nick O'Leary
50baad9624 Merge pull request #4612 from kazuhitoyokoi/dev-addjpn
Add Japanese translations for 4.0.0-beta.1
2024-03-21 11:08:28 +00:00
Nick O'Leary
fc0041bd91 Merge pull request #4615 from Steve-Mcl/4614-monaco-and-types
Update monaco to latest and node types to 18 LTS
2024-03-21 09:25:52 +00:00
Steve-Mcl
283f7f5992 support env var NR_PROXY_MODE "legacy"|"strict" 2024-03-17 17:21:33 +00:00
Steve-Mcl
1cf7b95891 add missing ref to getProxyForUrl helper 2024-03-17 17:20:53 +00:00
Steve-Mcl
7bdb8db5ff http node fix tests 2024-03-17 17:11:29 +00:00
Steve-Mcl
de27968e4e (re)add node.insecureHTTPParser) 2024-03-17 17:10:56 +00:00
Steve-Mcl
d31abda28f typo 2024-03-17 17:01:25 +00:00
Steve-Mcl
dcfb4c9a79 update unit tests 2024-03-17 16:36:24 +00:00
Steve-Mcl
bf065ee11d default to strict mode but permit settings 2024-03-17 16:34:42 +00:00
Steve-Mcl
5e3cbadffc merge dev 2024-03-17 12:51:57 +00:00
Steve-Mcl
535ef82e48 Merge remote-tracking branch 'upstream/dev' into proxy-logiv-dev-v4 2024-03-17 12:50:59 +00:00
Steve-Mcl
c368bfea3f var/const updates 2024-03-17 12:37:42 +00:00
Steve-Mcl
4498e4100e Update Monaco editor and type completions
closes #4614
2024-03-17 11:08:47 +00:00
Kazuhito Yokoi
4f1e4faede Add Japanese translations for TCP and CSV nodes 2024-03-16 19:32:42 +09:00
Kazuhito Yokoi
3ca045394a Remove typo in global config 2024-03-16 18:51:13 +09:00
Kazuhito Yokoi
9a19a1113e Fix image paths in previous welcome tour 2024-03-16 18:44:25 +09:00
Kazuhito Yokoi
1cd550022b Fix typos 2024-03-16 18:43:03 +09:00
Kazuhito Yokoi
bad08bafd7 Add Japanese translations for 4.0.0-beta.1 2024-03-16 18:34:24 +09:00
Patrick Wozniak
28907082f1 fix usage of vm.Script() 2024-01-21 02:16:00 +01:00
Patrick Wozniak
f83174c40a fix use of vm.Script by adding new 2024-01-21 01:23:07 +01:00
Patrick Wozniak
ec062d008f replace vm.createScript in favor of vm.Script 2024-01-21 01:13:00 +01:00
Patrick Wozniak
a587655a5a adding pollyfill for vm.createScript
adds support for bun.sh
2024-01-21 01:00:02 +01:00
GogoVega
282d52cf0b Fix non-boolean returned value + try to find validation msg in tooltip 2023-12-17 19:22:44 +01:00
GogoVega
ba08cf0417 Add tooltip input validation msg 2023-12-12 17:17:33 +01:00
Ralph Wetzel
3df3096bb4 Fix to please linter 2023-10-18 08:07:49 +02:00
Ralph Wetzel
bb10d5bb94 Fix scope of variable 2023-10-18 08:07:06 +02:00
Ralph Wetzel
1704ab7454 Compensate for incomplete config data (e.g. test) 2023-10-18 08:06:15 +02:00
Ralph Wetzel
3275a76fb0 Adapt test after modification to uninstallModule 2023-10-18 08:04:52 +02:00
Ralph Wetzel
81937ddc45 Add plugin support to palette manager 2023-10-17 22:44:33 +02:00
Mauricio Bonani
3e6f0acf79 Refactor code 2023-10-03 15:42:33 -04:00
Mauricio Bonani
7f93d943d7 Merge remote-tracking branch 'upstream/master' into fix-build-script 2023-10-03 09:04:40 -04:00
Steve-Mcl
f61971bc23 first pass at common proxy determining logic 2022-12-01 12:53:03 +00:00
Mauricio Bonani
12543d2c2a Ensure all CSS variables are in the output file 2022-07-06 19:06:11 -04:00
271 changed files with 50980 additions and 6726 deletions

View File

@@ -16,7 +16,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [18, 20]
node-version: [18, 20, 22.4.x]
steps:
- uses: actions/checkout@v4
- name: Use Node.js ${{ matrix.node-version }}

View File

@@ -1,3 +1,145 @@
#### 4.0.2: Maintenance Release
Editor
- Use a more subtle border on the header (#4818) @bonanitech
- Improve the editor's French translations (#4824) @GogoVega
- Clean up orphaned editors (#4821) @Steve-Mcl
- Fix node validation if the property is not required (#4812) @GogoVega
- Ensure mermaid.min.js is cached properly between loads of the editor (#4817) @knolleary
Runtime
- Allow auth cookie name to be customised (#4815) @knolleary
- Guard against undefined sessions in multiplayer (#4816) @knolleary
#### 4.0.1: Maintenance Release
Editor
- Ensure subflow instance credential property values are extracted (#4802) @knolleary
- Use `_ADD_` value for both `add new...` and `none` options (#4800) @GogoVega
- Fix the config node select value assignment (#4788) @GogoVega
- Add tooltip for number of subflow instance on info tab (#4786) @kazuhitoyokoi
- Add Japanese translations for v4.0.0 (#4785) @kazuhitoyokoi
Runtime
- Ensure group nodes are properly exported in /flow api (#4803) @knolleary
Nodes
- Joins: make using msg.parts optional in join node (#4796) @dceejay
- HTTP Request: UI proxy should setup agents for both http_proxy and https_proxy (#4794) @Steve-Mcl
- HTTP Request: Remove default user agent (#4791) @Steve-Mcl
#### 4.0.0: Milestone Release
This marks the next major release of Node-RED. The following changes represent
those added since the last beta. Check the beta release details below for the complete
list.
Breaking Changes
- Node-RED now requires Node 18.x or later. At the time of release, we recommend
using Node 20.
Editor
- Add `httpStaticCors` (#4761) @knolleary
- Update dependencies (#4763) @knolleary
- Sync master to dev (#4756) @knolleary
- Add tooltip and message validation to `typedInput` (#4747) @GogoVega
- Replace bcrypt with @node-rs/bcrypt (#4744) @knolleary
- Export Nodes dialog refinement (#4746) @Steve-Mcl
#### 4.0.0-beta.4: Beta Release
Editor
- Fix the Sidebar Config is not refreshed after a deploy (#4734) @GogoVega
- Fix checkboxes are not updated when calling `typedInput("value", "")` (#4729) @GogoVega
- Fix panning with middle mouse button on windows 10/11 (#4716) @corentin-sodebo-voile
- Add Japanese translation for sidebar tooltip (#4727) @kazuhitoyokoi
- Translate the number of items selected in the options list (#4730) @GogoVega
- Fix a checkbox should return a Boolean value and not the string `on` (#4715) @GogoVega
- Deleting a grouped node should update the group (#4714) @GogoVega
- Change the Config Node cursor to `pointer` (#4711) @GogoVega
- Add missing tooltips to Sidebar (#4713) @GogoVega
- Allow nodes to return additional history entries in onEditSave (#4710) @knolleary
- Update to Monaco 0.49.0 (#4725) @Steve-Mcl
- Add Japanese translations for 4.0.0-beta.3 (#4726) @kazuhitoyokoi
- Show lock on deploy if user is read-only (#4706) @knolleary
Runtime
- Ensure all CSS variables are in the output file (#3743) @bonanitech
- Add httpAdminCookieOptions (#4718) @knolleary
- chore: migrate deprecated `util.isArray` (#4724) @Rotzbua
- Add --version cli args (#4707) @knolleary
- feat(grunt): fail if files are missing (#4739) @Rotzbua
- fix(node-red-pi): node-red not started by path (#4736) @Rotzbua
- fix(editor): remove trailing slash (#4735) @Rotzbua
- fix: remove deprecated mqtt.js (#4733) @Rotzbua
Nodes
- Perform Proxy logic more like cURL (#4616) @Steve-Mcl
#### 4.0.0-beta.3: Beta Release
Editor
- Improve background-deploy notification handling (#4692) @knolleary
- Hide workspace tab on middle mouse click (#4657) @Steve-Mcl
- multiplayer: Add user presence indicators (#4666) @knolleary
- Enable updating dependency node of package.json in project feature (#4676) @kazuhitoyokoi
- Add French translations for 4.0.0-beta.2 (#4681) @GogoVega
- Add Japanese translations for 4.0.0-beta.2 (#4674) @kazuhitoyokoi
- Fix saving of conf-type properties in module packaged subflows (#4658) @knolleary
- Add npm install timeout notification (#4662) @hardillb
- Fix undo of subflow env property edits (#4667) @knolleary
- Fix three error typos in monaco.js (#4660) @JoshuaCWebDeveloper
- docs: Add closing paragraph tag (#4664) @ZJvandeWeg
- Avoid login loops when autoLogin enabled but login fails (#4684) @knolleary
Runtime
- Allow blank strings to be used for env var property substitutions (#4672) @knolleary
- Use rfdc for cloning pure JSON values (#4679) @knolleary
- fix: remove outdated Node 11+ check (#4314) @Rotzbua
- feat(ci): add new nodejs v22 (#4694) @Rotzbua
- fix(node): increase required node >=18.5 (#4690) @Rotzbua
- fix(dns): remove outdated node check (#4689) @Rotzbua
- fix(polyfill): remove import module polyfill (#4688) @Rotzbua
- Fix typo (#4686) @Rotzbua
Nodes
- Pass full error object in Function node and copy over cause property (#4685) @knolleary
- Replacing vm.createScript in favour of vm.Script (#4534) @patlux
#### 4.0.0-beta.2: Beta Release
Editor
- Introduce multiplayer feature (#4629) @knolleary
- Separate the "add new config-node" option into a new (+) button (#4627) @GogoVega
- Retain Palette categories collapsed and filter to localStorage (#4634) @knolleary
- Ensure palette filter reapplies and clear up unknown categories (#4637) @knolleary
- Add support for plugin (only) modules to the palette manager (#4620) @knolleary
- Update monaco to latest and node types to 18 LTS (#4615) @Steve-Mcl
Runtime
- Fix handling of subflow config-node select type in sf module (#4643) @knolleary
- Comms API updates (#4628) @knolleary
- Add French translations for 4.0.0-beta.1 (#4621) @GogoVega
- Add Japanese translations for 4.0.0-beta.1 (#4612) @kazuhitoyokoi
Nodes
- Fix change node handling of replacing with boolean (#4639) @knolleary
#### 4.0.0-beta.1: Beta Release
Editor
@@ -29,647 +171,6 @@ Nodes
- Let debug node status msg length be settable via settings (#4402) @dceejay
- Feat: Add ability to set headers for WebSocket client (#4436) @marcus-j-davies
#### 3.1.7: Maintenance Release
- Add Japanese translation for v3.1.6 (#4603) @kazuhitoyokoi
- Update jsonata version (#4593) @hardillb
#### 3.1.6: Maintenance Release
Editor
- Do not flag env var in num typedInput as error (#4582) @knolleary
- Fix example flow name in import dialog (#4578) @kazuhitoyokoi
- Fix missing node icons in workspace (#4570) @knolleary
Runtime
- Handle undefined env vars (#4581) @knolleary
- fix: Removed offending MD5 crypto hash and replaced with SHA1 and SHA256 … (#4568) @JaysonHurst
- chore: remove never use import code (#4580) @giscafer
Nodes
- fix: template node zh-CN translation (#4575) @giscafer
#### 3.1.5: Maintenance Release
Runtime
- Fix require of dns module (#4562) @knolleary
- Ensure global creds object is initialised when adding first cred (#4561) @knolleary
#### 3.1.4: Maintenance Release
Editor
- Highlight errors in config node sidebar (#4529) @knolleary
- Improve feedback in import dialog to show conflicted nodes (#4550) @knolleary
- Modify node users info in config editor footer (#4528) @knolleary
- Handle modified-nodes deploy after replacing unknown config node (#4556) @knolleary
- Handle undefined default export when importing module (#4539) @knolleary
- Fix icon scaling for non .svg icons (#4491) @ralphwetzel
- (convertNode) Do not create the credentials object if there is nothing to export (#4544) @GogoVega
- Ensure subflow instance node has g property set (#4538) @knolleary
- Handle importing flow with existing subflow and instance node (#4546) @knolleary
- Update index.mst (#4483) @gorenje
- Include top level property name when copying path from context (#4527) @knolleary
- Add handling to disable items on context menu (#4500) @kazuhitoyokoi
- Focus Quick Add dialog from context menu (#4516) @kazuhitoyokoi
- Fix subflow ports in Quick Add dialog (#4518) @kazuhitoyokoi
- Fix location of subflow ports in palette (#4502) @kazuhitoyokoi
- Client/Editor Events: fix off-in-on pattern emulating once (#4484) @gorenje
- Restore caching busting functionality without using explict version number (#4512) @knolleary
- Do not translate the list of available languages (#4531) @GogoVega
- Add French translation of v3.1.3 changes (#4477) @GogoVega
- i18n(es-ES) Spanish Spain translation (#4495) @joebordes
- Add missing validation messages (#4487) @GogoVega
- Add Japanese translations for v3.1.3 (#4498) @kazuhitoyokoi
- Replace `rename` by `edit` for the menu flow label (#4506) @GogoVega
- Update editor.json fix typo in German translation (#4552) @guidoffm
Runtime
- Bump the github-actions group with 1 update (#4554) @app/dependabot
- Clone objects types when getting env values (#4519) @knolleary
- Ensure global-config credential env vars are merged on deploy (#4526) @knolleary
Nodes
- 21-httprequest.js remove unused code, because of broken use of toLowercase (#4522) @gorenje
#### 3.1.3: Maintenance Release
Editor
- Add missing en-us messages (#4475) @knolleary
#### 3.1.2: Maintenance Release
Editor
- Relax some node validators to allow undefined value (#4471) @knolleary
- Fix switch validation of typeof field (#4465) @knolleary
- Use move cursor when hovering on group border (#4467) @knolleary
- Added action list Chinese (Simplified and Traditional) translation + v3.1.1 changes (#4470) @wangyiyi2056
- Add French translation of `action-list` + v3.1.1 changes (#4466) @GogoVega
Runtime
- Ensure nested groups inside subflows have their g props remapped (#4472) @knolleary
#### 3.1.1: Maintenance Release
Editor
- Fix debug filter (#4461) @knolleary
- Fix various issues with debug pop-out window (#4459) @knolleary
- Ensure subflow instances keep track of their groups (#4457) @knolleary
- Fix `validateNodeProperty` without validator provided (#4455) @GogoVega
- Debounce node-removed notifications (#4453) @knolleary
- Don't try to load the parents of the first commit (#4448) @bonanitech
- Allow a theme to specifiy which theme mermaid should use (#4441) @knolleary
- Update browser title with flow name if set (#4427) @knolleary
- Ensure typeSearch handles undefined node definitions (#4423) @knolleary
- Ensure group w/h are imported if present (#4426) @knolleary
- Hide node status background when there is no status to show (#4425) @knolleary
- Add a close button to the restart-required notification (#4407) @knolleary
- Extend typedInput "num" type validity check to NaN, binary, octal & hex (#4371) @ralphwetzel
- Fix unintended new line in node name (#4399) @kazuhitoyokoi
- Ctrl-Enter does not close tray (Monaco) #4377 (#4382) @hazymat
- fix buffer viewer to handle 0b style binary (#4393) @dceejay
- Rework mermaid integration to support off-DOM rendering (#4364) @knolleary
- Add missing nls labels to context menu (#4365) @knolleary
Runtime
- Bump the github-actions group with 2 updates (#4404) @app/dependabot
- Handle unknown node reference inside subflow module (#4460) @knolleary
- Add modules.install audit event when external module installed (#4452) @knolleary
- Allow import of modules with subpath in specifier (#4451) @knolleary
- Update node-red-admin version (#4438) @knolleary
- Handle false-like env vars properly (#4411) @knolleary
- Only save settings once during node load process (#4409) @knolleary
- Ensure global-config nodes lookup cred values properly (#4405) @knolleary
- Handle credential env var evaluation when no value set (#4362) @knolleary
- Don't commit package-lock.json (#4354) @bonanitech
- Fix env evaluation when one env references another in the same object (#4361) @knolleary
- Add dependabot for Github Actions (#4312) @Rotzbua
- Update outdated Github Actions (#4311) @Rotzbua
- github: Request `npm run test` in PR template (#4348) @ZJvandeWeg
- Add French translation of v3.1.0-beta.4 changes + slight improvements (#4329) @GogoVega
- Handle nodes with multiple input handlers properly (#4332) @knolleary
- Soften the language around unrequited PRs (#4351) @knolleary
Nodes
- CSV: make CSV export way faster by not re-allocating and handling huge string (#4349) @Fadoli
- Delay: Fix regression in delay node to not pass on msg.reset (#4350) @dceejay
- Link Call: Handle undefined linkType value for existing link-call nodes (#4331) @knolleary
- MQTT: Guard against node.broker being undefined (#4454) @knolleary
- MQTT: check topic length > 0 before publish (#4416) @dceejay
- Switch/Change: Improve validation of switch/change node rules (#4368) @knolleary
- Template: Fix height of description editor in template node (#4346) @kazuhitoyokoi
- Various: Add validators to any fields using msg-typed Input (#4440) @knolleary
#### 3.1.0: Milestone Release
Editor
- Default filter to All Catalogues and show nodes for small lists (#4318) @knolleary
- Better distinguish between ctrl and meta keys on mac (#4310) @knolleary
- Ensure junction appears when filtering quick-add list (#4297) @knolleary
- Update message catalogs for JSONata Expression editor (#4287) @kazuhitoyokoi
- Add tooltip to relevance sort button in user settings UI (#4288) @kazuhitoyokoi
- Capture workspace dirty state when quick-adding junction (#4283) @knolleary
- Add docs for $clone function (#4284) @knolleary
Runtime
- Dependency updates (#4317) @knolleary
- Ensure storage/util.writeFile handles concurrent write attempts (#4316) @knolleary
- Migrate http -> https for nodered.org (#4313) @Rotzbua
- Add Node 20 to GH Action test matrix (#4305) @Rotzbua
- Handle group-scoped nodes inside subflow (#4301) @knolleary
- Handle non-url-safe chars in context api (#4298) @knolleary
- Fix git pull operation in project feature (#4290) @kazuhitoyokoi
- Change linefeed codes in Korean message catalogs (#4286) @kazuhitoyokoi
- Fix file permissions of message catalogs (#4285) @kazuhitoyokoi
- Update tour (#4278) @knolleary
Nodes
- File: Fix handling in file nodes when number is specified as file name (#4267) @kazuhitoyokoi
- Function: Adding function timeout to settings file (#4265) (#4309) @knolleary
- Function: Fix function setup tab layout (#4299) @knolleary
- HTTP Request: Handle 204 in httprequest JSON (#4262) @sammachin
- JSON: Fix test cases of JSON node (#4275) @kazuhitoyokoi
- MQTT: Remove unnecessary check for clientid if autoUnsub set (#4302) @knolleary
##### 3.1.0-beta.4: Beta Release
Editor
- Add Japanese translation for 3.1.0 (#4252) @kazuhitoyokoi
- Improve Catalogue visibility (#4248) @Steve-Mcl
- Add support for wiring and moving junctions on touch device (#4244) @Steve-Mcl
- Show errors and statuses of config nodes in the sidebar when no catch node is available (#4231) @bvmensvoort
- Improve wiring for horizontally aligned nodes (#4232) @knolleary
- French translation of Welcome Tours (#4200) @GogoVega
- French translation of v3.1.0-beta.3 changes (#4199) @GogoVega
- add Japanese message for 3.1.0 beta 3 (#4209) @HiroyasuNishiyama
- Dont clone the group nodes `node` array when saving edits (#4208) @Steve-Mcl
Runtime
- Add NR_SUBFLOW_NAME/ID/PATH env vars (#4250) @knolleary
- Evaluate all env vars as part of async flow start (#4230) @knolleary
- Add support for httpStatic middleware (#4229) @knolleary
Nodes
- Fix JSONata in file nodes (#4246) @kazuhitoyokoi
- Fix timeout icon in function and link call nodes (#4253) @kazuhitoyokoi
- Fix connection keep-alive in http request node (#4228) @knolleary
- adding timeout attribute to function node (#4177) @k1ln
- Fix manual mode join when multiple sequences being handled (#4143) @BitCaesar
- Fix delay node flush issue (#4203) @dceejay
- Update status and catch node labels in group mode (#4207) @Steve-Mcl
##### 3.1.0-beta.3: Beta Release
Editor
- Select the item that is specified in a deep link URL (#4113) @Steve-Mcl
- Update to Monaco 0.38.0 (#4189) @Steve-Mcl
- Place subflow outputs/inputs relative to current view (#4183) @knolleary
- Enable RED.view.select to select group by id (#4184) @knolleary
- Combine existing env vars when merging groups (#4182) @knolleary
- Avoid creating empty global-config node if not needed (#4153) @knolleary
- Fix group selection when using lasso (#4108) @knolleary
- Use editor path in generating localStorage keys (#4151) @mw75
- Ensure no node credentials are included when exporting to clipboard (#4112) @knolleary
- Fix jsonata expression test ui (#4097) @knolleary
- Fix search button in palette popover (#4096) @knolleary
Runtime
- Allow options object on each httpStatic configuration (#4109) @kevinGodell
- Ensure non-zero exit codes for errors (#4181) @knolleary
- Ensure external modules are installed synchronously (#4180) @knolleary
- Update dependecies include got (#4155) @knolleary
- Add Japanese translations for v3.1 beta.2 (#4158) @kazuhitoyokoi
- Ensure express server options are applied consistently (#4178) @knolleary
- Remove version info from theme endpoint (#4179) @knolleary
- Add Japanese translations for welcome tour of 3.1.0 beta.2 (#4145) @kazuhitoyokoi
- Added SHA-256 and SHA-512-256 digest authentication (#4100) @sroebert
- Add "timers" types to known types (#4103) @Steve-Mcl
Nodes
- Allow Catch/Status nodes to be scoped to their group (#4185) @NetHans
- MQTT: Option to disable MQTT topic unsubscribe on disconnect (#4078) @flying7eleven
##### 3.1.0-beta.2: Beta Release
Editor
- NEW: Add change icon to tabs (#4068) @knolleary
- NEW: Complete overhaul of Group UX (#4079) @knolleary
- NEW: Add link to node help in node edit dialog footer (#4065) @knolleary
- NEW: Added editor feature for connecting multiple nodes to single node (#4051) @sonntam
- NEW: Increase workspace size to 8000x8000 (#4094) @knolleary
- Ensure node buttons are redrawn when flow lock state is changed (#4091) @knolleary
- Prevent loops being created with junction nodes (#4087) @knolleary
- Prevent opening locked node's edit dialog (#4069) @knolleary
- Reverse direction of tab scroll to expected direction (#4064) @knolleary
- Add cancel operation to editableList (#4077) @HiroyasuNishiyama
- Apply Mermaid diagram for project settings UI (#4054) @kazuhitoyokoi
- Add tooltip for show/hide button on info sidebar (#4050) @kazuhitoyokoi
- Fix align nodes on locked tab (#4072) @HiroyasuNishiyama
- Fix importing connected link nodes into a subflow (#4082) @knolleary
- Fix to add empty marker to empty group (#4060) @HiroyasuNishiyama
- Fix image URLs for v3.0 tour (#4053) @kazuhitoyokoi
- Show scrollbar in notification dialog only when needed (#4048) @kazuhitoyokoi
- Update-monaco-and-typings (#4089) @Steve-Mcl
- Update jquery UI (#4088) @knolleary
- Support i18n of lock/unlock buttons in flow property UI (#4049) @kazuhitoyokoi
- Translation kr (#3895) @hae-iotplatform
- Translation zhcn (请懂中文的帮忙review) (#3952) @cliyr
- Add French translation of nodes (#3964) @GogoVega
- Add French translation (#3962) @GogoVega
- Portuguese Brazilian (pt-BR) translation (#3804) @FabsMuller
Runtime
- NEW: Generate stable ids for subflow instance internal nodes (#4093) @knolleary
- NEW: Change default file name to flows.json in project feature (#4073) @kazuhitoyokoi
- NEW: Deprecate synchronous access to jsonata (#4090) @knolleary
- Add Node 18 to test matrix (#4084) @knolleary
- Bump minimum nodejs version supported to match documented value (#4086) @knolleary
- Update monaco docs link in settings.js (#4075) @Steve-Mcl
- Remove duplicated messages in the message catalog (#4066) @kazuhitoyokoi
- Ensure errors in preDeliver callback are handled (#3911) @knolleary
- Fix "EADDRINUSE" error (#4046) @bggbr
Nodes
- Link Call: Clear link-call timeouts when node is closed (#4085) @knolleary
- Join: ensure inflight status is cleared when in auto mode (#4083) @knolleary
- File Out: Fix extra newline append for multipart file write (#3915) @dceejay
- Add validators for complete and link call nodes (#4056) @kazuhitoyokoi
##### 3.1.0-beta.1: Beta Release
Editor
- NEW: Locking Flows (#3938) @knolleary
- NEW: Improve UX around hiding flows via context menu (#3930) @knolleary
- NEW: Add support for inline image in markdown editor by drag and drop of an image file (#4006) @HiroyasuNishiyama
- NEW: Add support for mermaid diagram to markdown editor (#4007) @HiroyasuNishiyama
- NEW: Support uri fragments for nodes and groups including edit support (#3870) @knolleary
- NEW: Add global environment variable feature (#3941) @HiroyasuNishiyama
- Remember compact/pretty flow export user choice (#3974) @Steve-Mcl
- fix .red-ui-notification class (#4035) @xiaobinqt
- Fix border radius on Modules list header (#4038) @bonanitech
- fix workspace reference error in case of empty tabs (#4029) @HiroyasuNishiyama
- Disable delete tab menu when single tab exists (#4030) @HiroyasuNishiyama
- Disable hide all menu if all tabs hidden (#4031) @HiroyasuNishiyama
- fix hide subflow tooltip (#4033) @HiroyasuNishiyama
- Fix disabled menu items in project feature (#4027) @kazuhitoyokoi
- Let themes change radialMenu text colors (#3995) @bonanitech
- Add Japanese translations for v3.0.3 (#4012) @kazuhitoyokoi
- Add Japanese translation for v3.1.0-beta.0 (#3997) @kazuhitoyokoi
- Add Japanese translation for v3.1.0-beta.0 (#3916) @kazuhitoyokoi
- Hide subflow category after deleting subflow (#3980) @kazuhitoyokoi
- Prevent dbl-click opening node edit dialog with text selected (#3970) @knolleary
- Handle replacing unknown node inside group or subflow (#3921) @knolleary
- Fix #3939, red border red-ui-typedInput-container (#3949) @Steveorevo
- i18n item URL copy notification & add Japanese message (#3946) @HiroyasuNishiyama
- add Japanese message for item url copy actions (#3947) @HiroyasuNishiyama
- Fix autocomplete entry for responseUrl (#3884) @knolleary
- Fix Japanese translation for JSONata editor (#3872) @HiroyasuNishiyama
- Fix search type with spaces (#3841) @Steve-Mcl
- Fix error hanndling of JSONata expression editor for extended functions (#3871) @HiroyasuNishiyama
- Add button type to the adding SSH key button (#3866) @kazuhitoyokoi
- Check radio button as default in project dialog (#3879) @kazuhitoyokoi
- Add $clone as supported function (#3874) @HiroyasuNishiyama
- Env var jsonata (#3807) @HiroyasuNishiyama
- Add Japanese translation for v3.0.2 (#3852) @kazuhitoyokoi
Runtime
- Force IPv4 name resolution to have priority (#4019) @dceejay
- Fix async loading of modules containing both nodes and plugins (#3999) @knolleary
- Use main branch as default in project feature (#4036) @kazuhitoyokoi
- Rename package var to avoid strict mode error (#4020) @knolleary
- Fix typos in settings.js (#4013) @ypid
- Ensure credentials object is removed before returning node in getFlow request (#3971) @knolleary
- Ignore commit error in project feature (#3987) @kazuhitoyokoi
- Update dependencies (#3969) @knolleary
- Add check that node sends object rather than primitive type (#3909) @knolleary
- Ensure key_path is quoted in GIT_SSH_COMMAND in case of spaces in pathname (#3912) @knolleary
- Fix nodesDir scan when node package has js/html in sub dir to package.json (#3867) @Steve-Mcl
- Fix file permissions (#3917) @kazuhitoyokoi
- ci: add minimum GitHub token permissions for workflows (#3907) @boahc077
Nodes
- Catch: fix typo in catch.html (#3965) @we11adam
- Change: Fix change node overwriting msg with itself (#3899) @dceejay
- Comment node: Clarify where the text will appear (#4004) @dirkjanfaber
- CSV: change replace to replaceAll (#3990) @dceejay
- CSV node: check header properties for ' and " (#3920) @dceejay
- CSV: Fix for CSV undefined property (#3906) @dceejay
- Delay: let delay node handle both flush then reset (#3898) @dceejay
- Function: Limit number of ports in function node (#3886) @kazuhitoyokoi
- Function: Remove dot from variable name for external module in function node (#3880) @kazuhitoyokoi
- Function: add function node monaco types util and promisify (#3868) @Steve-Mcl
- HTTP In: Ensure msg.req.headers is enumerable (#3908) @knolleary
- HTTP Request: Support form-data arrays (#3991) @hardillb
- HTTP Request: Fix httprequest tests to be more lenient on error message (#3922) @knolleary
- HTTP Request: Add missing property to node object HTTPRequest (#3842) @hardillb
- HTTP Request/Response: Support sortable list on property UI of http request and http response nodes (#3857) @kazuhitoyokoi
- HTTP Response: Ensure statusCode is a number (#3894) @hardillb
- Inject: Allow Inject node to work with async context stores (#4021) @knolleary
- Join/Batch: Add count to join and batch node labels (#4028) @dceejay
- MQTT: Fix birth topic handling in MQTT node (#3905) @Steve-Mcl
- MQTT: Fix pull-down menus of MQTT configuration node (#3890) @kazuhitoyokoi
- MQTT: Prevent invalid mqtt birth topic crashing node-red (#3869) @Steve-Mcl
- MQTT: ensure sessionExpiry(Interval) is applied (#3840) @Steve-Mcl
- MQTT: Fix mqtt nodes not reconnecting on modified-flows deploy (#3992) @knolleary
- MQTT: fix single subscription mqtt node status (#3966) @Steve-Mcl
- Range: Add drop mode to range node (#3935) @dceejay
- Remove done from describe (#3873) @HiroyasuNishiyama
- Split node: avoid duplicate done call for buffer split (#4000) @knolleary
- Status: Fix typo in 25-status.html (#3981) @kazuhitoyokoi
- TCP Node: ensure newline substitution applies to whole message (#4009) @dceejay
- Template: Add information about environment variable to template node (#3882) @kazuhitoyokoi
- Trigger: Hide trigger node repeat send option if sending nothing (#4023) @dceejay
- Watch: fix watch node test on MacOS/ARM (#3942) @HiroyasuNishiyama
#### 3.0.2: Maintenance Release
Editor
- Fix workspace chart bottom property (#3812) @bonanitech
- Update german translation (#3802) @Dennis14e
- Support color reset to the default in subflow and group (#3801) @kazuhitoyokoi
- Allow generateNodeNames to handle names containing regex control chars (#3817) @knolleary
- Hide scrollbars until they're needed (#3808) @bonanitech
- Include junctions/groups when exporting subflows plus related fixes (#3816) @knolleary
- remove console.log (#3820) @Steve-Mcl
Runtime
- Register subflow module instance node with parent flow (#3818) @knolleary
Nodes
- HTTP Request: Allow HTTP Headers not in spec (#3776) @hardillb
#### 3.0.1: Maintenance Release
Editor
- Allow codeEditor theme to be set even if `codeEditor` is not set in settings.js (#3794) @Steve-Mcl
- Sys info (diagnostics report) amendments (#3793) @Steve-Mcl
- Allow `mode` and `title` to be omitted in `options` argument for `createEditor` (#3791) @Steve-Mcl
- Fix focus issues (#3789) @Steve-Mcl
- Ensure all typedInput buttons have button type set (#3788) @knolleary
- Do not flag hasUsers=false nodes as unused in search (#3787) @knolleary
- Properly position quick-add dialog in all cases (#3786) @knolleary
- Ensure quick-add dialog does not obscure ghost node when shifted (#3785) @knolleary
- Remove use of Object.hasOwn (#3784) @knolleary
#### 3.0.0: Milestone Release
Editor
- Use theme page and header values if settings.js values are not present (#3767) @Steve-Mcl
- Focus editor for undo after some actions in menu (#3759) @kazuhitoyokoi
- Ensure node icon shade has properly rounded corners (#3763) @knolleary
- Fix storing subflow credential type when input has multiple types (#3762) @knolleary
- Ensure global-config and flow-config have info in the hierarchy popover (#3752) @Steve-Mcl
- Include dirty state in history event (#3748) @Steve-Mcl
- Fix display direction of context sub-menu (#3746) @knolleary
- Fix clear pinned paths of debug sidebar menu (#3745) @HiroyasuNishiyama
- prevent exception generating tooltip for deleted nodes (#3742) @Steve-Mcl
- Fix context menu issues ready for v3 beta.5 (#3741) @Steve-Mcl
- Do not generate new node-ids when pasting a cut flow (#3729) @knolleary
- Fix to prevent node from moving out of workspace (#3731) @HiroyasuNishiyama
- Don't let themes change disabled config node background color (#3736) @bonanitech
- Move colors left behind in #3692 to CSS variables (#3737) @bonanitech
- Fix handling of global debug message (#3733) @HiroyasuNishiyama
- Fix label overflow @ config-node palette (#3730) @ralphwetzel
- Fix defaulting to monaco if settings does not contain codeEditor (#3732) @knolleary
- Disable keyboard shortcut mapping when showing Edit[..]Dialog (#3700) @ralphwetzel
- Update add-junction menu to work in more cases (#3727) @knolleary
- Ensure importMap is not null when using import UI (#3723) @Steve-Mcl
- Add Japanese translations for v3.0-beta.4 (#3724) @kazuhitoyokoi
- Fix "split with" on virtual links (#3766) @Steve-Mcl
Runtime
- Do not remove unknown credentials of Subflow Modules (#3728) @knolleary
- Add missing entries from beta.4 changelog (#3721) @knolleary
Nodes
- Change: Fix change node, not handling from field properly when using context (#3754) @Fadoli
- Link Call: Fix linkcall registry bugs (#3751) @Steve-Mcl
- WebSocket: Fix close timeout of websocket node (#3734) @HiroyasuNishiyama
#### 3.0.0-beta.4: Beta Release
Editor
- Move all colours to CSS variables (#3692) @bonanitech
- Fix clicking on node in workspace to hide context menu (#3696) @knolleary
- Fix credential type input item of subflow template (#3703) @HiroyasuNishiyama
- Add option flag `reimport` to `importNodes` (#3718) @Steve-Mcl
- Update german translation (#3691) @Dennis14e
- List welcome tours in help sidebar (#3717) @knolleary
- Ensure 'hidden flow' count doesn't include subflows (#3715) @knolleary
- Fix Chinese translate (#3706) @hotlong
- Fix use default button for node icon (#3714) @kazuhitoyokoi
- Fix select boxes vertical alignment (#3698) @bonanitech
- Ensure workspace clean after undoing dropped node (#3708) @Steve-Mcl
- Use solid colour as config node icon background to hide text overflow (#3710) @Steve-Mcl
- Increase quick-add height to reveal 2 most recent entries (#3711) @Steve-Mcl
- Set default editor to monaco in absence of user preference (#3702) @knolleary
- Add Japanese translations for v3.0-beta.3 (#3688) @kazuhitoyokoi
- Fix handling of spacebar inside JSON visual editor (#3687) @knolleary
- Fix menu padding to handle both icons and submenus (#3686) @knolleary
- Include scroll offset when positioning quick-add dialog (#3685) @knolleary
Runtime
- Allow flows to be stopped and started manually (#3719) @knolleary
- Import default export if node is a transpiled es module (#3669) @dschmidt
- Leave Monaco theme commented out by default (#3704) @bonanitech
Nodes
- CSV: Fix CSV node to handle when outputting text fields (#3716) @dceejay
- Delay: Fix delay rate limit last timing when empty (#3709) @dceejay
- Link: Ensure link-call cache is updated when link-in is modified (#3695) @Steve-Mcl
- Join: Join node in reduce mode doesn't keep existing msg properties (#3670) @dceejay
- Template: Add support for evalulating {{env.<var>}} within a template node (#3690) @cow0w
#### 3.0.0-beta.3: Beta Release
Editor
- Add Right-Click content menu (#3678) @knolleary
- Fix disable junction (#3671) @HiroyasuNishiyama
- Add Japanese translations for v2.2.3 (#3672) @kazuhitoyokoi
- Reset mouse state when switching tabs (#3643) @knolleary
- Fix uncorrect fix of junction to subflow conversion (#3666) @HiroyasuNishiyama
- Fix undoing junction to subflow (#3653) @HiroyasuNishiyama
- Fix conversion of junction to subflow (#3652) @HiroyasuNishiyama
- Fix to include junction to exported nodes (#3650) @HiroyasuNishiyama
- Fix z-index value for shade to cover nodes in palette (#3649) @kazuhitoyokoi
- Fix to extend escaped subflow category characters (#3647) @HiroyasuNishiyama
- Fix to sanitize tab name (#3646) @HiroyasuNishiyama
- Fix selector placement (#3644) @bonanitech
- Add Japanese translations for v3.0-beta.2 (#3622) @kazuhitoyokoi
- Fix new folder menu of save to library dialog (#3633) @HiroyasuNishiyama
- Fix layer of palette node (#3638) @HiroyasuNishiyama
- Fix to place a node dragged from palette within the workspace (#3637) @HiroyasuNishiyama
- Fix typo in CSS (#3628) @bonanitech
- Use the correct variable for the gutter text color (#3615) @bonanitech
Runtime
- Support loading node modules from `nodesdir` (#3676) @Steve-Mcl
- fix buffer parse error message of evaluateNodeProperty (#3624) @HiroyasuNishiyama
Nodes
- File: Further simplify file node filename entry UX (v3) (#3677) @Steve-Mcl
- Function: Fix initial cursor position of init/finalize tab of function node (#3674) @HiroyasuNishiyama
- Function: Fix ESM module loading in Function node (#3645) @knolleary
- Inject: Fix JSONata evaluation of inject button (#3632) @HiroyasuNishiyama
- TCP: Dont delete TCP socket twice (#3630) @Steve-Mcl
- MQTT Node: define noproxy variable (#3626) @Steve-Mcl
- Debug: i18n debug sidebar node label (#3623) @HiroyasuNishiyama
#### 3.0.0-beta.2: Beta Release
**Migration from 2.x**
- The 'slice wires' action has changed from Ctrl-RightMouseButton to Alt-LeftMouseButton
Editor
- Rework Junctions to be more node like in their event handling (#3607) @knolleary
- Change slicing / slice-junction operations over to mouse button 0 (Left Mouse Button) (#3609) @Steve-Mcl
- Do not slice-junction link node wires (#3608) @knolleary
- Handle many-to-one slicing of wires (#3604) @knolleary
- Ensure ACE worker options are set (#3611) @Steve-Mcl
- Remove duplicate history add of ungroup event (#3605) @knolleary
- use text width instead of number of characters for deciding select fi… (#3603) @HiroyasuNishiyama
- Update Japanese info of link call node reflecting update of English info (#3600) @HiroyasuNishiyama
- Fix typedInput label not visible on themes (#3580) @bonanitech
- Fix project switching when junctions are present (#3595) @Steve-Mcl
- Fix junction: when wiring from a regular nodes INPUT, backwards to a junction (#3591) @Steve-Mcl
- Fix error initialising flow tab editor (#3585) @Steve-Mcl
- Add Japanese translations for v3.0-beta.1 (#3576) @kazuhitoyokoi
- Fix image paths where `red/image/typedInput/XXXX.png` should be `red/image/typedInput/XXXX.svg` (#3592) @kazuhitoyokoi
- Fix browser console error Uncaught TypeError when searching certain terms (#3584) @Steve-Mcl
Runtime
- fix error on system-info action (#3589) @HiroyasuNishiyama
Nodes
- I18n switch rule selector (#3602) @HiroyasuNishiyama
- Handle removal of event handlers to allow mqtt client.end() to work (#3594) @PhilDay-CT
- update link-call node info according to current behavior (#3597) @HiroyasuNishiyama
#### 3.0.0-beta.1: Beta Release
**Migration from 2.x**
- Node-RED now requires Node.js 14.x or later.
- New installs of Node-RED will default to the monaco editor.
Editor
- Add Junctions (#3462) @knolleary
- Allow node name to be auto-generated when added (#3478, #3538) @knolleary
- Set monaco as default code editor as of v3.x (#3543) @Steve-Mcl
- Update Monaco to V0.33.0 (#3522) @Steve-Mcl
- Auto-complete Improvements (#3521) @Steve-Mcl
- Add a tooltip to debug sidebar messages to reveal full path to node (#3503) @knolleary
- Fix down arrow triggering menu in search box (#3507) @Steve-Mcl
- Add Japanese translations for v3.0 (#3512) @kazuhitoyokoi
- Add feature: Continuous search tools (search previous, search next) (#3405) @Steve-Mcl
- Add feature: split-wire-to-links (#3399, #3476) @Steve-Mcl
- Add copy button to node properties tables (#3390) @knolleary
- Add info-tab search options dropdown to the regular search (#3395) @Steve-Mcl
- New Feature: Add ability to find modified nodes/flows. (#3392) @Steve-Mcl
- Code editor ux improvements around remembering state of each code editor in a flow (#3553) @Steve-Mcl
- Make it easier to apply themes on SVG icons (#3515) @bonanitech
- Add support of property validation message (#3438) @HiroyasuNishiyama
- Ensure node validation tooltip is closed when field becomes valid (#3570) @knolleary
- Add "search for" buttons to notifications (#3567) @Steve-Mcl
- Don't let themes change node config colors (#3564) @bonanitech
- Fix gap between typedInput containers borders (#3560) @bonanitech
- Fix recording removed links in edit history (#3547) @knolleary
- Remove unused SASS vars (#3536) @bonanitech
- Add custom style for jQuery widgets borders (#3537) @bonanitech
- fix out of scope reference of hasUnusedConfig variable (#3535) @HiroyasuNishiyama
- correct "non string" check parenthesis (#3524) @Steve-Mcl
- Ensure i18n of scoped package name (#3516) @Steve-Mcl
- Prevent shortcut deploy when deploy button shaded (#3517) @Steve-Mcl
- Fix: Sidebar "Configuration" filter button tooltip (#3500) @ralphwetzel
- Add the ability to customize diff colors even more (#3499) @bonanitech
- Do JSON comparison of old value/new value in editor (#3481) @Steve-Mcl
- Fix nodes losing their wires when in an iframe (#3484) @zettca
- Improve scroll into view (#3468) @Steve-Mcl
- Do not show 1st tab if hidden when loading (#3464) @Steve-Mcl
Runtime
- Fix importing external module from node-red module (#3541) @knolleary
- Add support for multiple static paths with optional static root (#3542) @Steve-Mcl
- Store external token when authenticating if provided (#3460) @ArFe
- Support OAuth/OpenID logout (#3388) @mw75
- Allow adminAuth to auto-login users when using passport strategy (#3519) @knolleary
- Add runtime diagnostics admin endpoint (#3511) @Steve-Mcl
- Don't start if user has no home directory (#3540) @hardillb
- Error on invalid encrypted credentials (#3498) @sammachin
Nodes
- Debug: Add message count option to Debug status (#3544 #3551) @rafaelmuynarsk @knolleary
- File: Change basic Filename field to a typedInput (#3533) @Steve-Mcl
- HTTP Request: Add UI for Http Request node headers (#3488) @Steve-Mcl
- Inject: let inject optionally fire at start in only at time mode. (#3385) @dceejay
- Link Call: Dynamic link call (#3463) @Steve-Mcl
- Link Call: Display link targets of nodes in a regular flow, for Link Call nodes inside a subflow (#3528) @Steve-Mcl
- MQTT: MQTT payload auto parsing improvements (#3530) @Steve-Mcl
- MQTT: Add client and Runtime MQTT topic validation (#3563) @Steve-Mcl [dev]
- MQTT: save and restore v5 config user props (#3562) @Steve-Mcl
- MQTT: Fix incorrect MQTT status (#3552) @Steve-Mcl
- MQTT: fix reference error of msg.status in debug node (#3526) @HiroyasuNishiyama
- MQTT: Add unit tests for MQTT nodes (#3497) @Steve-Mcl
- MQTT: fix typo of will properties (#3502) @Steve-Mcl
- MQTT: ensure mqtt v5 props can be set false (#3472) @Steve-Mcl
- Switch: add check for NaN in is of type number to be false (#3409) @dceejay
- TCP: TCP node better split (#3465) @dceejay
- Watch: Update Watch node to use node-watch module (#3559 #3569) @knolleary
- WebSocket: call done after ws disconnects (#3531) @Steve-Mcl
#### Older Releases
Change logs for older releases are available on GitHub: https://github.com/node-red/node-red/releases

View File

@@ -208,38 +208,52 @@ module.exports = function(grunt) {
"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"
],
nonull: true,
dest: "packages/node_modules/@node-red/editor-client/public/red/red.js"
},
vendor: {
files: {
"packages/node_modules/@node-red/editor-client/public/vendor/vendor.js": [
"packages/node_modules/@node-red/editor-client/src/vendor/jquery/js/jquery-3.5.1.min.js",
"packages/node_modules/@node-red/editor-client/src/vendor/jquery/js/jquery-migrate-3.3.0.min.js",
"packages/node_modules/@node-red/editor-client/src/vendor/jquery/js/jquery-ui.min.js",
"packages/node_modules/@node-red/editor-client/src/vendor/jquery/js/jquery.ui.touch-punch.min.js",
"node_modules/marked/marked.min.js",
"node_modules/dompurify/dist/purify.min.js",
"packages/node_modules/@node-red/editor-client/src/vendor/d3/d3.v3.min.js",
"node_modules/i18next/i18next.min.js",
"node_modules/i18next-http-backend/i18nextHttpBackend.min.js",
"node_modules/jquery-i18next/jquery-i18next.min.js",
"node_modules/jsonata/jsonata-es5.min.js",
"packages/node_modules/@node-red/editor-client/src/vendor/jsonata/formatter.js",
"packages/node_modules/@node-red/editor-client/src/vendor/ace/ace.js",
"packages/node_modules/@node-red/editor-client/src/vendor/ace/ext-language_tools.js"
],
// "packages/node_modules/@node-red/editor-client/public/vendor/vendor.css": [
// // TODO: resolve relative resource paths in
// // bootstrap/FA/jquery
// ],
"packages/node_modules/@node-red/editor-client/public/vendor/ace/worker-jsonata.js": [
"node_modules/jsonata/jsonata-es5.min.js",
"packages/node_modules/@node-red/editor-client/src/vendor/jsonata/worker-jsonata.js"
],
"packages/node_modules/@node-red/editor-client/public/vendor/mermaid/mermaid.min.js": [
"node_modules/mermaid/dist/mermaid.min.js"
]
}
files: [
{
src: [
"packages/node_modules/@node-red/editor-client/src/vendor/jquery/js/jquery-3.5.1.min.js",
"packages/node_modules/@node-red/editor-client/src/vendor/jquery/js/jquery-migrate-3.3.0.min.js",
"packages/node_modules/@node-red/editor-client/src/vendor/jquery/js/jquery-ui.min.js",
"packages/node_modules/@node-red/editor-client/src/vendor/jquery/js/jquery.ui.touch-punch.min.js",
"node_modules/marked/marked.min.js",
"node_modules/dompurify/dist/purify.min.js",
"packages/node_modules/@node-red/editor-client/src/vendor/d3/d3.v3.min.js",
"node_modules/i18next/i18next.min.js",
"node_modules/i18next-http-backend/i18nextHttpBackend.min.js",
"node_modules/jquery-i18next/jquery-i18next.min.js",
"node_modules/jsonata/jsonata-es5.min.js",
"packages/node_modules/@node-red/editor-client/src/vendor/jsonata/formatter.js",
"packages/node_modules/@node-red/editor-client/src/vendor/ace/ace.js",
"packages/node_modules/@node-red/editor-client/src/vendor/ace/ext-language_tools.js"
],
nonull: true,
dest: "packages/node_modules/@node-red/editor-client/public/vendor/vendor.js"
},
// {
// src: [
// // TODO: resolve relative resource paths in
// // bootstrap/FA/jquery
// ],
// dest: "packages/node_modules/@node-red/editor-client/public/vendor/vendor.css"
// },
{
src: [
"node_modules/jsonata/jsonata-es5.min.js",
"packages/node_modules/@node-red/editor-client/src/vendor/jsonata/worker-jsonata.js"
],
nonull: true,
dest: "packages/node_modules/@node-red/editor-client/public/vendor/ace/worker-jsonata.js",
},
{
src: "node_modules/mermaid/dist/mermaid.min.js",
nonull: true,
dest: "packages/node_modules/@node-red/editor-client/public/vendor/mermaid/mermaid.min.js",
},
]
}
},
uglify: {

View File

@@ -1,6 +1,6 @@
{
"name": "node-red",
"version": "4.0.0-beta.1",
"version": "4.1.0-beta.0",
"description": "Low-code programming for event-driven applications",
"homepage": "https://nodered.org",
"license": "Apache-2.0",
@@ -26,25 +26,25 @@
}
],
"dependencies": {
"acorn": "8.8.2",
"acorn-walk": "8.2.0",
"ajv": "8.12.0",
"async-mutex": "0.4.0",
"acorn": "8.11.3",
"acorn-walk": "8.3.2",
"ajv": "8.14.0",
"async-mutex": "0.5.0",
"basic-auth": "2.0.1",
"bcryptjs": "2.4.3",
"body-parser": "1.20.2",
"cheerio": "1.0.0-rc.10",
"clone": "2.1.2",
"content-type": "1.0.5",
"cookie": "0.5.0",
"cookie": "0.6.0",
"cookie-parser": "1.4.6",
"cors": "2.8.5",
"cronosjs": "1.7.1",
"denque": "2.1.0",
"express": "4.18.2",
"express-session": "1.17.3",
"express": "4.19.2",
"express-session": "1.18.0",
"form-data": "4.0.0",
"fs-extra": "11.1.1",
"fs-extra": "11.2.0",
"got": "12.6.0",
"hash-sum": "2.0.0",
"hpagent": "1.2.0",
@@ -54,35 +54,36 @@
"is-utf8": "0.2.1",
"js-yaml": "4.1.0",
"json-stringify-safe": "5.0.1",
"jsonata": "2.0.4",
"jsonata": "2.0.5",
"lodash.clonedeep": "^4.5.0",
"media-typer": "1.1.0",
"memorystore": "1.6.7",
"mime": "3.0.0",
"moment": "2.29.4",
"moment-timezone": "0.5.43",
"mqtt": "4.3.7",
"moment": "2.30.1",
"moment-timezone": "0.5.45",
"mqtt": "5.7.0",
"multer": "1.4.5-lts.1",
"mustache": "4.2.0",
"node-red-admin": "^3.1.2",
"node-red-admin": "^4.0.0",
"node-watch": "0.7.4",
"nopt": "5.0.0",
"oauth2orize": "1.11.1",
"oauth2orize": "1.12.0",
"on-headers": "1.0.2",
"passport": "0.6.0",
"passport": "0.7.0",
"passport-http-bearer": "1.0.1",
"passport-oauth2-client-password": "0.1.2",
"raw-body": "2.5.2",
"rfdc": "^1.3.1",
"semver": "7.5.4",
"tar": "6.1.13",
"tough-cookie": "4.1.3",
"tar": "7.2.0",
"tough-cookie": "4.1.4",
"uglify-js": "3.17.4",
"uuid": "9.0.0",
"ws": "7.5.6",
"uuid": "9.0.1",
"ws": "7.5.10",
"xml2js": "0.6.2"
},
"optionalDependencies": {
"bcrypt": "5.1.1"
"@node-rs/bcrypt": "1.10.4"
},
"devDependencies": {
"dompurify": "2.4.1",
@@ -112,7 +113,7 @@
"mermaid": "^10.4.0",
"minami": "1.2.3",
"mocha": "9.2.2",
"node-red-node-test-helper": "^0.3.2",
"node-red-node-test-helper": "^0.3.3",
"nodemon": "2.0.20",
"proxy": "^1.0.2",
"sass": "1.62.1",
@@ -122,6 +123,6 @@
"supertest": "6.3.3"
},
"engines": {
"node": ">=18"
"node": ">=18.5"
}
}

View File

@@ -91,6 +91,7 @@ module.exports = {
// Plugins
adminApp.get("/plugins", needsPermission("plugins.read"), plugins.getAll, apiUtil.errorHandler);
adminApp.get("/plugins/messages", needsPermission("plugins.read"), plugins.getCatalogs, apiUtil.errorHandler);
adminApp.get(/^\/plugins\/((@[^\/]+\/)?[^\/]+)\/([^\/]+)$/,needsPermission("plugins.read"),plugins.getConfig,apiUtil.errorHandler);
adminApp.get("/diagnostics", needsPermission("diagnostics.read"), diagnostics.getReport, apiUtil.errorHandler);

View File

@@ -40,5 +40,31 @@ module.exports = {
console.log(err.stack);
apiUtils.rejectHandler(req,res,err);
})
},
getConfig: function(req, res) {
let opts = {
user: req.user,
module: req.params[0],
req: apiUtils.getRequestLogObject(req)
}
if (req.get("accept") === "application/json") {
runtimeAPI.nodes.getNodeInfo(opts.module).then(function(result) {
res.send(result);
}).catch(function(err) {
apiUtils.rejectHandler(req,res,err);
})
} else {
opts.lang = apiUtils.determineLangFromHeaders(req.acceptsLanguages());
if (/[^0-9a-z=\-\*]/i.test(opts.lang)) {
opts.lang = "en-US";
}
runtimeAPI.plugins.getPluginConfig(opts).then(function(result) {
return res.send(result);
}).catch(function(err) {
apiUtils.rejectHandler(req,res,err);
})
}
}
};

View File

@@ -160,20 +160,34 @@ function completeVerify(profile,done) {
function genericStrategy(adminApp,strategy) {
var crypto = require("crypto")
var session = require('express-session')
var MemoryStore = require('memorystore')(session)
const crypto = require("crypto")
const session = require('express-session')
const MemoryStore = require('memorystore')(session)
adminApp.use(session({
// As the session is only used across the life-span of an auth
// hand-shake, we can use a instance specific random string
secret: crypto.randomBytes(20).toString('hex'),
resave: false,
saveUninitialized: false,
store: new MemoryStore({
checkPeriod: 86400000 // prune expired entries every 24h
})
}));
const sessionOptions = {
// As the session is only used across the life-span of an auth
// hand-shake, we can use a instance specific random string
secret: crypto.randomBytes(20).toString('hex'),
resave: false,
saveUninitialized: false,
store: new MemoryStore({
checkPeriod: 86400000 // prune expired entries every 24h
})
}
if (settings.httpAdminCookieOptions) {
sessionOptions.cookie = {
path: '/',
httpOnly: true,
secure: false,
maxAge: null,
...settings.httpAdminCookieOptions
}
if (sessionOptions.cookie.name){
sessionOptions.name = sessionOptions.cookie.name
delete sessionOptions.cookie.name
}
}
adminApp.use(session(sessionOptions));
//TODO: all passport references ought to be in ./auth
adminApp.use(passport.initialize());
adminApp.use(passport.session());
@@ -205,11 +219,12 @@ function genericStrategy(adminApp,strategy) {
passport.use(new strategy.strategy(options, verify));
adminApp.get('/auth/strategy',
passport.authenticate(strategy.name, {session:false,
failureMessage: true,
failureRedirect: settings.httpAdminRoot
passport.authenticate(strategy.name, {
session:false,
failWithError: true,
failureMessage: true
}),
completeGenerateStrategyAuth,
completeGenericStrategyAuth,
handleStrategyError
);
@@ -221,14 +236,14 @@ function genericStrategy(adminApp,strategy) {
passport.authenticate(strategy.name, {
session:false,
failureMessage: true,
failureRedirect: settings.httpAdminRoot
failWithError: true
}),
completeGenerateStrategyAuth,
completeGenericStrategyAuth,
handleStrategyError
);
}
function completeGenerateStrategyAuth(req,res) {
function completeGenericStrategyAuth(req,res) {
var tokens = req.user.tokens;
delete req.user.tokens;
// Successful authentication, redirect home.
@@ -238,6 +253,8 @@ function handleStrategyError(err, req, res, next) {
if (res.headersSent) {
return next(err)
}
// Remove the header that passport auto-adds as we don't need it
res.removeHeader('WWW-Authenticate')
log.audit({event: "auth.login.fail.oauth",error:err.toString()});
res.redirect(settings.httpAdminRoot + '?session_message='+err.toString());
}

View File

@@ -25,7 +25,7 @@ function hasPermission(userScope,permission) {
}
var i;
if (util.isArray(permission)) {
if (Array.isArray(permission)) {
// Multiple permissions requested - check each one
for (i=0;i<permission.length;i++) {
if (!hasPermission(userScope,permission[i])) {
@@ -36,7 +36,7 @@ function hasPermission(userScope,permission) {
return true;
}
if (util.isArray(userScope)) {
if (Array.isArray(userScope)) {
if (userScope.length === 0) {
return false;
}

View File

@@ -17,7 +17,7 @@
var util = require("util");
var clone = require("clone");
var bcrypt;
try { bcrypt = require('bcrypt'); }
try { bcrypt = require('@node-rs/bcrypt'); }
catch(e) { bcrypt = require('bcryptjs'); }
var users = {};
var defaultUser = null;
@@ -33,11 +33,11 @@ function authenticate() {
if (args.length === 2) {
// Username/password authentication
var password = args[1];
return new Promise(function(resolve,reject) {
bcrypt.compare(password, user.password, function(err, res) {
resolve(res?cleanUser(user):null);
});
});
return bcrypt.compare(password, user.password).then(res => {
return res ? cleanUser(user) : null
}).catch(err => {
return null
})
} else {
// Try to extract common profile information
if (args[0].hasOwnProperty('photos') && args[0].photos.length > 0) {
@@ -74,7 +74,7 @@ function init(config) {
} else {
var us = config.users;
/* istanbul ignore else */
if (!util.isArray(us)) {
if (!Array.isArray(us)) {
us = [us];
}
for (var i=0;i<us.length;i++) {

View File

@@ -70,7 +70,7 @@ function serveFilesFromTheme(themeValue, themeApp, directory, baseDirectory) {
var result = [];
if (themeValue) {
var array = themeValue;
if (!util.isArray(array)) {
if (!Array.isArray(array)) {
array = [array];
}

View File

@@ -1,6 +1,6 @@
{
"name": "@node-red/editor-api",
"version": "4.0.0-beta.1",
"version": "4.1.0-beta.0",
"license": "Apache-2.0",
"main": "./lib/index.js",
"repository": {
@@ -16,25 +16,25 @@
}
],
"dependencies": {
"@node-red/util": "4.0.0-beta.1",
"@node-red/editor-client": "4.0.0-beta.1",
"@node-red/util": "4.1.0-beta.0",
"@node-red/editor-client": "4.1.0-beta.0",
"bcryptjs": "2.4.3",
"body-parser": "1.20.2",
"clone": "2.1.2",
"cors": "2.8.5",
"express-session": "1.17.3",
"express": "4.18.2",
"express-session": "1.18.0",
"express": "4.19.2",
"memorystore": "1.6.7",
"mime": "3.0.0",
"multer": "1.4.5-lts.1",
"mustache": "4.2.0",
"oauth2orize": "1.11.1",
"oauth2orize": "1.12.0",
"passport-http-bearer": "1.0.1",
"passport-oauth2-client-password": "0.1.2",
"passport": "0.6.0",
"ws": "7.5.6"
"passport": "0.7.0",
"ws": "7.5.10"
},
"optionalDependencies": {
"bcrypt": "5.1.0"
"@node-rs/bcrypt": "1.10.4"
}
}

View File

@@ -590,6 +590,8 @@
},
"nodeCount": "__label__ Node",
"nodeCount_plural": "__label__ Nodes",
"pluginCount": "__count__ Plugin",
"pluginCount_plural": "__count__ Plugins",
"moduleCount": "__count__ Modul verfügbar",
"moduleCount_plural": "__count__ Module verfügbar",
"inuse": "In Gebrauch",

View File

@@ -27,7 +27,8 @@
"lock": "Lock",
"unlock": "Unlock",
"locked": "Locked",
"unlocked": "Unlocked"
"unlocked": "Unlocked",
"format": "Format"
},
"type": {
"string": "string",
@@ -372,6 +373,7 @@
"deleted": "deleted",
"flowDeleted": "flow deleted",
"flowAdded": "flow added",
"moved": "moved",
"movedTo": "moved to __id__",
"movedFrom": "moved from __id__"
},
@@ -614,8 +616,12 @@
},
"nodeCount": "__label__ node",
"nodeCount_plural": "__label__ nodes",
"pluginCount": "__count__ plugin",
"pluginCount_plural": "__count__ plugins",
"moduleCount": "__count__ module available",
"moduleCount_plural": "__count__ modules available",
"updateCount": "__count__ update available",
"updateCount_plural": "__count__ updates available",
"inuse": "in use",
"enableall": "enable all",
"disableall": "disable all",
@@ -641,6 +647,7 @@
"errors": {
"catalogLoadFailed": "<p>Failed to load node catalogue.</p><p>Check the browser console for more information</p>",
"installFailed": "<p>Failed to install: __module__</p><p>__message__</p><p>Check the log for more information</p>",
"installTimeout": "<p>Install continuing the background.</p><p>Nodes will appear in palette when complete. Check the log for more information.</p>",
"removeFailed": "<p>Failed to remove: __module__</p><p>__message__</p><p>Check the log for more information</p>",
"updateFailed": "<p>Failed to update: __module__</p><p>__message__</p><p>Check the log for more information</p>",
"enableFailed": "<p>Failed to enable: __module__</p><p>__message__</p><p>Check the log for more information</p>",
@@ -655,6 +662,9 @@
"body": "<p>Removing '__module__'</p><p>Removing the node will uninstall it from Node-RED. The node may continue to use resources until Node-RED is restarted.</p>",
"title": "Remove nodes"
},
"removePlugin": {
"body": "<p>Removed plugin __module__. Please reload the editor to clear left-overs.</p>"
},
"update": {
"body": "<p>Updating '__module__'</p><p>Updating the node will require a restart of Node-RED to complete the update. This must be done manually.</p>",
"title": "Update nodes"
@@ -666,7 +676,8 @@
"review": "Open node information",
"install": "Install",
"remove": "Remove",
"update": "Update"
"update": "Update",
"understood": "Understood"
}
}
}
@@ -719,6 +730,7 @@
"nodeHelp": "Node Help",
"showHelp": "Show help",
"showInOutline": "Show in outline",
"hideTopics": "Hide topics",
"showTopics": "Show topics",
"noHelp": "No help topic selected",
"changeLog": "Change Log"
@@ -914,6 +926,8 @@
}
},
"typedInput": {
"selected": "__count__ selected",
"selected_plural": "__count__ selected",
"type": {
"str": "string",
"num": "number",

View File

@@ -27,7 +27,8 @@
"lock": "Verrouiller",
"unlock": "Déverrouiller",
"locked": "Verrouillé",
"unlocked": "Déverrouillé"
"unlocked": "Déverrouillé",
"format": "Format"
},
"type": {
"string": "chaîne de caractères",
@@ -54,10 +55,10 @@
"workspace": {
"defaultName": "Flux __number__",
"editFlow": "Modifier le flux : __name__",
"confirmDelete": "Confirmation de la suppression",
"delete": "Etes-vous sûr de vouloir supprimer '__label__'?",
"dropFlowHere": "Déposer le flux ici",
"dropImageHere": "Déposer l'image ici",
"confirmDelete": "Confirmer la suppression",
"delete": "Êtes-vous sûr de vouloir supprimer '__label__' ?",
"dropFlowHere": "Lâchez le flux ici",
"dropImageHere": "Lâchez l'image ici",
"addFlow": "Ajouter un flux",
"addFlowToRight": "Ajouter un flux à droite",
"closeFlow": "Fermer le flux",
@@ -74,7 +75,7 @@
"enabled": "Activé",
"disabled": "Désactivé",
"info": "Description",
"selectNodes": "Cliquer sur les noeuds pour sélectionner",
"selectNodes": "Cliquer pour sélectionner",
"enableFlow": "Activer le flux",
"disableFlow": "Désactiver le flux",
"lockFlow": "Verrouiller le flux",
@@ -98,7 +99,7 @@
"rtl": "De droite à gauche",
"auto": "Contextuel",
"language": "Langue",
"browserDefault": "Navigateur par défaut"
"browserDefault": "Par défaut du Navigateur"
},
"sidebar": {
"show": "Afficher la barre latérale"
@@ -134,7 +135,7 @@
"disableSelectedNodes": "Désactiver les noeuds sélectionnés",
"showSelectedNodeLabels": "Afficher les étiquettes des noeuds sélectionnés",
"hideSelectedNodeLabels": "Masquer les étiquettes des noeuds sélectionnés",
"showWelcomeTours": "Afficher les visites guidées pour les nouvelles versions",
"showWelcomeTours": "Afficher les visites guidées des nouvelles versions",
"help": "Site web de Node-RED",
"projects": "Projets",
"projects-new": "Nouveau projet",
@@ -143,7 +144,7 @@
"showNodeLabelDefault": "Afficher l'étiquette des noeuds nouvellement ajoutés",
"codeEditor": "Éditeur de code",
"groups": "Groupes",
"groupSelection": "Grouper cette sélection",
"groupSelection": "Grouper la sélection",
"ungroupSelection": "Dégrouper la sélection",
"groupMergeSelection": "Fusionner la sélection",
"groupRemoveSelection": "Supprimer du groupe",
@@ -155,7 +156,7 @@
"alignMiddle": "Aligner au milieu",
"alignBottom": "Aligner en bas",
"distributeHorizontally": "Répartir horizontalement",
"distributeVertically": "Distribuer verticalement",
"distributeVertically": "Répartir verticalement",
"moveToBack": "Déplacer vers l'arrière",
"moveToFront": "Déplacer vers l'avant",
"moveBackwards": "Reculer",
@@ -163,21 +164,21 @@
}
},
"actions": {
"toggle-navigator": "Basculer de navigateur",
"zoom-out": "Dézoomer",
"zoom-reset": "Réinitialiser le zoom",
"toggle-navigator": "Basculer l'affichage du navigateur",
"zoom-out": "Réduire",
"zoom-reset": "Réinitialiser",
"zoom-in": "Agrandir",
"search-flows": "Rechercher le flux",
"search-prev": "Précédent",
"search-next": "Suivant",
"search-counter": "\"__term__\" __result__ de __count__"
"search-counter": "\"__term__\" __result__ sur __count__"
},
"user": {
"loggedInAs": "Connecté en tant que __name__",
"username": "Nom d'utilisateur",
"password": "Mot de passe",
"login": "Connexion",
"loginFailed": "Échec de la connexion",
"login": "Se connecter",
"loginFailed": "Échec de connexion",
"notAuthorized": "Pas autorisé",
"errors": {
"settings": "Vous devez être connecté pour accéder aux paramètres",
@@ -193,16 +194,16 @@
"warning": "<strong>Attention</strong> : __message__",
"warnings": {
"undeployedChanges": "Le noeud a des modifications non déployées",
"nodeActionDisabled": "Actions de noeud désactivées",
"nodeActionDisabledSubflow": "Actions de noeud désactivées dans le sous-flux",
"nodeActionDisabled": "Les actions du noeud sont désactivées",
"nodeActionDisabledSubflow": "Les actions de noeud sont désactivées à l'intérieur du sous-flux",
"missing-types": "<p>Flux arrêtés en raison de types de noeuds manquants.</p>",
"missing-modules": "<p>Flux arrêtés en raison de modules manquants.</p>",
"safe-mode": "<p>Flux arrêtés en mode sans échec.</p><p>Vous pouvez modifier vos flux et déployer les changements pour redémarrer.</p>",
"safe-mode": "<p>Flux arrêtés en mode sans échec.</p><p>Vous pouvez modifier vos flux et déployer ensuite les changements afin de démarrer vos flux.</p>",
"restartRequired": "Node-RED doit être redémarré pour mettre à jour les modules",
"credentials_load_failed": "<p>Les flux se sont arrêtés car les informations d'identification n'ont pas pu être déchiffrées.</p><p>Le fichier d'informations d'identification du flux est chiffré, mais la clé de chiffrement du projet est manquante ou invalide.</p>",
"credentials_load_failed_reset": "<p>Les informations d'identification n'ont pas pu être déchiffrées</p><p>Le fichier d'informations d'identification du flux est chiffré, mais la clé de chiffrement du projet est manquante ou invalide.</p><p>Le fichier d'informations d'identification du flux sera réinitialisé lors du prochain déploiement. Toutes les informations d'identification de flux existantes seront perdues.</p>",
"credentials_load_failed": "<p>Les flux se sont arrêtés car les informations d'identification n'ont pas pu être déchiffrées.</p><p>Le fichier d'informations d'identification du flux est chiffré mais la clé de chiffrement du projet est manquante ou invalide.</p>",
"credentials_load_failed_reset": "<p>Les informations d'identification n'ont pas pu être déchiffrées</p><p>Le fichier d'informations d'identification du flux est chiffré mais la clé de chiffrement du projet est manquante ou invalide.</p><p>Le fichier d'informations d'identification du flux sera réinitialisé lors du prochain déploiement. Toutes les informations d'identification des flux existants seront perdues.</p>",
"missing_flow_file": "<p>Fichier contenant les flux introuvable.</p><p>Le projet n'est pas configuré avec un fichier de flux.</p>",
"missing_package_file": "<p>Fichier de paquetage du projet introuvable.</p><p>Il manque au projet un fichier package.json.</p>",
"missing_package_file": "<p>Fichier de paquetage du projet introuvable.</p><p>Il manque au projet le fichier <code>package.json</code>.</p>",
"project_empty": "<p>Le projet est vide.</p><p>Voulez-vous créer un ensemble de fichiers de projet par défaut ?<br/>Sinon, vous devrez ajouter manuellement des fichiers au projet (en dehors de l'éditeur).</p>",
"project_not_found": "<p>Le projet '__project__' est introuvable.</p>",
"git_merge_conflict": "<p>La fusion automatique des modifications a échoué.</p><p>Corriger les conflits non fusionnés, puis valider le résultat.</p>"
@@ -219,7 +220,7 @@
},
"project": {
"change-branch": "Changer pour une branche locale '__project__'",
"merge-abort": "Git fusion abandonnée",
"merge-abort": "Fusion Git abandonnée",
"loaded": "Projet '__project__' chargé",
"updated": "Projet '__project__' mis à jour",
"pull": "Projet '__project__' rechargé",
@@ -352,7 +353,7 @@
"backgroundUpdate": "Les flux sur le serveur ont été mis à jour.",
"conflictChecking": "Vérifier si les modifications peuvent être fusionnées automatiquement",
"conflictAutoMerge": "Les modifications n'incluent aucun conflit et peuvent être fusionnées automatiquement.",
"conflictManualMerge": "Les changements incluent des conflits qui doivent être résolus avant de pouvoir être déployés.",
"conflictManualMerge": "Les modifications incluent des conflits qui doivent être résolus avant de pouvoir être déployées.",
"plusNMore": "+ __count__ en plus"
}
},
@@ -372,16 +373,17 @@
"deleted": "supprimé",
"flowDeleted": "flux supprimé",
"flowAdded": "flux ajouté",
"moved": "déplacé",
"movedTo": "déplacé vers __id__",
"movedFrom": "déplacé depuis __id__"
},
"nodeCount": "__count__ noeud",
"nodeCount_plural": "__count__ noeuds",
"local": "Changements locaux",
"remote": "Modifications à distance",
"remote": "Changements distants",
"reviewChanges": "Examiner les modifications",
"noBinaryFileShowed": "Impossible d'afficher le contenu du fichier binaire",
"viewCommitDiff": "Afficher les modifications de validation",
"viewCommitDiff": "Afficher les modifications de la validation",
"compareChanges": "Comparer les modifications",
"saveConflict": "Enregistrer la résolution des conflits",
"conflictHeader": "<span>__resolved__</span> sur <span>__unresolved__</span> conflit(s) résolu(s)",
@@ -395,9 +397,9 @@
"edit": "Modifier le modèle du sous-flux",
"subflowInstances": "Il existe __count__ instance de ce modèle de sous-flux",
"subflowInstances_plural": "Il existe __count__ instances de ce modèle de sous-flux",
"editSubflowProperties": "modifier les propriétés",
"input": "Entrées:",
"output": "Sorties:",
"editSubflowProperties": "Modifier les propriétés",
"input": "Entrées :",
"output": "Sorties :",
"status": "Statut du noeud",
"deleteSubflow": "Supprimer le sous-flux",
"confirmDelete": "Voulez-vous vraiment supprimer ce sous-flux ?",
@@ -411,7 +413,7 @@
"version": "Version",
"versionPlaceholder": "x.y.z",
"keys": "Mots clés",
"keysPlaceholder": "Mots clés séparés par des virgules",
"keysPlaceholder": "Mots clés séparés par une virgule",
"author": "Auteur",
"authorPlaceholder": "Votre nom <email@exemple.com>",
"desc": "Description",
@@ -468,7 +470,7 @@
"select": "sélection",
"checkbox": "case à cocher",
"spinner": "valeurs à défiler",
"none": "aucune",
"none": "aucun",
"hidden": "masquer la propriété"
},
"types": {
@@ -496,7 +498,7 @@
"max": "Maximum"
},
"errors": {
"scopeChange": "La modification de la portée la rendra indisponible pour les noeuds d'autres flux qui l'utilisent",
"scopeChange": "La modification de la portée rendra indisponible ce noeud de configuration aux noeuds d'autres flux qui l'utilisent",
"invalidProperties": "Propriétés invalides :",
"credentialLoadFailed": "Échec du chargement des identifiants du noeud"
}
@@ -510,7 +512,7 @@
"unassigned": "Non attribué",
"global": "Global",
"workspace": "Espace de travail",
"editor": "Boîte de dialogue d'édition",
"editor": "Boîte d'édition",
"selectAll": "Tout sélectionner",
"selectNone": "Ne rien sélectionner",
"selectAllConnected": "Sélectionner tous les éléments connectés",
@@ -541,7 +543,7 @@
"openLibrary": "Ouvrir la bibliothèque...",
"saveToLibrary": "Enregistrer dans la bibliothèque...",
"typeLibrary": "__type__ bibliothèque",
"unnamedType": "Innomé __type__",
"unnamedType": "Sans nom __type__",
"exportedToLibrary": "Noeuds exportés vers la bibliothèque",
"dialogSaveOverwrite": "Une __libraryType__ appelée __libraryName__ existe déjà. Écraser ?",
"invalidFilename": "Nom de fichier non valide",
@@ -558,7 +560,7 @@
"noInfo": "Pas d'information disponible",
"filter": "Rechercher le noeud",
"search": "Rechercher les modules",
"addCategory": "Ajouter un nouveau...",
"addCategory": "Ajouter une nouvelle...",
"label": {
"subflows": "Sous-flux",
"network": "Réseau",
@@ -614,6 +616,8 @@
},
"nodeCount": "__label__ noeud",
"nodeCount_plural": "__label__ noeuds",
"pluginCount": "__count__ plugin",
"pluginCount_plural": "__count__ plugins",
"moduleCount": "__count__ module disponible",
"moduleCount_plural": "__count__ modules disponibles",
"inuse": "En cours d'utilisation",
@@ -636,11 +640,12 @@
"sortAZ": "A-Z",
"sortRecent": "Récent",
"more": "+ __count__ en plus",
"upload": "Charger le fichier tgz du module",
"upload": "Charger le fichier .tgz du module",
"refresh": "Actualiser la liste des modules",
"errors": {
"catalogLoadFailed": "<p>Échec du chargement du catalogue de noeuds.</p><p>Vérifier la console du navigateur pour plus d'informations</p>",
"installFailed": "<p>Échec lors de l'installation : __module__</p><p>__message__</p><p>Consulter le journal pour plus d'informations</p>",
"installTimeout": "<p>L'installation continue en arrière-plan.</p><p>Les noeuds apparaîtront dans la palette une fois l'installation terminée. Consulter le journal pour plus d'informations.</p>",
"removeFailed": "<p>Échec lors de la suppression : __module__</p><p>__message__</p><p>Consulter le journal pour plus d'informations</p>",
"updateFailed": "<p>Échec lors de la mise à jour : __module__</p><p>__message__</p><p>Consulter le journal pour plus d'informations</p>",
"enableFailed": "<p>Échec lors de l'activation : __module__</p><p>__message__</p><p>Consulter le journal pour plus d'informations</p>",
@@ -648,25 +653,29 @@
},
"confirm": {
"install": {
"body": "<p>Installation de '__module__'</p><p>Avant l'installation, veuiller lire la documentation du noeud. Certains noeuds ont des dépendances qui ne peuvent pas être résolues automatiquement et peuvent nécessiter un redémarrage de Node-RED.</p>",
"body": "<p>Installation de '__module__'</p><p>Avant l'installation, veuillez lire la documentation du noeud. Certains noeuds ont des dépendances qui ne peuvent pas être résolues automatiquement et peuvent nécessiter un redémarrage de Node-RED.</p>",
"title": "Installer les noeuds"
},
"remove": {
"body": "<p>Suppression de '__module__'</p><p>La suppression du noeud le désinstallera de Node-RED. Le noeud peut continuer à utiliser des ressources jusqu'au redémarrage de Node-RED.</p>",
"body": "<p>Suppression de '__module__'</p><p>La suppression du noeud le désinstallera de Node-RED. Le noeud peut continuer à utiliser ses ressources jusqu'au redémarrage de Node-RED.</p>",
"title": "Supprimer les noeuds"
},
"removePlugin": {
"body": "<p>Suppression du plugin '__module__'. Veuillez recharger l'éditeur afin d'appliquer les changements.</p>"
},
"update": {
"body": "<p>Mise à jour de '__module__'</p><p>La mise à jour du noeud nécessitera un redémarrage de Node-RED pour terminer la mise à jour. Cela doit être fait manuellement.</p>",
"title": "Mettre à jour les noeuds"
},
"cannotUpdate": {
"body": "Une mise à jour pour ce noeud est disponible, mais il n'est pas installé dans un emplacement que le gestionnaire de palette peut mettre à jour.<br/><br/>Veuiller vous référer à la documentation pour savoir comment mettre à jour ce noeud."
"body": "Une mise à jour pour ce noeud est disponible, mais il n'est pas installé dans un emplacement que le gestionnaire de palette peut mettre à jour.<br/><br/>Veuillez vous référer à la documentation pour savoir comment mettre à jour ce noeud."
},
"button": {
"review": "Ouvrir la documentation",
"install": "Installer",
"remove": "Supprimer",
"update": "Mettre à jour"
"update": "Mettre à jour",
"understood": "Compris"
}
}
}
@@ -701,8 +710,8 @@
"nodeHelp": "Aide sur les noeuds",
"none": "Aucun",
"arrayItems": "__count__ éléments",
"showTips": "Vous pouvez ouvrir les astuces à partir du panneau des paramètres",
"outline": "Plan",
"showTips": "Vous pouvez afficher les astuces à partir du panneau des paramètres",
"outline": "Contour",
"empty": "Vide",
"globalConfig": "Noeuds de configuration globale",
"triggerAction": "Déclencher une action",
@@ -715,10 +724,11 @@
"help": {
"name": "Aide",
"label": "Aide",
"search": "Aide à la recherche",
"search": "Rechercher l'aide",
"nodeHelp": "Aide sur les noeuds",
"showHelp": "Afficher l'aide",
"showInOutline": "Afficher dans les grandes lignes",
"hideTopics": "Masquer les sujets",
"showTopics": "Afficher les sujets",
"noHelp": "Aucune rubrique d'aide sélectionnée",
"changeLog": "Journal des modifications"
@@ -793,7 +803,7 @@
"branches": "Branches",
"noBranches": "Pas de branche",
"deleteConfirm": "Êtes-vous sûr de vouloir supprimer la branche locale '__name__' ? Ça ne peut pas être annulé.",
"unmergedConfirm": "La branche locale '__name__' contient des modifications non fusionnées qui seront perdues. Etes-vous sûr de vouloir la supprimer?",
"unmergedConfirm": "La branche locale '__name__' contient des modifications non fusionnées qui seront perdues. Êtes-vous sûr de vouloir la supprimer?",
"deleteUnmergedBranch": "Supprimer la branche non fusionnée",
"gitRemotes": "Git distant",
"addRemote": "Ajout distant",
@@ -837,17 +847,17 @@
"deleteConfirm": "Êtes-vous sûr de vouloir supprimer la clé SSH __name__ ? Ça ne peut pas être annulé."
},
"versionControl": {
"unstagedChanges": "Abandon des changements",
"stagedChanges": "Changement mis en place",
"unstageChange": "Ne pas mettre en place le changement",
"stageChange": "Mettre en place le changement",
"unstageAllChange": "Ne pas mettre en place tous les changements",
"stageAllChange": "Mettre en place tous les changements",
"unstagedChanges": "Changements non indexés",
"stagedChanges": "Changements indexés",
"unstageChange": "Annuler l'indexation des changements",
"stageChange": "Indexer les changements",
"unstageAllChange": "Annuler l'indexation de tous les changements",
"stageAllChange": "Indexer tous les changements",
"commitChanges": "Valider les changements",
"resolveConflicts": "Résoudre les conflits",
"head": "En-tête",
"staged": "Mis en place",
"unstaged": "Non mis en place",
"staged": "Indexé",
"unstaged": "Non indexé",
"local": "Local",
"remote": "Distant",
"revert": "Voulez-vous vraiment annuler les modifications apportées à '__file__' ? Ça ne peut pas être annulé.",
@@ -881,11 +891,11 @@
"pushFailed": "L'envoi a échoué car la branche a des validations plus récentes. Tirer et fusionner d'abord, puis envoyer à nouveau.",
"push": "Envoyer",
"pull": "Tirer",
"unablePull": "<p>Impossible d'extraire les modifications à distance ; vos modifications locales non mises en place seraient écrasées.</p><p>Valider vos modifications et réessayer.</p>",
"showUnstagedChanges": "Afficher les modifications non mise en place",
"unablePull": "<p>Impossible d'extraire les modifications à distance; vos modifications locales non mises en place seraient écrasées.</p><p>Valider vos modifications et réessayer.</p>",
"showUnstagedChanges": "Afficher les modifications non indexées",
"connectionFailed": "Impossible de se connecter au référentiel distant: ",
"pullUnrelatedHistory": "<p>Le réferentiel distant a un historique de validations sans rapport.</p><p>Êtes-vous sûr de vouloir extraire les modifications dans votre référentiel local ?</p>",
"pullChanges": "Tirer les changements",
"pullChanges": "Tirer les changements distants",
"history": "Historique",
"projectHistory": "Historique du projet",
"daysAgo": "il y a __count__ jour",
@@ -914,6 +924,8 @@
}
},
"typedInput": {
"selected": "__count__ sélectionnée",
"selected_plural": "__count__ sélectionnées",
"type": {
"str": "chaîne de caractères",
"num": "nombre",
@@ -924,7 +936,14 @@
"date": "horodatage",
"jsonata": "expression",
"env": "variable d'environnement",
"cred": "identifiant"
"cred": "identifiant",
"conf-types": "noeud de configuration"
},
"date": {
"format": {
"timestamp": "millisecondes depuis l'époque",
"object": "Objet de date JavaScript"
}
}
},
"editableList": {
@@ -957,7 +976,7 @@
"result": "Résultat",
"format": "Format",
"compatMode": "Mode de compatibilité activé",
"compatModeDesc": "<h3>Mode de compatibilité JSONata</h3><p> L'expression actuelle semble toujours faire référence à <code>msg</code> et sera donc évaluée en mode de compatibilité. Veuiller mettre à jour l'expression pour ne pas utiliser <code>msg</code> car ce mode sera supprimé à l'avenir.</p><p> Lorsque la prise en charge de JSONata a été ajoutée pour la première fois à Node-RED, il fallait que l'expression référencie l'objet <code>msg</code>. Par exemple, <code>msg.payload</code> serait utilisé pour accéder à la charge utile.</p><p> Cela n'est plus nécessaire car l'expression sera évaluée directement par rapport au message. Pour accéder à la charge utile, l'expression doit être simplement <code>charge utile</code>.</p>",
"compatModeDesc": "<h3>Mode de compatibilité JSONata</h3><p> L'expression actuelle semble toujours faire référence à <code>msg</code> et sera donc évaluée en mode de compatibilité. Veuillez mettre à jour l'expression pour ne pas utiliser <code>msg</code> car ce mode sera supprimé à l'avenir.</p><p> Lorsque la prise en charge de JSONata a été ajoutée pour la première fois à Node-RED, il fallait que l'expression référencie l'objet <code>msg</code>. Par exemple, <code>msg.payload</code> serait utilisé pour accéder à la charge utile.</p><p> Cela n'est plus nécessaire car l'expression sera évaluée directement par rapport au message. Pour accéder à la charge utile, l'expression doit être simplement <code>charge utile</code>.</p>",
"noMatch": "Aucun résultat correspondant",
"errors": {
"invalid-expr": "Expression JSONata non valide :\n __message__",
@@ -980,7 +999,7 @@
},
"jsonEditor": {
"title": "Éditeur JSON",
"format": "Format JSON",
"format": "Formatter JSON",
"rawMode": "Modifier JSON",
"uiMode": "Afficher l'éditeur",
"rawMode-readonly": "JSON",
@@ -999,7 +1018,7 @@
"markdownEditor": {
"title": "Éditeur Markdown",
"expand": "Développer",
"format": "Formaté avec Markdown",
"format": "Formatter avec Markdown",
"heading1": "Rubrique 1",
"heading2": "Rubrique 2",
"heading3": "Rubrique 3",
@@ -1073,7 +1092,7 @@
"credential-key": "Clé de chiffrement des identifiants",
"cant-get-ssh-key": "Erreur! Impossible d'obtenir le chemin de la clé SSH sélectionnée.",
"already-exists2": "Existe déjà",
"git-error": "Erreur git",
"git-error": "Erreur Git",
"connection-failed": "La connexion a échoué",
"not-git-repo": "Ce n'est pas un dépôt Git",
"repo-not-found": "Référentiel introuvable"
@@ -1087,7 +1106,7 @@
"credentials-file": "Fichier d'identifiants"
},
"encryption-config": {
"setup": "Configuration du chiffrage de votre fichier d'informations d'identification",
"setup": "Configuration du chiffrement de votre fichier d'informations d'identification",
"desc0": "Votre fichier d'informations d'identification de flux peut être chiffré pour sécuriser son contenu.",
"desc1": "Si vous souhaitez stocker ces identifiants dans un référentiel Git public, vous devez les chiffrer en fournissant une phrase clé secrète.",
"desc2": "Votre fichier d'identifiants de flux n'est actuellement pas chiffré.",
@@ -1144,9 +1163,9 @@
"add-ssh-key": "Ajouter une clé ssh",
"credentials-encryption-key": "Clé de chiffrement des identifiants",
"already-exists-2": "Existe déjà",
"git-error": "Erreur git",
"git-error": "Erreur Git",
"con-failed": "La connexion a échoué",
"not-git": "Ce n'est pas un dépôt git",
"not-git": "Ce n'est pas un dépôt Git",
"no-resource": "Référentiel introuvable",
"cant-get-ssh-key-path": "Erreur! Impossible d'obtenir le chemin de la clé SSH sélectionnée.",
"unexpected_error": "Erreur inattendue",
@@ -1184,7 +1203,7 @@
},
"errors": {
"no-username-email": "Votre client Git n'est pas configuré avec un nom d'utilisateur/e-mail.",
"unexpected": "Une erreur inattendue est apparue",
"unexpected": "Une erreur inattendue est survenue",
"code": "Code"
}
},
@@ -1253,7 +1272,7 @@
"list-modified-nodes": "Afficher les flux modifiés",
"list-hidden-flows": "Afficher les flux cachés",
"list-flows": "Lister les flux",
"list-subflows": "Liste les sous-flux",
"list-subflows": "Lister les sous-flux",
"go-to-previous-location": "Aller à l'emplacement précédent",
"go-to-next-location": "Aller à l'emplacement suivant",
"copy-selection-to-internal-clipboard": "Copier la sélection dans le presse-papiers",
@@ -1313,8 +1332,8 @@
"align-selection-to-bottom": "Aligner la sélection vers le bas",
"align-selection-to-middle": "Aligner la sélection au centre verticalement",
"align-selection-to-center": "Aligner la sélection au centre horizontalement",
"distribute-selection-horizontally": "Distribuer la sélection horizontalement",
"distribute-selection-vertical": "Distribuer la sélection verticalement",
"distribute-selection-horizontally": "Répartir la sélection horizontalement",
"distribute-selection-vertical": "Répartir la sélection verticalement",
"wire-series-of-nodes": "Connecter les noeuds en série",
"wire-node-to-multiple": "Connecter les noeuds à plusieurs",
"wire-multiple-to-node": "Connecter plusieurs au noeud",

View File

@@ -27,7 +27,8 @@
"lock": "固定",
"unlock": "固定を解除",
"locked": "固定済み",
"unlocked": "固定なし"
"unlocked": "固定なし",
"format": "形式"
},
"type": {
"string": "文字列",
@@ -281,8 +282,8 @@
"selected": "選択したフロー",
"current": "現在のタブ",
"all": "全てのタブ",
"compact": "インデントのないJSONフォーマット",
"formatted": "インデント付きのJSONフォーマット",
"compact": "インデントなし",
"formatted": "インデント付き",
"copy": "書き出し",
"export": "ライブラリに書き出し",
"exportAs": "書き出し先",
@@ -372,6 +373,7 @@
"deleted": "削除",
"flowDeleted": "削除されたフロー",
"flowAdded": "追加されたフロー",
"moved": "移動",
"movedTo": "__id__ へ移動",
"movedFrom": "__id__ から移動"
},
@@ -614,6 +616,8 @@
},
"nodeCount": "__label__ 個のノード",
"nodeCount_plural": "__label__ 個のノード",
"pluginCount": "__count__ 個のプラグイン",
"pluginCount_plural": "__count__ 個のプラグイン",
"moduleCount": "__count__ 個のモジュール",
"moduleCount_plural": "__count__ 個のモジュール",
"inuse": "使用中",
@@ -641,6 +645,7 @@
"errors": {
"catalogLoadFailed": "<p>ノードのカタログの読み込みに失敗しました。</p><p>詳細はブラウザのコンソールを確認してください。</p>",
"installFailed": "<p>追加処理が失敗しました: __module__</p><p>__message__</p><p>詳細はログを確認してください。</p>",
"installTimeout": "<p>バックグラウンドでインストールが継続されます。</p><p>完了した時にノードが表示されます。詳細はログを確認してください。</p>",
"removeFailed": "<p>削除処理が失敗しました: __module__</p><p>__message__</p><p>詳細はログを確認してください。</p>",
"updateFailed": "<p>更新処理が失敗しました: __module__</p><p>__message__</p><p>詳細はログを確認してください。</p>",
"enableFailed": "<p>有効化処理が失敗しました: __module__</p><p>__message__</p><p>詳細はログを確認してください。</p>",
@@ -655,6 +660,9 @@
"body": "<p>__module__ を削除します。</p><p>Node-REDからードを削除します。ードはNode-REDが再起動されるまで、リソースを使い続ける可能性があります。</p>",
"title": "ノードを削除"
},
"removePlugin": {
"body": "<p>プラグイン __module__ を削除しました。ブラウザを再読み込みして残った表示を消してください。</p>"
},
"update": {
"body": "<p>__module__ を更新します。</p><p>更新を完了するには手動でNode-REDを再起動する必要があります。</p>",
"title": "ノードの更新"
@@ -666,7 +674,8 @@
"review": "ノードの情報を参照",
"install": "追加",
"remove": "削除",
"update": "更新"
"update": "更新",
"understood": "了解"
}
}
}
@@ -719,6 +728,7 @@
"nodeHelp": "ノードヘルプ",
"showHelp": "ヘルプを表示",
"showInOutline": "アウトラインに表示",
"hideTopics": "トピックを非表示",
"showTopics": "トピックを表示",
"noHelp": "ヘルプのトピックが未選択",
"changeLog": "更新履歴"
@@ -914,6 +924,8 @@
}
},
"typedInput": {
"selected": "__count__個を選択",
"selected_plural": "__count__個を選択",
"type": {
"str": "文字列",
"num": "数値",
@@ -924,7 +936,14 @@
"date": "日時",
"jsonata": "JSONata式",
"env": "環境変数",
"cred": "認証情報"
"cred": "認証情報",
"conf-types": "設定ノード"
},
"date": {
"format": {
"timestamp": "エポックからの経過ミリ秒",
"object": "JavaScript日付オブジェクト"
}
}
},
"editableList": {
@@ -1230,7 +1249,7 @@
},
"env-var": {
"environment": "環境変数",
"header": "大域環境変数",
"header": "グローバル環境変数",
"revert": "破棄"
},
"action-list": {
@@ -1382,7 +1401,7 @@
"copy-item-edit-url": "要素の編集URLをコピー",
"move-flow-to-start": "フローを先頭に移動",
"move-flow-to-end": "フローを末尾に移動",
"show-global-env": "大域環境変数を表示",
"show-global-env": "グローバル環境変数を表示",
"lock-flow": "フローを固定",
"unlock-flow": "フローの固定を解除",
"show-node-help": "ノードのヘルプを表示"

View File

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

View File

@@ -29,7 +29,14 @@ RED.history = (function() {
}
return RED.nodes.junction(id);
}
function ensureUnlocked(id, flowsToLock) {
const flow = id && (RED.nodes.workspace(id) || RED.nodes.subflow(id) || null);
const isLocked = flow ? flow.locked : false;
if (flow && isLocked) {
flow.locked = false;
flowsToLock.add(flow)
}
}
function undoEvent(ev) {
var i;
var len;
@@ -59,18 +66,46 @@ RED.history = (function() {
t: 'replace',
config: RED.nodes.createCompleteNodeSet(),
changed: {},
rev: RED.nodes.version()
moved: {},
complete: true,
rev: RED.nodes.version(),
dirty: RED.nodes.dirty()
};
var selectedTab = RED.workspaces.active();
inverseEv.config.forEach(n => {
const node = RED.nodes.node(n.id)
if (node) {
inverseEv.changed[n.id] = node.changed
inverseEv.moved[n.id] = node.moved
}
})
RED.nodes.clear();
var imported = RED.nodes.import(ev.config);
// Clear all change flags from the import
RED.nodes.dirty(false);
const flowsToLock = new Set()
imported.nodes.forEach(function(n) {
if (ev.changed[n.id]) {
ensureUnlocked(n.z, flowsToLock)
n.changed = true;
inverseEv.changed[n.id] = true;
}
if (ev.moved[n.id]) {
ensureUnlocked(n.z, flowsToLock)
n.moved = true;
}
})
flowsToLock.forEach(flow => {
flow.locked = true
})
RED.nodes.version(ev.rev);
RED.view.redraw(true);
RED.palette.refresh();
RED.workspaces.refresh();
RED.workspaces.show(selectedTab, true);
RED.sidebar.config.refresh();
} else {
var importMap = {};
ev.config.forEach(function(n) {

View File

@@ -1,114 +1,92 @@
RED.multiplayer = (function () {
// sessionId - used to identify sessions across websocket reconnects
let sessionId
// activeSessionId - used to identify sessions across websocket reconnects
let activeSessionId
let headerWidget
// Map of session id to { session:'', user:{}, location:{}}
let connections = {}
// Map of username to { user:{}, connections:[] }
let sessions = {}
// Map of username to { user:{}, sessions:[] }
let users = {}
function addUserConnection (connection) {
if (connections[connection.session]) {
function addUserSession (session) {
if (sessions[session.session]) {
// This is an existing connection that has been authenticated
const existingConnection = connections[connection.session]
if (existingConnection.user.username !== connection.user.username) {
removeUserButton(users[existingConnection.user.username])
const existingSession = sessions[session.session]
if (existingSession.user.username !== session.user.username) {
removeUserHeaderButton(users[existingSession.user.username])
}
}
connections[connection.session] = connection
const user = users[connection.user.username] = users[connection.user.username] || {
user: connection.user,
connections: []
sessions[session.session] = session
const user = users[session.user.username] = users[session.user.username] || {
user: session.user,
sessions: []
}
connection.location = connection.location || {}
user.connections.push(connection)
if (session.user.profileColor === undefined) {
session.user.profileColor = (1 + Math.floor(Math.random() * 5))
}
session.location = session.location || {}
user.sessions.push(session)
if (connection.user.username === RED.settings.user?.username ||
connection.session === sessionId
) {
// This is the current user - do not add a extra button for them
if (session.session === activeSessionId) {
// This is the current user session - do not add a extra button for them
} else {
if (user.connections.length === 1) {
if (user.sessions.length === 1) {
if (user.button) {
clearTimeout(user.inactiveTimeout)
clearTimeout(user.removeTimeout)
user.button.removeClass('inactive')
} else {
addUserButton(user)
addUserHeaderButton(user)
}
}
sessions[session.session].location = session.location
updateUserLocation(session.session)
}
}
function removeUserConnection (session, isDisconnected) {
const connection = connections[session]
delete connections[session]
const user = users[connection.user.username]
const i = user.connections.indexOf(connection)
user.connections.splice(i, 1)
function removeUserSession (sessionId, isDisconnected) {
removeUserLocation(sessionId)
const session = sessions[sessionId]
delete sessions[sessionId]
const user = users[session.user.username]
const i = user.sessions.indexOf(session)
user.sessions.splice(i, 1)
if (isDisconnected) {
removeUserButton(user)
removeUserHeaderButton(user)
} else {
if (user.connections.length === 0) {
if (user.sessions.length === 0) {
// Give the user 5s to reconnect before marking inactive
user.inactiveTimeout = setTimeout(() => {
user.button.addClass('inactive')
// Give the user further 20 seconds to reconnect before removing them
// from the user toolbar entirely
user.removeTimeout = setTimeout(() => {
removeUserButton(user)
removeUserHeaderButton(user)
}, 20000)
}, 5000)
}
}
}
function addUserButton (user) {
user.button = $('<li class="red-ui-multiplayer-user"><button type="button" class="red-ui-multiplayer-user-icon" href="#"></button></li>')
function addUserHeaderButton (user) {
user.button = $('<li class="red-ui-multiplayer-user"><button type="button" class="red-ui-multiplayer-user-icon"></button></li>')
.attr('data-username', user.user.username)
.prependTo("#red-ui-multiplayer-user-list");
var button = user.button.find("button")
RED.popover.tooltip(button, user.user.username)
button.on('click', function () {
RED.popover.create({
target:button,
trigger: 'modal',
interactive: true,
width: "250px",
direction: 'bottom',
content: () => {
const content = $('<div>')
$('<div style="text-align: center">').text(user.user.username).appendTo(content)
const location = user.connections[0].location
if (location.workspace) {
const ws = RED.nodes.workspace(location.workspace) || RED.nodes.subflow(location.workspace)
if (ws) {
$('<div>').text(`${ws.type}: ${ws.label||ws.name||ws.id}`).appendTo(content)
} else {
$('<div>').text(`tab: unknown`).appendTo(content)
}
}
if (location.node) {
const node = RED.nodes.node(location.node)
if (node) {
$('<div>').text(`node: ${node.id}`).appendTo(content)
} else {
$('<div>').text(`node: unknown`).appendTo(content)
}
}
return content
},
}).open()
const location = user.sessions[0].location
revealUser(location)
})
if (!user.user.image) {
$('<i class="fa fa-user"></i>').appendTo(button);
} else {
$('<span class="user-profile"></span>').css({
backgroundImage: "url("+user.user.image+")",
}).appendTo(button);
}
const userProfile = RED.user.generateUserIcon(user.user)
userProfile.appendTo(button)
}
function removeUserHeaderButton (user) {
user.button.remove()
delete user.button
}
function getLocation () {
@@ -124,7 +102,7 @@ RED.multiplayer = (function () {
}
return location
}
function updateLocation () {
function publishLocation () {
const location = getLocation()
if (location.workspace !== 0) {
log('send', 'multiplayer/location', location)
@@ -132,31 +110,314 @@ RED.multiplayer = (function () {
}
}
function removeUserButton (user) {
user.button.remove()
delete user.button
function revealUser(location, skipWorkspace) {
if (location.node) {
// Need to check if this is a known node, so we can fall back to revealing
// the workspace instead
const node = RED.nodes.node(location.node)
if (node) {
RED.view.reveal(location.node)
} else if (!skipWorkspace && location.workspace) {
RED.view.reveal(location.workspace)
}
} else if (!skipWorkspace && location.workspace) {
RED.view.reveal(location.workspace)
}
}
function updateUserLocation (data) {
connections[data.session].location = data
delete data.session
const workspaceTrays = {}
function getWorkspaceTray(workspaceId) {
// console.log('get tray for',workspaceId)
if (!workspaceTrays[workspaceId]) {
const tray = $('<div class="red-ui-multiplayer-users-tray"></div>')
const users = []
const userIcons = {}
const userCountIcon = $(`<div class="red-ui-multiplayer-user-location"><span class="red-ui-user-profile red-ui-multiplayer-user-count"><span></span></span></div>`)
const userCountSpan = userCountIcon.find('span span')
userCountIcon.hide()
userCountSpan.text('')
userCountIcon.appendTo(tray)
const userCountTooltip = RED.popover.tooltip(userCountIcon, function () {
const content = $('<div>')
users.forEach(sessionId => {
$('<div>').append($('<a href="#">').text(sessions[sessionId].user.username).on('click', function (evt) {
evt.preventDefault()
revealUser(sessions[sessionId].location, true)
userCountTooltip.close()
})).appendTo(content)
})
return content
},
null,
true
)
const updateUserCount = function () {
const maxShown = 2
const children = tray.children()
children.each(function (index, element) {
const i = users.length - index
if (i > maxShown) {
$(this).hide()
} else if (i >= 0) {
$(this).show()
}
})
if (users.length < maxShown + 1) {
userCountIcon.hide()
} else {
userCountSpan.text('+'+(users.length - maxShown))
userCountIcon.show()
}
}
workspaceTrays[workspaceId] = {
attached: false,
tray,
users,
userIcons,
addUser: function (sessionId) {
if (users.indexOf(sessionId) === -1) {
// console.log(`addUser ws:${workspaceId} session:${sessionId}`)
users.push(sessionId)
const userLocationId = `red-ui-multiplayer-user-location-${sessionId}`
const userLocationIcon = $(`<div class="red-ui-multiplayer-user-location" id="${userLocationId}"></div>`)
RED.user.generateUserIcon(sessions[sessionId].user).appendTo(userLocationIcon)
userLocationIcon.prependTo(tray)
RED.popover.tooltip(userLocationIcon, sessions[sessionId].user.username)
userIcons[sessionId] = userLocationIcon
updateUserCount()
}
},
removeUser: function (sessionId) {
// console.log(`removeUser ws:${workspaceId} session:${sessionId}`)
const userLocationId = `red-ui-multiplayer-user-location-${sessionId}`
const index = users.indexOf(sessionId)
if (index > -1) {
users.splice(index, 1)
userIcons[sessionId].remove()
delete userIcons[sessionId]
}
updateUserCount()
},
updateUserCount
}
}
const trayDef = workspaceTrays[workspaceId]
if (!trayDef.attached) {
const workspaceTab = $(`#red-ui-tab-${workspaceId}`)
if (workspaceTab.length > 0) {
trayDef.attached = true
trayDef.tray.appendTo(workspaceTab)
trayDef.users.forEach(sessionId => {
trayDef.userIcons[sessionId].on('click', function (evt) {
revealUser(sessions[sessionId].location, true)
})
})
}
}
return workspaceTrays[workspaceId]
}
function attachWorkspaceTrays () {
let viewTouched = false
for (let sessionId of Object.keys(sessions)) {
const location = sessions[sessionId].location
if (location) {
if (location.workspace) {
getWorkspaceTray(location.workspace).updateUserCount()
}
if (location.node) {
addUserToNode(sessionId, location.node)
viewTouched = true
}
}
}
if (viewTouched) {
RED.view.redraw()
}
}
function addUserToNode(sessionId, nodeId) {
const node = RED.nodes.node(nodeId)
if (node) {
if (!node._multiplayer) {
node._multiplayer = {
users: [sessionId]
}
node._multiplayer_refresh = true
} else {
if (node._multiplayer.users.indexOf(sessionId) === -1) {
node._multiplayer.users.push(sessionId)
node._multiplayer_refresh = true
}
}
}
}
function removeUserFromNode(sessionId, nodeId) {
const node = RED.nodes.node(nodeId)
if (node && node._multiplayer) {
const i = node._multiplayer.users.indexOf(sessionId)
if (i > -1) {
node._multiplayer.users.splice(i, 1)
}
if (node._multiplayer.users.length === 0) {
delete node._multiplayer
} else {
node._multiplayer_refresh = true
}
}
}
function removeUserLocation (sessionId) {
updateUserLocation(sessionId, {})
}
function updateUserLocation (sessionId, location) {
let viewTouched = false
const oldLocation = sessions[sessionId].location
if (location) {
if (oldLocation.workspace !== location.workspace) {
// console.log('removing', sessionId, oldLocation.workspace)
workspaceTrays[oldLocation.workspace]?.removeUser(sessionId)
}
if (oldLocation.node !== location.node) {
removeUserFromNode(sessionId, oldLocation.node)
viewTouched = true
}
sessions[sessionId].location = location
} else {
location = sessions[sessionId].location
}
// console.log(`updateUserLocation sessionId:${sessionId} oldWS:${oldLocation?.workspace} newWS:${location.workspace}`)
if (location.workspace) {
getWorkspaceTray(location.workspace).addUser(sessionId)
}
if (location.node) {
addUserToNode(sessionId, location.node)
viewTouched = true
}
if (viewTouched) {
RED.view.redraw()
}
}
// function refreshUserLocations () {
// for (const session of Object.keys(sessions)) {
// if (session !== activeSessionId) {
// updateUserLocation(session)
// }
// }
// }
return {
init: function () {
sessionId = RED.settings.getLocal('multiplayer:sessionId')
if (!sessionId) {
sessionId = RED.nodes.id()
RED.settings.setLocal('multiplayer:sessionId', sessionId)
function createAnnotationUser(user) {
const group = document.createElementNS("http://www.w3.org/2000/svg","g");
const badge = document.createElementNS("http://www.w3.org/2000/svg","circle");
const radius = 20
badge.setAttribute("cx",radius/2);
badge.setAttribute("cy",radius/2);
badge.setAttribute("r",radius/2);
badge.setAttribute("class", "red-ui-multiplayer-annotation-background")
group.appendChild(badge)
if (user && user.profileColor !== undefined) {
badge.setAttribute("class", "red-ui-multiplayer-annotation-background red-ui-user-profile-color-" + user.profileColor)
}
if (user && user.image) {
const image = document.createElementNS("http://www.w3.org/2000/svg","image");
image.setAttribute("width", radius)
image.setAttribute("height", radius)
image.setAttribute("href", user.image)
image.setAttribute("clip-path", "circle("+Math.floor(radius/2)+")")
group.appendChild(image)
} else if (user && user.anonymous) {
const anonIconHead = document.createElementNS("http://www.w3.org/2000/svg","circle");
anonIconHead.setAttribute("cx", radius/2)
anonIconHead.setAttribute("cy", radius/2 - 2)
anonIconHead.setAttribute("r", 2.4)
anonIconHead.setAttribute("class","red-ui-multiplayer-annotation-anon-label");
group.appendChild(anonIconHead)
const anonIconBody = document.createElementNS("http://www.w3.org/2000/svg","path");
anonIconBody.setAttribute("class","red-ui-multiplayer-annotation-anon-label");
// anonIconBody.setAttribute("d",`M ${radius/2 - 4} ${radius/2 + 1} h 8 v4 h -8 z`);
anonIconBody.setAttribute("d",`M ${radius/2} ${radius/2 + 5} h -2.5 c -2 1 -2 -5 0.5 -4.5 c 2 1 2 1 4 0 c 2.5 -0.5 2.5 5.5 0 4.5 z`);
group.appendChild(anonIconBody)
} else {
const labelText = user.username ? user.username.substring(0,2) : user
const label = document.createElementNS("http://www.w3.org/2000/svg","text");
if (user.username) {
label.setAttribute("class","red-ui-multiplayer-annotation-label");
label.textContent = user.username.substring(0,2)
} else {
label.setAttribute("class","red-ui-multiplayer-annotation-label red-ui-multiplayer-user-count")
label.textContent = user
}
label.setAttribute("text-anchor", "middle")
label.setAttribute("x",radius/2);
label.setAttribute("y",radius/2 + 3);
group.appendChild(label)
}
const border = document.createElementNS("http://www.w3.org/2000/svg","circle");
border.setAttribute("cx",radius/2);
border.setAttribute("cy",radius/2);
border.setAttribute("r",radius/2);
border.setAttribute("class", "red-ui-multiplayer-annotation-border")
group.appendChild(border)
return group
}
RED.view.annotations.register("red-ui-multiplayer",{
type: 'badge',
align: 'left',
class: "red-ui-multiplayer-annotation",
show: "_multiplayer",
refresh: "_multiplayer_refresh",
element: function(node) {
const containerGroup = document.createElementNS("http://www.w3.org/2000/svg","g");
containerGroup.setAttribute("transform","translate(0,-4)")
if (node._multiplayer) {
let y = 0
for (let i = Math.min(1, node._multiplayer.users.length - 1); i >= 0; i--) {
const user = sessions[node._multiplayer.users[i]].user
const group = createAnnotationUser(user)
group.setAttribute("transform","translate("+y+",0)")
y += 15
containerGroup.appendChild(group)
}
if (node._multiplayer.users.length > 2) {
const group = createAnnotationUser('+'+(node._multiplayer.users.length - 2))
group.setAttribute("transform","translate("+y+",0)")
y += 12
containerGroup.appendChild(group)
}
}
return containerGroup;
},
tooltip: node => { return node._multiplayer.users.map(u => sessions[u].user.username).join('\n') }
});
// activeSessionId = RED.settings.getLocal('multiplayer:sessionId')
// if (!activeSessionId) {
activeSessionId = RED.nodes.id()
// RED.settings.setLocal('multiplayer:sessionId', activeSessionId)
// log('Session ID (new)', activeSessionId)
// } else {
log('Session ID', activeSessionId)
// }
headerWidget = $('<li><ul id="red-ui-multiplayer-user-list"></ul></li>').prependTo('.red-ui-header-toolbar')
RED.comms.on('connect', () => {
const location = getLocation()
const connectInfo = {
session: sessionId
session: activeSessionId
}
if (location.workspace !== 0) {
connectInfo.location = location
@@ -168,40 +429,52 @@ RED.multiplayer = (function () {
if (topic === 'multiplayer/init') {
// We have just reconnected, runtime has sent state to
// initialise the world
connections = {}
sessions = {}
users = {}
$('#red-ui-multiplayer-user-list').empty()
msg.forEach(connection => {
addUserConnection(connection)
msg.sessions.forEach(session => {
addUserSession(session)
})
} else if (topic === 'multiplayer/connection-added') {
addUserConnection(msg)
addUserSession(msg)
} else if (topic === 'multiplayer/connection-removed') {
removeUserConnection(msg.session, msg.disconnected)
removeUserSession(msg.session, msg.disconnected)
} else if (topic === 'multiplayer/location') {
updateUserLocation(msg)
const session = msg.session
delete msg.session
updateUserLocation(session, msg)
}
})
RED.events.on('workspace:change', (event) => {
updateLocation()
getWorkspaceTray(event.workspace)
publishLocation()
})
RED.events.on('editor:open', () => {
updateLocation()
publishLocation()
})
RED.events.on('editor:close', () => {
updateLocation()
publishLocation()
})
RED.events.on('editor:change', () => {
updateLocation()
publishLocation()
})
RED.events.on('login', () => {
updateLocation()
publishLocation()
})
RED.events.on('flows:loaded', () => {
attachWorkspaceTrays()
})
RED.events.on('workspace:close', (event) => {
// A subflow tab has been closed. Need to mark its tray as detached
if (workspaceTrays[event.workspace]) {
workspaceTrays[event.workspace].attached = false
}
})
RED.events.on('logout', () => {
const disconnectInfo = {
session: sessionId
session: activeSessionId
}
RED.comms.send('multiplayer/disconnect', disconnectInfo)
RED.settings.removeLocal('multiplayer:sessionId')

View File

@@ -149,6 +149,8 @@ RED.nodes = (function() {
},
removeNodeSet: function(id) {
var ns = nodeSets[id];
if (!ns) { return {} }
for (var j=0;j<ns.types.length;j++) {
delete typeToId[ns.types[j]];
}
@@ -572,12 +574,16 @@ RED.nodes = (function() {
* @param {String} z tab id
*/
checkTabState: function (z) {
const ws = workspaces[z]
const ws = workspaces[z] || subflows[z]
if (ws) {
const contentsChanged = tabDirtyMap[z].size > 0 || tabDeletedNodesMap[z].size > 0
if (Boolean(ws.contentsChanged) !== contentsChanged) {
ws.contentsChanged = contentsChanged
RED.events.emit("flows:change", ws);
if (ws.type === 'tab') {
RED.events.emit("flows:change", ws);
} else {
RED.events.emit("subflows:change", ws);
}
}
}
}
@@ -1050,7 +1056,22 @@ RED.nodes = (function() {
RED.nodes.registerType("subflow:"+sf.id, {
defaults:{
name:{value:""},
env:{value:[]}
env:{value:[], validate: function(value) {
const errors = []
if (value) {
value.forEach(env => {
const r = RED.utils.validateTypedProperty(env.value, env.type)
if (r !== true) {
errors.push(env.name+': '+r)
}
})
}
if (errors.length === 0) {
return true
} else {
return errors
}
}}
},
icon: function() { return sf.icon||"subflow.svg" },
category: sf.category || "subflows",
@@ -2385,6 +2406,13 @@ RED.nodes = (function() {
} else {
delete n.g
}
// If importing into a subflow, ensure an outbound-link doesn't get added
if (activeSubflow && /^link /.test(n.type) && n.links) {
n.links = n.links.filter(function(id) {
const otherNode = node_map[id] || RED.nodes.node(id);
return (otherNode && otherNode.z === activeWorkspace);
});
}
for (var d3 in n._def.defaults) {
if (n._def.defaults.hasOwnProperty(d3)) {
if (n._def.defaults[d3].type) {
@@ -2408,14 +2436,6 @@ RED.nodes = (function() {
}
}
}
// If importing into a subflow, ensure an outbound-link doesn't
// get added
if (activeSubflow && /^link /.test(n.type) && n.links) {
n.links = n.links.filter(function(id) {
const otherNode = node_map[id] || RED.nodes.node(id);
return (otherNode && otherNode.z === activeWorkspace)
});
}
}
for (i=0;i<new_subflows.length;i++) {
n = new_subflows[i];

View File

@@ -1,6 +1,7 @@
RED.plugins = (function() {
var plugins = {};
var pluginsByType = {};
var moduleList = {};
function registerPlugin(id,definition) {
plugins[id] = definition;
@@ -38,9 +39,43 @@ RED.plugins = (function() {
function getPluginsByType(type) {
return pluginsByType[type] || [];
}
function setPluginList(list) {
for(let i=0;i<list.length;i++) {
let p = list[i];
addPlugin(p);
}
}
function addPlugin(p) {
moduleList[p.module] = moduleList[p.module] || {
name:p.module,
version:p.version,
local:p.local,
sets:{},
plugin: true,
id: p.id
};
if (p.pending_version) {
moduleList[p.module].pending_version = p.pending_version;
}
moduleList[p.module].sets[p.name] = p;
RED.events.emit("registry:plugin-module-added",p.module);
}
function getModule(module) {
return moduleList[module];
}
return {
registerPlugin: registerPlugin,
getPlugin: getPlugin,
getPluginsByType: getPluginsByType
getPluginsByType: getPluginsByType,
setPluginList: setPluginList,
addPlugin: addPlugin,
getModule: getModule
}
})();

View File

@@ -25,6 +25,7 @@ var RED = (function() {
cache: false,
url: 'plugins',
success: function(data) {
RED.plugins.setPluginList(data);
loader.reportProgress(RED._("event.loadPlugins"), 13)
RED.i18n.loadPluginCatalogs(function() {
loadPlugins(function() {
@@ -297,6 +298,7 @@ var RED = (function() {
RED.workspaces.show(workspaces[0]);
}
}
RED.events.emit('flows:loaded')
} catch(err) {
console.warn(err);
RED.notify(
@@ -534,6 +536,41 @@ var RED = (function() {
RED.view.redrawStatus(node);
}
});
RED.comms.subscribe("notification/plugin/#",function(topic,msg) {
if (topic == "notification/plugin/added") {
RED.settings.refreshSettings(function(err, data) {
let addedPlugins = [];
msg.forEach(function(m) {
let id = m.id;
RED.plugins.addPlugin(m);
m.plugins.forEach((p) => {
addedPlugins.push(p.id);
})
RED.i18n.loadNodeCatalog(id, function() {
var lang = localStorage.getItem("editor-language")||RED.i18n.detectLanguage();
$.ajax({
headers: {
"Accept":"text/html",
"Accept-Language": lang
},
cache: false,
url: 'plugins/'+id,
success: function(data) {
appendPluginConfig(data);
}
});
});
});
if (addedPlugins.length) {
let pluginList = "<ul><li>"+addedPlugins.map(RED.utils.sanitize).join("</li><li>")+"</li></ul>";
// ToDo: Adapt notification (node -> plugin)
RED.notify(RED._("palette.event.nodeAdded", {count:addedPlugins.length})+pluginList,"success");
}
})
}
});
let pendingNodeRemovedNotifications = []
let pendingNodeRemovedTimeout

View File

@@ -26,6 +26,7 @@ RED.clipboard = (function() {
var currentPopoverError;
var activeTab;
var libraryBrowser;
var clipboardTabs;
var activeLibraries = {};
@@ -215,6 +216,13 @@ RED.clipboard = (function() {
open: function( event, ui ) {
RED.keyboard.disable();
},
beforeClose: function(e) {
if (clipboardTabs && activeTab === "red-ui-clipboard-dialog-export-tab-clipboard") {
const jsonTabIndex = clipboardTabs.getTabIndex('red-ui-clipboard-dialog-export-tab-clipboard-json')
const activeTabIndex = clipboardTabs.activeIndex()
RED.settings.set("editor.dialog.export.json-view", activeTabIndex === jsonTabIndex )
}
},
close: function(e) {
RED.keyboard.enable();
if (popover) {
@@ -228,12 +236,23 @@ RED.clipboard = (function() {
exportNodesDialog =
'<div class="form-row">'+
'<label style="width:auto;margin-right: 10px;" data-i18n="common.label.export"></label>'+
'<span id="red-ui-clipboard-dialog-export-rng-group" class="button-group">'+
'<a id="red-ui-clipboard-dialog-export-rng-selected" class="red-ui-button toggle" href="#" data-i18n="clipboard.export.selected"></a>'+
'<a id="red-ui-clipboard-dialog-export-rng-flow" class="red-ui-button toggle" href="#" data-i18n="clipboard.export.current"></a>'+
'<a id="red-ui-clipboard-dialog-export-rng-full" class="red-ui-button toggle" href="#" data-i18n="clipboard.export.all"></a>'+
'</span>'+
'<div style="display: flex; justify-content: space-between;">'+
'<div class="form-row">'+
'<label style="width:auto;margin-right: 10px;" data-i18n="common.label.export"></label>'+
'<span id="red-ui-clipboard-dialog-export-rng-group" class="button-group">'+
'<a id="red-ui-clipboard-dialog-export-rng-selected" class="red-ui-button toggle" href="#" data-i18n="clipboard.export.selected"></a>'+
'<a id="red-ui-clipboard-dialog-export-rng-flow" class="red-ui-button toggle" href="#" data-i18n="clipboard.export.current"></a>'+
'<a id="red-ui-clipboard-dialog-export-rng-full" class="red-ui-button toggle" href="#" data-i18n="clipboard.export.all"></a>'+
'</span>'+
'</div>'+
'<div class="form-row">'+
'<label style="width:auto;margin-right: 10px;" data-i18n="common.label.format"></label>'+
'<span id="red-ui-clipboard-dialog-export-fmt-group" class="button-group">'+
'<a id="red-ui-clipboard-dialog-export-fmt-mini" class="red-ui-button red-ui-button toggle" href="#" data-i18n="clipboard.export.compact"></a>'+
'<a id="red-ui-clipboard-dialog-export-fmt-full" class="red-ui-button red-ui-button toggle" href="#" data-i18n="clipboard.export.formatted"></a>'+
'</span>'+
'</div>'+
'</div>'+
'</div>'+
'<div class="red-ui-clipboard-dialog-box">'+
'<div class="red-ui-clipboard-dialog-tabs">'+
@@ -248,15 +267,9 @@ RED.clipboard = (function() {
'<div id="red-ui-clipboard-dialog-export-tab-clipboard-preview-list"></div>'+
'</div>'+
'<div class="red-ui-clipboard-dialog-export-tab-clipboard-tab" id="red-ui-clipboard-dialog-export-tab-clipboard-json">'+
'<div class="form-row" style="height:calc(100% - 40px)">'+
'<div class="form-row" style="height:calc(100% - 10px)">'+
'<textarea readonly id="red-ui-clipboard-dialog-export-text"></textarea>'+
'</div>'+
'<div class="form-row" style="text-align: right;">'+
'<span id="red-ui-clipboard-dialog-export-fmt-group" class="button-group">'+
'<a id="red-ui-clipboard-dialog-export-fmt-mini" class="red-ui-button red-ui-button-small toggle" href="#" data-i18n="clipboard.export.compact"></a>'+
'<a id="red-ui-clipboard-dialog-export-fmt-full" class="red-ui-button red-ui-button-small toggle" href="#" data-i18n="clipboard.export.formatted"></a>'+
'</span>'+
'</div>'+
'</div>'+
'</div>'+
'<div class="form-row" id="red-ui-clipboard-dialog-export-tab-library-filename">'+
@@ -569,7 +582,7 @@ RED.clipboard = (function() {
dialogContainer.empty();
dialogContainer.append($(exportNodesDialog));
clipboardTabs = null
var tabs = RED.tabs.create({
id: "red-ui-clipboard-dialog-export-tabs",
vertical: true,
@@ -630,7 +643,7 @@ RED.clipboard = (function() {
$("#red-ui-clipboard-dialog-tab-library-name").on('paste',function() { setTimeout(validateExportFilename,10)});
$("#red-ui-clipboard-dialog-export").button("enable");
var clipboardTabs = RED.tabs.create({
clipboardTabs = RED.tabs.create({
id: "red-ui-clipboard-dialog-export-tab-clipboard-tabs",
onchange: function(tab) {
$(".red-ui-clipboard-dialog-export-tab-clipboard-tab").hide();
@@ -647,6 +660,9 @@ RED.clipboard = (function() {
id: "red-ui-clipboard-dialog-export-tab-clipboard-json",
label: RED._("editor.types.json")
});
if (RED.settings.get("editor.dialog.export.json-view") === true) {
clipboardTabs.activateTab("red-ui-clipboard-dialog-export-tab-clipboard-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: []

View File

@@ -445,9 +445,12 @@ RED.popover = (function() {
return {
create: createPopover,
tooltip: function(target,content, action) {
tooltip: function(target,content, action, interactive) {
var label = function() {
var label = content;
if (typeof content === 'function') {
label = content()
}
if (action) {
var shortcut = RED.keyboard.getShortcut(action);
if (shortcut && shortcut.key) {
@@ -463,6 +466,7 @@ RED.popover = (function() {
size: "small",
direction: "bottom",
content: label,
interactive,
delay: { show: 750, hide: 50 }
});
popover.setContent = function(newContent) {

View File

@@ -365,7 +365,10 @@ RED.tabs = (function() {
var thisTabA = thisTab.find("a");
if (options.onclick) {
options.onclick(tabs[thisTabA.attr('href').slice(1)]);
options.onclick(tabs[thisTabA.attr('href').slice(1)], evt);
if (evt.isDefaultPrevented() && evt.isPropagationStopped()) {
return false
}
}
activateTab(thisTabA);
if (fireSelectionChanged) {
@@ -548,6 +551,8 @@ RED.tabs = (function() {
ul.find("li.red-ui-tab a")
.on("mousedown", function(evt) { mousedownTab = evt.currentTarget })
.on("mouseup",onTabClick)
// prevent browser-default middle-click behaviour
.on("auxclick", function(evt) { evt.preventDefault() })
.on("click", function(evt) {evt.preventDefault(); })
.on("dblclick", function(evt) {evt.stopPropagation(); evt.preventDefault(); })
@@ -816,6 +821,8 @@ RED.tabs = (function() {
}
link.on("mousedown", function(evt) { mousedownTab = evt.currentTarget })
link.on("mouseup",onTabClick);
// prevent browser-default middle-click behaviour
link.on("auxclick", function(evt) { evt.preventDefault() })
link.on("click", function(evt) { evt.preventDefault(); })
link.on("dblclick", function(evt) { evt.stopPropagation(); evt.preventDefault(); })

View File

@@ -358,61 +358,64 @@
{ value: "_session", source: ["websocket out","tcp out"] },
]
var allOptions = {
msg: {value:"msg",label:"msg.",validate:RED.utils.validatePropertyExpression, autoComplete: msgAutoComplete(msgCompletions)},
flow: {value:"flow",label:"flow.",hasValue:true,
options:[],
validate:RED.utils.validatePropertyExpression,
msg: { value: "msg", label: "msg.", validate: RED.utils.validatePropertyExpression, autoComplete: msgAutoComplete(msgCompletions) },
flow: { value: "flow", label: "flow.", hasValue: true,
options: [],
validate: RED.utils.validatePropertyExpression,
parse: contextParse,
export: contextExport,
valueLabel: contextLabel,
autoComplete: contextAutoComplete
},
global: {value:"global",label:"global.",hasValue:true,
options:[],
validate:RED.utils.validatePropertyExpression,
global: {
value: "global", label: "global.", hasValue: true,
options: [],
validate: RED.utils.validatePropertyExpression,
parse: contextParse,
export: contextExport,
valueLabel: contextLabel,
autoComplete: contextAutoComplete
},
str: {value:"str",label:"string",icon:"red/images/typedInput/az.svg"},
num: {value:"num",label:"number",icon:"red/images/typedInput/09.svg",validate: function(v) {
return (true === RED.utils.validateTypedProperty(v, "num"));
str: { value: "str", label: "string", icon: "red/images/typedInput/az.svg" },
num: { value: "num", label: "number", icon: "red/images/typedInput/09.svg", validate: function (v, o) {
return RED.utils.validateTypedProperty(v, "num", o);
} },
bool: {value:"bool",label:"boolean",icon:"red/images/typedInput/bool.svg",options:["true","false"]},
bool: { value: "bool", label: "boolean", icon: "red/images/typedInput/bool.svg", options: ["true", "false"] },
json: {
value:"json",
label:"JSON",
icon:"red/images/typedInput/json.svg",
validate: function(v) { try{JSON.parse(v);return true;}catch(e){return false;}},
expand: function() {
value: "json",
label: "JSON",
icon: "red/images/typedInput/json.svg",
validate: function (v, o) {
return RED.utils.validateTypedProperty(v, "json", o);
},
expand: function () {
var that = this;
var value = this.value();
try {
value = JSON.stringify(JSON.parse(value),null,4);
} catch(err) {
value = JSON.stringify(JSON.parse(value), null, 4);
} catch (err) {
}
RED.editor.editJSON({
value: value,
stateId: RED.editor.generateViewStateId("typedInput", that, "json"),
focus: true,
complete: function(v) {
complete: function (v) {
var value = v;
try {
value = JSON.stringify(JSON.parse(v));
} catch(err) {
} catch (err) {
}
that.value(value);
}
})
}
},
re: {value:"re",label:"regular expression",icon:"red/images/typedInput/re.svg"},
re: { value: "re", label: "regular expression", icon: "red/images/typedInput/re.svg" },
date: {
value:"date",
label:"timestamp",
icon:"fa fa-clock-o",
options:[
value: "date",
label: "timestamp",
icon: "fa fa-clock-o",
options: [
{
label: 'milliseconds since epoch',
value: ''
@@ -431,15 +434,17 @@
value: "jsonata",
label: "expression",
icon: "red/images/typedInput/expr.svg",
validate: function(v) { try{jsonata(v);return true;}catch(e){return false;}},
expand:function() {
validate: function (v, o) {
return RED.utils.validateTypedProperty(v, "jsonata", o);
},
expand: function () {
var that = this;
RED.editor.editExpression({
value: this.value().replace(/\t/g,"\n"),
value: this.value().replace(/\t/g, "\n"),
stateId: RED.editor.generateViewStateId("typedInput", that, "jsonata"),
focus: true,
complete: function(v) {
that.value(v.replace(/\n/g,"\t"));
complete: function (v) {
that.value(v.replace(/\n/g, "\t"));
}
})
}
@@ -448,13 +453,13 @@
value: "bin",
label: "buffer",
icon: "red/images/typedInput/bin.svg",
expand: function() {
expand: function () {
var that = this;
RED.editor.editBuffer({
value: this.value(),
stateId: RED.editor.generateViewStateId("typedInput", that, "bin"),
focus: true,
complete: function(v) {
complete: function (v) {
that.value(v);
}
})
@@ -470,9 +475,9 @@
value: "node",
label: "node",
icon: "red/images/typedInput/target.svg",
valueLabel: function(container,value) {
valueLabel: function (container, value) {
var node = RED.nodes.node(value);
var nodeDiv = $('<div>',{class:"red-ui-search-result-node"}).css({
var nodeDiv = $('<div>', { class: "red-ui-search-result-node" }).css({
"margin-top": "2px",
"margin-left": "3px"
}).appendTo(container);
@@ -481,117 +486,117 @@
"margin-left": "6px"
}).appendTo(container);
if (node) {
var colour = RED.utils.getNodeColor(node.type,node._def);
var icon_url = RED.utils.getNodeIcon(node._def,node);
var colour = RED.utils.getNodeColor(node.type, node._def);
var icon_url = RED.utils.getNodeIcon(node._def, node);
if (node.type === 'tab') {
colour = "#C0DEED";
}
nodeDiv.css('backgroundColor',colour);
var iconContainer = $('<div/>',{class:"red-ui-palette-icon-container"}).appendTo(nodeDiv);
nodeDiv.css('backgroundColor', colour);
var iconContainer = $('<div/>', { class: "red-ui-palette-icon-container" }).appendTo(nodeDiv);
RED.utils.createIconElement(icon_url, iconContainer, true);
var l = RED.utils.getNodeLabel(node,node.id);
var l = RED.utils.getNodeLabel(node, node.id);
nodeLabel.text(l);
} else {
nodeDiv.css({
'backgroundColor': '#eee',
'border-style' : 'dashed'
'border-style': 'dashed'
});
}
},
expand: function() {
expand: function () {
var that = this;
RED.tray.hide();
RED.view.selectNodes({
single: true,
selected: [that.value()],
onselect: function(selection) {
onselect: function (selection) {
that.value(selection.id);
RED.tray.show();
},
oncancel: function() {
oncancel: function () {
RED.tray.show();
}
})
}
},
cred:{
value:"cred",
label:"credential",
icon:"fa fa-lock",
cred: {
value: "cred",
label: "credential",
icon: "fa fa-lock",
inputType: "password",
valueLabel: function(container,value) {
valueLabel: function (container, value) {
var that = this;
container.css("pointer-events","none");
container.css("flex-grow",0);
container.css("pointer-events", "none");
container.css("flex-grow", 0);
this.elementDiv.hide();
var buttons = $('<div>').css({
position: "absolute",
right:"6px",
right: "6px",
top: "6px",
"pointer-events":"all"
"pointer-events": "all"
}).appendTo(container);
var eyeButton = $('<button type="button" class="red-ui-button red-ui-button-small"></button>').css({
width:"20px"
}).appendTo(buttons).on("click", function(evt) {
width: "20px"
}).appendTo(buttons).on("click", function (evt) {
evt.preventDefault();
var cursorPosition = that.input[0].selectionStart;
var currentType = that.input.attr("type");
if (currentType === "text") {
that.input.attr("type","password");
that.input.attr("type", "password");
eyeCon.removeClass("fa-eye-slash").addClass("fa-eye");
setTimeout(function() {
setTimeout(function () {
that.input.focus();
that.input[0].setSelectionRange(cursorPosition, cursorPosition);
},50);
}, 50);
} else {
that.input.attr("type","text");
that.input.attr("type", "text");
eyeCon.removeClass("fa-eye").addClass("fa-eye-slash");
setTimeout(function() {
setTimeout(function () {
that.input.focus();
that.input[0].setSelectionRange(cursorPosition, cursorPosition);
},50);
}, 50);
}
}).hide();
var eyeCon = $('<i class="fa fa-eye"></i>').css("margin-left","-2px").appendTo(eyeButton);
var eyeCon = $('<i class="fa fa-eye"></i>').css("margin-left", "-2px").appendTo(eyeButton);
if (value === "__PWRD__") {
var innerContainer = $('<div><i class="fa fa-asterisk"></i><i class="fa fa-asterisk"></i><i class="fa fa-asterisk"></i><i class="fa fa-asterisk"></i><i class="fa fa-asterisk"></i></div>').css({
padding:"6px 6px",
borderRadius:"4px"
padding: "6px 6px",
borderRadius: "4px"
}).addClass("red-ui-typedInput-value-label-inactive").appendTo(container);
var editButton = $('<button type="button" class="red-ui-button red-ui-button-small"><i class="fa fa-pencil"></i></button>').appendTo(buttons).on("click", function(evt) {
var editButton = $('<button type="button" class="red-ui-button red-ui-button-small"><i class="fa fa-pencil"></i></button>').appendTo(buttons).on("click", function (evt) {
evt.preventDefault();
innerContainer.hide();
container.css("background","none");
container.css("pointer-events","none");
container.css("background", "none");
container.css("pointer-events", "none");
that.input.val("");
that.element.val("");
that.elementDiv.show();
editButton.hide();
cancelButton.show();
eyeButton.show();
setTimeout(function() {
setTimeout(function () {
that.input.focus();
},50);
}, 50);
});
var cancelButton = $('<button type="button" class="red-ui-button red-ui-button-small"><i class="fa fa-times"></i></button>').css("margin-left","3px").appendTo(buttons).on("click", function(evt) {
var cancelButton = $('<button type="button" class="red-ui-button red-ui-button-small"><i class="fa fa-times"></i></button>').css("margin-left", "3px").appendTo(buttons).on("click", function (evt) {
evt.preventDefault();
innerContainer.show();
container.css("background","");
container.css("background", "");
that.input.val("__PWRD__");
that.element.val("__PWRD__");
that.elementDiv.hide();
editButton.show();
cancelButton.hide();
eyeButton.hide();
that.input.attr("type","password");
that.input.attr("type", "password");
eyeCon.removeClass("fa-eye-slash").addClass("fa-eye");
}).hide();
} else {
container.css("background","none");
container.css("pointer-events","none");
container.css("background", "none");
container.css("pointer-events", "none");
this.elementDiv.show();
eyeButton.show();
}
@@ -1009,12 +1014,12 @@
}
if (menu.opts.multiple) {
var selected = {};
this.value().split(",").forEach(function(f) {
selected[f] = true;
})
this.value().split(",").forEach(function(f) {
selected[f] = true;
});
menu.find('input[type="checkbox"]').each(function() {
$(this).prop("checked",selected[$(this).data('value')])
})
$(this).prop("checked", selected[$(this).data('value')] || false);
});
}
@@ -1105,7 +1110,7 @@
this.input.trigger('change',[this.propertyType,this.value()]);
}
} else {
this.optionSelectLabel.text(o.length+" selected");
this.optionSelectLabel.text(RED._("typedInput.selected", { count: o.length }));
}
}
},
@@ -1538,26 +1543,48 @@
}
}
},
validate: function() {
var result;
var value = this.value();
var type = this.type();
validate: function(options) {
let valid = true;
const value = this.value();
const type = this.type();
if (this.typeMap[type] && this.typeMap[type].validate) {
var val = this.typeMap[type].validate;
if (typeof val === 'function') {
result = val(value);
const validate = this.typeMap[type].validate;
if (typeof validate === 'function') {
valid = validate(value, {});
} else {
result = val.test(value);
// Regex
valid = validate.test(value);
if (!valid) {
valid = RED._("validator.errors.invalid-regexp");
}
}
}
if ((typeof valid === "string") || !valid) {
this.element.addClass("input-error");
this.uiSelect.addClass("input-error");
if (typeof valid === "string") {
let tooltip = this.element.data("tooltip");
if (tooltip) {
tooltip.setContent(valid);
} else {
tooltip = RED.popover.tooltip(this.elementDiv, valid);
this.element.data("tooltip", tooltip);
}
}
} else {
result = true;
this.element.removeClass("input-error");
this.uiSelect.removeClass("input-error");
const tooltip = this.element.data("tooltip");
if (tooltip) {
this.element.data("tooltip", null);
tooltip.delete();
}
}
if (result) {
this.uiSelect.removeClass('input-error');
} else {
this.uiSelect.addClass('input-error');
if (options?.returnErrorMessage === true) {
return valid;
}
return result;
// Must return a boolean for no 3.x validator
return (typeof valid === "string") ? false : valid;
},
show: function() {
this.uiSelect.show();

View File

@@ -32,24 +32,28 @@ RED.contextMenu = (function () {
const canRemoveFromGroup = hasSelection && !!selection.nodes[0].g
let hasGroup, isAllGroups = true, hasDisabledNode, hasEnabledNode, hasLabeledNode, hasUnlabeledNode;
if (hasSelection) {
selection.nodes.forEach(n => {
const nodes = selection.nodes.slice();
while (nodes.length) {
const n = nodes.shift();
if (n.type === 'group') {
hasGroup = true;
nodes.push(...n.nodes);
} else {
isAllGroups = false;
}
if (n.d) {
hasDisabledNode = true;
} else {
hasEnabledNode = true;
if (n.d) {
hasDisabledNode = true;
} else {
hasEnabledNode = true;
}
}
if (n.l === undefined || n.l) {
hasLabeledNode = true;
} else {
hasUnlabeledNode = true;
}
});
}
}
const offset = $("#red-ui-workspace-chart").offset()
let addX = options.x - offset.left + $("#red-ui-workspace-chart").scrollLeft()
@@ -118,10 +122,16 @@ RED.contextMenu = (function () {
onselect: 'core:split-wire-with-link-nodes',
disabled: !canEdit || !hasLinks
},
null,
{ onselect: 'core:show-import-dialog', label: RED._('common.label.import')},
{ onselect: 'core:show-examples-import-dialog', label: RED._('menu.label.importExample') }
null
)
if (RED.settings.theme("menu.menu-item-import-library", true)) {
insertOptions.push(
{ onselect: 'core:show-import-dialog', label: RED._('common.label.import')},
{ onselect: 'core:show-examples-import-dialog', label: RED._('menu.label.importExample') }
)
}
if (hasSelection && canEdit) {
const nodeOptions = []
if (!hasMultipleSelection && !isGroup) {
@@ -194,8 +204,14 @@ RED.contextMenu = (function () {
{ onselect: 'core:paste-from-internal-clipboard', label: RED._("keyboard.pasteNode"), disabled: !canEdit || !RED.view.clipboard() },
{ onselect: 'core:delete-selection', label: RED._('keyboard.deleteSelected'), disabled: !canEdit || !canDelete },
{ onselect: 'core:delete-selection-and-reconnect', label: RED._('keyboard.deleteReconnect'), disabled: !canEdit || !canDelete },
{ onselect: 'core:show-export-dialog', label: RED._("menu.label.export") },
{ onselect: 'core:select-all-nodes', label: RED._("keyboard.selectAll") },
)
if (RED.settings.theme("menu.menu-item-export-library", true)) {
menuItems.push(
{ onselect: 'core:show-export-dialog', label: RED._("menu.label.export") }
)
}
menuItems.push(
{ onselect: 'core:select-all-nodes', label: RED._("keyboard.selectAll") }
)
}

View File

@@ -34,6 +34,8 @@ RED.deploy = (function() {
var currentDiff = null;
var activeBackgroundDeployNotification;
function changeDeploymentType(type) {
deploymentType = type;
$("#red-ui-header-button-deploy-icon").attr("src",deploymentTypes[type].img);
@@ -61,7 +63,7 @@ RED.deploy = (function() {
'<img src="red/images/spin.svg"/>'+
'</span>'+
'</a>'+
'<a id="red-ui-header-button-deploy-options" class="red-ui-deploy-button" href="#"><i class="fa fa-caret-down"></i></a>'+
'<a id="red-ui-header-button-deploy-options" class="red-ui-deploy-button" href="#"><i class="fa fa-caret-down"></i><i class="fa fa-lock"></i></a>'+
'</span></li>').prependTo(".red-ui-header-toolbar");
const mainMenuItems = [
{id:"deploymenu-item-full",toggle:"deploy-type",icon:"red/images/deploy-full.svg",label:RED._("deploy.full"),sublabel:RED._("deploy.fullDesc"),selected: true, onselect:function(s) { if(s){changeDeploymentType("full")}}},
@@ -112,53 +114,80 @@ RED.deploy = (function() {
RED.actions.add("core:set-deploy-type-to-modified-nodes",function() { RED.menu.setSelected("deploymenu-item-node",true); });
}
window.addEventListener('beforeunload', function (event) {
if (RED.nodes.dirty()) {
event.preventDefault();
event.stopImmediatePropagation()
event.returnValue = RED._("deploy.confirm.undeployedChanges");
return
}
})
RED.events.on('workspace:dirty',function(state) {
if (RED.settings.user?.permissions === 'read') {
return
}
if (state.dirty) {
window.onbeforeunload = function() {
return RED._("deploy.confirm.undeployedChanges");
}
// window.onbeforeunload = function() {
// return
// }
$("#red-ui-header-button-deploy").removeClass("disabled");
} else {
window.onbeforeunload = null;
// window.onbeforeunload = null;
$("#red-ui-header-button-deploy").addClass("disabled");
}
});
var activeNotifyMessage;
RED.comms.subscribe("notification/runtime-deploy",function(topic,msg) {
if (!activeNotifyMessage) {
var currentRev = RED.nodes.version();
if (currentRev === null || deployInflight || currentRev === msg.revision) {
return;
}
var message = $('<p>').text(RED._('deploy.confirm.backgroundUpdate'));
activeNotifyMessage = RED.notify(message,{
modal: true,
fixed: true,
buttons: [
{
text: RED._('deploy.confirm.button.ignore'),
click: function() {
activeNotifyMessage.close();
activeNotifyMessage = null;
}
},
{
text: RED._('deploy.confirm.button.review'),
class: "primary",
click: function() {
activeNotifyMessage.close();
var nns = RED.nodes.createCompleteNodeSet();
resolveConflict(nns,false);
activeNotifyMessage = null;
}
var currentRev = RED.nodes.version();
if (currentRev === null || deployInflight || currentRev === msg.revision) {
return;
}
if (activeBackgroundDeployNotification?.hidden && !activeBackgroundDeployNotification?.closed) {
activeBackgroundDeployNotification.showNotification()
return
}
const message = $('<p>').text(RED._('deploy.confirm.backgroundUpdate'));
const options = {
id: 'background-update',
type: 'compact',
modal: false,
fixed: true,
timeout: 10000,
buttons: [
{
text: RED._('deploy.confirm.button.review'),
class: "primary",
click: function() {
activeBackgroundDeployNotification.hideNotification();
var nns = RED.nodes.createCompleteNodeSet();
resolveConflict(nns,false);
}
]
});
}
]
}
if (!activeBackgroundDeployNotification || activeBackgroundDeployNotification.closed) {
activeBackgroundDeployNotification = RED.notify(message, options)
} else {
activeBackgroundDeployNotification.update(message, options)
}
});
updateLockedState()
RED.events.on('login', updateLockedState)
}
function updateLockedState() {
if (RED.settings.user?.permissions === 'read') {
$(".red-ui-deploy-button-group").addClass("readOnly");
$("#red-ui-header-button-deploy").addClass("disabled");
} else {
$(".red-ui-deploy-button-group").removeClass("readOnly");
if (RED.nodes.dirty()) {
$("#red-ui-header-button-deploy").removeClass("disabled");
}
}
}
function getNodeInfo(node) {
@@ -213,7 +242,11 @@ RED.deploy = (function() {
class: "primary disabled",
click: function() {
if (!$("#red-ui-deploy-dialog-confirm-deploy-review").hasClass('disabled')) {
RED.diff.showRemoteDiff();
RED.diff.showRemoteDiff(null, {
onmerge: function () {
activeBackgroundDeployNotification.close()
}
});
conflictNotification.close();
}
}
@@ -226,6 +259,7 @@ RED.deploy = (function() {
if (!$("#red-ui-deploy-dialog-confirm-deploy-merge").hasClass('disabled')) {
RED.diff.mergeDiff(currentDiff);
conflictNotification.close();
activeBackgroundDeployNotification.close()
}
}
}
@@ -238,6 +272,7 @@ RED.deploy = (function() {
click: function() {
save(true,activeDeploy);
conflictNotification.close();
activeBackgroundDeployNotification.close()
}
})
}
@@ -248,21 +283,17 @@ RED.deploy = (function() {
buttons: buttons
});
var now = Date.now();
RED.diff.getRemoteDiff(function(diff) {
var ellapsed = Math.max(1000 - (Date.now()-now), 0);
currentDiff = diff;
setTimeout(function() {
conflictCheck.hide();
var d = Object.keys(diff.conflicts);
if (d.length === 0) {
conflictAutoMerge.show();
$("#red-ui-deploy-dialog-confirm-deploy-merge").removeClass('disabled')
} else {
conflictManualMerge.show();
}
$("#red-ui-deploy-dialog-confirm-deploy-review").removeClass('disabled')
},ellapsed);
conflictCheck.hide();
var d = Object.keys(diff.conflicts);
if (d.length === 0) {
conflictAutoMerge.show();
$("#red-ui-deploy-dialog-confirm-deploy-merge").removeClass('disabled')
} else {
conflictManualMerge.show();
}
$("#red-ui-deploy-dialog-confirm-deploy-review").removeClass('disabled')
})
}
function cropList(list) {
@@ -612,7 +643,10 @@ RED.deploy = (function() {
}
});
RED.nodes.eachSubflow(function (subflow) {
subflow.changed = false;
if (subflow.changed) {
subflow.changed = false;
RED.events.emit("subflows:change", subflow);
}
});
RED.nodes.eachWorkspace(function (ws) {
if (ws.changed || ws.added) {
@@ -628,6 +662,7 @@ RED.deploy = (function() {
// Once deployed, cannot undo back to a clean state
RED.history.markAllDirty();
RED.view.redraw();
RED.sidebar.config.refresh();
RED.events.emit("deploy");
}).fail(function (xhr, textStatus, err) {
RED.nodes.dirty(true);

View File

@@ -1,5 +1,4 @@
RED.diff = (function() {
var currentDiff = {};
var diffVisible = false;
var diffList;
@@ -62,12 +61,14 @@ RED.diff = (function() {
addedCount:0,
deletedCount:0,
changedCount:0,
movedCount:0,
unchangedCount: 0
},
remote: {
addedCount:0,
deletedCount:0,
changedCount:0,
movedCount:0,
unchangedCount: 0
},
conflicts: 0
@@ -138,7 +139,7 @@ RED.diff = (function() {
$(this).parent().toggleClass('collapsed');
});
createNodePropertiesTable(def,tab,localTabNode,remoteTabNode,conflicts).appendTo(div);
createNodePropertiesTable(def,tab,localTabNode,remoteTabNode).appendTo(div);
selectState = "";
if (conflicts[tab.id]) {
flowStats.conflicts++;
@@ -208,19 +209,26 @@ RED.diff = (function() {
var localStats = $('<span>',{class:"red-ui-diff-list-flow-stats"}).appendTo(localCell);
$('<span class="red-ui-diff-status"></span>').text(RED._('diff.nodeCount',{count:localNodeCount})).appendTo(localStats);
if (flowStats.conflicts + flowStats.local.addedCount + flowStats.local.changedCount + flowStats.local.deletedCount > 0) {
if (flowStats.conflicts + flowStats.local.addedCount + flowStats.local.changedCount + flowStats.local.movedCount + flowStats.local.deletedCount > 0) {
$('<span class="red-ui-diff-status"> [ </span>').appendTo(localStats);
if (flowStats.conflicts > 0) {
$('<span class="red-ui-diff-status-conflict"><span class="red-ui-diff-status"><i class="fa fa-exclamation"></i> '+flowStats.conflicts+'</span></span>').appendTo(localStats);
}
if (flowStats.local.addedCount > 0) {
$('<span class="red-ui-diff-status-added"><span class="red-ui-diff-status"><i class="fa fa-plus-square"></i> '+flowStats.local.addedCount+'</span></span>').appendTo(localStats);
const cell = $('<span class="red-ui-diff-status-added"><span class="red-ui-diff-status"><i class="fa fa-plus-square"></i> '+flowStats.local.addedCount+'</span></span>').appendTo(localStats);
RED.popover.tooltip(cell, RED._('diff.type.added'))
}
if (flowStats.local.changedCount > 0) {
$('<span class="red-ui-diff-status-changed"><span class="red-ui-diff-status"><i class="fa fa-square"></i> '+flowStats.local.changedCount+'</span></span>').appendTo(localStats);
const cell = $('<span class="red-ui-diff-status-changed"><span class="red-ui-diff-status"><i class="fa fa-square"></i> '+flowStats.local.changedCount+'</span></span>').appendTo(localStats);
RED.popover.tooltip(cell, RED._('diff.type.changed'))
}
if (flowStats.local.movedCount > 0) {
const cell = $('<span class="red-ui-diff-status-moved"><span class="red-ui-diff-status"><i class="fa fa-square"></i> '+flowStats.local.movedCount+'</span></span>').appendTo(localStats);
RED.popover.tooltip(cell, RED._('diff.type.moved'))
}
if (flowStats.local.deletedCount > 0) {
$('<span class="red-ui-diff-status-deleted"><span class="red-ui-diff-status"><i class="fa fa-minus-square"></i> '+flowStats.local.deletedCount+'</span></span>').appendTo(localStats);
const cell = $('<span class="red-ui-diff-status-deleted"><span class="red-ui-diff-status"><i class="fa fa-minus-square"></i> '+flowStats.local.deletedCount+'</span></span>').appendTo(localStats);
RED.popover.tooltip(cell, RED._('diff.type.deleted'))
}
$('<span class="red-ui-diff-status"> ] </span>').appendTo(localStats);
}
@@ -246,19 +254,26 @@ RED.diff = (function() {
}
var remoteStats = $('<span>',{class:"red-ui-diff-list-flow-stats"}).appendTo(remoteCell);
$('<span class="red-ui-diff-status"></span>').text(RED._('diff.nodeCount',{count:remoteNodeCount})).appendTo(remoteStats);
if (flowStats.conflicts + flowStats.remote.addedCount + flowStats.remote.changedCount + flowStats.remote.deletedCount > 0) {
if (flowStats.conflicts + flowStats.remote.addedCount + flowStats.remote.changedCount + flowStats.remote.movedCount + flowStats.remote.deletedCount > 0) {
$('<span class="red-ui-diff-status"> [ </span>').appendTo(remoteStats);
if (flowStats.conflicts > 0) {
$('<span class="red-ui-diff-status-conflict"><span class="red-ui-diff-status"><i class="fa fa-exclamation"></i> '+flowStats.conflicts+'</span></span>').appendTo(remoteStats);
}
if (flowStats.remote.addedCount > 0) {
$('<span class="red-ui-diff-status-added"><span class="red-ui-diff-status"><i class="fa fa-plus-square"></i> '+flowStats.remote.addedCount+'</span></span>').appendTo(remoteStats);
const cell = $('<span class="red-ui-diff-status-added"><span class="red-ui-diff-status"><i class="fa fa-plus-square"></i> '+flowStats.remote.addedCount+'</span></span>').appendTo(remoteStats);
RED.popover.tooltip(cell, RED._('diff.type.added'))
}
if (flowStats.remote.changedCount > 0) {
$('<span class="red-ui-diff-status-changed"><span class="red-ui-diff-status"><i class="fa fa-square"></i> '+flowStats.remote.changedCount+'</span></span>').appendTo(remoteStats);
const cell = $('<span class="red-ui-diff-status-changed"><span class="red-ui-diff-status"><i class="fa fa-square"></i> '+flowStats.remote.changedCount+'</span></span>').appendTo(remoteStats);
RED.popover.tooltip(cell, RED._('diff.type.changed'))
}
if (flowStats.remote.movedCount > 0) {
const cell = $('<span class="red-ui-diff-status-moved"><span class="red-ui-diff-status"><i class="fa fa-square"></i> '+flowStats.remote.movedCount+'</span></span>').appendTo(remoteStats);
RED.popover.tooltip(cell, RED._('diff.type.moved'))
}
if (flowStats.remote.deletedCount > 0) {
$('<span class="red-ui-diff-status-deleted"><span class="red-ui-diff-status"><i class="fa fa-minus-square"></i> '+flowStats.remote.deletedCount+'</span></span>').appendTo(remoteStats);
const cell = $('<span class="red-ui-diff-status-deleted"><span class="red-ui-diff-status"><i class="fa fa-minus-square"></i> '+flowStats.remote.deletedCount+'</span></span>').appendTo(remoteStats);
RED.popover.tooltip(cell, RED._('diff.type.deleted'))
}
$('<span class="red-ui-diff-status"> ] </span>').appendTo(remoteStats);
}
@@ -293,7 +308,7 @@ RED.diff = (function() {
if (options.mode === "merge") {
diffPanel.addClass("red-ui-diff-panel-merge");
}
var diffList = createDiffTable(diffPanel, diff);
var diffList = createDiffTable(diffPanel, diff, options);
var localDiff = diff.localDiff;
var remoteDiff = diff.remoteDiff;
@@ -516,7 +531,6 @@ RED.diff = (function() {
var hasChanges = false; // exists in original and local/remote but with changes
var unChanged = true; // existing in original,local,remote unchanged
var localChanged = false;
if (localDiff.added[node.id]) {
stats.local.addedCount++;
@@ -535,12 +549,20 @@ RED.diff = (function() {
unChanged = false;
}
if (localDiff.changed[node.id]) {
stats.local.changedCount++;
if (localDiff.positionChanged[node.id]) {
stats.local.movedCount++
} else {
stats.local.changedCount++;
}
hasChanges = true;
unChanged = false;
}
if (remoteDiff && remoteDiff.changed[node.id]) {
stats.remote.changedCount++;
if (remoteDiff.positionChanged[node.id]) {
stats.remote.movedCount++
} else {
stats.remote.changedCount++;
}
hasChanges = true;
unChanged = false;
}
@@ -605,27 +627,32 @@ RED.diff = (function() {
localNodeDiv.addClass("red-ui-diff-status-moved");
var localMovedMessage = "";
if (node.z === localN.z) {
localMovedMessage = RED._("diff.type.movedFrom",{id:(localDiff.currentConfig.all[node.id].z||'global')});
const movedFromNodeTab = localDiff.currentConfig.all[localDiff.currentConfig.all[node.id].z]
const movedFromLabel = `'${movedFromNodeTab ? (movedFromNodeTab.label || movedFromNodeTab.id) : 'global'}'`
localMovedMessage = RED._("diff.type.movedFrom",{id: movedFromLabel});
} else {
localMovedMessage = RED._("diff.type.movedTo",{id:(localN.z||'global')});
const movedToNodeTab = localDiff.newConfig.all[localN.z]
const movedToLabel = `'${movedToNodeTab ? (movedToNodeTab.label || movedToNodeTab.id) : 'global'}'`
localMovedMessage = RED._("diff.type.movedTo",{id:movedToLabel});
}
$('<span class="red-ui-diff-status"><i class="fa fa-caret-square-o-right"></i> '+localMovedMessage+'</span>').appendTo(localNodeDiv);
}
localChanged = true;
} else if (localDiff.deleted[node.z]) {
localNodeDiv.addClass("red-ui-diff-empty");
localChanged = true;
} else if (localDiff.deleted[node.id]) {
localNodeDiv.addClass("red-ui-diff-status-deleted");
$('<span class="red-ui-diff-status"><i class="fa fa-minus-square"></i> <span data-i18n="diff.type.deleted"></span></span>').appendTo(localNodeDiv);
localChanged = true;
} else if (localDiff.changed[node.id]) {
if (localDiff.newConfig.all[node.id].z !== node.z) {
localNodeDiv.addClass("red-ui-diff-empty");
} else {
localNodeDiv.addClass("red-ui-diff-status-changed");
$('<span class="red-ui-diff-status"><i class="fa fa-square"></i> <span data-i18n="diff.type.changed"></span></span>').appendTo(localNodeDiv);
localChanged = true;
if (localDiff.positionChanged[node.id]) {
localNodeDiv.addClass("red-ui-diff-status-moved");
$('<span class="red-ui-diff-status"><i class="fa fa-square"></i> <span data-i18n="diff.type.moved"></span></span>').appendTo(localNodeDiv);
} else {
localNodeDiv.addClass("red-ui-diff-status-changed");
$('<span class="red-ui-diff-status"><i class="fa fa-square"></i> <span data-i18n="diff.type.changed"></span></span>').appendTo(localNodeDiv);
}
}
} else {
if (localDiff.newConfig.all[node.id].z !== node.z) {
@@ -646,9 +673,13 @@ RED.diff = (function() {
remoteNodeDiv.addClass("red-ui-diff-status-moved");
var remoteMovedMessage = "";
if (node.z === remoteN.z) {
remoteMovedMessage = RED._("diff.type.movedFrom",{id:(remoteDiff.currentConfig.all[node.id].z||'global')});
const movedFromNodeTab = remoteDiff.currentConfig.all[remoteDiff.currentConfig.all[node.id].z]
const movedFromLabel = `'${movedFromNodeTab ? (movedFromNodeTab.label || movedFromNodeTab.id) : 'global'}'`
remoteMovedMessage = RED._("diff.type.movedFrom",{id:movedFromLabel});
} else {
remoteMovedMessage = RED._("diff.type.movedTo",{id:(remoteN.z||'global')});
const movedToNodeTab = remoteDiff.newConfig.all[remoteN.z]
const movedToLabel = `'${movedToNodeTab ? (movedToNodeTab.label || movedToNodeTab.id) : 'global'}'`
remoteMovedMessage = RED._("diff.type.movedTo",{id:movedToLabel});
}
$('<span class="red-ui-diff-status"><i class="fa fa-caret-square-o-right"></i> '+remoteMovedMessage+'</span>').appendTo(remoteNodeDiv);
}
@@ -661,8 +692,13 @@ RED.diff = (function() {
if (remoteDiff.newConfig.all[node.id].z !== node.z) {
remoteNodeDiv.addClass("red-ui-diff-empty");
} else {
remoteNodeDiv.addClass("red-ui-diff-status-changed");
$('<span class="red-ui-diff-status"><i class="fa fa-square"></i> <span data-i18n="diff.type.changed"></span></span>').appendTo(remoteNodeDiv);
if (remoteDiff.positionChanged[node.id]) {
remoteNodeDiv.addClass("red-ui-diff-status-moved");
$('<span class="red-ui-diff-status"><i class="fa fa-square"></i> <span data-i18n="diff.type.moved"></span></span>').appendTo(remoteNodeDiv);
} else {
remoteNodeDiv.addClass("red-ui-diff-status-changed");
$('<span class="red-ui-diff-status"><i class="fa fa-square"></i> <span data-i18n="diff.type.changed"></span></span>').appendTo(remoteNodeDiv);
}
}
} else {
if (remoteDiff.newConfig.all[node.id].z !== node.z) {
@@ -788,7 +824,7 @@ RED.diff = (function() {
$("<td>",{class:"red-ui-diff-list-cell-label"}).text("position").appendTo(row);
localCell = $("<td>",{class:"red-ui-diff-list-cell red-ui-diff-list-node-local"}).appendTo(row);
if (localNode) {
localCell.addClass("red-ui-diff-status-"+(localChanged?"changed":"unchanged"));
localCell.addClass("red-ui-diff-status-"+(localChanged?"moved":"unchanged"));
$('<span class="red-ui-diff-status">'+(localChanged?'<i class="fa fa-square"></i>':'')+'</span>').appendTo(localCell);
element = $('<span class="red-ui-diff-list-element"></span>').appendTo(localCell);
var localPosition = {x:localNode.x,y:localNode.y};
@@ -813,7 +849,7 @@ RED.diff = (function() {
if (remoteNode !== undefined) {
remoteCell = $("<td>",{class:"red-ui-diff-list-cell red-ui-diff-list-node-remote"}).appendTo(row);
remoteCell.addClass("red-ui-diff-status-"+(remoteChanged?"changed":"unchanged"));
remoteCell.addClass("red-ui-diff-status-"+(remoteChanged?"moved":"unchanged"));
if (remoteNode) {
$('<span class="red-ui-diff-status">'+(remoteChanged?'<i class="fa fa-square"></i>':'')+'</span>').appendTo(remoteCell);
element = $('<span class="red-ui-diff-list-element"></span>').appendTo(remoteCell);
@@ -1099,11 +1135,11 @@ RED.diff = (function() {
// var diff = generateDiff(originalFlow,nns);
// showDiff(diff);
// }
function showRemoteDiff(diff) {
if (diff === undefined) {
getRemoteDiff(showRemoteDiff);
function showRemoteDiff(diff, options = {}) {
if (!diff) {
getRemoteDiff((remoteDiff) => showRemoteDiff(remoteDiff, options));
} else {
showDiff(diff,{mode:'merge'});
showDiff(diff,{...options, mode:'merge'});
}
}
function parseNodes(nodeList) {
@@ -1144,23 +1180,53 @@ RED.diff = (function() {
}
}
function generateDiff(currentNodes,newNodes) {
var currentConfig = parseNodes(currentNodes);
var newConfig = parseNodes(newNodes);
var added = {};
var deleted = {};
var changed = {};
var moved = {};
const currentConfig = parseNodes(currentNodes);
const newConfig = parseNodes(newNodes);
const added = {};
const deleted = {};
const changed = {};
const positionChanged = {};
const moved = {};
Object.keys(currentConfig.all).forEach(function(id) {
var node = RED.nodes.workspace(id)||RED.nodes.subflow(id)||RED.nodes.node(id);
const node = RED.nodes.workspace(id)||RED.nodes.subflow(id)||RED.nodes.node(id);
if (!newConfig.all.hasOwnProperty(id)) {
deleted[id] = true;
} else if (JSON.stringify(currentConfig.all[id]) !== JSON.stringify(newConfig.all[id])) {
return
}
const currentConfigJSON = JSON.stringify(currentConfig.all[id])
const newConfigJSON = JSON.stringify(newConfig.all[id])
if (currentConfigJSON !== newConfigJSON) {
changed[id] = true;
if (currentConfig.all[id].z !== newConfig.all[id].z) {
moved[id] = true;
} else if (
currentConfig.all[id].x !== newConfig.all[id].x ||
currentConfig.all[id].y !== newConfig.all[id].y ||
currentConfig.all[id].w !== newConfig.all[id].w ||
currentConfig.all[id].h !== newConfig.all[id].h
) {
// This node's position on its parent has changed. We want to
// check if this is the *only* change for this given node
const currentNodeClone = JSON.parse(currentConfigJSON)
const newNodeClone = JSON.parse(newConfigJSON)
delete currentNodeClone.x
delete currentNodeClone.y
delete currentNodeClone.w
delete currentNodeClone.h
delete newNodeClone.x
delete newNodeClone.y
delete newNodeClone.w
delete newNodeClone.h
if (JSON.stringify(currentNodeClone) === JSON.stringify(newNodeClone)) {
// Only the position has changed - everything else is the same
positionChanged[id] = true
}
}
}
});
Object.keys(newConfig.all).forEach(function(id) {
@@ -1169,13 +1235,14 @@ RED.diff = (function() {
}
});
var diff = {
currentConfig: currentConfig,
newConfig: newConfig,
added: added,
deleted: deleted,
changed: changed,
moved: moved
const diff = {
currentConfig,
newConfig,
added,
deleted,
changed,
positionChanged,
moved
};
return diff;
}
@@ -1240,12 +1307,14 @@ RED.diff = (function() {
return diff;
}
function showDiff(diff,options) {
function showDiff(diff, options) {
if (diffVisible) {
return;
}
options = options || {};
var mode = options.mode || 'merge';
options.hidePositionChanges = true
var localDiff = diff.localDiff;
var remoteDiff = diff.remoteDiff;
@@ -1315,6 +1384,9 @@ RED.diff = (function() {
if (!$("#red-ui-diff-view-diff-merge").hasClass('disabled')) {
refreshConflictHeader(diff);
mergeDiff(diff);
if (options.onmerge) {
options.onmerge()
}
RED.tray.close();
}
}
@@ -1345,6 +1417,7 @@ RED.diff = (function() {
var newConfig = [];
var node;
var nodeChangedStates = {};
var nodeMovedStates = {};
var localChangedStates = {};
for (id in localDiff.newConfig.all) {
if (localDiff.newConfig.all.hasOwnProperty(id)) {
@@ -1352,12 +1425,14 @@ RED.diff = (function() {
if (resolutions[id] === 'local') {
if (node) {
nodeChangedStates[id] = node.changed;
nodeMovedStates[id] = node.moved;
}
newConfig.push(localDiff.newConfig.all[id]);
} else if (resolutions[id] === 'remote') {
if (!remoteDiff.deleted[id] && remoteDiff.newConfig.all.hasOwnProperty(id)) {
if (node) {
nodeChangedStates[id] = node.changed;
nodeMovedStates[id] = node.moved;
}
localChangedStates[id] = 1;
newConfig.push(remoteDiff.newConfig.all[id]);
@@ -1381,8 +1456,9 @@ RED.diff = (function() {
}
return {
config: newConfig,
nodeChangedStates: nodeChangedStates,
localChangedStates: localChangedStates
nodeChangedStates,
nodeMovedStates,
localChangedStates
}
}
@@ -1393,6 +1469,7 @@ RED.diff = (function() {
var newConfig = appliedDiff.config;
var nodeChangedStates = appliedDiff.nodeChangedStates;
var nodeMovedStates = appliedDiff.nodeMovedStates;
var localChangedStates = appliedDiff.localChangedStates;
var isDirty = RED.nodes.dirty();
@@ -1401,33 +1478,56 @@ RED.diff = (function() {
t:"replace",
config: RED.nodes.createCompleteNodeSet(),
changed: nodeChangedStates,
moved: nodeMovedStates,
complete: true,
dirty: isDirty,
rev: RED.nodes.version()
}
RED.history.push(historyEvent);
var originalFlow = RED.nodes.originalFlow();
// originalFlow is what the editor things it loaded
// - add any newly added nodes from remote diff as they are now part of the record
for (var id in diff.remoteDiff.added) {
if (diff.remoteDiff.added.hasOwnProperty(id)) {
if (diff.remoteDiff.newConfig.all.hasOwnProperty(id)) {
originalFlow.push(JSON.parse(JSON.stringify(diff.remoteDiff.newConfig.all[id])));
}
}
}
// var originalFlow = RED.nodes.originalFlow();
// // originalFlow is what the editor thinks it loaded
// // - add any newly added nodes from remote diff as they are now part of the record
// for (var id in diff.remoteDiff.added) {
// if (diff.remoteDiff.added.hasOwnProperty(id)) {
// if (diff.remoteDiff.newConfig.all.hasOwnProperty(id)) {
// originalFlow.push(JSON.parse(JSON.stringify(diff.remoteDiff.newConfig.all[id])));
// }
// }
// }
RED.nodes.clear();
var imported = RED.nodes.import(newConfig);
// Restore the original flow so subsequent merge resolutions can properly
// identify new-vs-old
RED.nodes.originalFlow(originalFlow);
// // Restore the original flow so subsequent merge resolutions can properly
// // identify new-vs-old
// RED.nodes.originalFlow(originalFlow);
// Clear all change flags from the import
RED.nodes.dirty(false);
const flowsToLock = new Set()
function ensureUnlocked(id) {
const flow = id && (RED.nodes.workspace(id) || RED.nodes.subflow(id) || null);
const isLocked = flow ? flow.locked : false;
if (flow && isLocked) {
flow.locked = false;
flowsToLock.add(flow)
}
}
imported.nodes.forEach(function(n) {
if (nodeChangedStates[n.id] || localChangedStates[n.id]) {
if (nodeChangedStates[n.id]) {
ensureUnlocked(n.z)
n.changed = true;
}
if (nodeMovedStates[n.id]) {
ensureUnlocked(n.z)
n.moved = true;
}
})
flowsToLock.forEach(flow => {
flow.locked = true
})
RED.nodes.version(diff.remoteDiff.rev);

View File

@@ -157,6 +157,12 @@ RED.editor = (function() {
}
}
if (valid && "validate" in definition[property]) {
if (definition[property].hasOwnProperty("required") &&
definition[property].required === false) {
if (value === "") {
return true;
}
}
try {
var opt = {};
if (label) {
@@ -183,6 +189,11 @@ RED.editor = (function() {
});
}
} else if (valid) {
if (definition[property].hasOwnProperty("required") && definition[property].required === false) {
if (value === "") {
return true;
}
}
// If the validator is not provided in node property => Check if the input has a validator
if ("category" in node._def) {
const isConfig = node._def.category === "config";
@@ -190,7 +201,10 @@ RED.editor = (function() {
const input = $("#"+prefix+"-"+property);
const isTypedInput = input.length > 0 && input.next(".red-ui-typedInput-container").length > 0;
if (isTypedInput) {
valid = input.typedInput("validate");
valid = input.typedInput("validate", { returnErrorMessage: true });
if (typeof valid === "string") {
return label ? label + ": " + valid : valid;
}
}
}
}
@@ -248,6 +262,8 @@ RED.editor = (function() {
var value = input.val();
if (defaults[property].hasOwnProperty("format") && defaults[property].format !== "" && input[0].nodeName === "DIV") {
value = input.text();
} else if (input.attr("type") === "checkbox") {
value = input.prop("checked");
}
var valid = validateNodeProperty(node, defaults, property,value);
if (((typeof valid) === "string") || !valid) {
@@ -341,8 +357,9 @@ RED.editor = (function() {
nodeValue = node[property]
}
const buttonId = `${prefix}-lookup-${property}`
const selectId = prefix + '-' + property
const addBtnId = `${prefix}-btn-${property}-add`;
const editBtnId = `${prefix}-btn-${property}-edit`;
const selectId = prefix + '-' + property;
const input = $(`#${selectId}`);
if (input.length === 0) {
return;
@@ -365,41 +382,61 @@ RED.editor = (function() {
select.css({
'flex-grow': 1
});
updateConfigNodeSelect(property, type, nodeValue, prefix, filter);
const disableButton = function(disabled) {
btn.prop( "disabled", !!disabled)
btn.toggleClass("disabled", !!disabled)
}
// create the edit button
const btn = $('<a id="' + buttonId + '" class="red-ui-button"><i class="fa fa-pencil"></i></a>')
const editButton = $('<a id="' + editBtnId + '" class="red-ui-button"><i class="fa fa-pencil"></i></a>')
.css({ "margin-left": "10px" })
.appendTo(outerWrap);
RED.popover.tooltip(editButton, RED._('editor.editConfig', { type }));
// create the add button
const addButton = $('<a id="' + addBtnId + '" class="red-ui-button"><i class="fa fa-plus"></i></a>')
.css({ "margin-left": "10px" })
.appendTo(outerWrap);
RED.popover.tooltip(addButton, RED._('editor.addNewConfig', { type }));
const disableButton = function(button, disabled) {
$(button).prop("disabled", !!disabled)
$(button).toggleClass("disabled", !!disabled)
};
// add the click handler
btn.on("click", function (e) {
addButton.on("click", function (e) {
if (addButton.prop("disabled")) { return }
showEditConfigNodeDialog(property, type, "_ADD_", prefix, node);
e.preventDefault();
});
editButton.on("click", function (e) {
const selectedOpt = select.find(":selected")
if (selectedOpt.data('env')) { return } // don't show the dialog for env vars items (MVP. Future enhancement: lookup the env, if present, show the associated edit dialog)
if (btn.prop("disabled")) { return }
if (editButton.prop("disabled")) { return }
showEditConfigNodeDialog(property, type, selectedOpt.val(), prefix, node);
e.preventDefault();
});
// dont permit the user to click the button if the selected option is an env var
select.on("change", function () {
const selectedOpt = select.find(":selected")
const selectedOpt = select.find(":selected");
const optionsLength = select.find("option").length;
if (selectedOpt?.data('env')) {
disableButton(true)
disableButton(addButton, true);
disableButton(editButton, true);
// disable the edit button if no options available or 'none' selected
} else if (optionsLength === 1 || selectedOpt.val() === "_ADD_") {
disableButton(addButton, false);
disableButton(editButton, true);
} else {
disableButton(false)
disableButton(addButton, false);
disableButton(editButton, false);
}
});
var label = "";
var configNode = RED.nodes.node(nodeValue);
if (configNode) {
label = RED.utils.getNodeLabel(configNode, configNode.id);
}
input.val(label);
// If the value is "", 'add new...' option if no config node available or 'none' option
// Otherwise, it's a config node
select.val(nodeValue || '_ADD_');
}
/**
@@ -772,9 +809,16 @@ RED.editor = (function() {
}
try {
var rc = editing_node._def.oneditsave.call(editing_node);
const rc = editing_node._def.oneditsave.call(editing_node);
if (rc === true) {
editState.changed = true;
} else if (typeof rc === 'object' && rc !== null ) {
if (rc.changed === true) {
editState.changed = true
}
if (Array.isArray(rc.history) && rc.history.length > 0) {
editState.history = rc.history
}
}
} catch(err) {
console.warn("oneditsave",editing_node.id,editing_node.type,err.toString());
@@ -892,7 +936,14 @@ RED.editor = (function() {
}
}
select.append('<option value="_ADD_"'+(value===""?" selected":"")+'>'+RED._("editor.addNewType", {type:label})+'</option>');
if (!configNodes.length) {
// Add 'add new...' option
select.append('<option value="_ADD_" selected>' + RED._("editor.addNewType", { type: label }) + '</option>');
} else {
// Add 'none' option
select.append('<option value="_ADD_">' + RED._("editor.inputs.none") + '</option>');
}
window.setTimeout(function() { select.trigger("change");},50);
}
}
@@ -971,6 +1022,17 @@ RED.editor = (function() {
dirty: startDirty
}
if (editing_node.g) {
const group = RED.nodes.group(editing_node.g);
// Don't use RED.group.removeFromGroup as that emits
// a change event on the node - but we're deleting it
const index = group?.nodes.indexOf(editing_node) ?? -1;
if (index > -1) {
group.nodes.splice(index, 1);
RED.group.markDirty(group);
}
}
RED.nodes.dirty(true);
RED.view.redraw(true);
RED.history.push(historyEvent);
@@ -1072,7 +1134,7 @@ RED.editor = (function() {
}
});
}
var historyEvent = {
let historyEvent = {
t:'edit',
node:editing_node,
changes:editState.changes,
@@ -1088,6 +1150,15 @@ RED.editor = (function() {
instances:subflowInstances
}
}
if (editState.history) {
historyEvent = {
t: 'multi',
events: [ historyEvent, ...editState.history ],
dirty: wasDirty
}
}
RED.history.push(historyEvent);
}
editing_node.dirty = true;
@@ -1687,8 +1758,8 @@ RED.editor = (function() {
}
if (!isSameObj(old_env, new_env)) {
editing_node.env = new_env;
editState.changes.env = editing_node.env;
editing_node.env = new_env;
editState.changed = true;
}

View File

@@ -165,7 +165,13 @@ RED.editor.codeEditor.monaco = (function() {
//Handles orphaned models
//ensure loaded models that are not explicitly destroyed by a call to .destroy() are disposed
RED.events.on("editor:close",function() {
let models = window.monaco ? monaco.editor.getModels() : null;
if (!window.monaco) { return; }
const editors = window.monaco.editor.getEditors()
const orphanEditors = editors.filter(editor => editor && !document.body.contains(editor.getDomNode()))
orphanEditors.forEach(editor => {
editor.dispose();
});
let models = monaco.editor.getModels()
if(models && models.length) {
console.warn("Cleaning up monaco models left behind. Any node that calls createEditor() should call .destroy().")
for (let index = 0; index < models.length; index++) {
@@ -514,7 +520,7 @@ RED.editor.codeEditor.monaco = (function() {
_monaco.languages.json.jsonDefaults.setDiagnosticsOptions(diagnosticOptions);
if(modeConfiguration) { _monaco.languages.json.jsonDefaults.setModeConfiguration(modeConfiguration); }
} catch (error) {
console.warn("monaco - Error setting up json options", err)
console.warn("monaco - Error setting up json options", error)
}
}
@@ -526,7 +532,7 @@ RED.editor.codeEditor.monaco = (function() {
if(htmlDefaults) { _monaco.languages.html.htmlDefaults.setOptions(htmlDefaults); }
if(handlebarDefaults) { _monaco.languages.html.handlebarDefaults.setOptions(handlebarDefaults); }
} catch (error) {
console.warn("monaco - Error setting up html options", err)
console.warn("monaco - Error setting up html options", error)
}
}
@@ -546,7 +552,7 @@ RED.editor.codeEditor.monaco = (function() {
if(lessDefaults_modeConfiguration) { _monaco.languages.css.cssDefaults.setDiagnosticsOptions(lessDefaults_modeConfiguration); }
if(scssDefaults_modeConfiguration) { _monaco.languages.css.cssDefaults.setDiagnosticsOptions(scssDefaults_modeConfiguration); }
} catch (error) {
console.warn("monaco - Error setting up CSS/SCSS/LESS options", err)
console.warn("monaco - Error setting up CSS/SCSS/LESS options", error)
}
}
@@ -585,7 +591,7 @@ RED.editor.codeEditor.monaco = (function() {
createMonacoCompletionItem("set (flow context)", 'flow.set("${1:name}", ${1:value});','Set a value in flow context',range),
createMonacoCompletionItem("get (global context)", 'global.get("${1:name}");','Get a value from global context',range),
createMonacoCompletionItem("set (global context)", 'global.set("${1:name}", ${1:value});','Set a value in global context',range),
createMonacoCompletionItem("get (env)", 'env.get("${1|NR_NODE_ID,NR_NODE_NAME,NR_NODE_PATH,NR_GROUP_ID,NR_GROUP_NAME,NR_FLOW_ID,NR_FLOW_NAME|}");','Get env variable value',range),
createMonacoCompletionItem("get (env)", 'env.get("${1|NR_NODE_ID,NR_NODE_NAME,NR_NODE_PATH,NR_GROUP_ID,NR_GROUP_NAME,NR_FLOW_ID,NR_FLOW_NAME,NR_SUBFLOW_NAME,NR_SUBFLOW_ID,NR_SUBFLOW_PATH|}");','Get env variable value',range),
createMonacoCompletionItem("cloneMessage (RED.util)", 'RED.util.cloneMessage(${1:msg});',
["```typescript",
"RED.util.cloneMessage<T extends registry.NodeMessage>(msg: T): T",
@@ -1124,6 +1130,7 @@ RED.editor.codeEditor.monaco = (function() {
$(el).remove();
$(toolbarRow).remove();
ed.dispose();
}
ed.resize = function resize() {

View File

@@ -11,9 +11,22 @@ RED.editor.mermaid = (function () {
if (!initializing) {
initializing = true
$.getScript(
'vendor/mermaid/mermaid.min.js',
function (data, stat, jqxhr) {
// Find the cache-buster:
let cacheBuster
$('script').each(function (i, el) {
if (!cacheBuster) {
const src = el.getAttribute('src')
const m = /\?v=(.+)$/.exec(src)
if (m) {
cacheBuster = m[1]
}
}
})
$.ajax({
url: `vendor/mermaid/mermaid.min.js?v=${cacheBuster}`,
dataType: "script",
cache: true,
success: function (data, stat, jqxhr) {
mermaid.initialize({
startOnLoad: false,
theme: RED.settings.get('mermaid', {}).theme
@@ -24,7 +37,7 @@ RED.editor.mermaid = (function () {
render(pending)
}
}
)
});
}
} else {
const nodes = document.querySelectorAll(selector)

View File

@@ -221,12 +221,12 @@ RED.notifications = (function() {
if (newType) {
n.className = "red-ui-notification red-ui-notification-"+newType;
}
newTimeout = newOptions.hasOwnProperty('timeout')?newOptions.timeout:timeout
if (!fixed || newOptions.fixed === false) {
newTimeout = (newOptions.hasOwnProperty('timeout')?newOptions.timeout:timeout)||5000;
newTimeout = newTimeout || 5000
}
if (newOptions.buttons) {
var buttonSet = $('<div style="margin-top: 20px;" class="ui-dialog-buttonset"></div>').appendTo(nn)
var buttonSet = $('<div class="ui-dialog-buttonset"></div>').appendTo(nn)
newOptions.buttons.forEach(function(buttonDef) {
var b = $('<button>').text(buttonDef.text).on("click", buttonDef.click).appendTo(buttonSet);
if (buttonDef.id) {
@@ -272,6 +272,15 @@ RED.notifications = (function() {
};
})());
n.timeoutid = window.setTimeout(n.close,timeout||5000);
} else if (timeout) {
$(n).on("click.red-ui-notification-close", (function() {
var nn = n;
return function() {
nn.hideNotification();
window.clearTimeout(nn.timeoutid);
};
})());
n.timeoutid = window.setTimeout(n.hideNotification,timeout||5000);
}
currentNotifications.push(n);
if (options.id) {

View File

@@ -115,8 +115,65 @@ RED.palette.editor = (function() {
});
})
}
function installNodeModule(id,version,url,callback) {
var requestBody = {
const moduleQueue = [];
const processQueue = function () {
if (moduleQueue.length === 0) {
return;
}
const { type, body, callback } = moduleQueue[0];
if (type === "install") {
RED.eventLog.startEvent(RED._("palette.editor.confirm.button.install") + ` : ${body.module} ${body.version}`);
$.ajax({
url: "nodes",
type: "POST",
data: JSON.stringify(body),
contentType: "application/json; charset=utf-8"
}).done(function(_data, _textStatus, _xhr) {
callback();
}).fail(function(xhr, textStatus, err) {
callback(xhr, textStatus, err);
}).always(function () {
// Remove the task from the list
moduleQueue.shift();
// Process the next task
processQueue();
});
} else if (type === "remove") {
RED.eventLog.startEvent(RED._("palette.editor.confirm.button.remove") + ` : ${body.id}`);
$.ajax({
url: "nodes/" + body.id,
type: "DELETE"
}).done(function(_data, _textStatus, _xhr) {
callback();
}).fail(function(xhr, _textStatus, _err) {
callback(xhr);
}).always(function () {
// Remove the task from the list
moduleQueue.shift();
// Process the next task
processQueue();
});
}
};
/**
* Adds a module to the processing queue to install or remove it
* @param {string} type the type of request to apply to the module
* @param {Object} body an object with module info
* @param {(xhr?: JQuery.jqXHR, textStatus?: JQuery.Ajax.ErrorTextStatus, err?: string) => void} callback a callback function called when the request is done
*/
function addModuleToQueue(type, body, callback) {
moduleQueue.push({ type, body, callback });
if (moduleQueue.length === 1) {
processQueue();
}
}
function installNodeModule(id, version, url, callback) {
const requestBody = {
module: id
};
if (version) {
@@ -125,26 +182,10 @@ RED.palette.editor = (function() {
if (url) {
requestBody.url = url;
}
$.ajax({
url:"nodes",
type: "POST",
data: JSON.stringify(requestBody),
contentType: "application/json; charset=utf-8"
}).done(function(data,textStatus,xhr) {
callback();
}).fail(function(xhr,textStatus,err) {
callback(xhr);
});
addModuleToQueue("install", requestBody, callback);
}
function removeNodeModule(id,callback) {
$.ajax({
url:"nodes/"+id,
type: "DELETE"
}).done(function(data,textStatus,xhr) {
callback();
}).fail(function(xhr,textStatus,err) {
callback(xhr);
})
function removeNodeModule(id, callback) {
addModuleToQueue("remove", { id: id }, callback);
}
function refreshNodeModuleList() {
@@ -248,86 +289,106 @@ RED.palette.editor = (function() {
var moduleInfo = nodeEntries[module].info;
var nodeEntry = nodeEntries[module].elements;
if (nodeEntry) {
var activeTypeCount = 0;
var typeCount = 0;
var errorCount = 0;
nodeEntry.errorList.empty();
nodeEntries[module].totalUseCount = 0;
nodeEntries[module].setUseCount = {};
if (moduleInfo.plugin) {
nodeEntry.enableButton.hide();
nodeEntry.removeButton.show();
for (var setName in moduleInfo.sets) {
if (moduleInfo.sets.hasOwnProperty(setName)) {
var inUseCount = 0;
var set = moduleInfo.sets[setName];
var setElements = nodeEntry.sets[setName];
if (set.err) {
errorCount++;
var errMessage = set.err;
if (set.err.message) {
errMessage = set.err.message;
} else if (set.err.code) {
errMessage = set.err.code;
let pluginCount = 0;
for (let setName in moduleInfo.sets) {
if (moduleInfo.sets.hasOwnProperty(setName)) {
let set = moduleInfo.sets[setName];
if (set.plugins) {
pluginCount += set.plugins.length;
}
$("<li>").text(errMessage).appendTo(nodeEntry.errorList);
}
if (set.enabled) {
activeTypeCount += set.types.length;
}
typeCount += set.types.length;
for (var i=0;i<moduleInfo.sets[setName].types.length;i++) {
var t = moduleInfo.sets[setName].types[i];
inUseCount += (typesInUse[t]||0);
var swatch = setElements.swatches[t];
}
nodeEntry.setCount.text(RED._('palette.editor.pluginCount',{count:pluginCount,label:pluginCount}));
} else {
var activeTypeCount = 0;
var typeCount = 0;
var errorCount = 0;
nodeEntry.errorList.empty();
nodeEntries[module].totalUseCount = 0;
nodeEntries[module].setUseCount = {};
for (var setName in moduleInfo.sets) {
if (moduleInfo.sets.hasOwnProperty(setName)) {
var inUseCount = 0;
const set = moduleInfo.sets[setName];
const setElements = nodeEntry.sets[setName]
if (set.err) {
errorCount++;
var errMessage = set.err;
if (set.err.message) {
errMessage = set.err.message;
} else if (set.err.code) {
errMessage = set.err.code;
}
$("<li>").text(errMessage).appendTo(nodeEntry.errorList);
}
if (set.enabled) {
var def = RED.nodes.getType(t);
if (def && def.color) {
swatch.css({background:RED.utils.getNodeColor(t,def)});
swatch.css({border: "1px solid "+getContrastingBorder(swatch.css('backgroundColor'))})
activeTypeCount += set.types.length;
}
typeCount += set.types.length;
for (var i=0;i<moduleInfo.sets[setName].types.length;i++) {
var t = moduleInfo.sets[setName].types[i];
inUseCount += (typesInUse[t]||0);
if (setElements && set.enabled) {
var def = RED.nodes.getType(t);
if (def && def.color) {
setElements.swatches[t].css({background:RED.utils.getNodeColor(t,def)});
setElements.swatches[t].css({border: "1px solid "+getContrastingBorder(setElements.swatches[t].css('backgroundColor'))})
}
}
}
}
nodeEntries[module].setUseCount[setName] = inUseCount;
nodeEntries[module].totalUseCount += inUseCount;
nodeEntries[module].setUseCount[setName] = inUseCount;
nodeEntries[module].totalUseCount += inUseCount;
if (inUseCount > 0) {
setElements.enableButton.text(RED._('palette.editor.inuse'));
setElements.enableButton.addClass('disabled');
} else {
setElements.enableButton.removeClass('disabled');
if (set.enabled) {
setElements.enableButton.text(RED._('palette.editor.disable'));
} else {
setElements.enableButton.text(RED._('palette.editor.enable'));
if (setElements) {
if (inUseCount > 0) {
setElements.enableButton.text(RED._('palette.editor.inuse'));
setElements.enableButton.addClass('disabled');
} else {
setElements.enableButton.removeClass('disabled');
if (set.enabled) {
setElements.enableButton.text(RED._('palette.editor.disable'));
} else {
setElements.enableButton.text(RED._('palette.editor.enable'));
}
}
setElements.setRow.toggleClass("red-ui-palette-module-set-disabled",!set.enabled);
}
}
setElements.setRow.toggleClass("red-ui-palette-module-set-disabled",!set.enabled);
}
}
if (errorCount === 0) {
nodeEntry.errorRow.hide()
} else {
nodeEntry.errorRow.show();
}
var nodeCount = (activeTypeCount === typeCount)?typeCount:activeTypeCount+" / "+typeCount;
nodeEntry.setCount.text(RED._('palette.editor.nodeCount',{count:typeCount,label:nodeCount}));
if (nodeEntries[module].totalUseCount > 0) {
nodeEntry.enableButton.text(RED._('palette.editor.inuse'));
nodeEntry.enableButton.addClass('disabled');
nodeEntry.removeButton.hide();
} else {
nodeEntry.enableButton.removeClass('disabled');
if (moduleInfo.local) {
nodeEntry.removeButton.css('display', 'inline-block');
}
if (activeTypeCount === 0) {
nodeEntry.enableButton.text(RED._('palette.editor.enableall'));
if (errorCount === 0) {
nodeEntry.errorRow.hide()
} else {
nodeEntry.enableButton.text(RED._('palette.editor.disableall'));
nodeEntry.errorRow.show();
}
var nodeCount = (activeTypeCount === typeCount)?typeCount:activeTypeCount+" / "+typeCount;
nodeEntry.setCount.text(RED._('palette.editor.nodeCount',{count:typeCount,label:nodeCount}));
if (nodeEntries[module].totalUseCount > 0) {
nodeEntry.enableButton.text(RED._('palette.editor.inuse'));
nodeEntry.enableButton.addClass('disabled');
nodeEntry.removeButton.hide();
} else {
nodeEntry.enableButton.removeClass('disabled');
if (moduleInfo.local) {
nodeEntry.removeButton.css('display', 'inline-block');
}
if (activeTypeCount === 0) {
nodeEntry.enableButton.text(RED._('palette.editor.enableall'));
} else {
nodeEntry.enableButton.text(RED._('palette.editor.disableall'));
}
nodeEntry.container.toggleClass("disabled",(activeTypeCount === 0));
}
nodeEntry.container.toggleClass("disabled",(activeTypeCount === 0));
}
}
if (moduleInfo.pending_version) {
@@ -365,54 +426,62 @@ RED.palette.editor = (function() {
var catalogueCount;
var catalogueLoadStatus = [];
var catalogueLoadStart;
var catalogueLoadErrors = false;
var activeSort = sortModulesRelevance;
function handleCatalogResponse(err,catalog,index,v) {
const url = catalog.url
catalogueLoadStatus.push(err||v);
if (!err) {
if (v.modules) {
v.modules = v.modules.filter(function(m) {
if (RED.utils.checkModuleAllowed(m.id,m.version,installAllowList,installDenyList)) {
loadedIndex[m.id] = m;
m.index = [m.id];
if (m.keywords) {
m.index = m.index.concat(m.keywords);
}
if (m.types) {
m.index = m.index.concat(m.types);
}
if (m.updated_at) {
m.timestamp = new Date(m.updated_at).getTime();
} else {
m.timestamp = 0;
}
m.index = m.index.join(",").toLowerCase();
m.catalog = catalog;
m.catalogIndex = index;
return true;
function refreshCatalogues (done) {
catalogueLoadStatus = [];
catalogueCount = catalogues.length;
loadedList = []
loadedIndex = {}
loadedCatalogs.length = 0
let handled = 0
for (let index = 0; index < catalogues.length; index++) {
const url = catalogues[index];
$.getJSON(url, {_: new Date().getTime()},function(v) {
loadedCatalogs.push({ index: index, url: url, name: v.name, updated_at: v.updated_at, modules_count: (v.modules || []).length })
handleCatalogResponse({ url: url, name: v.name},index,v);
}).fail(function(jqxhr, textStatus, error) {
console.warn("Error loading catalog",url,":",error);
}).always(function() {
handled++;
if (handled === catalogueCount) {
//sort loadedCatalogs by e.index ascending
loadedCatalogs.sort((a, b) => a.index - b.index)
refreshUpdateStatus();
if (done) {
done()
}
return false;
})
loadedList = loadedList.concat(v.modules);
}
} else {
catalogueLoadErrors = true;
}
})
}
if (catalogueCount > 1) {
$(".red-ui-palette-module-shade-status").html(RED._('palette.editor.loading')+"<br>"+catalogueLoadStatus.length+"/"+catalogueCount);
}
if (catalogueLoadStatus.length === catalogueCount) {
if (catalogueLoadErrors) {
RED.notify(RED._('palette.editor.errors.catalogLoadFailed',{url: url}),"error",false,8000);
}
var delta = 250-(Date.now() - catalogueLoadStart);
setTimeout(function() {
$("#red-ui-palette-module-install-shade").hide();
},Math.max(delta,0));
}
function handleCatalogResponse(catalog,index,v) {
if (v.modules) {
v.modules = v.modules.filter(function(m) {
if (RED.utils.checkModuleAllowed(m.id,m.version,installAllowList,installDenyList)) {
loadedIndex[m.id] = m;
m.index = [m.id];
if (m.keywords) {
m.index = m.index.concat(m.keywords);
}
if (m.types) {
m.index = m.index.concat(m.types);
}
if (m.updated_at) {
m.timestamp = new Date(m.updated_at).getTime();
} else {
m.timestamp = 0;
}
m.index = m.index.join(",").toLowerCase();
m.catalog = catalog;
m.catalogIndex = index;
return true;
}
return false;
})
loadedList = loadedList.concat(v.modules);
}
}
@@ -424,35 +493,19 @@ RED.palette.editor = (function() {
packageList.editableList('empty');
$(".red-ui-palette-module-shade-status").text(RED._('palette.editor.loading'));
catalogueLoadStatus = [];
catalogueLoadErrors = false;
catalogueCount = catalogues.length;
if (catalogues.length > 1) {
$(".red-ui-palette-module-shade-status").html(RED._('palette.editor.loading')+"<br>0/"+catalogues.length);
}
$("#red-ui-palette-module-install-shade").show();
catalogueLoadStart = Date.now();
var handled = 0;
loadedCatalogs.length = 0; // clear the loadedCatalogs array
for (let index = 0; index < catalogues.length; index++) {
const url = catalogues[index];
$.getJSON(url, {_: new Date().getTime()},function(v) {
loadedCatalogs.push({ index: index, url: url, name: v.name, updated_at: v.updated_at, modules_count: (v.modules || []).length })
handleCatalogResponse(null,{ url: url, name: v.name},index,v);
refreshNodeModuleList();
}).fail(function(jqxhr, textStatus, error) {
console.warn("Error loading catalog",url,":",error);
handleCatalogResponse(jqxhr,url,index);
}).always(function() {
handled++;
if (handled === catalogueCount) {
//sort loadedCatalogs by e.index ascending
loadedCatalogs.sort((a, b) => a.index - b.index)
updateCatalogFilter(loadedCatalogs)
}
})
}
catalogueLoadStart = Date.now()
refreshCatalogues(function () {
refreshNodeModuleList();
updateCatalogFilter(loadedCatalogs)
const delta = 250-(Date.now() - catalogueLoadStart);
setTimeout(function() {
$("#red-ui-palette-module-install-shade").hide();
},Math.max(delta,0));
})
} else {
refreshNodeModuleList();
updateCatalogFilter(loadedCatalogs)
}
}
@@ -466,7 +519,6 @@ RED.palette.editor = (function() {
if (catalogSelection.length === 0) {
// sidebar not yet loaded (red-catalogue-filter-select is not in dom)
if (maxRetry > 0) {
// console.log("updateCatalogFilter: sidebar not yet loaded, retrying in 100ms")
// try again in 100ms
setTimeout(() => {
updateCatalogFilter(catalogEntries, maxRetry - 1)
@@ -605,12 +657,18 @@ RED.palette.editor = (function() {
}
})
// Add the update status to the status bar
addUpdateInfoToStatusBar();
refreshCatalogues()
RED.actions.add("core:manage-palette",function() {
RED.userSettings.show('palette');
});
RED.events.on('registry:module-updated', function(ns) {
refreshNodeModule(ns.module);
refreshUpdateStatus();
});
RED.events.on('registry:node-set-enabled', function(ns) {
refreshNodeModule(ns.module);
@@ -622,12 +680,14 @@ RED.palette.editor = (function() {
if (!/^subflow:/.test(nodeType)) {
var ns = RED.nodes.registry.getNodeSetForType(nodeType);
refreshNodeModule(ns.module);
refreshUpdateStatus();
}
});
RED.events.on('registry:node-type-removed', function(nodeType) {
if (!/^subflow:/.test(nodeType)) {
var ns = RED.nodes.registry.getNodeSetForType(nodeType);
refreshNodeModule(ns.module);
refreshUpdateStatus();
}
});
RED.events.on('registry:node-set-added', function(ns) {
@@ -678,6 +738,34 @@ RED.palette.editor = (function() {
}
}
})
RED.events.on("registry:plugin-module-added", function(module) {
if (!nodeEntries.hasOwnProperty(module)) {
nodeEntries[module] = {info:RED.plugins.getModule(module)};
var index = [module];
for (var s in nodeEntries[module].info.sets) {
if (nodeEntries[module].info.sets.hasOwnProperty(s)) {
index.push(s);
index = index.concat(nodeEntries[module].info.sets[s].types)
}
}
nodeEntries[module].index = index.join(",").toLowerCase();
nodeList.editableList('addItem', nodeEntries[module]);
} else {
_refreshNodeModule(module);
}
refreshUpdateStatus();
for (var i=0;i<filteredList.length;i++) {
if (filteredList[i].info.id === module) {
var installButton = filteredList[i].elements.installButton;
installButton.addClass('disabled');
installButton.text(RED._('palette.editor.installed'));
break;
}
}
});
}
var settingsPane;
@@ -804,6 +892,7 @@ RED.palette.editor = (function() {
errorRow: errorRow,
errorList: errorList,
setCount: setCount,
setButton: setButton,
container: container,
shade: shade,
versionSpan: versionSpan,
@@ -814,49 +903,88 @@ RED.palette.editor = (function() {
if (container.hasClass('expanded')) {
container.removeClass('expanded');
contentRow.slideUp();
setTimeout(() => {
contentRow.empty()
}, 200)
object.elements.sets = {}
} else {
container.addClass('expanded');
populateSetList()
contentRow.slideDown();
}
})
var setList = Object.keys(entry.sets)
setList.sort(function(A,B) {
return A.toLowerCase().localeCompare(B.toLowerCase());
});
setList.forEach(function(setName) {
var set = entry.sets[setName];
var setRow = $('<div>',{class:"red-ui-palette-module-set"}).appendTo(contentRow);
var buttonGroup = $('<div>',{class:"red-ui-palette-module-set-button-group"}).appendTo(setRow);
var typeSwatches = {};
set.types.forEach(function(t) {
var typeDiv = $('<div>',{class:"red-ui-palette-module-type"}).appendTo(setRow);
typeSwatches[t] = $('<span>',{class:"red-ui-palette-module-type-swatch"}).appendTo(typeDiv);
$('<span>',{class:"red-ui-palette-module-type-node"}).text(t).appendTo(typeDiv);
})
var enableButton = $('<a href="#" class="red-ui-button red-ui-button-small"></a>').appendTo(buttonGroup);
enableButton.on("click", function(evt) {
evt.preventDefault();
if (object.setUseCount[setName] === 0) {
var currentSet = RED.nodes.registry.getNodeSet(set.id);
shade.show();
var newState = !currentSet.enabled
changeNodeState(set.id,newState,shade,function(xhr){
if (xhr) {
if (xhr.responseJSON) {
RED.notify(RED._('palette.editor.errors.'+(newState?'enable':'disable')+'Failed',{module: id,message:xhr.responseJSON.message}));
const populateSetList = function () {
var setList = Object.keys(entry.sets)
setList.sort(function(A,B) {
return A.toLowerCase().localeCompare(B.toLowerCase());
});
setList.forEach(function(setName) {
var set = entry.sets[setName];
var setRow = $('<div>',{class:"red-ui-palette-module-set"}).appendTo(contentRow);
var buttonGroup = $('<div>',{class:"red-ui-palette-module-set-button-group"}).appendTo(setRow);
var typeSwatches = {};
let enableButton;
if (set.types) {
set.types.forEach(function(t) {
var typeDiv = $('<div>',{class:"red-ui-palette-module-type"}).appendTo(setRow);
typeSwatches[t] = $('<span>',{class:"red-ui-palette-module-type-swatch"}).appendTo(typeDiv);
if (set.enabled) {
var def = RED.nodes.getType(t);
if (def && def.color) {
typeSwatches[t].css({background:RED.utils.getNodeColor(t,def)});
typeSwatches[t].css({border: "1px solid "+getContrastingBorder(typeSwatches[t].css('backgroundColor'))})
}
}
});
}
})
$('<span>',{class:"red-ui-palette-module-type-node"}).text(t).appendTo(typeDiv);
})
enableButton = $('<a href="#" class="red-ui-button red-ui-button-small"></a>').appendTo(buttonGroup);
enableButton.on("click", function(evt) {
evt.preventDefault();
if (object.setUseCount[setName] === 0) {
var currentSet = RED.nodes.registry.getNodeSet(set.id);
shade.show();
var newState = !currentSet.enabled
changeNodeState(set.id,newState,shade,function(xhr){
if (xhr) {
if (xhr.responseJSON) {
RED.notify(RED._('palette.editor.errors.'+(newState?'enable':'disable')+'Failed',{module: id,message:xhr.responseJSON.message}));
}
}
});
}
})
object.elements.sets[set.name] = {
setRow: setRow,
enableButton: enableButton,
swatches: typeSwatches
};
});
if (object.setUseCount[setName] > 0) {
enableButton.text(RED._('palette.editor.inuse'));
enableButton.addClass('disabled');
} else {
enableButton.removeClass('disabled');
if (set.enabled) {
enableButton.text(RED._('palette.editor.disable'));
} else {
enableButton.text(RED._('palette.editor.enable'));
}
}
setRow.toggleClass("red-ui-palette-module-set-disabled",!set.enabled);
}
if (set.plugins) {
set.plugins.forEach(function(p) {
var typeDiv = $('<div>',{class:"red-ui-palette-module-type"}).appendTo(setRow);
// typeSwatches[p.id] = $('<span>',{class:"red-ui-palette-module-type-swatch"}).appendTo(typeDiv);
$('<span><i class="fa fa-puzzle-piece" aria-hidden="true"></i> </span>',{class:"red-ui-palette-module-type-swatch"}).appendTo(typeDiv);
$('<span>',{class:"red-ui-palette-module-type-node"}).text(p.id).appendTo(typeDiv);
})
}
object.elements.sets[set.name] = {
setRow: setRow,
enableButton: enableButton,
swatches: typeSwatches
};
});
}
enableButton.on("click", function(evt) {
evt.preventDefault();
if (object.totalUseCount === 0) {
@@ -1144,7 +1272,6 @@ RED.palette.editor = (function() {
evt.preventDefault();
RED.actions.invoke("core:show-event-log");
});
RED.eventLog.startEvent(RED._("palette.editor.confirm.button.install")+" : "+entry.name+" "+version);
installNodeModule(entry.name,version,url,function(xhr) {
spinner.remove();
if (xhr) {
@@ -1203,7 +1330,6 @@ RED.palette.editor = (function() {
evt.preventDefault();
RED.actions.invoke("core:show-event-log");
});
RED.eventLog.startEvent(RED._("palette.editor.confirm.button.remove")+" : "+entry.name);
removeNodeModule(entry.name, function(xhr) {
spinner.remove();
if (xhr) {
@@ -1226,7 +1352,56 @@ RED.palette.editor = (function() {
}
}
]
}); }
});
}
} else {
// dedicated list management for plugins
if (entry.plugin) {
let e = nodeEntries[entry.name];
if (e) {
nodeList.editableList('removeItem', e);
delete nodeEntries[entry.name];
refreshUpdateStatus();
}
// We assume that a plugin that implements onremove
// cleans the editor accordingly of its left-overs.
let found_onremove = true;
let keys = Object.keys(entry.sets);
keys.forEach((key) => {
let set = entry.sets[key];
for (let i=0; i<set.plugins?.length; i++) {
let plgn = RED.plugins.getPlugin(set.plugins[i].id);
if (plgn && plgn.onremove && typeof plgn.onremove === 'function') {
plgn.onremove();
} else {
if (plgn && plgn.onadd && typeof plgn.onadd === 'function') {
// if there's no 'onadd', there shouldn't be any left-overs
found_onremove = false;
}
}
}
});
if (!found_onremove) {
let removeNotify = RED.notify(RED._("palette.editor.confirm.removePlugin.body",{module:entry.name}),{
modal: true,
fixed: true,
type: 'warning',
buttons: [
{
text: RED._("palette.editor.confirm.button.understood"),
class:"primary",
click: function(e) {
removeNotify.close();
}
}
]
});
}
}
}
})
notification.close();
@@ -1269,10 +1444,28 @@ RED.palette.editor = (function() {
evt.preventDefault();
RED.actions.invoke("core:show-event-log");
});
RED.eventLog.startEvent(RED._("palette.editor.confirm.button.install")+" : "+entry.id+" "+entry.version);
installNodeModule(entry.id,entry.version,entry.pkg_url,function(xhr) {
installNodeModule(entry.id,entry.version,entry.pkg_url,function(xhr, textStatus,err) {
spinner.remove();
if (xhr) {
if (err && xhr.status === 504) {
var notification = RED.notify(RED._("palette.editor.errors.installTimeout"), {
modal: true,
fixed: true,
buttons: [
{
text: RED._("common.label.close"),
click: function() {
notification.close();
}
},{
text: RED._("eventLog.view"),
click: function() {
notification.close();
RED.actions.invoke("core:show-event-log");
}
}
]
})
} else if (xhr) {
if (xhr.responseJSON) {
var notification = RED.notify(RED._('palette.editor.errors.installFailed',{module: entry.id,message:xhr.responseJSON.message}),{
type: 'error',
@@ -1308,6 +1501,66 @@ RED.palette.editor = (function() {
})
}
const updateStatusWidget = $('<button type="button" class="red-ui-footer-button red-ui-update-status"></button>');
let updateAvailable = [];
function addUpdateInfoToStatusBar() {
updateStatusWidget.on("click", function (evt) {
RED.actions.invoke("core:manage-palette", {
view: "nodes",
filter: '"' + updateAvailable.join('", "') + '"'
});
});
RED.popover.tooltip(updateStatusWidget, function () {
const count = updateAvailable.length || 0;
return RED._("palette.editor.updateCount", { count: count });
});
RED.statusBar.add({
id: "update",
align: "right",
element: updateStatusWidget
});
updateStatus({ count: 0 });
}
let pendingRefreshTimeout
function refreshUpdateStatus() {
clearTimeout(pendingRefreshTimeout)
pendingRefreshTimeout = setTimeout(() => {
updateAvailable = [];
for (const module of Object.keys(nodeEntries)) {
if (loadedIndex.hasOwnProperty(module)) {
const moduleInfo = nodeEntries[module].info;
if (moduleInfo.pending_version) {
// Module updated
continue;
}
if (updateAllowed &&
semVerCompare(loadedIndex[module].version, moduleInfo.version) > 0 &&
RED.utils.checkModuleAllowed(module, null, updateAllowList, updateDenyList)
) {
updateAvailable.push(module);
}
}
}
updateStatus({ count: updateAvailable.length });
}, 200)
}
function updateStatus(opts) {
if (opts.count) {
RED.statusBar.show("update");
updateStatusWidget.empty();
$('<span><i class="fa fa-cube"></i> ' + opts.count + '</span>').appendTo(updateStatusWidget);
} else {
RED.statusBar.hide("update");
}
}
return {
init: init,
install: install

View File

@@ -35,6 +35,10 @@ RED.palette = (function() {
var categoryContainers = {};
var sidebarControls;
let paletteState = { filter: "", collapsed: [] };
let filterRefreshTimeout
function createCategory(originalCategory,rootCategory,category,ns) {
if ($("#red-ui-palette-base-category-"+rootCategory).length === 0) {
createCategoryContainer(originalCategory,rootCategory, ns+":palette.label."+rootCategory);
@@ -60,20 +64,57 @@ RED.palette = (function() {
catDiv.data('label',label);
categoryContainers[category] = {
container: catDiv,
close: function() {
hide: function (instant) {
if (instant) {
catDiv.hide()
} else {
catDiv.slideUp()
}
},
show: function () {
catDiv.show()
},
isOpen: function () {
return !!catDiv.hasClass("red-ui-palette-open")
},
getNodeCount: function (visibleOnly) {
const nodes = catDiv.find(".red-ui-palette-node")
if (visibleOnly) {
return nodes.filter(function() { return $(this).css('display') !== 'none'}).length
} else {
return nodes.length
}
},
close: function(instant, skipSaveState) {
catDiv.removeClass("red-ui-palette-open");
catDiv.addClass("red-ui-palette-closed");
$("#red-ui-palette-base-category-"+category).slideUp();
if (instant) {
$("#red-ui-palette-base-category-"+category).hide();
} else {
$("#red-ui-palette-base-category-"+category).slideUp();
}
$("#red-ui-palette-header-"+category+" i").removeClass("expanded");
if (!skipSaveState) {
if (!paletteState.collapsed.includes(category)) {
paletteState.collapsed.push(category);
savePaletteState();
}
}
},
open: function() {
open: function(skipSaveState) {
catDiv.addClass("red-ui-palette-open");
catDiv.removeClass("red-ui-palette-closed");
$("#red-ui-palette-base-category-"+category).slideDown();
$("#red-ui-palette-header-"+category+" i").addClass("expanded");
if (!skipSaveState) {
if (paletteState.collapsed.includes(category)) {
paletteState.collapsed.splice(paletteState.collapsed.indexOf(category), 1);
savePaletteState();
}
}
},
toggle: function() {
if (catDiv.hasClass("red-ui-palette-open")) {
if (categoryContainers[category].isOpen()) {
categoryContainers[category].close();
} else {
categoryContainers[category].open();
@@ -415,8 +456,16 @@ RED.palette = (function() {
var categoryNode = $("#red-ui-palette-container-"+rootCategory);
if (categoryNode.find(".red-ui-palette-node").length === 1) {
categoryContainers[rootCategory].open();
if (!paletteState?.collapsed?.includes(rootCategory)) {
categoryContainers[rootCategory].open();
} else {
categoryContainers[rootCategory].close(true);
}
}
clearTimeout(filterRefreshTimeout)
filterRefreshTimeout = setTimeout(() => {
refreshFilter()
}, 200)
}
}
@@ -516,7 +565,8 @@ RED.palette = (function() {
paletteNode.css("backgroundColor", sf.color);
}
function filterChange(val) {
function refreshFilter() {
const val = $("#red-ui-palette-search input").val()
var re = new RegExp(val.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'),'i');
$("#red-ui-palette-container .red-ui-palette-node").each(function(i,el) {
var currentLabel = $(el).attr("data-palette-label");
@@ -528,16 +578,26 @@ RED.palette = (function() {
}
});
for (var category in categoryContainers) {
for (let category in categoryContainers) {
if (categoryContainers.hasOwnProperty(category)) {
if (categoryContainers[category].container
.find(".red-ui-palette-node")
.filter(function() { return $(this).css('display') !== 'none'}).length === 0) {
categoryContainers[category].close();
categoryContainers[category].container.slideUp();
const categorySection = categoryContainers[category]
if (categorySection.getNodeCount(true) === 0) {
categorySection.hide()
} else {
categoryContainers[category].open();
categoryContainers[category].container.show();
categorySection.show()
if (val) {
// There is a filter being applied and it has matched
// something in this category - show the contents
categorySection.open(true)
} else {
// No filter. Only show the category if it isn't in lastState
if (!paletteState.collapsed.includes(category)) {
categorySection.open(true)
} else if (categorySection.isOpen()) {
// This section should be collapsed but isn't - so make it so
categorySection.close(true, true)
}
}
}
}
}
@@ -553,6 +613,9 @@ RED.palette = (function() {
$("#red-ui-palette > .red-ui-palette-spinner").show();
RED.events.on('logout', function () {
RED.settings.removeLocal('palette-state')
})
RED.events.on('registry:node-type-added', function(nodeType) {
var def = RED.nodes.getType(nodeType);
@@ -596,14 +659,14 @@ RED.palette = (function() {
RED.events.on("subflows:change",refreshSubflow);
$("#red-ui-palette-search input").searchBox({
delay: 100,
change: function() {
filterChange($(this).val());
refreshFilter();
paletteState.filter = $(this).val();
savePaletteState();
}
})
});
sidebarControls = $('<div class="red-ui-sidebar-control-left"><i class="fa fa-chevron-left"></i></div>').appendTo($("#red-ui-palette"));
RED.popover.tooltip(sidebarControls,RED._("keyboard.togglePalette"),"core:toggle-palette");
@@ -669,7 +732,23 @@ RED.palette = (function() {
togglePalette(state);
}
});
try {
paletteState = JSON.parse(RED.settings.getLocal("palette-state") || '{"filter":"", "collapsed": []}');
if (paletteState.filter) {
// Apply the category filter
$("#red-ui-palette-search input").searchBox("value", paletteState.filter);
}
} catch (error) {
console.error("Unexpected error loading palette state from localStorage: ", error);
}
setTimeout(() => {
// Lazily tidy up any categories that haven't been reloaded
paletteState.collapsed = paletteState.collapsed.filter(category => !!categoryContainers[category])
savePaletteState()
}, 10000)
}
function togglePalette(state) {
if (!state) {
$("#red-ui-main-container").addClass("red-ui-palette-closed");
@@ -689,6 +768,15 @@ RED.palette = (function() {
})
return categories;
}
function savePaletteState() {
try {
RED.settings.setLocal("palette-state", JSON.stringify(paletteState));
} catch (error) {
console.error("Unexpected error saving palette state to localStorage: ", error);
}
}
return {
init: init,
add:addNodeType,

View File

@@ -287,7 +287,7 @@ RED.projects.settings = (function() {
var notInstalledCount = 0;
for (var m in modulesInUse) {
if (modulesInUse.hasOwnProperty(m)) {
if (modulesInUse.hasOwnProperty(m) && !activeProject.dependencies.hasOwnProperty(m)) {
depsList.editableList('addItem',{
id: modulesInUse[m].module,
version: modulesInUse[m].version,
@@ -307,8 +307,8 @@ RED.projects.settings = (function() {
if (activeProject.dependencies) {
for (var m in activeProject.dependencies) {
if (activeProject.dependencies.hasOwnProperty(m) && !modulesInUse.hasOwnProperty(m)) {
var installed = !!RED.nodes.registry.getModule(m);
if (activeProject.dependencies.hasOwnProperty(m)) {
var installed = !!RED.nodes.registry.getModule(m) && activeProject.dependencies[m] === modulesInUse[m].version;
depsList.editableList('addItem',{
id: m,
version: activeProject.dependencies[m], //RED.nodes.registry.getModule(module).version,

View File

@@ -33,6 +33,7 @@ RED.statusBar = (function() {
var el = $('<span class="red-ui-statusbar-widget"></span>');
el.prop('id', options.id);
options.element.appendTo(el);
options.elementDiv = el;
if (options.align === 'left') {
leftBucket.append(el);
} else if (options.align === 'right') {
@@ -40,12 +41,30 @@ RED.statusBar = (function() {
}
}
function hideWidget(id) {
const widget = widgets[id];
if (widget && widget.elementDiv) {
widget.elementDiv.hide();
}
}
function showWidget(id) {
const widget = widgets[id];
if (widget && widget.elementDiv) {
widget.elementDiv.show();
}
}
return {
init: function() {
leftBucket = $('<span class="red-ui-statusbar-bucket red-ui-statusbar-bucket-left">').appendTo("#red-ui-workspace-footer");
rightBucket = $('<span class="red-ui-statusbar-bucket red-ui-statusbar-bucket-right">').appendTo("#red-ui-workspace-footer");
},
add: addWidget
add: addWidget,
hide: hideWidget,
show: showWidget
}
})();

View File

@@ -1100,7 +1100,7 @@ RED.subflow = (function() {
input.val(val.value);
break;
case "cred":
input = $('<input type="password">').css('width','70%').appendTo(row);
input = $('<input type="password">').css('width','70%').attr('id', elId).appendTo(row);
if (node.credentials) {
if (node.credentials[tenv.name]) {
input.val(node.credentials[tenv.name]);
@@ -1280,14 +1280,20 @@ RED.subflow = (function() {
var nodePropValue = nodeProp;
if (prop.ui && prop.ui.type === "cred") {
nodePropType = "cred";
} else if (prop.ui && prop.ui.type === "conf-types") {
nodePropType = prop.value.type
} else {
switch(typeof nodeProp) {
case "string": nodePropType = "str"; break;
case "number": nodePropType = "num"; break;
case "boolean": nodePropType = "bool"; nodePropValue = nodeProp?"true":"false"; break;
default:
nodePropType = nodeProp.type;
nodePropValue = nodeProp.value;
if (nodeProp) {
nodePropType = nodeProp.type;
nodePropValue = nodeProp.value;
} else {
nodePropType = 'str'
}
}
}
var item = {
@@ -1340,7 +1346,7 @@ RED.subflow = (function() {
}
break;
case "cred":
item.value = input.val();
item.value = input.typedInput('value');
item.type = 'cred';
break;
case "spinner":
@@ -1357,7 +1363,7 @@ RED.subflow = (function() {
break;
case "conf-types":
item.value = input.val()
item.type = data.parent.value;
item.type = "conf-type"
}
if (ui.type === "cred" || item.type !== data.parent.type || item.value !== data.parent.value) {
env.push(item);

View File

@@ -382,9 +382,11 @@ RED.sidebar.config = (function() {
refreshConfigNodeList();
}
});
RED.popover.tooltip($('#red-ui-sidebar-config-filter-all'), RED._("sidebar.config.showAllConfigNodes"));
RED.popover.tooltip($('#red-ui-sidebar-config-filter-unused'), RED._("sidebar.config.showAllUnusedConfigNodes"));
RED.popover.tooltip($('#red-ui-sidebar-config-collapse-all'), RED._("palette.actions.collapse-all"));
RED.popover.tooltip($('#red-ui-sidebar-config-expand-all'), RED._("palette.actions.expand-all"));
}
function flashConfigNode(el) {

View File

@@ -36,7 +36,13 @@ RED.sidebar.help = (function() {
toolbar = $("<div>", {class:"red-ui-sidebar-header red-ui-info-toolbar"}).appendTo(content);
$('<span class="button-group"><a id="red-ui-sidebar-help-show-toc" class="red-ui-button red-ui-button-small selected" href="#"><i class="fa fa-list-ul"></i></a></span>').appendTo(toolbar)
var showTOCButton = toolbar.find('#red-ui-sidebar-help-show-toc')
RED.popover.tooltip(showTOCButton,RED._("sidebar.help.showTopics"));
RED.popover.tooltip(showTOCButton, function () {
if ($(showTOCButton).hasClass('selected')) {
return RED._("sidebar.help.hideTopics");
} else {
return RED._("sidebar.help.showTopics");
}
});
showTOCButton.on("click",function(e) {
e.preventDefault();
if ($(this).hasClass('selected')) {
@@ -158,8 +164,10 @@ RED.sidebar.help = (function() {
function refreshSubflow(sf) {
var item = treeList.treeList('get',"node-type:subflow:"+sf.id);
item.subflowLabel = sf._def.label().toLowerCase();
item.treeList.replaceElement(getNodeLabel({_def:sf._def,type:sf._def.label()}));
if (item) {
item.subflowLabel = sf._def.label().toLowerCase();
item.treeList.replaceElement(getNodeLabel({_def:sf._def,type:sf._def.label()}));
}
}
function hideTOC() {

View File

@@ -103,7 +103,7 @@ RED.sidebar.info.outliner = (function() {
evt.stopPropagation();
RED.search.show("type:subflow:"+n.id);
})
// RED.popover.tooltip(userCountBadge,function() { return RED._('editor.nodesUse',{count:n.users.length})});
RED.popover.tooltip(subflowInstanceBadge,function() { return RED._('subflow.subflowInstances',{count:n.instances.length})});
}
if (n._def.category === "config" && n.type !== "group") {
var userCountBadge = $('<button type="button" class="red-ui-info-outline-item-control-users red-ui-button red-ui-button-small"><i class="fa fa-toggle-right"></i></button>').text(n.users.length).appendTo(controls).on("click",function(evt) {

View File

@@ -901,11 +901,25 @@ RED.utils = (function() {
return parts;
}
function validatePropertyExpression(str) {
/**
* Validate a property expression
* @param {*} str - the property value
* @returns {boolean|string} whether the node proprty is valid. `true`: valid `false|String`: invalid
*/
function validatePropertyExpression(str, opt) {
try {
var parts = normalisePropertyExpression(str);
const parts = normalisePropertyExpression(str);
return true;
} catch(err) {
// If the validator has opt, it is a 3.x validator that
// can return a String to mean 'invalid' and provide a reason
if (opt) {
if (opt.label) {
return opt.label + ': ' + err.message;
}
return err.message;
}
// Otherwise, a 2.x returns a false value
return false;
}
}
@@ -923,22 +937,24 @@ RED.utils = (function() {
// Allow ${ENV_VAR} value
return true
}
let error
let error;
if (propertyType === 'json') {
try {
JSON.parse(propertyValue);
} catch(err) {
error = RED._("validator.errors.invalid-json", {
error: err.message
})
});
}
} else if (propertyType === 'msg' || propertyType === 'flow' || propertyType === 'global' ) {
if (!RED.utils.validatePropertyExpression(propertyValue)) {
error = RED._("validator.errors.invalid-prop")
// To avoid double label
const valid = RED.utils.validatePropertyExpression(propertyValue, opt ? {} : null);
if (valid !== true) {
error = opt ? valid : RED._("validator.errors.invalid-prop");
}
} else if (propertyType === 'num') {
if (!/^NaN$|^[+-]?[0-9]*\.?[0-9]*([eE][-+]?[0-9]+)?$|^[+-]?(0b|0B)[01]+$|^[+-]?(0o|0O)[0-7]+$|^[+-]?(0x|0X)[0-9a-fA-F]+$/.test(propertyValue)) {
error = RED._("validator.errors.invalid-num")
error = RED._("validator.errors.invalid-num");
}
} else if (propertyType === 'jsonata') {
try {
@@ -946,16 +962,16 @@ RED.utils = (function() {
} catch(err) {
error = RED._("validator.errors.invalid-expr", {
error: err.message
})
});
}
}
if (error) {
if (opt && opt.label) {
return opt.label+': '+error
return opt.label + ': ' + error;
}
return error
return error;
}
return true
return true;
}
function getMessageProperty(msg,expr) {

View File

@@ -9,14 +9,27 @@ RED.view.annotations = (function() {
addAnnotation(evt.node.__pendingAnnotation__,evt);
delete evt.node.__pendingAnnotation__;
}
var badgeDX = 0;
var controlDX = 0;
for (var i=0,l=evt.el.__annotations__.length;i<l;i++) {
var annotation = evt.el.__annotations__[i];
let badgeRDX = 0;
let badgeLDX = 0;
for (let i=0,l=evt.el.__annotations__.length;i<l;i++) {
const annotation = evt.el.__annotations__[i];
if (annotations.hasOwnProperty(annotation.id)) {
var opts = annotations[annotation.id];
var showAnnotation = true;
var isBadge = opts.type === 'badge';
const opts = annotations[annotation.id];
let showAnnotation = true;
const isBadge = opts.type === 'badge';
if (opts.refresh !== undefined) {
let refreshAnnotation = false
if (typeof opts.refresh === "string") {
refreshAnnotation = !!evt.node[opts.refresh]
delete evt.node[opts.refresh]
} else if (typeof opts.refresh === "function") {
refreshAnnotation = opts.refresh(evnt.node)
}
if (refreshAnnotation) {
refreshAnnotationElement(annotation.id, annotation.node, annotation.element)
}
}
if (opts.show !== undefined) {
if (typeof opts.show === "string") {
showAnnotation = !!evt.node[opts.show]
@@ -29,17 +42,24 @@ RED.view.annotations = (function() {
}
if (isBadge) {
if (showAnnotation) {
var rect = annotation.element.getBoundingClientRect();
badgeDX += rect.width;
annotation.element.setAttribute("transform", "translate("+(evt.node.w-3-badgeDX)+", -8)");
badgeDX += 4;
}
} else {
if (showAnnotation) {
var rect = annotation.element.getBoundingClientRect();
annotation.element.setAttribute("transform", "translate("+(3+controlDX)+", -12)");
controlDX += rect.width + 4;
const rect = annotation.element.getBoundingClientRect();
let annotationX
if (!opts.align || opts.align === 'right') {
annotationX = evt.node.w - 3 - badgeRDX - rect.width
badgeRDX += rect.width + 4;
} else if (opts.align === 'left') {
annotationX = 3 + badgeLDX
badgeLDX += rect.width + 4;
}
annotation.element.setAttribute("transform", "translate("+annotationX+", -8)");
}
// } else {
// if (showAnnotation) {
// var rect = annotation.element.getBoundingClientRect();
// annotation.element.setAttribute("transform", "translate("+(3+controlDX)+", -12)");
// controlDX += rect.width + 4;
// }
}
} else {
annotation.element.parentNode.removeChild(annotation.element);
@@ -95,15 +115,25 @@ RED.view.annotations = (function() {
annotationGroup.setAttribute("class",opts.class || "");
evt.el.__annotations__.push({
id:id,
node: evt.node,
element: annotationGroup
});
var annotation = opts.element(evt.node);
refreshAnnotationElement(id, evt.node, annotationGroup)
evt.el.appendChild(annotationGroup);
}
function refreshAnnotationElement(id, node, annotationGroup) {
const opts = annotations[id];
const annotation = opts.element(node);
if (opts.tooltip) {
annotation.addEventListener("mouseenter", getAnnotationMouseEnter(annotation,evt.node,opts.tooltip));
annotation.addEventListener("mouseenter", getAnnotationMouseEnter(annotation, node, opts.tooltip));
annotation.addEventListener("mouseleave", annotationMouseLeave);
}
if (annotationGroup.hasChildNodes()) {
annotationGroup.removeChild(annotationGroup.firstChild)
}
annotationGroup.appendChild(annotation);
evt.el.appendChild(annotationGroup);
}

View File

@@ -646,120 +646,128 @@ RED.view = (function() {
}
d3.event = event;
var selected_tool = $(ui.draggable[0]).attr("data-palette-type");
var result = createNode(selected_tool);
if (!result) {
return;
}
var historyEvent = result.historyEvent;
var nn = RED.nodes.add(result.node);
var showLabel = RED.utils.getMessageProperty(RED.settings.get('editor'),"view.view-node-show-label");
if (showLabel !== undefined && (nn._def.hasOwnProperty("showLabel")?nn._def.showLabel:true) && !nn._def.defaults.hasOwnProperty("l")) {
nn.l = showLabel;
}
var helperOffset = d3.touches(ui.helper.get(0))[0]||d3.mouse(ui.helper.get(0));
var helperWidth = ui.helper.width();
var helperHeight = ui.helper.height();
var mousePos = d3.touches(this)[0]||d3.mouse(this);
try {
var isLink = (nn.type === "link in" || nn.type === "link out")
var hideLabel = nn.hasOwnProperty('l')?!nn.l : isLink;
var label = RED.utils.getNodeLabel(nn, nn.type);
var labelParts = getLabelParts(label, "red-ui-flow-node-label");
if (hideLabel) {
nn.w = node_height;
nn.h = Math.max(node_height,(nn.outputs || 0) * 15);
} else {
nn.w = Math.max(node_width,20*(Math.ceil((labelParts.width+50+(nn._def.inputs>0?7:0))/20)) );
nn.h = Math.max(6+24*labelParts.lines.length,(nn.outputs || 0) * 15, 30);
var result = createNode(selected_tool);
if (!result) {
return;
}
} catch(err) {
}
var historyEvent = result.historyEvent;
var nn = RED.nodes.add(result.node);
mousePos[1] += this.scrollTop + ((helperHeight/2)-helperOffset[1]);
mousePos[0] += this.scrollLeft + ((helperWidth/2)-helperOffset[0]);
mousePos[1] /= scaleFactor;
mousePos[0] /= scaleFactor;
var showLabel = RED.utils.getMessageProperty(RED.settings.get('editor'),"view.view-node-show-label");
if (showLabel !== undefined && (nn._def.hasOwnProperty("showLabel")?nn._def.showLabel:true) && !nn._def.defaults.hasOwnProperty("l")) {
nn.l = showLabel;
}
nn.x = mousePos[0];
nn.y = mousePos[1];
var helperOffset = d3.touches(ui.helper.get(0))[0]||d3.mouse(ui.helper.get(0));
var helperWidth = ui.helper.width();
var helperHeight = ui.helper.height();
var mousePos = d3.touches(this)[0]||d3.mouse(this);
var minX = nn.w/2 -5;
if (nn.x < minX) {
nn.x = minX;
}
var minY = nn.h/2 -5;
if (nn.y < minY) {
nn.y = minY;
}
var maxX = space_width -nn.w/2 +5;
if (nn.x > maxX) {
nn.x = maxX;
}
var maxY = space_height -nn.h +5;
if (nn.y > maxY) {
nn.y = maxY;
}
try {
var isLink = (nn.type === "link in" || nn.type === "link out")
var hideLabel = nn.hasOwnProperty('l')?!nn.l : isLink;
if (snapGrid) {
var gridOffset = RED.view.tools.calculateGridSnapOffsets(nn);
nn.x -= gridOffset.x;
nn.y -= gridOffset.y;
}
var label = RED.utils.getNodeLabel(nn, nn.type);
var labelParts = getLabelParts(label, "red-ui-flow-node-label");
if (hideLabel) {
nn.w = node_height;
nn.h = Math.max(node_height,(nn.outputs || 0) * 15);
} else {
nn.w = Math.max(node_width,20*(Math.ceil((labelParts.width+50+(nn._def.inputs>0?7:0))/20)) );
nn.h = Math.max(6+24*labelParts.lines.length,(nn.outputs || 0) * 15, 30);
}
} catch(err) {
}
var linkToSplice = $(ui.helper).data("splice");
if (linkToSplice) {
spliceLink(linkToSplice, nn, historyEvent)
}
mousePos[1] += this.scrollTop + ((helperHeight/2)-helperOffset[1]);
mousePos[0] += this.scrollLeft + ((helperWidth/2)-helperOffset[0]);
mousePos[1] /= scaleFactor;
mousePos[0] /= scaleFactor;
nn.x = mousePos[0];
nn.y = mousePos[1];
var minX = nn.w/2 -5;
if (nn.x < minX) {
nn.x = minX;
}
var minY = nn.h/2 -5;
if (nn.y < minY) {
nn.y = minY;
}
var maxX = space_width -nn.w/2 +5;
if (nn.x > maxX) {
nn.x = maxX;
}
var maxY = space_height -nn.h +5;
if (nn.y > maxY) {
nn.y = maxY;
}
if (snapGrid) {
var gridOffset = RED.view.tools.calculateGridSnapOffsets(nn);
nn.x -= gridOffset.x;
nn.y -= gridOffset.y;
}
var linkToSplice = $(ui.helper).data("splice");
if (linkToSplice) {
spliceLink(linkToSplice, nn, historyEvent)
}
var group = $(ui.helper).data("group");
if (group) {
var oldX = group.x;
var oldY = group.y;
RED.group.addToGroup(group, nn);
var moveEvent = null;
if ((group.x !== oldX) ||
(group.y !== oldY)) {
moveEvent = {
t: "move",
nodes: [{n: group,
ox: oldX, oy: oldY,
dx: group.x -oldX,
dy: group.y -oldY}],
dirty: true
};
}
historyEvent = {
t: 'multi',
events: [historyEvent],
var group = $(ui.helper).data("group");
if (group) {
var oldX = group.x;
var oldY = group.y;
RED.group.addToGroup(group, nn);
var moveEvent = null;
if ((group.x !== oldX) ||
(group.y !== oldY)) {
moveEvent = {
t: "move",
nodes: [{n: group,
ox: oldX, oy: oldY,
dx: group.x -oldX,
dy: group.y -oldY}],
dirty: true
};
if (moveEvent) {
historyEvent.events.push(moveEvent)
}
historyEvent.events.push({
t: "addToGroup",
group: group,
nodes: nn
})
}
historyEvent = {
t: 'multi',
events: [historyEvent],
};
if (moveEvent) {
historyEvent.events.push(moveEvent)
RED.history.push(historyEvent);
RED.editor.validateNode(nn);
RED.nodes.dirty(true);
// auto select dropped node - so info shows (if visible)
clearSelection();
nn.selected = true;
movingSet.add(nn);
updateActiveNodes();
updateSelection();
redraw();
if (nn._def.autoedit) {
RED.editor.edit(nn);
}
} catch (error) {
if (error.code != "NODE_RED") {
RED.notify(RED._("notification.error",{message:error.toString()}),"error");
} else {
RED.notify(RED._("notification.error",{message:error.message}),"error");
}
historyEvent.events.push({
t: "addToGroup",
group: group,
nodes: nn
})
}
RED.history.push(historyEvent);
RED.editor.validateNode(nn);
RED.nodes.dirty(true);
// auto select dropped node - so info shows (if visible)
clearSelection();
nn.selected = true;
movingSet.add(nn);
updateActiveNodes();
updateSelection();
redraw();
if (nn._def.autoedit) {
RED.editor.edit(nn);
}
}
});
@@ -857,6 +865,39 @@ RED.view = (function() {
RED.view.navigator.init();
RED.view.tools.init();
RED.view.annotations.register("red-ui-flow-node-docs",{
type: "badge",
class: "red-ui-flow-node-docs",
element: function(node) {
const docsBadge = document.createElementNS("http://www.w3.org/2000/svg","g")
const pageOutline = document.createElementNS("http://www.w3.org/2000/svg","rect");
pageOutline.setAttribute("x",0);
pageOutline.setAttribute("y",0);
pageOutline.setAttribute("rx",2);
pageOutline.setAttribute("width",7);
pageOutline.setAttribute("height",10);
docsBadge.appendChild(pageOutline)
const pageLines = document.createElementNS("http://www.w3.org/2000/svg","path");
pageLines.setAttribute("d", "M 7 3 h -3 v -3 M 2 8 h 3 M 2 6 h 3 M 2 4 h 2")
docsBadge.appendChild(pageLines)
$(docsBadge).on('click', function (evt) {
if (node.type === "subflow") {
RED.editor.editSubflow(activeSubflow, 'editor-tab-description');
} else if (node.type === "group") {
RED.editor.editGroup(node, 'editor-tab-description');
} else {
RED.editor.edit(node, 'editor-tab-description');
}
})
return docsBadge;
},
show: function(n) { return !!n.info }
})
RED.view.annotations.register("red-ui-flow-node-changed",{
type: "badge",
@@ -1182,6 +1223,7 @@ RED.view = (function() {
if (d3.event.button === 1) {
// Middle Click pan
d3.event.preventDefault();
mouse_mode = RED.state.PANNING;
mouse_position = [d3.event.pageX,d3.event.pageY]
scroll_position = [chart.scrollLeft(),chart.scrollTop()];
@@ -6063,14 +6105,19 @@ RED.view = (function() {
function createNode(type, x, y, z) {
const wasDirty = RED.nodes.dirty()
var m = /^subflow:(.+)$/.exec(type);
var activeSubflow = z ? RED.nodes.subflow(z) : null;
var activeSubflow = (z || RED.workspaces.active()) ? RED.nodes.subflow(z || RED.workspaces.active()) : null;
if (activeSubflow && m) {
var subflowId = m[1];
let err
if (subflowId === activeSubflow.id) {
throw new Error(RED._("notification.error", { message: RED._("notification.errors.cannotAddSubflowToItself") }))
err = new Error(RED._("notification.errors.cannotAddSubflowToItself"))
} else if (RED.nodes.subflowContains(m[1], activeSubflow.id)) {
err = new Error(RED._("notification.errors.cannotAddCircularReference"))
}
if (RED.nodes.subflowContains(m[1], activeSubflow.id)) {
throw new Error(RED._("notification.error", { message: RED._("notification.errors.cannotAddCircularReference") }))
if (err) {
err.code = 'NODE_RED'
throw err
}
}

View File

@@ -359,11 +359,17 @@ RED.workspaces = (function() {
RED.sidebar.config.refresh();
RED.view.focus();
},
onclick: function(tab) {
if (tab.id !== activeWorkspace) {
addToViewStack(activeWorkspace);
onclick: function(tab, evt) {
if(evt.which === 2) {
evt.preventDefault();
evt.stopPropagation();
RED.actions.invoke("core:hide-flow", tab)
} else {
if (tab.id !== activeWorkspace) {
addToViewStack(activeWorkspace);
}
RED.view.focus();
}
RED.view.focus();
},
ondblclick: function(tab) {
if (tab.type != "subflow") {
@@ -401,6 +407,7 @@ RED.workspaces = (function() {
if (tab.type === "tab") {
workspaceTabCount--;
} else {
RED.events.emit("workspace:close",{workspace: tab.id})
hideStack.push(tab.id);
}
RED.menu.setDisabled("menu-item-workspace-delete",activeWorkspace === 0 || workspaceTabCount <= 1);
@@ -491,6 +498,11 @@ RED.workspaces = (function() {
createWorkspaceTabs();
RED.events.on("sidebar:resize",workspace_tabs.resize);
RED.events.on("workspace:clear", () => {
// Reset the index used to generate new flow names
workspaceIndex = 0
})
RED.actions.add("core:show-next-tab",function() {
var oldActive = activeWorkspace;
workspace_tabs.nextTab();
@@ -657,6 +669,9 @@ RED.workspaces = (function() {
RED.events.on("flows:change", (ws) => {
$("#red-ui-tab-"+(ws.id.replace(".","-"))).toggleClass('red-ui-workspace-changed',!!(ws.contentsChanged || ws.changed || ws.added));
})
RED.events.on("subflows:change", (ws) => {
$("#red-ui-tab-"+(ws.id.replace(".","-"))).toggleClass('red-ui-workspace-changed',!!(ws.contentsChanged || ws.changed || ws.added));
})
hideWorkspace();
}

View File

@@ -212,6 +212,8 @@ RED.user = (function() {
function updateUserMenu() {
$("#red-ui-header-button-user-submenu li").remove();
const userMenu = $("#red-ui-header-button-user")
userMenu.empty()
if (RED.settings.user.anonymous) {
RED.menu.addItem("red-ui-header-button-user",{
id:"usermenu-item-login",
@@ -226,7 +228,6 @@ RED.user = (function() {
});
}
});
$('<i class="fa fa-user"></i>').appendTo("#red-ui-header-button-user");
} else {
RED.menu.addItem("red-ui-header-button-user",{
id:"usermenu-item-username",
@@ -239,17 +240,9 @@ RED.user = (function() {
RED.user.logout();
}
});
const userMenu = $("#red-ui-header-button-user")
userMenu.empty()
if (RED.settings.user.image) {
$('<span class="user-profile"></span>').css({
backgroundImage: "url("+RED.settings.user.image+")",
}).appendTo(userMenu);
} else {
$('<i class="fa fa-user"></i>').appendTo(userMenu);
}
}
const userIcon = generateUserIcon(RED.settings.user)
userIcon.appendTo(userMenu);
}
function init() {
@@ -320,12 +313,30 @@ RED.user = (function() {
return false;
}
function generateUserIcon(user) {
const userIcon = $('<span class="red-ui-user-profile"></span>')
if (user.image) {
userIcon.addClass('has_profile_image')
userIcon.css({
backgroundImage: "url("+user.image+")",
})
} else if (user.anonymous) {
$('<i class="fa fa-user"></i>').appendTo(userIcon);
} else {
$('<span>').text(user.username.substring(0,2)).appendTo(userIcon);
}
if (user.profileColor !== undefined) {
userIcon.addClass('red-ui-user-profile-color-' + user.profileColor)
}
return userIcon
}
return {
init: init,
login: login,
logout: logout,
hasPermission: hasPermission
hasPermission: hasPermission,
generateUserIcon
}
})();

View File

@@ -259,7 +259,7 @@ $deploy-button-background-disabled-hover: #555;
$header-background: #000;
$header-button-background-active: #121212;
$header-accent: #d41313;
$header-accent: #C02020;
$header-menu-color: #eee;
$header-menu-color-disabled: #666;
$header-menu-heading-color: #fff;
@@ -314,6 +314,16 @@ $spinner-color: #999;
$tab-icon-color: #dedede;
// Anonymous User Colors
$user-profile-colors: (
1: #822e81,
2: #955e42,
3: #9c914f,
4: #748e54,
5: #06bcc1
);
// Deprecated
$text-color-green: $text-color-success;
$info-text-code-color: $text-color-code;

View File

@@ -242,6 +242,18 @@ svg:not(.red-ui-workspace-lasso-active) {
stroke-linecap: round;
}
.red-ui-flow-node-docs {
stroke-width: 1px;
stroke-linejoin: round;
stroke-linecap: round;
stroke: var(--red-ui-node-border);
fill: none;
cursor: pointer;
rect {
fill: white;
}
}
g.red-ui-flow-node-selected {
.red-ui-workspace-select-mode & {
opacity: 1;

View File

@@ -186,6 +186,20 @@
}
}
.red-ui-deploy-button-group.readOnly {
.fa-caret-down { display: none; }
.fa-lock { display: inline-block; }
}
.red-ui-deploy-button-group:not(.readOnly) {
.fa-caret-down { display: inline-block; }
.fa-lock { display: none; }
}
.red-ui-deploy-button-group.readOnly {
a {
pointer-events: none;
}
}
li.open .button {
background: var(--red-ui-header-button-background-active);
border-color: var(--red-ui-header-button-background-active);
@@ -274,18 +288,44 @@
#usermenu-item-username > .red-ui-menu-label {
color: var(--red-ui-header-menu-heading-color);
}
}
.user-profile {
background-position: center center;
background-repeat: no-repeat;
background-size: contain;
display: inline-block;
width: 30px;
height: 30px;
vertical-align: middle;
.red-ui-user-profile {
background-color: var(--red-ui-header-background);
border: 2px solid var(--red-ui-header-menu-color);
border-radius: 30px;
overflow: hidden;
background-position: center center;
background-repeat: no-repeat;
background-size: contain;
display: inline-flex;
justify-content: center;
align-items: center;
vertical-align: middle;
width: 30px;
height: 30px;
font-size: 20px;
&.red-ui-user-profile-color-1 {
background-color: var(--red-ui-user-profile-colors-1);
}
&.red-ui-user-profile-color-2 {
background-color: var(--red-ui-user-profile-colors-2);
}
&.red-ui-user-profile-color-3 {
background-color: var(--red-ui-user-profile-colors-3);
}
&.red-ui-user-profile-color-4 {
background-color: var(--red-ui-user-profile-colors-4);
}
&.red-ui-user-profile-color-5 {
background-color: var(--red-ui-user-profile-colors-5);
}
}
@media only screen and (max-width: 450px) {
span.red-ui-header-logo > span {
display: none;

View File

@@ -5,23 +5,18 @@
li {
display: inline-flex;
align-items: center;
width: 30px;
margin: 0 2px;
}
}
.red-ui-multiplayer-user-icon {
background: var(--red-ui-header-background);
border: 2px solid var(--red-ui-header-menu-color);
border-radius: 30px;
background: none;
border: none;
display: inline-flex;
justify-content: center;
align-items: center;
width: 28px;
height: 28px;
text-align: center;
overflow: hidden;
box-sizing: border-box;
text-decoration: none;
color: var(--red-ui-header-menu-color);
@@ -36,13 +31,86 @@
.red-ui-multiplayer-user.inactive & {
opacity: 0.5;
}
.user-profile {
background-position: center center;
background-repeat: no-repeat;
background-size: contain;
display: inline-block;
vertical-align: middle;
width: 28px;
height: 28px;
.red-ui-user-profile {
width: 20px;
border-radius: 20px;
height: 20px;
font-size: 12px
}
}
.red-ui-multiplayer-users-tray {
position: absolute;
top: 5px;
right: 20px;
line-height: normal;
cursor: pointer;
// &:hover {
// .red-ui-multiplayer-user-location {
// margin-left: 1px;
// }
// }
}
$multiplayer-user-icon-background: var(--red-ui-primary-background);
$multiplayer-user-icon-border: var(--red-ui-view-background);
$multiplayer-user-icon-text-color: var(--red-ui-header-menu-color);
$multiplayer-user-icon-count-text-color: var(--red-ui-primary-color);
$multiplayer-user-icon-shadow: 0px 0px 4px var(--red-ui-shadow);
.red-ui-multiplayer-user-location {
display: inline-block;
margin-left: -6px;
transition: margin-left 0.2s;
.red-ui-user-profile {
border: 1px solid $multiplayer-user-icon-border;
color: $multiplayer-user-icon-text-color;
width: 18px;
height: 18px;
border-radius: 18px;
font-size: 10px;
font-weight: normal;
box-shadow: $multiplayer-user-icon-shadow;
&.red-ui-multiplayer-user-count {
color: $multiplayer-user-icon-count-text-color;
background-color: $multiplayer-user-icon-background;
}
}
}
.red-ui-multiplayer-annotation {
.red-ui-multiplayer-annotation-background {
filter: drop-shadow($multiplayer-user-icon-shadow);
fill: $multiplayer-user-icon-background;
&.red-ui-user-profile-color-1 {
fill: var(--red-ui-user-profile-colors-1);
}
&.red-ui-user-profile-color-2 {
fill: var(--red-ui-user-profile-colors-2);
}
&.red-ui-user-profile-color-3 {
fill: var(--red-ui-user-profile-colors-3);
}
&.red-ui-user-profile-color-4 {
fill: var(--red-ui-user-profile-colors-4);
}
&.red-ui-user-profile-color-5 {
fill: var(--red-ui-user-profile-colors-5);
}
}
.red-ui-multiplayer-annotation-border {
stroke: $multiplayer-user-icon-border;
stroke-width: 1px;
fill: none;
}
.red-ui-multiplayer-annotation-anon-label {
fill: $multiplayer-user-icon-text-color;
stroke: none;
}
text {
user-select: none;
fill: $multiplayer-user-icon-text-color;
stroke: none;
font-size: 10px;
&.red-ui-multiplayer-user-count {
fill: $multiplayer-user-icon-count-text-color;
}
}
}

View File

@@ -305,3 +305,8 @@ button.red-ui-palette-editor-upload-button {
margin-left: 10px;
}
}
button.red-ui-update-status {
width: auto;
padding: 0 3px;
}

View File

@@ -37,7 +37,6 @@ ul.red-ui-sidebar-node-config-list {
}
.red-ui-palette-node {
// overflow: hidden;
cursor: default;
&.selected {
border-color: transparent;
box-shadow: 0 0 0 2px var(--red-ui-node-selected-color);

View File

@@ -299,4 +299,7 @@
--red-ui-tab-icon-color: #{$tab-icon-color};
@each $current-color in 1 2 3 4 5 {
--red-ui-user-profile-colors-#{"" + $current-color}: #{map-get($user-profile-colors, $current-color)};
}
}

View File

@@ -50,7 +50,7 @@ export default {
"ja": "タブ上の変更通知",
"fr": "Notification de changement sur les onglets"
},
image: 'images/tab-changes.png',
image: '3.1/images/tab-changes.png',
description: {
"en-US": `<p>When a tab contains undeployed changes it now shows the
same style of change icon used by nodes.</p>
@@ -89,7 +89,7 @@ export default {
"ja": "ヘルプを見つける",
"fr": "Trouver de l'aide"
},
image: 'images/node-help.png',
image: '3.1/images/node-help.png',
description: {
"en-US": `<p>All node edit dialogs now include a link to that node's help
in the footer.</p>
@@ -107,7 +107,7 @@ export default {
"ja": "コンテキストメニューの改善",
"fr": "Menu contextuel amélioré"
},
image: 'images/context-menu.png',
image: '3.1/images/context-menu.png',
description: {
"en-US": `<p>The editor's context menu has been expanded to make lots more of
the built-in actions available.</p>
@@ -129,7 +129,7 @@ export default {
"ja": "フローを非表示",
"fr": "Masquage de flux"
},
image: 'images/hiding-flows.png',
image: '3.1/images/hiding-flows.png',
description: {
"en-US": `<p>Hiding flows is now done through the flow context menu.</p>
<p>The 'hide' button in previous releases has been removed from the tabs
@@ -147,7 +147,7 @@ export default {
"ja": "フローを固定",
"fr": "Verrouillage de flux"
},
image: 'images/locking-flows.png',
image: '3.1/images/locking-flows.png',
description: {
"en-US": `<p>Flows can now be locked to prevent accidental changes being made.</p>
<p>When locked you cannot modify the nodes in any way.</p>
@@ -187,7 +187,7 @@ export default {
"ja": "Mermaid図を追加",
"fr": "Ajout de diagrammes Mermaid"
},
image: 'images/mermaid.png',
image: '3.1/images/mermaid.png',
description: {
"en-US": `<p>You can also add <a href="https://github.com/mermaid-js/mermaid">Mermaid</a> diagrams directly into your node or flow descriptions.</p>
<p>This gives you much richer options for documenting your flows.</p>`,
@@ -203,11 +203,11 @@ export default {
"ja": "グローバル環境変数の管理",
"fr": "Gestion des variables d'environnement globales"
},
image: 'images/global-env-vars.png',
image: '3.1/images/global-env-vars.png',
description: {
"en-US": `<p>You can set environment variables that apply to all nodes and flows in the new
'Global Environment Variables' section of User Settings.</p>`,
"ja": `<p>ユーザ設定に新しく追加された「大域環境変数」のセクションで、全てのノードとフローに適用される環境変数を登録できます。</p>`,
"ja": `<p>ユーザ設定に新しく追加された「グローバル環境変数」のセクションで、全てのノードとフローに適用される環境変数を登録できます。</p>`,
"fr": `<p>Vous pouvez définir des variables d'environnement qui s'appliquent à tous les noeuds et flux dans la nouvelle
section "Global Environment Variables" des paramètres utilisateur.</p>`
},

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

View File

@@ -1,12 +1,12 @@
export default {
version: "4.0.0-beta.1",
version: "4.0.0",
steps: [
{
titleIcon: "fa fa-map-o",
title: {
"en-US": "Welcome to Node-RED 4.0 Beta 1!",
"ja": "Node-RED 4.0 Beta 0へようこそ!",
"fr": "Bienvenue dans Node-RED 4.0 Beta 1!"
"en-US": "Welcome to Node-RED 4.0!",
"ja": "Node-RED 4.0 へようこそ!",
"fr": "Bienvenue dans Node-RED 4.0!"
},
description: {
"en-US": "<p>Let's take a moment to discover the new features in this release.</p>",
@@ -14,10 +14,88 @@ export default {
"fr": "<p>Prenons un moment pour découvrir les nouvelles fonctionnalités de cette version.</p>"
}
},
{
title: {
"en-US": "Multiplayer Mode",
"ja": "複数ユーザ同時利用モード",
"fr": "Mode Multi-utilisateur"
},
image: 'images/nr4-multiplayer-location.png',
description: {
"en-US": `<p>This release includes the first small steps towards making Node-RED easier
to work with when you have multiple people editing flows at the same time.</p>
<p>When this feature is enabled, you will now see who else has the editor open and some
basic information on where they are in the editor.</p>
<p>Check the release post for details on how to enable this feature in your settings file.</p>`,
"ja": `<p>本リリースには、複数ユーザが同時にフローを編集する時に、Node-REDをより使いやすくするのための最初の微修正が入っています。</p>
<p>本機能を有効にすると、誰がエディタを開いているか、その人がエディタ上のどこにいるかの基本的な情報が表示されます。</p>
<p>設定ファイルで本機能を有効化する方法の詳細は、リリースの投稿を確認してください。</p>`,
"fr": `<p>Cette version inclut les premières étapes visant à rendre Node-RED plus facile à utiliser
lorsque plusieurs personnes modifient des flux en même temps.</p>
<p>Lorsque cette fonctionnalité est activée, vous pourrez désormais voir si dautres utilisateurs ont
ouvert l'éditeur. Vous pourrez également savoir où ces utilisateurs se trouvent dans l'éditeur.</p>
<p>Consultez la note de publication pour plus de détails sur la façon d'activer cette fonctionnalité
dans votre fichier de paramètres.</p>`
}
},
{
title: {
"en-US": "Better background deploy handling",
"ja": "バックグラウンドのデプロイ処理の改善",
"fr": "Meilleure gestion du déploiement en arrière-plan"
},
image: 'images/nr4-background-deploy.png',
description: {
"en-US": `<p>If another user deploys changes whilst you are editing, we now use a more discrete notification
that doesn't stop you continuing your work - especially if they are being very productive and deploying lots
of changes.</p>`,
"ja": `他のユーザが変更をデプロイした時に、特に変更が多い生産的な編集作業を妨げないように通知するようになりました。`,
"fr": `<p>Si un autre utilisateur déploie des modifications pendant que vous êtes en train de modifier, vous recevrez
une notification plus discrète qu'auparavant qui ne vous empêche pas de continuer votre travail.</p>`
}
},
{
title: {
"en-US": "Improved flow diffs",
"ja": "フローの差分表示の改善",
"fr": "Amélioration des différences de flux"
},
image: 'images/nr4-diff-update.png',
description: {
"en-US": `<p>When viewing changes made to a flow, Node-RED now distinguishes between nodes that have had configuration
changes and those that have only been moved.<p>
<p>When faced with a long list of changes to look at, this makes it much easier to focus on more significant items.</p>`,
"ja": `<p>フローの変更内容を表示する時に、Node-REDは設定が変更されたードと、移動されただけのードを区別するようになりました。<p>
<p>これによって、多くの変更内容を確認する際に、重要な項目に焦点を当てることができます。</p>`,
"fr": `<p>Lors de l'affichage des modifications apportées à un flux, Node-RED fait désormais la distinction entre les
noeuds qui ont changé de configuration et ceux qui ont seulement été déplacés.<p>
<p>Face à une longue liste de changements à examiner, il est beaucoup plus facile de se concentrer sur les éléments les
plus importants.</p>`
}
},
{
title: {
"en-US": "Better Configuration Node UX",
"ja": "設定ードのUXが向上",
"fr": "Meilleure expérience utilisateur du noeud de configuration"
},
image: 'images/nr4-config-select.png',
description: {
"en-US": `<p>The Configuration node selection UI has had a small update to have a dedicated 'add' button
next to the select box.</p>
<p>It's a small change, but should make it easier to work with your config nodes.</p>`,
"ja": `<p>設定ードを選択するUIが修正され、選択ボックスの隣に専用の「追加」ボタンが追加されました。</p>
<p>微修正ですが設定ノードの操作が容易になります。</p>`,
"fr": `<p>L'interface utilisateur de la sélection du noeud de configuration a fait l'objet d'une petite
mise à jour afin de disposer d'un bouton « Ajouter » à côté de la zone de sélection.</p>
<p>C'est un petit changement, mais cela devrait faciliter le travail avec vos noeuds de configuration.</p>`
}
},
{
title: {
"en-US": "Timestamp formatting options",
// "ja": ""
"ja": "タイムスタンプの形式の項目",
"fr": "Options de formatage de l'horodatage"
},
image: 'images/nr4-timestamp-formatting.png',
description: {
@@ -26,28 +104,47 @@ export default {
<ul>
<li>Milliseconds since epoch - this is existing behaviour of the timestamp option</li>
<li>ISO 8601 - a common format used by many systems</li>
<li>JavaScript Data Object</li>
<li>JavaScript Date Object</li>
</ul>`,
// "ja": ``
"ja": `<p>タイムスタンプを設定するノードに、タイムスタンプの形式を指定できる項目が追加されました。</p>
<p>次の3つの項目を追加したことで、簡単に選択できるようになりました:<p>
<ul>
<li>エポックからのミリ秒 - 従来動作と同じになるタイムスタンプの項目</li>
<li>ISO 8601 - 多くのシステムで使用されている共通の形式</li>
<li>JavaScript日付オブジェクト</li>
</ul>`,
"fr": `<p>Les noeuds qui vous permettent de définir un horodatage disposent désormais d'options sur le format dans lequel cet horodatage peut être défini.</p>
<p>Nous gardons les choses simples en proposant trois options :<p>
<ul>
<li>Millisecondes depuis l'époque : il s'agit du comportement existant de l'option d'horodatage</li>
<li>ISO 8601 : un format commun utilisé par de nombreux systèmes</li>
<li>Objet Date JavaScript</li>
</ul>`
}
},
{
title: {
"en-US": "Auto-complete of flow/global and env types",
// "ja": ""
"ja": "フロー/グローバル、環境変数の型の自動補完",
"fr": "Saisie automatique des types de flux/global et env"
},
image: 'images/nr4-auto-complete.png',
description: {
"en-US": `<p>The <code>flow</code>/<code>global</code> context inputs and the <code>env</code> input
now all include auto-complete suggestions based on the live state of your flows.</p>
`,
// "ja": ``
"ja": `<p><code>flow</code>/<code>global</code>コンテキストや<code>env</code>の入力を、現在のフローの状態をもとに自動補完で提案するようになりました。</p>
`,
"fr": `<p>Les entrées contextuelles <code>flow</code>/<code>global</code> et l'entrée <code>env</code>
incluent désormais des suggestions de saisie semi-automatique basées sur l'état actuel de vos flux.</p>
`,
}
},
{
title: {
"en-US": "Config node customisation in Subflows",
// "ja": ""
"ja": "サブフローでの設定ノードのカスタマイズ",
"fr": "Personnalisation du noeud de configuration dans les sous-flux"
},
image: 'images/nr4-sf-config.png',
description: {
@@ -56,7 +153,45 @@ export default {
<p>For example, each instance of a subflow that connects to an MQTT Broker and does some post-processing
of the messages received can be pointed at a different broker.</p>
`,
// "ja": ``
"ja": `<p>サブフローをカスタマイズして、選択した型の異なる設定ノードを各インスタンスが使用できるようになりました。</p>
<p>例えば、MQTTブローカへ接続し、メッセージ受信と後処理を行うサブフローの各インスタンスに異なるブローカを指定することも可能です。</p>
`,
"fr": `<p>Les sous-flux peuvent désormais être personnalisés pour permettre à chaque instance d'utiliser un
noeud de configuration d'un type sélectionné.</p>
<p>Par exemple, chaque instance d'un sous-flux qui se connecte à un courtier MQTT et effectue un post-traitement
des messages reçus peut être pointée vers un autre courtier.</p>
`
}
},
{
title: {
"en-US": "Remembering palette state",
"ja": "パレットの状態を維持",
"fr": "Mémorisation de l'état de la palette"
},
description: {
"en-US": `<p>The palette now remembers what categories you have hidden between reloads - as well as any
filter you have applied.</p>`,
"ja": `<p>パレット上で非表示にしたカテゴリや適用したフィルタが、リロードしても記憶されるようになりました。</p>`,
"fr": `<p>La palette se souvient désormais des catégories que vous avez masquées entre les rechargements,
ainsi que le filtre que vous avez appliqué.</p>`
}
},
{
title: {
"en-US": "Plugins shown in the Palette Manager",
"ja": "パレット管理にプラグインを表示",
"fr": "Affichage des Plugins dans le gestionnaire de palettes"
},
image: 'images/nr4-plugins.png',
description: {
"en-US": `<p>The palette manager now shows any plugin modules you have installed, such as
<code>node-red-debugger</code>. Previously they would only be shown if the plugins include
nodes for the palette.</p>`,
"ja": `<p>パレットの管理に <code>node-red-debugger</code> の様なインストールしたプラグインが表示されます。以前はプラグインにパレット向けのノードが含まれている時のみ表示されていました。</p>`,
"fr": `<p>Le gestionnaire de palettes affiche désormais tous les plugins que vous avez installés,
tels que <code>node-red-debugger</code>. Auparavant, ils n'étaient affichés que s'ils contenaient
des noeuds pour la palette.</p>`
}
},
{
@@ -74,6 +209,21 @@ export default {
<li>Customisable headers on the WebSocket node</li>
<li>Split node now can operate on any message property</li>
<li>and lots more...</li>
</ul>`,
"ja": `<p>コアノードには沢山の軽微な修正、ドキュメント更新、小さな機能拡張が入っています。全リストはヘルプサイドバーにある変更履歴を参照してください。</p>
<ul>
<li>RFC4180に完全に準拠したCSVモード</li>
<li>WebSocketードのカスタマイズ可能なヘッダ</li>
<li>Splitードは、メッセージプロパティで操作できるようになりました</li>
<li>他にも沢山あります...</li>
</ul>`,
"fr": `<p>Les noeuds principaux ont reçu de nombreux correctifs mineurs ainsi que des améliorations. La documentation a été mise à jour.
Consultez le journal des modifications dans la barre latérale d'aide pour une liste complète. Ci-dessous, les changements les plus importants :</p>
<ul>
<li>Un mode CSV entièrement conforme à la norme RFC4180</li>
<li>En-têtes personnalisables pour le noeud WebSocket</li>
<li>Le noeud Split peut désormais fonctionner sur n'importe quelle propriété de message</li>
<li>Et bien plus encore...</li>
</ul>`
}
}

View File

@@ -1,10 +1,10 @@
/* 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 {
topic?: string;
payload?: any;
_msgid?: string;
/** `_msgid` is generated internally. It not something you typically need to set or modify. */ _msgid?: string;
[other: string]: any; //permit other properties
}
@@ -19,15 +19,15 @@ declare const promisify:typeof import('util').promisify
/**
* @typedef NodeStatus
* @type {object}
* @property {string} [fill] The fill property can be: red, green, yellow, blue or grey.
* @property {string} [shape] The shape property can be: ring or dot.
* @property {string} [text] The text to display
* @property {'red'|'green'|'yellow'|'blue'|'grey'|string} [fill] - The fill property can be: red, green, yellow, blue or grey.
* @property {'ring'|'dot'|string} [shape] The shape property can be: ring or dot.
* @property {string|boolean|number} [text] The text to display
*/
interface NodeStatus {
/** The fill property can be: red, green, yellow, blue or grey */
fill?: string,
fill?: 'red'|'green'|'yellow'|'blue'|'grey'|string,
/** The shape property can be: ring or dot */
shape?: string,
shape?: 'ring'|'dot'|string,
/** The text to display */
text?: string|boolean|number
}
@@ -37,25 +37,24 @@ declare class node {
* Send 1 or more messages asynchronously
* @param {object | object[]} msg The msg object
* @param {Boolean} [clone=true] Flag to indicate the `msg` should be cloned. Default = `true`
* @see node-red documentation [writing-functions: sending messages asynchronously](https://nodered.org/docs/user-guide/writing-functions#sending-messages-asynchronously)
* @see Node-RED documentation [writing-functions: sending messages asynchronously](https://nodered.org/docs/user-guide/writing-functions#sending-messages-asynchronously)
*/
static send(msg:object|object[], clone?:Boolean): void;
static send(msg:NodeMessage|NodeMessage[], clone?:Boolean): void;
/** Inform runtime this instance has completed its operation */
static done();
/** Send an error to the console and debug side bar. Include `msg` in the 2nd parameter to trigger the catch node. */
static error(err:string|Error, msg?:object);
static error(err:string|Error, msg?:NodeMessage);
/** Log a warn message to the console and debug sidebar */
static warn(warning:string|object);
/** Log an info message to the console (not sent to sidebar)' */
static log(info:string|object);
/** Sets the status icon and text underneath the node.
* @param {NodeStatus} status - The status object `{fill, shape, text}`
* @see node-red documentation [writing-functions: adding-status](https://nodered.org/docs/user-guide/writing-functions#adding-status)
* @see Node-RED documentation [writing-functions: adding-status](https://nodered.org/docs/user-guide/writing-functions#adding-status)
*/
static status(status:NodeStatus);
/** Sets the status text underneath the node.
* @param {string} status - The status to display
* @see node-red documentation [writing-functions: adding-status](https://nodered.org/docs/user-guide/writing-functions#adding-status)
* @see Node-RED documentation [writing-functions: adding-status](https://nodered.org/docs/user-guide/writing-functions#adding-status)
*/
static status(status:string|boolean|number);
/** the id of this node */
@@ -264,9 +263,12 @@ declare class global {
/** Get an array of the keys in the context store */
static keys(store: string, callback: Function);
}
// (string & {}) is a workaround for offering string type completion without enforcing it. See https://github.com/microsoft/TypeScript/issues/29729#issuecomment-567871939
type NR_ENV_NAME_STRING = 'NR_NODE_ID'|'NR_NODE_NAME'|'NR_NODE_PATH'|'NR_GROUP_ID'|'NR_GROUP_NAME'|'NR_FLOW_ID'|'NR_FLOW_NAME'|'NR_SUBFLOW_ID'|'NR_SUBFLOW_NAME'|'NR_SUBFLOW_PATH' | (string & {})
declare class env {
/**
* Get an environment variable value
* Get an environment variable value defined in the OS, or in the global/flow/subflow/group environment variables.
*
* Predefined node-red variables...
* * `NR_NODE_ID` - the ID of the node
@@ -276,9 +278,16 @@ declare class env {
* * `NR_GROUP_NAME` - the Name of the containing group
* * `NR_FLOW_ID` - the ID of the flow the node is on
* * `NR_FLOW_NAME` - the Name of the flow the node is on
* @param name Name of the environment variable to get
* * `NR_SUBFLOW_ID` - the ID of the subflow the node is in
* * `NR_SUBFLOW_NAME` - the Name of the subflow the node is in
* * `NR_SUBFLOW_PATH` - the Path of the subflow the node is in
* @param name - The name of the environment variable
* @example
* ```const flowName = env.get("NR_FLOW_NAME");```
* ```const flowName = env.get("NR_FLOW_NAME") // get the name of the flow```
* @example
* ```const systemHomeDir = env.get("HOME") // get the user's home directory```
* @example
* ```const systemHomeDir = env.get("LABEL1") // get the value of a global/flow/subflow/group defined variable named "LABEL1"```
*/
static get(name:string) :any;
static get(name:NR_ENV_NAME_STRING) :any;
}

View File

@@ -1,10 +1,10 @@
/* 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 */
/**
* The `assert` module provides a set of assertion functions for verifying
* invariants.
* @see [source](https://github.com/nodejs/node/blob/v16.9.0/lib/assert.js)
* @see [source](https://github.com/nodejs/node/blob/v18.0.0/lib/assert.js)
*/
declare module 'assert' {
/**
@@ -290,8 +290,8 @@ declare module 'assert' {
* > Stability: 3 - Legacy: Use {@link strictEqual} instead.
*
* Tests shallow, coercive equality between the `actual` and `expected` parameters
* using the [Abstract Equality Comparison](https://tc39.github.io/ecma262/#sec-abstract-equality-comparison) ( `==` ). `NaN` is special handled
* and treated as being identical in case both sides are `NaN`.
* using the [`==` operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Equality). `NaN` is specially handled
* and treated as being identical if both sides are `NaN`.
*
* ```js
* import assert from 'assert';
@@ -323,9 +323,8 @@ declare module 'assert' {
*
* > Stability: 3 - Legacy: Use {@link notStrictEqual} instead.
*
* Tests shallow, coercive inequality with the [Abstract Equality Comparison](https://tc39.github.io/ecma262/#sec-abstract-equality-comparison)(`!=` ). `NaN` is special handled and treated as
* being identical in case both
* sides are `NaN`.
* Tests shallow, coercive inequality with the [`!=` operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Inequality). `NaN` is
* specially handled and treated as being identical if both sides are `NaN`.
*
* ```js
* import assert from 'assert';
@@ -415,7 +414,7 @@ declare module 'assert' {
function notDeepEqual(actual: unknown, expected: unknown, message?: string | Error): void;
/**
* Tests strict equality between the `actual` and `expected` parameters as
* determined by the [SameValue Comparison](https://tc39.github.io/ecma262/#sec-samevalue).
* determined by [`Object.is()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is).
*
* ```js
* import assert from 'assert/strict';
@@ -453,7 +452,7 @@ declare module 'assert' {
function strictEqual<T>(actual: unknown, expected: T, message?: string | Error): asserts actual is T;
/**
* Tests strict inequality between the `actual` and `expected` parameters as
* determined by the [SameValue Comparison](https://tc39.github.io/ecma262/#sec-samevalue).
* determined by [`Object.is()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is).
*
* ```js
* import assert from 'assert/strict';

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 */
declare module 'assert/strict' {
import { strict } from 'node:assert';

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 */
/**
* The `async_hooks` module provides an API to track asynchronous resources. It
@@ -9,7 +9,7 @@
* import async_hooks from 'async_hooks';
* ```
* @experimental
* @see [source](https://github.com/nodejs/node/blob/v16.9.0/lib/async_hooks.js)
* @see [source](https://github.com/nodejs/node/blob/v18.0.0/lib/async_hooks.js)
*/
declare module 'async_hooks' {
/**
@@ -367,7 +367,7 @@ declare module 'async_hooks' {
*
* Each instance of `AsyncLocalStorage` maintains an independent storage context.
* Multiple instances can safely exist simultaneously without risk of interfering
* with each other data.
* with each other's data.
* @since v13.10.0, v12.17.0
*/
class AsyncLocalStorage<T> {
@@ -398,8 +398,9 @@ declare module 'async_hooks' {
getStore(): T | undefined;
/**
* Runs a function synchronously within a context and returns its
* return value. The store is not accessible outside of the callback function or
* the asynchronous operations created within the callback.
* return value. The store is not accessible outside of the callback function.
* The store is accessible to any asynchronous operations created within the
* callback.
*
* The optional `args` are passed to the callback function.
*
@@ -413,6 +414,9 @@ declare module 'async_hooks' {
* try {
* asyncLocalStorage.run(store, () => {
* asyncLocalStorage.getStore(); // Returns the store object
* setTimeout(() => {
* asyncLocalStorage.getStore(); // Returns the store object
* }, 200);
* throw new Error();
* });
* } catch (e) {

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 */
/**
* `Buffer` objects are used to represent a fixed-length sequence of bytes. Many
@@ -44,7 +44,7 @@
* // Creates a Buffer containing the Latin-1 bytes [0x74, 0xe9, 0x73, 0x74].
* const buf7 = Buffer.from('tést', 'latin1');
* ```
* @see [source](https://github.com/nodejs/node/blob/v16.9.0/lib/buffer.js)
* @see [source](https://github.com/nodejs/node/blob/v18.0.0/lib/buffer.js)
*/
declare module 'buffer' {
import { BinaryLike } from 'node:crypto';
@@ -117,18 +117,17 @@ declare module 'buffer' {
/**
* A [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob) encapsulates immutable, raw data that can be safely shared across
* multiple worker threads.
* @since v15.7.0
* @experimental
* @since v15.7.0, v14.18.0
*/
export class Blob {
/**
* The total size of the `Blob` in bytes.
* @since v15.7.0
* @since v15.7.0, v14.18.0
*/
readonly size: number;
/**
* The content-type of the `Blob`.
* @since v15.7.0
* @since v15.7.0, v14.18.0
*/
readonly type: string;
/**
@@ -143,13 +142,13 @@ declare module 'buffer' {
/**
* Returns a promise that fulfills with an [ArrayBuffer](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer) containing a copy of
* the `Blob` data.
* @since v15.7.0
* @since v15.7.0, v14.18.0
*/
arrayBuffer(): Promise<ArrayBuffer>;
/**
* Creates and returns a new `Blob` containing a subset of this `Blob` objects
* data. The original `Blob` is not altered.
* @since v15.7.0
* @since v15.7.0, v14.18.0
* @param start The starting index.
* @param end The ending index.
* @param type The content-type for the new `Blob`
@@ -158,7 +157,7 @@ declare module 'buffer' {
/**
* Returns a promise that fulfills with the contents of the `Blob` decoded as a
* UTF-8 string.
* @since v15.7.0
* @since v15.7.0, v14.18.0
*/
text(): Promise<string>;
/**
@@ -169,6 +168,12 @@ declare module 'buffer' {
}
export import atob = globalThis.atob;
export import btoa = globalThis.btoa;
import { Blob as NodeBlob } from 'buffer';
// This conditional type will be the existing global Blob in a browser, or
// the copy below in a Node environment.
type __Blob = typeof globalThis extends { onmessage: any, Blob: infer T }
? T : NodeBlob;
global {
// Buffer class
type BufferEncoding = 'ascii' | 'utf8' | 'utf-8' | 'utf16le' | 'ucs2' | 'ucs-2' | 'base64' | 'base64url' | 'latin1' | 'binary' | 'hex';
@@ -394,7 +399,7 @@ declare module 'buffer' {
* @since v0.11.13
* @return Either `-1`, `0`, or `1`, depending on the result of the comparison. See `compare` for details.
*/
compare(buf1: Uint8Array, buf2: Uint8Array): number;
compare(buf1: Uint8Array, buf2: Uint8Array): -1 | 0 | 1;
/**
* Allocates a new `Buffer` of `size` bytes. If `fill` is `undefined`, the`Buffer` will be zero-filled.
*
@@ -447,7 +452,7 @@ declare module 'buffer' {
* Allocates a new `Buffer` of `size` bytes. If `size` is larger than {@link constants.MAX_LENGTH} or smaller than 0, `ERR_INVALID_ARG_VALUE` is thrown.
*
* The underlying memory for `Buffer` instances created in this way is _not_
* _initialized_. The contents of the newly created `Buffer` are unknown and_may contain sensitive data_. Use `Buffer.alloc()` instead to initialize`Buffer` instances with zeroes.
* _initialized_. The contents of the newly created `Buffer` are unknown and _may contain sensitive data_. Use `Buffer.alloc()` instead to initialize`Buffer` instances with zeroes.
*
* ```js
* import { Buffer } from 'buffer';
@@ -485,7 +490,7 @@ declare module 'buffer' {
* if `size` is 0.
*
* The underlying memory for `Buffer` instances created in this way is _not_
* _initialized_. The contents of the newly created `Buffer` are unknown and_may contain sensitive data_. Use `buf.fill(0)` to initialize
* _initialized_. The contents of the newly created `Buffer` are unknown and _may contain sensitive data_. Use `buf.fill(0)` to initialize
* such `Buffer` instances with zeroes.
*
* When using `Buffer.allocUnsafe()` to allocate new `Buffer` instances,
@@ -708,7 +713,7 @@ declare module 'buffer' {
* @param [sourceStart=0] The offset within `buf` at which to begin comparison.
* @param [sourceEnd=buf.length] The offset within `buf` at which to end comparison (not inclusive).
*/
compare(target: Uint8Array, targetStart?: number, targetEnd?: number, sourceStart?: number, sourceEnd?: number): number;
compare(target: Uint8Array, targetStart?: number, targetEnd?: number, sourceStart?: number, sourceEnd?: number): -1 | 0 | 1;
/**
* Copies data from a region of `buf` to a region in `target`, even if the `target`memory region overlaps with `buf`.
*
@@ -767,8 +772,6 @@ declare module 'buffer' {
* Returns a new `Buffer` that references the same memory as the original, but
* offset and cropped by the `start` and `end` indices.
*
* This is the same behavior as `buf.subarray()`.
*
* This method is not compatible with the `Uint8Array.prototype.slice()`,
* which is a superclass of `Buffer`. To copy the slice, use`Uint8Array.prototype.slice()`.
*
@@ -784,8 +787,17 @@ declare module 'buffer' {
*
* console.log(buf.toString());
* // Prints: buffer
*
* // With buf.slice(), the original buffer is modified.
* const notReallyCopiedBuf = buf.slice();
* notReallyCopiedBuf[0]++;
* console.log(notReallyCopiedBuf.toString());
* // Prints: cuffer
* console.log(buf.toString());
* // Also prints: cuffer (!)
* ```
* @since v0.3.0
* @deprecated Use `subarray` instead.
* @param [start=0] Where the new `Buffer` will start.
* @param [end=buf.length] Where the new `Buffer` will end (not inclusive).
*/
@@ -1952,7 +1964,7 @@ declare module 'buffer' {
*
* * a string, `value` is interpreted according to the character encoding in`encoding`.
* * a `Buffer` or [`Uint8Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array), `value` will be used in its entirety.
* To compare a partial `Buffer`, use `buf.slice()`.
* To compare a partial `Buffer`, use `buf.subarray`.
* * a number, `value` will be interpreted as an unsigned 8-bit integer
* value between `0` and `255`.
*
@@ -2208,7 +2220,7 @@ declare module 'buffer' {
* **binary data and predate the introduction of typed arrays in JavaScript.**
* **For code running using Node.js APIs, converting between base64-encoded strings**
* **and binary data should be performed using `Buffer.from(str, 'base64')` and`buf.toString('base64')`.**
* @since v15.13.0
* @since v15.13.0, v14.17.0
* @deprecated Use `Buffer.from(data, 'base64')` instead.
* @param data The Base64-encoded input string.
*/
@@ -2224,11 +2236,24 @@ declare module 'buffer' {
* **binary data and predate the introduction of typed arrays in JavaScript.**
* **For code running using Node.js APIs, converting between base64-encoded strings**
* **and binary data should be performed using `Buffer.from(str, 'base64')` and`buf.toString('base64')`.**
* @since v15.13.0
* @since v15.13.0, v14.17.0
* @deprecated Use `buf.toString('base64')` instead.
* @param data An ASCII (Latin1) string.
*/
function btoa(data: string): string;
interface Blob extends __Blob {}
/**
* `Blob` class is a global reference for `require('node:buffer').Blob`
* https://nodejs.org/api/buffer.html#class-blob
* @since v18.0.0
*/
var Blob: typeof globalThis extends {
onmessage: any;
Blob: infer T;
}
? T
: typeof NodeBlob;
}
}
declare module 'node:buffer' {

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 */
/**
* The `child_process` module provides the ability to spawn subprocesses in
@@ -31,8 +31,11 @@
* identical to the behavior of pipes in the shell. Use the `{ stdio: 'ignore' }`option if the output will not be consumed.
*
* The command lookup is performed using the `options.env.PATH` environment
* variable if it is in the `options` object. Otherwise, `process.env.PATH` is
* used.
* variable if `env` is in the `options` object. Otherwise, `process.env.PATH` is
* used. If `options.env` is set without `PATH`, lookup on Unix is performed
* on a default search path search of `/usr/bin:/bin` (see your operating system's
* manual for execvpe/execvp), on Windows the current processes environment
* variable `PATH` is used.
*
* On Windows, environment variables are case-insensitive. Node.js
* lexicographically sorts the `env` keys and uses the first one that
@@ -63,7 +66,7 @@
* For certain use cases, such as automating shell scripts, the `synchronous counterparts` may be more convenient. In many cases, however,
* the synchronous methods can have significant impact on performance due to
* stalling the event loop while spawned processes complete.
* @see [source](https://github.com/nodejs/node/blob/v16.9.0/lib/child_process.js)
* @see [source](https://github.com/nodejs/node/blob/v18.0.0/lib/child_process.js)
*/
declare module 'child_process' {
import { ObjectEncodingOptions } from 'node:fs';
@@ -624,7 +627,7 @@ declare module 'child_process' {
}
interface CommonOptions extends ProcessEnvOptions {
/**
* @default false
* @default true
*/
windowsHide?: boolean | undefined;
/**

View File

@@ -1,10 +1,11 @@
/* 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 */
/**
* A single instance of Node.js runs in a single thread. To take advantage of
* multi-core systems, the user will sometimes want to launch a cluster of Node.js
* processes to handle the load.
* Clusters of Node.js processes can be used to run multiple instances of Node.js
* that can distribute workloads among their application threads. When process
* isolation is not needed, use the `worker_threads` module instead, which
* allows running multiple application threads within a single Node.js instance.
*
* The cluster module allows easy creation of child processes that all share
* server ports.
@@ -52,7 +53,7 @@
* ```
*
* On Windows, it is not yet possible to set up a named pipe server in a worker.
* @see [source](https://github.com/nodejs/node/blob/v16.9.0/lib/cluster.js)
* @see [source](https://github.com/nodejs/node/blob/v18.0.0/lib/cluster.js)
*/
declare module 'cluster' {
import * as child from 'node:child_process';
@@ -102,9 +103,9 @@ declare module 'cluster' {
/**
* Send a message to a worker or primary, optionally with a handle.
*
* In the primary this sends a message to a specific worker. It is identical to `ChildProcess.send()`.
* In the primary, this sends a message to a specific worker. It is identical to `ChildProcess.send()`.
*
* In a worker this sends a message to the primary. It is identical to`process.send()`.
* In a worker, this sends a message to the primary. It is identical to`process.send()`.
*
* This example will echo back all messages from the primary:
*
@@ -126,19 +127,13 @@ declare module 'cluster' {
send(message: child.Serializable, sendHandle: child.SendHandle, callback?: (error: Error | null) => void): boolean;
send(message: child.Serializable, sendHandle: child.SendHandle, options?: child.MessageOptions, callback?: (error: Error | null) => void): boolean;
/**
* This function will kill the worker. In the primary, it does this
* by disconnecting the `worker.process`, and once disconnected, killing
* with `signal`. In the worker, it does it by disconnecting the channel,
* and then exiting with code `0`.
* This function will kill the worker. In the primary worker, it does this by
* disconnecting the `worker.process`, and once disconnected, killing with`signal`. In the worker, it does it by killing the process with `signal`.
*
* Because `kill()` attempts to gracefully disconnect the worker process, it is
* susceptible to waiting indefinitely for the disconnect to complete. For example,
* if the worker enters an infinite loop, a graceful disconnect will never occur.
* If the graceful disconnect behavior is not needed, use `worker.process.kill()`.
* The `kill()` function kills the worker process without waiting for a graceful
* disconnect, it has the same behavior as `worker.process.kill()`.
*
* Causes `.exitedAfterDisconnect` to be set.
*
* This method is aliased as `worker.destroy()` for backward compatibility.
* This method is aliased as `worker.destroy()` for backwards compatibility.
*
* In a worker, `process.kill()` exists, but it is not this function;
* it is `kill()`.
@@ -256,7 +251,8 @@ declare module 'cluster' {
*/
isDead(): boolean;
/**
* This property is `true` if the worker exited due to `.kill()` or`.disconnect()`. If the worker exited any other way, it is `false`. If the
* This property is `true` if the worker exited due to `.disconnect()`.
* If the worker exited any other way, it is `false`. If the
* worker has not exited, it is `undefined`.
*
* The boolean `worker.exitedAfterDisconnect` allows distinguishing between

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 */
/**
* The `console` module provides a simple debugging console that is similar to the
@@ -56,7 +56,7 @@
* myConsole.warn(`Danger ${name}! Danger!`);
* // Prints: Danger Will Robinson! Danger!, to err
* ```
* @see [source](https://github.com/nodejs/node/blob/v16.9.0/lib/console.js)
* @see [source](https://github.com/nodejs/node/blob/v18.0.0/lib/console.js)
*/
declare module 'console' {
import console = require('node:console');

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 */
/**
* The `crypto` module provides cryptographic functionality that includes a set of
@@ -16,12 +16,64 @@
* // Prints:
* // c0fa1bc00531bd78ef38c628449c5102aeabd49b5dc3a2a516ea6ea959d6658e
* ```
* @see [source](https://github.com/nodejs/node/blob/v16.9.0/lib/crypto.js)
* @see [source](https://github.com/nodejs/node/blob/v18.0.0/lib/crypto.js)
*/
declare module 'crypto' {
import * as stream from 'node:stream';
import { PeerCertificate } from 'node:tls';
interface Certificate {
/**
* SPKAC is a Certificate Signing Request mechanism originally implemented by
* Netscape and was specified formally as part of [HTML5's `keygen` element](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/keygen).
*
* `<keygen>` is deprecated since [HTML 5.2](https://www.w3.org/TR/html52/changes.html#features-removed) and new projects
* should not use this element anymore.
*
* The `crypto` module provides the `Certificate` class for working with SPKAC
* data. The most common usage is handling output generated by the HTML5`<keygen>` element. Node.js uses [OpenSSL's SPKAC
* implementation](https://www.openssl.org/docs/man1.1.0/apps/openssl-spkac.html) internally.
* @since v0.11.8
*/
class Certificate {
/**
* ```js
* const { Certificate } = await import('crypto');
* const spkac = getSpkacSomehow();
* const challenge = Certificate.exportChallenge(spkac);
* console.log(challenge.toString('utf8'));
* // Prints: the challenge as a UTF8 string
* ```
* @since v9.0.0
* @param encoding The `encoding` of the `spkac` string.
* @return The challenge component of the `spkac` data structure, which includes a public key and a challenge.
*/
static exportChallenge(spkac: BinaryLike): Buffer;
/**
* ```js
* const { Certificate } = await import('crypto');
* const spkac = getSpkacSomehow();
* const publicKey = Certificate.exportPublicKey(spkac);
* console.log(publicKey);
* // Prints: the public key as <Buffer ...>
* ```
* @since v9.0.0
* @param encoding The `encoding` of the `spkac` string.
* @return The public key component of the `spkac` data structure, which includes a public key and a challenge.
*/
static exportPublicKey(spkac: BinaryLike, encoding?: string): Buffer;
/**
* ```js
* import { Buffer } from 'buffer';
* const { Certificate } = await import('crypto');
*
* const spkac = getSpkacSomehow();
* console.log(Certificate.verifySpkac(Buffer.from(spkac)));
* // Prints: true or false
* ```
* @since v9.0.0
* @param encoding The `encoding` of the `spkac` string.
* @return `true` if the given `spkac` data structure is valid, `false` otherwise.
*/
static verifySpkac(spkac: NodeJS.ArrayBufferView): boolean;
/**
* @deprecated
* @param spkac
@@ -45,31 +97,6 @@ declare module 'crypto' {
*/
verifySpkac(spkac: NodeJS.ArrayBufferView): boolean;
}
const Certificate: Certificate & {
/** @deprecated since v14.9.0 - Use static methods of `crypto.Certificate` instead. */
new (): Certificate;
/** @deprecated since v14.9.0 - Use static methods of `crypto.Certificate` instead. */
(): Certificate;
/**
* @param spkac
* @returns The challenge component of the `spkac` data structure,
* which includes a public key and a challenge.
*/
exportChallenge(spkac: BinaryLike): Buffer;
/**
* @param spkac
* @param encoding The encoding of the spkac string.
* @returns The public key component of the `spkac` data structure,
* which includes a public key and a challenge.
*/
exportPublicKey(spkac: BinaryLike, encoding?: string): Buffer;
/**
* @param spkac
* @returns `true` if the given `spkac` data structure is valid,
* `false` otherwise.
*/
verifySpkac(spkac: NodeJS.ArrayBufferView): boolean;
};
namespace constants {
// https://nodejs.org/dist/latest-v10.x/docs/api/crypto.html#crypto_crypto_constants
const OPENSSL_VERSION_NUMBER: number;
@@ -175,7 +202,7 @@ declare module 'crypto' {
*
* The `algorithm` is dependent on the available algorithms supported by the
* version of OpenSSL on the platform. Examples are `'sha256'`, `'sha512'`, etc.
* On recent releases of OpenSSL, `openssl list -digest-algorithms`(`openssl list-message-digest-algorithms` for older versions of OpenSSL) will
* On recent releases of OpenSSL, `openssl list -digest-algorithms` will
* display the available digest algorithms.
*
* Example: generating the sha256 sum of a file
@@ -215,7 +242,7 @@ declare module 'crypto' {
*
* The `algorithm` is dependent on the available algorithms supported by the
* version of OpenSSL on the platform. Examples are `'sha256'`, `'sha512'`, etc.
* On recent releases of OpenSSL, `openssl list -digest-algorithms`(`openssl list-message-digest-algorithms` for older versions of OpenSSL) will
* On recent releases of OpenSSL, `openssl list -digest-algorithms` will
* display the available digest algorithms.
*
* The `key` is the HMAC key used to generate the cryptographic HMAC hash. If it is
@@ -253,7 +280,7 @@ declare module 'crypto' {
*/
function createHmac(algorithm: string, key: BinaryLike | KeyObject, options?: stream.TransformOptions): Hmac;
// https://nodejs.org/api/buffer.html#buffer_buffers_and_character_encodings
type BinaryToTextEncoding = 'base64' | 'base64url' | 'hex';
type BinaryToTextEncoding = 'base64' | 'base64url' | 'hex' | 'binary';
type CharacterEncoding = 'utf8' | 'utf-8' | 'utf16le' | 'latin1';
type LegacyCharacterEncoding = 'ascii' | 'binary' | 'ucs2' | 'ucs-2';
type Encoding = BinaryToTextEncoding | CharacterEncoding | LegacyCharacterEncoding;
@@ -662,12 +689,13 @@ declare module 'crypto' {
* Creates and returns a `Cipher` object that uses the given `algorithm` and`password`.
*
* The `options` argument controls stream behavior and is optional except when a
* cipher in CCM or OCB mode is used (e.g. `'aes-128-ccm'`). In that case, the`authTagLength` option is required and specifies the length of the
* cipher in CCM or OCB mode (e.g. `'aes-128-ccm'`) is used. In that case, the`authTagLength` option is required and specifies the length of the
* authentication tag in bytes, see `CCM mode`. In GCM mode, the `authTagLength`option is not required but can be used to set the length of the authentication
* tag that will be returned by `getAuthTag()` and defaults to 16 bytes.
* For `chacha20-poly1305`, the `authTagLength` option defaults to 16 bytes.
*
* The `algorithm` is dependent on OpenSSL, examples are `'aes192'`, etc. On
* recent OpenSSL releases, `openssl list -cipher-algorithms`(`openssl list-cipher-algorithms` for older versions of OpenSSL) will
* recent OpenSSL releases, `openssl list -cipher-algorithms` will
* display the available cipher algorithms.
*
* The `password` is used to derive the cipher key and initialization vector (IV).
@@ -700,12 +728,13 @@ declare module 'crypto' {
* initialization vector (`iv`).
*
* The `options` argument controls stream behavior and is optional except when a
* cipher in CCM or OCB mode is used (e.g. `'aes-128-ccm'`). In that case, the`authTagLength` option is required and specifies the length of the
* cipher in CCM or OCB mode (e.g. `'aes-128-ccm'`) is used. In that case, the`authTagLength` option is required and specifies the length of the
* authentication tag in bytes, see `CCM mode`. In GCM mode, the `authTagLength`option is not required but can be used to set the length of the authentication
* tag that will be returned by `getAuthTag()` and defaults to 16 bytes.
* For `chacha20-poly1305`, the `authTagLength` option defaults to 16 bytes.
*
* The `algorithm` is dependent on OpenSSL, examples are `'aes192'`, etc. On
* recent OpenSSL releases, `openssl list -cipher-algorithms`(`openssl list-cipher-algorithms` for older versions of OpenSSL) will
* recent OpenSSL releases, `openssl list -cipher-algorithms` will
* display the available cipher algorithms.
*
* The `key` is the raw key used by the `algorithm` and `iv` is an [initialization vector](https://en.wikipedia.org/wiki/Initialization_vector). Both arguments must be `'utf8'` encoded
@@ -925,8 +954,9 @@ declare module 'crypto' {
* Creates and returns a `Decipher` object that uses the given `algorithm` and`password` (key).
*
* The `options` argument controls stream behavior and is optional except when a
* cipher in CCM or OCB mode is used (e.g. `'aes-128-ccm'`). In that case, the`authTagLength` option is required and specifies the length of the
* cipher in CCM or OCB mode (e.g. `'aes-128-ccm'`) is used. In that case, the`authTagLength` option is required and specifies the length of the
* authentication tag in bytes, see `CCM mode`.
* For `chacha20-poly1305`, the `authTagLength` option defaults to 16 bytes.
*
* The implementation of `crypto.createDecipher()` derives keys using the OpenSSL
* function [`EVP_BytesToKey`](https://www.openssl.org/docs/man1.1.0/crypto/EVP_BytesToKey.html) with the digest algorithm set to MD5, one
@@ -951,12 +981,13 @@ declare module 'crypto' {
* Creates and returns a `Decipher` object that uses the given `algorithm`, `key`and initialization vector (`iv`).
*
* The `options` argument controls stream behavior and is optional except when a
* cipher in CCM or OCB mode is used (e.g. `'aes-128-ccm'`). In that case, the`authTagLength` option is required and specifies the length of the
* cipher in CCM or OCB mode (e.g. `'aes-128-ccm'`) is used. In that case, the`authTagLength` option is required and specifies the length of the
* authentication tag in bytes, see `CCM mode`. In GCM mode, the `authTagLength`option is not required but can be used to restrict accepted authentication tags
* to those with the specified length.
* For `chacha20-poly1305`, the `authTagLength` option defaults to 16 bytes.
*
* The `algorithm` is dependent on OpenSSL, examples are `'aes192'`, etc. On
* recent OpenSSL releases, `openssl list -cipher-algorithms`(`openssl list-cipher-algorithms` for older versions of OpenSSL) will
* recent OpenSSL releases, `openssl list -cipher-algorithms` will
* display the available cipher algorithms.
*
* The `key` is the raw key used by the `algorithm` and `iv` is an [initialization vector](https://en.wikipedia.org/wiki/Initialization_vector). Both arguments must be `'utf8'` encoded
@@ -1162,13 +1193,11 @@ declare module 'crypto' {
format?: KeyFormat | undefined;
type?: 'pkcs1' | 'pkcs8' | 'sec1' | undefined;
passphrase?: string | Buffer | undefined;
encoding?: string | undefined;
}
interface PublicKeyInput {
key: string | Buffer;
format?: KeyFormat | undefined;
type?: 'pkcs1' | 'spki' | undefined;
encoding?: string | undefined;
}
/**
* Asynchronously generates a new random secret key of the given `length`. The`type` will determine which validations will be performed on the `length`.
@@ -1279,7 +1308,6 @@ declare module 'crypto' {
interface VerifyKeyObjectInput extends SigningOptions {
key: KeyObject;
}
interface VerifyJsonWebKeyInput extends JsonWebKeyInput, SigningOptions {}
type KeyLike = string | Buffer | KeyObject;
/**
* The `Sign` class is a utility for generating signatures. It can be used in one
@@ -1434,8 +1462,8 @@ declare module 'crypto' {
* be passed instead of a public key.
* @since v0.1.92
*/
verify(object: KeyLike | VerifyKeyObjectInput | VerifyPublicKeyInput | VerifyJsonWebKeyInput, signature: NodeJS.ArrayBufferView): boolean;
verify(object: KeyLike | VerifyKeyObjectInput | VerifyPublicKeyInput | VerifyJsonWebKeyInput, signature: string, signature_format?: BinaryToTextEncoding): boolean;
verify(object: KeyLike | VerifyKeyObjectInput | VerifyPublicKeyInput, signature: NodeJS.ArrayBufferView): boolean;
verify(object: KeyLike | VerifyKeyObjectInput | VerifyPublicKeyInput, signature: string, signature_format?: BinaryToTextEncoding): boolean;
}
/**
* Creates a `DiffieHellman` key exchange object using the supplied `prime` and an
@@ -1453,10 +1481,10 @@ declare module 'crypto' {
* @param [generator=2]
* @param generatorEncoding The `encoding` of the `generator` string.
*/
function createDiffieHellman(primeLength: number, generator?: number | NodeJS.ArrayBufferView): DiffieHellman;
function createDiffieHellman(prime: NodeJS.ArrayBufferView): DiffieHellman;
function createDiffieHellman(prime: string, primeEncoding: BinaryToTextEncoding): DiffieHellman;
function createDiffieHellman(prime: string, primeEncoding: BinaryToTextEncoding, generator: number | NodeJS.ArrayBufferView): DiffieHellman;
function createDiffieHellman(primeLength: number, generator?: number): DiffieHellman;
function createDiffieHellman(prime: ArrayBuffer | NodeJS.ArrayBufferView, generator?: number | ArrayBuffer | NodeJS.ArrayBufferView): DiffieHellman;
function createDiffieHellman(prime: ArrayBuffer | NodeJS.ArrayBufferView, generator: string, generatorEncoding: BinaryToTextEncoding): DiffieHellman;
function createDiffieHellman(prime: string, primeEncoding: BinaryToTextEncoding, generator?: number | ArrayBuffer | NodeJS.ArrayBufferView): DiffieHellman;
function createDiffieHellman(prime: string, primeEncoding: BinaryToTextEncoding, generator: string, generatorEncoding: BinaryToTextEncoding): DiffieHellman;
/**
* The `DiffieHellman` class is a utility for creating Diffie-Hellman key
@@ -1805,7 +1833,7 @@ declare module 'crypto' {
* Return a random integer `n` such that `min <= n < max`. This
* implementation avoids [modulo bias](https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle#Modulo_bias).
*
* The range (`max - min`) must be less than `2**48`. `min` and `max` must
* The range (`max - min`) must be less than 2^48. `min` and `max` must
* be [safe integers](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isSafeInteger).
*
* If the `callback` function is not provided, the random integer is
@@ -2281,11 +2309,11 @@ declare module 'crypto' {
* If `encoding` is specified, a string is returned; otherwise a `Buffer` is
* returned.
* @since v0.11.14
* @param encoding The `encoding` of the return value.
* @param [encoding] The `encoding` of the return value.
* @param [format='uncompressed']
* @return The EC Diffie-Hellman public key in the specified `encoding` and `format`.
*/
getPublicKey(): Buffer;
getPublicKey(encoding?: null, format?: ECDHKeyFormat): Buffer;
getPublicKey(encoding: BinaryToTextEncoding, format?: ECDHKeyFormat): string;
/**
* Sets the EC Diffie-Hellman private key.
@@ -2316,7 +2344,8 @@ declare module 'crypto' {
* comparing HMAC digests or secret values like authentication cookies or [capability urls](https://www.w3.org/TR/capability-urls/).
*
* `a` and `b` must both be `Buffer`s, `TypedArray`s, or `DataView`s, and they
* must have the same byte length.
* must have the same byte length. An error is thrown if `a` and `b` have
* different byte lengths.
*
* If at least one of `a` and `b` is a `TypedArray` with more than one byte per
* entry, such as `Uint16Array`, the result will be computed using the platform
@@ -2331,7 +2360,7 @@ declare module 'crypto' {
/** @deprecated since v10.0.0 */
const DEFAULT_ENCODING: BufferEncoding;
type KeyType = 'rsa' | 'rsa-pss' | 'dsa' | 'ec' | 'ed25519' | 'ed448' | 'x25519' | 'x448';
type KeyFormat = 'pem' | 'der' | 'jwk';
type KeyFormat = 'pem' | 'der';
interface BasePrivateKeyEncodingOptions<T extends KeyFormat> {
format: T;
cipher?: string | undefined;
@@ -2942,16 +2971,11 @@ declare module 'crypto' {
* If the `callback` function is provided this function uses libuv's threadpool.
* @since v12.0.0
*/
function verify(algorithm: string | null | undefined, data: NodeJS.ArrayBufferView, key: KeyLike | VerifyKeyObjectInput | VerifyPublicKeyInput, signature: NodeJS.ArrayBufferView): boolean;
function verify(
algorithm: string | null | undefined,
data: NodeJS.ArrayBufferView,
key: KeyLike | VerifyKeyObjectInput | VerifyPublicKeyInput | VerifyJsonWebKeyInput,
signature: NodeJS.ArrayBufferView
): boolean;
function verify(
algorithm: string | null | undefined,
data: NodeJS.ArrayBufferView,
key: KeyLike | VerifyKeyObjectInput | VerifyPublicKeyInput | VerifyJsonWebKeyInput,
key: KeyLike | VerifyKeyObjectInput | VerifyPublicKeyInput,
signature: NodeJS.ArrayBufferView,
callback: (error: Error | null, result: boolean) => void
): void;
@@ -3100,34 +3124,33 @@ declare module 'crypto' {
*/
disableEntropyCache?: boolean | undefined;
}
type UUID = `${string}-${string}-${string}-${string}-${string}`;
/**
* Generates a random [RFC 4122](https://www.rfc-editor.org/rfc/rfc4122.txt) version 4 UUID. The UUID is generated using a
* cryptographic pseudorandom number generator.
* @since v15.6.0
* @since v15.6.0, v14.17.0
*/
function randomUUID(options?: RandomUUIDOptions): UUID;
function randomUUID(options?: RandomUUIDOptions): string;
interface X509CheckOptions {
/**
* @default 'always'
*/
subject?: 'always' | 'default' | 'never';
subject: 'always' | 'never';
/**
* @default true
*/
wildcards?: boolean;
wildcards: boolean;
/**
* @default true
*/
partialWildcards?: boolean;
partialWildcards: boolean;
/**
* @default false
*/
multiLabelWildcards?: boolean;
multiLabelWildcards: boolean;
/**
* @default false
*/
singleLabelSubdomains?: boolean;
singleLabelSubdomains: boolean;
}
/**
* Encapsulates an X509 certificate and provides read-only access to
@@ -3144,12 +3167,16 @@ declare module 'crypto' {
*/
class X509Certificate {
/**
* Will be \`true\` if this is a Certificate Authority (ca) certificate.
* Will be \`true\` if this is a Certificate Authority (CA) certificate.
* @since v15.6.0
*/
readonly ca: boolean;
/**
* The SHA-1 fingerprint of this certificate.
*
* Because SHA-1 is cryptographically broken and because the security of SHA-1 is
* significantly worse than that of algorithms that are commonly used to sign
* certificates, consider using `x509.fingerprint256` instead.
* @since v15.6.0
*/
readonly fingerprint: string;
@@ -3208,6 +3235,10 @@ declare module 'crypto' {
readonly raw: Buffer;
/**
* The serial number of this certificate.
*
* Serial numbers are assigned by certificate authorities and do not uniquely
* identify certificates. Consider using `x509.fingerprint256` as a unique
* identifier instead.
* @since v15.6.0
*/
readonly serialNumber: string;
@@ -3224,18 +3255,50 @@ declare module 'crypto' {
constructor(buffer: BinaryLike);
/**
* Checks whether the certificate matches the given email address.
*
* If the `'subject'` option is undefined or set to `'default'`, the certificate
* subject is only considered if the subject alternative name extension either does
* not exist or does not contain any email addresses.
*
* If the `'subject'` option is set to `'always'` and if the subject alternative
* name extension either does not exist or does not contain a matching email
* address, the certificate subject is considered.
*
* If the `'subject'` option is set to `'never'`, the certificate subject is never
* considered, even if the certificate contains no subject alternative names.
* @since v15.6.0
* @return Returns `email` if the certificate matches, `undefined` if it does not.
*/
checkEmail(email: string, options?: Pick<X509CheckOptions, 'subject'>): string | undefined;
/**
* Checks whether the certificate matches the given host name.
*
* If the certificate matches the given host name, the matching subject name is
* returned. The returned name might be an exact match (e.g., `foo.example.com`)
* or it might contain wildcards (e.g., `*.example.com`). Because host name
* comparisons are case-insensitive, the returned subject name might also differ
* from the given `name` in capitalization.
*
* If the `'subject'` option is undefined or set to `'default'`, the certificate
* subject is only considered if the subject alternative name extension either does
* not exist or does not contain any DNS names. This behavior is consistent with [RFC 2818](https://www.rfc-editor.org/rfc/rfc2818.txt) ("HTTP Over TLS").
*
* If the `'subject'` option is set to `'always'` and if the subject alternative
* name extension either does not exist or does not contain a matching DNS name,
* the certificate subject is considered.
*
* If the `'subject'` option is set to `'never'`, the certificate subject is never
* considered, even if the certificate contains no subject alternative names.
* @since v15.6.0
* @return Returns `name` if the certificate matches, `undefined` if it does not.
* @return Returns a subject name that matches `name`, or `undefined` if no subject name matches `name`.
*/
checkHost(name: string, options?: X509CheckOptions): string | undefined;
/**
* Checks whether the certificate matches the given IP address (IPv4 or IPv6).
*
* Only [RFC 5280](https://www.rfc-editor.org/rfc/rfc5280.txt) `iPAddress` subject alternative names are considered, and they
* must match the given `ip` address exactly. Other subject alternative names as
* well as the subject field of the certificate are ignored.
* @since v15.6.0
* @return Returns `ip` if the certificate matches, `undefined` if it does not.
*/
@@ -3408,6 +3471,19 @@ declare module 'crypto' {
* @param [flags=crypto.constants.ENGINE_METHOD_ALL]
*/
function setEngine(engine: string, flags?: number): void;
/**
* A convenient alias for `crypto.webcrypto.getRandomValues()`.
* This implementation is not compliant with the Web Crypto spec,
* to write web-compatible code use `crypto.webcrypto.getRandomValues()` instead.
* @since v17.4.0
* @returns Returns `typedArray`.
*/
function getRandomValues<T extends webcrypto.BufferSource>(typedArray: T): T;
/**
* A convenient alias for `crypto.webcrypto.subtle`.
* @since v17.4.0
*/
const subtle: webcrypto.SubtleCrypto;
/**
* An implementation of the Web Crypto API standard.
*
@@ -3565,7 +3641,7 @@ declare module 'crypto' {
* The UUID is generated using a cryptographic pseudorandom number generator.
* @since v16.7.0
*/
randomUUID(): UUID;
randomUUID(): string;
CryptoKey: CryptoKeyConstructor;
}
// This constructor throws ILLEGAL_CONSTRUCTOR so it should not be newable.
@@ -3650,17 +3726,22 @@ declare module 'crypto' {
/**
* Using the method and parameters specified in `algorithm` and the keying material provided by `baseKey`,
* `subtle.deriveBits()` attempts to generate `length` bits.
* The Node.js implementation requires that `length` is a multiple of `8`.
* The Node.js implementation requires that when `length` is a number it must be multiple of `8`.
* When `length` is `null` the maximum number of bits for a given algorithm is generated. This is allowed
* for the `'ECDH'`, `'X25519'`, and `'X448'` algorithms.
* If successful, the returned promise will be resolved with an `<ArrayBuffer>` containing the generated data.
*
* The algorithms currently supported include:
*
* - `'ECDH'`
* - `'X25519'`
* - `'X448'`
* - `'HKDF'`
* - `'PBKDF2'`
* @since v15.0.0
*/
deriveBits(algorithm: AlgorithmIdentifier | EcdhKeyDeriveParams | HkdfParams | Pbkdf2Params, baseKey: CryptoKey, length: number): Promise<ArrayBuffer>;
deriveBits(algorithm: EcdhKeyDeriveParams, baseKey: CryptoKey, length: number | null): Promise<ArrayBuffer>;
deriveBits(algorithm: AlgorithmIdentifier | HkdfParams | Pbkdf2Params, baseKey: CryptoKey, length: number): Promise<ArrayBuffer>;
/**
* Using the method and parameters specified in `algorithm`, and the keying material provided by `baseKey`,
* `subtle.deriveKey()` attempts to generate a new <CryptoKey>` based on the method and parameters in `derivedKeyAlgorithm`.
@@ -3671,6 +3752,8 @@ declare module 'crypto' {
* The algorithms currently supported include:
*
* - `'ECDH'`
* - `'X25519'`
* - `'X448'`
* - `'HKDF'`
* - `'PBKDF2'`
* @param keyUsages See {@link https://nodejs.org/docs/latest/api/webcrypto.html#cryptokeyusages Key usages}.
@@ -3739,7 +3822,11 @@ declare module 'crypto' {
* - `'RSA-PSS'`
* - `'RSA-OAEP'`
* - `'ECDSA'`
* - `'Ed25519'`
* - `'Ed448'`
* - `'ECDH'`
* - `'X25519'`
* - `'X448'`
* The `<CryptoKey>` (secret key) generating algorithms supported include:
*
* - `'HMAC'`
@@ -3787,6 +3874,8 @@ declare module 'crypto' {
* - `'RSASSA-PKCS1-v1_5'`
* - `'RSA-PSS'`
* - `'ECDSA'`
* - `'Ed25519'`
* - `'Ed448'`
* - `'HMAC'`
* @since v15.0.0
*/
@@ -3812,7 +3901,11 @@ declare module 'crypto' {
* - `'RSA-PSS'`
* - `'RSA-OAEP'`
* - `'ECDSA'`
* - `'Ed25519'`
* - `'Ed448'`
* - `'ECDH'`
* - `'X25519'`
* - `'X448'`
* - `'HMAC'`
* - `'AES-CTR'`
* - `'AES-CBC'`
@@ -3841,6 +3934,8 @@ declare module 'crypto' {
* - `'RSASSA-PKCS1-v1_5'`
* - `'RSA-PSS'`
* - `'ECDSA'`
* - `'Ed25519'`
* - `'Ed448'`
* - `'HMAC'`
* @since v15.0.0
*/

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 */
/**
* The `dgram` module provides an implementation of UDP datagram sockets.
@@ -26,7 +26,7 @@
* server.bind(41234);
* // Prints: server listening 0.0.0.0:41234
* ```
* @see [source](https://github.com/nodejs/node/blob/v16.9.0/lib/dgram.js)
* @see [source](https://github.com/nodejs/node/blob/v18.0.0/lib/dgram.js)
*/
declare module 'dgram' {
import { AddressInfo } from 'node:net';
@@ -263,7 +263,7 @@ declare module 'dgram' {
*
* The `address` argument is a string. If the value of `address` is a host name,
* DNS will be used to resolve the address of the host. If `address` is not
* provided or otherwise falsy, `'127.0.0.1'` (for `udp4` sockets) or `'::1'`(for `udp6` sockets) will be used by default.
* provided or otherwise nullish, `'127.0.0.1'` (for `udp4` sockets) or `'::1'`(for `udp6` sockets) will be used by default.
*
* If the socket has not been previously bound with a call to `bind`, the socket
* is assigned a random port number and is bound to the "all interfaces" address
@@ -454,7 +454,7 @@ declare module 'dgram' {
* TTL. If the TTL is decremented to 0 by a router, it will not be forwarded.
* Changing TTL values is typically done for network probes or when multicasting.
*
* The `ttl` argument may be between between 1 and 255\. The default on most systems
* The `ttl` argument may be between 1 and 255\. The default on most systems
* is 64.
*
* This method throws `EBADF` if called on an unbound socket.

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 */
/**
* The `diagnostics_channel` module provides an API to create named channels
@@ -23,7 +23,7 @@
* should generally include the module name to avoid collisions with data from
* other modules.
* @experimental
* @see [source](https://github.com/nodejs/node/blob/v16.9.0/lib/diagnostics_channel.js)
* @see [source](https://github.com/nodejs/node/blob/v18.0.0/lib/diagnostics_channel.js)
*/
declare module 'diagnostics_channel' {
/**
@@ -44,7 +44,7 @@ declare module 'diagnostics_channel' {
* @param name The channel name
* @return If there are active subscribers
*/
function hasSubscribers(name: string | symbol): boolean;
function hasSubscribers(name: string): boolean;
/**
* This is the primary entry-point for anyone wanting to interact with a named
* channel. It produces a channel object which is optimized to reduce overhead at
@@ -59,8 +59,8 @@ declare module 'diagnostics_channel' {
* @param name The channel name
* @return The named channel object
*/
function channel(name: string | symbol): Channel;
type ChannelListener = (message: unknown, name: string | symbol) => void;
function channel(name: string): Channel;
type ChannelListener = (message: unknown, name: string) => void;
/**
* The class `Channel` represents an individual named channel within the data
* pipeline. It is use to track subscribers and to publish messages when there
@@ -71,7 +71,7 @@ declare module 'diagnostics_channel' {
* @since v15.1.0, v14.17.0
*/
class Channel {
readonly name: string | symbol;
readonly name: string;
/**
* Check if there are active subscribers to this channel. This is helpful if
* the message you want to send might be expensive to prepare.
@@ -91,7 +91,7 @@ declare module 'diagnostics_channel' {
* @since v15.1.0, v14.17.0
*/
readonly hasSubscribers: boolean;
private constructor(name: string | symbol);
private constructor(name: string);
/**
* Publish a message to any subscribers to the channel. This will
* trigger message handlers synchronously so they will execute within
@@ -146,6 +146,7 @@ declare module 'diagnostics_channel' {
* ```
* @since v15.1.0, v14.17.0
* @param onMessage The previous subscribed handler to remove
* @return `true` if the handler was found, `false` otherwise.
*/
unsubscribe(onMessage: ChannelListener): void;
}

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 */
/**
* The `dns` module enables name resolution. For example, use it to look up IP
@@ -45,7 +45,7 @@
* ```
*
* See the `Implementation considerations section` for more information.
* @see [source](https://github.com/nodejs/node/blob/v16.9.0/lib/dns.js)
* @see [source](https://github.com/nodejs/node/blob/v18.0.0/lib/dns.js)
*/
declare module 'dns' {
import * as dnsPromises from 'node:dns/promises';
@@ -61,6 +61,9 @@ declare module 'dns' {
family?: number | undefined;
hints?: number | undefined;
all?: boolean | undefined;
/**
* @default true
*/
verbatim?: boolean | undefined;
}
export interface LookupOneOptions extends LookupOptions {
@@ -174,7 +177,7 @@ declare module 'dns' {
type: 'AAAA';
}
export interface CaaRecord {
critical: number;
critial: number;
issue?: string | undefined;
issuewild?: string | undefined;
iodef?: string | undefined;
@@ -317,7 +320,7 @@ declare module 'dns' {
* Uses the DNS protocol to resolve `CAA` records for the `hostname`. The`addresses` argument passed to the `callback` function
* will contain an array of certification authority authorization records
* available for the `hostname` (e.g. `[{critical: 0, iodef: 'mailto:pki@example.com'}, {critical: 128, issue: 'pki.example.com'}]`).
* @since v15.0.0
* @since v15.0.0, v14.17.0
*/
export function resolveCaa(hostname: string, callback: (err: NodeJS.ErrnoException | null, records: CaaRecord[]) => void): void;
export namespace resolveCaa {
@@ -530,14 +533,16 @@ declare module 'dns' {
*/
export function getServers(): string[];
/**
* Set the default value of `verbatim` in {@link lookup}. The value could be:
* - `ipv4first`: sets default `verbatim` `false`.
* - `verbatim`: sets default `verbatim` `true`.
* Set the default value of `verbatim` in {@link lookup} and `dnsPromises.lookup()`. The value could be:
*
* The default is `ipv4first` and {@link setDefaultResultOrder} have higher priority than `--dns-result-order`.
* When using worker threads, {@link setDefaultResultOrder} from the main thread won't affect the default dns orders in workers.
* @since v14.18.0
* @param order must be 'ipv4first' or 'verbatim'.
* * `ipv4first`: sets default `verbatim` `false`.
* * `verbatim`: sets default `verbatim` `true`.
*
* The default is `ipv4first` and {@link setDefaultResultOrder} have higher
* priority than `--dns-result-order`. When using `worker threads`,{@link setDefaultResultOrder} from the main thread won't affect the default
* dns orders in workers.
* @since v16.4.0, v14.18.0
* @param order must be `'ipv4first'` or `'verbatim'`.
*/
export function setDefaultResultOrder(order: 'ipv4first' | 'verbatim'): void;
// Error codes
@@ -643,7 +648,7 @@ declare module 'dns' {
* The resolver will use the v4 local address when making requests to IPv4 DNS
* servers, and the v6 local address when making requests to IPv6 DNS servers.
* The `rrtype` of resolution requests has no impact on the local address used.
* @since v15.1.0
* @since v15.1.0, v14.17.0
* @param [ipv4='0.0.0.0'] A string representation of an IPv4 address.
* @param [ipv6='::0'] A string representation of an IPv6 address.
*/

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 */
/**
* The `dns.promises` API provides an alternative set of asynchronous DNS methods
@@ -192,7 +192,7 @@ declare module 'dns/promises' {
* Uses the DNS protocol to resolve `CAA` records for the `hostname`. On success,
* the `Promise` is resolved with an array of objects containing available
* certification authority authorization records available for the `hostname`(e.g. `[{critical: 0, iodef: 'mailto:pki@example.com'},{critical: 128, issue: 'pki.example.com'}]`).
* @since v15.0.0
* @since v15.0.0, v14.17.0
*/
function resolveCaa(hostname: string): Promise<CaaRecord[]>;
/**
@@ -335,14 +335,16 @@ declare module 'dns/promises' {
*/
function setServers(servers: ReadonlyArray<string>): void;
/**
* Set the default value of `verbatim` in {@link lookup}. The value could be:
* - `ipv4first`: sets default `verbatim` `false`.
* - `verbatim`: sets default `verbatim` `true`.
* Set the default value of `verbatim` in `dns.lookup()` and `dnsPromises.lookup()`. The value could be:
*
* The default is `ipv4first` and {@link setDefaultResultOrder} have higher priority than `--dns-result-order`.
* When using worker threads, {@link setDefaultResultOrder} from the main thread won't affect the default dns orders in workers.
* @since v14.18.0
* @param order must be 'ipv4first' or 'verbatim'.
* * `ipv4first`: sets default `verbatim` `false`.
* * `verbatim`: sets default `verbatim` `true`.
*
* The default is `ipv4first` and `dnsPromises.setDefaultResultOrder()` have
* higher priority than `--dns-result-order`. When using `worker threads`,`dnsPromises.setDefaultResultOrder()` from the main thread won't affect the
* default dns orders in workers.
* @since v16.4.0, v14.18.0
* @param order must be `'ipv4first'` or `'verbatim'`.
*/
function setDefaultResultOrder(order: 'ipv4first' | 'verbatim'): void;
class Resolver {

View File

@@ -0,0 +1,129 @@
/* NOTE: Do not edit directly! This file is generated using `npm run update-types` in https://github.com/node-red/nr-monaco-build */
export {}; // Don't export anything!
//// DOM-like Events
// NB: The Event / EventTarget / EventListener implementations below were copied
// from lib.dom.d.ts, then edited to reflect Node's documentation at
// https://nodejs.org/api/events.html#class-eventtarget.
// Please read that link to understand important implementation differences.
// This conditional type will be the existing global Event in a browser, or
// the copy below in a Node environment.
type __Event = typeof globalThis extends { onmessage: any, Event: any }
? {}
: {
/** This is not used in Node.js and is provided purely for completeness. */
readonly bubbles: boolean;
/** Alias for event.stopPropagation(). This is not used in Node.js and is provided purely for completeness. */
cancelBubble: () => void;
/** True if the event was created with the cancelable option */
readonly cancelable: boolean;
/** This is not used in Node.js and is provided purely for completeness. */
readonly composed: boolean;
/** Returns an array containing the current EventTarget as the only entry or empty if the event is not being dispatched. This is not used in Node.js and is provided purely for completeness. */
composedPath(): [EventTarget?]
/** Alias for event.target. */
readonly currentTarget: EventTarget | null;
/** Is true if cancelable is true and event.preventDefault() has been called. */
readonly defaultPrevented: boolean;
/** This is not used in Node.js and is provided purely for completeness. */
readonly eventPhase: 0 | 2;
/** The `AbortSignal` "abort" event is emitted with `isTrusted` set to `true`. The value is `false` in all other cases. */
readonly isTrusted: boolean;
/** Sets the `defaultPrevented` property to `true` if `cancelable` is `true`. */
preventDefault(): void;
/** This is not used in Node.js and is provided purely for completeness. */
returnValue: boolean;
/** Alias for event.target. */
readonly srcElement: EventTarget | null;
/** Stops the invocation of event listeners after the current one completes. */
stopImmediatePropagation(): void;
/** This is not used in Node.js and is provided purely for completeness. */
stopPropagation(): void;
/** The `EventTarget` dispatching the event */
readonly target: EventTarget | null;
/** The millisecond timestamp when the Event object was created. */
readonly timeStamp: number;
/** Returns the type of event, e.g. "click", "hashchange", or "submit". */
readonly type: string;
};
// See comment above explaining conditional type
type __EventTarget = typeof globalThis extends { onmessage: any, EventTarget: any }
? {}
: {
/**
* Adds a new handler for the `type` event. Any given `listener` is added only once per `type` and per `capture` option value.
*
* If the `once` option is true, the `listener` is removed after the next time a `type` event is dispatched.
*
* The `capture` option is not used by Node.js in any functional way other than tracking registered event listeners per the `EventTarget` specification.
* Specifically, the `capture` option is used as part of the key when registering a `listener`.
* Any individual `listener` may be added once with `capture = false`, and once with `capture = true`.
*/
addEventListener(
type: string,
listener: EventListener | EventListenerObject,
options?: AddEventListenerOptions | boolean,
): void;
/** Dispatches a synthetic event event to target and returns true if either event's cancelable attribute value is false or its preventDefault() method was not invoked, and false otherwise. */
dispatchEvent(event: Event): boolean;
/** Removes the event listener in target's event listener list with the same type, callback, and options. */
removeEventListener(
type: string,
listener: EventListener | EventListenerObject,
options?: EventListenerOptions | boolean,
): void;
};
interface EventInit {
bubbles?: boolean;
cancelable?: boolean;
composed?: boolean;
}
interface EventListenerOptions {
/** Not directly used by Node.js. Added for API completeness. Default: `false`. */
capture?: boolean;
}
interface AddEventListenerOptions extends EventListenerOptions {
/** When `true`, the listener is automatically removed when it is first invoked. Default: `false`. */
once?: boolean;
/** When `true`, serves as a hint that the listener will not call the `Event` object's `preventDefault()` method. Default: false. */
passive?: boolean;
}
interface EventListener {
(evt: Event): void;
}
interface EventListenerObject {
handleEvent(object: Event): void;
}
import {} from 'events'; // Make this an ambient declaration
declare global {
/** An event which takes place in the DOM. */
interface Event extends __Event {}
var Event: typeof globalThis extends { onmessage: any, Event: infer T }
? T
: {
prototype: __Event;
new (type: string, eventInitDict?: EventInit): __Event;
};
/**
* EventTarget is a DOM interface implemented by objects that can
* receive events and may have listeners for them.
*/
interface EventTarget extends __EventTarget {}
var EventTarget: typeof globalThis extends { onmessage: any, EventTarget: infer T }
? T
: {
prototype: __EventTarget;
new (): __EventTarget;
};
}

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 */
/**
* **This module is pending deprecation.** Once a replacement API has been
@@ -15,7 +15,7 @@
* will be notified, rather than losing the context of the error in the`process.on('uncaughtException')` handler, or causing the program to
* exit immediately with an error code.
* @deprecated Since v1.4.2 - Deprecated
* @see [source](https://github.com/nodejs/node/blob/v16.9.0/lib/domain.js)
* @see [source](https://github.com/nodejs/node/blob/v18.0.0/lib/domain.js)
*/
declare module 'domain' {
import EventEmitter = require('node:events');

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 */
/**
* Much of the Node.js core API is built around an idiomatic asynchronous
@@ -35,19 +35,56 @@
* });
* myEmitter.emit('event');
* ```
* @see [source](https://github.com/nodejs/node/blob/v16.9.0/lib/events.js)
* @see [source](https://github.com/nodejs/node/blob/v18.0.0/lib/events.js)
*/
declare module 'events' {
// NOTE: This class is in the docs but is **not actually exported** by Node.
// If https://github.com/nodejs/node/issues/39903 gets resolved and Node
// actually starts exporting the class, uncomment below.
// import { EventListener, EventListenerObject } from '__dom-events';
// /** The NodeEventTarget is a Node.js-specific extension to EventTarget that emulates a subset of the EventEmitter API. */
// interface NodeEventTarget extends EventTarget {
// /**
// * Node.js-specific extension to the `EventTarget` class that emulates the equivalent `EventEmitter` API.
// * The only difference between `addListener()` and `addEventListener()` is that addListener() will return a reference to the EventTarget.
// */
// addListener(type: string, listener: EventListener | EventListenerObject, options?: { once: boolean }): this;
// /** Node.js-specific extension to the `EventTarget` class that returns an array of event `type` names for which event listeners are registered. */
// eventNames(): string[];
// /** Node.js-specific extension to the `EventTarget` class that returns the number of event listeners registered for the `type`. */
// listenerCount(type: string): number;
// /** Node.js-specific alias for `eventTarget.removeListener()`. */
// off(type: string, listener: EventListener | EventListenerObject): this;
// /** Node.js-specific alias for `eventTarget.addListener()`. */
// on(type: string, listener: EventListener | EventListenerObject, options?: { once: boolean }): this;
// /** Node.js-specific extension to the `EventTarget` class that adds a `once` listener for the given event `type`. This is equivalent to calling `on` with the `once` option set to `true`. */
// once(type: string, listener: EventListener | EventListenerObject): this;
// /**
// * Node.js-specific extension to the `EventTarget` class.
// * If `type` is specified, removes all registered listeners for `type`,
// * otherwise removes all registered listeners.
// */
// removeAllListeners(type: string): this;
// /**
// * Node.js-specific extension to the `EventTarget` class that removes the listener for the given `type`.
// * The only difference between `removeListener()` and `removeEventListener()` is that `removeListener()` will return a reference to the `EventTarget`.
// */
// removeListener(type: string, listener: EventListener | EventListenerObject): this;
// }
interface EventEmitterOptions {
/**
* Enables automatic capturing of promise rejection.
*/
captureRejections?: boolean | undefined;
}
interface NodeEventTarget {
// Any EventTarget with a Node-style `once` function
interface _NodeEventTarget {
once(eventName: string | symbol, listener: (...args: any[]) => void): this;
}
interface DOMEventTarget {
// Any EventTarget with a DOM-style `addEventListener`
interface _DOMEventTarget {
addEventListener(
eventName: string,
listener: (...args: any[]) => void,
@@ -157,8 +194,8 @@ declare module 'events' {
* ```
* @since v11.13.0, v10.16.0
*/
static once(emitter: NodeEventTarget, eventName: string | symbol, options?: StaticEventEmitterOptions): Promise<any[]>;
static once(emitter: DOMEventTarget, eventName: string, options?: StaticEventEmitterOptions): Promise<any[]>;
static once(emitter: _NodeEventTarget, eventName: string | symbol, options?: StaticEventEmitterOptions): Promise<any[]>;
static once(emitter: _DOMEventTarget, eventName: string, options?: StaticEventEmitterOptions): Promise<any[]>;
/**
* ```js
* const { on, EventEmitter } = require('events');
@@ -260,9 +297,9 @@ declare module 'events' {
* getEventListeners(et, 'foo'); // [listener]
* }
* ```
* @since v15.2.0
* @since v15.2.0, v14.17.0
*/
static getEventListeners(emitter: DOMEventTarget | NodeJS.EventEmitter, name: string | symbol): Function[];
static getEventListeners(emitter: _DOMEventTarget | NodeJS.EventEmitter, name: string | symbol): Function[];
/**
* ```js
* const {
@@ -280,7 +317,7 @@ declare module 'events' {
* @param eventsTargets Zero or more {EventTarget} or {EventEmitter} instances. If none are specified, `n` is set as the default max for all newly created {EventTarget} and {EventEmitter}
* objects.
*/
static setMaxListeners(n?: number, ...eventTargets: Array<DOMEventTarget | NodeJS.EventEmitter>): void;
static setMaxListeners(n?: number, ...eventTargets: Array<_DOMEventTarget | NodeJS.EventEmitter>): void;
/**
* This symbol shall be used to install a listener for only monitoring `'error'`
* events. Listeners installed using this symbol are called before the regular
@@ -396,8 +433,8 @@ declare module 'events' {
* called multiple times to remove each instance.
*
* Once an event is emitted, all listeners attached to it at the
* time of emitting are called in order. This implies that any`removeListener()` or `removeAllListeners()` calls _after_ emitting and_before_ the last listener finishes execution will
* not remove them from`emit()` in progress. Subsequent events behave as expected.
* time of emitting are called in order. This implies that any`removeListener()` or `removeAllListeners()` calls _after_ emitting and _before_ the last listener finishes execution
* will not remove them from`emit()` in progress. Subsequent events behave as expected.
*
* ```js
* const myEmitter = new MyEmitter();
@@ -599,7 +636,7 @@ declare module 'events' {
*/
prependListener(eventName: string | symbol, listener: (...args: any[]) => void): this;
/**
* Adds a **one-time**`listener` function for the event named `eventName` to the_beginning_ of the listeners array. The next time `eventName` is triggered, this
* Adds a **one-time**`listener` function for the event named `eventName` to the _beginning_ of the listeners array. The next time `eventName` is triggered, this
* listener is removed, and then invoked.
*
* ```js

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 */
/**
* The `fs` module enables interacting with the file system in a
@@ -19,7 +19,7 @@
*
* All file system operations have synchronous, callback, and promise-based
* forms, and are accessible using both CommonJS syntax and ES6 Modules (ESM).
* @see [source](https://github.com/nodejs/node/blob/v16.9.0/lib/fs.js)
* @see [source](https://github.com/nodejs/node/blob/v18.0.0/lib/fs.js)
*/
declare module 'fs' {
import * as stream from 'node:stream';
@@ -271,18 +271,22 @@ declare module 'fs' {
*/
export interface StatWatcher extends EventEmitter {
/**
* When called, requests that the Node.js event loop _not_ exit so long as the `fs.StatWatcher` is active. Calling `watcher.ref()` multiple times will have
* no effect.
*
* By default, all `fs.StatWatcher` objects are "ref'ed", making it normally
* unnecessary to call `watcher.ref()` unless `watcher.unref()` had been
* called previously.
* @since v14.3.0, v12.20.0
* When called, requests that the Node.js event loop not exit so long as the `fs.StatWatcher` is active.
* Calling `watcher.ref()` multiple times will have no effect.
* By default, all `fs.StatWatcher`` objects are "ref'ed", making it normally unnecessary to call `watcher.ref()`
* unless `watcher.unref()` had been called previously.
*/
ref(): this;
/**
* When called, the active `fs.StatWatcher` object will not require the Node.js
* event loop to remain active. If there is no other activity keeping the
* event loop running, the process may exit before the `fs.StatWatcher` object's
* callback is invoked. Calling `watcher.unref()` multiple times will have
* no effect.
* @since v14.3.0, v12.20.0
* When called, the active `fs.StatWatcher`` object will not require the Node.js event loop to remain active.
* If there is no other activity keeping the event loop running, the process may exit before the `fs.StatWatcher`` object's callback is invoked.
* `Calling watcher.unref()` multiple times will have no effect.
*/
unref(): this;
}
@@ -1017,8 +1021,10 @@ declare module 'fs' {
function __promisify__(fd: number, options?: StatOptions): Promise<Stats | BigIntStats>;
}
/**
* Synchronous fstat(2) - Get file status.
* @param fd A file descriptor.
* Retrieves the `fs.Stats` for the file descriptor.
*
* See the POSIX [`fstat(2)`](http://man7.org/linux/man-pages/man2/fstat.2.html) documentation for more detail.
* @since v0.1.95
*/
export function fstatSync(
fd: number,
@@ -1033,7 +1039,6 @@ declare module 'fs' {
}
): BigIntStats;
export function fstatSync(fd: number, options?: StatOptions): Stats | BigIntStats;
/**
* Retrieves the `fs.Stats` for the symbolic link referred to by the path.
* The callback gets two arguments `(err, stats)` where `stats` is a `fs.Stats` object. `lstat()` is identical to `stat()`, except that if `path` is a symbolic
@@ -1121,15 +1126,15 @@ declare module 'fs' {
* ```js
* import { symlink } from 'fs';
*
* symlink('./mew', './example/mewtwo', callback);
* symlink('./mew', './mewtwo', callback);
* ```
*
* The above example creates a symbolic link `mewtwo` in the `example` which points
* to `mew` in the same directory:
* The above example creates a symbolic link `mewtwo` which points to `mew` in the
* same directory:
*
* ```bash
* $ tree example/
* example/
* $ tree .
* .
* ├── mew
* └── mewtwo -> ./mew
* ```
@@ -1393,7 +1398,7 @@ declare module 'fs' {
* Use `fs.rm(path, { recursive: true, force: true })` instead.
*
* If `true`, perform a recursive directory removal. In
* recursive mode soperations are retried on failure.
* recursive mode, operations are retried on failure.
* @default false
*/
recursive?: boolean | undefined;
@@ -1999,8 +2004,8 @@ declare module 'fs' {
export function open(path: PathLike, flags: OpenMode | undefined, mode: Mode | undefined | null, callback: (err: NodeJS.ErrnoException | null, fd: number) => void): void;
/**
* Asynchronous open(2) - open and possibly create a file. If the file is created, its mode will be `0o666`.
* @param [flags='r'] See `support of file system `flags``.
* @param path A path to a file. If a URL is provided, it must use the `file:` protocol.
* @param [flags='r'] See `support of file system `flags``.
*/
export function open(path: PathLike, flags: OpenMode | undefined, callback: (err: NodeJS.ErrnoException | null, fd: number) => void): void;
/**
@@ -2008,6 +2013,7 @@ declare module 'fs' {
* @param path A path to a file. If a URL is provided, it must use the `file:` protocol.
*/
export function open(path: PathLike, callback: (err: NodeJS.ErrnoException | null, fd: number) => void): void;
export namespace open {
/**
* Asynchronous open(2) - open and possibly create a file.
@@ -2096,8 +2102,7 @@ declare module 'fs' {
*/
export function fsyncSync(fd: number): void;
/**
* Write `buffer` to the file specified by `fd`. If `buffer` is a normal object, it
* must have an own `toString` function property.
* Write `buffer` to the file specified by `fd`.
*
* `offset` determines the part of the buffer to be written, and `length` is
* an integer specifying the number of bytes to write.
@@ -2220,8 +2225,6 @@ declare module 'fs' {
}>;
}
/**
* If `buffer` is a plain object, it must have an own (not inherited) `toString`function property.
*
* For detailed information, see the documentation of the asynchronous version of
* this API: {@link write}.
* @since v0.1.21
@@ -2237,6 +2240,23 @@ declare module 'fs' {
*/
export function writeSync(fd: number, string: string, position?: number | null, encoding?: BufferEncoding | null): number;
export type ReadPosition = number | bigint;
export interface ReadSyncOptions {
/**
* @default 0
*/
offset?: number | undefined;
/**
* @default `length of buffer`
*/
length?: number | undefined;
/**
* @default null
*/
position?: ReadPosition | null | undefined;
}
export interface ReadAsyncOptions<TBuffer extends NodeJS.ArrayBufferView> extends ReadSyncOptions {
buffer?: TBuffer;
}
/**
* Read data from the file specified by `fd`.
*
@@ -2262,6 +2282,21 @@ declare module 'fs' {
position: ReadPosition | null,
callback: (err: NodeJS.ErrnoException | null, bytesRead: number, buffer: TBuffer) => void
): void;
/**
* Similar to the above `fs.read` function, this version takes an optional `options` object.
* If not otherwise specified in an `options` object,
* `buffer` defaults to `Buffer.alloc(16384)`,
* `offset` defaults to `0`,
* `length` defaults to `buffer.byteLength`, `- offset` as of Node 17.6.0
* `position` defaults to `null`
* @since v12.17.0, 13.11.0
*/
export function read<TBuffer extends NodeJS.ArrayBufferView>(
fd: number,
options: ReadAsyncOptions<TBuffer>,
callback: (err: NodeJS.ErrnoException | null, bytesRead: number, buffer: TBuffer) => void
): void;
export function read(fd: number, callback: (err: NodeJS.ErrnoException | null, bytesRead: number, buffer: NodeJS.ArrayBufferView) => void): void;
export namespace read {
/**
* @param fd A file descriptor.
@@ -2280,20 +2315,17 @@ declare module 'fs' {
bytesRead: number;
buffer: TBuffer;
}>;
}
export interface ReadSyncOptions {
/**
* @default 0
*/
offset?: number | undefined;
/**
* @default `length of buffer`
*/
length?: number | undefined;
/**
* @default null
*/
position?: ReadPosition | null | undefined;
function __promisify__<TBuffer extends NodeJS.ArrayBufferView>(
fd: number,
options: ReadAsyncOptions<TBuffer>
): Promise<{
bytesRead: number;
buffer: TBuffer;
}>;
function __promisify__(fd: number): Promise<{
bytesRead: number;
buffer: NodeJS.ArrayBufferView;
}>;
}
/**
* Returns the number of `bytesRead`.
@@ -2558,8 +2590,6 @@ declare module 'fs' {
*
* The `mode` option only affects the newly created file. See {@link open} for more details.
*
* If `data` is a plain object, it must have an own (not inherited) `toString`function property.
*
* ```js
* import { writeFile } from 'fs';
* import { Buffer } from 'buffer';
@@ -2636,8 +2666,6 @@ declare module 'fs' {
/**
* Returns `undefined`.
*
* If `data` is a plain object, it must have an own (not inherited) `toString`function property.
*
* The `mode` option only affects the newly created file. See {@link open} for more details.
*
* For detailed information, see the documentation of the asynchronous version of
@@ -2821,6 +2849,52 @@ declare module 'fs' {
persistent?: boolean | undefined;
interval?: number | undefined;
}
/**
* Watch for changes on `filename`. The callback `listener` will be called each
* time the file is accessed.
*
* The `options` argument may be omitted. If provided, it should be an object. The`options` object may contain a boolean named `persistent` that indicates
* whether the process should continue to run as long as files are being watched.
* The `options` object may specify an `interval` property indicating how often the
* target should be polled in milliseconds.
*
* The `listener` gets two arguments the current stat object and the previous
* stat object:
*
* ```js
* import { watchFile } from 'fs';
*
* watchFile('message.text', (curr, prev) => {
* console.log(`the current mtime is: ${curr.mtime}`);
* console.log(`the previous mtime was: ${prev.mtime}`);
* });
* ```
*
* These stat objects are instances of `fs.Stat`. If the `bigint` option is `true`,
* the numeric values in these objects are specified as `BigInt`s.
*
* To be notified when the file was modified, not just accessed, it is necessary
* to compare `curr.mtimeMs` and `prev.mtimeMs`.
*
* When an `fs.watchFile` operation results in an `ENOENT` error, it
* will invoke the listener once, with all the fields zeroed (or, for dates, the
* Unix Epoch). If the file is created later on, the listener will be called
* again, with the latest stat objects. This is a change in functionality since
* v0.10.
*
* Using {@link watch} is more efficient than `fs.watchFile` and`fs.unwatchFile`. `fs.watch` should be used instead of `fs.watchFile` and`fs.unwatchFile` when possible.
*
* When a file being watched by `fs.watchFile()` disappears and reappears,
* then the contents of `previous` in the second callback event (the file's
* reappearance) will be the same as the contents of `previous` in the first
* callback event (its disappearance).
*
* This happens when:
*
* * the file is deleted, followed by a restore
* * the file is renamed and then renamed a second time back to its original name
* @since v0.1.31
*/
export function watchFile(
filename: PathLike,
options:
@@ -3189,9 +3263,9 @@ declare module 'fs' {
/**
* Tests a user's permissions for the file or directory specified by `path`.
* The `mode` argument is an optional integer that specifies the accessibility
* checks to be performed. Check `File access constants` for possible values
* of `mode`. It is possible to create a mask consisting of the bitwise OR of
* two or more values (e.g. `fs.constants.W_OK | fs.constants.R_OK`).
* checks to be performed. `mode` should be either the value `fs.constants.F_OK`or a mask consisting of the bitwise OR of any of `fs.constants.R_OK`,`fs.constants.W_OK`, and `fs.constants.X_OK`
* (e.g.`fs.constants.W_OK | fs.constants.R_OK`). Check `File access constants` for
* possible values of `mode`.
*
* The final argument, `callback`, is a callback function that is invoked with
* a possible error argument. If any of the accessibility checks fail, the error
@@ -3217,14 +3291,9 @@ declare module 'fs' {
* console.log(`${file} ${err ? 'is not writable' : 'is writable'}`);
* });
*
* // Check if the file exists in the current directory, and if it is writable.
* access(file, constants.F_OK | constants.W_OK, (err) => {
* if (err) {
* console.error(
* `${file} ${err.code === 'ENOENT' ? 'does not exist' : 'is read-only'}`);
* } else {
* console.log(`${file} exists, and it is writable`);
* }
* // Check if the file is readable and writable.
* access(file, constants.R_OK | constants.W_OK, (err) => {
* console.log(`${file} ${err ? 'is not' : 'is'} readable and writable`);
* });
* ```
*
@@ -3368,10 +3437,9 @@ declare module 'fs' {
/**
* Synchronously tests a user's permissions for the file or directory specified
* by `path`. The `mode` argument is an optional integer that specifies the
* accessibility checks to be performed. Check `File access constants` for
* possible values of `mode`. It is possible to create a mask consisting of
* the bitwise OR of two or more values
* (e.g. `fs.constants.W_OK | fs.constants.R_OK`).
* accessibility checks to be performed. `mode` should be either the value`fs.constants.F_OK` or a mask consisting of the bitwise OR of any of`fs.constants.R_OK`, `fs.constants.W_OK`, and
* `fs.constants.X_OK` (e.g.`fs.constants.W_OK | fs.constants.R_OK`). Check `File access constants` for
* possible values of `mode`.
*
* If any of the accessibility checks fail, an `Error` will be thrown. Otherwise,
* the method will return `undefined`.
@@ -3474,9 +3542,9 @@ declare module 'fs' {
/**
* `options` may also include a `start` option to allow writing data at some
* position past the beginning of the file, allowed values are in the
* \[0, [`Number.MAX_SAFE_INTEGER`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/MAX_SAFE_INTEGER)\] range. Modifying a file rather than replacing
* it may require the `flags` option to be set to `r+` rather than the default `w`.
* The `encoding` can be any one of those accepted by `Buffer`.
* \[0, [`Number.MAX_SAFE_INTEGER`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/MAX_SAFE_INTEGER)\] range. Modifying a file rather than
* replacing it may require the `flags` option to be set to `r+` rather than the
* default `w`. The `encoding` can be any one of those accepted by `Buffer`.
*
* If `autoClose` is set to true (default behavior) on `'error'` or `'finish'`the file descriptor will be closed automatically. If `autoClose` is false,
* then the file descriptor won't be closed, even if there's an error.
@@ -3756,6 +3824,11 @@ declare module 'fs' {
* @default false
*/
recursive?: boolean;
/**
* When true, path resolution for symlinks will be skipped
* @default false
*/
verbatimSymlinks?: boolean;
}
export interface CopyOptions extends CopyOptionsBase {
/**

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 */
/**
* The `fs/promises` API provides asynchronous file system methods that return
@@ -14,6 +14,7 @@
declare module 'fs/promises' {
import { Abortable } from 'node:events';
import { Stream } from 'node:stream';
import { ReadableStream } from 'node:stream/web';
import {
BigIntStats,
BufferEncodingOption,
@@ -33,11 +34,14 @@ declare module 'fs/promises' {
RmOptions,
StatOptions,
Stats,
TimeLike,
WatchEventType,
WatchOptions,
WriteStream,
WriteVResult,
} from 'node:fs';
import { Interface as ReadlineInterface } from 'node:readline';
interface FileChangeInfo<T extends string | Buffer> {
eventType: WatchEventType;
filename: T;
@@ -46,11 +50,11 @@ declare module 'fs/promises' {
mode?: Mode | undefined;
flag?: OpenMode | undefined;
}
interface FileReadResult<T extends ArrayBufferView> {
interface FileReadResult<T extends NodeJS.ArrayBufferView> {
bytesRead: number;
buffer: T;
}
interface FileReadOptions<T extends ArrayBufferView = Buffer> {
interface FileReadOptions<T extends NodeJS.ArrayBufferView = Buffer> {
/**
* @default `Buffer.alloc(0xffff)`
*/
@@ -167,9 +171,9 @@ declare module 'fs/promises' {
/**
* `options` may also include a `start` option to allow writing data at some
* position past the beginning of the file, allowed values are in the
* \[0, [`Number.MAX_SAFE_INTEGER`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/MAX_SAFE_INTEGER)\] range. Modifying a file rather than replacing
* it may require the `flags` `open` option to be set to `r+` rather than the
* default `r`. The `encoding` can be any one of those accepted by `Buffer`.
* \[0, [`Number.MAX_SAFE_INTEGER`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/MAX_SAFE_INTEGER)\] range. Modifying a file rather than
* replacing it may require the `flags` `open` option to be set to `r+` rather than
* the default `r`. The `encoding` can be any one of those accepted by `Buffer`.
*
* If `autoClose` is set to true (default behavior) on `'error'` or `'finish'`the file descriptor will be closed automatically. If `autoClose` is false,
* then the file descriptor won't be closed, even if there's an error.
@@ -211,8 +215,31 @@ declare module 'fs/promises' {
* integer, the current file position will remain unchanged.
* @return Fulfills upon success with an object with two properties:
*/
read<T extends ArrayBufferView>(buffer: T, offset?: number | null, length?: number | null, position?: number | null): Promise<FileReadResult<T>>;
read<T extends ArrayBufferView = Buffer>(options?: FileReadOptions<T>): Promise<FileReadResult<T>>;
read<T extends NodeJS.ArrayBufferView>(buffer: T, offset?: number | null, length?: number | null, position?: number | null): Promise<FileReadResult<T>>;
read<T extends NodeJS.ArrayBufferView = Buffer>(options?: FileReadOptions<T>): Promise<FileReadResult<T>>;
/**
* Returns a `ReadableStream` that may be used to read the files data.
*
* An error will be thrown if this method is called more than once or is called after the `FileHandle` is closed
* or closing.
*
* ```js
* import { open } from 'node:fs/promises';
*
* const file = await open('./some/file/to/read');
*
* for await (const chunk of file.readableWebStream())
* console.log(chunk);
*
* await file.close();
* ```
*
* While the `ReadableStream` will read the file to completion, it will not close the `FileHandle` automatically. User code must still call the `fileHandle.close()` method.
*
* @since v17.0.0
* @experimental
*/
readableWebStream(): ReadableStream;
/**
* Asynchronously reads the entire contents of a file.
*
@@ -261,6 +288,23 @@ declare module 'fs/promises' {
| BufferEncoding
| null
): Promise<string | Buffer>;
/**
* Convenience method to create a `readline` interface and stream over the file. For example:
*
* ```js
* import { open } from 'node:fs/promises';
*
* const file = await open('./some/file/to/read');
*
* for await (const line of file.readLines()) {
* console.log(line);
* }
* ```
*
* @since v18.11.0
* @param options See `filehandle.createReadStream()` for the options.
*/
readLines(options?: CreateReadStreamOptions): ReadlineInterface;
/**
* @since v10.0.0
* @return Fulfills with an {fs.Stats} for the file.
@@ -309,13 +353,12 @@ declare module 'fs/promises' {
* Change the file system timestamps of the object referenced by the `FileHandle` then resolves the promise with no arguments upon success.
* @since v10.0.0
*/
utimes(atime: string | number | Date, mtime: string | number | Date): Promise<void>;
utimes(atime: TimeLike, mtime: TimeLike): Promise<void>;
/**
* Asynchronously writes data to a file, replacing the file if it already exists.`data` can be a string, a buffer, an
* [AsyncIterable](https://tc39.github.io/ecma262/#sec-asynciterable-interface) or
* [Iterable](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols#The_iterable_protocol) object, or an
* object with an own `toString` function
* property. The promise is resolved with no arguments upon success.
* [Iterable](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols#The_iterable_protocol) object.
* The promise is resolved with no arguments upon success.
*
* If `options` is a string, then it specifies the `encoding`.
*
@@ -333,20 +376,18 @@ declare module 'fs/promises' {
/**
* Write `buffer` to the file.
*
* If `buffer` is a plain object, it must have an own (not inherited) `toString`function property.
*
* The promise is resolved with an object containing two properties:
*
* It is unsafe to use `filehandle.write()` multiple times on the same file
* without waiting for the promise to be resolved (or rejected). For this
* scenario, use `fs.createWriteStream()`.
* scenario, use `filehandle.createWriteStream()`.
*
* On Linux, positional writes do not work when the file is opened in append mode.
* The kernel ignores the position argument and always appends the data to
* the end of the file.
* @since v10.0.0
* @param [offset=0] The start position from within `buffer` where the data to write begins.
* @param [length=buffer.byteLength] The number of bytes from `buffer` to write.
* @param [length=buffer.byteLength - offset] The number of bytes from `buffer` to write.
* @param position The offset from the beginning of the file where the data from `buffer` should be written. If `position` is not a `number`, the data will be written at the current position.
* See the POSIX pwrite(2) documentation for more detail.
*/
@@ -411,12 +452,13 @@ declare module 'fs/promises' {
}
const constants: typeof fsConstants;
/**
* Tests a user's permissions for the file or directory specified by `path`.
* The `mode` argument is an optional integer that specifies the accessibility
* checks to be performed. Check `File access constants` for possible values
* of `mode`. It is possible to create a mask consisting of the bitwise OR of
* two or more values (e.g. `fs.constants.W_OK | fs.constants.R_OK`).
* checks to be performed. `mode` should be either the value `fs.constants.F_OK`or a mask consisting of the bitwise OR of any of `fs.constants.R_OK`,`fs.constants.W_OK`, and `fs.constants.X_OK`
* (e.g.`fs.constants.W_OK | fs.constants.R_OK`). Check `File access constants` for
* possible values of `mode`.
*
* If the accessibility check is successful, the promise is resolved with no
* value. If any of the accessibility checks fail, the promise is rejected
@@ -747,7 +789,7 @@ declare module 'fs/promises' {
* @since v14.5.0, v12.19.0
* @return Fulfills with `undefined` upon success.
*/
function lutimes(path: PathLike, atime: string | number | Date, mtime: string | number | Date): Promise<void>;
function lutimes(path: PathLike, atime: TimeLike, mtime: TimeLike): Promise<void>;
/**
* Changes the ownership of a file.
* @since v10.0.0
@@ -765,7 +807,7 @@ declare module 'fs/promises' {
* @since v10.0.0
* @return Fulfills with `undefined` upon success.
*/
function utimes(path: PathLike, atime: string | number | Date, mtime: string | number | Date): Promise<void>;
function utimes(path: PathLike, atime: TimeLike, mtime: TimeLike): Promise<void>;
/**
* Determines the actual location of `path` using the same semantics as the`fs.realpath.native()` function.
*
@@ -836,7 +878,9 @@ declare module 'fs/promises' {
*/
function mkdtemp(prefix: string, options?: ObjectEncodingOptions | BufferEncoding | null): Promise<string | Buffer>;
/**
* Asynchronously writes data to a file, replacing the file if it already exists.`data` can be a string, a `Buffer`, or, an object with an own (not inherited)`toString` function property.
* Asynchronously writes data to a file, replacing the file if it already exists.`data` can be a string, a buffer, an
* [AsyncIterable](https://tc39.github.io/ecma262/#sec-asynciterable-interface) or
* [Iterable](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols#The_iterable_protocol) object.
*
* The `encoding` option is ignored if `data` is a buffer.
*
@@ -851,7 +895,7 @@ declare module 'fs/promises' {
*
* Similarly to `fsPromises.readFile` \- `fsPromises.writeFile` is a convenience
* method that performs multiple `write` calls internally to write the buffer
* passed to it. For performance sensitive code consider using `fs.createWriteStream()`.
* passed to it. For performance sensitive code consider using `fs.createWriteStream()` or `filehandle.createWriteStream()`.
*
* It is possible to use an `AbortSignal` to cancel an `fsPromises.writeFile()`.
* Cancelation is "best effort", and some amount of data is likely still
@@ -1049,7 +1093,7 @@ declare module 'fs/promises' {
* disappears in the directory.
*
* All the `caveats` for `fs.watch()` also apply to `fsPromises.watch()`.
* @since v15.9.0
* @since v15.9.0, v14.18.0
* @return of objects with the properties:
*/
function watch(

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 */
// Declare "static" methods in Error
interface ErrorConstructor {
@@ -56,28 +56,32 @@ interface AbortController {
/**
* Invoking this method will set this object's AbortSignal's aborted flag and signal to any observers that the associated activity is to be aborted.
*/
abort(reason?: any): void;
abort(): void;
}
/** A signal object that allows you to communicate with a DOM request (such as a Fetch) and abort it if required via an AbortController object. */
interface AbortSignal {
interface AbortSignal extends EventTarget {
/**
* Returns true if this AbortSignal's AbortController has signaled to abort, and false otherwise.
*/
readonly aborted: boolean;
}
declare var AbortController: {
prototype: AbortController;
new(): AbortController;
};
declare var AbortController: typeof globalThis extends {onmessage: any; AbortController: infer T}
? T
: {
prototype: AbortController;
new(): AbortController;
};
declare var AbortSignal: {
prototype: AbortSignal;
new(): AbortSignal;
abort(reason?: any): AbortSignal;
timeout(milliseconds: number): AbortSignal;
};
declare var AbortSignal: typeof globalThis extends {onmessage: any; AbortSignal: infer T}
? T
: {
prototype: AbortSignal;
new(): AbortSignal;
abort(reason?: any): AbortSignal;
timeout(milliseconds: number): AbortSignal;
};
//#endregion borrowed
//#region ArrayLike.at()
@@ -105,6 +109,16 @@ interface BigInt64Array extends RelativeIndexable<bigint> {}
interface BigUint64Array extends RelativeIndexable<bigint> {}
//#endregion ArrayLike.at() end
/**
* @since v17.0.0
*
* Creates a deep clone of an object.
*/
declare function structuredClone<T>(
value: T,
transfer?: { transfer: ReadonlyArray<import('worker_threads').TransferListItem> },
): T;
/*----------------------------------------------*
* *
* GLOBAL INTERFACES *
@@ -210,9 +224,9 @@ declare namespace NodeJS {
writable: boolean;
write(buffer: Uint8Array | string, cb?: (err?: Error | null) => void): boolean;
write(str: string, encoding?: BufferEncoding, cb?: (err?: Error | null) => void): boolean;
end(cb?: () => void): void;
end(data: string | Uint8Array, cb?: () => void): void;
end(str: string, encoding?: BufferEncoding, cb?: () => void): void;
end(cb?: () => void): this;
end(data: string | Uint8Array, cb?: () => void): this;
end(str: string, encoding?: BufferEncoding, cb?: () => void): this;
}
interface ReadWriteStream extends ReadableStream, WritableStream { }

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 */
/**
* To use the HTTP server and client one must `require('http')`.
@@ -16,7 +16,7 @@
* { 'content-length': '123',
* 'content-type': 'text/plain',
* 'connection': 'keep-alive',
* 'host': 'mysite.com',
* 'host': 'example.com',
* 'accept': '*' }
* ```
*
@@ -37,10 +37,10 @@
* 'content-LENGTH', '123',
* 'content-type', 'text/plain',
* 'CONNECTION', 'keep-alive',
* 'Host', 'mysite.com',
* 'Host', 'example.com',
* 'accepT', '*' ]
* ```
* @see [source](https://github.com/nodejs/node/blob/v16.9.0/lib/http.js)
* @see [source](https://github.com/nodejs/node/blob/v18.0.0/lib/http.js)
*/
declare module 'http' {
import * as stream from 'node:stream';
@@ -244,14 +244,12 @@ declare module 'http' {
* Limit the amount of time the parser will wait to receive the complete HTTP
* headers.
*
* In case of inactivity, the rules defined in `server.timeout` apply. However,
* that inactivity based timeout would still allow the connection to be kept open
* if the headers are being sent very slowly (by default, up to a byte per 2
* minutes). In order to prevent this, whenever header data arrives an additional
* check is made that more than `server.headersTimeout` milliseconds has not
* passed since the connection was established. If the check fails, a `'timeout'`event is emitted on the server object, and (by default) the socket is destroyed.
* See `server.timeout` for more information on how timeout behavior can be
* customized.
* If the timeout expires, the server responds with status 408 without
* forwarding the request to the request listener and then closes the connection.
*
* It must be set to a non-zero value (e.g. 120 seconds) to protect against
* potential Denial-of-Service attacks in case the server is deployed without a
* reverse proxy in front.
* @since v11.3.0, v10.14.0
*/
headersTimeout: number;
@@ -284,6 +282,16 @@ declare module 'http' {
* @since v14.11.0
*/
requestTimeout: number;
/**
* Closes all connections connected to this server.
* @since v18.2.0
*/
closeAllConnections(): void;
/**
* Closes all connections connected to this server which are not sending a request or waiting for a response.
* @since v18.2.0
*/
closeIdleConnections(): void;
addListener(event: string, listener: (...args: any[]) => void): this;
addListener(event: 'close', listener: () => void): this;
addListener(event: 'connection', listener: (socket: Socket) => void): this;
@@ -410,7 +418,7 @@ declare module 'http' {
/**
* Aliases of `outgoingMessage.socket`
* @since v0.3.0
* @deprecated Since v15.12.0 - Use `socket` instead.
* @deprecated Since v15.12.0,v14.17.1 - Use `socket` instead.
*/
readonly connection: Socket | null;
/**
@@ -461,13 +469,13 @@ declare module 'http' {
* const headers = outgoingMessage.getHeaders();
* // headers === { foo: 'bar', 'set-cookie': ['foo=bar', 'bar=baz'] }
* ```
* @since v8.0.0
* @since v7.7.0
*/
getHeaders(): OutgoingHttpHeaders;
/**
* Returns an array of names of headers of the outgoing outgoingMessage. All
* names are lowercase.
* @since v8.0.0
* @since v7.7.0
*/
getHeaderNames(): string[];
/**
@@ -477,7 +485,7 @@ declare module 'http' {
* ```js
* const hasContentType = outgoingMessage.hasHeader('content-type');
* ```
* @since v8.0.0
* @since v7.7.0
*/
hasHeader(name: string): boolean;
/**
@@ -487,6 +495,7 @@ declare module 'http' {
* outgoingMessage.removeHeader('Content-Encoding');
* ```
* @since v0.4.0
* @param name Header name
*/
removeHeader(name: string): void;
/**
@@ -564,11 +573,46 @@ declare module 'http' {
assignSocket(socket: Socket): void;
detachSocket(socket: Socket): void;
/**
* Sends a HTTP/1.1 100 Continue message to the client, indicating that
* Sends an HTTP/1.1 100 Continue message to the client, indicating that
* the request body should be sent. See the `'checkContinue'` event on`Server`.
* @since v0.3.0
*/
writeContinue(callback?: () => void): void;
/**
* Sends an HTTP/1.1 103 Early Hints message to the client with a Link header,
* indicating that the user agent can preload/preconnect the linked resources.
* The `hints` is an object containing the values of headers to be sent with
* early hints message. The optional `callback` argument will be called when
* the response message has been written.
*
* Example:
*
* ```js
* const earlyHintsLink = '</styles.css>; rel=preload; as=style';
* response.writeEarlyHints({
* 'link': earlyHintsLink,
* });
*
* const earlyHintsLinks = [
* '</styles.css>; rel=preload; as=style',
* '</scripts.js>; rel=preload; as=script',
* ];
* response.writeEarlyHints({
* 'link': earlyHintsLinks,
* 'x-trace-id': 'id for diagnostics'
* });
*
* const earlyHintsCallback = () => console.log('early hints message sent');
* response.writeEarlyHints({
* 'link': earlyHintsLinks
* }, earlyHintsCallback);
* ```
*
* @since v18.11.0
* @param hints An object containing the values of headers
* @param callback Will be called when the response message has been written
*/
writeEarlyHints(hints: Record<string, string | string[]>, callback?: () => void): void;
/**
* Sends a response header to the request. The status code is a 3-digit HTTP
* status code, like `404`. The last argument, `headers`, are the response headers.
@@ -633,7 +677,7 @@ declare module 'http' {
): this;
writeHead(statusCode: number, headers?: OutgoingHttpHeaders | OutgoingHttpHeader[]): this;
/**
* Sends a HTTP/1.1 102 Processing message to the client, indicating that
* Sends an HTTP/1.1 102 Processing message to the client, indicating that
* the request body should be sent.
* @since v10.0.0
*/
@@ -681,6 +725,7 @@ declare module 'http' {
* The `request.aborted` property will be `true` if the request has
* been aborted.
* @since v0.11.14
* @deprecated Since v17.0.0,v16.12.0 - Check `destroyed` instead.
*/
aborted: boolean;
/**
@@ -694,13 +739,58 @@ declare module 'http' {
*/
protocol: string;
/**
* Whether the request is send through a reused socket.
* When sending request through a keep-alive enabled agent, the underlying socket
* might be reused. But if server closes connection at unfortunate time, client
* may run into a 'ECONNRESET' error.
*
* ```js
* const http = require('http');
*
* // Server has a 5 seconds keep-alive timeout by default
* http
* .createServer((req, res) => {
* res.write('hello\n');
* res.end();
* })
* .listen(3000);
*
* setInterval(() => {
* // Adapting a keep-alive agent
* http.get('http://localhost:3000', { agent }, (res) => {
* res.on('data', (data) => {
* // Do nothing
* });
* });
* }, 5000); // Sending request on 5s interval so it's easy to hit idle timeout
* ```
*
* By marking a request whether it reused socket or not, we can do
* automatic error retry base on it.
*
* ```js
* const http = require('http');
* const agent = new http.Agent({ keepAlive: true });
*
* function retriableRequest() {
* const req = http
* .get('http://localhost:3000', { agent }, (res) => {
* // ...
* })
* .on('error', (err) => {
* // Check if retry is needed
* if (req.reusedSocket &#x26;&#x26; err.code === 'ECONNRESET') {
* retriableRequest();
* }
* });
* }
*
* retriableRequest();
* ```
* @since v13.0.0, v12.16.0
*/
reusedSocket: boolean;
/**
* Limits maximum response headers count. If set to 0, no limit will be applied.
* @default 2000
*/
maxHeadersCount: number;
constructor(url: string | URL | ClientRequestArgs, cb?: (res: IncomingMessage) => void);
@@ -750,9 +840,12 @@ declare module 'http' {
* const headerNames = request.getRawHeaderNames();
* // headerNames === ['Foo', 'Set-Cookie']
* ```
* @since v15.13.0
* @since v15.13.0, v14.17.0
*/
getRawHeaderNames(): string[];
/**
* @deprecated
*/
addListener(event: 'abort', listener: () => void): this;
addListener(
event: 'connect',
@@ -774,6 +867,9 @@ declare module 'http' {
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;
/**
* @deprecated
*/
on(event: 'abort', listener: () => void): this;
on(event: 'connect', listener: (response: IncomingMessage, socket: Socket, head: Buffer) => void): this;
on(event: 'continue', listener: () => void): this;
@@ -789,6 +885,9 @@ declare module 'http' {
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;
/**
* @deprecated
*/
once(event: 'abort', listener: () => void): this;
once(event: 'connect', listener: (response: IncomingMessage, socket: Socket, head: Buffer) => void): this;
once(event: 'continue', listener: () => void): this;
@@ -804,6 +903,9 @@ declare module 'http' {
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;
/**
* @deprecated
*/
prependListener(event: 'abort', listener: () => void): this;
prependListener(
event: 'connect',
@@ -825,6 +927,9 @@ declare module 'http' {
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;
/**
* @deprecated
*/
prependOnceListener(event: 'abort', listener: () => void): this;
prependOnceListener(
event: 'connect',
@@ -863,6 +968,7 @@ declare module 'http' {
* The `message.aborted` property will be `true` if the request has
* been aborted.
* @since v10.1.0
* @deprecated Since v17.0.0,v16.12.0 - Check `message.destroyed` from <a href="stream.html#class-streamreadable" class="type">stream.Readable</a>.
*/
aborted: boolean;
/**
@@ -914,7 +1020,7 @@ declare module 'http' {
*
* This property is guaranteed to be an instance of the `net.Socket` class,
* a subclass of `stream.Duplex`, unless the user specified a socket
* type other than `net.Socket`.
* type other than `net.Socket` or internally nulled.
* @since v0.3.0
*/
socket: Socket;
@@ -929,7 +1035,7 @@ declare module 'http' {
* // { 'user-agent': 'curl/7.22.0',
* // host: '127.0.0.1:8000',
* // accept: '*' }
* console.log(request.headers);
* console.log(request.getHeaders());
* ```
*
* Duplicates in raw headers are handled in the following ways, depending on the
@@ -1005,14 +1111,14 @@ declare module 'http' {
* To parse the URL into its parts:
*
* ```js
* new URL(request.url, `http://${request.headers.host}`);
* new URL(request.url, `http://${request.getHeaders().host}`);
* ```
*
* When `request.url` is `'/status?name=ryan'` and`request.headers.host` is `'localhost:3000'`:
* When `request.url` is `'/status?name=ryan'` and`request.getHeaders().host` is `'localhost:3000'`:
*
* ```console
* $ node
* > new URL(request.url, `http://${request.headers.host}`)
* > new URL(request.url, `http://${request.getHeaders().host}`)
* URL {
* href: 'http://localhost:3000/status?name=ryan',
* origin: 'http://localhost:3000',
@@ -1212,11 +1318,16 @@ declare module 'http' {
function createServer<
Request extends typeof IncomingMessage = typeof IncomingMessage,
Response extends typeof ServerResponse = typeof ServerResponse,
>(options: ServerOptions, requestListener?: RequestListener<Request, Response>): Server<Request, Response>;
>(
options: ServerOptions<Request, Response>,
requestListener?: RequestListener<Request, Response>,
): Server<Request, Response>;
// although RequestOptions are passed as ClientRequestArgs to ClientRequest directly,
// create interface RequestOptions would make the naming more clear to developers
interface RequestOptions extends ClientRequestArgs {}
/**
* `options` in `socket.connect()` are also supported.
*
* Node.js maintains several connections per server to make HTTP requests.
* This function allows one to transparently issue requests.
*

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 */
/**
* The `http2` module provides an implementation of the [HTTP/2](https://tools.ietf.org/html/rfc7540) protocol. It
@@ -9,7 +9,7 @@
* const http2 = require('http2');
* ```
* @since v8.4.0
* @see [source](https://github.com/nodejs/node/blob/v16.9.0/lib/http2.js)
* @see [source](https://github.com/nodejs/node/blob/v18.0.0/lib/http2.js)
*/
declare module 'http2' {
import EventEmitter = require('node:events');
@@ -86,7 +86,7 @@ declare module 'http2' {
*/
readonly destroyed: boolean;
/**
* Set the `true` if the `END_STREAM` flag was set in the request or response
* Set to `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.
* @since v10.11.0
@@ -761,7 +761,7 @@ declare module 'http2' {
* session.setLocalWindowSize(expectedWindowSize);
* });
* ```
* @since v15.3.0
* @since v15.3.0, v14.18.0
*/
setLocalWindowSize(windowSize: number): void;
/**
@@ -849,6 +849,11 @@ declare module 'http2' {
* For HTTP/2 Client `Http2Session` instances only, the `http2session.request()`creates and returns an `Http2Stream` instance that can be used to send an
* HTTP/2 request to the connected server.
*
* When a `ClientHttp2Session` is first created, the socket may not yet be
* connected. if `clienthttp2session.request()` is called during this time, the
* actual request will be deferred until the socket is ready to go.
* If the `session` is closed before the actual request be executed, an`ERR_HTTP2_GOAWAY_SESSION` is thrown.
*
* This method is only available if `http2session.type` is equal to`http2.constants.NGHTTP2_SESSION_CLIENT`.
*
* ```js
@@ -1640,7 +1645,7 @@ declare module 'http2' {
* be called multiple times to provide successive parts of the body.
*
* In the `http` module, the response body is omitted when the
* request is a HEAD request. Similarly, the `204` and `304` responses_must not_ include a message body.
* request is a HEAD request. Similarly, the `204` and `304` responses _must not_ include a message body.
*
* `chunk` can be a string or a buffer. If `chunk` is a string,
* the second parameter specifies how to encode it into a byte stream.
@@ -1668,6 +1673,34 @@ declare module 'http2' {
* @since v8.4.0
*/
writeContinue(): void;
/**
* Sends a status `103 Early Hints` to the client with a Link header,
* indicating that the user agent can preload/preconnect the linked resources.
* The `hints` is an object containing the values of headers to be sent with
* early hints message.
*
* Example:
*
* ```js
* const earlyHintsLink = '</styles.css>; rel=preload; as=style';
* response.writeEarlyHints({
* 'link': earlyHintsLink,
* });
*
* const earlyHintsLinks = [
* '</styles.css>; rel=preload; as=style',
* '</scripts.js>; rel=preload; as=script',
* ];
* response.writeEarlyHints({
* 'link': earlyHintsLinks,
* 'x-trace-id': 'id for diagnostics'
* });
* ```
*
* @since v18.11.0
* @param hints An object containing the values of headers
*/
writeEarlyHints(hints: Record<string, string | string[]>): void;
/**
* Sends a response header to the request. The status code is a 3-digit HTTP
* status code, like `404`. The last argument, `headers`, are the response headers.

View File

@@ -1,10 +1,10 @@
/* 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 */
/**
* HTTPS is the HTTP protocol over TLS/SSL. In Node.js this is implemented as a
* separate module.
* @see [source](https://github.com/nodejs/node/blob/v16.9.0/lib/https.js)
* @see [source](https://github.com/nodejs/node/blob/v18.0.0/lib/https.js)
*/
declare module 'https' {
import { Duplex } from 'node:stream';
@@ -17,7 +17,6 @@ declare module 'https' {
> = tls.SecureContextOptions & tls.TlsOptions & http.ServerOptions<Request, Response>;
type RequestOptions = http.RequestOptions &
tls.SecureContextOptions & {
checkServerIdentity?: typeof tls.checkServerIdentity | undefined;
rejectUnauthorized?: boolean | undefined; // Defaults to true
servername?: string | undefined; // SNI TLS Extension
};
@@ -50,6 +49,16 @@ declare module 'https' {
options: ServerOptions<Request, Response>,
requestListener?: http.RequestListener<Request, Response>,
);
/**
* Closes all connections connected to this server.
* @since v18.2.0
*/
closeAllConnections(): void;
/**
* Closes all connections connected to this server which are not sending a request or waiting for a response.
* @since v18.2.0
*/
closeIdleConnections(): void;
addListener(event: string, listener: (...args: any[]) => void): this;
addListener(event: 'keylog', listener: (line: Buffer, tlsSocket: tls.TLSSocket) => void): this;
addListener(

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 */
/**
* @since v0.3.7
@@ -88,7 +88,6 @@ declare module 'module' {
static wrap(code: string): string;
static createRequire(path: string | URL): NodeRequire;
static builtinModules: string[];
static isBuiltin(moduleName: string): boolean;
static Module: typeof Module;
constructor(id: string, parent?: Module);
}

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 */
/**
* > Stability: 2 - Stable
@@ -13,7 +13,7 @@
* ```js
* const net = require('net');
* ```
* @see [source](https://github.com/nodejs/node/blob/v16.9.0/lib/net.js)
* @see [source](https://github.com/nodejs/node/blob/v18.0.0/lib/net.js)
*/
declare module 'net' {
import * as stream from 'node:stream';
@@ -134,6 +134,17 @@ declare module 'net' {
* @return The socket itself.
*/
pause(): this;
/**
* Close the TCP connection by sending an RST packet and destroy the stream.
* If this TCP socket is in connecting status, it will send an RST packet
* and destroy this TCP socket once it is connected. Otherwise, it will call
* `socket.destroy` with an `ERR_SOCKET_CLOSED` Error. If this is not a TCP socket
* (for example, a pipe), calling this method will immediately throw
* an `ERR_INVALID_HANDLE_TYPE` Error.
* @since v18.3.0
* @return The socket itself.
*/
resetAndDestroy(): this;
/**
* Resumes reading after a call to `socket.pause()`.
* @return The socket itself.
@@ -211,7 +222,7 @@ declare module 'net' {
*/
unref(): this;
/**
* Opposite of `unref()`, calling `ref()` on a previously `unref`ed socket will_not_ let the program exit if it's the only socket left (the default behavior).
* Opposite of `unref()`, calling `ref()` on a previously `unref`ed socket will _not_ let the program exit if it's the only socket left (the default behavior).
* If the socket is `ref`ed calling `ref` again will have no effect.
* @since v0.9.1
* @return The socket itself.
@@ -271,15 +282,9 @@ declare module 'net' {
readonly localPort?: number;
/**
* The string representation of the local IP family. `'IPv4'` or `'IPv6'`.
* @since v18.8.0, v16.18.0
* @since v18.8.0
*/
readonly localFamily?: string;
/**
* This is `true` if the socket is not connected yet, either because `.connect()`
* has not yet been called or because it is still in the process of connecting (see `socket.connecting`).
* @since v10.16.0
*/
readonly pending: boolean;
/**
* This property represents the state of the connection as a string.
* @see {https://nodejs.org/api/net.html#socketreadystate}
@@ -329,7 +334,8 @@ declare module 'net' {
* 5. end
* 6. error
* 7. lookup
* 8. timeout
* 8. ready
* 9. timeout
*/
addListener(event: string, listener: (...args: any[]) => void): this;
addListener(event: 'close', listener: (hadError: boolean) => void): this;
@@ -436,6 +442,14 @@ declare module 'net' {
*/
keepAliveInitialDelay?: number | undefined;
}
interface DropArgument {
localAddress?: string;
localPort?: number;
localFamily?: string;
remoteAddress?: string;
remotePort?: number;
remoteFamily?: string;
}
/**
* This class is used to create a TCP or `IPC` server.
* @since v0.1.90
@@ -540,7 +554,7 @@ declare module 'net' {
*/
getConnections(cb: (error: Error | null, count: number) => void): void;
/**
* Opposite of `unref()`, calling `ref()` on a previously `unref`ed server will_not_ let the program exit if it's the only server left (the default behavior).
* Opposite of `unref()`, calling `ref()` on a previously `unref`ed server will _not_ let the program exit if it's the only server left (the default behavior).
* If the server is `ref`ed calling `ref()` again will have no effect.
* @since v0.9.1
*/
@@ -572,49 +586,56 @@ declare module 'net' {
* 2. connection
* 3. error
* 4. listening
* 5. drop
*/
addListener(event: string, listener: (...args: any[]) => void): this;
addListener(event: 'close', listener: () => void): this;
addListener(event: 'connection', listener: (socket: Socket) => void): this;
addListener(event: 'error', listener: (err: Error) => void): this;
addListener(event: 'listening', listener: () => void): this;
addListener(event: 'drop', listener: (data?: DropArgument) => void): this;
emit(event: string | symbol, ...args: any[]): boolean;
emit(event: 'close'): boolean;
emit(event: 'connection', socket: Socket): boolean;
emit(event: 'error', err: Error): boolean;
emit(event: 'listening'): boolean;
emit(event: 'drop', data?: DropArgument): boolean;
on(event: string, listener: (...args: any[]) => void): this;
on(event: 'close', listener: () => void): this;
on(event: 'connection', listener: (socket: Socket) => void): this;
on(event: 'error', listener: (err: Error) => void): this;
on(event: 'listening', listener: () => void): this;
on(event: 'drop', listener: (data?: DropArgument) => void): this;
once(event: string, listener: (...args: any[]) => void): this;
once(event: 'close', listener: () => void): this;
once(event: 'connection', listener: (socket: Socket) => void): this;
once(event: 'error', listener: (err: Error) => void): this;
once(event: 'listening', listener: () => void): this;
once(event: 'drop', listener: (data?: DropArgument) => void): this;
prependListener(event: string, listener: (...args: any[]) => void): this;
prependListener(event: 'close', listener: () => void): this;
prependListener(event: 'connection', listener: (socket: Socket) => void): this;
prependListener(event: 'error', listener: (err: Error) => void): this;
prependListener(event: 'listening', listener: () => void): this;
prependListener(event: 'drop', listener: (data?: DropArgument) => void): this;
prependOnceListener(event: string, listener: (...args: any[]) => void): this;
prependOnceListener(event: 'close', listener: () => void): this;
prependOnceListener(event: 'connection', listener: (socket: Socket) => void): this;
prependOnceListener(event: 'error', listener: (err: Error) => void): this;
prependOnceListener(event: 'listening', listener: () => void): this;
prependOnceListener(event: 'drop', listener: (data?: DropArgument) => void): this;
}
type IPVersion = 'ipv4' | 'ipv6';
/**
* The `BlockList` object can be used with some network APIs to specify rules for
* disabling inbound or outbound access to specific IP addresses, IP ranges, or
* IP subnets.
* @since v15.0.0
* @since v15.0.0, v14.18.0
*/
class BlockList {
/**
* Adds a rule to block the given IP address.
* @since v15.0.0
* @since v15.0.0, v14.18.0
* @param address An IPv4 or IPv6 address.
* @param [type='ipv4'] Either `'ipv4'` or `'ipv6'`.
*/
@@ -622,7 +643,7 @@ declare module 'net' {
addAddress(address: SocketAddress): void;
/**
* Adds a rule to block a range of IP addresses from `start` (inclusive) to`end` (inclusive).
* @since v15.0.0
* @since v15.0.0, v14.18.0
* @param start The starting IPv4 or IPv6 address in the range.
* @param end The ending IPv4 or IPv6 address in the range.
* @param [type='ipv4'] Either `'ipv4'` or `'ipv6'`.
@@ -631,7 +652,7 @@ declare module 'net' {
addRange(start: SocketAddress, end: SocketAddress): void;
/**
* Adds a rule to block a range of IP addresses specified as a subnet mask.
* @since v15.0.0
* @since v15.0.0, v14.18.0
* @param net The network IPv4 or IPv6 address.
* @param prefix The number of CIDR prefix bits. For IPv4, this must be a value between `0` and `32`. For IPv6, this must be between `0` and `128`.
* @param [type='ipv4'] Either `'ipv4'` or `'ipv6'`.
@@ -655,7 +676,7 @@ declare module 'net' {
* console.log(blockList.check('::ffff:7b7b:7b7b', 'ipv6')); // Prints: true
* console.log(blockList.check('::ffff:123.123.123.123', 'ipv6')); // Prints: true
* ```
* @since v15.0.0
* @since v15.0.0, v14.18.0
* @param address The IP address to check
* @param [type='ipv4'] Either `'ipv4'` or `'ipv6'`.
*/
@@ -686,7 +707,7 @@ declare module 'net' {
*
* The server can be a TCP server or an `IPC` server, depending on what it `listen()` to.
*
* Here is an example of an TCP echo server which listens for connections
* Here is an example of a TCP echo server which listens for connections
* on port 8124:
*
* ```js
@@ -765,19 +786,39 @@ declare module 'net' {
function createConnection(port: number, host?: string, connectionListener?: () => void): Socket;
function createConnection(path: string, connectionListener?: () => void): Socket;
/**
* Tests if input is an IP address. Returns `0` for invalid strings,
* returns `4` for IP version 4 addresses, and returns `6` for IP version 6
* addresses.
* Returns `6` if `input` is an IPv6 address. Returns `4` if `input` is an IPv4
* address in [dot-decimal notation](https://en.wikipedia.org/wiki/Dot-decimal_notation) with no leading zeroes. Otherwise, returns`0`.
*
* ```js
* net.isIP('::1'); // returns 6
* net.isIP('127.0.0.1'); // returns 4
* net.isIP('127.000.000.001'); // returns 0
* net.isIP('127.0.0.1/24'); // returns 0
* net.isIP('fhqwhgads'); // returns 0
* ```
* @since v0.3.0
*/
function isIP(input: string): number;
/**
* Returns `true` if input is a version 4 IP address, otherwise returns `false`.
* Returns `true` if `input` is an IPv4 address in [dot-decimal notation](https://en.wikipedia.org/wiki/Dot-decimal_notation) with no
* leading zeroes. Otherwise, returns `false`.
*
* ```js
* net.isIPv4('127.0.0.1'); // returns true
* net.isIPv4('127.000.000.001'); // returns false
* net.isIPv4('127.0.0.1/24'); // returns false
* net.isIPv4('fhqwhgads'); // returns false
* ```
* @since v0.3.0
*/
function isIPv4(input: string): boolean;
/**
* Returns `true` if input is a version 6 IP address, otherwise returns `false`.
* Returns `true` if `input` is an IPv6 address. Otherwise, returns `false`.
*
* ```js
* net.isIPv6('::1'); // returns true
* net.isIPv6('fhqwhgads'); // returns false
* ```
* @since v0.3.0
*/
function isIPv6(input: string): boolean;
@@ -803,25 +844,25 @@ declare module 'net' {
port?: number | undefined;
}
/**
* @since v15.14.0
* @since v15.14.0, v14.18.0
*/
class SocketAddress {
constructor(options: SocketAddressInitOptions);
/**
* @since v15.14.0
* @since v15.14.0, v14.18.0
*/
readonly address: string;
/**
* Either \`'ipv4'\` or \`'ipv6'\`.
* @since v15.14.0
* @since v15.14.0, v14.18.0
*/
readonly family: IPVersion;
/**
* @since v15.14.0
* @since v15.14.0, v14.18.0
*/
readonly port: number;
/**
* @since v15.14.0
* @since v15.14.0, v14.18.0
*/
readonly flowlabel: number;
}

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 */
/**
* The `os` module provides operating system-related utility methods and
@@ -8,7 +8,7 @@
* ```js
* const os = require('os');
* ```
* @see [source](https://github.com/nodejs/node/blob/v16.9.0/lib/os.js)
* @see [source](https://github.com/nodejs/node/blob/v18.0.0/lib/os.js)
*/
declare module 'os' {
interface CpuInfo {
@@ -31,6 +31,7 @@ declare module 'os' {
}
interface NetworkInterfaceInfoIPv4 extends NetworkInterfaceBase {
family: 'IPv4';
scopeid?: undefined;
}
interface NetworkInterfaceInfoIPv6 extends NetworkInterfaceBase {
family: 'IPv6';
@@ -390,7 +391,7 @@ declare module 'os' {
const EOL: string;
/**
* Returns the operating system CPU architecture for which the Node.js binary was
* compiled. Possible values are `'arm'`, `'arm64'`, `'ia32'`, `'mips'`,`'mipsel'`, `'ppc'`, `'ppc64'`, `'s390'`, `'s390x'`, `'x32'`, and `'x64'`.
* compiled. Possible values are `'arm'`, `'arm64'`, `'ia32'`, `'mips'`,`'mipsel'`, `'ppc'`, `'ppc64'`, `'s390'`, `'s390x'`, and `'x64'`.
*
* The return value is equivalent to `process.arch`.
* @since v0.5.0
@@ -405,8 +406,9 @@ declare module 'os' {
*/
function version(): string;
/**
* Returns a string identifying the operating system platform. The value is set
* at compile time. Possible values are `'aix'`, `'darwin'`, `'freebsd'`,`'linux'`, `'openbsd'`, `'sunos'`, and `'win32'`.
* Returns a string identifying the operating system platform for which
* the Node.js binary was compiled. The value is set at compile time.
* Possible values are `'aix'`, `'darwin'`, `'freebsd'`,`'linux'`,`'openbsd'`, `'sunos'`, and `'win32'`.
*
* The return value is equivalent to `process.platform`.
*
@@ -415,6 +417,15 @@ declare module 'os' {
* @since v0.5.0
*/
function platform(): NodeJS.Platform;
/**
* Returns the machine type as a string, such as arm, aarch64, mips, mips64, ppc64, ppc64le, s390, s390x, i386, i686, x86_64.
*
* On POSIX systems, the machine type is determined by calling [`uname(3)`](https://linux.die.net/man/3/uname).
* On Windows, `RtlGetVersion()` is used, and if it is not available, `GetVersionExW()` will be used.
* See [https://en.wikipedia.org/wiki/Uname#Examples](https://en.wikipedia.org/wiki/Uname#Examples) for more information.
* @since v18.9.0
*/
function machine(): string;
/**
* Returns the operating system's default directory for temporary files as a
* string.

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 */
declare module 'path/posix' {
import path = require('path');
@@ -16,7 +16,7 @@ declare module 'path/win32' {
* ```js
* const path = require('path');
* ```
* @see [source](https://github.com/nodejs/node/blob/v16.9.0/lib/path.js)
* @see [source](https://github.com/nodejs/node/blob/v18.0.0/lib/path.js)
*/
declare module 'path' {
namespace path {
@@ -93,7 +93,7 @@ declare module 'path' {
* 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 paths string paths to join.
* @param paths A sequence of paths or path segments.
* @throws {TypeError} if any of the arguments is not a string.
*/
resolve(...paths: string[]): string;
@@ -125,10 +125,10 @@ declare module 'path' {
* Often used to extract the file name from a fully qualified path.
*
* @param path the path to evaluate.
* @param ext optionally, an extension to remove from the result.
* @param suffix optionally, an extension to remove from the result.
* @throws {TypeError} if `path` is not a string or if `ext` is given and is not a string.
*/
basename(path: string, ext?: string): string;
basename(path: string, suffix?: 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.

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 */
/**
* This module provides an implementation of a subset of the W3C [Web Performance APIs](https://w3c.github.io/perf-timing-primer/) as well as additional APIs for
@@ -29,7 +29,7 @@
* performance.measure('A to B', 'A', 'B');
* });
* ```
* @see [source](https://github.com/nodejs/node/blob/v16.9.0/lib/perf_hooks.js)
* @see [source](https://github.com/nodejs/node/blob/v18.0.0/lib/perf_hooks.js)
*/
declare module 'perf_hooks' {
import { AsyncResource } from 'node:async_hooks';
@@ -88,6 +88,14 @@ declare module 'perf_hooks' {
* @since v16.0.0
*/
readonly detail?: NodeGCPerformanceDetail | unknown | undefined; // TODO: Narrow this based on entry type.
toJSON(): any;
}
class PerformanceMark extends PerformanceEntry {
readonly duration: 0;
readonly entryType: 'mark';
}
class PerformanceMeasure extends PerformanceEntry {
readonly entryType: 'measure';
}
/**
* _This property is an extension by Node.js. It is not available in Web browsers._
@@ -229,8 +237,9 @@ declare module 'perf_hooks' {
* and whose performanceEntry.duration is always 0.
* Performance marks are used to mark specific significant moments in the Performance Timeline.
* @param name
* @return The PerformanceMark entry that was created
*/
mark(name?: string, options?: MarkOptions): void;
mark(name?: string, options?: MarkOptions): PerformanceMark;
/**
* Creates a new PerformanceMeasure entry in the Performance Timeline.
* A PerformanceMeasure is a subclass of PerformanceEntry whose performanceEntry.entryType is always 'measure',
@@ -245,9 +254,10 @@ declare module 'perf_hooks' {
* @param name
* @param startMark
* @param endMark
* @return The PerformanceMeasure entry that was created
*/
measure(name: string, startMark?: string, endMark?: string): void;
measure(name: string, options: MeasureOptions): void;
measure(name: string, startMark?: string, endMark?: string): PerformanceMeasure;
measure(name: string, options: MeasureOptions): PerformanceMeasure;
/**
* An instance of the PerformanceNodeTiming class that provides performance metrics for specific Node.js operational milestones.
*/
@@ -302,6 +312,9 @@ declare module 'perf_hooks' {
* * }
* * ]
*
*
* performance.clearMarks();
* performance.clearMeasures();
* observer.disconnect();
* });
* obs.observe({ type: 'mark' });
@@ -349,6 +362,9 @@ declare module 'perf_hooks' {
* * ]
*
* console.log(perfObserverList.getEntriesByName('test', 'measure')); // []
*
* performance.clearMarks();
* performance.clearMeasures();
* observer.disconnect();
* });
* obs.observe({ entryTypes: ['mark', 'measure'] });
@@ -387,6 +403,8 @@ declare module 'perf_hooks' {
* * }
* * ]
*
* performance.clearMarks();
* performance.clearMeasures();
* observer.disconnect();
* });
* obs.observe({ type: 'mark' });
@@ -416,7 +434,7 @@ declare module 'perf_hooks' {
* } = require('perf_hooks');
*
* const obs = new PerformanceObserver((list, observer) => {
* // Called three times synchronously. `list` contains one item.
* // Called once asynchronously. `list` contains three items.
* });
* obs.observe({ type: 'mark' });
*
@@ -519,7 +537,7 @@ declare module 'perf_hooks' {
}
interface RecordableHistogram extends Histogram {
/**
* @since v15.9.0
* @since v15.9.0, v14.18.0
* @param val The amount to record in the histogram.
*/
record(val: number | bigint): void;
@@ -528,9 +546,15 @@ declare module 'perf_hooks' {
* previous call to `recordDelta()` and records that amount in the histogram.
*
* ## Examples
* @since v15.9.0
* @since v15.9.0, v14.18.0
*/
recordDelta(): void;
/**
* Adds the values from other to this histogram.
* @since v17.4.0, v16.14.0
* @param other Recordable Histogram to combine with
*/
add(other: RecordableHistogram): void;
}
/**
* _This property is an extension by Node.js. It is not available in Web browsers._
@@ -580,9 +604,24 @@ declare module 'perf_hooks' {
}
/**
* Returns a `RecordableHistogram`.
* @since v15.9.0
* @since v15.9.0, v14.18.0
*/
function createHistogram(options?: CreateHistogramOptions): RecordableHistogram;
import { performance as _performance } from 'perf_hooks';
global {
/**
* `performance` is a global reference for `require('perf_hooks').performance`
* https://nodejs.org/api/globals.html#performance
* @since v16.0.0
*/
var performance: typeof globalThis extends {
onmessage: any;
performance: infer T;
}
? T
: typeof _performance;
}
}
declare module 'node:perf_hooks' {
export * from 'perf_hooks';

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 */
declare module 'process' {
import * as tty from 'node:tty';
@@ -52,6 +52,7 @@ declare module 'process' {
openssl: string;
}
type Platform = 'aix' | 'android' | 'darwin' | 'freebsd' | 'haiku' | 'linux' | 'openbsd' | 'sunos' | 'win32' | 'cygwin' | 'netbsd';
type Architecture = 'arm' | 'arm64' | 'ia32' | 'mips' | 'mipsel' | 'ppc' | 'ppc64' | 's390' | 's390x' | 'x64';
type Signals =
| 'SIGABRT'
| 'SIGALRM'
@@ -99,7 +100,7 @@ declare module 'process' {
type UncaughtExceptionListener = (error: Error, origin: UncaughtExceptionOrigin) => void;
/**
* Most of the time the unhandledRejection will be an Error, but this should not be relied upon
* as *anything* can be thrown/rejected, it is therefore unsafe to assume the the value is an Error.
* as *anything* can be thrown/rejected, it is therefore unsafe to assume that the value is an Error.
*/
type UnhandledRejectionListener = (reason: unknown, promise: Promise<unknown>) => void;
type WarningListener = (warning: Error) => void;
@@ -592,7 +593,7 @@ declare module 'process' {
*
* The reason this is problematic is because writes to `process.stdout` in Node.js
* are sometimes _asynchronous_ and may occur over multiple ticks of the Node.js
* event loop. Calling `process.exit()`, however, forces the process to exit_before_ those additional writes to `stdout` can be performed.
* event loop. Calling `process.exit()`, however, forces the process to exit _before_ those additional writes to `stdout` can be performed.
*
* Rather than calling `process.exit()` directly, the code _should_ set the`process.exitCode` and allow the process to exit naturally by avoiding
* scheduling any additional work for the event loop:
@@ -644,7 +645,7 @@ declare module 'process' {
* Android).
* @since v0.1.31
*/
getgid(): number;
getgid?: () => number;
/**
* The `process.setgid()` method sets the group identity of the process. (See [`setgid(2)`](http://man7.org/linux/man-pages/man2/setgid.2.html).) The `id` can be passed as either a
* numeric ID or a group name
@@ -671,7 +672,7 @@ declare module 'process' {
* @since v0.1.31
* @param id The group name or ID
*/
setgid(id: number | string): void;
setgid?: (id: number | string) => void;
/**
* The `process.getuid()` method returns the numeric user identity of the process.
* (See [`getuid(2)`](http://man7.org/linux/man-pages/man2/getuid.2.html).)
@@ -688,7 +689,7 @@ declare module 'process' {
* Android).
* @since v0.1.28
*/
getuid(): number;
getuid?: () => number;
/**
* The `process.setuid(id)` method sets the user identity of the process. (See [`setuid(2)`](http://man7.org/linux/man-pages/man2/setuid.2.html).) The `id` can be passed as either a
* numeric ID or a username string.
@@ -714,7 +715,7 @@ declare module 'process' {
* This feature is not available in `Worker` threads.
* @since v0.1.28
*/
setuid(id: number | string): void;
setuid?: (id: number | string) => void;
/**
* The `process.geteuid()` method returns the numerical effective user identity of
* the process. (See [`geteuid(2)`](http://man7.org/linux/man-pages/man2/geteuid.2.html).)
@@ -731,7 +732,7 @@ declare module 'process' {
* Android).
* @since v2.0.0
*/
geteuid(): number;
geteuid?: () => number;
/**
* The `process.seteuid()` method sets the effective user identity of the process.
* (See [`seteuid(2)`](http://man7.org/linux/man-pages/man2/seteuid.2.html).) The `id` can be passed as either a numeric ID or a username
@@ -758,7 +759,7 @@ declare module 'process' {
* @since v2.0.0
* @param id A user name or ID
*/
seteuid(id: number | string): void;
seteuid?: (id: number | string) => void;
/**
* The `process.getegid()` method returns the numerical effective group identity
* of the Node.js process. (See [`getegid(2)`](http://man7.org/linux/man-pages/man2/getegid.2.html).)
@@ -775,7 +776,7 @@ declare module 'process' {
* Android).
* @since v2.0.0
*/
getegid(): number;
getegid?: () => number;
/**
* The `process.setegid()` method sets the effective group identity of the process.
* (See [`setegid(2)`](http://man7.org/linux/man-pages/man2/setegid.2.html).) The `id` can be passed as either a numeric ID or a group
@@ -802,7 +803,7 @@ declare module 'process' {
* @since v2.0.0
* @param id A group name or ID
*/
setegid(id: number | string): void;
setegid?: (id: number | string) => void;
/**
* The `process.getgroups()` method returns an array with the supplementary group
* IDs. POSIX leaves it unspecified if the effective group ID is included but
@@ -820,7 +821,7 @@ declare module 'process' {
* Android).
* @since v0.9.4
*/
getgroups(): number[];
getgroups?: () => number[];
/**
* The `process.setgroups()` method sets the supplementary group IDs for the
* Node.js process. This is a privileged operation that requires the Node.js
@@ -846,7 +847,7 @@ declare module 'process' {
* This feature is not available in `Worker` threads.
* @since v0.9.4
*/
setgroups(groups: ReadonlyArray<string | number>): void;
setgroups?: (groups: ReadonlyArray<string | number>) => void;
/**
* The `process.setUncaughtExceptionCaptureCallback()` function sets a function
* that will be invoked when an uncaught exception occurs, which will receive the
@@ -1043,7 +1044,7 @@ declare module 'process' {
title: string;
/**
* The operating system CPU architecture for which the Node.js binary was compiled.
* Possible values are: `'arm'`, `'arm64'`, `'ia32'`, `'mips'`,`'mipsel'`, `'ppc'`,`'ppc64'`, `'s390'`, `'s390x'`, `'x32'`, and `'x64'`.
* Possible values are: `'arm'`, `'arm64'`, `'ia32'`, `'mips'`,`'mipsel'`, `'ppc'`,`'ppc64'`, `'s390'`, `'s390x'`, and `'x64'`.
*
* ```js
* import { arch } from 'process';
@@ -1052,10 +1053,10 @@ declare module 'process' {
* ```
* @since v0.5.0
*/
readonly arch: string;
readonly arch: Architecture;
/**
* The `process.platform` property returns a string identifying the operating
* system platform on which the Node.js process is running.
* system platform for which the Node.js binary was compiled.
*
* Currently possible values are:
*
@@ -1408,7 +1409,7 @@ declare module 'process' {
emit(event: 'unhandledRejection', reason: unknown, promise: Promise<unknown>): boolean;
emit(event: 'warning', warning: Error): boolean;
emit(event: 'message', message: unknown, sendHandle: unknown): this;
emit(event: Signals, signal: Signals): boolean;
emit(event: Signals, signal?: Signals): boolean;
emit(event: 'multipleResolves', type: MultipleResolveType, promise: Promise<unknown>, value: unknown): this;
emit(event: 'worker', listener: WorkerListener): this;
on(event: 'beforeExit', listener: BeforeExitListener): this;

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 */
/**
* The `querystring` module provides utilities for parsing and formatting URL
@@ -12,7 +12,7 @@
* `querystring` is more performant than `URLSearchParams` but is not a
* standardized API. Use `URLSearchParams` when performance is not critical
* or when compatibility with browser code is desirable.
* @see [source](https://github.com/nodejs/node/blob/v16.9.0/lib/querystring.js)
* @see [source](https://github.com/nodejs/node/blob/v18.0.0/lib/querystring.js)
*/
declare module 'querystring' {
interface StringifyOptions {

View File

@@ -1,39 +1,46 @@
/* 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 */
/**
* The `readline` module provides an interface for reading data from a `Readable` stream (such as `process.stdin`) one line at a time. It can be accessed
* using:
* The `readline` module provides an interface for reading data from a `Readable` stream (such as `process.stdin`) one line at a time.
*
* To use the promise-based APIs:
*
* ```js
* const readline = require('readline');
* import * as readline from 'node:readline/promises';
* ```
*
* To use the callback and sync APIs:
*
* ```js
* import * as readline from 'node:readline';
* ```
*
* The following simple example illustrates the basic use of the `readline` module.
*
* ```js
* const readline = require('readline');
* import * as readline from 'node:readline/promises';
* import { stdin as input, stdout as output } from 'node:process';
*
* const rl = readline.createInterface({
* input: process.stdin,
* output: process.stdout
* });
* const rl = readline.createInterface({ input, output });
*
* rl.question('What do you think of Node.js? ', (answer) => {
* // TODO: Log the answer in a database
* console.log(`Thank you for your valuable feedback: ${answer}`);
* const answer = await rl.question('What do you think of Node.js? ');
*
* rl.close();
* });
* console.log(`Thank you for your valuable feedback: ${answer}`);
*
* rl.close();
* ```
*
* Once this code is invoked, the Node.js application will not terminate until the`readline.Interface` is closed because the interface waits for data to be
* received on the `input` stream.
* @see [source](https://github.com/nodejs/node/blob/v16.9.0/lib/readline.js)
* @see [source](https://github.com/nodejs/node/blob/v18.0.0/lib/readline.js)
*/
declare module 'readline' {
import { Abortable, EventEmitter } from 'node:events';
interface Key {
import * as promises from 'node:readline/promises';
export { promises };
export interface Key {
sequence?: string | undefined;
name?: string | undefined;
ctrl?: boolean | undefined;
@@ -47,7 +54,7 @@ declare module 'readline' {
* and is read from, the `input` stream.
* @since v0.1.104
*/
class Interface extends EventEmitter {
export class Interface extends EventEmitter {
readonly terminal: boolean;
/**
* The current input data being processed by node.
@@ -314,11 +321,11 @@ declare module 'readline' {
prependOnceListener(event: 'history', listener: (history: string[]) => 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) => void;
type CompleterResult = [string[], string];
interface ReadLineOptions {
export type ReadLine = Interface; // type forwarded for backwards compatibility
export type Completer = (line: string) => CompleterResult;
export type AsyncCompleter = (line: string, callback: (err?: null | Error, result?: CompleterResult) => void) => void;
export type CompleterResult = [string[], string];
export interface ReadLineOptions {
input: NodeJS.ReadableStream;
output?: NodeJS.WritableStream | undefined;
completer?: Completer | AsyncCompleter | undefined;
@@ -379,8 +386,8 @@ declare module 'readline' {
* ```
* @since v0.1.98
*/
function createInterface(input: NodeJS.ReadableStream, output?: NodeJS.WritableStream, completer?: Completer | AsyncCompleter, terminal?: boolean): Interface;
function createInterface(options: ReadLineOptions): Interface;
export function createInterface(input: NodeJS.ReadableStream, output?: NodeJS.WritableStream, completer?: Completer | AsyncCompleter, terminal?: boolean): Interface;
export function createInterface(options: ReadLineOptions): Interface;
/**
* The `readline.emitKeypressEvents()` method causes the given `Readable` stream to begin emitting `'keypress'` events corresponding to received input.
*
@@ -397,11 +404,114 @@ declare module 'readline' {
* if (process.stdin.isTTY)
* process.stdin.setRawMode(true);
* ```
*
* ## Example: Tiny CLI
*
* The following example illustrates the use of `readline.Interface` class to
* implement a small command-line interface:
*
* ```js
* const readline = require('readline');
* const rl = readline.createInterface({
* input: process.stdin,
* output: process.stdout,
* prompt: 'OHAI> '
* });
*
* rl.prompt();
*
* rl.on('line', (line) => {
* switch (line.trim()) {
* case 'hello':
* console.log('world!');
* break;
* default:
* console.log(`Say what? I might have heard '${line.trim()}'`);
* break;
* }
* rl.prompt();
* }).on('close', () => {
* console.log('Have a great day!');
* process.exit(0);
* });
* ```
*
* ## Example: Read file stream line-by-Line
*
* A common use case for `readline` is to consume an input file one line at a
* time. The easiest way to do so is leveraging the `fs.ReadStream` API as
* well as a `for await...of` loop:
*
* ```js
* const fs = require('fs');
* const readline = require('readline');
*
* async function processLineByLine() {
* const fileStream = fs.createReadStream('input.txt');
*
* const rl = readline.createInterface({
* input: fileStream,
* crlfDelay: Infinity
* });
* // Note: we use the crlfDelay option to recognize all instances of CR LF
* // ('\r\n') in input.txt as a single line break.
*
* for await (const line of rl) {
* // Each line in input.txt will be successively available here as `line`.
* console.log(`Line from file: ${line}`);
* }
* }
*
* processLineByLine();
* ```
*
* Alternatively, one could use the `'line'` event:
*
* ```js
* const fs = require('fs');
* const readline = require('readline');
*
* const rl = readline.createInterface({
* input: fs.createReadStream('sample.txt'),
* crlfDelay: Infinity
* });
*
* rl.on('line', (line) => {
* console.log(`Line from file: ${line}`);
* });
* ```
*
* Currently, `for await...of` loop can be a bit slower. If `async` / `await`flow and speed are both essential, a mixed approach can be applied:
*
* ```js
* const { once } = require('events');
* const { createReadStream } = require('fs');
* const { createInterface } = require('readline');
*
* (async function processLineByLine() {
* try {
* const rl = createInterface({
* input: createReadStream('big-file.txt'),
* crlfDelay: Infinity
* });
*
* rl.on('line', (line) => {
* // Process the line.
* });
*
* await once(rl, 'close');
*
* console.log('File processed.');
* } catch (err) {
* console.error(err);
* }
* })();
* ```
* @since v0.7.7
*/
function emitKeypressEvents(stream: NodeJS.ReadableStream, readlineInterface?: Interface): void;
type Direction = -1 | 0 | 1;
interface CursorPos {
export function emitKeypressEvents(stream: NodeJS.ReadableStream, readlineInterface?: Interface): void;
export type Direction = -1 | 0 | 1;
export interface CursorPos {
rows: number;
cols: number;
}
@@ -412,7 +522,7 @@ declare module 'readline' {
* @param callback Invoked once the operation completes.
* @return `false` if `stream` wishes for the calling code to wait for the `'drain'` event to be emitted before continuing to write additional data; otherwise `true`.
*/
function clearLine(stream: NodeJS.WritableStream, dir: Direction, callback?: () => void): boolean;
export function clearLine(stream: NodeJS.WritableStream, dir: Direction, callback?: () => void): boolean;
/**
* The `readline.clearScreenDown()` method clears the given `TTY` stream from
* the current position of the cursor down.
@@ -420,7 +530,7 @@ declare module 'readline' {
* @param callback Invoked once the operation completes.
* @return `false` if `stream` wishes for the calling code to wait for the `'drain'` event to be emitted before continuing to write additional data; otherwise `true`.
*/
function clearScreenDown(stream: NodeJS.WritableStream, callback?: () => void): boolean;
export function clearScreenDown(stream: NodeJS.WritableStream, callback?: () => void): boolean;
/**
* The `readline.cursorTo()` method moves cursor to the specified position in a
* given `TTY` `stream`.
@@ -428,7 +538,7 @@ declare module 'readline' {
* @param callback Invoked once the operation completes.
* @return `false` if `stream` wishes for the calling code to wait for the `'drain'` event to be emitted before continuing to write additional data; otherwise `true`.
*/
function cursorTo(stream: NodeJS.WritableStream, x: number, y?: number, callback?: () => void): boolean;
export function cursorTo(stream: NodeJS.WritableStream, x: number, y?: number, callback?: () => void): boolean;
/**
* The `readline.moveCursor()` method moves the cursor _relative_ to its current
* position in a given `TTY` `stream`.
@@ -539,7 +649,7 @@ declare module 'readline' {
* @param callback Invoked once the operation completes.
* @return `false` if `stream` wishes for the calling code to wait for the `'drain'` event to be emitted before continuing to write additional data; otherwise `true`.
*/
function moveCursor(stream: NodeJS.WritableStream, dx: number, dy: number, callback?: () => void): boolean;
export function moveCursor(stream: NodeJS.WritableStream, dx: number, dy: number, callback?: () => void): boolean;
}
declare module 'node:readline' {
export * from 'readline';

View File

@@ -0,0 +1,146 @@
/* NOTE: Do not edit directly! This file is generated using `npm run update-types` in https://github.com/node-red/nr-monaco-build */
/**
* The `readline/promise` module provides an API for reading lines of input from a Readable stream one line at a time.
*
* @see [source](https://github.com/nodejs/node/blob/v18.0.0/lib/readline/promises.js)
* @since v17.0.0
*/
declare module 'readline/promises' {
import { Interface as _Interface, ReadLineOptions, Completer, AsyncCompleter, Direction } from 'node:readline';
import { Abortable } from 'node:events';
class Interface extends _Interface {
/**
* The rl.question() method displays the query by writing it to the output, waits for user input to be provided on input,
* then invokes the callback function passing the provided input as the first argument.
*
* When called, rl.question() will resume the input stream if it has been paused.
*
* If the readlinePromises.Interface was created with output set to null or undefined the query is not written.
*
* If the question is called after rl.close(), it returns a rejected promise.
*
* Example usage:
*
* ```js
* const answer = await rl.question('What is your favorite food? ');
* console.log(`Oh, so your favorite food is ${answer}`);
* ```
*
* Using an AbortSignal to cancel a question.
*
* ```js
* const signal = AbortSignal.timeout(10_000);
*
* signal.addEventListener('abort', () => {
* console.log('The food question timed out');
* }, { once: true });
*
* const answer = await rl.question('What is your favorite food? ', { signal });
* console.log(`Oh, so your favorite food is ${answer}`);
* ```
*
* @since v17.0.0
* @param query A statement or query to write to output, prepended to the prompt.
*/
question(query: string): Promise<string>;
question(query: string, options: Abortable): Promise<string>;
}
class Readline {
/**
* @param stream A TTY stream.
*/
constructor(stream: NodeJS.WritableStream, options?: { autoCommit?: boolean });
/**
* The `rl.clearLine()` method adds to the internal list of pending action an action that clears current line of the associated `stream` in a specified direction identified by `dir`.
* Call `rl.commit()` to see the effect of this method, unless `autoCommit: true` was passed to the constructor.
*/
clearLine(dir: Direction): this;
/**
* The `rl.clearScreenDown()` method adds to the internal list of pending action an action that clears the associated `stream` from the current position of the cursor down.
* Call `rl.commit()` to see the effect of this method, unless `autoCommit: true` was passed to the constructor.
*/
clearScreenDown(): this;
/**
* The `rl.commit()` method sends all the pending actions to the associated `stream` and clears the internal list of pending actions.
*/
commit(): Promise<void>;
/**
* The `rl.cursorTo()` method adds to the internal list of pending action an action that moves cursor to the specified position in the associated `stream`.
* Call `rl.commit()` to see the effect of this method, unless `autoCommit: true` was passed to the constructor.
*/
cursorTo(x: number, y?: number): this;
/**
* The `rl.moveCursor()` method adds to the internal list of pending action an action that moves the cursor relative to its current position in the associated `stream`.
* Call `rl.commit()` to see the effect of this method, unless autoCommit: true was passed to the constructor.
*/
moveCursor(dx: number, dy: number): this;
/**
* The `rl.rollback()` method clears the internal list of pending actions without sending it to the associated `stream`.
*/
rollback(): this;
}
/**
* The `readlinePromises.createInterface()` method creates a new `readlinePromises.Interface` instance.
*
* ```js
* const readlinePromises = require('node:readline/promises');
* const rl = readlinePromises.createInterface({
* input: process.stdin,
* output: process.stdout
* });
* ```
*
* Once the `readlinePromises.Interface` instance is created, the most common case is to listen for the `'line'` event:
*
* ```js
* rl.on('line', (line) => {
* console.log(`Received: ${line}`);
* });
* ```
*
* If `terminal` is `true` for this instance then the `output` stream will get the best compatibility if it defines an `output.columns` property,
* and emits a `'resize'` event on the `output`, if or when the columns ever change (`process.stdout` does this automatically when it is a TTY).
*
* ## Use of the `completer` function
*
* The `completer` function takes the current line entered by the user as an argument, and returns an `Array` with 2 entries:
*
* - An Array with matching entries for the completion.
* - The substring that was used for the matching.
*
* For instance: `[[substr1, substr2, ...], originalsubstring]`.
*
* ```js
* function completer(line) {
* const completions = '.help .error .exit .quit .q'.split(' ');
* const hits = completions.filter((c) => c.startsWith(line));
* // Show all completions if none found
* return [hits.length ? hits : completions, line];
* }
* ```
*
* The `completer` function can also returns a `Promise`, or be asynchronous:
*
* ```js
* async function completer(linePartial) {
* await someAsyncWork();
* return [['123'], linePartial];
* }
* ```
*/
function createInterface(
input: NodeJS.ReadableStream,
output?: NodeJS.WritableStream,
completer?: Completer | AsyncCompleter,
terminal?: boolean,
): Interface;
function createInterface(options: ReadLineOptions): Interface;
}
declare module 'node:readline/promises' {
export * from 'readline/promises';
}

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 */
/**
* A stream is an abstract interface for working with streaming data in Node.js.
@@ -17,13 +17,14 @@
*
* The `stream` module is useful for creating new types of stream instances. It is
* usually not necessary to use the `stream` module to consume streams.
* @see [source](https://github.com/nodejs/node/blob/v16.9.0/lib/stream.js)
* @see [source](https://github.com/nodejs/node/blob/v18.0.0/lib/stream.js)
*/
declare module 'stream' {
import { EventEmitter, Abortable } from 'node:events';
import { Blob as NodeBlob } from 'node:buffer';
import { Blob as NodeBlob } from "node:buffer";
import * as streamPromises from 'node:stream/promises';
import * as streamConsumers from 'node:stream/consumers';
import * as streamWeb from 'node:stream/web';
class internal extends EventEmitter {
pipe<T extends NodeJS.WritableStream>(
destination: T,
@@ -56,11 +57,23 @@ declare module 'stream' {
* A utility method for creating Readable Streams out of iterators.
*/
static from(iterable: Iterable<any> | AsyncIterable<any>, options?: ReadableOptions): Readable;
/**
* A utility method for creating a `Readable` from a web `ReadableStream`.
* @since v17.0.0
* @experimental
*/
static fromWeb(readableStream: streamWeb.ReadableStream, options?: Pick<ReadableOptions, 'encoding' | 'highWaterMark' | 'objectMode' | 'signal'>): Readable;
/**
* Returns whether the stream has been read from or cancelled.
* @since v16.8.0
*/
static isDisturbed(stream: Readable | NodeJS.ReadableStream): boolean;
/**
* A utility method for creating a web `ReadableStream` from a `Readable`.
* @since v17.0.0
* @experimental
*/
static toWeb(streamReadable: Readable): streamWeb.ReadableStream;
/**
* Returns whether the stream was destroyed or errored before emitting `'end'`.
* @since v16.8.0
@@ -75,7 +88,7 @@ declare module 'stream' {
readable: boolean;
/**
* Returns whether `'data'` has been emitted.
* @since v16.7.0
* @since v16.7.0, v14.18.0
* @experimental
*/
readonly readableDidRead: boolean;
@@ -117,13 +130,23 @@ declare module 'stream' {
* @since v8.0.0
*/
destroyed: boolean;
/**
* Is true after 'close' has been emitted.
* @since v18.0.0
*/
readonly closed: boolean;
/**
* Returns error if the stream has been destroyed with an error.
* @since v18.0.0
*/
readonly errored: Error | null;
constructor(opts?: ReadableOptions);
_construct?(callback: (error?: Error | null) => void): void;
_read(size: number): void;
/**
* The `readable.read()` method pulls some data out of the internal buffer and
* returns it. If no data available to be read, `null` is returned. By default,
* the data will be returned as a `Buffer` object unless an encoding has been
* The `readable.read()` method reads data out of the internal buffer and
* returns it. If no data is available to be read, `null` is returned. By default,
* the data is returned as a `Buffer` object unless an encoding has been
* specified using the `readable.setEncoding()` method or the stream is operating
* in object mode.
*
@@ -338,7 +361,7 @@ declare module 'stream' {
* let chunk;
* while (null !== (chunk = stream.read())) {
* const str = decoder.write(chunk);
* if (str.match(/\n\n/)) {
* if (str.includes('\n\n')) {
* // Found the header boundary.
* const split = str.split(/\n\n/);
* header += split.shift();
@@ -351,10 +374,10 @@ declare module 'stream' {
* stream.unshift(buf);
* // Now the body of the message can be read from the stream.
* callback(null, header, stream);
* } else {
* // Still reading the header.
* header += str;
* return;
* }
* // Still reading the header.
* header += str;
* }
* }
* }
@@ -500,6 +523,18 @@ declare module 'stream' {
* @since v0.9.4
*/
class Writable extends Stream implements NodeJS.WritableStream {
/**
* A utility method for creating a `Writable` from a web `WritableStream`.
* @since v17.0.0
* @experimental
*/
static fromWeb(writableStream: streamWeb.WritableStream, options?: Pick<WritableOptions, 'decodeStrings' | 'highWaterMark' | 'objectMode' | 'signal'>): Writable;
/**
* A utility method for creating a web `WritableStream` from a `Writable`.
* @since v17.0.0
* @experimental
*/
static toWeb(streamWritable: Writable): streamWeb.WritableStream;
/**
* Is `true` if it is safe to call `writable.write()`, which means
* the stream has not been destroyed, errored or ended.
@@ -545,6 +580,21 @@ declare module 'stream' {
* @since v8.0.0
*/
destroyed: boolean;
/**
* Is true after 'close' has been emitted.
* @since v18.0.0
*/
readonly closed: boolean;
/**
* Returns error if the stream has been destroyed with an error.
* @since v18.0.0
*/
readonly errored: Error | null;
/**
* Is `true` if the stream's buffer has been full and stream will emit 'drain'.
* @since v15.2.0, v14.17.0
*/
readonly writableNeedDrain: boolean;
constructor(opts?: WritableOptions);
_write(chunk: any, encoding: BufferEncoding, callback: (error?: Error | null) => void): void;
_writev?(
@@ -571,7 +621,7 @@ declare module 'stream' {
* While a stream is not draining, calls to `write()` will buffer `chunk`, and
* return false. Once all currently buffered chunks are drained (accepted for
* delivery by the operating system), the `'drain'` event will be emitted.
* It is recommended that once `write()` returns false, no more chunks be written
* Once `write()` returns false, do not write more chunks
* until the `'drain'` event is emitted. While calling `write()` on a stream that
* is not draining is allowed, Node.js will buffer all written chunks until
* maximum memory usage occurs, at which point it will abort unconditionally.
@@ -665,8 +715,8 @@ declare module 'stream' {
* The `writable.uncork()` method flushes all data buffered since {@link cork} was called.
*
* When using `writable.cork()` and `writable.uncork()` to manage the buffering
* of writes to a stream, it is recommended that calls to `writable.uncork()` be
* deferred using `process.nextTick()`. Doing so allows batching of all`writable.write()` calls that occur within a given Node.js event loop phase.
* of writes to a stream, defer calls to `writable.uncork()` using`process.nextTick()`. Doing so allows batching of all`writable.write()` calls that occur within a given Node.js event
* loop phase.
*
* ```js
* stream.cork();
@@ -811,6 +861,9 @@ declare module 'stream' {
readonly writableLength: number;
readonly writableObjectMode: boolean;
readonly writableCorked: number;
readonly writableNeedDrain: boolean;
readonly closed: boolean;
readonly errored: Error | null;
/**
* If `false` then the stream will automatically end the writable side when the
* readable side ends. Set initially by the `allowHalfOpen` constructor option,
@@ -862,105 +915,6 @@ declare module 'stream' {
end(chunk: any, encoding?: BufferEncoding, cb?: () => void): this;
cork(): void;
uncork(): void;
/**
* Event emitter
* The defined events on documents including:
* 1. close
* 2. data
* 3. drain
* 4. end
* 5. error
* 6. finish
* 7. pause
* 8. pipe
* 9. readable
* 10. resume
* 11. unpipe
*/
addListener(event: 'close', listener: () => void): this;
addListener(event: 'data', listener: (chunk: any) => 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: 'pause', listener: () => void): this;
addListener(event: 'pipe', listener: (src: Readable) => void): this;
addListener(event: 'readable', listener: () => void): this;
addListener(event: 'resume', listener: () => 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: 'data', chunk: any): boolean;
emit(event: 'drain'): boolean;
emit(event: 'end'): boolean;
emit(event: 'error', err: Error): boolean;
emit(event: 'finish'): boolean;
emit(event: 'pause'): boolean;
emit(event: 'pipe', src: Readable): boolean;
emit(event: 'readable'): boolean;
emit(event: 'resume'): boolean;
emit(event: 'unpipe', src: Readable): boolean;
emit(event: string | symbol, ...args: any[]): boolean;
on(event: 'close', listener: () => void): this;
on(event: 'data', listener: (chunk: any) => 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: 'pause', listener: () => void): this;
on(event: 'pipe', listener: (src: Readable) => void): this;
on(event: 'readable', listener: () => void): this;
on(event: 'resume', listener: () => 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: 'data', listener: (chunk: any) => 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: 'pause', listener: () => void): this;
once(event: 'pipe', listener: (src: Readable) => void): this;
once(event: 'readable', listener: () => void): this;
once(event: 'resume', listener: () => 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: 'data', listener: (chunk: any) => 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: 'pause', listener: () => void): this;
prependListener(event: 'pipe', listener: (src: Readable) => void): this;
prependListener(event: 'readable', listener: () => void): this;
prependListener(event: 'resume', listener: () => 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: 'data', listener: (chunk: any) => 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: 'pause', listener: () => void): this;
prependOnceListener(event: 'pipe', listener: (src: Readable) => void): this;
prependOnceListener(event: 'readable', listener: () => void): this;
prependOnceListener(event: 'resume', listener: () => 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: 'data', listener: (chunk: any) => void): this;
removeListener(event: 'drain', listener: () => void): this;
removeListener(event: 'end', listener: () => void): this;
removeListener(event: 'error', listener: (err: Error) => void): this;
removeListener(event: 'finish', listener: () => void): this;
removeListener(event: 'pause', listener: () => void): this;
removeListener(event: 'pipe', listener: (src: Readable) => void): this;
removeListener(event: 'readable', listener: () => void): this;
removeListener(event: 'resume', listener: () => void): this;
removeListener(event: 'unpipe', listener: (src: Readable) => void): this;
removeListener(event: string | symbol, listener: (...args: any[]) => void): this;
}
type TransformCallback = (error?: Error | null, data?: any) => void;
interface TransformOptions extends DuplexOptions {
@@ -1209,7 +1163,7 @@ declare module 'stream' {
* async function run() {
* await pipeline(
* fs.createReadStream('lowercase.txt'),
* async function* (source, signal) {
* async function* (source, { signal }) {
* source.setEncoding('utf8'); // Work with strings rather than `Buffer`s.
* for await (const chunk of source) {
* yield await processChunk(chunk, { signal });
@@ -1233,7 +1187,7 @@ declare module 'stream' {
*
* async function run() {
* await pipeline(
* async function * (signal) {
* async function* ({ signal }) {
* await someLongRunningfn({ signal });
* yield 'asd';
* },
@@ -1252,7 +1206,31 @@ declare module 'stream' {
*
* `stream.pipeline()` leaves dangling event listeners on the streams
* after the `callback` has been invoked. In the case of reuse of streams after
* failure, this can cause event listener leaks and swallowed errors.
* failure, this can cause event listener leaks and swallowed errors. If the last
* stream is readable, dangling event listeners will be removed so that the last
* stream can be consumed later.
*
* `stream.pipeline()` closes all the streams when an error is raised.
* The `IncomingRequest` usage with `pipeline` could lead to an unexpected behavior
* once it would destroy the socket without sending the expected response.
* See the example below:
*
* ```js
* const fs = require('fs');
* const http = require('http');
* const { pipeline } = require('stream');
*
* const server = http.createServer((req, res) => {
* const fileStream = fs.createReadStream('./fileNotExist.txt');
* pipeline(fileStream, res, (err) => {
* if (err) {
* console.log(err); // No such file
* // this message can't be sent once `pipeline` already destroyed the socket
* return res.end('error!!!');
* }
* });
* });
* ```
* @since v10.0.0
* @param callback Called when the pipeline is fully done.
*/
@@ -1344,13 +1322,13 @@ declare module 'stream' {
/**
* Returns whether the stream has encountered an error.
* @since v16.14.0
* @since v17.3.0
*/
function isErrored(stream: Readable | Writable | NodeJS.ReadableStream | NodeJS.WritableStream): boolean;
/**
* Returns whether the stream is readable.
* @since v16.14.0
* @since v17.4.0
*/
function isReadable(stream: Readable | NodeJS.ReadableStream): boolean;

View File

@@ -1,9 +1,9 @@
/* 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 */
declare module 'stream/consumers' {
import { Readable } from 'node:stream';
import { Blob as NodeBlob } from "node:buffer";
import { Readable } from 'node:stream';
function buffer(stream: NodeJS.ReadableStream | Readable | AsyncIterator<any>): Promise<Buffer>;
function text(stream: NodeJS.ReadableStream | Readable | AsyncIterator<any>): Promise<string>;
function arrayBuffer(stream: NodeJS.ReadableStream | Readable | AsyncIterator<any>): Promise<ArrayBuffer>;

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 */
declare module 'stream/promises' {
import { FinishedOptions, PipelineSource, PipelineTransform, PipelineDestination, PipelinePromise, PipelineOptions } from 'node:stream';

View File

@@ -1,10 +1,9 @@
/* 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 */
declare module 'stream/web' {
// stub module, pending copy&paste from .d.ts or manual impl
// copy from lib.dom.d.ts
interface ReadableWritablePair<R = any, W = any> {
readable: ReadableStream<R>;
/**
@@ -18,7 +17,6 @@ declare module 'stream/web' {
*/
writable: WritableStream<W>;
}
interface StreamPipeOptions {
preventAbort?: boolean;
preventCancel?: boolean;
@@ -66,70 +64,53 @@ declare module 'stream/web' {
preventClose?: boolean;
signal?: AbortSignal;
}
interface ReadableStreamGenericReader {
readonly closed: Promise<undefined>;
cancel(reason?: any): Promise<void>;
}
interface ReadableStreamDefaultReadValueResult<T> {
done: false;
value: T;
}
interface ReadableStreamDefaultReadDoneResult {
done: true;
value?: undefined;
}
type ReadableStreamController<T> = ReadableStreamDefaultController<T>;
type ReadableStreamDefaultReadResult<T> =
| ReadableStreamDefaultReadValueResult<T>
| ReadableStreamDefaultReadDoneResult;
type ReadableStreamDefaultReadResult<T> = ReadableStreamDefaultReadValueResult<T> | ReadableStreamDefaultReadDoneResult;
interface ReadableByteStreamControllerCallback {
(controller: ReadableByteStreamController): void | PromiseLike<void>;
}
interface UnderlyingSinkAbortCallback {
(reason?: any): void | PromiseLike<void>;
}
interface UnderlyingSinkCloseCallback {
(): void | PromiseLike<void>;
}
interface UnderlyingSinkStartCallback {
(controller: WritableStreamDefaultController): any;
}
interface UnderlyingSinkWriteCallback<W> {
(chunk: W, controller: WritableStreamDefaultController): void | PromiseLike<void>;
}
interface UnderlyingSourceCancelCallback {
(reason?: any): void | PromiseLike<void>;
}
interface UnderlyingSourcePullCallback<R> {
(controller: ReadableStreamController<R>): void | PromiseLike<void>;
}
interface UnderlyingSourceStartCallback<R> {
(controller: ReadableStreamController<R>): any;
}
interface TransformerFlushCallback<O> {
(controller: TransformStreamDefaultController<O>): void | PromiseLike<void>;
}
interface TransformerStartCallback<O> {
(controller: TransformStreamDefaultController<O>): any;
}
interface TransformerTransformCallback<I, O> {
(chunk: I, controller: TransformStreamDefaultController<O>): void | PromiseLike<void>;
}
interface UnderlyingByteSource {
autoAllocateChunkSize?: number;
cancel?: ReadableStreamErrorCallback;
@@ -137,14 +118,12 @@ declare module 'stream/web' {
start?: ReadableByteStreamControllerCallback;
type: 'bytes';
}
interface UnderlyingSource<R = any> {
cancel?: UnderlyingSourceCancelCallback;
pull?: UnderlyingSourcePullCallback<R>;
start?: UnderlyingSourceStartCallback<R>;
type?: undefined;
}
interface UnderlyingSink<W = any> {
abort?: UnderlyingSinkAbortCallback;
close?: UnderlyingSinkCloseCallback;
@@ -152,11 +131,9 @@ declare module 'stream/web' {
type?: undefined;
write?: UnderlyingSinkWriteCallback<W>;
}
interface ReadableStreamErrorCallback {
(reason: any): void | PromiseLike<void>;
}
/** This Streams API interface represents a readable stream of byte data. */
interface ReadableStream<R = any> {
readonly locked: boolean;
@@ -168,29 +145,21 @@ declare module 'stream/web' {
values(options?: { preventCancel?: boolean }): AsyncIterableIterator<R>;
[Symbol.asyncIterator](): AsyncIterableIterator<R>;
}
const ReadableStream: {
prototype: ReadableStream;
new (
underlyingSource: UnderlyingByteSource,
strategy?: QueuingStrategy<Uint8Array>,
): ReadableStream<Uint8Array>;
new (underlyingSource: UnderlyingByteSource, strategy?: QueuingStrategy<Uint8Array>): ReadableStream<Uint8Array>;
new <R = any>(underlyingSource?: UnderlyingSource<R>, strategy?: QueuingStrategy<R>): ReadableStream<R>;
};
interface ReadableStreamDefaultReader<R = any> extends ReadableStreamGenericReader {
read(): Promise<ReadableStreamDefaultReadResult<R>>;
releaseLock(): void;
}
const ReadableStreamDefaultReader: {
prototype: ReadableStreamDefaultReader;
new <R = any>(stream: ReadableStream<R>): ReadableStreamDefaultReader<R>;
};
const ReadableStreamBYOBReader: any;
const ReadableStreamBYOBRequest: any;
interface ReadableByteStreamController {
readonly byobRequest: undefined;
readonly desiredSize: number | null;
@@ -198,24 +167,20 @@ declare module 'stream/web' {
enqueue(chunk: ArrayBufferView): void;
error(error?: any): void;
}
const ReadableByteStreamController: {
prototype: ReadableByteStreamController;
new (): ReadableByteStreamController;
};
interface ReadableStreamDefaultController<R = any> {
readonly desiredSize: number | null;
close(): void;
enqueue(chunk?: R): void;
error(e?: any): void;
}
const ReadableStreamDefaultController: {
prototype: ReadableStreamDefaultController;
new (): ReadableStreamDefaultController;
};
interface Transformer<I = any, O = any> {
flush?: TransformerFlushCallback<O>;
readableType?: undefined;
@@ -223,33 +188,24 @@ declare module 'stream/web' {
transform?: TransformerTransformCallback<I, O>;
writableType?: undefined;
}
interface TransformStream<I = any, O = any> {
readonly readable: ReadableStream<O>;
readonly writable: WritableStream<I>;
}
const TransformStream: {
prototype: TransformStream;
new <I = any, O = any>(
transformer?: Transformer<I, O>,
writableStrategy?: QueuingStrategy<I>,
readableStrategy?: QueuingStrategy<O>,
): TransformStream<I, O>;
new <I = any, O = any>(transformer?: Transformer<I, O>, writableStrategy?: QueuingStrategy<I>, readableStrategy?: QueuingStrategy<O>): TransformStream<I, O>;
};
interface TransformStreamDefaultController<O = any> {
readonly desiredSize: number | null;
enqueue(chunk?: O): void;
error(reason?: any): void;
terminate(): void;
}
const TransformStreamDefaultController: {
prototype: TransformStreamDefaultController;
new (): TransformStreamDefaultController;
};
/**
* This Streams API interface provides a standard abstraction for writing
* streaming data to a destination, known as a sink. This object comes with
@@ -261,12 +217,10 @@ declare module 'stream/web' {
close(): Promise<void>;
getWriter(): WritableStreamDefaultWriter<W>;
}
const WritableStream: {
prototype: WritableStream;
new <W = any>(underlyingSink?: UnderlyingSink<W>, strategy?: QueuingStrategy<W>): WritableStream<W>;
};
/**
* This Streams API interface is the object returned by
* WritableStream.getWriter() and once created locks the < writer to the
@@ -282,12 +236,10 @@ declare module 'stream/web' {
releaseLock(): void;
write(chunk?: W): Promise<void>;
}
const WritableStreamDefaultWriter: {
prototype: WritableStreamDefaultWriter;
new <W = any>(stream: WritableStream<W>): WritableStreamDefaultWriter<W>;
};
/**
* This Streams API interface represents a controller allowing control of a
* WritableStream's state. When constructing a WritableStream, the
@@ -297,21 +249,17 @@ declare module 'stream/web' {
interface WritableStreamDefaultController {
error(e?: any): void;
}
const WritableStreamDefaultController: {
prototype: WritableStreamDefaultController;
new (): WritableStreamDefaultController;
};
interface QueuingStrategy<T = any> {
highWaterMark?: number;
size?: QueuingStrategySize<T>;
}
interface QueuingStrategySize<T = any> {
(chunk?: T): number;
}
interface QueuingStrategyInit {
/**
* Creates a new ByteLengthQueuingStrategy with the provided high water
@@ -324,7 +272,6 @@ declare module 'stream/web' {
*/
highWaterMark: number;
}
/**
* This Streams API interface provides a built-in byte length queuing
* strategy that can be used when constructing streams.
@@ -333,12 +280,10 @@ declare module 'stream/web' {
readonly highWaterMark: number;
readonly size: QueuingStrategySize<ArrayBufferView>;
}
const ByteLengthQueuingStrategy: {
prototype: ByteLengthQueuingStrategy;
new (init: QueuingStrategyInit): ByteLengthQueuingStrategy;
};
/**
* This Streams API interface provides a built-in byte length queuing
* strategy that can be used when constructing streams.
@@ -347,12 +292,10 @@ declare module 'stream/web' {
readonly highWaterMark: number;
readonly size: QueuingStrategySize;
}
const CountQueuingStrategy: {
prototype: CountQueuingStrategy;
new (init: QueuingStrategyInit): CountQueuingStrategy;
};
interface TextEncoderStream {
/** Returns "utf-8". */
readonly encoding: 'utf-8';
@@ -360,19 +303,15 @@ declare module 'stream/web' {
readonly writable: WritableStream<string>;
readonly [Symbol.toStringTag]: string;
}
const TextEncoderStream: {
prototype: TextEncoderStream;
new (): TextEncoderStream;
};
interface TextDecoderOptions {
fatal?: boolean;
ignoreBOM?: boolean;
}
type BufferSource = ArrayBufferView | ArrayBuffer;
interface TextDecoderStream {
/** Returns encoding's name, lower cased. */
readonly encoding: string;
@@ -384,7 +323,6 @@ declare module 'stream/web' {
readonly writable: WritableStream<BufferSource>;
readonly [Symbol.toStringTag]: string;
}
const TextDecoderStream: {
prototype: TextDecoderStream;
new (label?: string, options?: TextDecoderOptions): TextDecoderStream;

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 */
/**
* The `string_decoder` module provides an API for decoding `Buffer` objects into
@@ -39,7 +39,7 @@
* decoder.write(Buffer.from([0x82]));
* console.log(decoder.end(Buffer.from([0xAC])));
* ```
* @see [source](https://github.com/nodejs/node/blob/v16.9.0/lib/string_decoder.js)
* @see [source](https://github.com/nodejs/node/blob/v18.0.0/lib/string_decoder.js)
*/
declare module 'string_decoder' {
class StringDecoder {

View File

@@ -1,11 +1,19 @@
/* 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 */
/**
* The `node:test` module provides a standalone testing module.
* @see [source](https://github.com/nodejs/node/blob/v16.17.0/lib/test.js)
* @see [source](https://github.com/nodejs/node/blob/v18.8.0/lib/test.js)
*/
declare module 'node:test' {
/**
* Programmatically start the test runner.
* @since v18.9.0
* @param options Configuration options for running tests.
* @returns A {@link TapStream} that emits events about the test execution.
*/
function run(options?: RunOptions): TapStream;
/**
* The `test()` function is the value imported from the test module. Each invocation of this
* function results in the creation of a test point in the TAP output.
@@ -31,7 +39,7 @@ declare module 'node:test' {
* });
* });
* ```
* @since v16.17.0
* @since v18.0.0
* @param name The name of the test, which is displayed when reporting test results.
* Default: The `name` property of fn, or `'<anonymous>'` if `fn` does not have a name.
* @param options Configuration options for the test
@@ -45,8 +53,8 @@ declare module 'node:test' {
function test(options?: TestOptions, fn?: TestFn): Promise<void>;
function test(fn?: TestFn): Promise<void>;
/*
* @since v16.17.0
/**
* @since v18.6.0
* @param name The name of the suite, which is displayed when reporting suite results.
* Default: The `name` property of fn, or `'<anonymous>'` if `fn` does not have a name.
* @param options Configuration options for the suite
@@ -57,8 +65,8 @@ declare module 'node:test' {
function describe(options?: TestOptions, fn?: SuiteFn): void;
function describe(fn?: SuiteFn): void;
/*
* @since v16.17.0
/**
* @since v18.6.0
* @param name The name of the test, which is displayed when reporting test results.
* Default: The `name` property of fn, or `'<anonymous>'` if `fn` does not have a name.
* @param options Configuration options for the test
@@ -89,17 +97,133 @@ declare module 'node:test' {
*/
type ItFn = (done: (result?: any) => void) => any;
interface RunOptions {
/**
* @default false
*/
concurrency?: number | boolean;
/**
* An array containing the list of files to run. If unspecified, the test runner execution model will be used.
*/
files?: readonly string[];
/**
* Allows aborting an in-progress test.
* @default undefined
*/
signal?: AbortSignal;
/**
* A number of milliseconds the test will fail after. If unspecified, subtests inherit this
* value from their parent.
* @default Infinity
*/
timeout?: number;
}
/**
* A successful call of the run() method will return a new TapStream object, streaming a TAP output.
* TapStream will emit events in the order of the tests' definitions.
* @since v18.9.0
*/
interface TapStream extends NodeJS.ReadableStream {
addListener(event: 'test:diagnostic', listener: (message: string) => void): this;
addListener(event: 'test:fail', listener: (data: TestFail) => void): this;
addListener(event: 'test:pass', listener: (data: TestPass) => void): this;
addListener(event: string, listener: (...args: any[]) => void): this;
emit(event: 'test:diagnostic', message: string): boolean;
emit(event: 'test:fail', data: TestFail): boolean;
emit(event: 'test:pass', data: TestPass): boolean;
emit(event: string | symbol, ...args: any[]): boolean;
on(event: 'test:diagnostic', listener: (message: string) => void): this;
on(event: 'test:fail', listener: (data: TestFail) => void): this;
on(event: 'test:pass', listener: (data: TestPass) => void): this;
on(event: string, listener: (...args: any[]) => void): this;
once(event: 'test:diagnostic', listener: (message: string) => void): this;
once(event: 'test:fail', listener: (data: TestFail) => void): this;
once(event: 'test:pass', listener: (data: TestPass) => void): this;
once(event: string, listener: (...args: any[]) => void): this;
prependListener(event: 'test:diagnostic', listener: (message: string) => void): this;
prependListener(event: 'test:fail', listener: (data: TestFail) => void): this;
prependListener(event: 'test:pass', listener: (data: TestPass) => void): this;
prependListener(event: string, listener: (...args: any[]) => void): this;
prependOnceListener(event: 'test:diagnostic', listener: (message: string) => void): this;
prependOnceListener(event: 'test:fail', listener: (data: TestFail) => void): this;
prependOnceListener(event: 'test:pass', listener: (data: TestPass) => void): this;
prependOnceListener(event: string, listener: (...args: any[]) => void): this;
}
interface TestFail {
/**
* The test duration.
*/
duration: number;
/**
* The failure casing test to fail.
*/
error: Error;
/**
* The test name.
*/
name: string;
/**
* The ordinal number of the test.
*/
testNumber: number;
/**
* Present if `context.todo` is called.
*/
todo?: string;
/**
* Present if `context.skip` is called.
*/
skip?: string;
}
interface TestPass {
/**
* The test duration.
*/
duration: number;
/**
* The test name.
*/
name: string;
/**
* The ordinal number of the test.
*/
testNumber: number;
/**
* Present if `context.todo` is called.
*/
todo?: string;
/**
* Present if `context.skip` is called.
*/
skip?: string;
}
/**
* An instance of `TestContext` is passed to each test function in order to interact with the
* test runner. However, the `TestContext` constructor is not exposed as part of the API.
* @since v16.17.0
* @since v18.0.0
*/
interface TestContext {
/**
* This function is used to write TAP diagnostics to the output. Any diagnostic information is
* included at the end of the test's results. This function does not return a value.
* @param message Message to be displayed as a TAP diagnostic.
* @since v16.17.0
* @since v18.0.0
*/
diagnostic(message: string): void;
@@ -108,7 +232,7 @@ declare module 'node:test' {
* option set. Otherwise, all tests are run. If Node.js was not started with the `--test-only`
* command-line option, this function is a no-op.
* @param shouldRunOnlyTests Whether or not to run `only` tests.
* @since v16.17.0
* @since v18.0.0
*/
runOnly(shouldRunOnlyTests: boolean): void;
@@ -117,7 +241,7 @@ declare module 'node:test' {
* provided, it is included in the TAP output. Calling `skip()` does not terminate execution of
* the test function. This function does not return a value.
* @param message Optional skip message to be displayed in TAP output.
* @since v16.17.0
* @since v18.0.0
*/
skip(message?: string): void;
@@ -126,14 +250,14 @@ declare module 'node:test' {
* included in the TAP output. Calling `todo()` does not terminate execution of the test
* function. This function does not return a value.
* @param message Optional `TODO` message to be displayed in TAP output.
* @since v16.17.0
* @since v18.0.0
*/
todo(message?: string): void;
/**
* This function is used to create subtests under the current test. This function behaves in
* the same fashion as the top level {@link test} function.
* @since v16.17.0
* @since v18.0.0
* @param name The name of the test, which is displayed when reporting test results.
* Default: The `name` property of fn, or `'<anonymous>'` if `fn` does not have a name.
* @param options Configuration options for the test
@@ -162,7 +286,7 @@ declare module 'node:test' {
/**
* Allows aborting an in-progress test.
* @since v16.17.0
* @since v18.8.0
*/
signal?: AbortSignal;
@@ -177,7 +301,7 @@ declare module 'node:test' {
* A number of milliseconds the test will fail after. If unspecified, subtests inherit this
* value from their parent.
* @default Infinity
* @since v16.17.0
* @since v18.7.0
*/
timeout?: number;
@@ -189,5 +313,65 @@ declare module 'node:test' {
todo?: boolean | string;
}
export { test as default, test, describe, it };
/**
* This function is used to create a hook running before running a suite.
* @param fn The hook function. If the hook uses callbacks, the callback function is passed as
* the second argument. Default: A no-op function.
* @param options Configuration options for the hook.
* @since v18.8.0
*/
function before(fn?: HookFn, options?: HookOptions): void;
/**
* This function is used to create a hook running after running a suite.
* @param fn The hook function. If the hook uses callbacks, the callback function is passed as
* the second argument. Default: A no-op function.
* @param options Configuration options for the hook.
* @since v18.8.0
*/
function after(fn?: HookFn, options?: HookOptions): void;
/**
* This function is used to create a hook running before each subtest of the current suite.
* @param fn The hook function. If the hook uses callbacks, the callback function is passed as
* the second argument. Default: A no-op function.
* @param options Configuration options for the hook.
* @since v18.8.0
*/
function beforeEach(fn?: HookFn, options?: HookOptions): void;
/**
* This function is used to create a hook running after each subtest of the current test.
* @param fn The hook function. If the hook uses callbacks, the callback function is passed as
* the second argument. Default: A no-op function.
* @param options Configuration options for the hook.
* @since v18.8.0
*/
function afterEach(fn?: HookFn, options?: HookOptions): void;
/**
* The hook function. If the hook uses callbacks, the callback function is passed as the
* second argument.
*/
type HookFn = (done: (result?: any) => void) => any;
/**
* Configuration options for hooks.
* @since v18.8.0
*/
interface HookOptions {
/**
* Allows aborting an in-progress hook.
*/
signal?: AbortSignal;
/**
* A number of milliseconds the hook will fail after. If unspecified, subtests inherit this
* value from their parent.
* @default Infinity
*/
timeout?: number;
}
export { test as default, run, test, describe, it, before, after, beforeEach, afterEach };
}

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 */
/**
* The `timer` module exposes a global API for scheduling functions to
@@ -9,7 +9,7 @@
* The timer functions within Node.js implement a similar API as the timers API
* provided by Web Browsers but use a different internal implementation that is
* built around the Node.js [Event Loop](https://nodejs.org/en/docs/guides/event-loop-timers-and-nexttick/#setimmediate-vs-settimeout).
* @see [source](https://github.com/nodejs/node/blob/v16.9.0/lib/timers.js)
* @see [source](https://github.com/nodejs/node/blob/v18.0.0/lib/timers.js)
*/
declare module 'timers' {
import { Abortable } from 'node:events';

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 */
/**
* The `timers/promises` API provides an alternative set of timer functions
@@ -65,31 +65,6 @@ declare module 'timers/promises' {
* @since v15.9.0
*/
function setInterval<T = void>(delay?: number, value?: T, options?: TimerOptions): AsyncIterable<T>;
interface Scheduler {
/**
* ```js
* import { scheduler } from 'node:timers/promises';
*
* await scheduler.wait(1000); // Wait one second before continuing
* ```
* An experimental API defined by the Scheduling APIs draft specification being developed as a standard Web Platform API.
* Calling timersPromises.scheduler.wait(delay, options) is roughly equivalent to calling timersPromises.setTimeout(delay, undefined, options) except that the ref option is not supported.
* @since v16.14.0
* @experimental
* @param [delay=1] The number of milliseconds to wait before fulfilling the promise.
*/
wait: (delay?: number, options?: TimerOptions) => Promise<void>;
/**
* An experimental API defined by the Scheduling APIs draft specification being developed as a standard Web Platform API.
* Calling timersPromises.scheduler.yield() is equivalent to calling timersPromises.setImmediate() with no arguments.
* @since v16.14.0
* @experimental
*/
yield: () => Promise<void>;
}
const scheduler: Scheduler;
}
declare module 'node:timers/promises' {
export * from 'timers/promises';

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 */
/**
* The `tls` module provides an implementation of the Transport Layer Security
@@ -9,11 +9,12 @@
* ```js
* const tls = require('tls');
* ```
* @see [source](https://github.com/nodejs/node/blob/v16.9.0/lib/tls.js)
* @see [source](https://github.com/nodejs/node/blob/v18.0.0/lib/tls.js)
*/
declare module 'tls' {
import { X509Certificate } from 'node:crypto';
import * as net from 'node:net';
import * as stream from 'stream';
const CLIENT_RENEG_LIMIT: number;
const CLIENT_RENEG_WINDOW: number;
interface Certificate {
@@ -145,8 +146,8 @@ declare module 'tls' {
*/
constructor(socket: net.Socket, options?: TLSSocketOptions);
/**
* Returns `true` if the peer certificate was signed by one of the CAs specified
* when creating the `tls.TLSSocket` instance, otherwise `false`.
* This property is `true` if the peer certificate was signed by one of the CAs
* specified when creating the `tls.TLSSocket` instance, otherwise `false`.
* @since v0.11.4
*/
authorized: boolean;
@@ -345,9 +346,9 @@ declare module 'tls' {
* When enabled, TLS packet trace information is written to `stderr`. This can be
* used to debug TLS connection problems.
*
* Note: The format of the output is identical to the output of `openssl s_client -trace` or `openssl s_server -trace`. While it is produced by OpenSSL's`SSL_trace()` function, the format is
* undocumented, can change without notice,
* and should not be relied on.
* The format of the output is identical to the output of`openssl s_client -trace` or `openssl s_server -trace`. While it is produced by
* OpenSSL's `SSL_trace()` function, the format is undocumented, can change
* without notice, and should not be relied on.
* @since v12.2.0
*/
enableTrace(): void;
@@ -376,7 +377,7 @@ declare module 'tls' {
* 128,
* 'client finished');
*
*
* /*
* Example return value of keyingMaterial:
* <Buffer 76 26 af 99 c5 56 8e 42 09 91 ef 9f 93 cb ad 6c 7b 65 f8 53 f1 d8 d9
* 12 5a 33 b8 b5 25 df 7b 37 9f e0 e2 4f b8 67 83 a3 2f cd 5d 41 42 4c 91
@@ -519,7 +520,7 @@ declare module 'tls' {
host?: string | undefined;
port?: number | undefined;
path?: string | undefined; // Creates unix socket connection to path. If this option is specified, `host` and `port` are ignored.
socket?: net.Socket | undefined; // Establish secure connection on a given socket rather than creating a new socket
socket?: stream.Duplex | undefined; // Establish secure connection on a given socket rather than creating a new socket
checkServerIdentity?: typeof checkServerIdentity | undefined;
servername?: string | undefined; // SNI TLS Extension
session?: Buffer | undefined;
@@ -725,7 +726,7 @@ declare module 'tls' {
* object.passphrase is optional. Encrypted keys will be decrypted with
* object.passphrase if provided, or options.passphrase if it is not.
*/
key?: string | Buffer | Array<Buffer | KeyObject> | undefined;
key?: string | Buffer | Array<string | Buffer | KeyObject> | undefined;
/**
* Name of an OpenSSL engine to get private key from. Should be used
* together with privateKeyIdentifier.
@@ -816,13 +817,19 @@ declare module 'tls' {
* Returns [Error](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error) object, populating it with `reason`, `host`, and `cert` on
* failure. On success, returns [undefined](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Undefined_type).
*
* This function can be overwritten by providing alternative function as part of
* the `options.checkServerIdentity` option passed to `tls.connect()`. The
* This function is intended to be used in combination with the`checkServerIdentity` option that can be passed to {@link connect} and as
* such operates on a `certificate object`. For other purposes, consider using `x509.checkHost()` instead.
*
* This function can be overwritten by providing an alternative function as the`options.checkServerIdentity` option that is passed to `tls.connect()`. The
* overwriting function can call `tls.checkServerIdentity()` of course, to augment
* the checks done with additional verification.
*
* This function is only called if the certificate passed all other checks, such as
* being issued by trusted CA (`options.ca`).
*
* Earlier versions of Node.js incorrectly accepted certificates for a given`hostname` if a matching `uniformResourceIdentifier` subject alternative name
* was present (see [CVE-2021-44531](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-44531)). Applications that wish to accept`uniformResourceIdentifier` subject alternative names can use
* a custom`options.checkServerIdentity` function that implements the desired behavior.
* @since v0.8.4
* @param hostname The host name or IP address to verify the certificate against.
* @param cert A `certificate object` representing the peer's certificate.
@@ -975,6 +982,8 @@ declare module 'tls' {
* lower-case for historical reasons, but must be uppercased to be used in
* the `ciphers` option of {@link createSecureContext}.
*
* Not all supported ciphers are enabled by default. See `Modifying the default TLS cipher suite`.
*
* Cipher names that start with `'tls_'` are for TLSv1.3, all the others are for
* TLSv1.2 and below.
*

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