rclnodejs 1.9.0 → 2.0.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (98) hide show
  1. package/.prettierignore +4 -0
  2. package/README.md +2 -2
  3. package/binding.gyp +6 -5
  4. package/lib/action/client.js +5 -4
  5. package/lib/action/uuid.js +1 -1
  6. package/lib/client.js +0 -45
  7. package/lib/distro.js +11 -4
  8. package/lib/interface_loader.js +1 -1
  9. package/lib/message_introspector.js +1 -29
  10. package/lib/message_serialization.js +2 -2
  11. package/lib/native_loader.js +21 -9
  12. package/lib/node.js +2 -2
  13. package/lib/prebuilds.js +47 -0
  14. package/lib/rmw.js +6 -1
  15. package/lib/subscription.js +2 -2
  16. package/package.json +11 -6
  17. package/prebuilds/linux-arm64/humble-jammy-arm64-electron-rclnodejs.node +0 -0
  18. package/prebuilds/linux-arm64/humble-jammy-arm64-node-rclnodejs.node +0 -0
  19. package/prebuilds/linux-arm64/jazzy-noble-arm64-electron-rclnodejs.node +0 -0
  20. package/prebuilds/linux-arm64/jazzy-noble-arm64-node-rclnodejs.node +0 -0
  21. package/prebuilds/linux-arm64/kilted-noble-arm64-electron-rclnodejs.node +0 -0
  22. package/prebuilds/linux-arm64/kilted-noble-arm64-node-rclnodejs.node +0 -0
  23. package/prebuilds/linux-arm64/lyrical-resolute-arm64-electron-rclnodejs.node +0 -0
  24. package/prebuilds/linux-arm64/lyrical-resolute-arm64-node-rclnodejs.node +0 -0
  25. package/prebuilds/linux-x64/humble-jammy-x64-electron-rclnodejs.node +0 -0
  26. package/prebuilds/linux-x64/humble-jammy-x64-node-rclnodejs.node +0 -0
  27. package/prebuilds/linux-x64/jazzy-noble-x64-electron-rclnodejs.node +0 -0
  28. package/prebuilds/linux-x64/jazzy-noble-x64-node-rclnodejs.node +0 -0
  29. package/prebuilds/linux-x64/kilted-noble-x64-electron-rclnodejs.node +0 -0
  30. package/prebuilds/linux-x64/kilted-noble-x64-node-rclnodejs.node +0 -0
  31. package/prebuilds/linux-x64/lyrical-resolute-x64-electron-rclnodejs.node +0 -0
  32. package/prebuilds/linux-x64/lyrical-resolute-x64-node-rclnodejs.node +0 -0
  33. package/rosidl_gen/packages.js +4 -4
  34. package/rosidl_gen/templates/message-template.js +20 -6
  35. package/rosocket/README.md +152 -0
  36. package/rosocket/cli.js +168 -0
  37. package/rosocket/index.js +245 -0
  38. package/scripts/install.js +14 -3
  39. package/scripts/tag_prebuilds.js +26 -9
  40. package/src/rcl_action_client_bindings.cpp +4 -4
  41. package/src/rcl_graph_bindings.cpp +8 -8
  42. package/src/rcl_lifecycle_bindings.cpp +1 -1
  43. package/src/rcl_subscription_bindings.cpp +2 -2
  44. package/src/rcl_utilities.cpp +4 -4
  45. package/src/rcl_utilities.h +2 -2
  46. package/types/distro.d.ts +15 -1
  47. package/prebuilds/linux-arm64/humble-jammy-arm64-rclnodejs.node +0 -0
  48. package/prebuilds/linux-arm64/jazzy-noble-arm64-rclnodejs.node +0 -0
  49. package/prebuilds/linux-arm64/kilted-noble-arm64-rclnodejs.node +0 -0
  50. package/prebuilds/linux-x64/humble-jammy-x64-rclnodejs.node +0 -0
  51. package/prebuilds/linux-x64/jazzy-noble-x64-rclnodejs.node +0 -0
  52. package/prebuilds/linux-x64/kilted-noble-x64-rclnodejs.node +0 -0
  53. package/tools/jsdoc/Makefile +0 -5
  54. package/tools/jsdoc/README.md +0 -96
  55. package/tools/jsdoc/build-index.js +0 -610
  56. package/tools/jsdoc/publish.js +0 -854
  57. package/tools/jsdoc/regenerate-published-docs.js +0 -605
  58. package/tools/jsdoc/static/fonts/OpenSans-Bold-webfont.eot +0 -0
  59. package/tools/jsdoc/static/fonts/OpenSans-Bold-webfont.svg +0 -1830
  60. package/tools/jsdoc/static/fonts/OpenSans-Bold-webfont.woff +0 -0
  61. package/tools/jsdoc/static/fonts/OpenSans-BoldItalic-webfont.eot +0 -0
  62. package/tools/jsdoc/static/fonts/OpenSans-BoldItalic-webfont.svg +0 -1830
  63. package/tools/jsdoc/static/fonts/OpenSans-BoldItalic-webfont.woff +0 -0
  64. package/tools/jsdoc/static/fonts/OpenSans-Italic-webfont.eot +0 -0
  65. package/tools/jsdoc/static/fonts/OpenSans-Italic-webfont.svg +0 -1830
  66. package/tools/jsdoc/static/fonts/OpenSans-Italic-webfont.woff +0 -0
  67. package/tools/jsdoc/static/fonts/OpenSans-Light-webfont.eot +0 -0
  68. package/tools/jsdoc/static/fonts/OpenSans-Light-webfont.svg +0 -1831
  69. package/tools/jsdoc/static/fonts/OpenSans-Light-webfont.woff +0 -0
  70. package/tools/jsdoc/static/fonts/OpenSans-LightItalic-webfont.eot +0 -0
  71. package/tools/jsdoc/static/fonts/OpenSans-LightItalic-webfont.svg +0 -1835
  72. package/tools/jsdoc/static/fonts/OpenSans-LightItalic-webfont.woff +0 -0
  73. package/tools/jsdoc/static/fonts/OpenSans-Regular-webfont.eot +0 -0
  74. package/tools/jsdoc/static/fonts/OpenSans-Regular-webfont.svg +0 -1831
  75. package/tools/jsdoc/static/fonts/OpenSans-Regular-webfont.woff +0 -0
  76. package/tools/jsdoc/static/scripts/linenumber.js +0 -25
  77. package/tools/jsdoc/static/scripts/prettify/Apache-License-2.0.txt +0 -202
  78. package/tools/jsdoc/static/scripts/prettify/lang-css.js +0 -36
  79. package/tools/jsdoc/static/scripts/prettify/prettify.js +0 -738
  80. package/tools/jsdoc/static/styles/jsdoc-default.css +0 -1012
  81. package/tools/jsdoc/static/styles/prettify-jsdoc.css +0 -111
  82. package/tools/jsdoc/static/styles/prettify-tomorrow.css +0 -132
  83. package/tools/jsdoc/tmpl/augments.tmpl +0 -10
  84. package/tools/jsdoc/tmpl/container.tmpl +0 -193
  85. package/tools/jsdoc/tmpl/details.tmpl +0 -143
  86. package/tools/jsdoc/tmpl/example.tmpl +0 -2
  87. package/tools/jsdoc/tmpl/examples.tmpl +0 -13
  88. package/tools/jsdoc/tmpl/exceptions.tmpl +0 -17
  89. package/tools/jsdoc/tmpl/layout.tmpl +0 -83
  90. package/tools/jsdoc/tmpl/mainpage.tmpl +0 -163
  91. package/tools/jsdoc/tmpl/members.tmpl +0 -43
  92. package/tools/jsdoc/tmpl/method.tmpl +0 -124
  93. package/tools/jsdoc/tmpl/params.tmpl +0 -133
  94. package/tools/jsdoc/tmpl/properties.tmpl +0 -110
  95. package/tools/jsdoc/tmpl/returns.tmpl +0 -12
  96. package/tools/jsdoc/tmpl/source.tmpl +0 -8
  97. package/tools/jsdoc/tmpl/tutorial.tmpl +0 -19
  98. package/tools/jsdoc/tmpl/type.tmpl +0 -7
