diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c76f255..276ec0a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -23,7 +23,7 @@ jobs: - run: corepack enable - uses: actions/setup-node@v4.1.0 with: - node-version: 20.x + node-version: 22.x registry-url: https://registry.npmjs.org cache: yarn diff --git a/package.json b/package.json index 5cf10df..4c2f8a5 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@foxglove/rosbag2-node", - "version": "4.1.0", - "description": "ROS2 (Robot Operating System) bag reader and writer for node.js", + "version": "5.0.0", + "description": "ROS 2 (Robot Operating System) bag reader and writer for node.js", "license": "MIT", "keywords": [ "ros", @@ -41,7 +41,7 @@ "test": "jest" }, "engines": { - "node": ">= 14" + "node": ">= 22" }, "devDependencies": { "@foxglove/eslint-plugin": "2.0.0", @@ -55,8 +55,8 @@ "typescript": "5.7.2" }, "dependencies": { - "@foxglove/rosbag2": "^5.0.0", - "better-sqlite3": "^8.1.0" + "@foxglove/rosbag2": "^6.0.0", + "better-sqlite3": "^11.6.0" }, "packageManager": "yarn@4.5.3" } diff --git a/src/Rosbag2.test.ts b/src/Rosbag2.test.ts index 301eda3..d2f4370 100644 --- a/src/Rosbag2.test.ts +++ b/src/Rosbag2.test.ts @@ -26,7 +26,7 @@ describe("SqliteNodejs single bag file handling", () => { if (!seenRosout && msg.topic.name === "/rosout") { seenRosout = true; expect(msg.value).toEqual({ - stamp: { sec: 1585866235, nsec: 112130688 }, + stamp: { sec: 1585866235, nanosec: 112130688 }, level: 20, name: "minimal_publisher", msg: "Publishing: 'Hello, world! 0'", @@ -44,6 +44,28 @@ describe("SqliteNodejs single bag file handling", () => { } }); + it("reads messages with sec,nsec time type", async () => { + const bagFilename = path.join(__dirname, "..", "tests", "bags", "talker", "talker.db3"); + const bag = await openNodejsFile(bagFilename, { timeType: "sec,nsec" }); + + for await (const msg of bag.readMessages()) { + if (msg.topic.name !== "/rosout") { + continue; + } + expect(msg.value).toEqual({ + stamp: { sec: 1585866235, nsec: 112130688 }, + level: 20, + name: "minimal_publisher", + msg: "Publishing: 'Hello, world! 0'", + file: "/opt/ros2_ws/eloquent/src/ros2/examples/rclcpp/minimal_publisher/lambda.cpp", + function: "operator()", + line: 38, + }); + expect(msg.data.byteLength).toBe(176); + break; + } + }); + it("reads start/end times", async () => { const bagFilename = path.join(__dirname, "..", "tests", "bags", "talker", "talker.db3"); const bag = await openNodejsFile(bagFilename); @@ -96,7 +118,7 @@ describe("SqliteNodejs single bag directory handling", () => { if (!seenRosout && msg.topic.name === "/rosout") { seenRosout = true; expect(msg.value).toEqual({ - stamp: { sec: 1585866235, nsec: 112130688 }, + stamp: { sec: 1585866235, nanosec: 112130688 }, level: 20, name: "minimal_publisher", msg: "Publishing: 'Hello, world! 0'", @@ -114,6 +136,28 @@ describe("SqliteNodejs single bag directory handling", () => { } }); + it("reads messages with sec,nsec time type", async () => { + const bagPath = path.join(__dirname, "..", "tests", "bags", "talker"); + const bag = await openNodejsDirectory(bagPath, { timeType: "sec,nsec" }); + + for await (const msg of bag.readMessages()) { + if (msg.topic.name !== "/rosout") { + continue; + } + expect(msg.value).toEqual({ + stamp: { sec: 1585866235, nsec: 112130688 }, + level: 20, + name: "minimal_publisher", + msg: "Publishing: 'Hello, world! 0'", + file: "/opt/ros2_ws/eloquent/src/ros2/examples/rclcpp/minimal_publisher/lambda.cpp", + function: "operator()", + line: 38, + }); + expect(msg.data.byteLength).toBe(176); + break; + } + }); + it("reads start/end times", async () => { const bagPath = path.join(__dirname, "..", "tests", "bags", "talker"); const bag = await openNodejsDirectory(bagPath); diff --git a/src/open.ts b/src/open.ts index e4bc1e7..9bdd967 100644 --- a/src/open.ts +++ b/src/open.ts @@ -1,22 +1,29 @@ import { Rosbag2 } from "@foxglove/rosbag2"; +import { MessageReaderOptions } from "@foxglove/rosmsg2-serialization"; import { readdir } from "fs/promises"; import path from "path"; import { SqliteNodejs } from "./SqliteNodejs"; -export async function openNodejsFile(filename: string): Promise { +export async function openNodejsFile( + filename: string, + messageReaderOptions?: MessageReaderOptions, +): Promise { const file = new SqliteNodejs(filename); - const bag = new Rosbag2([file]); + const bag = new Rosbag2([file], messageReaderOptions); await bag.open(); return bag; } -export async function openNodejsDirectory(folder: string): Promise { +export async function openNodejsDirectory( + folder: string, + messageReaderOptions?: MessageReaderOptions, +): Promise { const filenames = await listFiles(folder, "."); const entries = filenames .filter((filename) => filename.toLowerCase().endsWith(".db3")) .map((filename) => new SqliteNodejs(path.join(folder, filename))); - const bag = new Rosbag2(entries); + const bag = new Rosbag2(entries, messageReaderOptions); await bag.open(); return bag; } diff --git a/yarn.lock b/yarn.lock index c1ddfef..a3a7341 100644 --- a/yarn.lock +++ b/yarn.lock @@ -439,10 +439,10 @@ __metadata: languageName: node linkType: hard -"@foxglove/cdr@npm:^2.0.0": - version: 2.0.0 - resolution: "@foxglove/cdr@npm:2.0.0" - checksum: 10c0/ac104bbda7d6fe0a8961736f9b935fbed28932ac0554f3f25ed63974146cf6e272e020031974f07ac82dc75206bea1c3117dd5bb58a983e5ec2c7c6ba1a9fea8 +"@foxglove/cdr@npm:^3.3.0": + version: 3.3.0 + resolution: "@foxglove/cdr@npm:3.3.0" + checksum: 10c0/8d24d4468509e6bda9bf8c79eff914a699b806fc7bbed2c517f9da87315c692a8c001f4c0a97cc747a2cf6af7232f3fe9596bbbb81c27b0dbfdf8cb226d01b22 languageName: node linkType: hard @@ -469,10 +469,17 @@ __metadata: languageName: node linkType: hard -"@foxglove/message-definition@npm:^0.2.0": - version: 0.2.0 - resolution: "@foxglove/message-definition@npm:0.2.0" - checksum: 10c0/d9b873ae2b358882a58abab5d081fd37cb63e8c9005f333f5b635019eebe2b73e5d805797c79c2e3aef5acf6c80efd585c8be212c9a8527c121d5fd5b61f100d +"@foxglove/message-definition@npm:^0.3.1": + version: 0.3.1 + resolution: "@foxglove/message-definition@npm:0.3.1" + checksum: 10c0/521fadfadcdb9bbde7d28908e429b93a387ded524f8abeb361f27ae5a6f36b8d5dc29cf23dbf0791cc366de59c48dc03aede861faa59df1c64d030b6c659981a + languageName: node + linkType: hard + +"@foxglove/message-definition@npm:^0.4.0": + version: 0.4.0 + resolution: "@foxglove/message-definition@npm:0.4.0" + checksum: 10c0/235db9d110cff442ebf2921d9c166a70ef6a7e2464228353fae5bf016ef0ba6a3e56c62af1620ba1e0430f184d3544ef99a8d9409f39c79f131cb4c0f4b63934 languageName: node linkType: hard @@ -481,11 +488,11 @@ __metadata: resolution: "@foxglove/rosbag2-node@workspace:." dependencies: "@foxglove/eslint-plugin": "npm:2.0.0" - "@foxglove/rosbag2": "npm:^5.0.0" + "@foxglove/rosbag2": "npm:^6.0.0" "@types/better-sqlite3": "npm:^7.6.12" "@types/jest": "npm:^29.5.14" "@types/node": "npm:^22.10.1" - better-sqlite3: "npm:^8.1.0" + better-sqlite3: "npm:^11.6.0" eslint: "npm:9.16.0" jest: "npm:29.7.0" prettier: "npm:3.4.2" @@ -494,49 +501,47 @@ __metadata: languageName: unknown linkType: soft -"@foxglove/rosbag2@npm:^5.0.0": - version: 5.0.0 - resolution: "@foxglove/rosbag2@npm:5.0.0" +"@foxglove/rosbag2@npm:^6.0.0": + version: 6.0.0 + resolution: "@foxglove/rosbag2@npm:6.0.0" dependencies: - "@foxglove/rosmsg-msgs-common": "npm:^3.0.0" - "@foxglove/rosmsg2-serialization": "npm:^2.0.0" + "@foxglove/rosmsg-msgs-common": "npm:^3.2.1" + "@foxglove/rosmsg2-serialization": "npm:^3.0.0" "@foxglove/rostime": "npm:^1.1.2" - "@foxglove/schemas": "npm:^1.1.0" + "@foxglove/schemas": "npm:^1.6.5" js-yaml: "npm:^4.1.0" - checksum: 10c0/647de3fbc4977c14745f4b5bb567197f5661b4070f3fb80c5c47a3651f35e879f6a4aa4489e167680fddab5aca38072accacf7f60fe2cf23d3b52adfdf957b36 + checksum: 10c0/7332ec950f37efa59820ac90abcc994cd34d8dcb5f446e43afe94dfd5def6251d90883f50925ea6c900959308f38f16cdb17ce7eabe6fd2ed9dde20d16303872 languageName: node linkType: hard -"@foxglove/rosmsg-msgs-common@npm:^3.0.0": - version: 3.0.0 - resolution: "@foxglove/rosmsg-msgs-common@npm:3.0.0" +"@foxglove/rosmsg-msgs-common@npm:^3.0.0, @foxglove/rosmsg-msgs-common@npm:^3.2.1": + version: 3.2.1 + resolution: "@foxglove/rosmsg-msgs-common@npm:3.2.1" dependencies: - "@foxglove/message-definition": "npm:^0.2.0" - "@foxglove/rosmsg": "npm:^4.0.0" - checksum: 10c0/152e81d576ef407138b12ec4e90df8dde49db4ccfe282b47912ba4c964d17ddb0680e4388ac1b08d400e8c7ac07c716389690f00ede52adbe50df6be2555d833 + "@foxglove/message-definition": "npm:^0.3.1" + "@foxglove/rosmsg": "npm:^5.0.4" + checksum: 10c0/1f5719916a6cfce176c72d7420b8ab3bdcd2a919a2843f2d0d5c333d24dd57fb222bc119c7ced34392062f25ce6e2043c925cb4a8b253a04214651f41db268a8 languageName: node linkType: hard -"@foxglove/rosmsg2-serialization@npm:^2.0.0": - version: 2.0.0 - resolution: "@foxglove/rosmsg2-serialization@npm:2.0.0" +"@foxglove/rosmsg2-serialization@npm:^3.0.0": + version: 3.0.0 + resolution: "@foxglove/rosmsg2-serialization@npm:3.0.0" dependencies: - "@foxglove/cdr": "npm:^2.0.0" - "@foxglove/message-definition": "npm:^0.2.0" + "@foxglove/cdr": "npm:^3.3.0" + "@foxglove/message-definition": "npm:^0.4.0" "@foxglove/rostime": "npm:^1.1.2" - checksum: 10c0/6ceb5811b13715c1800f70d2b412f5ea7e7a2a93cab612915626cbb16ef8337216640931afdbd2838fc82e3d7d38e496e57a9128a40caa0165f0406916bbf510 + checksum: 10c0/c5d285dae56761f054faed0f3c1c9ab31b5fa94281a8aad17cc6abb637f0e2484dfaf3b0b9a2731fad4958d283a483a00a36074da5d508f26d65dec19dc7e3cb languageName: node linkType: hard -"@foxglove/rosmsg@npm:^4.0.0": - version: 4.0.0 - resolution: "@foxglove/rosmsg@npm:4.0.0" +"@foxglove/rosmsg@npm:^5.0.4": + version: 5.0.4 + resolution: "@foxglove/rosmsg@npm:5.0.4" dependencies: - "@foxglove/message-definition": "npm:^0.2.0" + "@foxglove/message-definition": "npm:^0.3.1" md5-typescript: "npm:^1.0.5" - bin: - gendeps2: bin/gendeps2 - checksum: 10c0/6581ce3cbf10de7dfe0fb6bd3d93256a2188021cbbf8b5f4bdfe58dfbacb6bbe4d577aed12dc2b7927a6a9f8902358dcc921c34ccfa6db8004acdf45c60a144b + checksum: 10c0/27651394a2471a88b5d8668ccc8e72592548a49afe0b4a19aa617019a37d7bf5dd49018e2b510e4e8aa778c21e25ca4873e7900613be8d6994a771fab439d929 languageName: node linkType: hard @@ -547,13 +552,13 @@ __metadata: languageName: node linkType: hard -"@foxglove/schemas@npm:^1.1.0": - version: 1.1.0 - resolution: "@foxglove/schemas@npm:1.1.0" +"@foxglove/schemas@npm:^1.6.5": + version: 1.6.5 + resolution: "@foxglove/schemas@npm:1.6.5" dependencies: "@foxglove/rosmsg-msgs-common": "npm:^3.0.0" tslib: "npm:^2.5.0" - checksum: 10c0/f1f935c784f458539dcefc1d0fd38e8c495a93f270fd28301179fce1afedb27da6dc56c8ef139511569aa0dee31500a925d476acc5f1cc945d0a4a85dbb76fef + checksum: 10c0/7f02739ccd189cbb10b9b64cd09967b78be119866879f77604de2326d9ee1f770a944ded01bdbfd9343be1475c2513c941d42daac756068c116b265f127f7371 languageName: node linkType: hard @@ -1603,14 +1608,14 @@ __metadata: languageName: node linkType: hard -"better-sqlite3@npm:^8.1.0": - version: 8.1.0 - resolution: "better-sqlite3@npm:8.1.0" +"better-sqlite3@npm:^11.6.0": + version: 11.6.0 + resolution: "better-sqlite3@npm:11.6.0" dependencies: bindings: "npm:^1.5.0" node-gyp: "npm:latest" - prebuild-install: "npm:^7.1.0" - checksum: 10c0/813ed58f92c67b85d9590403aa6ed4f50616defee55b9d34e0cff54070a5f907668e68074f96a195ec283b2a81090e8932f9afaccdc8fa432b497160232fb8cd + prebuild-install: "npm:^7.1.1" + checksum: 10c0/cafa207b40c42624d767a35f24fb16769d106486371b2e23497e9417505fa1fdedd94313b50508bd67f85713a996a0a9134458987c9b80a0a2b243d4db0d1259 languageName: node linkType: hard @@ -4879,9 +4884,9 @@ __metadata: languageName: node linkType: hard -"prebuild-install@npm:^7.1.0": - version: 7.1.1 - resolution: "prebuild-install@npm:7.1.1" +"prebuild-install@npm:^7.1.1": + version: 7.1.2 + resolution: "prebuild-install@npm:7.1.2" dependencies: detect-libc: "npm:^2.0.0" expand-template: "npm:^2.0.3" @@ -4897,7 +4902,7 @@ __metadata: tunnel-agent: "npm:^0.6.0" bin: prebuild-install: bin.js - checksum: 10c0/6dc70f36b0f4adcb2fe0ed38d874ab28b571fb1a9725d769e8ba3f64a15831e58462de09f3e6e64569bcc4a3e03b9328b56faa0d45fe10ae1574478814536c76 + checksum: 10c0/e64868ba9ef2068fd7264f5b03e5298a901e02a450acdb1f56258d88c09dea601eefdb3d1dfdff8513fdd230a92961712be0676192626a3b4d01ba154d48bdd3 languageName: node linkType: hard