npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@effective/rison

v2.0.1

Published

URI friendly encoding for JSON structures

Readme

rison

Modern, TypeScript-first, ESM-only Rison: compact serialization for JSON-like structures — great for URLs and for compact storage. Based on Rison (Original).

Rison is a slight variation of JSON that looks vastly superior after URI encoding — ideal for compact state in URLs and also useful for storing structured data in localStorage/sessionStorage.

Why Rison for URLs

  • Encodes nested objects/arrays compactly and URI‑friendly (minimal escaping).
  • Ideal for client state in query or fragment (filters, sorting, columns, pagination).
  • Practical URL limits are infrastructure‑driven: conservative target ≈ 2 KB total; common defaults ≈ 8 KB. Fragments (#state=…) aren’t sent to servers and bypass those limits.
  • This package includes native compression helpers (gzip/deflate via CompressionStream) with an auto mode that selects the shortest token.

Quick Start

import { encode, decode } from "@effective/rison";

encode({ any: "json", yes: true });
// -> (any:json,yes:!t)

decode("(any:json,yes:!t)");
// -> { any: 'json', yes: true }

Optional URL compression helpers (native CompressionStream in modern browsers):

import { compressToUrl, decompressFromUrl } from "@effective/rison";

// mode: 'auto' | 'deflate' | 'none' (default: 'auto')
const compact = await compressToUrl({ page: 1, filters: { active: true } }, { mode: 'auto' });
// -> safe, compact string for query params/fragments

const value = await decompressFromUrl(compact);

### Compression formats & prefixes

- `none`: returns raw Rison (no prefix)
- `deflate`: returns a token prefixed with `d:` and base64url‑encoded (deflate‑raw)
- `auto`: compares raw Rison vs deflate and picks the shortest
// -> original value

Storage (localStorage) Usage

For storage, URL compatibility isn’t required. This library offers high‑density UTF‑16 packing (Base32768‑like) that maps 15‑bit chunks to non‑surrogate code points, giving better density than base64. Storage helpers default to base32768 and keep the same compression prefixes.

import { compressForStorage, decompressFromStorage } from "@effective/rison";

// mode: 'auto' | 'deflate' | 'none' (default: 'auto')
// encoding: 'base32768' | 'base64' (default: 'base32768')
const token = await compressForStorage({ theme: 'dark', tabs: [1, 2, 3] }, { encoding: 'base32768' });
// store in localStorage yourself
localStorage.setItem('app:state', token);

// later…
const restored = await decompressFromStorage(localStorage.getItem('app:state')!, { encoding: 'base32768' });

Convenience wrappers are also available if you prefer direct storage calls:

import { saveToLocalStorage, loadFromLocalStorage } from "@effective/rison";

await saveToLocalStorage("app:state", { theme: "dark" }, { encoding: "base32768" });
const state = await loadFromLocalStorage("app:state", { encoding: "base32768" });

Installation

pnpm add @effective/rison
# or
npm install @effective/rison

Requirements & Support

  • Browsers: modern engines support CompressionStream/DecompressionStream.
  • Node.js: 20+ provides CompressionStream in runtime; this repo builds/tests on Node 22+.
  • ESM-only package.

API

  • encode(value) → string
  • decode(string) → any
  • encodeUri(value) → string (Rison-encode + relaxed URI escaping)
  • compressToUrl(value, { mode }) → Promise
  • decompressFromUrl(string) → Promise
  • compressForStorage(value, { mode, encoding }) → Promise
  • decompressFromStorage(string, { encoding }) → Promise
  • saveToLocalStorage(key, value, { mode, encoding }) → Promise
  • loadFromLocalStorage(key, { encoding }) → Promise<any | null>

Notes:

  • Storage encoding defaults to base32768 for maximum density with simple decoding. You can switch to base64 for interoperability.
  • Compression prefixes remain the same: d: (deflate-raw) or none (raw rison).

Types are published via dist/rison.d.ts.

Demos & Examples

  • Live demo: 3‑pane source → converted → restored
    • Radio options for compression: auto, deflate, none
    • Three presets (Short/Medium/Long) to test compression impact

Nuqs Integration

Use Rison with nuqs to manage URL state in React apps.

import { useQueryState } from "nuqs";
import { encode, decode } from "@effective/rison";

// Rison serializer for nuqs
const risonSerializer = {
  parse: (value: string) => decode(value),
  serialize: (value: unknown) => encode(value)
};

export function Example() {
  // e.g. ?state=(filter:(active:!t),page:3)
  const [state, setState] = useQueryState("state", risonSerializer as any);

  return (
    <div>
      <pre>{JSON.stringify(state, null, 2)}</pre>
      <button onClick={() => setState({ filter: { active: true }, page: 3 })}>Set State</button>
    </div>
  );
}

Compression helpers are async and not suitable for nuqs serializers; if you need compression with nuqs, use a custom async layer outside of serializer calls.

For smaller URLs, use the compressed variant above.

Breaking changes in v1

  • ESM-only package, Node 22+ recommended.
  • Removed default export; use named imports.
  • Removed legacy O-/A-Rison helpers; use encode/decode only.

Contributing

  • Run tests: pnpm test
  • Typecheck: pnpm run typecheck
  • Format: pnpm run format

Releasing

Manual, assisted by release-it. Ensure your npm and GitHub tokens are configured locally.

pnpm install
pnpm run release

This runs typecheck/tests, builds, bumps the version, publishes to npm (public), tags the release, and publishes a GitHub Release.

License

MIT — see LICENSE.md.

  • Copyright © 2007–2009 Metaweb Technologies, Inc.
  • Copyright © 2024–present, Sebastian Software GmbH, Germany.

Acknowledgments

  • Originally created and published by Metaweb Technologies, Inc. (Google).
  • Encoder inspired by Douglas Crockford's json.js; decoder inspired by Oliver Steele's JSON for OpenLaszlo.
  • Thanks to all contributors over the years.