Skip to content

feat(wren-core-wasm): publish wren-core-sdk npm package (Plan A-M4b)#1559

Merged
goldmedal merged 10 commits intoCanner:feat/wren-wasmfrom
goldmedal:plan-wasm-sdk-npm
Apr 15, 2026
Merged

feat(wren-core-wasm): publish wren-core-sdk npm package (Plan A-M4b)#1559
goldmedal merged 10 commits intoCanner:feat/wren-wasmfrom
goldmedal:plan-wasm-sdk-npm

Conversation

@goldmedal
Copy link
Copy Markdown
Contributor

@goldmedal goldmedal commented Apr 15, 2026

Summary

  • Implements Plan A-M4b: wraps wren-core-wasm as a publishable npm package (wren-core-sdk) and publishes it to npm.
  • TypeScript wrapper (WrenEngine.init / loadMDL / registerParquet / registerJson / query / free) with clean types, parsed query results, and a profile-based loadMDL API.
  • Build pipeline: `wasm-pack build --target web` + TypeScript compile + assemble `dist/` via `scripts/build.mjs`. Exposed through a `justfile` (build, test, serve, size, clean).
  • Integration tests (`node --test sdk/tests/index.test.mjs`) cover init, registerJson, registerParquet, loadMDL, query errors, and engine isolation.
  • CI workflow (`.github/workflows/wasm-ci.yml`) builds WASM, runs tests, checks binary size (< 15 MB gzip), and auto-publishes on `wasm-sdk/v*` tags.
  • Consolidated 15 milestone-era examples into 3 minimal ones covering the current API: `inline.html`, `url-mode.html`, `test-cdn.html`, served by a CORS/Range/MIME-aware `serve.mjs`.
  • Docs: README (API reference + both data modes), AGENT_GUIDE (prompt template for AI agents generating browser dashboards), LICENSE, and `.claude/CLAUDE.md` crate context.

Published

Test plan

  • `just build` produces `dist/` with WASM + TypeScript (local verified)
  • `just test` passes (Node.js integration tests)
  • `just typecheck` passes
  • Binary size: ~68 MB raw / ~14 MB gzip (under 15 MB CI limit)
  • Model A verified: self-contained HTML with inline data runs from CDN (`test-cdn.html`), both via local HTTP server and `file://`
  • npm published, unpkg CDN confirmed returning `application/wasm` (HTTP 200)

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Released wren-core-sdk: a WebAssembly-based semantic SQL engine for querying Parquet, CSV, and JSON data in the browser and Node.js environments.
    • Available via npm and CDN (unpkg).
    • TypeScript SDK with comprehensive API support.
  • Documentation

    • Added README with installation and usage examples.
    • Added guide for building browser-based dashboards.
    • Added working examples demonstrating inline and URL-based data workflows.
  • Chores

    • Added GitHub Actions CI/CD workflow.
    • Added Apache 2.0 license.

goldmedal and others added 7 commits April 15, 2026 13:45
…cture

