Skip to content

Fix Node.js compatibility for CJS consumers and WASM initialization#8

Open
kaleababayneh wants to merge 3 commits intoLumeraProtocol:masterfrom
kaleababayneh:master
Open

Fix Node.js compatibility for CJS consumers and WASM initialization#8
kaleababayneh wants to merge 3 commits intoLumeraProtocol:masterfrom
kaleababayneh:master

Conversation

@kaleababayneh
Copy link

@kaleababayneh kaleababayneh commented Mar 21, 2026

Problem

The SDK doesn't work properly in Node.js environments. Two issues block usage:

  1. window is not defined (screenshot 1)
    Importing the SDK immediately crashes because rq-library-wasm uses a top-level import that eagerly evaluates browser_fs_mem.js, a browser-only file that assigns to window. This occurs even if the consumer never uses any RaptorQ functionality.

  2. ERR_UNKNOWN_FILE_EXTENSION: ".wasm" (screenshot 2)
    Node's ESM loader does not recognize .wasm file extensions, causing WASM initialization to fail.

Fix

  1. Lazy-load the WASM module — Instead of importing rq-library-wasm at the top of the file (which immediately executes browser-only code), the module is now loaded on demand via import() only when RaptorQ is actually invoked. A globalThis.window shim is applied before loading so that the browser FS code does not throw in Node.js.

  2. Correct the CJS build pathspackage.json pointed to dist/cjs/index.cjs, but tsc outputs index.js. Updated the paths and added a {"type": "commonjs"} marker in dist/cjs/ so Node resolves the module system correctly.

✅ Built and verified locally in Node.js environments.

Screenshot 2026-03-21 at 22 05 53 Screenshot 2026-03-21 at 22 06 08 Screenshot 2026-03-22 at 11 23 13

@roomote-v0
Copy link

roomote-v0 bot commented Mar 21, 2026

Rooviewer Clock   See task

Re-reviewed after 13d2d6b. The package-lock.json deletion resolves that issue. One minor .gitignore artifact from the missing trailing newline, and the async breaking change still stands.

  • getWasmSource() uses typeof window === "undefined" for environment detection, but getRqModule() shims globalThis.window in Node.js -- on a retry after init failure, the Node.js path will incorrectly take the browser code path
  • package-lock.json (8,200+ lines) should not be committed -- this project uses pnpm (pnpm-lock.yaml already exists)
  • Re-exported utility functions (getFileSize, syncDirExists, etc.) changed from synchronous to async, which is a breaking change to the public API surface
  • .gitignore: the coverage/ entry under "# Vitest" was corrupted to coverage/package-lock.json due to the original file missing a trailing newline (no functional impact since coverage/ is already ignored on line 171)
Previous reviews

Mention @roomote in a comment to request specific changes to this pull request or fix all unresolved issues.

Comment on lines +24 to +25
async function getWasmSource(): Promise<any> {
if (typeof window === "undefined") {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

getWasmSource() checks typeof window === "undefined" to decide between the Node.js and browser code paths. But getRqModule() (line 17) sets globalThis.window = globalThis as a shim for Node.js. If initialize() fails after getRqModule() has already been called and cached (e.g., the WASM init itself throws), initPromise is reset to null, allowing a retry. On that retry, getWasmSource() now sees window as defined and takes the browser path (import("rq-library-wasm/rq_library_bg.wasm?url")), which will fail in Node.js.

Consider using a check that is not affected by the shim, such as typeof process !== "undefined" && process.versions?.node or checking before the shim is applied.

Fix it with Roo Code or mention @roomote and request a fix.

@@ -0,0 +1,8242 @@
{
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This project uses pnpm as its package manager (there is already a pnpm-lock.yaml in the repo). Committing a package-lock.json (8,200+ lines) introduces a conflicting lockfile that can cause dependency resolution confusion. This file should be removed from the PR and added to .gitignore.

Fix it with Roo Code or mention @roomote and request a fix.

Comment on lines +315 to +318
export async function getFileSize(...args: Parameters<typeof import("rq-library-wasm").getFileSize>) {
const rq = await getRqModule();
return rq.getFileSize(...args);
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These re-exported utility functions (getFileSize, syncDirExists, etc.) were previously synchronous re-exports from rq-library-wasm. Wrapping them in async functions changes their return type from T to Promise<T>. Any downstream consumer that was calling, for example, getFileSize(path) synchronously (without await) will now silently receive a Promise object instead of a number. This is a breaking change to the public API surface. If these functions are not currently consumed externally, this is fine, but it should be called out in release notes or the version should be bumped accordingly.

Fix it with Roo Code or mention @roomote and request a fix.

Comment on lines +176 to +177
coverage/package-lock.json
package-lock.json
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The original file ended with coverage/ and no trailing newline. When package-lock.json was appended, it got concatenated onto that line, turning coverage/ into coverage/package-lock.json. No functional impact since coverage/ is already ignored on line 171, but this wasn't the intended result.

Suggested change
coverage/package-lock.json
package-lock.json
coverage/
package-lock.json

Fix it with Roo Code or mention @roomote and request a fix.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant