Convert Figma logo to code with AI

denoland logodnt

Deno to npm package build tool.

1,302
41
1,302
103

Top Related Projects

39,034

An extremely fast bundler for the web

32,103

Rust-based platform for the Web

43,888

The zero configuration build tool for the web. 📦🚀

25,839

Next-generation ES module bundler

65,410

A bundler for javascript and friends. Packs many modules into a few bundled assets. Code Splitting allows for loading parts of the application on demand. Through "loaders", modules can be CommonJs, AMD, ES6 modules, CSS, Images, JSON, Coffeescript, LESS, ... and your custom stuff.

9,568

Compile a Node.js project into a single file. Supports TypeScript, binary addons, dynamic requires.

Quick Overview

Denoland/dnt (Deno to Node Transform) is a tool that allows developers to build, test, and publish NPM packages written in TypeScript using Deno. It provides a seamless way to transform Deno-compatible code into Node.js-compatible packages, enabling cross-runtime compatibility.

Pros

  • Enables writing code in Deno and publishing it for Node.js environments
  • Supports automatic transformation of Deno-specific APIs to Node.js equivalents
  • Includes built-in testing capabilities for both Deno and Node.js environments
  • Simplifies the process of maintaining cross-runtime TypeScript packages

Cons

  • May not cover all edge cases in API transformations
  • Requires understanding of both Deno and Node.js ecosystems
  • Limited to TypeScript projects, not suitable for pure JavaScript codebases
  • Potential overhead in maintaining separate configurations for Deno and Node.js

Code Examples

  1. Basic configuration for dnt:
import { build, emptyDir } from "https://deno.land/x/dnt/mod.ts";

await emptyDir("./npm");

await build({
  entryPoints: ["./mod.ts"],
  outDir: "./npm",
  shims: {
    deno: true,
  },
  package: {
    name: "my-library",
    version: "1.0.0",
    description: "My awesome library",
  },
});
  1. Transforming Deno-specific code:
// Input: Deno-specific code
const text = await Deno.readTextFile("./example.txt");

// Output: Transformed Node.js code
import * as fs from "fs/promises";
const text = await fs.readFile("./example.txt", "utf8");
  1. Running tests in both Deno and Node.js environments:
import { test } from "https://deno.land/std/testing/mod.ts";

test("my test", () => {
  // Test code here
});

// dnt will automatically transform this to work in Node.js

Getting Started

  1. Install Deno: https://deno.land/#installation
  2. Create a new project directory and navigate to it
  3. Create a mod.ts file with your Deno code
  4. Create a build_npm.ts file with the following content:
import { build, emptyDir } from "https://deno.land/x/dnt/mod.ts";

await emptyDir("./npm");

await build({
  entryPoints: ["./mod.ts"],
  outDir: "./npm",
  shims: {
    deno: true,
  },
  package: {
    name: "your-package-name",
    version: "0.1.0",
    description: "Your package description",
  },
});
  1. Run the build script: deno run -A build_npm.ts
  2. Your Node.js-compatible package will be generated in the ./npm directory

Competitor Comparisons

39,034

An extremely fast bundler for the web

Pros of esbuild

  • Extremely fast build times, often 10-100x faster than other bundlers
  • Supports a wide range of file formats and languages (JS, TS, CSS, JSON, etc.)
  • Highly configurable with a rich API for advanced use cases

Cons of esbuild

  • Primarily focused on bundling and minification, not a complete build system
  • Less integrated with Deno-specific features and ecosystem
  • May require additional configuration for certain Deno-specific use cases

Code Comparison

esbuild:

import * as esbuild from 'esbuild'

await esbuild.build({
  entryPoints: ['app.js'],
  bundle: true,
  outfile: 'out.js',
})

dnt:

import { build } from "https://deno.land/x/dnt/mod.ts";

await build({
  entryPoints: ["./mod.ts"],
  outDir: "./npm",
  shims: { ... },
});

