Skip to content

Commit 10a5ef4

Browse files
authored
[Demo] Modernize TypeScript demos to NodeNext + ES2022 (#1534)
## 1. ESM migration of `example/` (44 files) Converted every CommonJS example to native ESM (`.cjs` → `.mjs`): - Dropped `'use strict'`, replaced `require('…/index.js').default` with `import rclnodejs from '…/index.js'`. - Unwrapped `main()` / `.then().catch()` into top-level `await` + `try/catch`. - Preserved original copyright headers. - Updated all 10 example READMEs (`.cjs` → `.mjs`, plus the "import rclnodejs from 'rclnodejs'" note). ## 2. ESM migration of demos (3 files) - `demo/rosocket/server.cjs` → `server.mjs` - `demo/web/javascript/runtime.cjs` → `runtime.mjs` - `demo/web/javascript/static.cjs` → `static.mjs` (adds `__dirname` shim via `fileURLToPath`) - Directory imports made explicit (`../../rosocket/index.js`, `../../../lib/runtime/index.js`). - Updated `demo/rosocket/README.md`, `demo/web/javascript/README.md`, and `demo/web/typescript/server.ts` comments. ## 3. demo/typescript modernization (no .cjs→.mjs) - `actions/`, `services/`, `topics/` `tsconfig.json`: `module`/`moduleResolution` → `NodeNext`, `target`/`lib` → ES2022, removed stale `./types` typeRoots. - Updated `README.md` + per-folder READMEs (ES2022 wording, removed false "local type definitions" claims). ## 4. ESM fix for benchmarks (4 files) `benchmark/rclnodejs/**/*.js` used bare `require()` under the root `"type": "module"` and threw `ReferenceError: require is not defined`. Converted to ESM (`import { program } from 'commander'`, `import rclnodejs from '../../../index.js'`). Verified against ROS 2 Jazzy: topic + service pairs run with no exceptions. ## 5. CommonJS island fix for jsdoc tooling (1 file) Added `tools/jsdoc/package.json` = `{"type":"commonjs"}` so `build-index.js`, `regenerate-published-docs.js`, and the jsdoc template `publish.js` (which must keep that exact name and be CJS) load correctly. Without it, `npm run docs` aborts with "Unable to load template: require is not defined". Verified: `npm run docs` now exits 0. ## 6. Root README ESM conversion (`README.md`, 13/13 lines) - Top publisher snippet: `require('rclnodejs')` + `.init().then()` → `import rclnodejs from 'rclnodejs'` + top-level `await`. - Observable snippet: `require('rxjs')` → `import { throttleTime, map } from 'rxjs'`. - Message-generation snippet: `require('rclnodejs')` → `import rclnodejs from 'rclnodejs'`. - Quick Start: stale `publisher-example.cjs` → `publisher-example.mjs`. - TypeScript `tsconfig` snippet → `module: NodeNext`, `moduleResolution: NodeNext`, `target: es2022`. Fix: #1358
1 parent 01731e0 commit 10a5ef4

98 files changed

Lines changed: 1954 additions & 2283 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

README.md

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,13 @@
1616
**Key features:** Topics, Services, Actions, Parameters, Lifecycle Nodes, TypeScript support, RxJS Observables, Electron integration, ROS 2 in the browser (typed Web SDK + thin WebSocket gateway — `rclnodejs/web`, `rosocket`), and prebuilt binaries for Linux x64/arm64.
1717

1818
```javascript
19-
const rclnodejs = require('rclnodejs');
20-
rclnodejs.init().then(() => {
21-
const node = new rclnodejs.Node('publisher_example_node');
22-
const publisher = node.createPublisher('std_msgs/msg/String', 'topic');
23-
publisher.publish(`Hello ROS 2 from rclnodejs`);
24-
node.spin();
25-
});
19+
import rclnodejs from 'rclnodejs';
20+
21+
await rclnodejs.init();
22+
const node = new rclnodejs.Node('publisher_example_node');
23+
const publisher = node.createPublisher('std_msgs/msg/String', 'topic');
24+
publisher.publish(`Hello ROS 2 from rclnodejs`);
25+
node.spin();
2626
```
2727

2828
This example assumes your ROS 2 environment is already sourced.
@@ -105,7 +105,7 @@ npm install
105105
2. Run a publisher example from this checkout.
106106

107107
```bash
108-
node example/topics/publisher/publisher-example.cjs
108+
node example/topics/publisher/publisher-example.mjs
109109
```
110110

111111
More runnable examples in [example/](https://github.com/RobotWebTools/rclnodejs/tree/develop/example) and step-by-step guides in [tutorials/](./tutorials/).
@@ -146,7 +146,7 @@ how much glue you want to write.
146146
rclnodejs supports [RxJS](https://rxjs.dev/) Observable subscriptions for reactive programming with ROS 2 messages. Use operators like `throttleTime()`, `debounceTime()`, `map()`, and `combineLatest()` to build declarative message processing pipelines.
147147

148148
```javascript
149-
const { throttleTime, map } = require('rxjs');
149+
import { throttleTime, map } from 'rxjs';
150150

151151
const obsSub = node.createObservableSubscription(
152152
'sensor_msgs/msg/LaserScan',
@@ -173,7 +173,7 @@ rclnodejs auto-generates JavaScript bindings and TypeScript declarations for eve
173173
Use the generated types directly:
174174

175175
```javascript
176-
const rclnodejs = require('rclnodejs');
176+
import rclnodejs from 'rclnodejs';
177177
let stringMsgObject = rclnodejs.createMessageObject('std_msgs/msg/String');
178178
stringMsgObject.data = 'hello world';
179179
```
@@ -199,9 +199,9 @@ TypeScript declaration files are included in the package and exposed through the
199199
```jsonc
200200
{
201201
"compilerOptions": {
202-
"module": "commonjs",
203-
"moduleResolution": "node",
204-
"target": "es2020",
202+
"module": "NodeNext",
203+
"moduleResolution": "NodeNext",
204+
"target": "es2022",
205205
},
206206
}
207207
```

benchmark/rclnodejs/service/client-stress-test.js

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,9 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15-
'use strict';
16-
1715
/* eslint-disable camelcase */
18-
const { program } = require('commander');
19-
const rclnodejs = require('../../../index.js');
16+
import { program } from 'commander';
17+
import rclnodejs from '../../../index.js';
2018

2119
program
2220
.option('-r, --run <n>', 'How many times to run', '1')

benchmark/rclnodejs/service/service-stress-test.js

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,9 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15-
'use strict';
16-
1715
/* eslint-disable camelcase */
18-
const { program } = require('commander');
19-
const rclnodejs = require('../../../index.js');
16+
import { program } from 'commander';
17+
import rclnodejs from '../../../index.js';
2018

2119
program
2220
.option('-s, --size <size_kb>', 'The block size in KB', '1')

benchmark/rclnodejs/topic/publisher-stress-test.js

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,9 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15-
'use strict';
16-
1715
/* eslint-disable camelcase */
18-
const { program } = require('commander');
19-
const rclnodejs = require('../../../index.js');
16+
import { program } from 'commander';
17+
import rclnodejs from '../../../index.js';
2018

2119
program
2220
.option('-s, --size <size_kb>', 'The block size', '1')

benchmark/rclnodejs/topic/subscription-stress-test.js

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,7 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15-
'use strict';
16-
17-
const rclnodejs = require('../../../index.js');
15+
import rclnodejs from '../../../index.js';
1816

1917
async function main() {
2018
try {

demo/rosocket/README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,12 @@ library required.
1111
- Subscribe to and publish on `/chatter` (`std_msgs/msg/String`).
1212
- Call `/add_two_ints` (`example_interfaces/srv/AddTwoInts`) — the
1313
service implementation lives in
14-
[`example/services/service/service-example.cjs`](../../example/services/service/service-example.cjs)
14+
[`example/services/service/service-example.mjs`](../../example/services/service/service-example.mjs)
1515
and is launched in a second terminal.
1616

1717
## Layout
1818

19-
- `server.cjs``rclnodejs` node + `startRosocket` bridge only.
19+
- `server.mjs``rclnodejs` node + `startRosocket` bridge only.
2020
- `index.html` — single-file browser client using only built-in
2121
`WebSocket` and `JSON`.
2222

@@ -27,12 +27,12 @@ library required.
2727
source /opt/ros/$ROS_DISTRO/setup.bash
2828

2929
# 2. Terminal A — start the WebSocket gateway
30-
node demo/rosocket/server.cjs
30+
node demo/rosocket/server.mjs
3131
# [rosocket-demo] listening on ws://localhost:9000 (bind=0.0.0.0)
3232

3333
# 3. Terminal B — start the AddTwoInts service so the browser has
3434
# something to call
35-
node example/services/service/service-example.cjs
35+
node example/services/service/service-example.mjs
3636
```
3737

3838
The server binds to `0.0.0.0:9000` so it is reachable from any host

demo/rosocket/server.cjs

Lines changed: 0 additions & 78 deletions
This file was deleted.

demo/rosocket/server.mjs

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
// Copyright (c) 2026 RobotWebTools Contributors. 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+
// rosocket demo server.
10+
//
11+
// Bridges two ROS 2 endpoints to plain WebSocket URLs so a browser can
12+
// drive them with built-in `WebSocket` + `JSON`, no client library:
13+
//
14+
// ws://<host>:9000/topic/chatter std_msgs/msg/String
15+
// ws://<host>:9000/service/add_two_ints example_interfaces/srv/AddTwoInts
16+
//
17+
// Run inside WSL (where ROS 2 is sourced):
18+
// node demo/rosocket/server.mjs
19+
//
20+
// To exercise the service, start the existing AddTwoInts example in a
21+
// second terminal (it implements `/add_two_ints`):
22+
// node example/services/service/service-example.mjs
23+
//
24+
// Then open demo/rosocket/index.html on the Windows host browser. WSL2
25+
// forwards localhost so `ws://localhost:9000` works as-is. See README.md
26+
// for fallback instructions.
27+
28+
import rclnodejs from '../../index.js';
29+
import { startRosocket } from '../../rosocket/index.js';
30+
31+
const PORT = Number(process.env.PORT) || 9000;
32+
const HOST = process.env.HOST || '0.0.0.0';
33+
34+
await rclnodejs.init();
35+
const node = rclnodejs.createNode('rosocket_demo_node');
36+
rclnodejs.spin(node);
37+
38+
const bridge = await startRosocket({
39+
node,
40+
port: PORT,
41+
host: HOST,
42+
topicTypes: {
43+
'/chatter': 'std_msgs/msg/String',
44+
},
45+
serviceTypes: {
46+
'/add_two_ints': 'example_interfaces/srv/AddTwoInts',
47+
},
48+
});
49+
50+
const displayHost = HOST === '0.0.0.0' || HOST === '::' ? 'localhost' : HOST;
51+
const baseUrl = `ws://${displayHost}:${bridge.port}`;
52+
console.log(
53+
`[rosocket-demo] listening on ${baseUrl} (bind=${HOST}:${bridge.port})`
54+
);
55+
console.log('[rosocket-demo] endpoints:');
56+
console.log(` ${baseUrl}/topic/chatter`);
57+
console.log(` ${baseUrl}/service/add_two_ints`);
58+
console.log('Open demo/rosocket/index.html in the host browser to try it.');
59+
60+
const shutdown = () => {
61+
bridge.close().finally(() => {
62+
try {
63+
rclnodejs.shutdown();
64+
} catch (_) {}
65+
process.exit(0);
66+
});
67+
};
68+
process.on('SIGINT', shutdown);
69+
process.on('SIGTERM', shutdown);

demo/typescript/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ Asynchronous actions with progress feedback and cancellation
4242

4343
### Modern Development
4444

45-
- **ES2020+ syntax** with async/await patterns
45+
- **ES2022+ syntax** with async/await patterns
4646
- **Modular architecture** with clean separation of concerns
4747
- **Error boundaries** with comprehensive exception handling
4848
- **Graceful shutdown** handling for SIGINT/SIGTERM

demo/typescript/actions/README.md

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,6 @@ demo/typescript/actions/
3636
├── src/
3737
│ ├── client.ts # Action client implementation
3838
│ └── server.ts # Action server implementation
39-
├── types/
40-
│ └── rclnodejs.d.ts # Type definitions
4139
├── package.json # Project configuration
4240
├── tsconfig.json # TypeScript configuration
4341
├── .gitignore # Git ignore rules

0 commit comments

Comments
 (0)