From 58b349236963f6832ad0f8066e8e1ef1c6edf3a3 Mon Sep 17 00:00:00 2001 From: Minggang Wang Date: Wed, 10 Jun 2026 15:54:22 +0800 Subject: [PATCH 1/2] fix(types): add type declarations for the rclnodejs/rosocket subpath The ./rosocket subpath export shipped no type declarations, so under node16/nodenext resolution `import { startRosocket } from 'rclnodejs/rosocket'` failed with TS7016 (implicit any) and @arethetypeswrong reported 'No types'. - add rosocket/index.d.ts typing the public entry point (startRosocket, StartRosocketOptions, RosocketServer), matching rosocket/index.js. - add a rosocket/index.d.cts companion so the require condition resolves to a CommonJS-format type file (no 'Masquerading as ESM'). - wire per-condition types into the ./rosocket export. attw now reports rclnodejs/rosocket green across node10, node16 (CJS+ESM) and bundler; tsd passes and a nodenext+strict consumer resolves the subpath without TS7016. --- package.json | 10 ++++-- rosocket/index.d.cts | 6 ++++ rosocket/index.d.ts | 73 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 87 insertions(+), 2 deletions(-) create mode 100644 rosocket/index.d.cts create mode 100644 rosocket/index.d.ts diff --git a/package.json b/package.json index ad5b8615..d2631839 100644 --- a/package.json +++ b/package.json @@ -26,8 +26,14 @@ "default": "./dist/server.js" }, "./rosocket": { - "import": "./dist/rosocket.js", - "require": "./dist/rosocket.cjs", + "import": { + "types": "./rosocket/index.d.ts", + "default": "./dist/rosocket.js" + }, + "require": { + "types": "./rosocket/index.d.cts", + "default": "./dist/rosocket.cjs" + }, "default": "./dist/rosocket.js" }, "./lib/*": "./lib/*.js", diff --git a/rosocket/index.d.cts b/rosocket/index.d.cts new file mode 100644 index 00000000..dde182b5 --- /dev/null +++ b/rosocket/index.d.cts @@ -0,0 +1,6 @@ +// CommonJS type entry for `require('rclnodejs/rosocket')`. +// +// Re-exports the ESM declarations so the `require` condition has a CommonJS +// (`.d.cts`) type file whose module format matches the CommonJS JavaScript +// served by the same condition. +export * from './index.js'; diff --git a/rosocket/index.d.ts b/rosocket/index.d.ts new file mode 100644 index 00000000..cfcb5f38 --- /dev/null +++ b/rosocket/index.d.ts @@ -0,0 +1,73 @@ +// Copyright (c) 2026 RobotWebTools Contributors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Type surface for the `rclnodejs/rosocket` subpath export. +// +// `rosocket` exposes ROS 2 topics and services as plain WebSocket URLs that +// carry ROS messages as JSON. Only the public `startRosocket` entry point is +// typed here. + +import type { EventEmitter } from 'node:events'; +import type { IncomingMessage } from 'node:http'; +import type { Node } from 'rclnodejs'; + +/** Options accepted by {@link startRosocket}. */ +export interface StartRosocketOptions { + /** rclnodejs Node to host publishers/subscriptions/clients on. */ + node: Node; + /** Port to listen on. Default `9000`. */ + port?: number; + /** Host to bind to. Default `'0.0.0.0'`. */ + host?: string; + /** + * Optional default type per topic name, + * e.g. `{ '/chatter': 'std_msgs/msg/String' }`. + */ + topicTypes?: Record; + /** Optional default type per service name. */ + serviceTypes?: Record; + /** + * Optional auth hook called with the raw HTTP upgrade request; return + * `false` to reject the connection. + */ + verifyClient?: (req: IncomingMessage) => boolean; +} + +/** Handle returned by {@link startRosocket}. */ +export interface RosocketServer { + /** + * The underlying WebSocket server (a `ws` `WebSocketServer`, typed here as + * its `EventEmitter` supertype to avoid a hard dependency on `ws` types). + */ + wss: EventEmitter; + /** Stop the gateway and close all connections. */ + close: () => Promise; + /** The port the gateway is listening on. */ + port: number; +} + +/** + * Start a resource-style WebSocket gateway that exposes ROS 2 topics and + * services as plain WebSocket URLs carrying ROS messages as JSON. + * + * URL scheme: + * - `ws://host:port/topic/?type=/msg/` + * - `ws://host:port/service/?type=/srv/` + * + * @param options - Gateway configuration. `options.node` is required. + * @returns A Promise resolving with the gateway handle. + */ +export function startRosocket( + options: StartRosocketOptions +): Promise; From 51f2d3d1390ff640494ecad1b00814a02c078041 Mon Sep 17 00:00:00 2001 From: Minggang Wang Date: Wed, 10 Jun 2026 16:19:25 +0800 Subject: [PATCH 2/2] style(types): add license header to rosocket/index.d.cts Address Copilot review on #1533: add the standard Apache-2.0 license header to rosocket/index.d.cts to match the other shipped type entrypoints (web/index.d.ts, lib/runtime/index.d.ts, rosocket/index.d.ts). --- rosocket/index.d.cts | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/rosocket/index.d.cts b/rosocket/index.d.cts index dde182b5..a15c8901 100644 --- a/rosocket/index.d.cts +++ b/rosocket/index.d.cts @@ -1,3 +1,17 @@ +// Copyright (c) 2026 RobotWebTools Contributors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + // CommonJS type entry for `require('rclnodejs/rosocket')`. // // Re-exports the ESM declarations so the `require` condition has a CommonJS