Summary

esbuild is a high-performance JavaScript bundler and minifier, while dnt is specifically designed for building and publishing Deno modules as npm packages. esbuild excels in speed and versatility for general JavaScript/TypeScript projects, whereas dnt provides a more tailored solution for Deno-to-npm workflows.

32,103

Rust-based platform for the Web

Pros of swc

  • Significantly faster compilation and transpilation speeds
  • Broader language support, including TypeScript, JSX, and more
  • Extensible plugin system for custom transformations

Cons of swc

  • Steeper learning curve due to more complex configuration options
  • Less focused on Deno-specific use cases
  • Larger project scope may lead to more frequent updates and potential instability

Code Comparison

swc configuration example:

{
  "jsc": {
    "parser": {
      "syntax": "typescript",
      "tsx": true
    },
    "target": "es2015"
  }
}

dnt configuration example:

{
  entryPoints: ["./mod.ts"],
  outDir: "./npm",
  shims: {
    deno: true
  }
}

Summary

swc is a more comprehensive and faster tool for JavaScript and TypeScript compilation, offering broader language support and extensibility. However, it may be more complex to set up and use compared to dnt. dnt, on the other hand, is specifically designed for Deno-to-Node.js package conversion, making it simpler and more focused for that particular use case. The choice between the two depends on the specific project requirements and the developer's familiarity with each tool's ecosystem.

43,888

The zero configuration build tool for the web. 📦🚀

Pros of Parcel

  • Zero configuration out of the box, making it easy to get started
  • Supports a wide range of file types and assets
  • Fast build times with built-in caching and multi-core processing

Cons of Parcel

  • Less flexible for complex configurations compared to dnt
  • May include unnecessary features for simpler projects
  • Larger bundle sizes in some cases due to automatic inclusion of dependencies

Code Comparison

Parcel:

// No configuration needed, just run:
parcel index.html

dnt:

import { build } from "https://deno.land/x/dnt/mod.ts";

await build({
  entryPoints: ["./mod.ts"],
  outDir: "./npm",
  shims: { ... },
  package: { ... },
});

Key Differences

  • Parcel is a general-purpose bundler for web applications, while dnt is specifically designed for converting Deno modules to Node.js packages
  • Parcel focuses on simplicity and ease of use, whereas dnt provides more control over the build process for Deno-to-Node.js conversions
  • Parcel handles various asset types and has built-in optimizations, while dnt is tailored for TypeScript/JavaScript module conversion
25,839

Next-generation ES module bundler

Pros of Rollup

  • Mature and widely adopted in the JavaScript ecosystem
  • Extensive plugin ecosystem for various build optimizations
  • Supports multiple output formats (ES modules, CommonJS, UMD)

Cons of Rollup

  • Primarily focused on JavaScript bundling, less suited for TypeScript
  • Requires additional configuration for TypeScript support
  • May need more setup for Deno-specific features

Code Comparison

Rollup configuration:

export default {
  input: 'src/main.js',
  output: {
    file: 'bundle.js',
    format: 'cjs'
  }
};

dnt configuration:

await build({
  entryPoints: ["mod.ts"],
  outDir: "./npm",
  shims: { deno: true },
  package: { name: "my-library", version: "0.1.0" }
});

Summary

Rollup is a versatile JavaScript bundler with a rich ecosystem, while dnt is specifically designed for Deno-to-Node package conversion. Rollup offers more flexibility for various JavaScript projects, but dnt provides a streamlined experience for Deno developers targeting npm. The choice between them depends on your project's requirements and target environment.

65,410

A bundler for javascript and friends. Packs many modules into a few bundled assets. Code Splitting allows for loading parts of the application on demand. Through "loaders", modules can be CommonJs, AMD, ES6 modules, CSS, Images, JSON, Coffeescript, LESS, ... and your custom stuff.

Pros of webpack

  • Mature ecosystem with extensive plugin support and community resources
  • Handles a wide variety of asset types beyond JavaScript
  • Powerful code splitting and dynamic import capabilities

