rclnodejs 1.6.0 → 1.8.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 (84) hide show
  1. package/binding.gyp +2 -0
  2. package/index.js +152 -0
  3. package/lib/action/client.js +109 -10
  4. package/lib/action/deferred.js +8 -2
  5. package/lib/action/server.js +10 -1
  6. package/lib/action/uuid.js +4 -1
  7. package/lib/client.js +218 -4
  8. package/lib/clock.js +182 -1
  9. package/lib/clock_change.js +49 -0
  10. package/lib/clock_event.js +88 -0
  11. package/lib/context.js +12 -2
  12. package/lib/duration.js +37 -12
  13. package/lib/errors.js +621 -0
  14. package/lib/event_handler.js +21 -4
  15. package/lib/interface_loader.js +52 -12
  16. package/lib/lifecycle.js +8 -2
  17. package/lib/logging.js +90 -3
  18. package/lib/message_introspector.js +123 -0
  19. package/lib/message_serialization.js +10 -2
  20. package/lib/message_validation.js +512 -0
  21. package/lib/native_loader.js +9 -4
  22. package/lib/node.js +403 -50
  23. package/lib/node_options.js +40 -1
  24. package/lib/observable_subscription.js +105 -0
  25. package/lib/parameter.js +172 -35
  26. package/lib/parameter_client.js +506 -0
  27. package/lib/parameter_watcher.js +309 -0
  28. package/lib/publisher.js +56 -1
  29. package/lib/qos.js +79 -5
  30. package/lib/rate.js +6 -1
  31. package/lib/serialization.js +7 -2
  32. package/lib/subscription.js +8 -0
  33. package/lib/time.js +136 -21
  34. package/lib/time_source.js +13 -4
  35. package/lib/timer.js +42 -0
  36. package/lib/utils.js +27 -1
  37. package/lib/validator.js +74 -19
  38. package/package.json +4 -2
  39. package/prebuilds/linux-arm64/humble-jammy-arm64-rclnodejs.node +0 -0
  40. package/prebuilds/linux-arm64/jazzy-noble-arm64-rclnodejs.node +0 -0
  41. package/prebuilds/linux-arm64/kilted-noble-arm64-rclnodejs.node +0 -0
  42. package/prebuilds/linux-x64/humble-jammy-x64-rclnodejs.node +0 -0
  43. package/prebuilds/linux-x64/jazzy-noble-x64-rclnodejs.node +0 -0
  44. package/prebuilds/linux-x64/kilted-noble-x64-rclnodejs.node +0 -0
  45. package/rosidl_gen/message_translator.js +0 -61
  46. package/scripts/config.js +1 -0
  47. package/src/addon.cpp +2 -0
  48. package/src/clock_event.cpp +268 -0
  49. package/src/clock_event.hpp +62 -0
  50. package/src/macros.h +2 -4
  51. package/src/rcl_action_server_bindings.cpp +21 -3
  52. package/src/rcl_bindings.cpp +59 -0
  53. package/src/rcl_context_bindings.cpp +5 -0
  54. package/src/rcl_graph_bindings.cpp +73 -0
  55. package/src/rcl_logging_bindings.cpp +158 -0
  56. package/src/rcl_node_bindings.cpp +14 -2
  57. package/src/rcl_publisher_bindings.cpp +12 -0
  58. package/src/rcl_service_bindings.cpp +7 -6
  59. package/src/rcl_subscription_bindings.cpp +51 -14
  60. package/src/rcl_time_point_bindings.cpp +135 -0
  61. package/src/rcl_timer_bindings.cpp +140 -0
  62. package/src/rcl_utilities.cpp +103 -2
  63. package/src/rcl_utilities.h +7 -1
  64. package/types/action_client.d.ts +27 -2
  65. package/types/base.d.ts +6 -0
  66. package/types/client.d.ts +65 -1
  67. package/types/clock.d.ts +86 -0
  68. package/types/clock_change.d.ts +27 -0
  69. package/types/clock_event.d.ts +51 -0
  70. package/types/errors.d.ts +496 -0
  71. package/types/index.d.ts +10 -0
  72. package/types/logging.d.ts +32 -0
  73. package/types/message_introspector.d.ts +75 -0
  74. package/types/message_validation.d.ts +183 -0
  75. package/types/node.d.ts +107 -0
  76. package/types/node_options.d.ts +13 -0
  77. package/types/observable_subscription.d.ts +39 -0
  78. package/types/parameter_client.d.ts +252 -0
  79. package/types/parameter_watcher.d.ts +104 -0
  80. package/types/publisher.d.ts +28 -1
  81. package/types/qos.d.ts +18 -0
  82. package/types/subscription.d.ts +6 -0
  83. package/types/timer.d.ts +18 -0
  84. package/types/validator.d.ts +86 -0