@@ -0,0 +1,4 @@
1
+ # Prettier pads Markdown table separators to match cell width, which bloats
2
+ # long-URL badge tables. Exclude root READMEs to keep them minimal.
3
+ README.md
4
+ scripts/npmjs-readme.md
package/README.md CHANGED
@@ -20,7 +20,7 @@ This example assumes your ROS 2 environment is already sourced.
20
20
 
21
21
  ### Prerequisites
22
22
 
23
- - [Node.js](https://nodejs.org/en/) version >= 16.13.0
23
+ - [Node.js](https://nodejs.org/en/) version >= 20.20.2
24
24
  - [ROS 2 SDK](https://docs.ros.org/en/jazzy/Installation.html)
25
25
 
26
26
  Before installing or running rclnodejs, source your ROS 2 environment:
@@ -52,7 +52,7 @@ rclnodejs ships with prebuilt native binaries for common Linux configurations si
52
52
  - **Ubuntu 22.04 (Jammy)** - ROS 2 Humble
53
53
  - **Ubuntu 24.04 (Noble)** - ROS 2 Jazzy, Kilted
54
54
  - **Architectures:** x64, arm64
55
- - **Node.js:** >= 16.20.2 (N-API compatible)
55
+ - **Node.js:** >= 20.20.2 (N-API compatible)
56
56
 
57
57
  Installations outside this prebuilt matrix automatically fall back to building from source.
58
58
 
package/binding.gyp CHANGED
@@ -12,7 +12,6 @@
12
12
  'runtime%': 'node',
13
13
  'ros_lib_dir': "<!(node -p \"require('./scripts/config.js').getROSLibPath()\")",
14
14
  'ros_include_root': "<!(node -p \"require('./scripts/config.js').getROSIncludeRootPath()\")",
15
- 'node_major_version': '<!(node -p \"process.versions.node.split(\'.\')[0]\")',
16
15
  },
17
16
  'targets': [
18
17
  {
@@ -85,14 +84,15 @@
85
84
  ],
86
85
  'conditions': [
87
86
  [
88
- 'node_major_version >= 23', {
87
+ # Post-Kilted ROS distros require C++20.
88
+ 'ros_version > 2505', {
89
89
  'cflags_cc': [
90
90
  '-std=c++20'
91
91
  ]
92
92
  }
93
93
  ],
94
94
  [
95
- 'node_major_version < 23', {
95
+ 'ros_version <= 2505', {
96
96
  'cflags_cc': [
97
97
  '-std=c++17'
98
98
  ]
@@ -108,14 +108,15 @@
108
108
  ],
109
109
  'conditions': [
110
110
  [
111
- 'node_major_version >= 23', {
111
+ # Post-Kilted ROS distros require C++20.
112
+ 'ros_version > 2505', {
112
113
  'cflags_cc': [
113
114
  '-std=c++20'
114
115
  ]
115
116
  }
116
117
  ],
117
118
  [
118
- 'node_major_version < 23', {
119
+ 'ros_version <= 2505', {
119
120
  'cflags_cc': [
120
121
  '-std=c++17'
121
122
  ]
@@ -94,12 +94,13 @@ class ActionClient extends Entity {
94
94
  };
95
95
 
96
96
  // Enable feedback subscription content filter optimization.
97
- // Only supported on ROS2 Rolling and only effective when the native
98
- // binding provides the required functions AND the RMW implementation
99
- // actually supports content filtering on the feedback subscription.
97
+ // Only supported on ROS2 Lyrical or newer and only effective when the
98
+ // native binding provides the required functions AND the RMW
99
+ // implementation actually supports content filtering on the feedback
100
+ // subscription.
100
101
  this._enableFeedbackMsgOptimization =
101
102
  this._options.enableFeedbackMsgOptimization === true &&
102
- DistroUtils.getDistroId() >= DistroUtils.DistroId.ROLLING &&
103
+ DistroUtils.getDistroId() >= DistroUtils.DistroId.LYRICAL &&
103
104
  typeof rclnodejs.actionConfigureFeedbackSubFilterAddGoalId === 'function';
104
105
 
105
106
  let type = this.typeClass.type();
@@ -40,7 +40,7 @@ class ActionUuid {
40
40
  this._bytes = bytes;
41
41
  } else {
42
42
  // Generate random UUID.
43
- let uuid = randomUUID().replace(/-/g, '');
43
+ let uuid = randomUUID().replaceAll('-', '');
44
44
  this._bytes = Uint8Array.from(Buffer.from(uuid, 'hex'));
45
45
  }
46
46
  }
package/lib/client.js CHANGED
@@ -25,51 +25,6 @@ const {
25
25
  const { assertValidMessage } = require('./message_validation.js');
26
26
  const debug = require('debug')('rclnodejs:client');
27
27
 
28
- // Polyfill for AbortSignal.any() for Node.js <= 20.3.0
29
- // AbortSignal.any() was added in Node.js 20.3.0
30
- // See https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal/any_static
31
- if (!AbortSignal.any) {
32
- AbortSignal.any = function (signals) {
33
- // Filter out null/undefined values and validate inputs
34
- const validSignals = Array.isArray(signals)
35
- ? signals.filter((signal) => signal != null)
36
- : [];
37
-
38
- // If no valid signals, return a never-aborting signal
39
- if (validSignals.length === 0) {
40
- return new AbortController().signal;
41
- }
42
-
43
- const controller = new AbortController();
44
- const listeners = [];
45
-
46
- // Cleanup function to remove all event listeners
47
- const cleanup = () => {
48
- listeners.forEach(({ signal, listener }) => {
49
- signal.removeEventListener('abort', listener);
50
- });
51
- };
52
-
53
- for (const signal of validSignals) {
54
- if (signal.aborted) {
55
- cleanup();
56
- controller.abort(signal.reason);
57
- return controller.signal;
58
- }
59
-
60
- const listener = () => {
61
- cleanup();
62
- controller.abort(signal.reason);
63
- };
64
-
65
- signal.addEventListener('abort', listener);
66
- listeners.push({ signal, listener });
67
- }
68
-
69
- return controller.signal;
70
- };
71
- }
72
-
73
28
  /**
74
29
  * @class - Class representing a Client in ROS
75
30
  * @hideconstructor
package/lib/distro.js CHANGED
@@ -26,7 +26,9 @@ const DistroId = {
26
26
  IRON: 2305,
27
27
  JAZZY: 2405,
28
28
  KILTED: 2505,
29
+ LYRICAL: 2605,
29
30
  ROLLING: 5000,
31
+ FUTURE: 9999, // unrecognized ROS_DISTRO assumed newer than Rolling
30
32
  };
31
33
 
32
34
  const DistroNameIdMap = new Map();
@@ -37,6 +39,7 @@ DistroNameIdMap.set('humble', DistroId.HUMBLE);
37
39
  DistroNameIdMap.set('iron', DistroId.IRON);
38
40
  DistroNameIdMap.set('jazzy', DistroId.JAZZY);
39
41
  DistroNameIdMap.set('kilted', DistroId.KILTED);
42
+ DistroNameIdMap.set('lyrical', DistroId.LYRICAL);
40
43
  DistroNameIdMap.set('rolling', DistroId.ROLLING);
41
44
 
42
45
  const DistroUtils = {
@@ -48,11 +51,15 @@ const DistroUtils = {
48
51
  * @return {number} Return the rclnodejs distro identifier
49
52
  */
50
53
  getDistroId: function (distroName) {
51
- const dname = distroName ? distroName.toLowerCase() : this.getDistroName();
54
+ const dname =
55
+ (distroName || this.getDistroName() || '').toLowerCase() || undefined;
52
56
 
53
- return DistroNameIdMap.has(dname)
54
- ? DistroNameIdMap.get(dname)
55
- : DistroId.UNKNOWN;
57
+ if (dname && DistroNameIdMap.has(dname)) {
58
+ return DistroNameIdMap.get(dname);
59
+ }
60
+
61
+ // Unrecognized but provided/resolved distro name → assume future; unset → unknown
62
+ return dname ? DistroId.FUTURE : DistroId.UNKNOWN;
56
63
  },
57
64
 
58
65
  /**
@@ -57,7 +57,7 @@ let interfaceLoader = {
57
57
  }
58
58
 
59
59
  // TODO(Kenny): more checks of the string argument
60
- if (name.indexOf('/') !== -1) {
60
+ if (name.includes('/')) {
61
61
  let [packageName, type, messageName] = name.split('/');
62
62
  return this.loadInterface(packageName, type, messageName);
63
63
  }
@@ -88,35 +88,7 @@ class MessageIntrospector {
88
88
  const instance = new this.#typeClass();
89
89
  this.#defaultsCache = toPlainObject(instance);
90
90
  }
91
- return this.#deepClone(this.#defaultsCache);
92
- }
93
-
94
- /**
95
- * Deep clone an object.
96
- * @param {any} obj - Object to clone
97
- * @returns {any} Cloned object
98
- * @private
99
- */
100
- #deepClone(obj) {
101
- if (obj === null || typeof obj !== 'object') {
102
- return obj;
103
- }
104
-
105
- if (Array.isArray(obj)) {
106
- return obj.map((item) => this.#deepClone(item));
107
- }
108
-
109
- if (ArrayBuffer.isView(obj) && !(obj instanceof DataView)) {
110
- return obj.slice();
111
- }
112
-
113
- const cloned = {};
114
- for (const key in obj) {
115
- if (Object.prototype.hasOwnProperty.call(obj, key)) {
116
- cloned[key] = this.#deepClone(obj[key]);
117
- }
118
- }
119
- return cloned;
91
+ return structuredClone(this.#defaultsCache);
120
92
  }
121
93
  }
122
94
 
@@ -62,7 +62,7 @@ function toPlainArrays(obj) {
62
62
  if (typeof obj === 'object' && obj !== null) {
63
63
  const result = {};
64
64
  for (const key in obj) {
65
- if (Object.prototype.hasOwnProperty.call(obj, key)) {
65
+ if (Object.hasOwn(obj, key)) {
66
66
  result[key] = toPlainArrays(obj[key]);
67
67
  }
68
68
  }
@@ -105,7 +105,7 @@ function toJSONSafe(obj) {
105
105
  if (typeof obj === 'object' && obj !== null) {
106
106
  const result = {};
107
107
  for (const key in obj) {
108
- if (Object.prototype.hasOwnProperty.call(obj, key)) {
108
+ if (Object.hasOwn(obj, key)) {
109
109
  result[key] = toJSONSafe(obj[key]);
110
110
  }
111
111
  }
@@ -20,6 +20,10 @@ const { execSync } = require('child_process');
20
20
  const { NativeError } = require('./errors.js');
21
21
  const bindings = require('bindings');
22
22
  const debug = require('debug')('rclnodejs');
23
+ const {
24
+ detectPrebuildRuntime,
25
+ getTaggedPrebuildFilename,
26
+ } = require('./prebuilds');
23
27
  const { detectUbuntuCodename } = require('./utils');
24
28
 
25
29
  let nativeModule = null;
@@ -35,6 +39,7 @@ function customFallbackLoader() {
35
39
 
36
40
  const rosDistro = process.env.ROS_DISTRO;
37
41
  const arch = process.arch;
42
+ const runtime = detectPrebuildRuntime();
38
43
  const ubuntuCodename = detectUbuntuCodename();
39
44
 
40
45
  // Require all three components for exact match
@@ -58,16 +63,22 @@ function customFallbackLoader() {
58
63
  }
59
64
 
60
65
  try {
61
- // Look for exact match binary: {ros_distro}-{ubuntu_codename}-{arch}-rclnodejs.node
62
- const exactMatchFilename = `${rosDistro}-${ubuntuCodename}-${arch}-rclnodejs.node`;
63
- const exactMatchPath = path.join(prebuildDir, exactMatchFilename);
64
-
65
- if (fs.existsSync(exactMatchPath)) {
66
- debug(`Found exact match binary: ${exactMatchFilename}`);
67
- return require(exactMatchPath);
66
+ const candidate = getTaggedPrebuildFilename({
67
+ rosDistro,
68
+ ubuntuCodename,
69
+ arch,
70
+ runtime,
71
+ });
72
+ const candidatePath = path.join(prebuildDir, candidate);
73
+
74
+ if (fs.existsSync(candidatePath)) {
75
+ debug(`Found ${runtime} prebuilt binary: ${candidate}`);
76
+ return require(candidatePath);
68
77
  }
69
78
 
70
- debug(`No exact match found for: ${exactMatchFilename}`);
79
+ debug(
80
+ `No matching ${runtime} prebuilt binary found for ${rosDistro}-${ubuntuCodename}-${arch}`
81
+ );
71
82
  return null;
72
83
  } catch (e) {
73
84
  debug('Error in simplified prebuilt loader:', e.message);
@@ -110,10 +121,11 @@ function loadNativeAddon() {
110
121
  }
111
122
 
112
123
  const rosDistro = process.env.ROS_DISTRO;
124
+ const runtime = detectPrebuildRuntime();
113
125
  const ubuntuCodename = detectUbuntuCodename();
114
126
 
115
127
  debug(
116
- `Platform: ${process.platform}, Arch: ${process.arch}, Ubuntu: ${ubuntuCodename || 'unknown'}, ROS: ${rosDistro || 'unknown'}`
128
+ `Platform: ${process.platform}, Arch: ${process.arch}, Runtime: ${runtime}, Ubuntu: ${ubuntuCodename || 'unknown'}, ROS: ${rosDistro || 'unknown'}`
117
129
  );
118
130
 
119
131
  // Prebuilt binaries are only supported on Linux (Ubuntu)
package/lib/node.js CHANGED
@@ -1587,7 +1587,7 @@ class Node extends rclnodejs.ShadowNode {
1587
1587
  * @returns {Array} - list of clients
1588
1588
  */
1589
1589
  getClientsInfoByService(service, noDemangle = false) {
1590
- if (DistroUtils.getDistroId() < DistroUtils.DistroId.ROLLING) {
1590
+ if (DistroUtils.getDistroId() < DistroUtils.DistroId.LYRICAL) {
1591
1591
  console.warn(
1592
1592
  'getClientsInfoByService is not supported by this version of ROS 2'
1593
1593
  );
@@ -1621,7 +1621,7 @@ class Node extends rclnodejs.ShadowNode {
1621
1621
  * @returns {Array} - list of servers
1622
1622
  */
1623
1623
  getServersInfoByService(service, noDemangle = false) {
1624
- if (DistroUtils.getDistroId() < DistroUtils.DistroId.ROLLING) {
1624
+ if (DistroUtils.getDistroId() < DistroUtils.DistroId.LYRICAL) {
1625
1625
  console.warn(
1626
1626
  'getServersInfoByService is not supported by this version of ROS 2'
1627
1627
  );
@@ -0,0 +1,47 @@
1
+ // Copyright (c) 2026, The Robot Web Tools Contributors
2
+ //
3
+ // Licensed under the Apache License, Version 2.0 (the "License");
4
+ // you may not use this file except in compliance with the License.
5
+ // You may obtain a copy of the License at
6
+ //
7
+ // http://www.apache.org/licenses/LICENSE-2.0
8
+ //
9
+ // Unless required by applicable law or agreed to in writing, software
10
+ // distributed under the License is distributed on an "AS IS" BASIS,
11
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ // See the License for the specific language governing permissions and
13
+ // limitations under the License.
14
+
15
+ 'use strict';
16
+
17
+ const PREBUILD_PACKAGE_NAME = 'rclnodejs';
18
+ const SUPPORTED_PREBUILD_RUNTIMES = new Set(['node', 'electron']);
19
+
20
+ function detectPrebuildRuntime() {
21
+ if (process.env.npm_config_runtime === 'electron') {
22
+ return 'electron';
23
+ }
24
+
25
+ return process.versions.electron ? 'electron' : 'node';
26
+ }
27
+
28
+ function getTaggedPrebuildFilename({
29
+ rosDistro,
30
+ ubuntuCodename,
31
+ arch,
32
+ runtime,
33
+ }) {
34
+ return `${rosDistro}-${ubuntuCodename}-${arch}-${runtime}-${PREBUILD_PACKAGE_NAME}.node`;
35
+ }
36
+
37
+ function getRuntimeFromGeneratedPrebuild(fileName) {
38
+ const runtime = fileName.split('.')[0];
39
+ return SUPPORTED_PREBUILD_RUNTIMES.has(runtime) ? runtime : null;
40
+ }
41
+
42
+ module.exports = {
43
+ detectPrebuildRuntime,
44
+ getRuntimeFromGeneratedPrebuild,
45
+ getTaggedPrebuildFilename,
46
+ PREBUILD_PACKAGE_NAME,
47
+ };
package/lib/rmw.js CHANGED
@@ -19,6 +19,7 @@ const RMWNames = {
19
19
  CONNEXT: 'rmw_connext_cpp',
20
20
  CYCLONEDDS: 'rmw_cyclonedds_cpp',
21
21
  GURUMDDS: 'rmw_gurumdds_cpp',
22
+ ZENOH: 'rmw_zenoh_cpp',
22
23
  };
23
24
 
24
25
  const DefaultRosRMWNameMap = new Map();
@@ -26,6 +27,9 @@ DefaultRosRMWNameMap.set('eloquent', RMWNames.FASTRTPS);
26
27
  DefaultRosRMWNameMap.set('foxy', RMWNames.FASTRTPS);
27
28
  DefaultRosRMWNameMap.set('galactic', RMWNames.CYCLONEDDS);
28
29
  DefaultRosRMWNameMap.set('humble', RMWNames.FASTRTPS);
30
+ DefaultRosRMWNameMap.set('iron', RMWNames.FASTRTPS);
31
+ DefaultRosRMWNameMap.set('jazzy', RMWNames.FASTRTPS);
32
+ DefaultRosRMWNameMap.set('kilted', RMWNames.FASTRTPS);
29
33
  DefaultRosRMWNameMap.set('rolling', RMWNames.FASTRTPS);
30
34
 
31
35
  const RMWUtils = {
@@ -34,7 +38,8 @@ const RMWUtils = {
34
38
  getRMWName: function () {
35
39
  return process.env.RMW_IMPLEMENTATION
36
40
  ? process.env.RMW_IMPLEMENTATION
37
- : DefaultRosRMWNameMap.get(DistroUtils.getDistroName());
41
+ : DefaultRosRMWNameMap.get(DistroUtils.getDistroName()) ||
42
+ RMWNames.FASTRTPS;
38
43
  },
39
44
  };
40
45
 
@@ -147,11 +147,11 @@ class Subscription extends Entity {
147
147
 
148
148
  /**
149
149
  * Check if content filtering is supported for this subscription.
150
- * Requires ROS 2 Rolling or later.
150
+ * Requires ROS 2 Lyrical or later.
151
151
  * @returns {boolean} True if the subscription instance supports content filtering; otherwise false.
152
152
  */
153
153
  isContentFilterSupported() {
154
- if (DistroUtils.getDistroId() < DistroUtils.DistroId.ROLLING) {
154
+ if (DistroUtils.getDistroId() < DistroUtils.DistroId.LYRICAL) {
155
155
  return false;
156
156
  }
157
157
  return rclnodejs.isContentFilterSupported(this.handle);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rclnodejs",
3
- "version": "1.9.0",
3
+ "version": "2.0.0-beta.0",
4
4
  "description": "ROS2.0 JavaScript client with Node.js",
5
5
  "main": "index.js",
6
6
  "types": "types/index.d.ts",
@@ -34,10 +34,14 @@
34
34
  "format": "clang-format -i -style=file ./src/*.cpp ./src/*.h && npx --yes prettier --write \"{lib,rosidl_gen,rostsd_gen,rosidl_parser,types,example,test,scripts,benchmark,rostsd_gen}/**/*.{js,md,ts}\" ./*.{js,md,ts}",
35
35
  "prepare": "husky",
36
36
  "coverage": "cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js",
37
- "prebuild": "prebuildify --napi --strip --target 16.20.2 --target electron@23.0.0 && node scripts/tag_prebuilds.js"
37
+ "prebuild:node": "prebuildify --napi --strip --name node --target 20.20.2",
38
+ "prebuild:electron": "prebuildify --napi --strip --name electron --target electron@34.0.0",
39
+ "prebuild": "npm run prebuild:node && npm run prebuild:electron && node scripts/tag_prebuilds.js",
40
+ "rosocket": "node ./rosocket/cli.js"
38
41
  },
39
42
  "bin": {
40
- "generate-ros-messages": "./scripts/generate_messages.js"
43
+ "generate-ros-messages": "./scripts/generate_messages.js",
44
+ "rosocket": "./rosocket/cli.js"
41
45
  },
42
46
  "authors": [
43
47
  "Minggang Wang <minggangw@gmail.com>",
@@ -67,7 +71,7 @@
67
71
  "jsdoc": "^4.0.4",
68
72
  "lint-staged": "^16.2.0",
69
73
  "mocha": "^11.0.2",
70
- "node-gyp": "^10.3.1",
74
+ "node-gyp": "^12.2.0",
71
75
  "nyc": "^18.0.0",
72
76
  "prebuildify": "^6.0.1",
73
77
  "rimraf": "^6.0.1",
@@ -84,7 +88,8 @@
84
88
  "json-bigint": "^1.0.0",
85
89
  "node-addon-api": "^8.3.1",
86
90
  "rxjs": "^7.8.1",
87
- "walk": "^2.3.15"
91
+ "walk": "^2.3.15",
92
+ "ws": "^8.18.0"
88
93
  },
89
94
  "husky": {
90
95
  "hooks": {
@@ -103,6 +108,6 @@
103
108
  "directory": "test/types"
104
109
  },
105
110
  "engines": {
106
- "node": ">= 16.13.0"
111
+ "node": ">= 20.20.2"
107
112
  }
108
113
  }
@@ -29,7 +29,7 @@ const serviceMsgPath = path.join(generatedRoot, 'srv_msg');
29
29
 
30
30
  function getPackageName(filePath, amentExecuted) {
31
31
  if (os.type() === 'Windows_NT') {
32
- filePath = filePath.replace(/\\/g, '/');
32
+ filePath = filePath.replaceAll('\\', '/');
33
33
  }
34
34
 
35
35
  if (amentExecuted) {
@@ -41,14 +41,14 @@ function getPackageName(filePath, amentExecuted) {
41
41
 
42
42
  // If |packageName| equals to the file's extension, e.g. msg/srv, one level
43
43
  // up directory will be used as the package name.
44
- return packageName === path.parse(filePath).ext.substr(1)
44
+ return packageName === path.parse(filePath).ext.substring(1)
45
45
  ? folders.pop()
46
46
  : packageName;
47
47
  }
48
48
 
49
49
  function getSubFolder(filePath, amentExecuted) {
50
50
  if (os.type() === 'Windows_NT') {
51
- filePath = filePath.replace(/\\/g, '/');
51
+ filePath = filePath.replaceAll('\\', '/');
52
52
  }
53
53
 
54
54
  if (amentExecuted) {
@@ -61,7 +61,7 @@ function getSubFolder(filePath, amentExecuted) {
61
61
  }
62
62
  // If the |amentExecuted| equals to false, the file's extension will be assigned as
63
63
  // the name of sub folder.
64
- return path.parse(filePath).ext.substr(1);
64
+ return path.parse(filePath).ext.substring(1);
65
65
  }
66
66
 
67
67
  function grabInterfaceInfo(filePath, amentExecuted) {
@@ -156,15 +156,15 @@ const typedArrayType = [
156
156
  ];
157
157
 
158
158
  function isPrimitivePackage(baseType) {
159
- return primitiveBaseType.indexOf(baseType.type) !== -1;
159
+ return primitiveBaseType.includes(baseType.type);
160
160
  }
161
161
 
162
162
  function isTypedArrayType(type) {
163
- return typedArrayType.indexOf(type.type.toLowerCase()) !== -1;
163
+ return typedArrayType.includes(type.type.toLowerCase());
164
164
  }
165
165
 
166
166
  function isBigInt(type) {
167
- return ['int64', 'uint64'].indexOf(type.type.toLowerCase()) !== -1;
167
+ return ['int64', 'uint64'].includes(type.type.toLowerCase());
168
168
  }
169
169
 
170
170
  function getWrapperNameByType(type) {
@@ -265,6 +265,14 @@ function generateMessage(data) {
265
265
  const currentTypedArray = getTypedArrayName(spec.baseType);
266
266
  const currentTypedArrayElementType = getTypedArrayElementName(spec.baseType);
267
267
 
268
+ // ROS 2 Rolling (ros2/rosidl#941) added is_rosidl_buffer / owns_rosidl_buffer
269
+ // to every primitive sequence struct. Lyrical inherits the same ABI change.
270
+ // Emit the extra fields only for primitive-package types on Lyrical+.
271
+ const DistroUtils = require('../../lib/distro.js');
272
+ const needsRosidlBufferFields =
273
+ isPrimitivePackage(spec.baseType) &&
274
+ DistroUtils.getDistroId() >= DistroUtils.DistroId.LYRICAL;
275
+
268
276
  // Track required modules
269
277
  let existedModules = [];
270
278
  function shouldRequire(baseType, fieldType) {
@@ -275,7 +283,7 @@ function generateMessage(data) {
275
283
  !fieldType.isPrimitiveType ||
276
284
  fieldType.type === 'string');
277
285
 
278
- if (shouldReq && existedModules.indexOf(requiredModule) === -1) {
286
+ if (shouldReq && !existedModules.includes(requiredModule)) {
279
287
  existedModules.push(requiredModule);
280
288
  return true;
281
289
  } else {
@@ -347,7 +355,13 @@ ${
347
355
  : ` data: ${refArrayType},`
348
356
  }
349
357
  size: ref.types.size_t,
350
- capacity: ref.types.size_t
358
+ capacity: ref.types.size_t,
359
+ ${
360
+ needsRosidlBufferFields
361
+ ? ` is_rosidl_buffer: ref.types.bool,
362
+ owns_rosidl_buffer: ref.types.bool,`
363
+ : ''
364
+ }
351
365
  });
352
366
 
353
367
  ${generateWrapperClass()}
@@ -678,7 +692,7 @@ ${spec.fields
678
692
 
679
693
  hasMember(name) {
680
694
  let memberNames = ${extractMemberNames(spec.fields)};
681
- return memberNames.indexOf(name) !== -1;
695
+ return memberNames.includes(name);
682
696
  }
683
697
  }`;
684
698
  }