https://github.com/remcohaszing/estree-util-module-to-function
Convert an estree module into a function body
https://github.com/remcohaszing/estree-util-module-to-function
esast esm estree
Last synced: 2 months ago
JSON representation
Convert an estree module into a function body
- Host: GitHub
- URL: https://github.com/remcohaszing/estree-util-module-to-function
- Owner: remcohaszing
- License: mit
- Created: 2022-06-24T11:59:47.000Z (over 3 years ago)
- Default Branch: main
- Last Pushed: 2025-04-13T14:23:01.000Z (6 months ago)
- Last Synced: 2025-05-28T20:48:51.646Z (4 months ago)
- Topics: esast, esm, estree
- Language: JavaScript
- Homepage:
- Size: 698 KB
- Stars: 3
- Watchers: 2
- Forks: 0
- Open Issues: 2
-
Metadata Files:
- Readme: README.md
- License: LICENSE.md
Awesome Lists containing this project
README
# estree-util-module-to-function
[](https://github.com/remcohaszing/estree-util-module-to-function/actions/workflows/ci.yaml)
[](https://codecov.io/gh/remcohaszing/estree-util-module-to-function)
[](https://www.npmjs.com/package/estree-util-module-to-function)
[](https://www.npmjs.com/package/estree-util-module-to-function)Convert an estree module into a function body.
## Table of Contents
- [Installation](#installation)
- [Usage](#usage)
- [API](#api)
- [`moduleToFunction(ast, options?)`](#moduletofunctionast-options)
- [Examples](#examples)
- [Security](#security)
- [Compatibility](#compatibility)
- [License](#license)## Installation
```sh
npm install estree-util-module-to-function
```## Usage
Typically you’ll get an AST from [`acorn`](https://github.com/acornjs/acorn), then process it.
```typescript
import { parse } from 'acorn'
import { moduleToFunction } from 'estree-util-module-to-function'const ast = parse(source, { ecmaVersion: 'latest', sourceType: 'module' })
moduleToFunction(ast)console.dir(ast)
```## API
This module exports a single function named `moduleToFunction`.
### `moduleToFunction(ast, options?)`
Convert an estree module into a function body. This modifies the input AST.
#### Options
- `importName`: A custom name for the import. By default, `import()` expressions are used. If this
option is given, import expressions and import meta properties are transformed into identifiers
using this name. (type: `string`)## Examples
The following example shows how to read the home directory in Node.js by using ESM code from a
string.```typescript
import { parse } from 'acorn'
import { generate } from 'astring'
import { moduleToFunction } from 'estree-util-module-to-function'const AsyncFunction = (async () => {
// This function is only defined to access the AsyncFunction constructor.
}).constructorconst source = `
import { readdir } from 'node:fs/promises'
import { homedir } from 'node:os'const home = homedir()
export default home
export const files = await readdir(homedir())
`const ast = parse(source, { ecmaVersion: 'latest', sourceType: 'module' })
moduleToFunction(ast)
const transformed = generate(ast)
const fn = new AsyncFunction(transformed)const result = await fn()
console.dir(result)
```The following example is derived from the above. It injects a custom import function, which stubs
actual import behaviour.```typescript
import { parse } from 'acorn'
import { generate } from 'astring'
import { moduleToFunction } from 'estree-util-module-to-function'const customImport: Import = async (name) => {
switch (name) {
case 'node:fs/promises':
case 'fs/promises':
return {
async readdir() {
return [
'.cache',
'.config',
'.local',
'Documents',
'Downloads',
'Music',
'Pictures',
'Public',
'Templates',
'Videos'
]
}
}
case 'node:os':
case 'os':
return {
homedir() {
return '/home/fakeuser'
}
}
default:
throw new Error(`Cannot find package '${name}'`)
}
}// Optionally define import meta
costumImport.meta = {
dirname: '/stub/dir',
filename: '/stub/dir/path.js',
url: 'file:///stub/dir/path.js',
resolve(specifier) {
return specifier
}
}const AsyncFunction = customImport.constructor
const source = `
import { readdir } from 'node:fs/promises'
import { homedir } from 'node:os'const home = homedir()
export default home
export const files = await readdir(homedir())
`const importName = '__import__'
const ast = parse(source, { ecmaVersion: 'latest', sourceType: 'module' })
moduleToFunction(ast, { importName })
const transformed = generate(ast)
const fn = new AsyncFunction(importName, transformed)const result = await fn(customImport)
console.dir(result)
```## Security
This package only transforms the AST input, which is safe to use on its own. However, it was created
with the use case in mind to evaluate an ECMASscript module. Evaluating user input is dangerous and
should be avoided whenever possible.## Compatibility
This project is compatible with Node.js 20 or greater.
## License
[MIT](LICENSE.md) © [Remco Haszing](https://github.com/remcohaszing)