package/lib/errors.js ADDED
@@ -0,0 +1,621 @@
1
+ // Copyright (c) 2025 Mahmoud Alghalayini. All rights reserved.
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
+ /**
18
+ * Base error class for all rclnodejs errors.
19
+ * Provides structured error information with context.
20
+ * @class
21
+ */
22
+ class RclNodeError extends Error {
23
+ /**
24
+ * @param {string} message - Human-readable error message
25
+ * @param {object} [options] - Additional error context
26
+ * @param {string} [options.code] - Machine-readable error code (e.g., 'TIMEOUT', 'INVALID_ARGUMENT')
27
+ * @param {string} [options.nodeName] - Name of the node where error occurred
28
+ * @param {string} [options.entityType] - Type of entity (publisher, subscription, client, etc.)
29
+ * @param {string} [options.entityName] - Name of the entity (topic name, service name, etc.)
30
+ * @param {Error} [options.cause] - Original error that caused this error
31
+ * @param {any} [options.details] - Additional error-specific details
32
+ */
33
+ constructor(message, options = {}) {
34
+ super(message);
35
+
36
+ // Maintains proper stack trace for where our error was thrown
37
+ Error.captureStackTrace(this, this.constructor);
38
+
39
+ this.name = this.constructor.name;
40
+ this.code = options.code || 'UNKNOWN_ERROR';
41
+ this.nodeName = options.nodeName;
42
+ this.entityType = options.entityType;
43
+ this.entityName = options.entityName;
44
+ this.details = options.details;
45
+
46
+ // Error chaining (ES2022 feature, Node.js 16.9+)
47
+ if (options.cause) {
48
+ this.cause = options.cause;
49
+ }
50
+
51
+ // Timestamp for logging/debugging
52
+ this.timestamp = new Date();
53
+ }
54
+
55
+ /**
56
+ * Returns a detailed error object for logging/serialization
57
+ * @return {object} Structured error information
58
+ */
59
+ toJSON() {
60
+ return {
61
+ name: this.name,
62
+ message: this.message,
63
+ code: this.code,
64
+ nodeName: this.nodeName,
65
+ entityType: this.entityType,
66
+ entityName: this.entityName,
67
+ details: this.details,
68
+ timestamp: this.timestamp.toISOString(),
69
+ stack: this.stack,
70
+ cause: this.cause
71
+ ? this.cause.toJSON?.() || this.cause.message
72
+ : undefined,
73
+ };
74
+ }
75
+
76
+ /**
77
+ * Returns a user-friendly error description
78
+ * @return {string} Formatted error string
79
+ */
80
+ toString() {
81
+ let str = `${this.name}: ${this.message}`;
82
+ if (this.code) str += ` [${this.code}]`;
83
+ if (this.nodeName) str += ` (node: ${this.nodeName})`;
84
+ if (this.entityName)
85
+ str += ` (${this.entityType || 'entity'}: ${this.entityName})`;
86
+ return str;
87
+ }
88
+ }
89
+
90
+ /**
91
+ * Error thrown when validation fails
92
+ * @class
93
+ * @extends RclNodeError
94
+ */
95
+ class ValidationError extends RclNodeError {
96
+ /**
97
+ * @param {string} message - Error message
98
+ * @param {object} [options] - Additional options
99
+ * @param {string} [options.argumentName] - Name of the argument that failed validation
100
+ * @param {any} [options.providedValue] - The value that was provided
101
+ * @param {string} [options.expectedType] - The expected type or format
102
+ * @param {string} [options.validationRule] - The validation rule that failed
103
+ */
104
+ constructor(message, options = {}) {
105
+ super(message, { code: 'VALIDATION_ERROR', ...options });
106
+ this.argumentName = options.argumentName;
107
+ this.providedValue = options.providedValue;
108
+ this.expectedType = options.expectedType;
109
+ this.validationRule = options.validationRule;
110
+ }
111
+ }
112
+
113
+ /**
114
+ * Type validation error
115
+ * @class
116
+ * @extends ValidationError
117
+ */
118
+ class TypeValidationError extends ValidationError {
119
+ /**
120
+ * @param {string} argumentName - Name of the argument
121
+ * @param {any} providedValue - The value that was provided
122
+ * @param {string} expectedType - The expected type
123
+ * @param {object} [options] - Additional options
124
+ */
125
+ constructor(argumentName, providedValue, expectedType, options = {}) {
126
+ super(
127
+ `Invalid type for '${argumentName}': expected ${expectedType}, got ${typeof providedValue}`,
128
+ {
129
+ code: 'INVALID_TYPE',
130
+ argumentName,
131
+ providedValue,
132
+ expectedType,
133
+ ...options,
134
+ }
135
+ );
136
+ }
137
+ }
138
+
139
+ /**
140
+ * Range/value validation error
141
+ * @class
142
+ * @extends ValidationError
143
+ */
144
+ class RangeValidationError extends ValidationError {
145
+ /**
146
+ * @param {string} argumentName - Name of the argument
147
+ * @param {any} providedValue - The value that was provided
148
+ * @param {string} constraint - The constraint that was violated
149
+ * @param {object} [options] - Additional options
150
+ */
151
+ constructor(argumentName, providedValue, constraint, options = {}) {
152
+ super(
153
+ `Value '${providedValue}' for '${argumentName}' is out of range: ${constraint}`,
154
+ {
155
+ code: 'OUT_OF_RANGE',
156
+ argumentName,
157
+ providedValue,
158
+ validationRule: constraint,
159
+ ...options,
160
+ }
161
+ );
162
+ }
163
+ }
164
+
165
+ /**
166
+ * Message validation error for ROS message structure/type issues
167
+ * @class
168
+ * @extends ValidationError
169
+ */
170
+ class MessageValidationError extends ValidationError {
171
+ /**
172
+ * @param {string} messageType - The ROS message type (e.g., 'std_msgs/msg/String')
173
+ * @param {Array<object>} issues - Array of validation issues
174
+ * @param {string} issues[].field - Field path where issue occurred
175
+ * @param {string} issues[].problem - Problem type (UNKNOWN_FIELD, TYPE_MISMATCH, etc.)
176
+ * @param {string} [issues[].expected] - Expected type or value
177
+ * @param {any} [issues[].received] - Actual value received
178
+ * @param {object} [options] - Additional options
179
+ */
180
+ constructor(messageType, issues, options = {}) {
181
+ const issuesSummary = issues
182
+ .map((i) => `${i.field}: ${i.problem}`)
183
+ .join(', ');
184
+ super(`Invalid message for '${messageType}': ${issuesSummary}`, {
185
+ code: 'MESSAGE_VALIDATION_ERROR',
186
+ entityType: 'message',
187
+ entityName: messageType,
188
+ details: { issues },
189
+ ...options,
190
+ });
191
+ this.messageType = messageType;
192
+ this.issues = issues;
193
+ }
194
+
195
+ /**
196
+ * Get issues filtered by problem type
197
+ * @param {string} problemType - Problem type to filter by
198
+ * @returns {Array<object>} Filtered issues
199
+ */
200
+ getIssuesByType(problemType) {
201
+ return this.issues.filter((i) => i.problem === problemType);
202
+ }
203
+
204
+ /**
205
+ * Check if a specific field has validation issues
206
+ * @param {string} fieldPath - Field path to check
207
+ * @returns {boolean} True if field has issues
208
+ */
209
+ hasFieldIssue(fieldPath) {
210
+ return this.issues.some((i) => i.field === fieldPath);
211
+ }
212
+ }
213
+
214
+ /**
215
+ * ROS name validation error (topics, nodes, services)
216
+ * @class
217
+ * @extends ValidationError
218
+ */
219
+ class NameValidationError extends ValidationError {
220
+ /**
221
+ * @param {string} name - The invalid name
222
+ * @param {string} nameType - Type of name (node, topic, service, etc.)
223
+ * @param {string} validationResult - The validation error message
224
+ * @param {number} invalidIndex - Index where validation failed
225
+ * @param {object} [options] - Additional options
226
+ */
227
+ constructor(name, nameType, validationResult, invalidIndex, options = {}) {
228
+ super(
229
+ `Invalid ${nameType} name '${name}': ${validationResult}` +
230
+ (invalidIndex >= 0 ? ` at index ${invalidIndex}` : ''),
231
+ {
232
+ code: 'INVALID_NAME',
233
+ argumentName: nameType,
234
+ providedValue: name,
235
+ details: { validationResult, invalidIndex },
236
+ ...options,
237
+ }
238
+ );
239
+ this.invalidIndex = invalidIndex;
240
+ this.validationResult = validationResult;
241
+ }
242
+ }
243
+
244
+ /**
245
+ * Base class for operation/runtime errors
246
+ * @class
247
+ * @extends RclNodeError
248
+ */
249
+ class OperationError extends RclNodeError {
250
+ /**
251
+ * @param {string} message - Error message
252
+ * @param {object} [options] - Additional options
253
+ */
254
+ constructor(message, options = {}) {
255
+ super(message, { code: 'OPERATION_ERROR', ...options });
256
+ }
257
+ }
258
+
259
+ /**
260
+ * Request timeout error
261
+ * @class
262
+ * @extends OperationError
263
+ */
264
+ class TimeoutError extends OperationError {
265
+ /**
266
+ * @param {string} operationType - Type of operation that timed out
267
+ * @param {number} timeoutMs - Timeout duration in milliseconds
268
+ * @param {object} [options] - Additional options
269
+ */
270
+ constructor(operationType, timeoutMs, options = {}) {
271
+ super(`${operationType} timeout after ${timeoutMs}ms`, {
272
+ code: 'TIMEOUT',
273
+ details: { timeoutMs, operationType },
274
+ ...options,
275
+ });
276
+ this.timeout = timeoutMs;
277
+ this.operationType = operationType;
278
+ }
279
+ }
280
+
281
+ /**
282
+ * Request abortion error
283
+ * @class
284
+ * @extends OperationError
285
+ */
286
+ class AbortError extends OperationError {
287
+ /**
288
+ * @param {string} operationType - Type of operation that was aborted
289
+ * @param {string} [reason] - Reason for abortion
290
+ * @param {object} [options] - Additional options
291
+ */
292
+ constructor(operationType, reason, options = {}) {
293
+ super(`${operationType} was aborted` + (reason ? `: ${reason}` : ''), {
294
+ code: 'ABORTED',
295
+ details: { operationType, reason },
296
+ ...options,
297
+ });
298
+ this.operationType = operationType;
299
+ this.abortReason = reason;
300
+ }
301
+ }
302
+
303
+ /**
304
+ * Service not available error
305
+ * @class
306
+ * @extends OperationError
307
+ */
308
+ class ServiceNotFoundError extends OperationError {
309
+ /**
310
+ * @param {string} serviceName - Name of the service
311
+ * @param {object} [options] - Additional options
312
+ */
313
+ constructor(serviceName, options = {}) {
314
+ super(`Service '${serviceName}' is not available`, {
315
+ code: 'SERVICE_NOT_FOUND',
316
+ entityType: 'service',
317
+ entityName: serviceName,
318
+ ...options,
319
+ });
320
+ this.serviceName = serviceName;
321
+ }
322
+ }
323
+
324
+ /**
325
+ * Remote node not found error
326
+ * @class
327
+ * @extends OperationError
328
+ */
329
+ class NodeNotFoundError extends OperationError {
330
+ /**
331
+ * @param {string} nodeName - Name of the node
332
+ * @param {object} [options] - Additional options
333
+ */
334
+ constructor(nodeName, options = {}) {
335
+ super(`Node '${nodeName}' not found or not available`, {
336
+ code: 'NODE_NOT_FOUND',
337
+ entityType: 'node',
338
+ entityName: nodeName,
339
+ ...options,
340
+ });
341
+ this.targetNodeName = nodeName;
342
+ }
343
+ }
344
+
345
+ /**
346
+ * Base error for parameter operations
347
+ * @class
348
+ * @extends RclNodeError
349
+ */
350
+ class ParameterError extends RclNodeError {
351
+ /**
352
+ * @param {string} message - Error message
353
+ * @param {string} parameterName - Name of the parameter
354
+ * @param {object} [options] - Additional options
355
+ */
356
+ constructor(message, parameterName, options = {}) {
357
+ super(message, {
358
+ code: 'PARAMETER_ERROR',
359
+ entityType: 'parameter',
360
+ entityName: parameterName,
361
+ ...options,
362
+ });
363
+ this.parameterName = parameterName;
364
+ }
365
+ }
366
+
367
+ /**
368
+ * Parameter not found error
369
+ * @class
370
+ * @extends ParameterError
371
+ */
372
+ class ParameterNotFoundError extends ParameterError {
373
+ /**
374
+ * @param {string} parameterName - Name of the parameter
375
+ * @param {string} nodeName - Name of the node
376
+ * @param {object} [options] - Additional options
377
+ */
378
+ constructor(parameterName, nodeName, options = {}) {
379
+ super(
380
+ `Parameter '${parameterName}' not found on node '${nodeName}'`,
381
+ parameterName,
382
+ {
383
+ code: 'PARAMETER_NOT_FOUND',
384
+ nodeName,
385
+ ...options,
386
+ }
387
+ );
388
+ }
389
+ }
390
+
391
+ /**
392
+ * Parameter type mismatch error
393
+ * @class
394
+ * @extends ParameterError
395
+ */
396
+ class ParameterTypeError extends ParameterError {
397
+ /**
398
+ * @param {string} parameterName - Name of the parameter
399
+ * @param {string} expectedType - Expected parameter type
400
+ * @param {string} actualType - Actual parameter type
401
+ * @param {object} [options] - Additional options
402
+ */
403
+ constructor(parameterName, expectedType, actualType, options = {}) {
404
+ super(
405
+ `Type mismatch for parameter '${parameterName}': expected ${expectedType}, got ${actualType}`,
406
+ parameterName,
407
+ {
408
+ code: 'PARAMETER_TYPE_MISMATCH',
409
+ details: { expectedType, actualType },
410
+ ...options,
411
+ }
412
+ );
413
+ this.expectedType = expectedType;
414
+ this.actualType = actualType;
415
+ }
416
+ }
417
+
418
+ /**
419
+ * Read-only parameter modification error
420
+ * @class
421
+ * @extends ParameterError
422
+ */
423
+ class ReadOnlyParameterError extends ParameterError {
424
+ /**
425
+ * @param {string} parameterName - Name of the parameter
426
+ * @param {object} [options] - Additional options
427
+ */
428
+ constructor(parameterName, options = {}) {
429
+ super(
430
+ `Cannot modify read-only parameter '${parameterName}'`,
431
+ parameterName,
432
+ {
433
+ code: 'PARAMETER_READ_ONLY',
434
+ ...options,
435
+ }
436
+ );
437
+ }
438
+ }
439
+
440
+ /**
441
+ * Base error for topic operations
442
+ * @class
443
+ * @extends RclNodeError
444
+ */
445
+ class TopicError extends RclNodeError {
446
+ /**
447
+ * @param {string} message - Error message
448
+ * @param {string} topicName - Name of the topic
449
+ * @param {object} [options] - Additional options
450
+ */
451
+ constructor(message, topicName, options = {}) {
452
+ super(message, {
453
+ code: 'TOPIC_ERROR',
454
+ entityType: 'topic',
455
+ entityName: topicName,
456
+ ...options,
457
+ });
458
+ this.topicName = topicName;
459
+ }
460
+ }
461
+
462
+ /**
463
+ * Publisher-specific error
464
+ * @class
465
+ * @extends TopicError
466
+ */
467
+ class PublisherError extends TopicError {
468
+ /**
469
+ * @param {string} message - Error message
470
+ * @param {string} topicName - Name of the topic
471
+ * @param {object} [options] - Additional options
472
+ */
473
+ constructor(message, topicName, options = {}) {
474
+ super(message, topicName, {
475
+ code: 'PUBLISHER_ERROR',
476
+ entityType: 'publisher',
477
+ ...options,
478
+ });
479
+ }
480
+ }
481
+
482
+ /**
483
+ * Subscription-specific error
484
+ * @class
485
+ * @extends TopicError
486
+ */
487
+ class SubscriptionError extends TopicError {
488
+ /**
489
+ * @param {string} message - Error message
490
+ * @param {string} topicName - Name of the topic
491
+ * @param {object} [options] - Additional options
492
+ */
493
+ constructor(message, topicName, options = {}) {
494
+ super(message, topicName, {
495
+ code: 'SUBSCRIPTION_ERROR',
496
+ entityType: 'subscription',
497
+ ...options,
498
+ });
499
+ }
500
+ }
501
+
502
+ /**
503
+ * Base error for action operations
504
+ * @class
505
+ * @extends RclNodeError
506
+ */
507
+ class ActionError extends RclNodeError {
508
+ /**
509
+ * @param {string} message - Error message
510
+ * @param {string} actionName - Name of the action
511
+ * @param {object} [options] - Additional options
512
+ */
513
+ constructor(message, actionName, options = {}) {
514
+ super(message, {
515
+ code: 'ACTION_ERROR',
516
+ entityType: 'action',
517
+ entityName: actionName,
518
+ ...options,
519
+ });
520
+ this.actionName = actionName;
521
+ }
522
+ }
523
+
524
+ /**
525
+ * Goal rejected by action server
526
+ * @class
527
+ * @extends ActionError
528
+ */
529
+ class GoalRejectedError extends ActionError {
530
+ /**
531
+ * @param {string} actionName - Name of the action
532
+ * @param {string} goalId - ID of the rejected goal
533
+ * @param {object} [options] - Additional options
534
+ */
535
+ constructor(actionName, goalId, options = {}) {
536
+ super(`Goal rejected by action server '${actionName}'`, actionName, {
537
+ code: 'GOAL_REJECTED',
538
+ details: { goalId },
539
+ ...options,
540
+ });
541
+ this.goalId = goalId;
542
+ }
543
+ }
544
+
545
+ /**
546
+ * Action server not found
547
+ * @class
548
+ * @extends ActionError
549
+ */
550
+ class ActionServerNotFoundError extends ActionError {
551
+ /**
552
+ * @param {string} actionName - Name of the action
553
+ * @param {object} [options] - Additional options
554
+ */
555
+ constructor(actionName, options = {}) {
556
+ super(`Action server '${actionName}' is not available`, actionName, {
557
+ code: 'ACTION_SERVER_NOT_FOUND',
558
+ ...options,
559
+ });
560
+ }
561
+ }
562
+
563
+ /**
564
+ * Wraps errors from native C++ layer with additional context
565
+ * @class
566
+ * @extends RclNodeError
567
+ */
568
+ class NativeError extends RclNodeError {
569
+ /**
570
+ * @param {string} nativeMessage - Error message from C++ layer
571
+ * @param {string} operation - Operation that failed
572
+ * @param {object} [options] - Additional options
573
+ */
574
+ constructor(nativeMessage, operation, options = {}) {
575
+ super(`Native operation failed: ${operation} - ${nativeMessage}`, {
576
+ code: 'NATIVE_ERROR',
577
+ details: { nativeMessage, operation },
578
+ ...options,
579
+ });
580
+ this.nativeMessage = nativeMessage;
581
+ this.operation = operation;
582
+ }
583
+ }
584
+
585
+ module.exports = {
586
+ // Base error
587
+ RclNodeError,
588
+
589
+ // Validation errors
590
+ ValidationError,
591
+ TypeValidationError,
592
+ RangeValidationError,
593
+ MessageValidationError,
594
+ NameValidationError,
595
+
596
+ // Operation errors
597
+ OperationError,
598
+ TimeoutError,
599
+ AbortError,
600
+ ServiceNotFoundError,
601
+ NodeNotFoundError,
602
+
603
+ // Parameter errors
604
+ ParameterError,
605
+ ParameterNotFoundError,
606
+ ParameterTypeError,
607
+ ReadOnlyParameterError,
608
+
609
+ // Topic errors
610
+ TopicError,
611
+ PublisherError,
612
+ SubscriptionError,
613
+
614
+ // Action errors
615
+ ActionError,
616
+ GoalRejectedError,
617
+ ActionServerNotFoundError,
618
+
619
+ // Native error
620
+ NativeError,
621
+ };
@@ -16,6 +16,7 @@
16
16
 
