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

@mandel59/mojidata-api

v2.0.0

Published

Compatibility facade package for mojidata-api split packages

Readme

Mojidata API

@mandel59/mojidata-api is the compatibility facade for the split mojidata-api packages. New compositions should prefer the split packages directly, but the legacy subpath entrypoints remain available.

This facade package can run in both:

  • Node.js (HTTP server via Hono)
  • Browser (Hono app.fetch + SQL.js running in a WebWorker)

It also has split packages for composing the API yourself:

  • @mandel59/mojidata-api-core: backend-neutral SQL API composition
  • @mandel59/mojidata-api-hono: Hono app wiring
  • @mandel59/mojidata-api-runtime: worker client helpers and shared runtime utilities
  • @mandel59/mojidata-api-sqljs: explicit sql.js backend package
  • @mandel59/mojidata-api-sqlite-wasm: browser SQLite wasm OPFS backend package

The original @mandel59/mojidata-api/* subpath entrypoints remain available as compatibility facades and forward to the split packages.

Bundler-safe entrypoints

For bundled applications, choose the narrowest entrypoint for the runtime you are targeting. The root compatibility facade is convenient for Node scripts, but apps such as Cloudflare Workers, OpenNext, browser SPAs, and Web Workers should avoid importing backend packages they do not use.

| Target | Import | Notes | | --- | --- | --- | | Hono app wiring | @mandel59/mojidata-api/app | Edge-safe app factory. Does not select a database backend. | | Browser worker client | @mandel59/mojidata-api/browser-client | Re-exports the shared worker client. | | Worker protocol types | @mandel59/mojidata-api/worker-protocol | Type-only protocol surface for custom workers. | | Browser SQL.js worker | @mandel59/mojidata-api/browser-worker | Compatibility SQL.js worker entrypoint. | | Node SQL.js backend | @mandel59/mojidata-api/node-sqljs | Portable Node backend without native SQLite packages. | | Node better-sqlite3 backend | @mandel59/mojidata-api/node-better-sqlite3 | Requires installing @mandel59/mojidata-api-better-sqlite3 and its better-sqlite3 peer. | | Node node:sqlite backend | @mandel59/mojidata-api/node-sqlite | Requires installing @mandel59/mojidata-api-node-sqlite. | | SQLite wasm OPFS backend | @mandel59/mojidata-api-sqlite-wasm | Use the split ESM package directly for browser OPFS. | | SQLite wasm OPFS helpers | @mandel59/mojidata-api-sqlite-wasm/opfs-sahpool | Stable public helper subpath; avoid private lib/* imports. |

@mandel59/mojidata-api/node-better-sqlite3 and @mandel59/mojidata-api/node-sqlite are optional facade subpaths. They do not make native backends part of the default dependency path; install the matching split backend package when you import those subpaths.

For Node.js compatibility usage, createNodeDb() in this package uses the portable sql.js backend:

import { createNodeDb } from "@mandel59/mojidata-api"

const db = createNodeDb()

For new code that selects the backend explicitly, prefer @mandel59/mojidata-api/node-sqljs or the split @mandel59/mojidata-api-sqljs package. For browser SPAs that need persistent OPFS storage, use @mandel59/mojidata-api-sqlite-wasm explicitly.

Native Node backends are published separately so installing @mandel59/mojidata-api does not pull native SQLite concerns into the default path:

  • @mandel59/mojidata-api-better-sqlite3
  • @mandel59/mojidata-api-node-sqlite

Property search keys

/api/v1/idsfind supports property search through paired p and q parameters. Dictionary/index-like Unihan properties can be searched by exact value, .glob, .ne, and .notGlob keys:

/api/v1/idsfind?p=unihan.kMorohashi&q=03246
/api/v1/idsfind?p=unihan.kMorohashi.glob&q=4509*

Existence filters use p keys ending in .has or .notHas. Keep p and q arrays aligned and pass an empty q value for existence checks:

/api/v1/idsfind?ids=馬&p=totalStrokes.ge&q=25&p=unihan.kMorohashi.has&q=&limit=20

Representative supported keys include:

  • unihan.kMorohashi, unihan.kMorohashi.glob, unihan.kMorohashi.has
  • unihan.kKangXi, unihan.kHanYu, and other Unihan dictionary/index properties
  • mji.読み.has, mji.MJ文字図形名.has, mji.総画数.has
  • totalStrokes.has / totalStrokes.notHas

Tests

Tests live under tests/.

By default, they run against an in-process createNodeApp() instance, so no server startup is required:

yarn test

If you want to target an already-running server instead, set MOJIDATA_API_BASE_URL:

MOJIDATA_API_BASE_URL=http://localhost:3001 yarn test

If needed, start the dev server with:

yarn dev

Benchmarks

Repository benchmark tooling lives in the private workspace @mandel59/mojidata-api-bench, not in this published compatibility facade.

Use the workspace benchmark commands from the repository root:

yarn mojidata-api:bench:prepare
yarn mojidata-api:bench:local -- --scenario ivs-list --iterations 10
yarn mojidata-api:bench --backend sqljs

There is also a manual GitHub Actions workflow, Mojidata API Benchmark, for collecting benchmark artifacts on GitHub-hosted runners.

Browser usage (WebWorker)

mojidata-api needs these URLs at runtime:

  • sqlWasmUrl: URL to sql.js's sql-wasm.wasm
  • mojidataDbUrl: URL to moji.db
  • idsfindDbUrl: URL to idsfind.db

The exact way to obtain asset URLs depends on your bundler. For example, with Vite:

import wasmUrl from "sql.js/dist/sql-wasm.wasm?url"
import { createApp } from "@mandel59/mojidata-api-hono"
import { createMojidataApiWorkerClient } from "@mandel59/mojidata-api/browser-client"

const worker = new Worker(
  new URL("@mandel59/mojidata-api-sqljs/browser-worker", import.meta.url),
  { type: "module" },
)

const db = createMojidataApiWorkerClient(worker, {
  sqlWasmUrl: wasmUrl,
  mojidataDbUrl: "/assets/moji.db",
  idsfindDbUrl: "/assets/idsfind.db",
})
await db.ready

const app = createApp(db)

// Call in-browser (Hono `app.fetch`):
const url = new URL("/api/v1/mojidata?char=漢&select=UCS", "http://local")
const res = await app.fetch(new Request(url))
const body = await res.json()

// Cleanup when you're done:
db.terminate()

Custom browser workers can import protocol types from @mandel59/mojidata-api/worker-protocol instead of reaching into @mandel59/mojidata-api-runtime/lib/*.

Advanced composition

If you want to wire the API together yourself instead of using createNodeDb(), use the lower-level entry points:

import { createSqlApiDb } from "@mandel59/mojidata-api-core"
import { createApp } from "@mandel59/mojidata-api-hono"
import { createMojidataDbProvider, createSqlJsExecutor, openDatabaseFromFile } from "@mandel59/mojidata-api-sqljs"

const getMojidataDb = createMojidataDbProvider(() =>
  openDatabaseFromFile(require.resolve("@mandel59/mojidata/dist/moji.db")),
)

const getIdsfindDb = async () =>
  createSqlJsExecutor(
    await openDatabaseFromFile(require.resolve("@mandel59/idsdb/idsfind.db")),
  )

const db = createSqlApiDb({ getMojidataDb, getIdsfindDb })
const app = createApp(db)