@haatlabs-core/extension-kit
v0.10.0
Published
The browser side of an extension's panel: the active tab, page reads, downloads, sign-in keys.
Maintainers
Readme
@haatlabs-core/extension-kit
The browser side of an extension's panel (Manifest V3): the PanelEnv of
@haatlabs-core/extension-ui for a Chrome or Edge side panel, the service worker's setup, and the
key an app's own connect page hands the extension.
Install
pnpm add @haatlabs-core/extension-kitUse
createChromePanelEnv(): the active tab (once the person clicked the icon there, or allowed every site), tab changes in the panel's own window, downloads (a file made in parts is saved as one), JSON read from inside the page as the page would, and the page's scripts and globals.openSidePanelOnIconClick(), in the service worker: the toolbar icon opens the side panel.- Sign-in through the app's own connect page:
startConnect(webOrigin)opens<webOrigin>/connect/extension?extension=<id>;listenForConnections({ <app>: <webOrigin> })in the service worker keeps the key that page sends (<app>.connected), only from that origin;createAuthStore(app)reads, keeps and forgets it in local storage (never synced).
For an extension of an app with its own backend (not built on the platform):
fillFields(tabId, [{ selector, value }])fills a page's form in the page's own world, so React and Vue forms keep the values (a<select>by its value or its text), and returns{ filled, missing }: show what was missing, never skip it.copyText(text)copies.SiteAdapter: one site's form as data (matchesas Chrome match patterns, theanchorfield, andfields(data, page));matchAdapter(url, adapters)picks the page's.installFillButton({ adapters, label, onFill }), in a content script: a button beside the form's first field once it appears.startOAuthPkce({ authorizeUrl, tokenUrl, clientId, scopes })signs in throughchrome.identitywith OAuth 2 and PKCE (S256,statechecked) and returns{ accessToken, refreshToken, expiresAt };refreshOAuth(grant, tokenUrl, clientId)renews it in its last minute.createAuthStorekeeps either kind of grant.
Chrome, Edge, Firefox and Safari from one code base:
browserName()(chromium,firefox,safari, from the scheme of the extension's own pages) andextensionApi()(browserwhere there is one, elsechrome).createChromePanelEnvworks in each: Firefox and Safari answerchrome.*too.openPanelOnIconClick(), in the background script: Chromium's side panel, Firefox's sidebar; on Safari the panel is the action's popup.manifestFor(browser, base, { geckoId })writes each browser's manifest from one Chromium base: Firefox getssidebar_action, a background script andbrowser_specific_settings; Safari a popup and noidentitypermission.startOAuthPkcesigns in withchrome.identityorbrowser.identity; on Safari, which has none, through a tab to the app's own page (safariRedirectUri), which hands the answer back withbrowser.runtime.sendMessage.
The manifest needs the sidePanel, scripting, downloads, storage and activeTab
permissions, optional_host_permissions: ["https://*/*"], and the app's web origin in
externally_connectable.
The package is for the browser only: its code runs in an extension, through a bundler.