17
17
  const rclnodejs = require('./native_loader.js');
18
18
  const DistroUtils = require('./distro.js');
19
+ const { OperationError } = require('./errors.js');
19
20
  const Entity = require('./entity.js');
20
21
 
21
22
  /**
@@ -79,8 +80,16 @@ class EventHandler extends Entity {
79
80
  class PublisherEventCallbacks {
80
81
  constructor() {
81
82
  if (DistroUtils.getDistroId() < DistroUtils.getDistroId('jazzy')) {
82
- throw new Error(
83
- 'PublisherEventCallbacks is only available in ROS 2 Jazzy and later.'
83
+ throw new OperationError(
84
+ 'PublisherEventCallbacks is only available in ROS 2 Jazzy and later',
85
+ {
86
+ code: 'UNSUPPORTED_ROS_VERSION',
87
+ entityType: 'publisher event callbacks',
88
+ details: {
89
+ requiredVersion: 'jazzy',
90
+ currentVersion: DistroUtils.getDistroId(),
91
+ },
92
+ }
84
93
  );
85
94
  }
86
95
  this._deadline = null;
@@ -262,8 +271,16 @@ class PublisherEventCallbacks {
262
271
  class SubscriptionEventCallbacks {
263
272
  constructor() {
264
273
  if (DistroUtils.getDistroId() < DistroUtils.getDistroId('jazzy')) {
265
- throw new Error(
266
- 'SubscriptionEventCallbacks is only available in ROS 2 Jazzy and later.'
274
+ throw new OperationError(
275
+ 'SubscriptionEventCallbacks is only available in ROS 2 Jazzy and later',
276
+ {
277
+ code: 'UNSUPPORTED_ROS_VERSION',
278
+ entityType: 'subscription event callbacks',
279
+ details: {
280
+ requiredVersion: 'jazzy',
281
+ currentVersion: DistroUtils.getDistroId(),
282
+ },
283
+ }
267
284
  );
268
285
  }
269
286
  this._deadline = null;