Writing your first extension
1. Workspace Setup
In your workspace root, create or update MODULE.bazel to depend on extensions_sdk:
module(
name = "my_extensions",
version = "1.0.0",
)
bazel_dep(name = "extensions_sdk", version = "1.0.0")
2. Generating Boilerplate
The easiest way to get started is by using the built-in scaffolding tool. This generates both the Bazel BUILD file and the starter code for your extension:
{{#tabs }} {{#tab name="Rust" }}
bazel run @extensions_sdk//tools:scaffold -- --lang rust --name my_rust_ext
{{#endtab }} {{#tab name="Golang" }}
bazel run @extensions_sdk//tools:scaffold -- --lang go --name my_go_ext
{{#endtab }} {{#tab name="Python" }}
bazel run @extensions_sdk//tools:scaffold -- --lang python --name my_py_ext
{{#endtab }} {{#tab name="Javascript" }}
bazel run @extensions_sdk//tools:scaffold -- --lang js --name my_js_ext
{{#endtab }} {{#endtabs }}
3. Extension Rules & Implementation
{{#tabs }} {{#tab name="Rust" }}
Generated BUILD Rule
The scaffolding tool generates a BUILD file using rust_extension:
load("@extensions_sdk//:defs.bzl", "rust_extension")
package(default_visibility = ["//visibility:public"])
rust_extension(
name = "rust_sample",
srcs = ["src/lib.rs"],
package_name = "moosync.sample.rust",
display_name = "Sample Extension (Rust)",
version = "0.0.1",
)
Implementation
Extensions are represented by the Extension trait. You need to register your extension through the init function:
#![allow(unused)] fn main() { struct SampleExtension; impl Extension for SampleExtension {} impl Accounts for SampleExtension {} impl DatabaseEvents for SampleExtension {} impl PlayerEvents for SampleExtension {} impl PreferenceEvents for SampleExtension {} impl ContextMenu for SampleExtension {} #[unsafe(no_mangle)] pub extern "C" fn init() { info!("Initializing SampleExtension"); register_extension(Box::new(SampleExtension)).unwrap(); info!("Initialized SampleExtension"); } }
Build
bazel build //my_rust_ext:my_rust_ext
{{#endtab }} {{#tab name="Golang" }}
Generated BUILD Rule
The scaffolding tool generates a BUILD file using go_extension:
load("@extensions_sdk//:defs.bzl", "go_extension")
package(default_visibility = ["//visibility:public"])
go_extension(
name = "go_sample",
srcs = ["main.go"],
package_name = "moosync.sample.go",
display_name = "Sample Extension (Go)",
version = "0.0.1",
)
Implementation
Extensions are represented by embedding api.DefaultExtension. You need to register your extension through the entry function:
type SampleExtension struct {
api.DefaultExtension
}
//go:wasmexport entry
func entry() {
extension := &SampleExtension{}
api.RegisterExtension(extension)
}
func main() {}
Build
bazel build //my_go_ext:my_go_ext
{{#endtab }} {{#tab name="Python" }}
Generated BUILD Rule
The scaffolding tool generates a BUILD file using py_extension:
load("@extensions_sdk//:defs.bzl", "py_extension")
package(default_visibility = ["//visibility:public"])
py_extension(
name = "py_sample",
srcs = ["main.py"],
main = "main.py",
package_name = "moosync.sample.python",
display_name = "Sample Extension (Python)",
version = "0.0.1",
)
Implementation
All extensions must start in a module called main. Extensions are represented by the Extension class. You need to register your extension through the entry function:
class SampleExtension(Extension):
def __init__(self):
super().__init__()
def entry():
print("Initializing SampleExtension")
register_extension(SampleExtension())
Build
bazel build //my_py_ext:my_py_ext
{{#endtab }} {{#tab name="Javascript" }}
Generated BUILD Rule
The scaffolding tool generates a BUILD file using js_extension:
load("@extensions_sdk//:defs.bzl", "js_extension")
package(default_visibility = ["//visibility:public"])
js_extension(
name = "js_sample",
srcs = ["src/index.ts"],
package_name = "moosync.sample.js",
display_name = "Sample Extension (JavaScript)",
version = "0.0.1",
)
Implementation
You need to re-export all methods provided by wasm-extension-js package. The entrypoint of your extension is a function called entry:
export function entry(): number {
const api = getApi();
console.log("Initialized sample extension");
return 0;
}
Build
bazel build //my_js_ext:my_js_ext
{{#endtab }} {{#endtabs }}