@midra/webext 0.0.0-stage → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,899 @@
1
+ /// <reference types="chrome" preserve="true" />
2
+ import Browser from "webextension-polyfill";
3
+ //#region src/context.d.ts
4
+ /**
5
+ * インスタンス作成時に取得・推測した実行環境と、ポップアウトの関連付け情報。
6
+ *
7
+ * @remarks
8
+ * このオブジェクトは凍結され、作成後のURLやmanifest設定の変更には追従しません。
9
+ * ポップアウト関連の情報は拡張ページのクエリから取得する便宜上の情報であり、
10
+ * 認証・アクセス制御や、関連付け先タブが現在も存在することの保証には使えません。
11
+ * @see https://developer.chrome.com/docs/extensions/reference/api/runtime#method-getURL
12
+ * @see https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/getURL
13
+ */
14
+ interface WebExtContext {
15
+ /** 関連付け先タブIDを格納する内部クエリの名前(`_webext_linked_tab_id`)。 */
16
+ readonly LINKED_TAB_ID_NAME: string;
17
+ /** 拡張URLのスキームから判定するブラウザ種別。Chromium系は `chrome`。明示指定があればそちらを優先します。 */
18
+ readonly browser: 'chrome' | 'firefox' | 'unknown';
19
+ /** 実行コンテキストの役割。manifestや実行環境から判定できない場合は `null`。 */
20
+ readonly type: 'background' | 'content-script' | 'popup' | 'sidepanel' | null;
21
+ /** 拡張ページの内部クエリに指定された非負の安全な整数ID。未指定・不正・通常のWebページでは `null`。 */
22
+ readonly linkedTabId: number | null;
23
+ /** 拡張ページにポップアウト用の内部クエリがあるか。関連付け先がなくても `true` になり得ます。 */
24
+ readonly isPopout: boolean;
25
+ }
26
+ /** `CreateWebExtOptions` に含まれる実行環境の上書き設定。 */
27
+ interface ContextOptions {
28
+ /**
29
+ * 実行コンテキストの役割を明示します。省略時だけ自動判定し、`null` は判定しない指定です。
30
+ *
31
+ * @remarks 動的に変更したpopup・パネルのパスや独自の拡張ページでは、役割を明示してください。
32
+ */
33
+ context?: WebExtContext['type'];
34
+ /** ブラウザ種別を明示します。APIを切り替えたり、未対応機能を有効化したりする設定ではありません。 */
35
+ browser?: WebExtContext['browser'];
36
+ /**
37
+ * 環境判定と内部クエリの取得に使う絶対URL。省略時は `globalThis.location?.href`。
38
+ *
39
+ * @remarks テストなどで使う上書き値です。ページ遷移や権限の付与は行いません。
40
+ */
41
+ url?: string;
42
+ }
43
+ //#endregion
44
+ //#region src/messaging/types.d.ts
45
+ /**
46
+ * 1種類のメッセージの要求型と応答型。
47
+ *
48
+ * @remarks
49
+ * 型の定義であり、実行時スキーマではありません。要求・応答の内容は利用側で検証してください。
50
+ * 送受信値はJSON互換値に限定し、Firefoxのstructured cloneで送れる値より厳しく制限します。
51
+ * 有限数・文字列・真偽値・`null`・配列・プレーンオブジェクトが対象で、Date・Map・BigInt・
52
+ * 関数・循環参照などは拒否します。オブジェクト内の `undefined` は省略、疎配列の穴は `null` に変換し、
53
+ * 配列要素として明示した `undefined` は拒否します。最上位の `undefined` は内部で `null` とフラグに
54
+ * 符号化し、受信時に `undefined` に復元します。要求・応答とも同じ規則です。
55
+ * @see https://developer.chrome.com/docs/extensions/reference/api/runtime#method-sendMessage
56
+ * @see https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/sendMessage
57
+ */
58
+ interface MessageDefinition {
59
+ /** 送信する要求の型。型指定だけでは受信値を実行時検証しません。 */
60
+ request: unknown;
61
+ /** ハンドラーが返す応答の型。JSON互換性以外の実行時検証は行いません。 */
62
+ response: unknown;
63
+ }
64
+ /**
65
+ * メッセージ名から要求型・応答型への対応表。
66
+ *
67
+ * @remarks 同じチャンネルの送受信側で共有する型であり、実行時の登録・検証は行いません。
68
+ * @example
69
+ * ```ts
70
+ * interface Messages {
71
+ * greet: { request: { name: string }; response: string }
72
+ * }
73
+ * ```
74
+ */
75
+ type MessageSchema = Record<string, MessageDefinition>;
76
+ /**
77
+ * 送信先と送信側の応答待機を指定するオプション。
78
+ *
79
+ * @remarks
80
+ * `tabId` がなければ自拡張への `runtime.sendMessage()`、あれば `tabs.sendMessage()` を使用します。
81
+ * 外部拡張・Webページ宛ての送信は提供しません。対象フレーム・ドキュメントの存在と各オプションへの
82
+ * 対応はネイティブAPIに従い、未対応の指定を代替しません。
83
+ * @see https://developer.chrome.com/docs/extensions/reference/api/runtime#method-sendMessage
84
+ * @see https://developer.chrome.com/docs/extensions/reference/api/tabs#method-sendMessage
85
+ */
86
+ interface SendOptions {
87
+ /**
88
+ * 送信先コンテンツスクリプトを含むタブID。非負の安全な整数が必要です。
89
+ * @remarks ネイティブの `tabs.sendMessage()` が使えるコンテキストと、対象タブの受信ハンドラーが必要です。
90
+ * `tabs` 権限が一律に必須という意味ではありません。省略時はアクティブタブを検索せず、自拡張へ送信します。
91
+ */
92
+ tabId?: number;
93
+ /**
94
+ * 対象フレームのID。`tabId` が必須です。`0` はトップレベルフレーム。
95
+ * @remarks 値の有効性・対象の存在はネイティブAPIに従います。省略時はネイティブの既定の送信範囲です。
96
+ * @see https://developer.chrome.com/docs/extensions/reference/api/tabs#method-sendMessage
97
+ */
98
+ frameId?: number;
99
+ /**
100
+ * 対象ドキュメントのID。`tabId` と、ネイティブAPIのこのオプションへの対応が必要です。
101
+ * @remarks 値・対象の有効性はネイティブAPIに従い、未対応環境での補完は行いません。
102
+ * @see https://developer.chrome.com/docs/extensions/reference/api/tabs#method-sendMessage
103
+ */
104
+ documentId?: string;
105
+ /**
106
+ * 送信側の待機上限(ミリ秒)。既定値は10,000、正の有限数で最大2,147,483,647。
107
+ * @remarks 範囲外は送信前に `TypeError` でPromiseが拒否されます。期限超過は `MessageTimeoutError`。
108
+ * 終了するのはローカルの待機だけで、受信側の処理や送信済みのネイティブ通信はキャンセルしません。
109
+ */
110
+ timeoutMs?: number;
111
+ /**
112
+ * 送信側の待機を中止するシグナル。
113
+ * @remarks 既に中止済みなら送信しません。中止時は `signal.reason`(なければ `AbortError`)で
114
+ * Promiseが拒否されます。送信後の中止はローカルの待機だけを終了し、受信処理はキャンセルしません。
115
+ */
116
+ signal?: AbortSignal;
117
+ }
118
+ /**
119
+ * 同じ拡張内の名前付き要求・応答チャンネル。
120
+ *
121
+ * @typeParam Schema - メッセージ名ごとの要求型・応答型。実行時スキーマ検証は行いません。
122
+ * @remarks
123
+ * ファクトリーごとに単一の `runtime.onMessage` ルーターを共有し、ハンドラーがある間だけ登録します。
124
+ * 受信は `sender.id === runtime.id` の内部メッセージに限定し、未登録のチャンネル・メッセージは扱いません。
125
+ * この確認は要求内容や送信元URLの信頼性を保証しません。必要な検証はハンドラーで行ってください。
126
+ * 1つの要求に応答するコンテキストは1つにしてください。複数の受信先が応答する場合の順序は保証しません。
127
+ * @see https://developer.chrome.com/docs/extensions/reference/api/runtime#type-MessageSender
128
+ * @see https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/onMessage
129
+ */
130
+ interface MessageChannel<Schema extends { [K in keyof Schema]: MessageDefinition; }> {
131
+ /**
132
+ * JSON互換の要求を送り、対応するハンドラーの応答を待ちます。
133
+ *
134
+ * @typeParam K - スキーマ内のメッセージ名。
135
+ * @param type - 送受信側で共有するメッセージ名。
136
+ * @param request - 要求値。直列化の制約は {@link MessageDefinition} を参照してください。
137
+ * @param options - 送信先・待機上限・中止シグナル。
138
+ * @returns 応答値で解決するPromise。応答型の実行時検証は行いません。
139
+ * @throws {TypeError} 無効なタブID・待機上限、`tabId` なしのframe/document指定、非JSON互換の要求。
140
+ * @throws {UnsupportedOperationError} タブ送信に必要なネイティブAPIが利用できない場合。
141
+ * @throws {MessageTimeoutError} 応答待機の期限を超過した場合。
142
+ * @throws {RemoteError} ハンドラーの例外・Promise拒否、または応答のJSON化失敗。
143
+ * @throws 破棄済みチャンネル・非互換の応答・ネイティブ通信エラー・シグナル中止理由。
144
+ * @remarks
145
+ * 上記の失敗はすべて戻り値のPromiseの拒否です(同期例外ではありません)。受信先がない場合も成功扱いにしません。
146
+ * `tabId` なしの送信は送信元自身を除く拡張コンテキスト宛てで、コンテンツスクリプト宛てではありません。
147
+ * コンテンツスクリプトへは `tabId` を指定してください。待機の中止は受信処理を停止しません。
148
+ * @see https://developer.chrome.com/docs/extensions/reference/api/runtime#method-sendMessage
149
+ * @see https://developer.chrome.com/docs/extensions/reference/api/tabs#method-sendMessage
150
+ * @see https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/sendMessage
151
+ */
152
+ send<K extends keyof Schema & string>(type: K, request: Schema[K]['request'], options?: SendOptions): Promise<Schema[K]['response']>;
153
+ /**
154
+ * 1種類のメッセージを処理するハンドラーを登録します。
155
+ *
156
+ * @typeParam K - スキーマ内のメッセージ名。
157
+ * @param type - 処理するメッセージ名。同じチャンネル内で重複登録はできません。
158
+ * @param handler - 要求値とネイティブのMessageSenderを受け取り、JSON互換の応答値またはそのPromiseを返す関数。
159
+ * @returns この登録だけを解除する関数。繰り返し呼んでも一度だけ解除し、後続の再登録は解除しません。
160
+ * @throws {UnsupportedOperationError} `runtime.onMessage` が利用できない場合に同期的に送出します。
161
+ * @throws 破棄済みチャンネル・同じメッセージ名の重複登録は同期例外です。
162
+ * @remarks
163
+ * 受信イベント内でハンドラーを同期的に呼び、その結果をawaitしてcallbackで応答します。
164
+ * Chrome / Firefoxとも内部リスナーは `true` を返して非同期応答を維持します。
165
+ * ハンドラーの例外は送信側で `RemoteError` となります。要求値・senderの追加検証は利用側の責任です。
166
+ * backgroundでは再起動時にも登録されるようトップレベルで呼んでください。
167
+ * @example
168
+ * ```ts
169
+ * const channel = webext.messaging.channel<Messages>('app/background')
170
+ * const stop = channel.handle('greet', ({ name }) => `Hello, ${name}`)
171
+ * // 別コンテキストで同名チャンネルを作成し、send('greet', { name: 'Midra' })
172
+ * stop()
173
+ * ```
174
+ * @see https://developer.chrome.com/docs/extensions/reference/api/runtime#event-onMessage
175
+ * @see https://developer.chrome.com/docs/extensions/reference/api/runtime#type-MessageSender
176
+ * @see https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/onMessage
177
+ */
178
+ handle<K extends keyof Schema & string>(type: K, handler: (request: Schema[K]['request'], sender: Browser.Runtime.MessageSender) => Schema[K]['response'] | Promise<Schema[K]['response']>): () => void;
179
+ /**
180
+ * このチャンネルの全ハンドラーを解除し、このオブジェクトを終端的に破棄します。
181
+ *
182
+ * @returns 戻り値はありません。繰り返し呼べます。
183
+ * @remarks
184
+ * 以後の `send()` はPromiseの拒否、`handle()` は同期例外になります。
185
+ * ファクトリーが未破棄なら `messaging.channel(name)` で同名の新しいチャンネルを作れます。
186
+ * 既に実行中のハンドラーや送信側の待機はキャンセルしません。
187
+ */
188
+ dispose(): void;
189
+ }
190
+ /** 名前付きチャンネルを管理する、WebExtインスタンスごとのメッセージングファクトリー。 */
191
+ interface Messaging {
192
+ /**
193
+ * 名前に対応するチャンネルを取得・作成します。
194
+ *
195
+ * @typeParam Schema - 送受信側で共有する型。同じ名前に異なる型を指定しても実行時に検出しません。
196
+ * @param name - チャンネル名。空文字・空白のみは禁止で、それ以外は空白も含め完全一致で識別します。
197
+ * @returns 同じファクトリー内では、同名の未破棄チャンネルを再利用します。
198
+ * @throws {TypeError} 名前が空文字・空白のみなら同期的に送出します。
199
+ * @throws ファクトリーが破棄済みなら同期例外です。
200
+ * @remarks 取得だけでは受信リスナーを登録しません。送受信側で同じ名前とスキーマを共有してください。
201
+ * @example
202
+ * ```ts
203
+ * const channel = webext.messaging.channel<Messages>('app/background')
204
+ * const greeting = await channel.send('greet', { name: 'Midra' })
205
+ * ```
206
+ */
207
+ channel<Schema extends { [K in keyof Schema]: MessageDefinition; }>(name: string): MessageChannel<Schema>;
208
+ /**
209
+ * 全チャンネルと共有ルーターを解除し、ファクトリーを終端的に破棄します。
210
+ *
211
+ * @returns 戻り値はありません。繰り返し呼べます。
212
+ * @remarks
213
+ * `webext.dispose()` でも呼ばれます。破棄後は `channel()` を呼べません。
214
+ * 再利用には `createWebExt()` で新しいインスタンスを作成してください。
215
+ * 送信済みの待機や実行中の受信処理をキャンセルするものではありません。
216
+ */
217
+ dispose(): void;
218
+ }
219
+ //#endregion
220
+ //#region src/popout.d.ts
221
+ /**
222
+ * actionのpopupやサイドパネルの拡張ページを別ウィンドウで開くためのライブラリ独自設定。
223
+ *
224
+ * @remarks
225
+ * ウィンドウの種類は `popup`、URLは対象ページから生成する。
226
+ * `tabId` 以外の値は `windows.create` にそのまま渡し、省略値もブラウザの既定に従う。
227
+ * 寸法・位置・状態の組み合わせやプライベートウィンドウの制約はネイティブ側で検証され、エラーは伝播する。
228
+ * @example
229
+ * ```ts
230
+ * await webext.side.openPopout({ tabId: null, width: 420, height: 720 })
231
+ * ```
232
+ * @see https://developer.chrome.com/docs/extensions/reference/api/windows#method-create
233
+ * @see https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/windows/create
234
+ */
235
+ interface PopoutOptions {
236
+ /**
237
+ * 関連付けるタブの非負の安全な整数ID。既存タブは移動しない。
238
+ *
239
+ * @remarks
240
+ * 省略時は `tabs.getTargetId()` の対象を使う。`null` または対象がない場合は関連付けなし。
241
+ * URLの内部クエリに記録する独自の関連付けであり、認証・アクセス制御には使わない。
242
+ * タブを移動するネイティブの `windows.create` の `tabId` には渡さない。
243
+ * @see https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/windows/create#parameters
244
+ */
245
+ tabId?: number | null;
246
+ /** フレームを含むウィンドウ幅(ピクセル)。省略時はブラウザが決定する。`state` の併用制約に注意。 */
247
+ width?: number;
248
+ /** フレームを含むウィンドウ高さ(ピクセル)。省略時はブラウザが決定する。`state` の併用制約に注意。 */
249
+ height?: number;
250
+ /** 画面左端からの位置(ピクセル)。省略時はブラウザが決定する。`state` の併用制約に注意。 */
251
+ left?: number;
252
+ /** 画面上端からの位置(ピクセル)。省略時はブラウザが決定する。`state` の併用制約に注意。 */
253
+ top?: number;
254
+ /** `true` ならフォーカスして開き、`false` なら非アクティブで開く。省略時はネイティブの既定に従う。 */
255
+ focused?: boolean;
256
+ /**
257
+ * シークレット/プライベートウィンドウとして開くか。
258
+ *
259
+ * @remarks
260
+ * 拡張機能のプライベート利用許可やブラウザの制約により、ネイティブ側で拒否される場合がある。
261
+ * 利用許可の取得や別のウィンドウへのフォールバックは行わない。
262
+ */
263
+ incognito?: boolean;
264
+ /**
265
+ * 作成時のウィンドウ状態。
266
+ *
267
+ * @remarks `minimized`・`maximized`・`fullscreen` は `left`・`top`・`width`・`height` と併用できない。
268
+ * @see https://developer.chrome.com/docs/extensions/reference/api/windows#method-create
269
+ * @see https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/windows/create#parameters
270
+ */
271
+ state?: 'normal' | 'minimized' | 'maximized' | 'fullscreen';
272
+ }
273
+ //#endregion
274
+ //#region src/errors.d.ts
275
+ /**
276
+ * 現在のブラウザ・実行コンテキストに、操作に必要なAPIや機能がない場合のエラー。
277
+ *
278
+ * @remarks
279
+ * 権限不足などのネイティブエラーを一律にこの型へ変換するものではありません。
280
+ * `StorageHelpers.watch()` / `MessageChannel.handle()` では同期的に送出し、`MessageChannel.send()` など
281
+ * Promiseを返す操作では拒否理由になります。捕捉方法は呼び出すAPIに従ってください。
282
+ */
283
+ export declare class UnsupportedOperationError extends Error {
284
+ /** 利用できなかった操作の識別子。 */
285
+ readonly operation: string;
286
+ /**
287
+ * 利用できない操作名を含むエラーを作成します。
288
+ * @param operation - ライブラリ内の操作識別子(例: `storage.watch`)。
289
+ */
290
+ constructor(
291
+ /** 利用できなかった操作の識別子。 */
292
+ operation: string);
293
+ }
294
+ /**
295
+ * メッセージの応答待機が送信側の期限を超過した場合のエラー。
296
+ *
297
+ * @remarks
298
+ * `channel.send()` のPromiseの拒否理由です。受信側の処理やネイティブ通信が停止したことは意味しません。
299
+ * 不正な待機上限の指定はこの型ではなく `TypeError` になります。
300
+ */
301
+ export declare class MessageTimeoutError extends Error {
302
+ /** 送信側で設定した応答待機の上限(ミリ秒)。 */
303
+ readonly timeoutMs: number;
304
+ /**
305
+ * 応答待機の上限を含むエラーを作成します。
306
+ * @param timeoutMs - 超過した待機上限(ミリ秒)。このコンストラクター自体は値を検証しません。
307
+ */
308
+ constructor(
309
+ /** 送信側で設定した応答待機の上限(ミリ秒)。 */
310
+ timeoutMs: number);
311
+ }
312
+ /**
313
+ * 受信側のハンドラーの失敗を送信側へ伝えるエラー。
314
+ *
315
+ * @remarks
316
+ * ハンドラーの同期例外・Promiseの拒否・応答のJSON化失敗は、`channel.send()` のPromiseをこの型で拒否します。
317
+ * `name` は `RemoteError`、元の名前は `remoteName`、失敗内容は継承した `message` に保持します。
318
+ * 元の例外オブジェクト・スタック・独自プロパティは転送しません。Error以外の例外値は名前を `Error` として
319
+ * 文字列化し、文字列化も失敗した場合は `Error` / `Remote handler failed` にフォールバックします。
320
+ */
321
+ export declare class RemoteError extends Error {
322
+ /** 受信側で正規化した例外名。送信側の `name` とは異なります。 */
323
+ readonly remoteName: string;
324
+ /**
325
+ * 受信側から転送された名前とメッセージでエラーを作成します。
326
+ * @param message - 受信側のエラーメッセージ、または例外値を文字列化した内容。
327
+ * @param remoteName - 受信側の例外名。名前を取得できない場合は `Error`。
328
+ */
329
+ constructor(message: string,
330
+ /** 受信側で正規化した例外名。送信側の `name` とは異なります。 */
331
+ remoteName: string);
332
+ }
333
+ //#endregion
334
+ //#region src/side.d.ts
335
+ /**
336
+ * サイドパネルの開閉対象。
337
+ *
338
+ * @remarks
339
+ * 対象省略時は現在のウィンドウ。ChromeではネイティブAPIへ対象を渡す。
340
+ * Firefoxの開閉は対象指定に対応せず、省略または `windowId: -2` のみ受け付ける。
341
+ * @see https://developer.chrome.com/docs/extensions/reference/api/sidePanel#type-OpenOptions
342
+ * @see https://developer.chrome.com/docs/extensions/reference/api/sidePanel#type-CloseOptions
343
+ */
344
+ interface SideTarget {
345
+ /** 対象タブの非負の安全な整数ID。Firefoxの開閉では指定不可。 */
346
+ tabId?: number;
347
+ /** 対象ウィンドウの非負の安全な整数ID。`-2` は現在のウィンドウを表す。 */
348
+ windowId?: number;
349
+ }
350
+ /**
351
+ * サイドパネルのパス設定を取得・変更する対象。ウィンドウ単位の指定は提供しない。
352
+ *
353
+ * @see https://developer.chrome.com/docs/extensions/reference/api/sidePanel#type-GetPanelOptions
354
+ * @see https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/sidebarAction/setPanel
355
+ */
356
+ interface SidePathTarget {
357
+ /** 対象タブの非負の安全な整数ID。省略時はグローバル(既定)の設定を扱う。 */
358
+ tabId?: number;
359
+ }
360
+ /**
361
+ * 初期化時に検出したサイドパネル関連APIの対応状況。
362
+ *
363
+ * @remarks
364
+ * APIの存在に基づく判定であり、権限・manifest設定・バージョン要件や操作の成功は保証しない。
365
+ */
366
+ interface SideCapabilities {
367
+ /** パネルを開くAPIがあるか。 */
368
+ readonly open: boolean;
369
+ /** パネルを閉じるAPIがあるか。ChromeのネイティブAPIは141以降。 */
370
+ readonly close: boolean;
371
+ /** パス設定の取得・変更に必要なAPIがあるか。 */
372
+ readonly path: boolean;
373
+ /**
374
+ * 開状態の判定方式。`false` は未対応。
375
+ *
376
+ * @remarks
377
+ * `native` はFirefoxの表示状態取得、`document` はChromeのパネルドキュメントの存在観測。
378
+ * 後者は切り替え・終了途中などの厳密なUI表示状態と一致しない可能性がある。
379
+ * @see https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/sidebarAction/isOpen
380
+ * @see https://developer.chrome.com/docs/extensions/reference/api/runtime#method-getContexts
381
+ */
382
+ readonly isOpen: 'native' | 'document' | false;
383
+ /** 明示的なタブ・ウィンドウを指定して開くAPIがあるか。閉じる操作の対応状況ではない。 */
384
+ readonly targetedOpen: boolean;
385
+ /** actionクリックイベントとパネルを開くAPIがあり、クリック連携を登録できるか。 */
386
+ readonly actionClick: boolean;
387
+ }
388
+ /**
389
+ * ChromeのsidePanelとFirefoxのsidebarActionを共通の操作として扱うライブラリ独自API。
390
+ *
391
+ * @remarks
392
+ * ネイティブAPIの完全な模倣ではなく、パスの統一やポップアウトなどの補助操作を提供する。
393
+ * 非同期操作の検証エラー・未対応エラー・ネイティブAPIのエラーはPromiseの拒否として伝播する。
394
+ * @see https://developer.chrome.com/docs/extensions/reference/api/sidePanel
395
+ * @see https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/sidebarAction/open
396
+ */
397
+ interface Side {
398
+ /** 開くAPIがあるか。表示中かどうかや、権限・manifest設定の正しさを示すものではない。 */
399
+ readonly available: boolean;
400
+ /** APIの存在から検出した機能別の対応状況。 */
401
+ readonly capabilities: SideCapabilities;
402
+ /**
403
+ * 拡張機能のサイドパネルを開く。
404
+ *
405
+ * @param target - 開く対象。省略時、Chromeは現在のウィンドウのグローバルパネルを開く。
406
+ * @returns 開く処理が完了すると値なしで解決するPromise。
407
+ * @remarks
408
+ * 両ブラウザでユーザー操作のハンドラーから直接呼ぶ。Chromeの `sidePanel.open` は116以降。
409
+ * Chromeで `tabId` を指定するとタブ固有パネルを使い、未設定ならグローバルパネルを使う。
410
+ * `windowId` のみではタブ固有パネルを選ばない。Firefoxはアクティブなウィンドウで開く。
411
+ * 省略時はChromeへ `windowId: -2` を同期的に渡すため、この定数に未対応の環境では実際のIDを指定する。
412
+ * @throws {@link UnsupportedOperationError} 開くAPIがない場合、またはFirefoxで明示的な対象を指定した場合。
413
+ * @throws {TypeError} タブ・ウィンドウIDが不正な場合。
414
+ * @example
415
+ * ```ts
416
+ * button.addEventListener('click', () => {
417
+ * void webext.side.open().catch(console.error)
418
+ * })
419
+ * ```
420
+ * @see https://developer.chrome.com/docs/extensions/reference/api/sidePanel#method-open
421
+ * @see https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/sidebarAction/open
422
+ */
423
+ open(target?: SideTarget): Promise<void>;
424
+ /**
425
+ * 拡張機能のサイドパネルを閉じる。無効化やパス設定の変更は行わない。
426
+ *
427
+ * @param target - 閉じる対象。省略時は現在のウィンドウ(Chromeではグローバルパネル)。
428
+ * @returns 閉じる処理が完了すると値なしで解決するPromise。
429
+ * @remarks
430
+ * Chromeの `sidePanel.close` は141以降。現在のウィンドウ指定は実際のIDを取得してから渡す。
431
+ * タブ指定時の動作はネイティブに従い、Chrome 145以降はグローバルパネルしか開いていないと拒否される。
432
+ * Firefoxはアクティブなウィンドウで閉じる。MDNの制約に従いユーザー操作のハンドラーから呼ぶ。
433
+ * @throws {@link UnsupportedOperationError} 閉じるためのAPIがない場合、またはFirefoxで明示的な対象を指定した場合。
434
+ * @throws {TypeError} タブ・ウィンドウIDが不正な場合。
435
+ * @see https://developer.chrome.com/docs/extensions/reference/api/sidePanel#method-close
436
+ * @see https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/sidebarAction/close
437
+ */
438
+ close(target?: SideTarget): Promise<void>;
439
+ /**
440
+ * 設定中のパネルのパスを拡張ルート相対形式で取得する。
441
+ *
442
+ * @param target - 設定の取得対象。省略時はグローバル(既定)の設定。
443
+ * @returns クエリ・ハッシュを保持したパス。パスが未設定または空なら `undefined`。
444
+ * @throws {@link UnsupportedOperationError} パスを取得するAPIがない場合。
445
+ * @throws {TypeError} タブIDが不正、または取得したパスが同じ拡張内を指さない場合。
446
+ * @see https://developer.chrome.com/docs/extensions/reference/api/sidePanel#method-getOptions
447
+ * @see https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/sidebarAction/getPanel
448
+ */
449
+ getPath(target?: SidePathTarget): Promise<string | undefined>;
450
+ /**
451
+ * パネルに使用する拡張ページのパスを変更する。
452
+ *
453
+ * @param path - 拡張ルート相対パス、または同じ拡張内の絶対URL。クエリ・ハッシュを保持する。
454
+ * @param target - 設定の変更対象。省略時はグローバル(既定)の設定。
455
+ * @returns パス設定の変更が完了すると値なしで解決するPromise。
456
+ * @remarks パネルを開く操作ではない。FirefoxのネイティブAPIと異なり、外部URLや空文字列による設定解除は受け付けない。
457
+ * @throws {@link UnsupportedOperationError} パスを変更するAPIがない場合。
458
+ * @throws {TypeError} タブIDやパスが不正、空のパス、または外部URLを指定した場合。
459
+ * @see https://developer.chrome.com/docs/extensions/reference/api/sidePanel#method-setOptions
460
+ * @see https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/sidebarAction/setPanel
461
+ */
462
+ setPath(path: string, target?: SidePathTarget): Promise<void>;
463
+ /**
464
+ * 指定ウィンドウでパネルが開いているかを判定する。
465
+ *
466
+ * @param target - 判定対象。
467
+ * @param target.windowId - ウィンドウID。省略または `-2` は現在のウィンドウ(Firefoxでは最前面)。
468
+ * @returns Firefoxではネイティブの表示状態、Chromeでは対象ウィンドウの `SIDE_PANEL` コンテキストが存在するか。
469
+ * @remarks
470
+ * Firefoxでは開閉と異なり明示的なウィンドウIDを指定できる。
471
+ * Chromeは `runtime.getContexts` によるドキュメントの存在観測であり、厳密なUI表示状態を保証しない。
472
+ * @throws {@link UnsupportedOperationError} 状態判定に必要なAPIがない場合。
473
+ * @throws {TypeError} ウィンドウIDが不正な場合。
474
+ * @see https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/sidebarAction/isOpen
475
+ * @see https://developer.chrome.com/docs/extensions/reference/api/runtime#method-getContexts
476
+ */
477
+ isOpen(target?: {
478
+ windowId?: number;
479
+ }): Promise<boolean>;
480
+ /**
481
+ * 対象タブに設定中のパネルページを別ウィンドウで開くライブラリ独自ヘルパー。
482
+ *
483
+ * @param options - 関連付けるタブとウィンドウの設定。`tabId: null` は関連付けなしでグローバルのパスを使う。
484
+ * @returns ネイティブの `windows.create` が返すウィンドウ情報、または `undefined`。
485
+ * @remarks
486
+ * `tabId` 省略時は `tabs.getTargetId()` の対象を使い、対象がなければグローバルのパスを使う。
487
+ * 既存タブの移動やサイドパネルの開閉は行わない。寸法・状態・プライベート設定の制約は {@link PopoutOptions} を参照。
488
+ * @throws {@link UnsupportedOperationError} パス取得やウィンドウ作成に必要なAPIがない場合。
489
+ * @throws {TypeError} タブIDやパスが不正な場合。
490
+ * @throws {Error} パネルのパスが未設定の場合。対象解決・設定取得・ウィンドウ作成のエラーも伝播する。
491
+ * @example
492
+ * ```ts
493
+ * await webext.side.openPopout({ tabId: null, width: 420, height: 720 })
494
+ * ```
495
+ * @see https://developer.chrome.com/docs/extensions/reference/api/windows#method-create
496
+ * @see https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/windows/create
497
+ */
498
+ openPopout(options?: PopoutOptions): Promise<Browser.Windows.Window | undefined>;
499
+ /**
500
+ * actionクリックでパネルを開くリスナーを登録するライブラリ独自ヘルパー。
501
+ *
502
+ * @param onError - パネルを開くPromiseが拒否されたときに呼ぶエラーハンドラー。
503
+ * @returns この登録を解除する関数。繰り返し呼んでもよい。
504
+ * @remarks
505
+ * background起動時のトップレベルで同期的に登録する。actionのpopupが設定されているタブではクリックイベントが発火しない。
506
+ * Chromeではクリックしたタブのウィンドウのグローバルパネルを開き、Firefoxではアクティブなウィンドウで開く。
507
+ * ネイティブの `setPanelBehavior` を設定するものではなく、クリック時に `open` を呼ぶ。
508
+ * @throws {@link UnsupportedOperationError} クリックイベントまたはパネルを開くAPIがない場合。
509
+ * @example
510
+ * ```ts
511
+ * const unbind = webext.side.bindActionClick(console.error)
512
+ * ```
513
+ * @see https://developer.chrome.com/docs/extensions/reference/api/action#event-onClicked
514
+ */
515
+ bindActionClick(onError: (error: unknown) => void): () => void;
516
+ /** このインスタンスが登録したactionクリックのリスナーをすべて解除する。パネルは閉じない。繰り返し呼んでもよい。 */
517
+ dispose(): void;
518
+ }
519
+ //#endregion
520
+ //#region src/storage.d.ts
521
+ /**
522
+ * 利用可能なストレージ領域に追加する共通ヘルパー。
523
+ *
524
+ * @remarks
525
+ * `storage` 権限が必要です。領域へのアクセス制限・保存形式・クォータはネイティブAPIに従います。
526
+ * Promiseを返すメソッドの失敗は拒否として伝播し、`watch()` の登録失敗は同期例外です。
527
+ * 型引数 `T` は実行時のデータ検証・変換を行いません。
528
+ * @see https://developer.chrome.com/docs/extensions/reference/api/storage
529
+ * @see https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/storage
530
+ */
531
+ interface StorageHelpers {
532
+ /** 補完メソッドの実装方式。権限・領域へのアクセス可否を保証するものではありません。 */
533
+ readonly capabilities: {
534
+ /** `native` はネイティブ呼び出し、`polyfilled` は全値の取得によるキー列挙。 */
535
+ readonly getKeys: 'native' | 'polyfilled';
536
+ /** `native` はネイティブの計測、`estimated` はJSONに基づく推定。 */
537
+ readonly getBytesInUse: 'native' | 'estimated';
538
+ };
539
+ /**
540
+ * 領域内の全キーを取得します。
541
+ *
542
+ * @returns キーの配列。ネイティブが未対応なら `get(null)` で全値を読み、キーを列挙します。
543
+ * @throws ネイティブの読み取りエラーでPromiseが拒否されます。
544
+ * @remarks 補完時はキーだけでなく全値の読み取りコストが発生します。
545
+ * @see https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/storage/StorageArea
546
+ */
547
+ getKeys(): Promise<string[]>;
548
+ /**
549
+ * 指定キーの使用バイト数を取得し、ネイティブが未対応なら推定します。
550
+ *
551
+ * @param keys - 対象キー。省略・`null` は全件、空配列は対象なし。
552
+ * @returns ネイティブの計測値、またはキーとJSON化した値のUTF-8バイト数の合計。
553
+ * @throws 読み取り・JSON化の失敗でPromiseが拒否されます。
554
+ * @remarks
555
+ * `capabilities.getBytesInUse` で実装方式を確認できます。推定値はディスク使用量でも
556
+ * ブラウザのクォータ計測値でもなく、クォータ超過の判定には使えません。
557
+ * 特にsession領域のメモリ使用量とは異なります。
558
+ * @see https://developer.chrome.com/docs/extensions/reference/api/storage
559
+ * @see https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/storage/StorageArea/get
560
+ */
561
+ getBytesInUse(keys?: string | string[] | null): Promise<number>;
562
+ /**
563
+ * 単一キーの値を取得します。
564
+ *
565
+ * @typeParam T - 期待する値の型。実行時検証は行いません。
566
+ * @param key - 取得するキー。
567
+ * @returns 保存値。キーが存在しなければ `undefined`。
568
+ * @throws ネイティブの読み取りエラーでPromiseが拒否されます。
569
+ * @see https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/storage/StorageArea/get
570
+ */
571
+ getValue<T>(key: string): Promise<T | undefined>;
572
+ /**
573
+ * 単一キーの値を、未保存時の既定値付きで取得します。
574
+ *
575
+ * @typeParam T - 期待する値の型。保存値の実行時検証は行いません。
576
+ * @param key - 取得するキー。
577
+ * @param defaultValue - キーが存在しない場合だけ返す値。ストレージには保存しません。
578
+ * @returns 保存値、または既定値。既存の `null` などは既定値に置き換えません。
579
+ * @throws ネイティブの読み取りエラーでPromiseが拒否されます。既定値ではエラーを補いません。
580
+ * @example
581
+ * ```ts
582
+ * const theme = await webext.storage.local.getValue('theme', 'system')
583
+ * ```
584
+ * @see https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/storage/StorageArea/get
585
+ */
586
+ getValue<T>(key: string, defaultValue: T): Promise<T>;
587
+ /**
588
+ * 単一キーの値をネイティブの `set()` で保存・更新します。
589
+ *
590
+ * @typeParam T - 保存する値の型。実行時検証は行いません。
591
+ * @param key - 保存先のキー。
592
+ * @param value - ネイティブのストレージAPIで保存可能な値。
593
+ * @returns 保存完了時に解決するPromise。
594
+ * @throws 保存形式・権限・クォータなどのネイティブエラーでPromiseが拒否されます。
595
+ * managed領域は読み取り専用のため書き込みが拒否されます。
596
+ * @see https://developer.chrome.com/docs/extensions/reference/api/storage
597
+ */
598
+ setValue<T>(key: string, value: T): Promise<void>;
599
+ /**
600
+ * この領域・キーに対するネイティブの変更通知を監視します。
601
+ *
602
+ * @typeParam T - 通知値の期待する型。実行時検証は行いません。
603
+ * @param key - 監視するキー。
604
+ * @param listener - 新しい値と以前の値を受け取る関数。削除後の値・追加前の値は `undefined`。
605
+ * @returns この監視だけを解除する関数。繰り返し呼んでも解除処理は一度だけです。
606
+ * @throws {UnsupportedOperationError} `storage.onChanged` がなければ同期的に送出します。
607
+ * @remarks
608
+ * 登録時に現在値は通知しません。値の比較や重複排除は行わず、Firefoxでは値が変わらなくても
609
+ * 通知される場合があります。managedの通知可否もネイティブに従います。
610
+ * `storage.dispose()` / `webext.dispose()` でもこのヘルパーの監視を解除します。
611
+ * @example
612
+ * ```ts
613
+ * const stop = webext.storage.local.watch<string>('theme', (value, previous) => {
614
+ * console.log(previous, value)
615
+ * })
616
+ * stop()
617
+ * ```
618
+ * @see https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/storage/onChanged
619
+ */
620
+ watch<T>(key: string, listener: (value: T | undefined, previous: T | undefined) => void): () => void;
621
+ }
622
+ /**
623
+ * ネイティブのStorageAreaに共通ヘルパーを追加した領域。
624
+ *
625
+ * @remarks
626
+ * 継承する `get(keys)` は値の辞書を取得し、省略・`null` は全件、既定値の辞書も指定できます。
627
+ * `set(items)` はキーと値の辞書を保存、`remove(keys)` は指定キーを削除、`clear()` は全件削除します。
628
+ * これらはネイティブのPromiseを返し、失敗は拒否として伝播します。managedへの変更操作は拒否されます。
629
+ * `onChanged` は領域単位のネイティブイベントです。直接登録したリスナーは利用側で解除してください。
630
+ * 共通ヘルパー以外のネイティブメソッド・イベントの対応状況やアクセス制限は補完しません。
631
+ * @see https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/storage/StorageArea
632
+ * @see https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/storage/StorageArea/get
633
+ */
634
+ type StorageArea = Omit<Browser.Storage.StorageArea, 'getBytesInUse'> & StorageHelpers;
635
+ /**
636
+ * 拡張機能のネイティブストレージと共通ヘルパー。
637
+ *
638
+ * @remarks `storage` 権限が必要です。領域の存在だけでは権限・アクセス設定・ポリシーの利用可否を保証しません。
639
+ * @see https://developer.chrome.com/docs/extensions/reference/api/storage
640
+ * @see https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/storage
641
+ */
642
+ interface WebExtStorage {
643
+ /** ローカルに永続保存する領域。保存量の制限はネイティブに従います。 */
644
+ local: StorageArea;
645
+ /** ブラウザの同期設定に従って同期する領域。容量・書き込み頻度の制限はネイティブに従います。 */
646
+ sync: StorageArea;
647
+ /**
648
+ * 管理者などが構成する読み取り専用領域。`setValue()` やネイティブの変更操作は拒否されます。
649
+ *
650
+ * @remarks
651
+ * Chromeはスキーマと企業ポリシー、Firefoxはネイティブマニフェストまたは `3rdparty` ポリシーなどで
652
+ * 利用側が事前構成します。Firefoxでは未構成の領域の読み取りも失敗し得るため、空の辞書を前提にしないでください。
653
+ * @see https://developer.chrome.com/docs/extensions/reference/api/storage
654
+ * @see https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/storage/managed
655
+ * @see https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/storage/StorageArea/get
656
+ */
657
+ managed: StorageArea;
658
+ /**
659
+ * ブラウザが提供する、ディスクに永続保存しないメモリ上のsession領域。
660
+ *
661
+ * @remarks
662
+ * 未対応なら `undefined`。service worker内のメモリやlocalなどの永続領域では代用しません。
663
+ * 利用可否・寿命はブラウザと実行コンテキストに依存し、通常コンテンツスクリプトには公開されません。
664
+ * 必要なネイティブのアクセス設定は利用側で行います。
665
+ * @see https://developer.chrome.com/docs/extensions/reference/api/storage
666
+ * @see https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/storage/session
667
+ */
668
+ session?: StorageArea;
669
+ /**
670
+ * 全領域のネイティブ変更イベント。値の重複排除は行いません。
671
+ *
672
+ * @remarks 直接登録したリスナーは `dispose()` の対象外です。利用側で `removeListener()` してください。
673
+ * @see https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/storage/onChanged
674
+ */
675
+ onChanged: Browser.Storage.Static['onChanged'];
676
+ /**
677
+ * このラッパーの `watch()` が登録した監視を解除します。
678
+ *
679
+ * @returns 戻り値はありません。
680
+ * @remarks
681
+ * 繰り返し呼べます。保存値・ネイティブ設定・直接登録されたリスナーは変更しません。
682
+ * 終端的な破棄ではなく、その後も読み書きや新しい `watch()` の登録が可能です。
683
+ */
684
+ dispose(): void;
685
+ }
686
+ //#endregion
687
+ //#region src/tabs.d.ts
688
+ /**
689
+ * ネイティブのtabs APIに、実行コンテキストを考慮したタブ取得ヘルパーを追加したAPI。
690
+ *
691
+ * @remarks
692
+ * コンテンツスクリプトでは、backgroundのトップレベルで `webext.initialize()` を呼ぶと
693
+ * 共通ヘルパーを内部メッセージ経由で利用できます。ネイティブの `query()` などを
694
+ * コンテンツスクリプトへ公開するものではありません。
695
+ * タブIDの取得自体に `tabs` 権限が一律に必要なわけではありませんが、返されるタブの
696
+ * `url`・`pendingUrl`・`title`・`favIconUrl` などの情報には `tabs` または対象のホスト権限が必要です。
697
+ * ヘルパーの失敗はPromiseの拒否として伝播します。
698
+ * @see https://developer.chrome.com/docs/extensions/reference/api/tabs
699
+ * @see https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs/query
700
+ */
701
+ type WebExtTabs = Browser.Tabs.Static & {
702
+ /** ネイティブのtabs APIが存在するか。`false` でも内部ブリッジ経由の共通ヘルパーは利用できます。 */
703
+ readonly available: boolean;
704
+ /**
705
+ * 現在のウィンドウのアクティブタブを取得します。ポップアウトの関連付け先は優先しません。
706
+ *
707
+ * @returns 条件に合う最初のタブ。タブがなければ `undefined`。
708
+ * @remarks
709
+ * ネイティブでは `query({ active: true, currentWindow: true })` を使います。
710
+ * 内部ブリッジ経由では、送信元タブのウィンドウIDがあればそのウィンドウに限定して検索します。
711
+ * 受信先がない場合やネイティブAPIの失敗は、メッセージング・ネイティブのエラーで拒否されます。
712
+ * @see https://developer.chrome.com/docs/extensions/reference/api/tabs#method-query
713
+ * @see https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs/query
714
+ */
715
+ getCurrentActive(): Promise<Browser.Tabs.Tab | undefined>;
716
+ /**
717
+ * `getCurrentActive()` で取得したタブのIDを返します。
718
+ * @returns タブID。タブまたはIDがなければ `undefined`。取得エラーは伝播します。
719
+ */
720
+ getCurrentActiveId(): Promise<number | undefined>;
721
+ /**
722
+ * 関連付け先タブ、コンテンツスクリプト自身のタブ、アクティブタブの順に対象を解決します。
723
+ *
724
+ * @returns 解決したタブ。対象がなければ `undefined`。
725
+ * @remarks
726
+ * `context.linkedTabId` があればネイティブの `tabs.get()` を使います。
727
+ * 未指定ならコンテンツスクリプトでは `getSelf()`、それ以外では `getCurrentActive()` を使います。
728
+ * 関連付け先が閉じられていても別のタブへフォールバックせず、取得エラーを伝播します。
729
+ * @throws {UnsupportedOperationError} 関連付け先が指定されているのにネイティブのtabs APIがない場合。
730
+ * @see https://developer.chrome.com/docs/extensions/reference/api/tabs#method-get
731
+ * @see https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs/get
732
+ */
733
+ getTarget(): Promise<Browser.Tabs.Tab | undefined>;
734
+ /**
735
+ * `getTarget()` で解決したタブのIDを返します。
736
+ * @returns タブID。対象タブまたはIDがなければ `undefined`。取得エラーは伝播します。
737
+ */
738
+ getTargetId(): Promise<number | undefined>;
739
+ /**
740
+ * このスクリプト自身を含むタブを取得します。アクティブタブや関連付け先とは異なります。
741
+ *
742
+ * @returns 自身を含むタブ。backgroundや通常のaction popupなど、タブに属さなければ `undefined`。
743
+ * @remarks
744
+ * コンテンツスクリプト、またはネイティブのtabs APIがない環境では、backgroundが受け取る
745
+ * `MessageSender.tab` を利用します。それ以外ではネイティブの `tabs.getCurrent()` を使います。
746
+ * ブリッジの未登録やネイティブの取得失敗はエラーとして伝播します。
747
+ * @see https://developer.chrome.com/docs/extensions/reference/api/tabs#method-getCurrent
748
+ * @see https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs/getCurrent
749
+ * @see https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/MessageSender
750
+ */
751
+ getSelf(): Promise<Browser.Tabs.Tab | undefined>;
752
+ /**
753
+ * `getSelf()` で取得した自身のタブIDを返します。
754
+ * @returns タブID。自身のタブまたはIDがなければ `undefined`。取得エラーは伝播します。
755
+ */
756
+ getSelfId(): Promise<number | undefined>;
757
+ };
758
+ //#endregion
759
+ //#region src/core.d.ts
760
+ /**
761
+ * 共通APIインスタンスの作成設定。省略した値はネイティブAPIと実行環境から取得します。
762
+ *
763
+ * @remarks
764
+ * ブラウザAPIのアクセス権限を付与したり、ネイティブAPI全体をPromise化したりする設定ではありません。
765
+ * 環境判定の上書きは継承した `context`・`browser`・`url` で指定します。
766
+ * @see https://developer.chrome.com/docs/extensions/reference/api/runtime#method-getManifest
767
+ */
768
+ interface CreateWebExtOptions extends ContextOptions {
769
+ /**
770
+ * 利用するネイティブAPI。テストでは互換のモックを注入できます。
771
+ *
772
+ * @remarks
773
+ * 省略時は `runtime.id` があるグローバルの `browser` を優先し、なければ `chrome` を使います。
774
+ * ライブラリからこのオブジェクトやグローバルのAPIを変更しません。
775
+ */
776
+ api?: typeof chrome | Browser.Browser;
777
+ }
778
+ /**
779
+ * Chrome / FirefoxのネイティブAPIに、共通操作と実用ヘルパーを追加したライブラリの公開API。
780
+ *
781
+ * @remarks
782
+ * Manifest V3とPromise版のネイティブAPIがある環境を対象にします。
783
+ * APIの利用可否はブラウザ・権限・manifest・実行コンテキストに依存し、未対応の
784
+ * ネイティブAPI全体を補完するものではありません。独自ヘルパーの仕様は各メンバーを参照してください。
785
+ * @see https://developer.chrome.com/docs/extensions/reference/api
786
+ * @see https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API
787
+ */
788
+ type WebExt = Omit<Browser.Browser, 'tabs' | 'action' | 'storage' | 'menus' | 'sidebarAction'> & {
789
+ /** ブラウザ固有APIへのアクセス用の元のAPIオブジェクト。ライブラリからは変更しません。 */
790
+ readonly native: typeof chrome | Browser.Browser;
791
+ /** 初期化時の実行環境とポップアウトの関連付け情報。作成後の変更には追従しません。 */
792
+ readonly context: WebExtContext;
793
+ /** サイドパネルの共通操作。ネイティブのsidePanel / sidebarActionとは別の独自APIです。 */
794
+ readonly side: Side;
795
+ /** 同じ拡張内の型付き要求・応答チャンネルを管理する独自API。 */
796
+ readonly messaging: Messaging;
797
+ /** ネイティブのtabs APIと、コンテンツスクリプトでも使える共通タブ取得ヘルパー。 */
798
+ readonly tabs: WebExtTabs;
799
+ /** ネイティブの各ストレージ領域と、値取得・変更監視などの共通ヘルパー。`storage` 権限が必要です。 */
800
+ readonly storage: WebExtStorage;
801
+ /**
802
+ * Firefoxの `menus`、またはChromeの `contextMenus` をネイティブのまま公開します。
803
+ * @remarks 利用するブラウザのメニュー権限が必要です。ネイティブのcallback専用メソッドはPromise化しません。
804
+ * @see https://developer.chrome.com/docs/extensions/reference/api/contextMenus
805
+ * @see https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/menus
806
+ */
807
+ readonly menus: Browser.ContextMenus.Static;
808
+ /**
809
+ * 存在する場合のみ公開するChromeのネイティブsidePanel API。共通操作には `side` を使用します。
810
+ * @see https://developer.chrome.com/docs/extensions/reference/api/sidePanel
811
+ */
812
+ readonly sidePanel?: typeof chrome.sidePanel;
813
+ /**
814
+ * 存在する場合のみ公開するFirefoxのネイティブsidebarAction API。共通操作には `side` を使用します。
815
+ * @see https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/sidebarAction
816
+ */
817
+ readonly sidebarAction?: Browser.SidebarAction.Static;
818
+ /**
819
+ * ネイティブaction APIと、popupページを別ウィンドウで開く独自ヘルパー。
820
+ * @remarks manifestのaction設定や、利用可能な実行コンテキストが必要です。
821
+ * @see https://developer.chrome.com/docs/extensions/reference/api/action
822
+ * @see https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/action
823
+ */
824
+ readonly action: Browser.Action.Static & {
825
+ /**
826
+ * 対象タブに現在設定されているactionのpopupページを別ウィンドウで開きます。
827
+ *
828
+ * @param options - 関連付けるタブとウィンドウの設定。省略した `tabId` は `tabs.getTargetId()`、`null` は関連付けなし。
829
+ * @returns ネイティブの `windows.create()` が返すウィンドウ情報、または `undefined`。
830
+ * @remarks
831
+ * 既存タブは移動しません。URLのクエリとハッシュを保持します。
832
+ * popupが空に設定されている場合は、manifestの初期値へ戻さずエラーにします。
833
+ * @throws {TypeError} タブIDや取得したページのパスが不正な場合。Promiseの拒否として伝播します。
834
+ * @throws {Error} popup未設定、対象解決やネイティブAPIの失敗。ウィンドウAPI未対応時は `UnsupportedOperationError`。
835
+ * @see https://developer.chrome.com/docs/extensions/reference/api/action#method-getPopup
836
+ * @see https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/action/getPopup
837
+ * @see https://developer.chrome.com/docs/extensions/reference/api/windows#method-create
838
+ */
839
+ openPopout(options?: PopoutOptions): Promise<Browser.Windows.Window | undefined>;
840
+ };
841
+ /**
842
+ * background側の内部タブ取得ブリッジを同期的に登録します。
843
+ *
844
+ * @remarks
845
+ * backgroundのトップレベルで呼んでください。service workerの起動ごとに同期登録される必要があります。
846
+ * `createWebExt()` は作成時にもこの処理を呼びます。遅延初期化される `webext` では、
847
+ * トップレベルの `webext.initialize()` により初期化と登録をその場で行えます。
848
+ * 複数回呼んでも登録は増えず、background以外では何もしません。
849
+ * @throws {UnsupportedOperationError} backgroundでネイティブのtabs APIが利用できない場合。同期例外です。
850
+ * @see https://developer.chrome.com/docs/extensions/develop/concepts/service-workers/events
851
+ */
852
+ initialize(): void;
853
+ /**
854
+ * このインスタンスのメッセージ受信、storage.watch、actionクリック連携を解除します。
855
+ *
856
+ * @remarks
857
+ * 繰り返し呼べます。保存値・パネル・ネイティブ設定・直接登録されたリスナーは変更しません。
858
+ * 送信済みの待機や実行中の受信処理はキャンセルしません。
859
+ * メッセージングは終端的に破棄されるため、再利用には `createWebExt()` で新しいインスタンスを作成してください。
860
+ */
861
+ dispose(): void;
862
+ };
863
+ /**
864
+ * ネイティブAPIを変更せず、独立した共通APIのインスタンスを作成します。
865
+ *
866
+ * @param options - APIの注入と実行環境の上書き設定。
867
+ * @returns 実行環境・共通ヘルパー・解除処理を持つインスタンス。
868
+ * @remarks
869
+ * backgroundとして作成する場合、内部タブ取得ブリッジはこの呼び出し中に同期登録されます。
870
+ * 権限取得、manifestの変換、ネイティブAPI全体のPromise化は行いません。
871
+ * @throws {Error} 拡張APIがない場合や、初期化に必要なネイティブAPIが失敗した場合。同期例外です。
872
+ * @throws {TypeError} 上書きURLなどをURLとして解析できない場合。同期例外です。
873
+ * @example
874
+ * ```ts
875
+ * const webext = createWebExt({ context: 'sidepanel' })
876
+ * const tab = await webext.tabs.getTarget()
877
+ * ```
878
+ * @see https://developer.chrome.com/docs/extensions/reference/api/runtime#method-getURL
879
+ * @see https://developer.chrome.com/docs/extensions/develop/concepts/service-workers/events
880
+ */
881
+ export declare function createWebExt(options?: CreateWebExtOptions): WebExt;
882
+ /**
883
+ * 初回のプロパティアクセスで初期化する、既定の共通APIインスタンス。
884
+ *
885
+ * @remarks
886
+ * モジュールのインポートだけでは拡張APIへアクセスしません。プロパティの読み取りや列挙などは
887
+ * 初期化を発生させるため、拡張環境が必要です。backgroundのトップレベルでは
888
+ * `webext.initialize()` を同期的に呼び、内部ブリッジを登録してください。
889
+ * 設定の注入や破棄後の新しいインスタンスには {@link createWebExt} を使用します。
890
+ * @example
891
+ * ```ts
892
+ * import { webext } from '@midra/webext'
893
+ * webext.initialize()
894
+ * ```
895
+ * @see https://developer.chrome.com/docs/extensions/develop/concepts/service-workers/events
896
+ */
897
+ export declare const webext: WebExt;
898
+ //#endregion
899
+ export type { CreateWebExtOptions, MessageChannel, MessageDefinition, MessageSchema, Messaging, PopoutOptions, SendOptions, Side, SideCapabilities, SidePathTarget, SideTarget, StorageArea, StorageHelpers, WebExt, WebExtContext, WebExtStorage, WebExtTabs };