Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 15 additions & 2 deletions .github/workflows/npm-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,19 @@ jobs:
echo "=== arm64 prebuilds ==="
ls -la prebuilds/linux-arm64/

- name: Install dependencies
# --ignore-scripts skips install/postinstall (native build + message
# generation need a sourced ROS env, which this job doesn't have) while
# still installing devDependencies such as tsup needed for build:dist.
run: npm install --ignore-scripts

- name: Build dist (ESM/CJS bundles)
# npm-pack.sh packs with --ignore-scripts, so the prepack hook that
# normally runs build:dist is skipped. dist/ is git-ignored and absent
# on a fresh checkout, so build it explicitly before packing — the
# published package's main/module/exports all point at ./dist/*.
run: npm run build:dist

- name: Pack
run: ./scripts/npm-pack.sh

Expand Down Expand Up @@ -96,7 +109,7 @@ jobs:
fi
if [[ "${{ inputs.dry_run }}" == "true" ]]; then
echo "=== DRY RUN ==="
npm publish --provenance --access public --tag "$TAG" --dry-run ./dist/rclnodejs-*.tgz
npm publish --provenance --access public --tag "$TAG" --dry-run ./pack/rclnodejs-*.tgz
else
npm publish --provenance --access public --tag "$TAG" ./dist/rclnodejs-*.tgz
npm publish --provenance --access public --tag "$TAG" ./pack/rclnodejs-*.tgz
fi
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ cpplint.py
generated
types/interfaces.d.ts
dist
pack
build
log
.vscode
Expand Down
5 changes: 4 additions & 1 deletion .npmignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
.gitignore
.prettierrc.yml
eslint.config.mjs
tsup.config.js
CONTRIBUTORS.md
Dockerfile
cpplint.py
Expand All @@ -15,9 +16,11 @@ build/
__pycache__/
*.pyc
coverage/
dist/
log/
install/
pack/
dist/package/
dist/*.tgz
test/
docs/
example/
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ npm install
2. Run a publisher example from this checkout.

```bash
node example/topics/publisher/publisher-example.js
node example/topics/publisher/publisher-example.cjs
```
Comment on lines 105 to 109

More runnable examples in [example/](https://github.com/RobotWebTools/rclnodejs/tree/develop/example) and step-by-step guides in [tutorials/](./tutorials/).
Expand Down
8 changes: 4 additions & 4 deletions demo/rosocket/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@ library required.
- Subscribe to and publish on `/chatter` (`std_msgs/msg/String`).
- Call `/add_two_ints` (`example_interfaces/srv/AddTwoInts`) — the
service implementation lives in
[`example/services/service/service-example.js`](../../example/services/service/service-example.js)
[`example/services/service/service-example.cjs`](../../example/services/service/service-example.cjs)
and is launched in a second terminal.

## Layout

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

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

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

# 3. Terminal B — start the AddTwoInts service so the browser has
# something to call
node example/services/service/service-example.js
node example/services/service/service-example.cjs
```

The server binds to `0.0.0.0:9000` so it is reachable from any host
Expand Down
6 changes: 3 additions & 3 deletions demo/rosocket/server.js → demo/rosocket/server.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,17 @@
// ws://<host>:9000/service/add_two_ints example_interfaces/srv/AddTwoInts
//
// Run inside WSL (where ROS 2 is sourced):
// node demo/rosocket/server.js
// node demo/rosocket/server.cjs
//
// To exercise the service, start the existing AddTwoInts example in a
// second terminal (it implements `/add_two_ints`):
// node example/services/service/service-example.js
// node example/services/service/service-example.cjs
//
// Then open demo/rosocket/index.html on the Windows host browser. WSL2
// forwards localhost so `ws://localhost:9000` works as-is. See README.md
// for fallback instructions.

const rclnodejs = require('../../index.js');
const rclnodejs = require('../../index.js').default;
const { startRosocket } = require('../../rosocket');

const PORT = Number(process.env.PORT) || 9000;
Expand Down
16 changes: 8 additions & 8 deletions demo/web/javascript/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,20 @@ cd demo/web/javascript

```bash
source /opt/ros/<distro>/setup.bash
node runtime.js
node runtime.cjs
# rclnodejs/web : ws://localhost:9000/capability
# also http://localhost:9001/capability (call/publish, curl-able)
```

`runtime.js` exposes a tiny `/add_two_ints` service + 1 Hz
`runtime.cjs` exposes a tiny `/add_two_ints` service + 1 Hz
`/web_demo_tick` publisher so every panel has live data.

**Shell 2 — static-file server (hosts `index.html` + maps `/sdk/*` to
the in-repo [`web/`](../../../web/) folder so the page can `import`
the SDK from a plain URL):**

```bash
node static.js
node static.cjs
# Static files : http://localhost:8080/
```

Expand Down Expand Up @@ -67,18 +67,18 @@ curl -sS -X POST http://localhost:9001/capability/call/add_two_ints \

Subscribe stays on WebSocket.

## Without the bundled `runtime.js`
## Without the bundled `runtime.cjs`

`runtime.js` bundles the rclnodejs/web runtime and the demo's sample
`runtime.cjs` bundles the rclnodejs/web runtime and the demo's sample
ROS 2 nodes (the `/add_two_ints` service + the `/web_demo_tick`
publisher) into one process so the demo runs out of the box. In a
real project you already have those ROS 2 nodes running elsewhere,
so you only need the runtime. **Replace shell 1's `node runtime.js`
with the CLI** — shell 2 (`node static.js`) and the browser code are
so you only need the runtime. **Replace shell 1's `node runtime.cjs`
with the CLI** — shell 2 (`node static.cjs`) and the browser code are
unchanged:

```bash
# shell 1 (instead of `node runtime.js`); the `-p rclnodejs` tells npx
# shell 1 (instead of `node runtime.cjs`); the `-p rclnodejs` tells npx
# the `rclnodejs-web` binary lives inside the `rclnodejs` package:
npx -p rclnodejs rclnodejs-web web.json

Expand Down
2 changes: 1 addition & 1 deletion demo/web/javascript/index.html
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<!doctype html>
<!--
rclnodejs/web demo. Open via http://localhost:8080/ once both
`node runtime.js` (rclnodejs/web runtime) and `node static.js`
`node runtime.cjs` (rclnodejs/web runtime) and `node static.cjs`
(page server) are running — see README.md.
-->
<html lang="en">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,18 @@
// http://www.apache.org/licenses/LICENSE-2.0
//
// rclnodejs/web demo — runtime side (rclnodejs/web runtime + the demo's
// ROS 2 nodes; named `runtime.js` to avoid being confused with the
// page-side `static.js`).
// ROS 2 nodes; named `runtime.cjs` to avoid being confused with the
// page-side `static.cjs`).
//
// 1. Source ROS 2 (`source /opt/ros/<distro>/setup.bash`)
// 2. From this folder run `node runtime.js`
// 3. In another shell run `node static.js` to host
// 2. From this folder run `node runtime.cjs`
// 3. In another shell run `node static.cjs` to host
// `index.html` on http://localhost:8080/ — same split as the
// TypeScript demo's `tsx server.ts` + `vite`.

'use strict';

const rclnodejs = require('../../../index.js');
const rclnodejs = require('../../../index.js').default;
// In a downstream project this is the public, supported import:
// const { createRuntime, WebSocketTransport, HttpTransport } =
// require('rclnodejs/web/server');
Expand Down Expand Up @@ -135,7 +135,7 @@ async function main() {
console.log(formatCapabilities(caps));
console.log();
console.log(
'Static page: run `node static.js` in another shell, then open http://localhost:8080/'
'Static page: run `node static.cjs` in another shell, then open http://localhost:8080/'
);

// ---- Graceful shutdown ----------------------------------------------
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// rclnodejs/web demo — static-file server (page side; named `static.js`
// to avoid being confused with the runtime-side `runtime.js`).
// rclnodejs/web demo — static-file server (page side; named `static.cjs`
// to avoid being confused with the runtime-side `runtime.cjs`).
//
// Serves index.html on port 8080 and maps `/sdk/*` to the in-repo
// `web/` folder so the page can `import { connect } from '/sdk/index.js'`
// without bundling. In a downstream project you'd `npm install rclnodejs`
// and `import { connect } from 'rclnodejs/web'` instead.
//
// Pair with `node runtime.js` (the rclnodejs/web runtime + the demo's
// Pair with `node runtime.cjs` (the rclnodejs/web runtime + the demo's
// ROS 2 nodes) in another shell — the same split as the TypeScript
// demo's `tsx server.ts` + `vite`. Production deployments use nginx,
// a CDN, or any other static host.
Expand Down
6 changes: 3 additions & 3 deletions demo/web/typescript/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@
// http://www.apache.org/licenses/LICENSE-2.0
//
// TypeScript demo server. Run with `npm run server` (which uses tsx) or
// `npx tsx server.ts`. Behaviour matches demo/web/javascript/runtime.js
// `npx tsx server.ts`. Behaviour matches demo/web/javascript/runtime.cjs
// — same runtime + same demo nodes — except this side is written in
// TypeScript so the typed SDK story is visible end to end. The static
// page server is Vite (`npm run dev`), parallel to the JS demo's
// separate `node static.js`.
// separate `node static.cjs`.

// rclnodejs is a CommonJS module without first-class ESM types; using
// require keeps the server independent of how a downstream project
Expand All @@ -30,7 +30,7 @@ const RUNTIME_PORT = Number(process.env.RUNTIME_PORT || 9000);
const HTTP_PORT = Number(process.env.HTTP_PORT || 9001);

// Render the registry as a small human-readable table — see the matching
// helper in demo/web/javascript/runtime.js.
// helper in demo/web/javascript/runtime.cjs.
function formatCapabilities(
caps: Record<'call' | 'publish' | 'subscribe', Record<string, string>>
): string {
Expand Down
4 changes: 2 additions & 2 deletions eslint.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ export default [
ecmaVersion: "latest",
sourceType: "module",
},
files: ["lib/**/*.js", "test/**/*.js", "bin/**/*.js", "rosocket/**/*.js", "index.js"],
files: ["lib/**/*.js", "test/**/*.js", "bin/**/*.js", "rosocket/**/*.js", "index.js", "example/**/*.mjs"],
rules: {
...eslintPluginPrettierRecommended.rules,
},
Expand All @@ -78,7 +78,7 @@ export default [
sourceType: "commonjs",
},
files: ["rosidl_parser/**/*.{js,cjs}", "rosidl_gen/**/*.{js,cjs}",
"rostsd_gen/**/*.{js,cjs}", "example/**/*.js"],
"rostsd_gen/**/*.{js,cjs}", "example/**/*.cjs"],
rules: {
...eslintPluginPrettierRecommended.rules,
},
Expand Down
34 changes: 17 additions & 17 deletions example/actions/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ Actions are ideal for:

