A comprehensive toolkit for building type-safe browser extensions with robust messaging patterns.
- π Type-safe messaging system
- πΎ Storage management system
- π Background script proxy pattern
- π― Runtime validation
- π¦ Modular handler system
- π Built with Bun + Vite + TypeScript
bun add browser-extension-toolkit webextension-polyfill
# or
npm install browser-extension-toolkit webextension-polyfill
src/
βββ lib/
β βββ messaging/
β β βββ types.ts # Core type definitions
β β βββ interfaces.ts # Operation interfaces
β β βββ constants.ts # Message type constants
β β βββ messenger.ts # MessagingProxy class
β βββ storage/ # Storage system
β β βββ types.ts # Storage type definitions
β β βββ storage.ts # ExtensionStorage class
β β βββ decorators.ts # Storage decorators
β βββ proxy/
β β βββ handlers/
β β β βββ index.ts # Handler exports
β β β βββ tabs.ts # Tab operations
β βββ utils/
β βββ testing.ts # Test utilities
βββ tests/
β βββ setup.ts # Test configuration
β βββ messenger.test.ts # Core tests
β βββ handlers.test.ts # Handler tests
βββ examples/
βββ popup/
β βββ messaging.ts # Popup usage example
βββ background/
βββ setup.ts # Background setup example
import type { MessageTypes } from "browser-extension-toolkit";
import { MESSAGE_TYPES, MessagingProxy } from "browser-extension-toolkit";
const backgroundProxy = new MessagingProxy<MessageTypes>("popup");
// Open a new tab
const response = await proxy.sendProxyMessage(MESSAGE_TYPES.TAB.OPEN, {
url: "https://example.com",
});
import type { MessageTypes } from "browser-extension-toolkit";
import {
MESSAGE_TYPES,
MessagingProxy,
tabProxyHandlers,
} from "browser-extension-toolkit";
const backgroundProxy = new MessagingProxy<MessageTypes>("background");
// Register handlers
backgroundProxy.registerProxyHandler(
MESSAGE_TYPES.TAB.OPEN,
tabProxyHandlers.openTab,
);
The toolkit includes pre-built handlers for common operations:
// Tab operations
tabProxyHandlers.openTab;
tabProxyHandlers.closeTab;
tabProxyHandlers.updateTab;
// Extension page operations
extensionProxyHandlers.openOptionsPage;
extensionProxyHandlers.openPopup;
Create your own handlers with full type safety:
import type { MessageHandler } from "browser-extension-toolkit";
const customHandler: MessageHandler<InputType, OutputType> = async (
data,
source,
sender,
) => {
// Implementation
return result;
};
// Define your storage schema
interface UserPreferences {
theme: "light" | "dark";
fontSize: number;
notifications: boolean;
}
// Using ExtensionStorage class
const storage = new ExtensionStorage<UserPreferences>({
area: "sync",
prefix: "prefs",
});
// Set multiple values in storage at once
await storage.bulkSet({ theme: "light", fontSize: 12, notifications: true });
// Set multiple values and remove others atomically
await store.bulkUpdate({
set: {
theme: "dark",
fontSize: 16,
},
remove: ["notifications"],
});
// Set and get values with type safety
await storage.set("theme", "dark");
const theme = await storage.get("theme");
// Listen for changes
storage.addChangeListener((changes) => {
if ("theme" in changes) {
console.log("Theme changed:", changes.theme.newValue);
}
});
// Using decorators
class Settings {
@persist({ area: "sync", prefix: "settings" })
public theme!: "light" | "dark";
@persist({ area: "local", prefix: "settings" })
public fontSize!: number;
}
// Namespace isolation
const userStorage = new ExtensionStorage<UserData>({ prefix: "user" });
const settingsStorage = new ExtensionStorage<Settings>({ prefix: "settings" });
// Batch operations
const allSettings = await settingsStorage.getAll();
// Area-specific storage
const syncStorage = new ExtensionStorage<SyncData>({ area: "sync" });
const localStorage = new ExtensionStorage<LocalData>({ area: "local" });
// With serialization control
const rawStorage = new ExtensionStorage<RawData>({
serialize: false,
});
// Change detection
storage.addChangeListener(async (changes, area) => {
for (const [key, { oldValue, newValue }] of Object.entries(changes)) {
console.log(`${key} changed in ${area}:`, { oldValue, newValue });
}
});
See CONTRIBUTING.md for development setup and guidelines.
MIT License. See LICENSE for details.