@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: explicitsql.jsbackend 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=20Representative supported keys include:
unihan.kMorohashi,unihan.kMorohashi.glob,unihan.kMorohashi.hasunihan.kKangXi,unihan.kHanYu, and other Unihan dictionary/index propertiesmji.読み.has,mji.MJ文字図形名.has,mji.総画数.hastotalStrokes.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 testIf you want to target an already-running server instead, set MOJIDATA_API_BASE_URL:
MOJIDATA_API_BASE_URL=http://localhost:3001 yarn testIf needed, start the dev server with:
yarn devBenchmarks
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 sqljsThere 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 tosql.js'ssql-wasm.wasmmojidataDbUrl: URL tomoji.dbidsfindDbUrl: URL toidsfind.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)