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

@bubblyworld/highs-ts

v1.2.0

Published

A wasm build of the HiGHS (highs.dev) MILP solver with a convenient typescript interface. Runs with zero dependencies in both node and web environments.

Readme

highs-ts

npm version CI License

WASM build of the HiGHS solver with TypeScript bindings. Supports linear and mixed-integer linear programming, and runs in both node and browser environments with zero runtime dependencies.

Basic Usage

The HiGHS class provides direct access to the solver. Problems can be loaded from strings in CPLEX LP or MPS format.

import { HiGHS } from '@bubblyworld/highs-ts';

const lp = `
Maximize
  obj: x + 2 y
Subject To
  c1: x + y <= 10
  c2: x <= 5
Bounds
  0 <= x <= 10
  0 <= y <= 10
End
`;

const highs = await HiGHS.create();
await highs.parse(lp, 'lp');
const result = await highs.solve();

console.log(result.status);     // @expect: result.status === 'optimal'
console.log(result.objective);  // @expect: result.objective === 20
console.log(result.solution);   // Map { 'x' => 0, 'y' => 10 }

highs.free();

High-Level API

The Model class provides a builder interface for defining problems programmatically.

import { Model, sum } from '@bubblyworld/highs-ts';

const model = new Model();

// Variables: numVar (continuous), intVar (integer), boolVar (binary)
const x = model.numVar(0, 10, 'x');
const y = model.numVar(0, 10, 'y');

// Constraints with expressions
model.addConstraint(x.plus(y).leq(10), 'c1');
model.addConstraint(x.leq(5), 'c2');

// Objective
model.maximize(x.plus(y.times(2)));

const solution = await model.solve();
console.log(solution.status);      // @expect: solution.status === 'optimal'
console.log(solution.objective);   // @expect: solution.objective === 20
console.log(solution.getValue(x)); // 0
console.log(solution.getValue(y)); // 10

Expressions support chained arithmetic: plus(), minus(), times(), neg(). Constraints are created with leq(), geq(), and eq(). The sum() helper combines multiple terms. You can mix and match different kinds of variables and constraints as you like:

const model = new Model();
const x_a = model.intVar(0, 10, 'x_a');
const x_b = model.intVar(0, 8, 'x_b');
const y_a = model.boolVar('y_a');
const y_b = model.boolVar('y_b');

model.addConstraint(x_a.minus(y_a.times(10)).leq(0), 'cap_a');
model.addConstraint(x_b.minus(y_b.times(8)).leq(0), 'cap_b');
model.addConstraint(x_a.plus(x_b).leq(12), 'material');

model.maximize(
  x_a.times(10)
    .plus(x_b.times(12))
    .minus(y_a.times(50))
    .minus(y_b.times(60))
);

const solution = await model.solve();
console.log(solution.objective); // @expect: solution.objective === 50

Modelling Primitives

The Model class includes a number of higher-level primitives for common MILP reformulations, built on top of the basic variable and constraint API. Logical operations (and, or, not, xor), cardinality constraints (addAtMost, addAtLeast, addExactly), indicators, abs, max, min, and product are all available — see the source for full details. The rest of this section covers some of the less obvious primitives.

Semi-Continuous Variables

A semi-continuous variable is either exactly zero or lies within a range [lb, ub], with no values in between. This is useful for modelling minimum-batch-size or on/off decisions where partial activation doesn't make sense.

const model = new Model();
const batch = model.semiContVar(100, 500, 'batch');

model.maximize(batch);
const solution = await model.solve();
console.log(solution.objective); // @expect: solution.objective === 500

Integer Division

divMod(expr, d) returns quotient and remainder variables for dividing a non-negative integer expression by a positive integer constant.

const model = new Model();
const minutes = model.intVar(0, 1440, 'minutes');
const { quotient, remainder } = model.divMod(minutes, 60);

model.addConstraint(minutes.eq(145));
model.minimize(quotient);

const solution = await model.solve();
console.log(solution.objective); // @expect: solution.objective === 2

Either-Or Constraints

addEitherOr(c1, c2) enforces that at least one of two constraints must hold, using indicator variables internally.

const model = new Model();
const x = model.numVar(0, 100, 'x');
const y = model.numVar(0, 100, 'y');

model.addEitherOr(x.leq(10), y.leq(10));
model.maximize(x.plus(y));

const solution = await model.solve();
console.log(solution.objective); // @expect: solution.objective === 110

Reification

reify(constraint) returns a binary variable delta that is 1 if and only if the constraint is satisfied. This is the most general way to convert a constraint into a variable for use in other expressions. It supports <=, >=, and = senses.

const model = new Model();
const tasks = [
  model.intVar(0, 10, 'a'),
  model.intVar(0, 10, 'b'),
  model.intVar(0, 10, 'c'),
];

const overloaded = tasks.map(t => model.reify(t.geq(8)));
model.addConstraint(sum(...overloaded).leq(1));

model.maximize(sum(...tasks));
const solution = await model.solve();
console.log(solution.objective); // @expect: solution.objective === 24

Epsilon defaults to 1 for purely-integer expressions (exact reification) and 1e-6 for continuous expressions. Both epsilon and Big-M can be overridden via options:

const model = new Model();
const x = model.numVar(0, 100, 'x');
const delta = model.reify(x.leq(50), { bigM: 200, epsilon: 1e-4 });

model.addConstraint(delta.eq(1));
model.maximize(x);

const solution = await model.solve();
console.log(solution.objective); // @expect: solution.objective === 50

Configuration

Console Output

By default, solver output is suppressed. To enable progress logging, pass an explicit console configuration:

const highs = await HiGHS.create({
  console: {
    log: (msg) => console.log(msg),
    error: (msg) => console.error(msg)
  }
});

The same option works for Model.solve():

const solution = await model.solve({
  console: { log: console.log, error: console.error }
});

Building

Build the project (requires Emscripten for WASM compilation):

npm run build
npm run build:ts
npm run build:wasm

Run the test suite (requires a playwright-compatible browser):

npm test
npm run test:node    # Node only
npm run test:browser # Browser only (using Playwright)

Start the development server:

npm run serve

Licensing

This package is licensed under the MIT License. The WASM bundle includes HiGHS, also licensed under MIT (license).

Acknowledgements

The vast majority of the credit here goes to the authors of HiGHS. I've just packaged it nicely for use in the javascript/typescript world.