Documentation content

npm Dependencies

Programs can import npm packages the same way they do under Node.js. scriptc compiles each package your program uses to native code along with your own code. The executable doesn't read node_modules at runtime.

Package support is partial. Packages that scriptc can't compile are reported at build time with a diagnostic, so check new dependencies with scriptc coverage before relying on them.

Use a package

Create tool.ts:

tool.ts
import { Command } from "commander";

const program = new Command();

program
  .name("greet")
  .argument("<name>", "who to greet")
  .option("-u, --upper", "use uppercase")
  .action((name: string, opts: { upper?: boolean }) => {
    const text = `hello, ${name}`;
    console.log(opts.upper ? text.toUpperCase() : text);
  });

program.parse();

Install the dependency, then build and run the executable:

$ npm install commander
$ scriptc build tool.ts -o greet >/dev/null
$ ./greet ada --upper
HELLO, ADA

Your callback and the commander implementation both compile to native code. No extra flags are needed.

Package resolution

scriptc finds packages in node_modules with Node.js's resolution rules, including the export conditions in package.json, and compiles their dependencies too. TypeScript workspace packages compile as part of your program, including .js import specifiers that resolve to .ts sources.

Which packages compile

scriptc compiles a package automatically when it:

  • ships its own type declarations, and
  • ships readable, unminified JavaScript.

A package that doesn't meet these requirements, or that uses something scriptc can't compile, gets a package-specific diagnostic that explains why. The usual fixes are to switch to a version or alternative package that compiles, or to replace the call with code you write yourself.

Explicit package selection

Some packages rely on separately installed declarations, such as an @types/ package, or on types inferred from their JavaScript. To try compiling one of them, name it with --npm-static:

$ scriptc build app.ts --npm-static=three -o app >/dev/null

Naming a package skips the declaration requirement above, but the package still has to compile. --npm-static=auto uses the default automatic selection. The option accepts a comma-separated list and can be repeated.

Unsupported code inside a package

A JavaScript package can contain operations scriptc can't compile, often in functions your program never calls. These don't fail the build: each one compiles to code that throws a runtime error if it ever runs. Coverage reports list them as deferred sites, so review the list and test the parts of the package your program uses.

Provenance sources (experimental)

--provenance-sources compiles a package from the source at the commit its npm provenance attestation names, instead of from its published JavaScript. This lets packages written in TypeScript compile from their original TypeScript. Packages without a usable attestation compile from their installed files as usual.

Upgrading from scriptc 0.2

scriptc 0.2 had a --dynamic mode that embedded a JavaScript engine in the executable to run code that didn't compile, including packages that failed native compilation. scriptc 0.3 removed --dynamic and the embedded engine, so all application and package code now compiles to native code.

If you built with --dynamic, remove the flag and run scriptc coverage on your entry file. The report lists the operations and packages that need a change; rewrite those sites or replace the package. If you link native program objects into your own builds, use the runtime pack that matches the 0.3 compiler.