Skip to content

Latest commit

 

History

History
158 lines (125 loc) · 2.84 KB

README.md

File metadata and controls

158 lines (125 loc) · 2.84 KB

typed-webext

Type safe web extension api (partial)

Warning

Still working in progress, do not use in production

Message

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

sendMessage("get-time")
  .then((time) => {
    console.log(time)
    //          ^ time: number
  })
  .catch(error => {
    console.error(error)
  })

onMessage

// background.ts

onMessage("get-time", () => {
  const now = new Date()
  if (now.getFullYear() > 1999) {
    throw new Error("You are late!")
  } else {
    return +now
  }
})

Stream

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 }
    ]
   }
}

openStream

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))
  }
})

onOpenStream

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) })
      })
  })
})

Storage Local

Based on browser.storage.local

import 'typed-webext'

declare module "typed-webext" {
  interface StorageLocalProtocol {
    theme: "light" | "dark" | "high-contrast" | "auto"
  }
}

getStorageLocal

async function getTheme() {
  const theme = await getStorageLocal("theme", "auto")
  //    ^ "light" | "dark" | "high-contrast" | "auto"
}

setStorageLocal

async function setTheme(theme: "light" | "dark" | "high-contrast" | "auto") {
  // Key, Value
  await setStorageLocal("theme", theme)
  // Or Key-value pair
  // await setStroageLocal({ theme })
}