The `action_client/` directory contains examples of nodes that send goals to action servers:

#### 1. Basic Action Client (`action-client-example.js`)
#### 1. Basic Action Client (`action-client-example.cjs`)

**Purpose**: Demonstrates basic action client functionality with the Fibonacci action.

Expand All @@ -40,9 +40,9 @@ The `action_client/` directory contains examples of nodes that send goals to act
- Goal acceptance verification
- Feedback handling during execution
- Result processing with status checking
- **Run Command**: `node action_client/action-client-example.js`
- **Run Command**: `node action_client/action-client-example.cjs`

#### 2. Action Client with Cancellation (`action-client-cancel-example.js`)
#### 2. Action Client with Cancellation (`action-client-cancel-example.cjs`)

**Purpose**: Demonstrates how to cancel an action goal during execution.

Expand All @@ -58,9 +58,9 @@ The `action_client/` directory contains examples of nodes that send goals to act
- Goal cancellation with `cancelGoal()`
- Cancellation response verification
- Cleanup and shutdown handling
- **Run Command**: `node action_client/action-client-cancel-example.js`
- **Run Command**: `node action_client/action-client-cancel-example.cjs`

#### 3. Action Client Validation (`action-client-validation-example.js`)
#### 3. Action Client Validation (`action-client-validation-example.cjs`)