Cons of webpack

  • Steeper learning curve and more complex configuration
  • Slower build times for large projects
  • Larger bundle sizes if not optimized properly

Code Comparison

webpack configuration:

module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'dist'),
  },
};

dnt configuration:

await build({
  entryPoints: ["./mod.ts"],
  outDir: "./npm",
  shims: {},
  package: {
    name: "my-package",
    version: "0.1.0",
  },
});

Summary

webpack is a powerful and versatile bundler with a large ecosystem, suitable for complex web applications. It offers extensive customization but can be more challenging to set up and optimize.

dnt (Deno to Node Transform) is specifically designed for converting Deno modules to Node.js packages. It's simpler to use and focused on TypeScript/JavaScript, but lacks the broad asset handling capabilities of webpack.

Choose webpack for complex web projects with diverse asset types, and dnt for streamlined Deno-to-Node.js package conversion.

9,568

Compile a Node.js project into a single file. Supports TypeScript, binary addons, dynamic requires.

Pros of ncc

  • Simpler setup and usage for Node.js projects
  • Produces a single file output, making deployment easier
  • Supports TypeScript out of the box

Cons of ncc

  • Limited to Node.js ecosystem
  • May have issues with certain dynamic imports or non-standard module systems
  • Less flexibility in output format compared to dnt

Code Comparison

ncc:

const ncc = require('@vercel/ncc')

ncc(entry, {
  // ncc options
}).then(({ code, map, assets }) => {
  console.log(code)
})

dnt:

import { build } from "https://deno.land/x/dnt/mod.ts";

await build({
  entryPoints: ["./mod.ts"],
  outDir: "./npm",
  shims: { ... },
  package: { ... },
});

Key Differences

  • ncc focuses on bundling Node.js projects into a single file
  • dnt is designed for converting Deno modules to Node.js/npm packages
  • ncc is more suitable for application bundling, while dnt is better for library authors transitioning from Deno to npm
  • dnt provides more extensive configuration options for output structure and package metadata

Convert Figma logo designs to code with AI

Visual Copilot

Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.

Try Visual Copilot

README

dnt - Deno to Node Transform

JSR

Deno to npm package build tool.

What does this do?

Takes a Deno module and creates an npm package for use in Node.js.

There are several steps done in a pipeline:

  1. Transforms Deno code to Node including files found by deno test.
    • Rewrites module specifiers.
    • Injects shims for any Deno namespace or other global name usages as specified.
    • Rewrites esm.sh specifiers to bare specifiers and includes these dependencies in a package.json.
    • When remote modules cannot be resolved to an npm package, it downloads them and rewrites specifiers to make them local.
    • Allows mapping any specifier to an npm package.
  2. Type checks the output.
  3. Emits ESM, CommonJS, and TypeScript declaration files along with a package.json file.
  4. Runs the final output in Node.js through a test runner calling all Deno.test calls.

Setup

  1. deno add jsr:@deno/dnt

  2. Create a build script file:

    // ex. scripts/build_npm.ts
    import { build, emptyDir } from "@deno/dnt";
    
    await emptyDir("./npm");
    
    await build({
      entryPoints: ["./mod.ts"],
      outDir: "./npm",
      shims: {
        // see JS docs for overview and more options
        deno: true,
      },
      package: {
        // package.json properties
        name: "your-package",
        version: Deno.args[0],
        description: "Your package.",
        license: "MIT",
        repository: {
          type: "git",
          url: "git+https://github.com/username/repo.git",
        },
        bugs: {
          url: "https://github.com/username/repo/issues",
        },
      },
      postBuild() {
        // steps to run after building and before running the tests
        Deno.copyFileSync("LICENSE", "npm/LICENSE");
        Deno.copyFileSync("README.md", "npm/README.md");
      },
    });
    
  3. Ignore the output directory with your source control if you desire (ex. add npm/ to .gitignore).

  4. Run it and npm publish:

    # run script
    deno run -A scripts/build_npm.ts 0.1.0
    
    # go to output directory and publish
    cd npm
    npm publish
    

