Switch from the WASM package#

Move code written for the plen-wasm glue API to plen-js and drop the WebAssembly module and its async startup.

Both packages expose the same Project API: the same methods, options, data and result types, and the same schedule, InputError and ProjectError exports. Results match the WASM package's, and result keys come back in the same sorted order. Most code moves over with an import change.

Prerequisites#

  • Code that uses the glue entry of plen-wasm (Project, schedule, InputError, ProjectError, default init). Code built on the raw JsonProject exports and JSON strings has no counterpart here.
  • Node 18 or later, or a browser.

Steps#

  1. Replace the dependency:

    npm uninstall plen-wasm
    npm install plen-js
    
  2. Change the import specifier. The export names stay the same:

    // before
    import init, { Project, schedule, InputError, ProjectError } from "plen-wasm";
    
    // after
    import init, { Project, schedule, InputError, ProjectError } from "plen-js";
    

    For CommonJS, use require. The named exports are direct, and init is .default:

    const { Project, schedule, InputError, ProjectError } = require("plen-js");
    
  3. Remove the await init() call. A Project works right after the import:

    import { Project } from "plen-js";
    
    const project = new Project();
    const result = project.solve({
      tasks: [
        { id: 1, start_date: "2026-08-10 08:00", duration: 2 },
        { id: 2, start_date: "2026-08-10 08:00", duration: 1 },
      ],
      links: [{ id: 1, source: 1, target: 2 }],
    });
    

    You don't need to call init(); it exists only so code written for the WASM package works unchanged. If you keep the call, it resolves undefined immediately. It doesn't return the module exports the WASM init() returns, so remove any code that reads its result. Drop the .wasm file path or bytes you passed to it too: init ignores its argument.

  4. Keep or remove the dispose() calls. dispose() is optional in JavaScript; after it, every call on that project throws Error("Project has been disposed"). Garbage collection frees the memory either way. Keep the calls if the same code must also run on the WASM package.

  5. Check code that depends on WASM-specific failures. Everything else, including InputError kind, message and path and ProjectError code, stays the same:

    Case plen-wasm plen-js
    A required argument is undefined, e.g. preview(undefined) wasm-bindgen argument error InputError
    A string contains a lone surrogate rejected accepted
    An input object has a getter read twice read once
    Internal engine failure WebAssembly trap Error named Panic

    See Error handling for the full list of errors.

Result#

The project schedules with no WebAssembly download or init() wait, and result has the same shape and values the WASM package returned:

{ baselineId: "1-…", conflicts: [], converged: true, cycles: [], notes: [],
  updates: [{ end_date: "2026-08-13 08:00", id: 2, kind: "task", start_date: "2026-08-12 08:00" }] }

baselineId is an opaque token, so its value can differ from the one the WASM package returned for the same data.

Every method still runs synchronously on the calling thread, as it did on the WASM package. To keep long leveling or evaluate runs off the UI thread, see Run in a worker.