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

inchi-js

v0.2.0

Published

InChI engine in TypeScript: convert Molfile ↔ InChI ↔ InChIKey. Wraps the official IUPAC InChI C library compiled to WebAssembly and base64-embedded so the package is self-contained.

Readme

inchi-js

A self-contained TypeScript wrapper around the official IUPAC InChI C library compiled to WebAssembly. Convert MDL Molfiles to InChI/InChIKey and back, in Node and in the browser, without any external file or fetch — the WASM binary is gzip-compressed and base64-embedded inside the package.

Installation

npm install inchi-js

Quick start

import {
  inchiFromMolfile,
  inchikeyFromInchi,
  molfileFromInchi,
} from 'inchi-js';

const ethanol = `\
  Mrv2014 01010100002D

  3  2  0  0  0  0            999 V2000
    0.0000    0.0000    0.0000 C   0  0  0  0  0  0  0  0  0  0  0  0
    1.0000    0.0000    0.0000 C   0  0  0  0  0  0  0  0  0  0  0  0
    2.0000    0.0000    0.0000 O   0  0  0  0  0  0  0  0  0  0  0  0
  1  2  1  0  0  0  0
  2  3  1  0  0  0  0
M  END
`;

const { inchi } = await inchiFromMolfile(ethanol);
// → 'InChI=1S/C2H6O/c1-2-3/h3H,2H2,1H3'

const { inchikey } = await inchikeyFromInchi(inchi);
// → 'LFQSCWFLJHTTHZ-UHFFFAOYSA-N'

const { molfile } = await molfileFromInchi(inchi);
// → reconstructed Molfile

API

All four functions are async because the WASM module is initialised lazily on first call (and cached forever after).

inchiFromMolfile(molfile, options?)

inchiFromMolfile(molfile: string, options?: {
  /** Raw InChI option string, e.g. '-AuxNone -DoNotAddH'. Default: '' */
  options?: string;
}): Promise<{
  returnCode: -1 | 0 | 1;
  inchi: string;
  auxinfo: string;
  message: string;
  log: string;
}>;

Wraps MakeINCHIFromMolfileText. returnCode === 0 means success; 1 is a warning (the result is still usable, see message/log); -1 is an error.

The InChI option string is documented in the IUPAC InChI Technical Manual. Common options include -AuxNone, -DoNotAddH, -FixedH, -RecMet, -SUU, -SLUUD.

inchikeyFromInchi(inchi)

inchikeyFromInchi(inchi: string): Promise<{
  returnCode: -1 | 0 | 1;
  inchikey: string;
  message: string;
}>;

Wraps GetINCHIKeyFromINCHI. Returns the 27-character InChIKey for a given InChI string.

molfileFromInchi(inchi, options?)

molfileFromInchi(inchi: string, options?: {
  options?: string;
}): Promise<{
  returnCode: -1 | 0 | 1;
  molfile: string;
  message: string;
  log: string;
}>;

Wraps GetStructFromINCHIEx + GetINCHIEx with -OutputSDF. Reconstructs an MDL Molfile from an InChI string.

molfileFromAuxinfo(auxinfo, options?)

molfileFromAuxinfo(auxinfo: string, options?: {
  /** Do not add explicit hydrogens. Default: false */
  doNotAddH?: boolean;
  /** Differentiate "unknown" from "undefined" stereo. Default: false */
  diffUnkUndfStereo?: boolean;
}): Promise<{
  returnCode: -1 | 0 | 1;
  molfile: string;
  message: string;
  log: string;
}>;

Wraps Get_inchi_Input_FromAuxInfo. The MDL chiral flag stored in the AuxInfo is preserved when emitting the Molfile.

loadInchiWasm()

Eagerly preloads the WASM module so the first conversion isn't slowed by the (one-time, ~100ms) instantiation. Returns the underlying Emscripten Module object.

import { loadInchiWasm } from 'inchi-js';

await loadInchiWasm();

How the WASM binary is shipped

