Load module from string using
require
orimport
.
npm install module-from-string
import {
requireFromString,
importFromString,
importFromStringSync
} from 'module-from-string'
requireFromString("module.exports = 'hi'") // => 'hi'
requireFromString("exports.greet = 'hi'") // => { greet: 'hi' }
;(async () => {
await importFromString("export default 'hi'") // => { default: 'hi' }
})()
importFromStringSync(
"export const greet = Buffer.from([0x68, 0x69]).toString('utf8')",
{ globals: { Buffer } }
) // => { greet: 'hi' }
import { Context } from 'vm';
import { TransformOptions } from 'esbuild';
interface Options {
filename?: string
dirname?: string
globals?: Context
useCurrentGlobal?: boolean
}
declare const requireFromString: (code: string, options?: Options) => any
declare const createRequireFromString: (options?: Options) => typeof requireFromString
interface ImportOptions extends Options {
transformOptions?: TransformOptions
}
declare const importFromString: (code: string, options?: ImportOptions) => Promise<any>
declare const createImportFromString: (options?: ImportOptions) => typeof importFromString
declare const importFromStringSync: (code: string, options?: ImportOptions) => any
declare const createImportFromStringSync: (options?: ImportOptions) => typeof importFromStringSync
Name, path or URL string of the virtual file for better exception stack trace.
requireFromString(
"throw new Error('boom!')",
{ filename: '/home/foo.js' }
)
// /home/foo.js:1
// throw new Error('boom!')
// ^
//
// Error: boom!
// at /home/foo.js:1:7
// at ...
Path or URL string of the directory for resolving require
or import
from relative path.
requireFromString(
"module.exports = require('.')",
{ dirname: path.join(__dirname, "../lib") }
) // => require('../lib')
If not specified, the default value will be the current file's directory.
Underneath the hood, module-from-string
uses Node.js built-in vm
module to execute code.
// requireFromString
vm.runInNewContext(
code,
{
__dirname: contextModule.path,
__filename: contextModule.filename,
exports: contextModule.exports,
module: contextModule,
require: contextModule.require,
...globals
},
Take requireFromString
for example, only the module scope variables are passed into the contextObject
.
In order to use other global objects that are specific to Node.js, they need to be added to option globals
or set option useCurrentGlobal
to true
.
requireFromString(
'module.exports = process.cwd()',
{ globals: { process } }
) // => $PWD
Note: by default the built-in objects have a different prototype.
const error = requireFromString('module.exports = new Error()')
error instanceof Error // => false
Default to false
. If set to true
, all the available variables from the current global
(or globalThis
) are passed into the context.
Function importFromString
and importFromStringSync
can use esbuild
to transform code syntax. See esbuild Transform API for documentation.
const { greet } = importFromStringSync(
"export const greet: () => string = () => 'hi'",
{ transformOptions: { loader: 'ts' } }
)
greet() // => 'hi'
Dynamic import()
expression of ES modules is supported by all three functions requireFromString
, importFromString
and importFromStringSync
.
;(async () => {
await requireFromString("module.exports = import('./index.mjs')")
})()
import
statement of ES modules is supported only by asynchronous function importFromString
using Node.js experimental API vm.Module
.
node --experimental-vm-modules index.js
# Or use environment variable
NODE_OPTIONS=--experimental-vm-modules node index.js
// with top-level await
await importFromString("export { foo as default } from './index.mjs'")
MIT License © 2021 Exuanbo