Instead of parsing and statically looking for module exports in the compile step, this evaluates the code to find the exports. Thus we can support bundled JS code.
How to use
In order to get this to work, you just need a working bundler and you need to output in CJS format, not ESM format. I've tested in esbuild but webpack and other should work. You should be able to write your plugin in typescript too, i haven't tested though!
Here is an example of a js project from scratch with esbuild:
# Make a new JS project
mkdir extism-plugin
cd extism-plugin
npm init -y
npm install --save-dev
Add esbuild.js:
const esbuild = require('esbuild');
esbuild
.build({
entryPoints: ['src/index.js'],
outdir: 'dist',
bundle: true,
sourcemap: true,
minify: false,
format: 'cjs', // needs to be CJS for now
target: ['es2020'] // don't go over es2020 because quickjs doesn't support it
})
Now make some code in src/index.js. You can use import to load node_modules:
import {distance, closest} from 'fastest-levenshtein'
// this function is private to the module
function privateFunc() { return 'world' }
// use any export syntax to export a function be callable by the extism host
export function get_closest() {
let input = Host.inputString()
let result = closest(input, ['slow', 'faster', 'fastest'])
Host.outputString(result + ' ' + privateFunc())
return 0
}
# Run the build script and the plugin will be compiled to dist/plugin.wasm
npm run build
# You can now call from the extism cli or a host SDK
extism call dist/plugin.wasm get_closest --input="fest" --wasi
faster World
Next Steps
I need to go back and possibly refactor the core after this. Right now it seems to still work but I'm concerned the global functions will get their names mangled. So instead core should look inside module.exports and find the function reference there rather than expecting the global name to be preserved.
Instead of parsing and statically looking for module exports in the compile step, this evaluates the code to find the exports. Thus we can support bundled JS code.
How to use
In order to get this to work, you just need a working bundler and you need to output in CJS format, not ESM format. I've tested in esbuild but webpack and other should work. You should be able to write your plugin in typescript too, i haven't tested though!
Here is an example of a js project from scratch with esbuild:
Add
esbuild.js
:make some directories
Add a
build
script to yourpackage.json
:Let's import a module from NPM:
Now make some code in
src/index.js
. You can useimport
to load node_modules:Next Steps
I need to go back and possibly refactor the core after this. Right now it seems to still work but I'm concerned the global functions will get their names mangled. So instead core should look inside module.exports and find the function reference there rather than expecting the global name to be preserved.