The library is intentionally fetch-free. At build time (build/build-wasm.sh):

  1. The IUPAC InChI C source from vendor/inchi/INCHI-1-SRC/{INCHI_BASE,INCHI_API/libinchi}/src/*.c is linked with build/inchi_web.c (a JSON-emitting wrapper adapted from IUPAC-InChI/InChI-Web-Demo) via Emscripten + CMake.
  2. The resulting inchi.wasm is gzip-compressed (level: 9) and base64-encoded into src/wasm/data.ts.
  3. The Emscripten JS glue is rewritten as an ES module in src/wasm/glue.ts and the factory function is given the decoded bytes via the wasmBinary option — bypassing fetch entirely. The runtime bridge that decodes the bytes and instantiates the module lives in src/wasm/loadWasm.ts.

The generated data.ts and glue.ts files are committed, so consumers never need a C toolchain.

Test coverage vs. the upstream IUPAC suite

npm test runs the full upstream IUPAC test corpus against the WebAssembly build, in addition to the small canonical tests under src/__tests__/:

| Folder | Mirrors | Coverage | | ---------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | __tests__/regression/inchiSdf.test.ts | INCHI-1-TEST/tests/test_library/data/ci/inchi.sdf.gz | 2,190 structures — every InChI must equal the reference SQLite snapshot, plus InChIKey parity on the first 100. Honors the upstream expected_failures list (4 known regressions). | | __tests__/regression/mculeSdf.test.ts | INCHI-1-TEST/tests/test_library/data/ci/mcule.sdf.gz | 2,000 mcule.com structures vs. the reference SQLite snapshot. | | __tests__/executable/github52.test.ts | test_executable/test_github_52.py | V3000 empty bond block parsing. | | __tests__/executable/testIo.test.ts | test_executable/test_io.py | V3000 I/O edge cases: SCSR rejection, >999-atom rejection, -LargeMolecules switch, 999-atom acceptance. | | __tests__/executable/organometallicsPubchem.test.ts | test_executable/test_organometallics_pubchem.py | Every structure in the PubChem organometallics fixture must yield an InChI under -RecMet. | | __tests__/executable/aromaticIons.test.ts | test_executable/test_aromatic_ions.py | Three aromatic-bond cation/anion cases — xfail in upstream and here (test.fails). |

Out of scope: the upstream INCHI-1-TEST/tests/test_unit/ C++ unit tests (test_strutil.cpp, test_ichican2.cpp, …) exercise internal C functions that are not part of the public InChI API exposed via WebAssembly, and would require a separate native build. The upstream test_executable cases that depend on InChI CLI stderr parsing (test_alex_clark_structures, test_organometallics_ccdc, test_github_67, test_github_40, test_pubchem_107) are all marked xfail upstream and are skipped here as well — they document broken behavior rather than asserted invariants.

Benchmark vs. the native inchi-1 binary

benchmark/bench-inchi.ts runs the WASM build against the official IUPAC inchi-1 executable on the same 2,190-structure corpus used by the regression tests (vendor/inchi/INCHI-1-TEST/tests/test_library/data/ci/inchi.sdf.gz, avg ~3.7 KB / molfile). It reports three modes side by side:

  1. WASM, per molfile — the realistic JS use case: one inchiFromMolfile() call per structure inside a single Node process.
  2. Native, batch — the realistic CLI use case: one inchi-1 process that walks the whole SDF.
  3. Native, per call — for a 50-structure sample, spawn inchi-1 once per molfile. This isolates the per-structure C kernel cost from process-startup overhead.

Results on an Apple M1 with inchi-1 1.07.5 and Node 26:

| Mode | ms / structure | structures / s | | --------------------------------------------------------- | -------------- | -------------- | | WASM inchi-js, per molfile | 0.69 | ~1,450 | | Native inchi-1, batch (1 process for the whole SDF) | 0.43 | ~2,325 | | Native inchi-1, per molfile (separate process per call) | ~3.1 | ~320 |

  • WASM is ~1.6× slower than the native binary running in batch mode.
  • Spawning inchi-1 per molfile is ~7× slower than batching — the per-call mode exists to make that anti-pattern visible.
  • 2,188 / 2,190 InChIs match the native binary byte-for-byte; the two differences correspond to the known upstream regressions documented in inchiSdf.test.ts.
  • WASM cold start (module instantiation + gzip decompression) is ~60 ms and only paid once per process.

Run it with:

npm run benchmark                                  # full 2,190-structure corpus
node benchmark/bench-inchi.ts <sdf-path> [limit]   # custom corpus / limit
INCHI_BIN=/path/to/inchi-1 npm run benchmark       # use a specific native binary

Rebuilding the WASM

You only need this if you bump the InChI C version or change build/inchi_web.c. Requirements:

git submodule update --init --recursive
npm run build-wasm    # rebuilds src/wasm/data.ts + src/wasm/glue.ts
npm run tsc           # recompiles the lib/ output
npm test              # runs the test suite to verify

License

MIT — Copyright (c) cheminfo. See LICENSE for the full text and the acknowledgement of the bundled IUPAC InChI software (also MIT, Copyright (c) 2024 InChI Project).