You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
@kriszyp for tons of helpful feedback on how to improve Node-API support in bun
@adaptive for replacing "wrangler@beta" with "wrangler" in the examples for bun add
@littledivy for adding a couple missing packages to the build instructions
bun:sqlite
bun:sqlite is a high-performance builtin SQLite module for bun.js.
It tends to be around 3x faster than the popular better-sqlite3 npm package
Note: in the benchmark I tweeted earlier, better-sqlite3 was returning arrays of values rather than arrays of objects, which was inconsistent with what bun:sqlite & deno's x/sqlite were doing
Usage
import{Database}from"bun:sqlite";constdb=newDatabase("mydb.sqlite");db.run("CREATE TABLE IF NOT EXISTS foo (id INTEGER PRIMARY KEY AUTOINCREMENT, greeting TEXT)");db.run("INSERT INTO foo (greeting) VALUES (?)","Welcome to bun!");db.run("INSERT INTO foo (greeting) VALUES (?)","Hello World!");// get the first rowdb.query("SELECT * FROM foo").get();// { id: 1, greeting: "Welcome to bun!" }// get all rowsdb.query("SELECT * FROM foo").all();// [// { id: 1, greeting: "Welcome to bun!" },// { id: 2, greeting: "Hello World!" },// ]// get all rows matching a conditiondb.query("SELECT * FROM foo WHERE greeting = ?").all("Welcome to bun!");// [// { id: 1, greeting: "Welcome to bun!" },// ]// get first row matching a named conditiondb.query("SELECT * FROM foo WHERE greeting = $greeting").get({$greeting: "Welcome to bun!",});// [// { id: 1, greeting: "Welcome to bun!" },// ]
CFunction lets you call native library functions from a function pointer.
It works like dlopen but its for cases where you already have the function pointer so you don't need to open a library. This is useful for:
callbacks passed from native libraries to JavaScript
using Node-API and bun:ffi together
import{CFunction}from'bun:ffi';constmyNativeLibraryGetVersion: number|bigint=/* Somehow you got this function pointer */constgetVersion=newCFunction({returns: "cstring",args: [],// ptr is required// this is where the function pointer goes!ptr: myNativeLibraryGetVersion,});getVersion();getVersion.close();
linkSymbols is like CFunction except for when there are multiple functions. It returns the same object as dlopen except ptr is required and there is no path
import{linkSymbols}from"bun:ffi";const[majorPtr,minorPtr,patchPtr]=getVersionPtrs();constlib=linkSymbols({// Unlike with dlopen(), the names here can be whatever you wantgetMajor: {returns: "cstring",args: [],// Since this doesn't use dlsym(), you have to provide a valid ptr// That ptr could be a number or a bigint// An invalid pointer will crash your program.ptr: majorPtr,},getMinor: {returns: "cstring",args: [],ptr: minorPtr,},getPatch: {returns: "cstring",args: [],ptr: patchPtr,},});const[major,minor,patch]=[lib.symbols.getMajor(),lib.symbols.getMinor(),lib.symbols.getPatch(),];
new CString(ptr) should be a little faster due to using a more optimized function for getting the length of a string.
require.resolve()
Running require.resolve("my-module") in Bun.js will now resolve the path to the module. Previously, this was not supported.
In browsers, it becomes the absolute filepath at build-time. In node, it's left in without any changes.
Internally, Bun's JavaScript transpiler transforms it to:
You can see this for yourself by running bun build ./file.js --platform=bun
"node:module" module polyfill
Node's "module" module lets you create require functions from ESM modules.
Bun now has a polyfill that implements a subset of the "module" module.
Normally require() in bun transforms statically at build-time to an ESM import statement. That doesn't work as well for Node-API (napi) modules because they cannot be statically analyzed by a JavaScript parser (since they're not JavaScript).
For napi modules, bun uses a dynamic require function and the "module" module exports a way to create those using the same interface as in Node.js
import{createRequire}from"module";// this also works://import {createRequire} from 'node:module';varrequire=createRequire(import.meta.url);require.resolve("my-module");// dynamic require is supported for:// - .json files// - .node files (napi modules)require("my-napi-module");
This is mostly intended for improving Node-API compatibility with modules loaded from ESM.
As an extra thing, you can also use require() this way for .json files.
Bun.Transpiler – pass objects to macros
Bun.Transpiler now supports passing objects to macros.
import{Transpiler}from"bun";import{parseCookie}from"my-cookie-lib";import{Database}from"bun:sqlite";consttranspiler=newTranspiler();constdb=newDatabase("mydb.sqlite");exportdefault{fetch(req){consttranspiled=transpiler.transformSync(`import {getUser} from 'macro:./get-user';export function Hello({name}) { return <div>Hello {name}</div>;}export const HelloCurrentUser = <Hello {...getUser()} />;`,// passing contextual data to Bun.Transpiler{userId: parseCookie(req.headers.get("Cookie")).userId,db: db,});},};
Then, in get-user.js:
// db, userId is now accessible in macrosexportfunctiongetUser(expr,{ db, userId }){// we can use it to query the database while transpilingreturndb.query("SELECT * FROM users WHERE id = ? LIMIT 1").get(userId);}
That inlines the returned current user into the JavaScript source code, producing output equivalent to this:
exportfunctionHello({ name }){return<div>Hello {name}</div>;}// notice that the current user is inlined rather than a function callexportconstHelloCurrentUser=<Helloname="Jarred"/>;
Bug fixes
Buffer.from(arrayBuffer, byteOffset, length) now works as expected (thanks to @kriszyp for reporting)
Misc
Receiving and sending strings to Node-API modules should be a little faster
This discussion was created from the release bun v0.0.83.
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
-
To upgrade:
Having trouble upgrading?
You can also try the install script.
curl https://bun.sh/install | bash
Thanks to:
"wrangler@beta"
with"wrangler"
in the examples forbun add
bun:sqlite
bun:sqlite
is a high-performance builtin SQLite module for bun.js.It tends to be around 3x faster than the popular
better-sqlite3
npm packageNote: in the benchmark I tweeted earlier,
better-sqlite3
was returning arrays of values rather than arrays of objects, which was inconsistent with whatbun:sqlite
& deno's x/sqlite were doingUsage
There are more detailed docs in Bun's README
bun:sqlite
's API is loosely based on @joshuawise's better-sqlite3New in
bun:ffi
CFunction
lets you call native library functions from a function pointer.It works like
dlopen
but its for cases where you already have the function pointer so you don't need to open a library. This is useful for:linkSymbols
is likeCFunction
except for when there are multiple functions. It returns the same object asdlopen
exceptptr
is required and there is no pathnew CString(ptr)
should be a little faster due to using a more optimized function for getting the length of a string.require.resolve()
Running
require.resolve("my-module")
in Bun.js will now resolve the path to the module. Previously, this was not supported.In browsers, it becomes the absolute filepath at build-time. In node, it's left in without any changes.
Internally, Bun's JavaScript transpiler transforms it to:
You can see this for yourself by running
bun build ./file.js --platform=bun
"node:module"
module polyfillNode's
"module"
module lets you create require functions from ESM modules.Bun now has a polyfill that implements a subset of the
"module"
module.Normally
require()
in bun transforms statically at build-time to an ESMimport
statement. That doesn't work as well for Node-API (napi) modules because they cannot be statically analyzed by a JavaScript parser (since they're not JavaScript).For napi modules, bun uses a dynamic require function and the
"module"
module exports a way to create those using the same interface as in Node.jsThis is mostly intended for improving Node-API compatibility with modules loaded from ESM.
As an extra thing, you can also use
require()
this way for .json files.Bun.Transpiler – pass objects to macros
Bun.Transpiler
now supports passing objects to macros.Then, in
get-user.js
:That inlines the returned current user into the JavaScript source code, producing output equivalent to this:
Bug fixes
Buffer.from(arrayBuffer, byteOffset, length)
now works as expected (thanks to @kriszyp for reporting)Misc
This discussion was created from the release bun v0.0.83.
Beta Was this translation helpful? Give feedback.
All reactions