Type safe web extension api (partial)
Warning
Still working in progress, do not use in production
Based on browser.runtime.sendMessage
To Start using this, you need to extend the MessageProtocol
interface
import 'typed-webext'
declare module "typed-webext" {
interface MessageProtocol<T = unknown> {
"get-time": [never, number]
}
}
sendMessage("get-time")
.then((time) => {
console.log(time)
// ^ time: number
})
.catch(error => {
console.error(error)
})
// background.ts
onMessage("get-time", () => {
const now = new Date()
if (now.getFullYear() > 1999) {
throw new Error("You are late!")
} else {
return +now
}
})
Based on browser.runtime.connect
import 'typed-webext'
declare module "typed-webext" {
interface StreamProtocol {
chat: [
// Stream sender data type
{ text: string, model: "gpt-4" },
// Stream reciver return data type
{ text: string } | { error: ErrorObject } | { done: true }
]
}
}
import { deserializeError } from 'serialize-error'
const stream = openStream("chat")
// 1. use async iterator
for await (data of stream.iter({ text: "Hi", model: "gpt-4" })) {
if (Object.hasOwn(data, "text")) {
console.log(data.text)
} else if (Object.hasOwn(data, "error")) {
console.error(deserializeError(data.error))
}
}
// 2. use onMessage callback
stream.send({ text: "Hi", model: "gpt-4" })
stream.onMessage((data) => {
if (Object.hasOwn(data, "text")) {
console.log(data.text)
} else if (Object.hasOwn(data, "error")) {
console.error(deserializeError(data.error))
}
})
import { serializeError } from 'serialize-error'
onOpenStream("chat", (stream) => {
stream.onMessage(data => {
chatApi(data, {
signal: stream.signal,
onStramn(data) {
stream.send({ data })
}
})
.then(() => {
stream.send({ done: true })
stream.close()
})
.catch(error => {
if (error.name === "AbortError") {
return
}
stream.send({ error: serializeError(error) })
})
})
})
Based on browser.storage.local
import 'typed-webext'
declare module "typed-webext" {
interface StorageLocalProtocol {
theme: "light" | "dark" | "high-contrast" | "auto"
}
}
async function getTheme() {
const theme = await getStorageLocal("theme", "auto")
// ^ "light" | "dark" | "high-contrast" | "auto"
}
async function setTheme(theme: "light" | "dark" | "high-contrast" | "auto") {
// Key, Value
await setStorageLocal("theme", theme)
// Or Key-value pair
// await setStroageLocal({ theme })
}