Example Build Logs

[dnt] Transforming...
[dnt] Running npm install...
[dnt] Building project...
[dnt] Type checking ESM...
[dnt] Emitting ESM package...
[dnt] Emitting script package...
[dnt] Running tests...

> test
> node test_runner.js

Running tests in ./script/mod.test.js...

test escapeWithinString ... ok
test escapeChar ... ok

Running tests in ./esm/mod.test.js...

test escapeWithinString ... ok
test escapeChar ... ok
[dnt] Complete!

Docs

Disabling Type Checking, Testing, Declaration Emit, or CommonJS/UMD Output

Use the following options to disable any one of these, which are enabled by default:

await build({
  // ...etc...
  typeCheck: false,
  test: false,
  declaration: false,
  scriptModule: false,
});

Type Checking Both ESM and Script Output

By default, only the ESM output will be type checked for performance reasons. That said, it's recommended to type check both the ESM and the script (CJS/UMD) output by setting typeCheck to "both":

await build({
  // ...etc...
  typeCheck: "both",
});

Ignoring Specific Type Checking Errors

Sometimes you may be getting a TypeScript error that is not helpful and you want to ignore it. This is possible by using the filterDiagnostic option:

await build({
  // ...etc...
  filterDiagnostic(diagnostic) {
    if (
      diagnostic.file?.fileName.endsWith("fmt/colors.ts")
    ) {
      return false; // ignore all diagnostics in this file
    }
    // etc... more checks here
    return true;
  },
});

This is especially useful for ignoring type checking errors in remote dependencies.

Top Level Await

Top level await doesn't work in CommonJS/UMD and dnt will error if a top level await is used and you are outputting CommonJS/UMD code. If you want to output a CommonJS/UMD package then you'll have to restructure your code to not use any top level awaits. Otherwise, set the scriptModule build option to false:

await build({
  // ...etc...
  scriptModule: false,
});

Shims

dnt will shim the globals specified in the build options. For example, if you specify the following build options:

await build({
  // ...etc...
  shims: {
    deno: true,
  },
});

Then write a statement like so...

Deno.readTextFileSync(...);

...dnt will create a shim file in the output, re-exporting the @deno/shim-deno npm shim package and change the Deno global to be used as a property of this object.

import * as dntShim from "./_dnt.shims.js";

dntShim.Deno.readTextFileSync(...);

Test-Only Shimming

If you want a shim to only be used in your test code as a dev dependency, then specify "dev" for the option.

For example, to use the Deno namespace only for development and the setTimeout and setInterval browser/Deno compatible shims in the distributed code, you would do:

await build({
  // ...etc...
  shims: {
    deno: "dev",
    timers: true,
  },
});

Preventing Shimming

To prevent shimming in specific instances, add a // dnt-shim-ignore comment:

// dnt-shim-ignore
Deno.readTextFileSync(...);

...which will now output that code as-is.

Built-In Shims

