@opentabs-dev/browser-extension 0.0.34
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.
- package/dist/background-log-state.d.ts +10 -0
- package/dist/background-log-state.d.ts.map +1 -0
- package/dist/background-log-state.js +11 -0
- package/dist/background-log-state.js.map +1 -0
- package/dist/background-message-handlers.d.ts +41 -0
- package/dist/background-message-handlers.d.ts.map +1 -0
- package/dist/background-message-handlers.js +214 -0
- package/dist/background-message-handlers.js.map +1 -0
- package/dist/background.d.ts +2 -0
- package/dist/background.d.ts.map +1 -0
- package/dist/background.js +3780 -0
- package/dist/background.js.map +1 -0
- package/dist/bg-log-state.d.ts +10 -0
- package/dist/bg-log-state.d.ts.map +1 -0
- package/dist/bg-log-state.js +11 -0
- package/dist/bg-log-state.js.map +1 -0
- package/dist/browser-commands/content-commands.d.ts +25 -0
- package/dist/browser-commands/content-commands.d.ts.map +1 -0
- package/dist/browser-commands/content-commands.js +166 -0
- package/dist/browser-commands/content-commands.js.map +1 -0
- package/dist/browser-commands/cookie-commands.d.ts +14 -0
- package/dist/browser-commands/cookie-commands.d.ts.map +1 -0
- package/dist/browser-commands/cookie-commands.js +99 -0
- package/dist/browser-commands/cookie-commands.js.map +1 -0
- package/dist/browser-commands/extension-commands.d.ts +12 -0
- package/dist/browser-commands/extension-commands.d.ts.map +1 -0
- package/dist/browser-commands/extension-commands.js +386 -0
- package/dist/browser-commands/extension-commands.js.map +1 -0
- package/dist/browser-commands/helpers.d.ts +35 -0
- package/dist/browser-commands/helpers.d.ts.map +1 -0
- package/dist/browser-commands/helpers.js +121 -0
- package/dist/browser-commands/helpers.js.map +1 -0
- package/dist/browser-commands/index.d.ts +11 -0
- package/dist/browser-commands/index.d.ts.map +1 -0
- package/dist/browser-commands/index.js +10 -0
- package/dist/browser-commands/index.js.map +1 -0
- package/dist/browser-commands/interaction-commands.d.ts +23 -0
- package/dist/browser-commands/interaction-commands.d.ts.map +1 -0
- package/dist/browser-commands/interaction-commands.js +353 -0
- package/dist/browser-commands/interaction-commands.js.map +1 -0
- package/dist/browser-commands/key-press-command.d.ts +2 -0
- package/dist/browser-commands/key-press-command.d.ts.map +1 -0
- package/dist/browser-commands/key-press-command.js +144 -0
- package/dist/browser-commands/key-press-command.js.map +1 -0
- package/dist/browser-commands/network-commands.d.ts +6 -0
- package/dist/browser-commands/network-commands.d.ts.map +1 -0
- package/dist/browser-commands/network-commands.js +69 -0
- package/dist/browser-commands/network-commands.js.map +1 -0
- package/dist/browser-commands/resource-commands.d.ts +37 -0
- package/dist/browser-commands/resource-commands.d.ts.map +1 -0
- package/dist/browser-commands/resource-commands.js +153 -0
- package/dist/browser-commands/resource-commands.js.map +1 -0
- package/dist/browser-commands/scroll-command.d.ts +2 -0
- package/dist/browser-commands/scroll-command.d.ts.map +1 -0
- package/dist/browser-commands/scroll-command.js +133 -0
- package/dist/browser-commands/scroll-command.js.map +1 -0
- package/dist/browser-commands/tab-commands.d.ts +33 -0
- package/dist/browser-commands/tab-commands.d.ts.map +1 -0
- package/dist/browser-commands/tab-commands.js +121 -0
- package/dist/browser-commands/tab-commands.js.map +1 -0
- package/dist/browser-commands.d.ts +36 -0
- package/dist/browser-commands.d.ts.map +1 -0
- package/dist/browser-commands.js +1931 -0
- package/dist/browser-commands.js.map +1 -0
- package/dist/confirmation-badge.d.ts +17 -0
- package/dist/confirmation-badge.d.ts.map +1 -0
- package/dist/confirmation-badge.js +64 -0
- package/dist/confirmation-badge.js.map +1 -0
- package/dist/constants.d.ts +79 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +79 -0
- package/dist/constants.js.map +1 -0
- package/dist/dispatch-helpers.d.ts +61 -0
- package/dist/dispatch-helpers.d.ts.map +1 -0
- package/dist/dispatch-helpers.js +149 -0
- package/dist/dispatch-helpers.js.map +1 -0
- package/dist/extension-messages.d.ts +146 -0
- package/dist/extension-messages.d.ts.map +1 -0
- package/dist/extension-messages.js +2 -0
- package/dist/extension-messages.js.map +1 -0
- package/dist/iife-injection.d.ts +55 -0
- package/dist/iife-injection.d.ts.map +1 -0
- package/dist/iife-injection.js +474 -0
- package/dist/iife-injection.js.map +1 -0
- package/dist/json-rpc-errors.d.ts +8 -0
- package/dist/json-rpc-errors.d.ts.map +1 -0
- package/dist/json-rpc-errors.js +8 -0
- package/dist/json-rpc-errors.js.map +1 -0
- package/dist/known-methods.d.ts +19 -0
- package/dist/known-methods.d.ts.map +1 -0
- package/dist/known-methods.js +68 -0
- package/dist/known-methods.js.map +1 -0
- package/dist/log-collector.d.ts +45 -0
- package/dist/log-collector.d.ts.map +1 -0
- package/dist/log-collector.js +99 -0
- package/dist/log-collector.js.map +1 -0
- package/dist/message-router.d.ts +28 -0
- package/dist/message-router.d.ts.map +1 -0
- package/dist/message-router.js +367 -0
- package/dist/message-router.js.map +1 -0
- package/dist/messaging.d.ts +15 -0
- package/dist/messaging.d.ts.map +1 -0
- package/dist/messaging.js +41 -0
- package/dist/messaging.js.map +1 -0
- package/dist/network-capture.d.ts +56 -0
- package/dist/network-capture.d.ts.map +1 -0
- package/dist/network-capture.js +374 -0
- package/dist/network-capture.js.map +1 -0
- package/dist/offscreen/index.d.ts +16 -0
- package/dist/offscreen/index.d.ts.map +1 -0
- package/dist/offscreen/index.js +549 -0
- package/dist/offscreen/index.js.map +1 -0
- package/dist/plugin-storage.d.ts +19 -0
- package/dist/plugin-storage.d.ts.map +1 -0
- package/dist/plugin-storage.js +100 -0
- package/dist/plugin-storage.js.map +1 -0
- package/dist/rate-limiter.d.ts +18 -0
- package/dist/rate-limiter.d.ts.map +1 -0
- package/dist/rate-limiter.js +53 -0
- package/dist/rate-limiter.js.map +1 -0
- package/dist/resource-prompt-dispatch.d.ts +14 -0
- package/dist/resource-prompt-dispatch.d.ts.map +1 -0
- package/dist/resource-prompt-dispatch.js +195 -0
- package/dist/resource-prompt-dispatch.js.map +1 -0
- package/dist/sanitize-error.d.ts +8 -0
- package/dist/sanitize-error.d.ts.map +1 -0
- package/dist/sanitize-error.js +25 -0
- package/dist/sanitize-error.js.map +1 -0
- package/dist/sanitize-svg.d.ts +20 -0
- package/dist/sanitize-svg.d.ts.map +1 -0
- package/dist/sanitize-svg.js +296 -0
- package/dist/sanitize-svg.js.map +1 -0
- package/dist/side-panel/App.d.ts +3 -0
- package/dist/side-panel/App.d.ts.map +1 -0
- package/dist/side-panel/App.js +147 -0
- package/dist/side-panel/App.js.map +1 -0
- package/dist/side-panel/bridge.d.ts +50 -0
- package/dist/side-panel/bridge.d.ts.map +1 -0
- package/dist/side-panel/bridge.js +113 -0
- package/dist/side-panel/bridge.js.map +1 -0
- package/dist/side-panel/components/ConfirmationDialog.d.ts +16 -0
- package/dist/side-panel/components/ConfirmationDialog.d.ts.map +1 -0
- package/dist/side-panel/components/ConfirmationDialog.js +39 -0
- package/dist/side-panel/components/ConfirmationDialog.js.map +1 -0
- package/dist/side-panel/components/EmptyStates.d.ts +8 -0
- package/dist/side-panel/components/EmptyStates.d.ts.map +1 -0
- package/dist/side-panel/components/EmptyStates.js +40 -0
- package/dist/side-panel/components/EmptyStates.js.map +1 -0
- package/dist/side-panel/components/ErrorBoundary.d.ts +23 -0
- package/dist/side-panel/components/ErrorBoundary.d.ts.map +1 -0
- package/dist/side-panel/components/ErrorBoundary.js +28 -0
- package/dist/side-panel/components/ErrorBoundary.js.map +1 -0
- package/dist/side-panel/components/FailedPluginCard.d.ts +6 -0
- package/dist/side-panel/components/FailedPluginCard.d.ts.map +1 -0
- package/dist/side-panel/components/FailedPluginCard.js +9 -0
- package/dist/side-panel/components/FailedPluginCard.js.map +1 -0
- package/dist/side-panel/components/Footer.d.ts +3 -0
- package/dist/side-panel/components/Footer.d.ts.map +1 -0
- package/dist/side-panel/components/Footer.js +32 -0
- package/dist/side-panel/components/Footer.js.map +1 -0
- package/dist/side-panel/components/Header.d.ts +5 -0
- package/dist/side-panel/components/Header.d.ts.map +1 -0
- package/dist/side-panel/components/Header.js +6 -0
- package/dist/side-panel/components/Header.js.map +1 -0
- package/dist/side-panel/components/PluginCard.d.ts +10 -0
- package/dist/side-panel/components/PluginCard.d.ts.map +1 -0
- package/dist/side-panel/components/PluginCard.js +50 -0
- package/dist/side-panel/components/PluginCard.js.map +1 -0
- package/dist/side-panel/components/PluginIcon.d.ts +21 -0
- package/dist/side-panel/components/PluginIcon.d.ts.map +1 -0
- package/dist/side-panel/components/PluginIcon.js +48 -0
- package/dist/side-panel/components/PluginIcon.js.map +1 -0
- package/dist/side-panel/components/PluginList.d.ts +11 -0
- package/dist/side-panel/components/PluginList.d.ts.map +1 -0
- package/dist/side-panel/components/PluginList.js +17 -0
- package/dist/side-panel/components/PluginList.js.map +1 -0
- package/dist/side-panel/components/ToolIcon.d.ts +7 -0
- package/dist/side-panel/components/ToolIcon.d.ts.map +1 -0
- package/dist/side-panel/components/ToolIcon.js +8 -0
- package/dist/side-panel/components/ToolIcon.js.map +1 -0
- package/dist/side-panel/components/ToolRow.d.ts +11 -0
- package/dist/side-panel/components/ToolRow.d.ts.map +1 -0
- package/dist/side-panel/components/ToolRow.js +8 -0
- package/dist/side-panel/components/ToolRow.js.map +1 -0
- package/dist/side-panel/components/VersionMismatchBanner.d.ts +3 -0
- package/dist/side-panel/components/VersionMismatchBanner.d.ts.map +1 -0
- package/dist/side-panel/components/VersionMismatchBanner.js +5 -0
- package/dist/side-panel/components/VersionMismatchBanner.js.map +1 -0
- package/dist/side-panel/components/retro/Accordion.d.ts +8 -0
- package/dist/side-panel/components/retro/Accordion.d.ts.map +1 -0
- package/dist/side-panel/components/retro/Accordion.js +15 -0
- package/dist/side-panel/components/retro/Accordion.js.map +1 -0
- package/dist/side-panel/components/retro/Alert.d.ts +25 -0
- package/dist/side-panel/components/retro/Alert.d.ts.map +1 -0
- package/dist/side-panel/components/retro/Alert.js +33 -0
- package/dist/side-panel/components/retro/Alert.js.map +1 -0
- package/dist/side-panel/components/retro/Badge.d.ts +15 -0
- package/dist/side-panel/components/retro/Badge.d.ts.map +1 -0
- package/dist/side-panel/components/retro/Badge.js +23 -0
- package/dist/side-panel/components/retro/Badge.js.map +1 -0
- package/dist/side-panel/components/retro/Button.d.ts +13 -0
- package/dist/side-panel/components/retro/Button.d.ts.map +1 -0
- package/dist/side-panel/components/retro/Button.js +33 -0
- package/dist/side-panel/components/retro/Button.js.map +1 -0
- package/dist/side-panel/components/retro/Empty.d.ts +31 -0
- package/dist/side-panel/components/retro/Empty.d.ts.map +1 -0
- package/dist/side-panel/components/retro/Empty.js +25 -0
- package/dist/side-panel/components/retro/Empty.js.map +1 -0
- package/dist/side-panel/components/retro/Input.d.ts +8 -0
- package/dist/side-panel/components/retro/Input.d.ts.map +1 -0
- package/dist/side-panel/components/retro/Input.js +7 -0
- package/dist/side-panel/components/retro/Input.js.map +1 -0
- package/dist/side-panel/components/retro/Loader.d.ts +14 -0
- package/dist/side-panel/components/retro/Loader.d.ts.map +1 -0
- package/dist/side-panel/components/retro/Loader.js +30 -0
- package/dist/side-panel/components/retro/Loader.js.map +1 -0
- package/dist/side-panel/components/retro/Menu.d.ts +9 -0
- package/dist/side-panel/components/retro/Menu.d.ts.map +1 -0
- package/dist/side-panel/components/retro/Menu.js +17 -0
- package/dist/side-panel/components/retro/Menu.js.map +1 -0
- package/dist/side-panel/components/retro/NumberStepper.d.ts +18 -0
- package/dist/side-panel/components/retro/NumberStepper.d.ts.map +1 -0
- package/dist/side-panel/components/retro/NumberStepper.js +38 -0
- package/dist/side-panel/components/retro/NumberStepper.js.map +1 -0
- package/dist/side-panel/components/retro/Progress.d.ts +9 -0
- package/dist/side-panel/components/retro/Progress.d.ts.map +1 -0
- package/dist/side-panel/components/retro/Progress.js +6 -0
- package/dist/side-panel/components/retro/Progress.js.map +1 -0
- package/dist/side-panel/components/retro/Switch.d.ts +4 -0
- package/dist/side-panel/components/retro/Switch.d.ts.map +1 -0
- package/dist/side-panel/components/retro/Switch.js +6 -0
- package/dist/side-panel/components/retro/Switch.js.map +1 -0
- package/dist/side-panel/components/retro/Text.d.ts +11 -0
- package/dist/side-panel/components/retro/Text.d.ts.map +1 -0
- package/dist/side-panel/components/retro/Text.js +28 -0
- package/dist/side-panel/components/retro/Text.js.map +1 -0
- package/dist/side-panel/components/retro/Tooltip.d.ts +12 -0
- package/dist/side-panel/components/retro/Tooltip.d.ts.map +1 -0
- package/dist/side-panel/components/retro/Tooltip.js +32 -0
- package/dist/side-panel/components/retro/Tooltip.js.map +1 -0
- package/dist/side-panel/constants.d.ts +5 -0
- package/dist/side-panel/constants.d.ts.map +1 -0
- package/dist/side-panel/constants.js +5 -0
- package/dist/side-panel/constants.js.map +1 -0
- package/dist/side-panel/hooks/useServerNotifications.d.ts +21 -0
- package/dist/side-panel/hooks/useServerNotifications.d.ts.map +1 -0
- package/dist/side-panel/hooks/useServerNotifications.js +93 -0
- package/dist/side-panel/hooks/useServerNotifications.js.map +1 -0
- package/dist/side-panel/hooks/useTheme.d.ts +8 -0
- package/dist/side-panel/hooks/useTheme.d.ts.map +1 -0
- package/dist/side-panel/hooks/useTheme.js +30 -0
- package/dist/side-panel/hooks/useTheme.js.map +1 -0
- package/dist/side-panel/index.d.ts +2 -0
- package/dist/side-panel/index.d.ts.map +1 -0
- package/dist/side-panel/index.js +12 -0
- package/dist/side-panel/index.js.map +1 -0
- package/dist/side-panel/lib/cn.d.ts +3 -0
- package/dist/side-panel/lib/cn.d.ts.map +1 -0
- package/dist/side-panel/lib/cn.js +4 -0
- package/dist/side-panel/lib/cn.js.map +1 -0
- package/dist/side-panel/lib/utils.d.ts +3 -0
- package/dist/side-panel/lib/utils.d.ts.map +1 -0
- package/dist/side-panel/lib/utils.js +4 -0
- package/dist/side-panel/lib/utils.js.map +1 -0
- package/dist/side-panel/side-panel.js +78034 -0
- package/dist/side-panel/styles.css +2 -0
- package/dist/side-panel-state.d.ts +11 -0
- package/dist/side-panel-state.d.ts.map +1 -0
- package/dist/side-panel-state.js +38 -0
- package/dist/side-panel-state.js.map +1 -0
- package/dist/side-panel-toggle.d.ts +3 -0
- package/dist/side-panel-toggle.d.ts.map +1 -0
- package/dist/side-panel-toggle.js +31 -0
- package/dist/side-panel-toggle.js.map +1 -0
- package/dist/tab-matching.d.ts +51 -0
- package/dist/tab-matching.d.ts.map +1 -0
- package/dist/tab-matching.js +160 -0
- package/dist/tab-matching.js.map +1 -0
- package/dist/tab-state.d.ts +56 -0
- package/dist/tab-state.d.ts.map +1 -0
- package/dist/tab-state.js +282 -0
- package/dist/tab-state.js.map +1 -0
- package/dist/tool-dispatch.d.ts +19 -0
- package/dist/tool-dispatch.d.ts.map +1 -0
- package/dist/tool-dispatch.js +336 -0
- package/dist/tool-dispatch.js.map +1 -0
- package/dist/types.d.ts +82 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/icons/icon-128.png +0 -0
- package/icons/icon-16.png +0 -0
- package/icons/icon-32.png +0 -0
- package/icons/icon-48.png +0 -0
- package/icons/icon.svg +6 -0
- package/manifest.json +38 -0
- package/offscreen/offscreen.html +10 -0
- package/package.json +49 -0
- package/side-panel/dark-mode.js +29 -0
- package/side-panel/fonts/archivo-black-latin.woff2 +0 -0
- package/side-panel/fonts/space-grotesk-latin.woff2 +0 -0
- package/side-panel/fonts/space-mono-400-latin.woff2 +0 -0
- package/side-panel/fonts/space-mono-700-latin.woff2 +0 -0
- package/side-panel/fonts.css +34 -0
- package/side-panel/side-panel.html +16 -0
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { PLUGINS_META_KEY } from './constants.js';
|
|
2
|
+
/**
|
|
3
|
+
* Write-through in-memory cache of plugin metadata.
|
|
4
|
+
* Populated on first read, kept in sync on every write.
|
|
5
|
+
* Avoids redundant async chrome.storage.local reads on hot paths
|
|
6
|
+
* (tabs.onUpdated, tab state checks).
|
|
7
|
+
*/
|
|
8
|
+
let metaCache = null;
|
|
9
|
+
/** Serializes all write operations to prevent concurrent read-modify-write races. */
|
|
10
|
+
let writeMutex = Promise.resolve();
|
|
11
|
+
const serialize = (fn) => {
|
|
12
|
+
const result = writeMutex.then(fn);
|
|
13
|
+
writeMutex = result.then(() => { }, () => { });
|
|
14
|
+
return result;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Store a batch of plugins in a single chrome.storage.local.set() call.
|
|
18
|
+
* Builds the full meta index in memory and writes the meta index atomically.
|
|
19
|
+
*/
|
|
20
|
+
const storePluginsBatch = (metas) => serialize(async () => {
|
|
21
|
+
if (metas.length === 0)
|
|
22
|
+
return;
|
|
23
|
+
const index = await getAllPluginMeta();
|
|
24
|
+
for (const meta of metas) {
|
|
25
|
+
index[meta.name] = meta;
|
|
26
|
+
}
|
|
27
|
+
await chrome.storage.local.set({ [PLUGINS_META_KEY]: index });
|
|
28
|
+
metaCache = index;
|
|
29
|
+
});
|
|
30
|
+
const removePlugin = (pluginName) => serialize(async () => {
|
|
31
|
+
const index = await getAllPluginMeta();
|
|
32
|
+
if (!(pluginName in index))
|
|
33
|
+
return;
|
|
34
|
+
const { [pluginName]: _, ...rest } = index;
|
|
35
|
+
await chrome.storage.local.set({ [PLUGINS_META_KEY]: rest });
|
|
36
|
+
metaCache = rest;
|
|
37
|
+
});
|
|
38
|
+
/**
|
|
39
|
+
* Remove multiple plugins in a single batched operation.
|
|
40
|
+
* Reads the meta index once, removes all named plugins, then writes the
|
|
41
|
+
* updated index in one call.
|
|
42
|
+
*/
|
|
43
|
+
const removePluginsBatch = (pluginNames) => serialize(async () => {
|
|
44
|
+
if (pluginNames.length === 0)
|
|
45
|
+
return;
|
|
46
|
+
const index = await getAllPluginMeta();
|
|
47
|
+
const removeSet = new Set(pluginNames);
|
|
48
|
+
const filtered = {};
|
|
49
|
+
for (const [name, meta] of Object.entries(index)) {
|
|
50
|
+
if (!removeSet.has(name)) {
|
|
51
|
+
filtered[name] = meta;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
await chrome.storage.local.set({ [PLUGINS_META_KEY]: filtered });
|
|
55
|
+
metaCache = filtered;
|
|
56
|
+
});
|
|
57
|
+
const VALID_TRUST_TIERS = new Set(['official', 'community', 'local']);
|
|
58
|
+
const isValidPluginMeta = (value) => {
|
|
59
|
+
if (typeof value !== 'object' || value === null)
|
|
60
|
+
return false;
|
|
61
|
+
const obj = value;
|
|
62
|
+
return (typeof obj.name === 'string' &&
|
|
63
|
+
typeof obj.version === 'string' &&
|
|
64
|
+
Array.isArray(obj.urlPatterns) &&
|
|
65
|
+
typeof obj.trustTier === 'string' &&
|
|
66
|
+
VALID_TRUST_TIERS.has(obj.trustTier) &&
|
|
67
|
+
Array.isArray(obj.tools));
|
|
68
|
+
};
|
|
69
|
+
const getAllPluginMeta = async () => {
|
|
70
|
+
if (metaCache !== null) {
|
|
71
|
+
return { ...metaCache };
|
|
72
|
+
}
|
|
73
|
+
const data = await chrome.storage.local.get(PLUGINS_META_KEY);
|
|
74
|
+
const index = data[PLUGINS_META_KEY];
|
|
75
|
+
if (!index || typeof index !== 'object') {
|
|
76
|
+
metaCache = {};
|
|
77
|
+
return {};
|
|
78
|
+
}
|
|
79
|
+
const validated = {};
|
|
80
|
+
for (const [key, value] of Object.entries(index)) {
|
|
81
|
+
if (isValidPluginMeta(value)) {
|
|
82
|
+
validated[key] = value;
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
console.warn(`[opentabs] Skipping corrupted plugin meta entry: ${key}`);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
metaCache = validated;
|
|
89
|
+
return { ...validated };
|
|
90
|
+
};
|
|
91
|
+
const getPluginMeta = async (pluginName) => {
|
|
92
|
+
const index = await getAllPluginMeta();
|
|
93
|
+
return index[pluginName];
|
|
94
|
+
};
|
|
95
|
+
/** Invalidate the in-memory cache, forcing the next read to hit chrome.storage.local. */
|
|
96
|
+
const invalidatePluginCache = () => {
|
|
97
|
+
metaCache = null;
|
|
98
|
+
};
|
|
99
|
+
export { storePluginsBatch, removePlugin, removePluginsBatch, getAllPluginMeta, getPluginMeta, invalidatePluginCache };
|
|
100
|
+
//# sourceMappingURL=plugin-storage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin-storage.js","sourceRoot":"","sources":["../src/plugin-storage.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sliding window rate limiter for browser commands.
|
|
3
|
+
*
|
|
4
|
+
* Tracks request timestamps per method and rejects requests that exceed the
|
|
5
|
+
* configured limit within the window. Timestamps older than the window are
|
|
6
|
+
* lazily pruned on each check to prevent unbounded memory growth.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Check whether a request for the given method is allowed under the rate limit.
|
|
10
|
+
* Returns true if the request is allowed, false if it should be rejected.
|
|
11
|
+
*
|
|
12
|
+
* @param now - Optional timestamp override (milliseconds). Defaults to Date.now().
|
|
13
|
+
* Exposed for deterministic testing without global Date mocks.
|
|
14
|
+
*/
|
|
15
|
+
export declare const checkRateLimit: (method: string, now?: number) => boolean;
|
|
16
|
+
/** Clear all rate limiter state. Exposed for test isolation. */
|
|
17
|
+
export declare const resetRateLimiter: () => void;
|
|
18
|
+
//# sourceMappingURL=rate-limiter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rate-limiter.d.ts","sourceRoot":"","sources":["../src/rate-limiter.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAiCH;;;;;;GAMG;AACH,eAAO,MAAM,cAAc,GAAI,QAAQ,MAAM,EAAE,MAAK,MAAmB,KAAG,OAiBzE,CAAC;AAEF,gEAAgE;AAChE,eAAO,MAAM,gBAAgB,QAAO,IAEnC,CAAC"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sliding window rate limiter for browser commands.
|
|
3
|
+
*
|
|
4
|
+
* Tracks request timestamps per method and rejects requests that exceed the
|
|
5
|
+
* configured limit within the window. Timestamps older than the window are
|
|
6
|
+
* lazily pruned on each check to prevent unbounded memory growth.
|
|
7
|
+
*/
|
|
8
|
+
/** Per-method rate limit configuration */
|
|
9
|
+
const METHOD_LIMITS = new Map([
|
|
10
|
+
// Expensive operations — tight limits
|
|
11
|
+
['browser.screenshotTab', { maxRequests: 2, windowMs: 1_000 }],
|
|
12
|
+
['browser.enableNetworkCapture', { maxRequests: 2, windowMs: 1_000 }],
|
|
13
|
+
['browser.executeScript', { maxRequests: 15, windowMs: 1_000 }],
|
|
14
|
+
// Tool dispatch — allow bursts of sequential/concurrent tool calls from agents
|
|
15
|
+
['tool.dispatch', { maxRequests: 30, windowMs: 1_000 }],
|
|
16
|
+
]);
|
|
17
|
+
/** Default limit for methods without a specific config */
|
|
18
|
+
const DEFAULT_LIMIT = { maxRequests: 20, windowMs: 1_000 };
|
|
19
|
+
/**
|
|
20
|
+
* Methods exempt from rate limiting. These are control/lifecycle methods that
|
|
21
|
+
* must always be processed (e.g., sync.full arrives once on connect, and
|
|
22
|
+
* extension.reload must never be delayed).
|
|
23
|
+
*/
|
|
24
|
+
const EXEMPT_METHODS = new Set(['extension.reload', 'sync.full', 'plugin.update', 'plugin.uninstall']);
|
|
25
|
+
/** Sliding window timestamps per method */
|
|
26
|
+
const methodTimestamps = new Map();
|
|
27
|
+
/**
|
|
28
|
+
* Check whether a request for the given method is allowed under the rate limit.
|
|
29
|
+
* Returns true if the request is allowed, false if it should be rejected.
|
|
30
|
+
*
|
|
31
|
+
* @param now - Optional timestamp override (milliseconds). Defaults to Date.now().
|
|
32
|
+
* Exposed for deterministic testing without global Date mocks.
|
|
33
|
+
*/
|
|
34
|
+
export const checkRateLimit = (method, now = Date.now()) => {
|
|
35
|
+
if (EXEMPT_METHODS.has(method))
|
|
36
|
+
return true;
|
|
37
|
+
const config = METHOD_LIMITS.get(method) ?? DEFAULT_LIMIT;
|
|
38
|
+
const cutoff = now - config.windowMs;
|
|
39
|
+
// Get existing timestamps and prune expired entries
|
|
40
|
+
const timestamps = (methodTimestamps.get(method) ?? []).filter(t => t > cutoff);
|
|
41
|
+
if (timestamps.length >= config.maxRequests) {
|
|
42
|
+
methodTimestamps.set(method, timestamps);
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
timestamps.push(now);
|
|
46
|
+
methodTimestamps.set(method, timestamps);
|
|
47
|
+
return true;
|
|
48
|
+
};
|
|
49
|
+
/** Clear all rate limiter state. Exposed for test isolation. */
|
|
50
|
+
export const resetRateLimiter = () => {
|
|
51
|
+
methodTimestamps.clear();
|
|
52
|
+
};
|
|
53
|
+
//# sourceMappingURL=rate-limiter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rate-limiter.js","sourceRoot":"","sources":["../src/rate-limiter.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AASH,0CAA0C;AAC1C,MAAM,aAAa,GAAyC,IAAI,GAAG,CAAC;IAClE,sCAAsC;IACtC,CAAC,uBAAuB,EAAE,EAAE,WAAW,EAAE,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;IAC9D,CAAC,8BAA8B,EAAE,EAAE,WAAW,EAAE,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;IACrE,CAAC,uBAAuB,EAAE,EAAE,WAAW,EAAE,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;IAE/D,+EAA+E;IAC/E,CAAC,eAAe,EAAE,EAAE,WAAW,EAAE,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;CACxD,CAAC,CAAC;AAEH,0DAA0D;AAC1D,MAAM,aAAa,GAAoB,EAAE,WAAW,EAAE,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;AAE5E;;;;GAIG;AACH,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC,CAAC,kBAAkB,EAAE,WAAW,EAAE,eAAe,EAAE,kBAAkB,CAAC,CAAC,CAAC;AAEvG,2CAA2C;AAC3C,MAAM,gBAAgB,GAAG,IAAI,GAAG,EAAoB,CAAC;AAErD;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,MAAc,EAAE,MAAc,IAAI,CAAC,GAAG,EAAE,EAAW,EAAE;IAClF,IAAI,cAAc,CAAC,GAAG,CAAC,MAAM,CAAC;QAAE,OAAO,IAAI,CAAC;IAE5C,MAAM,MAAM,GAAG,aAAa,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,aAAa,CAAC;IAC1D,MAAM,MAAM,GAAG,GAAG,GAAG,MAAM,CAAC,QAAQ,CAAC;IAErC,oDAAoD;IACpD,MAAM,UAAU,GAAG,CAAC,gBAAgB,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC;IAEhF,IAAI,UAAU,CAAC,MAAM,IAAI,MAAM,CAAC,WAAW,EAAE,CAAC;QAC5C,gBAAgB,CAAC,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;QACzC,OAAO,KAAK,CAAC;IACf,CAAC;IAED,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACrB,gBAAgB,CAAC,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IACzC,OAAO,IAAI,CAAC;AACd,CAAC,CAAC;AAEF,gEAAgE;AAChE,MAAM,CAAC,MAAM,gBAAgB,GAAG,GAAS,EAAE;IACzC,gBAAgB,CAAC,KAAK,EAAE,CAAC;AAC3B,CAAC,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Handle resource.read request from MCP server.
|
|
3
|
+
* Finds matching tabs, checks adapter readiness, executes the resource read,
|
|
4
|
+
* and returns the result.
|
|
5
|
+
*/
|
|
6
|
+
declare const handleResourceRead: (params: Record<string, unknown>, id: string | number) => Promise<void>;
|
|
7
|
+
/**
|
|
8
|
+
* Handle prompt.get request from MCP server.
|
|
9
|
+
* Finds matching tabs, checks adapter readiness, executes the prompt render,
|
|
10
|
+
* and returns the result.
|
|
11
|
+
*/
|
|
12
|
+
declare const handlePromptGet: (params: Record<string, unknown>, id: string | number) => Promise<void>;
|
|
13
|
+
export { handleResourceRead, handlePromptGet };
|
|
14
|
+
//# sourceMappingURL=resource-prompt-dispatch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resource-prompt-dispatch.d.ts","sourceRoot":"","sources":["../src/resource-prompt-dispatch.ts"],"names":[],"mappings":"AAwLA;;;;GAIG;AACH,QAAA,MAAM,kBAAkB,GAAU,QAAQ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,MAAM,GAAG,MAAM,KAAG,OAAO,CAAC,IAAI,CAiBpG,CAAC;AAEF;;;;GAIG;AACH,QAAA,MAAM,eAAe,GAAU,QAAQ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,MAAM,GAAG,MAAM,KAAG,OAAO,CAAC,IAAI,CAgCjG,CAAC;AAEF,OAAO,EAAE,kBAAkB,EAAE,eAAe,EAAE,CAAC"}
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
import { requireStringParam } from './browser-commands/helpers.js';
|
|
2
|
+
import { SCRIPT_TIMEOUT_MS } from './constants.js';
|
|
3
|
+
import { dispatchWithTabFallback, executeWithTimeout, resolvePlugin } from './dispatch-helpers.js';
|
|
4
|
+
import { JSONRPC_INVALID_PARAMS } from './json-rpc-errors.js';
|
|
5
|
+
import { sendToServer } from './messaging.js';
|
|
6
|
+
/**
|
|
7
|
+
* Execute a resource read on a specific tab. Returns the structured result
|
|
8
|
+
* from the adapter script, or throws if the tab is inaccessible.
|
|
9
|
+
*/
|
|
10
|
+
const executeResourceReadOnTab = async (tabId, pluginName, resourceUri) => {
|
|
11
|
+
const scriptPromise = chrome.scripting.executeScript({
|
|
12
|
+
target: { tabId },
|
|
13
|
+
world: 'MAIN',
|
|
14
|
+
func: async (pName, uri) => {
|
|
15
|
+
const ot = globalThis.__openTabs;
|
|
16
|
+
const adapter = ot?.adapters?.[pName];
|
|
17
|
+
if (!adapter || typeof adapter !== 'object') {
|
|
18
|
+
return { type: 'error', code: -32002, message: `Adapter "${pName}" not injected or not ready` };
|
|
19
|
+
}
|
|
20
|
+
if (!Object.isFrozen(adapter)) {
|
|
21
|
+
return {
|
|
22
|
+
type: 'error',
|
|
23
|
+
code: -32002,
|
|
24
|
+
message: `Adapter "${pName}" failed integrity check (not frozen)`,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
if (typeof adapter.isReady !== 'function') {
|
|
28
|
+
return { type: 'error', code: -32002, message: `Adapter "${pName}" has no isReady function` };
|
|
29
|
+
}
|
|
30
|
+
let ready;
|
|
31
|
+
try {
|
|
32
|
+
ready = await adapter.isReady();
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
return { type: 'error', code: -32002, message: `Adapter "${pName}" isReady() threw an error` };
|
|
36
|
+
}
|
|
37
|
+
if (!ready) {
|
|
38
|
+
return {
|
|
39
|
+
type: 'error',
|
|
40
|
+
code: -32002,
|
|
41
|
+
message: `Plugin "${pName}" is not ready (state: unavailable)`,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
if (!Array.isArray(adapter.resources)) {
|
|
45
|
+
return { type: 'error', code: -32603, message: `Adapter "${pName}" has no resources array` };
|
|
46
|
+
}
|
|
47
|
+
const resource = adapter.resources.find((r) => r.uri === uri);
|
|
48
|
+
if (!resource || typeof resource.read !== 'function') {
|
|
49
|
+
return { type: 'error', code: -32603, message: `Resource "${uri}" not found in adapter "${pName}"` };
|
|
50
|
+
}
|
|
51
|
+
try {
|
|
52
|
+
const output = await resource.read(uri);
|
|
53
|
+
return { type: 'success', output };
|
|
54
|
+
}
|
|
55
|
+
catch (err) {
|
|
56
|
+
const caughtError = err;
|
|
57
|
+
return {
|
|
58
|
+
type: 'error',
|
|
59
|
+
code: -32603,
|
|
60
|
+
message: caughtError.message ?? 'Resource read failed',
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
args: [pluginName, resourceUri],
|
|
65
|
+
});
|
|
66
|
+
return executeWithTimeout(scriptPromise, SCRIPT_TIMEOUT_MS, 'No result from resource read');
|
|
67
|
+
};
|
|
68
|
+
/**
|
|
69
|
+
* Execute a prompt render on a specific tab. Returns the structured result
|
|
70
|
+
* from the adapter script, or throws if the tab is inaccessible.
|
|
71
|
+
*/
|
|
72
|
+
const executePromptGetOnTab = async (tabId, pluginName, promptName, promptArgs) => {
|
|
73
|
+
const scriptPromise = chrome.scripting.executeScript({
|
|
74
|
+
target: { tabId },
|
|
75
|
+
world: 'MAIN',
|
|
76
|
+
func: async (pName, pPromptName, pArgs) => {
|
|
77
|
+
const ot = globalThis.__openTabs;
|
|
78
|
+
const adapter = ot?.adapters?.[pName];
|
|
79
|
+
if (!adapter || typeof adapter !== 'object') {
|
|
80
|
+
return { type: 'error', code: -32002, message: `Adapter "${pName}" not injected or not ready` };
|
|
81
|
+
}
|
|
82
|
+
if (!Object.isFrozen(adapter)) {
|
|
83
|
+
return {
|
|
84
|
+
type: 'error',
|
|
85
|
+
code: -32002,
|
|
86
|
+
message: `Adapter "${pName}" failed integrity check (not frozen)`,
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
if (typeof adapter.isReady !== 'function') {
|
|
90
|
+
return { type: 'error', code: -32002, message: `Adapter "${pName}" has no isReady function` };
|
|
91
|
+
}
|
|
92
|
+
let ready;
|
|
93
|
+
try {
|
|
94
|
+
ready = await adapter.isReady();
|
|
95
|
+
}
|
|
96
|
+
catch {
|
|
97
|
+
return { type: 'error', code: -32002, message: `Adapter "${pName}" isReady() threw an error` };
|
|
98
|
+
}
|
|
99
|
+
if (!ready) {
|
|
100
|
+
return {
|
|
101
|
+
type: 'error',
|
|
102
|
+
code: -32002,
|
|
103
|
+
message: `Plugin "${pName}" is not ready (state: unavailable)`,
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
if (!Array.isArray(adapter.prompts)) {
|
|
107
|
+
return { type: 'error', code: -32603, message: `Adapter "${pName}" has no prompts array` };
|
|
108
|
+
}
|
|
109
|
+
const prompt = adapter.prompts.find((p) => p.name === pPromptName);
|
|
110
|
+
if (!prompt || typeof prompt.render !== 'function') {
|
|
111
|
+
return {
|
|
112
|
+
type: 'error',
|
|
113
|
+
code: -32603,
|
|
114
|
+
message: `Prompt "${pPromptName}" not found in adapter "${pName}"`,
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
try {
|
|
118
|
+
const output = await prompt.render(pArgs);
|
|
119
|
+
return { type: 'success', output };
|
|
120
|
+
}
|
|
121
|
+
catch (err) {
|
|
122
|
+
const caughtError = err;
|
|
123
|
+
return {
|
|
124
|
+
type: 'error',
|
|
125
|
+
code: -32603,
|
|
126
|
+
message: caughtError.message ?? 'Prompt render failed',
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
},
|
|
130
|
+
args: [pluginName, promptName, promptArgs],
|
|
131
|
+
});
|
|
132
|
+
return executeWithTimeout(scriptPromise, SCRIPT_TIMEOUT_MS, 'No result from prompt render');
|
|
133
|
+
};
|
|
134
|
+
/**
|
|
135
|
+
* Handle resource.read request from MCP server.
|
|
136
|
+
* Finds matching tabs, checks adapter readiness, executes the resource read,
|
|
137
|
+
* and returns the result.
|
|
138
|
+
*/
|
|
139
|
+
const handleResourceRead = async (params, id) => {
|
|
140
|
+
const pluginName = requireStringParam(params, 'plugin', id);
|
|
141
|
+
if (!pluginName)
|
|
142
|
+
return;
|
|
143
|
+
const resourceUri = requireStringParam(params, 'uri', id);
|
|
144
|
+
if (!resourceUri)
|
|
145
|
+
return;
|
|
146
|
+
const plugin = await resolvePlugin(pluginName, id);
|
|
147
|
+
if (!plugin)
|
|
148
|
+
return;
|
|
149
|
+
await dispatchWithTabFallback({
|
|
150
|
+
id,
|
|
151
|
+
pluginName,
|
|
152
|
+
plugin,
|
|
153
|
+
operationName: 'resource read',
|
|
154
|
+
executeOnTab: tabId => executeResourceReadOnTab(tabId, pluginName, resourceUri),
|
|
155
|
+
});
|
|
156
|
+
};
|
|
157
|
+
/**
|
|
158
|
+
* Handle prompt.get request from MCP server.
|
|
159
|
+
* Finds matching tabs, checks adapter readiness, executes the prompt render,
|
|
160
|
+
* and returns the result.
|
|
161
|
+
*/
|
|
162
|
+
const handlePromptGet = async (params, id) => {
|
|
163
|
+
const pluginName = requireStringParam(params, 'plugin', id);
|
|
164
|
+
if (!pluginName)
|
|
165
|
+
return;
|
|
166
|
+
const promptName = requireStringParam(params, 'prompt', id);
|
|
167
|
+
if (!promptName)
|
|
168
|
+
return;
|
|
169
|
+
const rawArgs = params.arguments;
|
|
170
|
+
if (rawArgs !== undefined && rawArgs !== null && (typeof rawArgs !== 'object' || Array.isArray(rawArgs))) {
|
|
171
|
+
sendToServer({
|
|
172
|
+
jsonrpc: '2.0',
|
|
173
|
+
error: { code: JSONRPC_INVALID_PARAMS, message: 'Invalid "arguments" param (expected object)' },
|
|
174
|
+
id,
|
|
175
|
+
});
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
const rawObj = (rawArgs ?? {});
|
|
179
|
+
const promptArgs = {};
|
|
180
|
+
for (const [key, val] of Object.entries(rawObj)) {
|
|
181
|
+
promptArgs[key] = String(val);
|
|
182
|
+
}
|
|
183
|
+
const plugin = await resolvePlugin(pluginName, id);
|
|
184
|
+
if (!plugin)
|
|
185
|
+
return;
|
|
186
|
+
await dispatchWithTabFallback({
|
|
187
|
+
id,
|
|
188
|
+
pluginName,
|
|
189
|
+
plugin,
|
|
190
|
+
operationName: 'prompt get',
|
|
191
|
+
executeOnTab: tabId => executePromptGetOnTab(tabId, pluginName, promptName, promptArgs),
|
|
192
|
+
});
|
|
193
|
+
};
|
|
194
|
+
export { handleResourceRead, handlePromptGet };
|
|
195
|
+
//# sourceMappingURL=resource-prompt-dispatch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resource-prompt-dispatch.js","sourceRoot":"","sources":["../src/resource-prompt-dispatch.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sanitize error messages before returning them to external clients.
|
|
3
|
+
* Strips absolute file paths, URLs, localhost references, and IP addresses
|
|
4
|
+
* to prevent leaking internal system details. Truncates to 500 characters.
|
|
5
|
+
*/
|
|
6
|
+
declare const sanitizeErrorMessage: (message: string) => string;
|
|
7
|
+
export { sanitizeErrorMessage };
|
|
8
|
+
//# sourceMappingURL=sanitize-error.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sanitize-error.d.ts","sourceRoot":"","sources":["../src/sanitize-error.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,QAAA,MAAM,oBAAoB,GAAI,SAAS,MAAM,KAAG,MAkB/C,CAAC;AAEF,OAAO,EAAE,oBAAoB,EAAE,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sanitize error messages before returning them to external clients.
|
|
3
|
+
* Strips absolute file paths, URLs, localhost references, and IP addresses
|
|
4
|
+
* to prevent leaking internal system details. Truncates to 500 characters.
|
|
5
|
+
*/
|
|
6
|
+
const MAX_LENGTH = 500;
|
|
7
|
+
const sanitizeErrorMessage = (message) => {
|
|
8
|
+
let sanitized = message
|
|
9
|
+
// Windows absolute paths: C:\path\to\file or C:/path/to/file
|
|
10
|
+
.replace(/[a-z]:[/\\][^\s,;)}\]]+/gi, '[PATH]')
|
|
11
|
+
// Unix absolute paths: /path/to/file (at least 2 segments to avoid false positives like "/")
|
|
12
|
+
.replace(/\/[a-z0-9._-]+(?:\/[a-z0-9._-]+)+/gi, '[PATH]')
|
|
13
|
+
// Full URLs with protocol
|
|
14
|
+
.replace(/https?:\/\/[^\s,;)}\]]+/gi, '[URL]')
|
|
15
|
+
// localhost with port
|
|
16
|
+
.replace(/localhost:\d+/gi, '[LOCALHOST]')
|
|
17
|
+
// IPv4 addresses
|
|
18
|
+
.replace(/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/g, '[IP]');
|
|
19
|
+
if (sanitized.length > MAX_LENGTH) {
|
|
20
|
+
sanitized = sanitized.slice(0, MAX_LENGTH - 3) + '...';
|
|
21
|
+
}
|
|
22
|
+
return sanitized;
|
|
23
|
+
};
|
|
24
|
+
export { sanitizeErrorMessage };
|
|
25
|
+
//# sourceMappingURL=sanitize-error.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sanitize-error.js","sourceRoot":"","sources":["../src/sanitize-error.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,UAAU,GAAG,GAAG,CAAC;AAEvB,MAAM,oBAAoB,GAAG,CAAC,OAAe,EAAU,EAAE;IACvD,IAAI,SAAS,GAAG,OAAO;QACrB,6DAA6D;SAC5D,OAAO,CAAC,2BAA2B,EAAE,QAAQ,CAAC;QAC/C,6FAA6F;SAC5F,OAAO,CAAC,qCAAqC,EAAE,QAAQ,CAAC;QACzD,0BAA0B;SACzB,OAAO,CAAC,2BAA2B,EAAE,OAAO,CAAC;QAC9C,sBAAsB;SACrB,OAAO,CAAC,iBAAiB,EAAE,aAAa,CAAC;QAC1C,iBAAiB;SAChB,OAAO,CAAC,qCAAqC,EAAE,MAAM,CAAC,CAAC;IAE1D,IAAI,SAAS,CAAC,MAAM,GAAG,UAAU,EAAE,CAAC;QAClC,SAAS,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,UAAU,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC;IACzD,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC,CAAC;AAEF,OAAO,EAAE,oBAAoB,EAAE,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SVG sanitizer for plugin icons rendered via dangerouslySetInnerHTML.
|
|
3
|
+
*
|
|
4
|
+
* Uses an element/attribute allowlist approach — only known-safe SVG elements
|
|
5
|
+
* and attributes are preserved. Everything else is stripped. This prevents XSS
|
|
6
|
+
* vectors including <script>, <foreignObject>, event handler attributes,
|
|
7
|
+
* javascript: URIs, and CSS-based attacks.
|
|
8
|
+
*
|
|
9
|
+
* Runs in the side panel context (browser DOM available) and is also testable
|
|
10
|
+
* in Bun's test runner (no DOM dependency — pure string processing).
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* Sanitize an SVG string by stripping all elements and attributes not on the allowlist.
|
|
14
|
+
*
|
|
15
|
+
* Returns the sanitized SVG string safe for use with dangerouslySetInnerHTML.
|
|
16
|
+
* Returns an empty string for non-string or empty input.
|
|
17
|
+
*/
|
|
18
|
+
declare const sanitizeSvg: (svg: string) => string;
|
|
19
|
+
export { sanitizeSvg };
|
|
20
|
+
//# sourceMappingURL=sanitize-svg.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sanitize-svg.d.ts","sourceRoot":"","sources":["../src/sanitize-svg.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAiPH;;;;;GAKG;AACH,QAAA,MAAM,WAAW,GAAI,KAAK,MAAM,KAAG,MA2ElC,CAAC;AAEF,OAAO,EAAE,WAAW,EAAE,CAAC"}
|