Wrap the WASM engine in a typed TypeScript API (WrenEngine class) that
handles JSON serialization, WASM init, and provides a clean interface
for browser-based semantic SQL queries. Includes npm package config,
build script, type stubs, and integration tests.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
CI triggers on wren-core-wasm/** changes, builds WASM + TypeScript,
checks binary size (<15 MB gzip), runs integration tests, and
publishes to npm on wasm-sdk/v* tags. README documents both URL
and inline data modes with full API reference.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Prompt template and complete examples for AI agents generating
browser-based dashboards with wren-core-sdk. Covers URL mode,
inline mode, MDL structure, Chart.js integration, and common pitfalls.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace 15 milestone-era examples with 3 minimal files covering
the current API: inline.html (registerJson + loadMDL + query),
url-mode.html (URL source mode), and serve.mjs (CORS + Range +
MIME-aware HTTP server with streaming).

Add justfile with build, test, serve, size, and clean recipes.
Add .claude/CLAUDE.md with crate-level context for AI agents.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy Apache-2.0 LICENSE to wren-core-wasm/ so npm publish includes it.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
test-cdn.html demonstrates self-contained HTML dashboard using the
published wren-core-sdk from unpkg (inline data + MDL + Chart.js).
Works both via local server and file:// (Model A verified).

Update README and AGENT_GUIDE to warn against jsDelivr: its free CDN
has a 50 MB per-file limit and the WASM binary is ~68 MB raw, so
jsDelivr returns 403 on the .wasm fetch. Use unpkg instead.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 15, 2026

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b3ca0824-6570-4ca7-aeed-862edf09d171

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • ✅ Review completed - (🔄 Check again to review again)
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions github-actions bot added documentation Improvements or additions to documentation ci labels Apr 15, 2026
Publish will be integrated with release-please instead of tag-triggered.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (12)
wren-core-wasm/LICENSE (1)

189-189: Copyright year may need updating.

The copyright year is 2024, but given this is a new package being published in 2026, consider updating to 2024-2026 or just 2026 to reflect when this package was actually created.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@wren-core-wasm/LICENSE` at line 189, Update the copyright notice string
"Copyright 2024 Canner, Inc." in the LICENSE to reflect the package publication
year (e.g., "Copyright 2024-2026 Canner, Inc." or "Copyright 2026 Canner,
Inc."); modify the exact line containing that string so it shows the chosen year
range or single year consistently across the LICENSE file.
wren-core-wasm/examples/test-cdn.html (1)

126-131: Consider cleanup in finally block.

engine.free() is only called on the success path. If an error occurs after engine initialization but before free(), the WASM memory won't be released. For a demo page this is minor, but for robustness:

Suggested pattern
+        let engine;
         try {
             // 1. Init engine from CDN
             log('Loading WASM from CDN...');
             const t0 = performance.now();
-            const engine = await WrenEngine.init();
+            engine = await WrenEngine.init();
             // ... rest of code ...
-            engine.free();
             log('Done');
         } catch (e) {
             log(`Error: ${e.message || e}`, false);
             console.error(e);
+        } finally {
+            engine?.free();
         }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@wren-core-wasm/examples/test-cdn.html` around lines 126 - 131, Move the
engine.free() call into a finally block so WASM memory is released even when an
exception occurs: after creating/initializing the engine (the variable named
engine in the try block), wrap the existing try/catch in try { ... } catch (e) {
... } finally { if (engine) engine.free(); } to ensure engine.free() is only
called when engine was successfully initialized; keep the existing logging in
catch (using e.message || e) and retain console.error(e).
wren-core-wasm/examples/serve.mjs (2)

10-10: Unused import.

readFile is imported but never used in the server logic.

Suggested fix
-import { stat, readFile } from 'node:fs/promises';
+import { stat } from 'node:fs/promises';
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@wren-core-wasm/examples/serve.mjs` at line 10, Remove the unused import by
deleting readFile from the import statement that currently reads "import { stat,
readFile } from 'node:fs/promises'"; keep stat only so the import becomes
"import { stat } from 'node:fs/promises'". This removes the unused symbol
readFile and avoids lint warnings while leaving the existing server logic (which
uses stat) unchanged.

39-39: Path traversal consideration for dev server.

The path construction joins user-controlled input directly. While this is a local development server, paths like /../../etc/passwd could theoretically escape the served root. Consider validating that the resolved path stays within ROOT if this server is ever exposed beyond localhost.

Optional hardening
-        const filePath = join(ROOT, decodeURIComponent(new URL(req.url, 'http://x').pathname));
+        const reqPath = decodeURIComponent(new URL(req.url, 'http://x').pathname);
+        const filePath = join(ROOT, reqPath);
+        if (!filePath.startsWith(ROOT)) {
+            return res.writeHead(403, { 'Content-Type': 'text/plain' }).end('Forbidden');
+        }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@wren-core-wasm/examples/serve.mjs` at line 39, The current construction of
filePath using join(ROOT, decodeURIComponent(new URL(req.url,
'http://x').pathname)) allows path traversal; fix by resolving and validating
the final path is inside ROOT before serving: compute the resolved path (using
path.resolve or equivalent) from ROOT and the decoded request pathname (symbols:
filePath, ROOT, decodeURIComponent, new URL), then check using
startsWith(resolvedRoot) or path.relative(ROOT, resolvedPath) to ensure it does
not escape the ROOT; if it does, return a 403/404 and do not serve the file.
wren-core-wasm/package.json (1)

6-7: Consider adding an exports field for modern ESM resolution.

Modern Node.js and bundlers prefer the exports field over main/types. This provides better encapsulation and explicit subpath exports.

Suggested addition
   "main": "dist/index.js",
   "types": "dist/index.d.ts",
+  "exports": {
+    ".": {
+      "types": "./dist/index.d.ts",
+      "default": "./dist/index.js"
+    }
+  },
   "files": [
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@wren-core-wasm/package.json` around lines 6 - 7, Add an "exports" field to
package.json to provide explicit ESM/CJS entry points and subpath encapsulation
instead of relying solely on "main" and "types"; update the package.json to
include an "exports" mapping that points the package root (".") to
"./dist/index.js" (and an appropriate "./dist/index.cjs" if you produce CJS),
and include a "types" or "types" conditional pointing to "./dist/index.d.ts" so
bundlers and Node's ESM resolver can find the correct module and type entry;
ensure the "main" and "types" fields remain or are made consistent with the new
"exports" mapping.
wren-core-wasm/sdk/tests/index.test.mjs (1)

329-335: Consider testing that engine is unusable after free().

The test only verifies free() doesn't throw. It might be valuable to also verify that subsequent operations on a freed engine fail appropriately, which would document the expected behavior and catch regressions.

💡 Proposed enhancement
 describe("free", () => {
   it("can be called without error", async () => {
     const engine = await WrenEngine.init({ wasmUrl: wasmBytes });
     engine.free();
     // No assertion needed — just verify it doesn't throw
   });
+
+  it("engine is unusable after free", async () => {
+    const engine = await WrenEngine.init({ wasmUrl: wasmBytes });
+    engine.free();
+
+    await assert.rejects(
+      () => engine.query("SELECT 1"),
+      /null pointer|freed|invalid/i,
+      "should reject operations on freed engine"
+    );
+  });
 });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@wren-core-wasm/sdk/tests/index.test.mjs` around lines 329 - 335, Add
assertions that a freed engine becomes unusable: after calling engine.free() in
the "free" test (WrenEngine.init -> engine.free), attempt at least one
representative operation (e.g., engine.eval, engine.call or
engine.createModule/execute) and assert it throws or returns an error as per
current API; update the test to expect the specific error/exception behavior to
document and lock in that post-free usage is invalid.
wren-core-wasm/.claude/CLAUDE.md (2)

13-22: Add language specifier to fenced code block.

The architecture diagram lacks a language specifier. While it's ASCII art, adding a language identifier (even text or plaintext) improves markdown linting compliance and accessibility.

📝 Proposed fix
-```
+```text
 Browser JS
   ├── registerParquet(name, bytes) → Arrow RecordBatch → MemTable
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@wren-core-wasm/.claude/CLAUDE.md` around lines 13 - 22, The fenced ASCII
diagram block is missing a language specifier; update the Markdown block by
adding a language label such as "text" or "plaintext" to the opening fence so
markdown linters parse it correctly (e.g., change the triple backticks before
the lines containing registerParquet, registerJson, loadMDL, query to ```text).
Ensure the opening fence now includes the specifier while leaving the ASCII art
content (the lines mentioning registerParquet, registerJson, loadMDL, query)
unchanged.

26-26: Hardcoded line count will become stale.

The documentation states "src/lib.rs (758 lines)" which will become inaccurate as the file evolves. Consider removing the line count or describing it qualitatively (e.g., "single-file crate").

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@wren-core-wasm/.claude/CLAUDE.md` at line 26, Remove the hardcoded line count
in the CLAUDE.md entry that reads "`src/lib.rs` (758 lines) — Single-file crate
with `WrenEngine` struct" and replace it with a stable description such as
"`src/lib.rs` — Single-file crate containing the WrenEngine struct" (or simply
omit the line count), ensuring the reference to src/lib.rs and the WrenEngine
struct remains for clarity.
wren-core-wasm/justfile (1)

55-68: Size reporting relies on bc which may not be universally available.

The size task uses bc for floating-point arithmetic. While bc is commonly installed, it's not guaranteed on minimal CI images or containers. Consider using awk for better portability.

♻️ Proposed fix using awk for portability
-    echo "WASM binary: $(echo "scale=1; $raw / 1048576" | bc) MB raw, $(echo "scale=1; $gzip / 1048576" | bc) MB gzip"
+    echo "WASM binary: $(awk "BEGIN {printf \"%.1f\", $raw / 1048576}") MB raw, $(awk "BEGIN {printf \"%.1f\", $gzip / 1048576}") MB gzip"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@wren-core-wasm/justfile` around lines 55 - 68, The size task in the justfile
uses bc for floating-point division in the echo line, which may be missing in
minimal CI; update the size recipe (the block starting with the size: shebang
and variables wasm/raw/gzip) to perform the MB calculations with awk instead of
bc, i.e., compute raw and gzip sizes divided by 1048576 and format to one
decimal place using awk, then include those awk-produced values in the final
echo so the script no longer depends on bc.
wren-core-wasm/scripts/build.mjs (1)

54-63: Unnecessary dynamic import of statSync.

statSync is dynamically imported at line 57, but other fs functions are already imported at the top (line 11). This adds inconsistency without benefit since the module is already loaded.

♻️ Proposed fix to use static import
-import { cpSync, existsSync, mkdirSync, rmSync } from "node:fs";
+import { cpSync, existsSync, mkdirSync, rmSync, statSync } from "node:fs";

Then at line 57-58:

-  const { statSync } = await import("node:fs");
-  const stats = statSync(wasmPath);
+  const stats = statSync(wasmPath);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@wren-core-wasm/scripts/build.mjs` around lines 54 - 63, The dynamic import of
statSync is unnecessary; update the top-level imports to include statSync from
"node:fs" (alongside existsSync already imported) and remove the inline await
import("node:fs") block in the report section: in the block that computes
wasmPath and checks existsSync(wasmPath), call statSync(wasmPath) directly to
get stats and compute sizeMB, eliminating the dynamic import and keeping
resolve, dist, existsSync, and statSync usage consistent.
.github/workflows/wasm-ci.yml (2)

35-45: Cache key may cause stale dependency issues.

The cache key only hashes Cargo.toml, but dependency versions are locked in Cargo.lock. If Cargo.lock changes without Cargo.toml changing, the cache will restore stale compiled dependencies.

♻️ Proposed fix to include Cargo.lock in cache key
-          key: wasm-cargo-${{ hashFiles('wren-core-wasm/Cargo.toml') }}
+          key: wasm-cargo-${{ hashFiles('wren-core-wasm/Cargo.toml', 'wren-core-wasm/Cargo.lock') }}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/wasm-ci.yml around lines 35 - 45, Update the Cache Cargo
step so the cache key includes the lockfile hash too: modify the key expression
that currently uses hashFiles('wren-core-wasm/Cargo.toml') (in the step named
"Cache Cargo") to also hash the corresponding Cargo.lock (e.g., include
'wren-core-wasm/Cargo.lock' in hashFiles) so changes to locked dependency
versions invalidate the cache and prevent restoring stale compiled dependencies.

47-48: Consider pinning wasm-pack version for reproducibility.

Installing via curl | sh fetches the latest version, which could introduce unexpected behavior if wasm-pack releases a breaking change. For CI stability, consider pinning a specific version.

♻️ Proposed fix to pin version
       - name: Install wasm-pack
-        run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
+        run: cargo install wasm-pack --version 0.13.1

Or use the cached binary approach with a version check.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/wasm-ci.yml around lines 47 - 48, The CI step named
"Install wasm-pack" currently pipes the installer script from the web, which
installs the latest release; change the step to pin a concrete wasm-pack version
(e.g., 0.12.1) by either downloading the matching release binary from the
wasm-pack GitHub releases page or invoking the installer with a fixed VERSION
(replace the current `curl ... | sh` in the "Install wasm-pack" run command).
Ensure the command explicitly references the chosen version so the workflow uses
a reproducible wasm-pack release.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@wren-core-wasm/justfile`:
- Around line 38-50: Add a new Just task named test-examples to the justfile (to
match the CLAUDE.md doc) that runs the Headless Node.js example tests (invoke
Node's test runner against the examples' test entry) so the documented "just
test-examples" command exists; if you prefer not to add a task instead, update
CLAUDE.md to remove or change the reference to test-examples. Reference the
justfile task name test-examples and the examples test entry (e.g., the examples
test entry point under examples/) when making the change.

In `@wren-core-wasm/sdk/src/index.ts`:
- Around line 45-47: Add a prominent warning and optional guard for URL-mode
name collisions in the loadMDL API: update the doc comment for loadMDL to
explicitly warn that URL mode resolves files as `{source}/{bare_name}.parquet`
and that identical bare table names across different schemas can silently
collide, and add an optional runtime check/flag (e.g., a new boolean option or
parameter in loadMDL like `failOnNameCollision` or `preventUrlResolution`) that,
when enabled, detects duplicate bare names resolved from MDL (using the same
logic as load_mdl_url_mode) and throws/logs a clear error instead of silently
reading the wrong file; reference the loadMDL function and the load_mdl_url_mode
resolution behavior when making the doc and guard changes.
- Around line 58-60: Change the registerParquet API to accept BufferSource
instead of ArrayBuffer and preserve ArrayBufferView metadata when converting to
Uint8Array: update the method signature for registerParquet(name: string, data:
BufferSource): Promise<void>, and inside the function detect if data is an
ArrayBufferView (ArrayBuffer.isView(data) / use instanceof ArrayBufferView) and
call this.engine.registerParquet(name, new Uint8Array((data as
ArrayBufferView).buffer, (data as ArrayBufferView).byteOffset, (data as
ArrayBufferView).byteLength)); otherwise call this.engine.registerParquet(name,
new Uint8Array(data as ArrayBuffer)); ensure you reference registerParquet and
this.engine.registerParquet in the change.

---

Nitpick comments:
In @.github/workflows/wasm-ci.yml:
- Around line 35-45: Update the Cache Cargo step so the cache key includes the
lockfile hash too: modify the key expression that currently uses
hashFiles('wren-core-wasm/Cargo.toml') (in the step named "Cache Cargo") to also
hash the corresponding Cargo.lock (e.g., include 'wren-core-wasm/Cargo.lock' in
hashFiles) so changes to locked dependency versions invalidate the cache and
prevent restoring stale compiled dependencies.
- Around line 47-48: The CI step named "Install wasm-pack" currently pipes the
installer script from the web, which installs the latest release; change the
step to pin a concrete wasm-pack version (e.g., 0.12.1) by either downloading
the matching release binary from the wasm-pack GitHub releases page or invoking
the installer with a fixed VERSION (replace the current `curl ... | sh` in the
"Install wasm-pack" run command). Ensure the command explicitly references the
chosen version so the workflow uses a reproducible wasm-pack release.

In `@wren-core-wasm/.claude/CLAUDE.md`:
- Around line 13-22: The fenced ASCII diagram block is missing a language
specifier; update the Markdown block by adding a language label such as "text"
or "plaintext" to the opening fence so markdown linters parse it correctly
(e.g., change the triple backticks before the lines containing registerParquet,
registerJson, loadMDL, query to ```text). Ensure the opening fence now includes
the specifier while leaving the ASCII art content (the lines mentioning
registerParquet, registerJson, loadMDL, query) unchanged.
- Line 26: Remove the hardcoded line count in the CLAUDE.md entry that reads
"`src/lib.rs` (758 lines) — Single-file crate with `WrenEngine` struct" and
replace it with a stable description such as "`src/lib.rs` — Single-file crate
containing the WrenEngine struct" (or simply omit the line count), ensuring the
reference to src/lib.rs and the WrenEngine struct remains for clarity.

In `@wren-core-wasm/examples/serve.mjs`:
- Line 10: Remove the unused import by deleting readFile from the import
statement that currently reads "import { stat, readFile } from
'node:fs/promises'"; keep stat only so the import becomes "import { stat } from
'node:fs/promises'". This removes the unused symbol readFile and avoids lint
warnings while leaving the existing server logic (which uses stat) unchanged.
- Line 39: The current construction of filePath using join(ROOT,
decodeURIComponent(new URL(req.url, 'http://x').pathname)) allows path
traversal; fix by resolving and validating the final path is inside ROOT before
serving: compute the resolved path (using path.resolve or equivalent) from ROOT
and the decoded request pathname (symbols: filePath, ROOT, decodeURIComponent,
new URL), then check using startsWith(resolvedRoot) or path.relative(ROOT,
resolvedPath) to ensure it does not escape the ROOT; if it does, return a
403/404 and do not serve the file.

In `@wren-core-wasm/examples/test-cdn.html`:
- Around line 126-131: Move the engine.free() call into a finally block so WASM
memory is released even when an exception occurs: after creating/initializing
the engine (the variable named engine in the try block), wrap the existing
try/catch in try { ... } catch (e) { ... } finally { if (engine) engine.free();
} to ensure engine.free() is only called when engine was successfully
initialized; keep the existing logging in catch (using e.message || e) and
retain console.error(e).

In `@wren-core-wasm/justfile`:
- Around line 55-68: The size task in the justfile uses bc for floating-point
division in the echo line, which may be missing in minimal CI; update the size
recipe (the block starting with the size: shebang and variables wasm/raw/gzip)
to perform the MB calculations with awk instead of bc, i.e., compute raw and
gzip sizes divided by 1048576 and format to one decimal place using awk, then
include those awk-produced values in the final echo so the script no longer
depends on bc.

In `@wren-core-wasm/LICENSE`:
- Line 189: Update the copyright notice string "Copyright 2024 Canner, Inc." in
the LICENSE to reflect the package publication year (e.g., "Copyright 2024-2026
Canner, Inc." or "Copyright 2026 Canner, Inc."); modify the exact line
containing that string so it shows the chosen year range or single year
consistently across the LICENSE file.

In `@wren-core-wasm/package.json`:
- Around line 6-7: Add an "exports" field to package.json to provide explicit
ESM/CJS entry points and subpath encapsulation instead of relying solely on
"main" and "types"; update the package.json to include an "exports" mapping that
points the package root (".") to "./dist/index.js" (and an appropriate
"./dist/index.cjs" if you produce CJS), and include a "types" or "types"
conditional pointing to "./dist/index.d.ts" so bundlers and Node's ESM resolver
can find the correct module and type entry; ensure the "main" and "types" fields
remain or are made consistent with the new "exports" mapping.

In `@wren-core-wasm/scripts/build.mjs`:
- Around line 54-63: The dynamic import of statSync is unnecessary; update the
top-level imports to include statSync from "node:fs" (alongside existsSync
already imported) and remove the inline await import("node:fs") block in the
report section: in the block that computes wasmPath and checks
existsSync(wasmPath), call statSync(wasmPath) directly to get stats and compute
sizeMB, eliminating the dynamic import and keeping resolve, dist, existsSync,
and statSync usage consistent.

In `@wren-core-wasm/sdk/tests/index.test.mjs`:
- Around line 329-335: Add assertions that a freed engine becomes unusable:
after calling engine.free() in the "free" test (WrenEngine.init -> engine.free),
attempt at least one representative operation (e.g., engine.eval, engine.call or
engine.createModule/execute) and assert it throws or returns an error as per
current API; update the test to expect the specific error/exception behavior to
document and lock in that post-free usage is invalid.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: e51429fd-58d7-4201-8d2a-7fe6884fd578

📥 Commits

Reviewing files that changed from the base of the PR and between 2e0e865 and 509021f.

⛔ Files ignored due to path filters (1)
  • wren-core-wasm/examples/data/orders.parquet is excluded by !**/*.parquet