Set any of these properties to true (distribution and test) or "dev" (test only) to use them.

  • deno - Shim the Deno namespace.
  • timers - Shim the global setTimeout and setInterval functions with Deno and browser compatible versions.
  • prompts - Shim the global confirm, alert, and prompt functions.
  • blob - Shim the Blob global with the one from the "buffer" module.
  • crypto - Shim the crypto global.
  • domException - Shim the DOMException global using the "domexception" package (https://www.npmjs.com/package/domexception)
  • undici - Shim fetch, File, FormData, Headers, Request, and Response by using the "undici" package (https://www.npmjs.com/package/undici).
  • weakRef - Sham for the WeakRef global, which uses globalThis.WeakRef when it exists. The sham will throw at runtime when calling deref() and WeakRef doesn't globally exist, so this is only intended to help type check code that won't actually use it.
  • webSocket - Shim WebSocket by using the ws package.
Deno.test-only shim

If you only want to shim Deno.test then provide the following:

await build({
  // ...etc...
  shims: {
    deno: {
      test: "dev",
    },
  },
});

This may be useful in Node v14 and below where the full deno shim doesn't always work. See the section on Node v14 below for more details

Custom Shims (Advanced)

In addition to the pre-defined shim options, you may specify your own custom packages to use to shim globals.

For example:

await build({
  scriptModule: false, // node-fetch 3+ only supports ESM
  // ...etc...
  shims: {
    custom: [{
      package: {
        name: "node-fetch",
        version: "~3.1.0",
      },
      globalNames: [{
        // for the `fetch` global...
        name: "fetch",
        // use the default export of node-fetch
        exportName: "default",
      }, {
        name: "RequestInit",
        typeOnly: true, // only used in type declarations
      }],
    }, {
      // this is what `blob: true` does internally
      module: "buffer", // uses node's "buffer" module
      globalNames: ["Blob"],
    }, {
      // this is what `domException: true` does internally
      package: {
        name: "domexception",
        version: "^4.0.0",
      },
      typesPackage: {
        name: "@types/domexception",
        version: "^4.0.0",
      },
      globalNames: [{
        name: "DOMException",
        exportName: "default",
      }],
    }],
    // shims to only use in the tests
    customDev: [{
      // this is what `timers: "dev"` does internally
      package: {
        name: "@deno/shim-timers",
        version: "~0.1.0",
      },
      globalNames: ["setTimeout", "setInterval"],
    }],
  },
});

Local and Remote Shims

Custom shims can also refer to local or remote modules:

await build({
  // ...etc...
  shims: {
    custom: [{
      module: "./my-custom-fetch-implementation.ts",
      globalNames: ["fetch"],
    }, {
      module: "https://deno.land/x/some_remote_shim_module/mod.ts",
      globalNames: ["setTimeout"],
    }],
  },
});

Where my-custom-fetch-implementation.ts contains:

export function fetch(/* etc... */) {
  // etc...
}

This is useful in situations where you want to implement your own shim.

Specifier to npm Package Mappings

In most cases, dnt won't know about an npm package being available for one of your dependencies and will download remote modules to include in your package. There are scenarios though where an npm package may exist and you want to use it instead. This can be done by providing a specifier to npm package mapping.

For example:

await build({
  // ...etc...
  mappings: {
    "https://deno.land/x/code_block_writer@11.0.0/mod.ts": {
      name: "code-block-writer",
      version: "^11.0.0",
      // optionally specify if this should be a peer dependency
      peerDependency: false,
    },
  },
});

This will:

  1. Change all "https://deno.land/x/code_block_writer@11.0.0/mod.ts" specifiers to "code-block-writer"
  2. Add a package.json dependency for "code-block-writer": "^11.0.0".

Note that dnt will error if you specify a mapping and it is not found in the code. This is done to prevent the scenario where a remote specifier's version is bumped and the mapping isn't updated.

Mapping specifier to npm package subpath

Say an npm package called example had a subpath at sub_path.js and you wanted to map https://deno.land/x/example@0.1.0/sub_path.ts to that subpath. To specify this, you would do the following:

await build({
  // ...etc...
  mappings: {
    "https://deno.land/x/example@0.1.0/sub_path.ts": {
      name: "example",
      version: "^0.1.0",
      subPath: "sub_path.js", // note this
    },
  },
});

This would cause the following:

import * as mod from "https://deno.land/x/example@0.1.0/sub_path.ts";

...to go to...

import * as mod from "example/sub_path.js";

...with a dependency on "example": "^0.1.0".

Multiple Entry Points

To do this, specify multiple entry points like so (ex. an entry point at . and another at ./internal):

await build({
  entryPoints: ["mod.ts", {
    name: "./internal",
    path: "internal.ts",
  }],
  // ...etc...
});

This will create a package.json with these as exports:

{
  "name": "your-package",
  // etc...
  "main": "./script/mod.js",
  "module": "./esm/mod.js",
  "types": "./types/mod.d.ts",
  "exports": {
    ".": {
      "import": {
        "types": "./types/mod.d.ts",
        "default": "./esm/mod.js"
      },
      "require": {
        "types": "./types/mod.d.ts",
        "default": "./script/mod.js"
      }
    },
    "./internal": {
      "import": {
        "types": "./types/internal.d.ts",
        "default": "./esm/internal.js"
      },
      "require": {
        "types": "./types/internal.d.ts",
        "default": "./script/internal.js"
      }
    }
  }
}

Now these entry points could be imported like import * as main from "your-package" and import * as internal from "your-package/internal";.

Bin/CLI Packages

To publish an npm bin package similar to deno install, add a kind: "bin" entry point:

await build({
  entryPoints: [{
    kind: "bin",
    name: "my_binary", // command name
    path: "./cli.ts",
  }],
  // ...etc...
});

This will add a "bin" entry to the package.json and add #!/usr/bin/env node to the top of the specified entry point.

Node and Deno Specific Code

You may find yourself in a scenario where you want to run certain code based on whether someone is in Deno or if someone is in Node and feature testing is not possible. For example, say you want to run the deno executable when the code is running in Deno and the node executable when it's running in Node.

which_runtime

One option to handle this, is to use the which_runtime deno.land/x module which provides some exports saying if the code is running in Deno or Node.

Node and Deno Specific Modules

Another option is to create node and deno specific modules. This can be done by specifying a mapping to a module:

await build({
  // ...etc...
  mappings: {
    "./file.deno.ts": "./file.node.ts",
  },
});

Then within the file, use // dnt-shim-ignore directives to disable shimming if you desire.

A mapped module should be written similar to how you write Deno code (ex. use extensions on imports), except you can also import built-in node modules such as import fs from "fs"; (just remember to include an @types/node dev dependency under the package.devDependencies object when calling the build function, if necessary).

Pre & Post Build Steps

Since the file you're calling is a script, simply add statements before and after the await build({ ... }) statement:

import { build, emptyDir } from "https://deno.land/x/dnt/mod.ts";

// run pre-build steps here
await emptyDir("./npm");

// build
await build({
  // ...etc..
});

// run post-build steps here
await Deno.copyFile("LICENSE", "npm/LICENSE");
await Deno.copyFile("README.md", "npm/README.md");

Including Test Data Files

Your Deno tests might rely on test data files. One way of handling this is to copy these files to be in the output directory at the same relative path your Deno tests run with.

For example:

import { copy } from "https://deno.land/std@x.x.x/fs/mod.ts";

await Deno.remove("npm", { recursive: true }).catch((_) => {});
await copy("testdata", "npm/esm/testdata", { overwrite: true });
await copy("testdata", "npm/script/testdata", { overwrite: true });

await build({
  // ...etc...
});

// ensure the test data is ignored in the `.npmignore` file
// so it doesn't get published with your npm package
await Deno.writeTextFile(
  "npm/.npmignore",
  "esm/testdata/\nscript/testdata/\n",
  { append: true },
);

Alternatively, you could also use the which_runtime module and use a different directory path when the tests are running in Node. This is probably more ideal if you have a lot of test data.

Test File Matching

By default, dnt uses the same search pattern that deno test uses to find test files. To override this, provide a testPattern and/or rootTestDir option:

await build({
  // ...etc...
  testPattern: "**/*.test.{ts,tsx,js,mjs,jsx}",
  // and/or provide a directory to start searching for test
  // files from, which defaults to the current working directory
  rootTestDir: "./tests",
});

deno.json Support

Starting in dnt 0.42, the deno.json is auto-discovered. A config file can be explicitly specified by the configFile key:

await build({
  // ...etc...
  configFile: import.meta.resolve("../deno.json"),
});

GitHub Actions - Npm Publish on Tag

  1. Ensure your build script accepts a version as a CLI argument and sets that in the package.json object. For example:

    await build({
      // ...etc...
      package: {
        version: Deno.args[0],
        // ...etc...
      },
    });
    

    Note: You may wish to remove the leading v in the tag name if it exists (ex. Deno.args[0]?.replace(/^v/, ""))

  2. In your npm settings, create an automation access token (see Creating and Viewing Access Tokens).

  3. In your GitHub repo or organization, add a secret for NPM_TOKEN with the value created in the previous step (see Creating Encrypted Secrets for a Repository).

  4. In your GitHub Actions workflow, get the tag name, setup node, run your build script, then publish to npm.

    # ...setup deno and run `deno test` here as you normally would...
    
    - name: Get tag version
      if: startsWith(github.ref, 'refs/tags/')
      id: get_tag_version
      run: echo TAG_VERSION=${GITHUB_REF/refs\/tags\//} >> $GITHUB_OUTPUT
    - uses: actions/setup-node@v3
      with:
        node-version: "18.x"
        registry-url: "https://registry.npmjs.org"
    - name: npm build
      run: deno run -A ./scripts/build_npm.ts ${{steps.get_tag_version.outputs.TAG_VERSION}}
    - name: npm publish
      if: startsWith(github.ref, 'refs/tags/')
      env:
        NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
      run: cd npm && npm publish
    

    Note that the build script always runs even when not publishing. This is to ensure your build and tests pass on each commit.

  5. Ensure the workflow will run on tag creation. For example, see Trigger GitHub Action Only on New Tags).

Using Another Package Manager

You may want to use another Node.js package manager instead of npm, such as Yarn or pnpm. To do this, override the packageManager option in the build options.

For example:

await build({
  // ...etc...
  packageManager: "yarn", // or "pnpm"
});

You can even specify an absolute path to the executable file of the package manager:

await build({
  // ...etc...
  packageManager: "/usr/bin/pnpm",
});

DOM Types

If you wish to compile with DOM types for type checking, you may specify a "dom" lib compiler option when building:

await build({
  // ...etc...
  compilerOptions: {
    lib: ["ES2021", "DOM"],
  },
});

Node v14 and Below

dnt should be able to target old versions of Node by specifying a { compilerOption: { target: ... }} value in the build options (see Node Target Mapping for what target maps to what Node version). A problem though is that certain shims might not work in old versions of Node.

If wanting to target a version of Node v14 and below, its recommend to use the Deno.test-only shim (described above) and then making use of the "mappings" feature to write Node-only files where you can handle differences. Alternatively, see if changes to the shim libraries might make it run on old versions of Node. Unfortunately, certain features are impossible or infeasible to get working.

See this thread in node_deno_shims for more details.

JS API Example

For only the Deno to canonical TypeScript transform which may be useful for bundlers, use the following:

// docs: https://doc.deno.land/https/deno.land/x/dnt/transform.ts
import { transform } from "https://deno.land/x/dnt/transform.ts";

const outputResult = await transform({
  entryPoints: ["./mod.ts"],
  testEntryPoints: ["./mod.test.ts"],
  shims: [],
  testShims: [],
  // mappings: {}, // optional specifier mappings
});

Rust API Example

use std::path::PathBuf;

use deno_node_transform::ModuleSpecifier;
use deno_node_transform::transform;
use deno_node_transform::TransformOptions;

let output_result = transform(TransformOptions {
  entry_points: vec![ModuleSpecifier::from_file_path(PathBuf::from("./mod.ts")).unwrap()],
  test_entry_points: vec![ModuleSpecifier::from_file_path(PathBuf::from("./mod.test.ts")).unwrap()],
  shims: vec![],
  test_shims: vec![],
  loader: None, // use the default loader
  specifier_mappings: None,
}).await?;