Skip to content

knightedcodemonkey/module

Repository files navigation

CI codecov NPM version

Node.js utility for transforming a JavaScript or TypeScript file from an ES module to CommonJS, or vice versa.

  • ES module ➡️ CommonJS
  • CommonJS ➡️ ES module

Important

All parsing logic is applied under the assumption the code is in strict mode which modules run under by default.

By default @knighted/module transforms the one-to-one differences between ES modules and CommonJS. Options let you control syntax rewriting, specifier updates, and output.

Requirements

  • Node >= 20.11.0

Example

Given an ES module

file.js

import { argv } from 'node:process'
import { pathToFileURL } from 'node:url'
import { realpath } from 'node:fs/promises'

const detectCalledFromCli = async path => {
  const realPath = await realpath(path)

  if (import.meta.url === pathToFileURL(realPath).href) {
    console.log('invoked directly by node')
  }
}

detectCalledFromCli(argv[1])

You can transform it to the equivalent CommonJS module

import { transform } from '@knighted/module'

await transform('./file.js', {
  target: 'commonjs',
  out: './file.cjs',
})

Which produces

file.cjs

const { argv } = require('node:process')
const { pathToFileURL } = require('node:url')
const { realpath } = require('node:fs/promises')

const detectCalledFromCli = async path => {
  const realPath = await realpath(path)

  if (
    require('node:url').pathToFileURL(__filename).toString() ===
    pathToFileURL(realPath).href
  ) {
    console.log('invoked directly by node')
  }
}

detectCalledFromCli(argv[1])

When executed from the CLI

use@computer: $ node file.cjs
invoked directly by node

Options

type ModuleOptions = {
  target: 'module' | 'commonjs'
  sourceType?: 'auto' | 'module' | 'commonjs'
  transformSyntax?: boolean
  liveBindings?: 'strict' | 'loose' | 'off'
  rewriteSpecifier?:
    | '.js'
    | '.mjs'
    | '.cjs'
    | '.ts'
    | '.mts'
    | '.cts'
    | ((value: string) => string | null | undefined)
  dirFilename?: 'inject' | 'preserve' | 'error'
  importMeta?: 'preserve' | 'shim' | 'error'
  requireSource?: 'builtin' | 'create-require'
  cjsDefault?: 'module-exports' | 'auto' | 'none'
  topLevelAwait?: 'error' | 'wrap' | 'preserve'
  out?: string
  inPlace?: boolean
}

Roadmap

  • Remove @knighted/specifier and avoid double parsing.
  • Flesh out live-binding and top-level await handling.

About

Transforms Node.js files from ES module to CommonJS, or vice versa.

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 2

  •  
  •