feat(ext): split PopupMessage / ContentMessage unions + capability sets

This commit is contained in:
adlee-was-taken
2026-04-20 19:43:09 -04:00
parent 04c9503036
commit b4da5bffcf

View File

@@ -1,68 +1,78 @@
import type { Entry, Manifest, ManifestEntry, VaultConfig, SetupState } from './types'; import type {
Item, ItemId, Manifest, ManifestEntry, VaultConfig, SetupState,
DeviceSettings, GeneratorRequest,
} from './types';
// --- Request types (popup/content -> service worker) --- // --- Messages a popup (or setup page) may send ---
export type Request = export type PopupMessage =
| { type: 'is_unlocked' }
| { type: 'unlock'; passphrase: string } | { type: 'unlock'; passphrase: string }
| { type: 'lock' } | { type: 'lock' }
| { type: 'is_unlocked' } | { type: 'list_items'; group?: string }
| { type: 'list_entries'; group?: string } | { type: 'get_item'; id: ItemId }
| { type: 'get_entry'; id: string } | { type: 'add_item'; item: Item }
| { type: 'search_entries'; query: string } | { type: 'update_item'; id: ItemId; item: Item }
| { type: 'add_entry'; entry: Entry } | { type: 'delete_item'; id: ItemId } // soft-delete
| { type: 'update_entry'; id: string; entry: Entry } | { type: 'get_totp'; id: ItemId }
| { type: 'delete_entry'; id: string }
| { type: 'get_totp'; id: string }
| { type: 'get_autofill_candidates'; url: string }
| { type: 'get_credentials'; id: string }
| { type: 'sync' } | { type: 'sync' }
| { type: 'get_setup_state' } | { type: 'get_setup_state' }
| { type: 'save_setup'; config: VaultConfig; imageBase64: string } | { type: 'save_setup'; config: VaultConfig; imageBase64: string }
| { type: 'generate_password'; length: number } | { type: 'rate_passphrase'; passphrase: string }
| { type: 'fill_credentials'; username: string; password: string } | { type: 'generate_password'; request: GeneratorRequest }
| { type: 'check_credential'; url: string; username: string; password: string } | { type: 'fill_credentials'; id: ItemId; capturedTabId: number; capturedUrl: string }
| { type: 'blacklist_site'; hostname: string } | { type: 'ack_autofill_origin'; hostname: string }
| { type: 'get_settings' } | { type: 'get_settings' }
| { type: 'update_settings'; settings: Partial<import('./types').RelicarioSettings> } | { type: 'update_settings'; settings: Partial<DeviceSettings> }
| { type: 'get_blacklist' } | { type: 'get_blacklist' }
| { type: 'remove_blacklist'; hostname: string }; | { type: 'remove_blacklist'; hostname: string };
// --- Response types (service worker -> popup/content) --- // --- Messages a content script may send ---
// Note deliberate absence of a `url` field — the SW derives origin from sender.tab.url.
export type ContentMessage =
| { type: 'get_autofill_candidates' }
| { type: 'get_credentials'; id: ItemId }
| { type: 'check_credential'; username: string; password: string }
| { type: 'blacklist_site' };
// --- Union for chrome.runtime.sendMessage call sites ---
export type Request = PopupMessage | ContentMessage;
// --- Response ---
export type Response = export type Response =
| { ok: true; data?: unknown } | { ok: true; data?: unknown }
| { ok: false; error: string }; | { ok: false; error: string };
export interface UnlockResponse extends Extract<Response, { ok: true }> { // --- Typed response helpers ---
data: undefined;
}
export interface IsUnlockedResponse extends Extract<Response, { ok: true }> { export interface IsUnlockedResponse extends Extract<Response, { ok: true }> {
data: { unlocked: boolean }; data: { unlocked: boolean };
} }
export interface ListEntriesResponse extends Extract<Response, { ok: true }> { export interface ListItemsResponse extends Extract<Response, { ok: true }> {
data: { entries: Array<[string, ManifestEntry]> }; data: { items: Array<[ItemId, ManifestEntry]> };
} }
export interface GetEntryResponse extends Extract<Response, { ok: true }> { export interface GetItemResponse extends Extract<Response, { ok: true }> {
data: { entry: Entry }; data: { item: Item };
}
export interface SearchEntriesResponse extends Extract<Response, { ok: true }> {
data: { entries: Array<[string, ManifestEntry]> };
} }
export interface TotpResponse extends Extract<Response, { ok: true }> { export interface TotpResponse extends Extract<Response, { ok: true }> {
data: { code: string; remaining_seconds: number }; data: { code: string; expires_at: number };
} }
export interface AutofillCandidatesResponse extends Extract<Response, { ok: true }> { export interface AutofillCandidatesResponse extends Extract<Response, { ok: true }> {
data: { candidates: Array<[string, ManifestEntry]> }; data: { candidates: Array<[ItemId, ManifestEntry]> };
} }
export interface CredentialsResponse extends Extract<Response, { ok: true }> { export interface CredentialsResponse extends Extract<Response, { ok: true }> {
data: { username: string; password: string }; data:
| { requires_ack: true; hostname: string }
| { username: string; password: string };
} }
export interface SetupStateResponse extends Extract<Response, { ok: true }> { export interface SetupStateResponse extends Extract<Response, { ok: true }> {
@@ -72,3 +82,21 @@ export interface SetupStateResponse extends Extract<Response, { ok: true }> {
export interface GeneratePasswordResponse extends Extract<Response, { ok: true }> { export interface GeneratePasswordResponse extends Extract<Response, { ok: true }> {
data: { password: string }; data: { password: string };
} }
export interface RatePassphraseResponse extends Extract<Response, { ok: true }> {
data: { score: number; guesses_log10: number };
}
// --- Capability sets (consumed by the router) ---
export const POPUP_ONLY_TYPES: ReadonlySet<PopupMessage['type']> = new Set([
'is_unlocked', 'unlock', 'lock', 'list_items', 'get_item', 'add_item',
'update_item', 'delete_item', 'get_totp', 'sync', 'get_setup_state',
'save_setup', 'rate_passphrase', 'generate_password', 'fill_credentials',
'ack_autofill_origin', 'get_settings', 'update_settings', 'get_blacklist',
'remove_blacklist',
] as PopupMessage['type'][]);
export const CONTENT_CALLABLE_TYPES: ReadonlySet<ContentMessage['type']> = new Set([
'get_autofill_candidates', 'get_credentials', 'check_credential', 'blacklist_site',
] as ContentMessage['type'][]);