bun-types 1.1.39-canary.20241203T140606 → 1.1.39-canary.20241205T140550
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bun.d.ts +33 -15
- package/docs/runtime/plugins.md +98 -1
- package/ffi.d.ts +15 -10
- package/package.json +1 -1
package/bun.d.ts
CHANGED
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
* This module aliases `globalThis.Bun`.
|
|
15
15
|
*/
|
|
16
16
|
declare module "bun" {
|
|
17
|
+
import type { FFIFunctionCallableSymbol } from "bun:ffi";
|
|
17
18
|
import type { Encoding as CryptoEncoding } from "crypto";
|
|
18
19
|
import type {
|
|
19
20
|
CipherNameAndProtocol,
|
|
@@ -4043,7 +4044,11 @@ declare module "bun" {
|
|
|
4043
4044
|
defer: () => Promise<void>;
|
|
4044
4045
|
}
|
|
4045
4046
|
|
|
4046
|
-
type OnLoadResult =
|
|
4047
|
+
type OnLoadResult =
|
|
4048
|
+
| OnLoadResultSourceCode
|
|
4049
|
+
| OnLoadResultObject
|
|
4050
|
+
| undefined
|
|
4051
|
+
| void;
|
|
4047
4052
|
type OnLoadCallback = (
|
|
4048
4053
|
args: OnLoadArgs,
|
|
4049
4054
|
) => OnLoadResult | Promise<OnLoadResult>;
|
|
@@ -4099,7 +4104,34 @@ declare module "bun" {
|
|
|
4099
4104
|
| undefined
|
|
4100
4105
|
| null;
|
|
4101
4106
|
|
|
4107
|
+
type FFIFunctionCallable = Function & {
|
|
4108
|
+
// Making a nominally typed function so that the user must get it from dlopen
|
|
4109
|
+
readonly __ffi_function_callable: typeof FFIFunctionCallableSymbol;
|
|
4110
|
+
};
|
|
4111
|
+
|
|
4102
4112
|
interface PluginBuilder {
|
|
4113
|
+
/**
|
|
4114
|
+
* Register a callback which will be invoked when bundling starts.
|
|
4115
|
+
* @example
|
|
4116
|
+
* ```ts
|
|
4117
|
+
* Bun.plugin({
|
|
4118
|
+
* setup(builder) {
|
|
4119
|
+
* builder.onStart(() => {
|
|
4120
|
+
* console.log("bundle just started!!")
|
|
4121
|
+
* });
|
|
4122
|
+
* },
|
|
4123
|
+
* });
|
|
4124
|
+
* ```
|
|
4125
|
+
*/
|
|
4126
|
+
onStart(callback: OnStartCallback): void;
|
|
4127
|
+
onBeforeParse(
|
|
4128
|
+
constraints: PluginConstraints,
|
|
4129
|
+
callback: {
|
|
4130
|
+
napiModule: unknown;
|
|
4131
|
+
symbol: string;
|
|
4132
|
+
external?: unknown | undefined;
|
|
4133
|
+
},
|
|
4134
|
+
): void;
|
|
4103
4135
|
/**
|
|
4104
4136
|
* Register a callback to load imports with a specific import specifier
|
|
4105
4137
|
* @param constraints The constraints to apply the plugin to
|
|
@@ -4135,20 +4167,6 @@ declare module "bun" {
|
|
|
4135
4167
|
constraints: PluginConstraints,
|
|
4136
4168
|
callback: OnResolveCallback,
|
|
4137
4169
|
): void;
|
|
4138
|
-
/**
|
|
4139
|
-
* Register a callback which will be invoked when bundling starts.
|
|
4140
|
-
* @example
|
|
4141
|
-
* ```ts
|
|
4142
|
-
* Bun.plugin({
|
|
4143
|
-
* setup(builder) {
|
|
4144
|
-
* builder.onStart(() => {
|
|
4145
|
-
* console.log("bundle just started!!")
|
|
4146
|
-
* });
|
|
4147
|
-
* },
|
|
4148
|
-
* });
|
|
4149
|
-
* ```
|
|
4150
|
-
*/
|
|
4151
|
-
onStart(callback: OnStartCallback): void;
|
|
4152
4170
|
/**
|
|
4153
4171
|
* The config object passed to `Bun.build` as is. Can be mutated.
|
|
4154
4172
|
*/
|
package/docs/runtime/plugins.md
CHANGED
|
@@ -355,7 +355,7 @@ Bun.build({
|
|
|
355
355
|
|
|
356
356
|
{% /callout %}
|
|
357
357
|
|
|
358
|
-
## Lifecycle
|
|
358
|
+
## Lifecycle hooks
|
|
359
359
|
|
|
360
360
|
Plugins can register callbacks to be run at various points in the lifecycle of a bundle:
|
|
361
361
|
|
|
@@ -363,6 +363,8 @@ Plugins can register callbacks to be run at various points in the lifecycle of a
|
|
|
363
363
|
- [`onResolve()`](#onresolve): Run before a module is resolved
|
|
364
364
|
- [`onLoad()`](#onload): Run before a module is loaded.
|
|
365
365
|
|
|
366
|
+
### Reference
|
|
367
|
+
|
|
366
368
|
A rough overview of the types (please refer to Bun's `bun.d.ts` for the full type definitions):
|
|
367
369
|
|
|
368
370
|
```ts
|
|
@@ -603,3 +605,98 @@ plugin({
|
|
|
603
605
|
```
|
|
604
606
|
|
|
605
607
|
Note that the `.defer()` function currently has the limitation that it can only be called once per `onLoad` callback.
|
|
608
|
+
|
|
609
|
+
## Native plugins
|
|
610
|
+
|
|
611
|
+
{% callout %}
|
|
612
|
+
**NOTE** — This is an advanced and experiemental API recommended for plugin developers who are familiar with systems programming and the C ABI. Use with caution.
|
|
613
|
+
{% /callout %}
|
|
614
|
+
|
|
615
|
+
One of the reasons why Bun's bundler is so fast is that it is written in native code and leverages multi-threading to load and parse modules in parallel.
|
|
616
|
+
|
|
617
|
+
However, one limitation of plugins written in JavaScript is that JavaScript itself is single-threaded.
|
|
618
|
+
|
|
619
|
+
Native plugins are written as [NAPI](/docs/node-api) modules and can be run on multiple threads. This allows native plugins to run much faster than JavaScript plugins.
|
|
620
|
+
|
|
621
|
+
In addition, native plugins can skip unnecessary work such as the UTF-8 -> UTF-16 conversion needed to pass strings to JavaScript.
|
|
622
|
+
|
|
623
|
+
These are the following lifecycle hooks which are available to native plugins:
|
|
624
|
+
|
|
625
|
+
- [`onBeforeParse()`](#onbeforeparse): Called on any thread before a file is parsed by Bun's bundler.
|
|
626
|
+
|
|
627
|
+
### Creating a native plugin
|
|
628
|
+
|
|
629
|
+
Native plugins are NAPI modules which expose lifecycle hooks as C ABI functions.
|
|
630
|
+
|
|
631
|
+
To create a native plugin, you must export a C ABI function which matches the signature of the native lifecycle hook you want to implement.
|
|
632
|
+
|
|
633
|
+
#### Example: Rust with napi-rs
|
|
634
|
+
|
|
635
|
+
First initialize a napi project (see [here](https://napi.rs/docs/introduction/getting-started) for a more comprehensive guide).
|
|
636
|
+
|
|
637
|
+
Then install Bun's official safe plugin wrapper crate:
|
|
638
|
+
|
|
639
|
+
```bash
|
|
640
|
+
cargo add bun-native-plugin
|
|
641
|
+
```
|
|
642
|
+
|
|
643
|
+
Now you can export an `extern "C" fn` which is the implementation of your plugin:
|
|
644
|
+
|
|
645
|
+
```rust
|
|
646
|
+
#[no_mangle]
|
|
647
|
+
extern "C" fn on_before_parse_impl(
|
|
648
|
+
args: *const bun_native_plugin::sys::OnBeforeParseArguments,
|
|
649
|
+
result: *mut bun_native_plugin::sys::OnBeforeParseResult,
|
|
650
|
+
) {
|
|
651
|
+
let args = unsafe { &*args };
|
|
652
|
+
let result = unsafe { &mut *result };
|
|
653
|
+
|
|
654
|
+
let mut handle = match bun_native_plugin::OnBeforeParse::from_raw(args, result) {
|
|
655
|
+
Ok(handle) => handle,
|
|
656
|
+
Err(_) => {
|
|
657
|
+
return;
|
|
658
|
+
}
|
|
659
|
+
};
|
|
660
|
+
|
|
661
|
+
let source_code = match handle.input_source_code() {
|
|
662
|
+
Ok(source_code) => source_code,
|
|
663
|
+
Err(_) => {
|
|
664
|
+
handle.log_error("Fetching source code failed!");
|
|
665
|
+
return;
|
|
666
|
+
}
|
|
667
|
+
};
|
|
668
|
+
|
|
669
|
+
let loader = handle.output_loader();
|
|
670
|
+
handle.set_output_source_code(source_code.replace("foo", "bar"), loader);
|
|
671
|
+
```
|
|
672
|
+
|
|
673
|
+
Use napi-rs to compile the plugin to a `.node` file, then you can `require()` it from JS and use it:
|
|
674
|
+
|
|
675
|
+
```js
|
|
676
|
+
await Bun.build({
|
|
677
|
+
entrypoints: ["index.ts"],
|
|
678
|
+
setup(build) {
|
|
679
|
+
const myNativePlugin = require("./path/to/plugin.node");
|
|
680
|
+
|
|
681
|
+
build.onBeforeParse(
|
|
682
|
+
{ filter: /\.ts/ },
|
|
683
|
+
{ napiModule: myNativePlugin, symbol: "on_before_parse_impl" },
|
|
684
|
+
);
|
|
685
|
+
},
|
|
686
|
+
});
|
|
687
|
+
```
|
|
688
|
+
|
|
689
|
+
### `onBeforeParse`
|
|
690
|
+
|
|
691
|
+
```ts
|
|
692
|
+
onBeforeParse(
|
|
693
|
+
args: { filter: RegExp; namespace?: string },
|
|
694
|
+
callback: { napiModule: NapiModule; symbol: string; external?: unknown },
|
|
695
|
+
): void;
|
|
696
|
+
```
|
|
697
|
+
|
|
698
|
+
This lifecycle callback is run immediately before a file is parsed by Bun's bundler.
|
|
699
|
+
|
|
700
|
+
As input, it receives the file's contents and can optionally return new source code.
|
|
701
|
+
|
|
702
|
+
This callback can be called from any thread and so the napi module implementation must be thread-safe.
|
package/ffi.d.ts
CHANGED
|
@@ -570,17 +570,22 @@ declare module "bun:ffi" {
|
|
|
570
570
|
? FFITypeStringToType[T]
|
|
571
571
|
: never;
|
|
572
572
|
|
|
573
|
+
const FFIFunctionCallableSymbol: unique symbol;
|
|
573
574
|
type ConvertFns<Fns extends Symbols> = {
|
|
574
|
-
[K in keyof Fns]:
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
[
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
:
|
|
575
|
+
[K in keyof Fns]: {
|
|
576
|
+
(
|
|
577
|
+
...args: Fns[K]["args"] extends infer A extends
|
|
578
|
+
readonly FFITypeOrString[]
|
|
579
|
+
? { [L in keyof A]: FFITypeToArgsType[ToFFIType<A[L]>] }
|
|
580
|
+
: // eslint-disable-next-line @definitelytyped/no-single-element-tuple-type
|
|
581
|
+
[unknown] extends [Fns[K]["args"]]
|
|
582
|
+
? []
|
|
583
|
+
: never
|
|
584
|
+
): [unknown] extends [Fns[K]["returns"]] // eslint-disable-next-line @definitelytyped/no-single-element-tuple-type
|
|
585
|
+
? undefined
|
|
586
|
+
: FFITypeToReturnsType[ToFFIType<NonNullable<Fns[K]["returns"]>>];
|
|
587
|
+
__ffi_function_callable: typeof FFIFunctionCallableSymbol;
|
|
588
|
+
};
|
|
584
589
|
};
|
|
585
590
|
|
|
586
591
|
/**
|
package/package.json
CHANGED