Skip to content

Bundling & runtimes

Mero.js is a zero-dependency package built on Web Platform APIs. This guide covers how it’s packaged, which runtimes support which features, and the browser-specific concerns (CORS, SSR).

The package is "type": "module" and ships three builds, selected automatically through its exports map:

Condition File Format
import (bundlers, Node ESM) dist/index.mjs ESM
require (Node CommonJS) dist/index.cjs CommonJS
browser (bundler browser target) dist/index.browser.mjs ESM, minified
types dist/index.d.ts TypeScript declarations
// ESM / TypeScript
import { createMeroJs } from '@calimero-network/mero-js';
// CommonJS
const { createMeroJs } = require('@calimero-network/mero-js');

The package sets "sideEffects": false, so a modern bundler (esbuild, Rollup, Vite, webpack) tree-shakes away everything you don’t import — pull in just createMeroJs, or only a helper like withRetry, and the rest is dropped.

The HTTP and SSE surfaces run on every modern runtime. The WebSocket client and the browser-only helpers have narrower support:

Feature Browser Node 18–21 Node 22+ Deno / Bun Edge workers
sdk.admin / sdk.auth / sdk.rpc (fetch)
sdk.events (SSE, fetch streaming) ⚠️¹
sdk.ws (needs global WebSocket) ❌² ⚠️¹
LocalStorageTokenStore ❌³ ❌³ ❌³ ❌³
CloudClient (window.open)
  1. Edge runtimes restrict long-lived fetch streams and outbound WebSocket; check your platform’s limits before relying on live event streams there.
  2. Node gained a global WebSocket in v22. On 18–21, sdk.ws throws unless you install a WebSocket polyfill onto globalThis. Prefer sdk.events (SSE) server-side.
  3. Falls back to a no-op / null off the browser (it guards typeof localStorage). Use MemoryTokenStore, or a custom TokenStore, on the server.

A browser app calling a merod node on a different origin is a cross-origin request, so the node must return the appropriate CORS headers (Access-Control-Allow-Origin, and for preflight Access-Control-Allow-Methods / -Headers). Because the SDK authenticates with an Authorization: Bearer header, requests are non-simple and the browser sends a preflight OPTIONS the node must answer. A CORS rejection surfaces as an HTTPError with status: 0 (the browser hides the details from JavaScript). Only set requestCredentials: 'include' if the node authenticates with cookies — with bearer tokens you don’t need it.

A few APIs touch browser globals and must be guarded (or only called client-side) in Next.js / Remix / SvelteKit:

  • LocalStorageTokenStore — safe to construct anywhere (returns null on the server), but it only persists in the browser.
  • MeroJs.parseAuthCallback() / parseAuthCallback() — read window.location and call history.replaceState; browser-only.
  • CloudClient.enableHA / disableHA — call window.open; browser-only.

Everything else (sdk.admin, sdk.auth, sdk.rpc, sdk.events) works on the server. For a server-only MeroJs, pass a MemoryTokenStore (or your own store) and drive baseUrl/credentials from environment variables.