**Purpose**: Demonstrates goal validation features for action clients.

Expand All @@ -80,14 +80,14 @@ The `action_client/` directory contains examples of nodes that send goals to act
- **Detailed Errors**: Field-level validation issues with expected vs received types
- **Strict Mode**: Detect extra fields that don't belong in the goal
- **Reusable Validators**: Create validators for repeated goal validation
- **Run Command**: `node action_client/action-client-validation-example.js`
- **Run Command**: `node action_client/action-client-validation-example.cjs`
- **Note**: Standalone example - demonstrates validation errors without requiring a running action server

### Action Server Examples

The `action_server/` directory contains examples of nodes that provide action services:

#### 1. Basic Action Server (`action-server-example.js`)
#### 1. Basic Action Server (`action-server-example.cjs`)

**Purpose**: Demonstrates basic action server implementation for computing Fibonacci sequences.

Expand All @@ -103,9 +103,9 @@ The `action_server/` directory contains examples of nodes that provide action se
- Execution callback with feedback publishing
- Cancellation handling (`cancelCallback`)
- Progress updates every second
- **Run Command**: `node action_server/action-server-example.js`
- **Run Command**: `node action_server/action-server-example.cjs`

#### 2. Deferred Execution Server (`action-server-defer-example.js`)
#### 2. Deferred Execution Server (`action-server-defer-example.cjs`)

