From 2a20e2088f02f5948e3f7c2098b3f70f68735e0b Mon Sep 17 00:00:00 2001 From: ruvnet Date: Thu, 7 May 2026 15:30:56 -0400 Subject: [PATCH] fix(rvf-wasm): publish as ESM-only to resolve #415 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The published 0.1.6 tarball was unloadable: pkg/rvf_wasm.js used `import.meta.url` and `export default` while package.json had no `"type": "module"`, so Node parsed it as CJS and threw `SyntaxError: Cannot use 'import.meta' outside a module` before any runtime guard could execute. The .mjs entry just re-imported the same broken .js, so the ESM path crashed identically. Fix: - Add `"type": "module"` and switch `main` to `pkg/rvf_wasm.mjs`. - Drop the `require`/`default` exports that pointed at the broken CJS-classified .js. Node 22.12+ supports `require(ESM)` natively, so the single ESM entry covers both consumers. - Add `tests/smoke.mjs` as a regression guard (also wired into `prepublishOnly`) that imports the package, calls `init()`, asserts real WASM memory, and confirms idempotency. - Bump 0.1.5 → 0.1.7 (skip the broken 0.1.6). Verified end-to-end against a packed tarball installed into /tmp: ESM import works (1.1 MB memory allocated), CJS require also works on Node 22.22.2. Closes #415 Co-Authored-By: claude-flow --- npm/packages/rvf-wasm/package.json | 13 ++++----- npm/packages/rvf-wasm/tests/smoke.mjs | 39 +++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 6 deletions(-) create mode 100644 npm/packages/rvf-wasm/tests/smoke.mjs diff --git a/npm/packages/rvf-wasm/package.json b/npm/packages/rvf-wasm/package.json index 9cc2dcd41..cc17ab798 100644 --- a/npm/packages/rvf-wasm/package.json +++ b/npm/packages/rvf-wasm/package.json @@ -1,22 +1,23 @@ { "name": "@ruvector/rvf-wasm", - "version": "0.1.5", + "version": "0.1.7", "description": "RuVector Format WASM microkernel for browser and edge vector operations", - "main": "pkg/rvf_wasm.js", + "type": "module", + "main": "pkg/rvf_wasm.mjs", "types": "pkg/rvf_wasm.d.ts", "exports": { ".": { "types": "./pkg/rvf_wasm.d.ts", - "import": "./pkg/rvf_wasm.mjs", - "require": "./pkg/rvf_wasm.js", - "default": "./pkg/rvf_wasm.js" + "default": "./pkg/rvf_wasm.mjs" } }, "files": [ "pkg/" ], "scripts": { - "build": "cargo build --release --target wasm32-unknown-unknown --manifest-path ../../crates/rvf/rvf-wasm/Cargo.toml && wasm-opt -Oz ../../crates/rvf/target/wasm32-unknown-unknown/release/rvf_wasm.wasm -o pkg/rvf_wasm_bg.wasm" + "build": "cargo build --release --target wasm32-unknown-unknown --manifest-path ../../crates/rvf/rvf-wasm/Cargo.toml && wasm-opt -Oz ../../crates/rvf/target/wasm32-unknown-unknown/release/rvf_wasm.wasm -o pkg/rvf_wasm_bg.wasm", + "test": "node tests/smoke.mjs", + "prepublishOnly": "node tests/smoke.mjs" }, "license": "MIT", "repository": { diff --git a/npm/packages/rvf-wasm/tests/smoke.mjs b/npm/packages/rvf-wasm/tests/smoke.mjs new file mode 100644 index 000000000..811c5b241 --- /dev/null +++ b/npm/packages/rvf-wasm/tests/smoke.mjs @@ -0,0 +1,39 @@ +// Smoke test: regression guard for issue #415. +// Verifies that @ruvector/rvf-wasm can be loaded as ESM without +// `SyntaxError: Cannot use 'import.meta' outside a module` and that +// init() returns a usable WASM exports object. + +import { fileURLToPath } from 'node:url'; +import { dirname, join } from 'node:path'; + +const __dirname = dirname(fileURLToPath(import.meta.url)); +const pkgRoot = join(__dirname, '..'); + +let failures = 0; +function assert(cond, msg) { + if (!cond) { + console.error('FAIL:', msg); + failures++; + } else { + console.log(' ok:', msg); + } +} + +// 1. ESM import via package.json `default` (the published surface). +const mod = await import(join(pkgRoot, 'pkg/rvf_wasm.mjs')); +assert(typeof mod.default === 'function', 'mjs default export is a function'); + +// 2. Initialize and confirm we got real WASM exports back. +const exports_ = await mod.default(); +assert(exports_ != null && typeof exports_ === 'object', 'init() returned exports object'); +assert(exports_.memory instanceof WebAssembly.Memory, 'exports.memory is WebAssembly.Memory'); + +// 3. Idempotent re-init returns the cached instance. +const exports2 = await mod.default(); +assert(exports2 === exports_, 'init() is idempotent'); + +if (failures > 0) { + console.error(`\n${failures} smoke check(s) failed`); + process.exit(1); +} +console.log('\nrvf-wasm smoke OK');