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.
- Node >= 20.11.0
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 nodetype 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
}- Remove
@knighted/specifierand avoid double parsing. - Flesh out live-binding and top-level await handling.