**Purpose**: Shows how to defer goal execution using timers and handle accepted callbacks.

Expand All @@ -121,9 +121,9 @@ The `action_server/` directory contains examples of nodes that provide action se
- Handle accepted callback (`handleAcceptedCallback`)
- Timer-based execution control
- Manual goal execution triggering
- **Run Command**: `node action_server/action-server-defer-example.js`
- **Run Command**: `node action_server/action-server-defer-example.cjs`

#### 3. Single Goal Server (`action-server-single-goal-example.js`)
#### 3. Single Goal Server (`action-server-single-goal-example.cjs`)

**Purpose**: Demonstrates a server that only allows one active goal at a time.

Expand All @@ -139,7 +139,7 @@ The `action_server/` directory contains examples of nodes that provide action se
- Automatic abortion of previous goals
- Goal state tracking (`isActive`)
- Handle accepted callback for goal management
- **Run Command**: `node action_server/action-server-single-goal-example.js`
- **Run Command**: `node action_server/action-server-single-goal-example.cjs`

## How to Run the Examples

Expand All @@ -156,7 +156,7 @@ The `action_server/` directory contains examples of nodes that provide action se

```bash
cd example/actions
node action_server/action-server-example.js
node action_server/action-server-example.cjs
```

You should see:
Expand All @@ -169,7 +169,7 @@ The `action_server/` directory contains examples of nodes that provide action se

```bash
cd example/actions
node action_client/action-client-example.js
node action_client/action-client-example.cjs
```

3. **Expected Output**:
Expand Down Expand Up @@ -203,14 +203,14 @@ The `action_server/` directory contains examples of nodes that provide action se
1. **Start Server**: Run any action server example
2. **Start Cancellation Client**:
```bash
node action_client/action-client-cancel-example.js
node action_client/action-client-cancel-example.cjs
```
3. **Expected Behavior**: Client sends goal, receives feedback for 2 seconds, then cancels

#### Specialized Server Examples

- **Deferred Execution**: Use `action-server-defer-example.js` to see 3-second execution delay
- **Single Goal**: Use `action-server-single-goal-example.js` to test goal abortion behavior
- **Deferred Execution**: Use `action-server-defer-example.cjs` to see 3-second execution delay
- **Single Goal**: Use `action-server-single-goal-example.cjs` to test goal abortion behavior

## Action Components Explained

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

'use strict';

const rclnodejs = require('../../../index.js');
const rclnodejs = require('../../../index.js').default;
const Fibonacci = rclnodejs.require('test_msgs/action/Fibonacci');

class FibonacciActionClient {
Expand Down
Loading
Loading