📒 Files selected for processing (17)
  • .github/workflows/wasm-ci.yml
  • wren-core-wasm/.claude/CLAUDE.md
  • wren-core-wasm/.gitignore
  • wren-core-wasm/AGENT_GUIDE.md
  • wren-core-wasm/LICENSE
  • wren-core-wasm/README.md
  • wren-core-wasm/examples/inline.html
  • wren-core-wasm/examples/serve.mjs
  • wren-core-wasm/examples/test-cdn.html
  • wren-core-wasm/examples/url-mode.html
  • wren-core-wasm/justfile
  • wren-core-wasm/package.json
  • wren-core-wasm/scripts/build.mjs
  • wren-core-wasm/sdk/src/index.ts
  • wren-core-wasm/sdk/src/wren_core_wasm.d.ts
  • wren-core-wasm/sdk/tests/index.test.mjs
  • wren-core-wasm/sdk/tsconfig.json

Comment thread wren-core-wasm/justfile
Comment thread wren-core-wasm/sdk/src/index.ts Outdated
Comment thread wren-core-wasm/sdk/src/index.ts Outdated
goldmedal and others added 2 commits April 15, 2026 14:23
SDK API:
- registerParquet accepts BufferSource (not just ArrayBuffer), preserving
  TypedArray byteOffset/byteLength view metadata
- loadMDL JSDoc warns about URL-mode {source}/{bare_name}.parquet name
  collisions across schemas

Infra:
- Commit wren-core-wasm/Cargo.lock for WASM binary reproducibility
  (this crate is a WASM app, not a library published to crates.io).
  CI cache key now hashes Cargo.lock too.
- Pin wasm-pack to 0.14.0 via cargo install (reproducible CI)

Hygiene:
- serve.mjs: remove unused readFile import, add path traversal guard
- build.mjs: hoist statSync to static import
- justfile: size task uses awk instead of bc (more portable)
- package.json: add "exports" field for modern Node/bundler resolution
- test-cdn.html: move engine.free() to finally block
- CLAUDE.md: drop stale line count, add code-block lang, remove
  reference to non-existent test-examples task

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
cargo install fails because wasm-pack is pre-installed on ubuntu-latest
runners. taiki-e/install-action downloads the prebuilt binary for the
pinned version, which is both faster and correctly overrides the
pre-installed version.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@goldmedal goldmedal merged commit 0c04aed into Canner:feat/wren-wasm Apr 15, 2026
5 checks passed
@goldmedal goldmedal deleted the plan-wasm-sdk-npm branch April 15, 2026 06:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci documentation Improvements or additions to documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant