TypeScript SDK
npm package:
npm install lapis-lazuli
The SDK is the public TypeScript authoring surface for Lapis Lazuli. It is service-first and TypeScript-first; it does not attempt to mirror Bukkit or Paper class-for-class.
Minimal Example
import { definePlugin } from "lapis-lazuli";
export default definePlugin({
name: "Example Plugin",
onEnable(context) {
context.app.log.info("Enabled.");
context.commands.register({
name: "hello",
execute({ sender }) {
sender.sendMessage("Hello from Lapis.");
},
});
},
});
PluginContext
interface PluginContext {
app: AppService;
commands: CommandRegistry;
events: EventRegistry;
tasks: TaskRegistry;
players: PlayerDirectory;
worlds: WorldDirectory;
entities: EntityDirectory;
items: ItemFactory;
inventory: InventoryDirectory;
chat: ChatService;
http: HttpService;
storage: StorageService;
config: KeyValueStore;
unsafe: UnsafeBridge;
}
Main Design Rules
- Common plugin work should not require Java knowledge.
- Service modules should stay small and discoverable.
- Values passed across the API should prefer plain DTOs such as
Location,TextInput, and item specs. - Raw backend access belongs under
unsafe.
Event Model
The SDK ships typed Lapis event names instead of raw Java event class names. Examples:
server.readyplayer.joinplayer.chatblock.breakentity.damageinventory.click
For backend-specific or not-yet-modeled events, use context.unsafe.events.onJava(...).
Handle Model
The SDK uses focused handles such as:
PlayerHandleWorldHandleEntityHandleBlockHandleInventoryHandleItemHandle
These provide a curated subset of common operations. They are not intended to be direct wrappers around the full Java object model.
HTTP
TypeScript plugins can make HTTP requests through context.http.fetch(...).
const response = await context.http.fetch("https://example.com/api", {
method: "POST",
headers: {
"content-type": "application/json",
},
body: JSON.stringify({ hello: "lapis" }),
});
context.app.log.info(`status=${response.status}`);
context.app.log.info(response.body);
Escape Hatch
The SDK still supports advanced backend access through:
context.unsafe.java.type(...)context.unsafe.backend.*
Treat those as secondary APIs, not the primary authoring path.
When a bundle uses engine: "node", only context.unsafe.backend.dispatchCommand(...)
is available. Raw Java access and backend handles remain limited to the embedded
js runtime.
For the exact exported types, read sdks/typescript/src/index.ts.