opendevbrowser 0.0.11 → 0.0.12
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/README.md +74 -1
- package/dist/chunk-WTFSMBVH.js +2815 -0
- package/dist/chunk-WTFSMBVH.js.map +1 -0
- package/dist/cli/index.js +1589 -71
- package/dist/cli/index.js.map +1 -1
- package/dist/index.js +164 -2804
- package/dist/index.js.map +1 -1
- package/dist/opendevbrowser.js +164 -2804
- package/dist/opendevbrowser.js.map +1 -1
- package/extension/dist/background.js +121 -0
- package/extension/dist/popup.js +37 -5
- package/extension/dist/relay-settings.js +2 -1
- package/extension/icons/icon128.png +0 -0
- package/extension/icons/icon16.png +0 -0
- package/extension/icons/icon32.png +0 -0
- package/extension/icons/icon48.png +0 -0
- package/extension/manifest.json +1 -1
- package/extension/popup.html +326 -66
- package/package.json +1 -1
- package/skills/AGENTS.md +1 -0
- package/dist/chunk-R5VUZEUU.js +0 -128
- package/dist/chunk-R5VUZEUU.js.map +0 -1
|
@@ -1,5 +1,126 @@
|
|
|
1
1
|
import { ConnectionManager } from "./services/ConnectionManager.js";
|
|
2
|
+
import { DEFAULT_AUTO_CONNECT, DEFAULT_AUTO_PAIR, DEFAULT_DISCOVERY_PORT, DEFAULT_PAIRING_ENABLED, DEFAULT_RELAY_PORT } from "./relay-settings.js";
|
|
2
3
|
const connection = new ConnectionManager();
|
|
4
|
+
let autoConnectInFlight = false;
|
|
5
|
+
const updateBadge = (status) => {
|
|
6
|
+
const isConnected = status === "connected";
|
|
7
|
+
chrome.action.setBadgeText({ text: isConnected ? "ON" : "OFF" });
|
|
8
|
+
chrome.action.setBadgeBackgroundColor({
|
|
9
|
+
color: isConnected ? "#20d5c6" : "#5b667a"
|
|
10
|
+
});
|
|
11
|
+
};
|
|
12
|
+
const parsePort = (value) => {
|
|
13
|
+
if (typeof value === "number" && Number.isInteger(value) && value > 0 && value <= 65535) {
|
|
14
|
+
return value;
|
|
15
|
+
}
|
|
16
|
+
if (typeof value === "string" && value.trim()) {
|
|
17
|
+
const parsed = Number(value);
|
|
18
|
+
if (Number.isInteger(parsed) && parsed > 0 && parsed <= 65535) {
|
|
19
|
+
return parsed;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
return null;
|
|
23
|
+
};
|
|
24
|
+
const fetchRelayConfig = async (port) => {
|
|
25
|
+
try {
|
|
26
|
+
const response = await fetch(`http://127.0.0.1:${port}/config`, {
|
|
27
|
+
method: "GET",
|
|
28
|
+
headers: { "Accept": "application/json" }
|
|
29
|
+
});
|
|
30
|
+
if (!response.ok) {
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
const data = await response.json();
|
|
34
|
+
const relayPort = parsePort(data.relayPort);
|
|
35
|
+
if (!relayPort) {
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
const pairingRequired = typeof data.pairingRequired === "boolean" ? data.pairingRequired : true;
|
|
39
|
+
return { relayPort, pairingRequired };
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
const fetchTokenFromPlugin = async (port) => {
|
|
46
|
+
try {
|
|
47
|
+
const response = await fetch(`http://127.0.0.1:${port}/pair`, {
|
|
48
|
+
method: "GET",
|
|
49
|
+
headers: { "Accept": "application/json" }
|
|
50
|
+
});
|
|
51
|
+
if (!response.ok) {
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
const data = await response.json();
|
|
55
|
+
return typeof data.token === "string" ? data.token : null;
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
const attemptAutoConnect = async () => {
|
|
62
|
+
const data = await new Promise((resolve) => {
|
|
63
|
+
chrome.storage.local.get(["autoConnect", "autoPair", "pairingEnabled", "pairingToken", "relayPort"], (items) => {
|
|
64
|
+
resolve(items);
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
const autoConnect = typeof data.autoConnect === "boolean" ? data.autoConnect : DEFAULT_AUTO_CONNECT;
|
|
68
|
+
if (!autoConnect || connection.getStatus() === "connected") {
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
const autoPair = typeof data.autoPair === "boolean" ? data.autoPair : DEFAULT_AUTO_PAIR;
|
|
72
|
+
const pairingEnabled = typeof data.pairingEnabled === "boolean" ? data.pairingEnabled : DEFAULT_PAIRING_ENABLED;
|
|
73
|
+
if (autoPair && pairingEnabled) {
|
|
74
|
+
const config = await fetchRelayConfig(DEFAULT_DISCOVERY_PORT);
|
|
75
|
+
const relayPort = config?.relayPort ?? parsePort(data.relayPort) ?? DEFAULT_RELAY_PORT;
|
|
76
|
+
if (config?.relayPort) {
|
|
77
|
+
chrome.storage.local.set({ relayPort: config.relayPort });
|
|
78
|
+
}
|
|
79
|
+
const pairingRequired = config?.pairingRequired ?? true;
|
|
80
|
+
if (pairingRequired) {
|
|
81
|
+
const fetchedToken = await fetchTokenFromPlugin(relayPort);
|
|
82
|
+
if (fetchedToken) {
|
|
83
|
+
chrome.storage.local.set({ pairingToken: fetchedToken });
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
await connection.connect();
|
|
91
|
+
};
|
|
92
|
+
const autoConnect = async () => {
|
|
93
|
+
if (autoConnectInFlight) {
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
autoConnectInFlight = true;
|
|
97
|
+
try {
|
|
98
|
+
await attemptAutoConnect();
|
|
99
|
+
}
|
|
100
|
+
catch {
|
|
101
|
+
connection.disconnect();
|
|
102
|
+
}
|
|
103
|
+
finally {
|
|
104
|
+
autoConnectInFlight = false;
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
connection.onStatus(updateBadge);
|
|
108
|
+
updateBadge(connection.getStatus());
|
|
109
|
+
chrome.runtime.onStartup.addListener(() => {
|
|
110
|
+
autoConnect().catch(() => { });
|
|
111
|
+
});
|
|
112
|
+
chrome.runtime.onInstalled.addListener(() => {
|
|
113
|
+
autoConnect().catch(() => { });
|
|
114
|
+
});
|
|
115
|
+
autoConnect().catch(() => { });
|
|
116
|
+
chrome.storage.onChanged.addListener((changes, area) => {
|
|
117
|
+
if (area !== "local") {
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
if (changes.autoConnect?.newValue === true) {
|
|
121
|
+
autoConnect().catch(() => { });
|
|
122
|
+
}
|
|
123
|
+
});
|
|
3
124
|
chrome.runtime.onMessage.addListener((message, _sender, sendResponse) => {
|
|
4
125
|
const respond = (status) => {
|
|
5
126
|
sendResponse(status);
|
package/extension/dist/popup.js
CHANGED
|
@@ -1,23 +1,32 @@
|
|
|
1
|
-
import { DEFAULT_AUTO_PAIR, DEFAULT_DISCOVERY_PORT, DEFAULT_PAIRING_ENABLED, DEFAULT_PAIRING_TOKEN, DEFAULT_RELAY_PORT } from "./relay-settings.js";
|
|
1
|
+
import { DEFAULT_AUTO_CONNECT, DEFAULT_AUTO_PAIR, DEFAULT_DISCOVERY_PORT, DEFAULT_PAIRING_ENABLED, DEFAULT_PAIRING_TOKEN, DEFAULT_RELAY_PORT } from "./relay-settings.js";
|
|
2
2
|
const statusEl = document.getElementById("status");
|
|
3
3
|
const statusIndicator = document.getElementById("statusIndicator");
|
|
4
|
+
const statusPill = document.getElementById("statusPill");
|
|
5
|
+
const statusNote = document.getElementById("statusNote");
|
|
4
6
|
const toggleButton = document.getElementById("toggle");
|
|
5
7
|
const relayPortInput = document.getElementById("relayPort");
|
|
6
8
|
const pairingTokenInput = document.getElementById("pairingToken");
|
|
7
9
|
const pairingEnabledInput = document.getElementById("pairingEnabled");
|
|
8
10
|
const autoPairInput = document.getElementById("autoPair");
|
|
9
|
-
|
|
11
|
+
const autoConnectInput = document.getElementById("autoConnect");
|
|
12
|
+
if (!statusEl || !statusIndicator || !statusPill || !statusNote || !toggleButton || !relayPortInput || !pairingTokenInput || !pairingEnabledInput || !autoPairInput || !autoConnectInput) {
|
|
10
13
|
throw new Error("Popup DOM missing required elements");
|
|
11
14
|
}
|
|
15
|
+
const defaultNote = "Local relay only. Tokens stay on-device.";
|
|
16
|
+
const setNote = (message = defaultNote) => {
|
|
17
|
+
statusNote.textContent = message;
|
|
18
|
+
};
|
|
12
19
|
const setStatus = (status) => {
|
|
13
20
|
const isConnected = status === "connected";
|
|
14
21
|
statusEl.textContent = isConnected ? "Connected" : "Disconnected";
|
|
15
22
|
toggleButton.textContent = isConnected ? "Disconnect" : "Connect";
|
|
16
23
|
if (isConnected) {
|
|
17
24
|
statusIndicator.classList.add("connected");
|
|
25
|
+
statusPill.classList.add("connected");
|
|
18
26
|
}
|
|
19
27
|
else {
|
|
20
28
|
statusIndicator.classList.remove("connected");
|
|
29
|
+
statusPill.classList.remove("connected");
|
|
21
30
|
}
|
|
22
31
|
};
|
|
23
32
|
const sendMessage = (message) => {
|
|
@@ -30,6 +39,7 @@ const sendMessage = (message) => {
|
|
|
30
39
|
const refreshStatus = async () => {
|
|
31
40
|
const response = await sendMessage({ type: "status" });
|
|
32
41
|
setStatus(response.status);
|
|
42
|
+
setNote();
|
|
33
43
|
};
|
|
34
44
|
const fetchTokenFromPlugin = async (port) => {
|
|
35
45
|
try {
|
|
@@ -89,23 +99,29 @@ const applyRelayPort = (port) => {
|
|
|
89
99
|
};
|
|
90
100
|
const loadSettings = async () => {
|
|
91
101
|
const data = await new Promise((resolve) => {
|
|
92
|
-
chrome.storage.local.get(["pairingToken", "pairingEnabled", "relayPort", "autoPair"], (items) => {
|
|
102
|
+
chrome.storage.local.get(["pairingToken", "pairingEnabled", "relayPort", "autoPair", "autoConnect"], (items) => {
|
|
93
103
|
resolve(items);
|
|
94
104
|
});
|
|
95
105
|
});
|
|
96
106
|
const autoPair = typeof data.autoPair === "boolean" ? data.autoPair : DEFAULT_AUTO_PAIR;
|
|
107
|
+
const autoConnect = typeof data.autoConnect === "boolean" ? data.autoConnect : DEFAULT_AUTO_CONNECT;
|
|
97
108
|
const pairingEnabled = typeof data.pairingEnabled === "boolean"
|
|
98
109
|
? data.pairingEnabled
|
|
99
110
|
: DEFAULT_PAIRING_ENABLED;
|
|
100
111
|
const rawToken = typeof data.pairingToken === "string" ? data.pairingToken.trim() : "";
|
|
101
112
|
const tokenValue = pairingEnabled ? (rawToken || DEFAULT_PAIRING_TOKEN || "") : rawToken;
|
|
102
113
|
const portValue = parsePort(data.relayPort) ?? DEFAULT_RELAY_PORT;
|
|
114
|
+
autoConnectInput.checked = autoConnect;
|
|
103
115
|
autoPairInput.checked = autoPair;
|
|
104
116
|
pairingEnabledInput.checked = pairingEnabled;
|
|
105
117
|
pairingTokenInput.disabled = !pairingEnabled || autoPair;
|
|
106
118
|
pairingTokenInput.value = tokenValue;
|
|
107
119
|
relayPortInput.value = Number.isInteger(portValue) ? String(portValue) : String(DEFAULT_RELAY_PORT);
|
|
120
|
+
setNote();
|
|
108
121
|
const updates = {};
|
|
122
|
+
if (typeof data.autoConnect !== "boolean") {
|
|
123
|
+
updates.autoConnect = autoConnect;
|
|
124
|
+
}
|
|
109
125
|
if (typeof data.autoPair !== "boolean") {
|
|
110
126
|
updates.autoPair = autoPair;
|
|
111
127
|
}
|
|
@@ -118,6 +134,7 @@ const loadSettings = async () => {
|
|
|
118
134
|
};
|
|
119
135
|
const toggle = async () => {
|
|
120
136
|
const isConnected = statusEl.textContent === "Connected";
|
|
137
|
+
setNote();
|
|
121
138
|
if (!isConnected && autoPairInput.checked && pairingEnabledInput.checked) {
|
|
122
139
|
const config = await fetchRelayConfig(DEFAULT_DISCOVERY_PORT);
|
|
123
140
|
const relayPort = config?.relayPort ?? parsePort(relayPortInput.value) ?? DEFAULT_RELAY_PORT;
|
|
@@ -132,7 +149,8 @@ const toggle = async () => {
|
|
|
132
149
|
chrome.storage.local.set({ pairingToken: fetchedToken });
|
|
133
150
|
}
|
|
134
151
|
else {
|
|
135
|
-
|
|
152
|
+
setStatus("disconnected");
|
|
153
|
+
setNote("Auto-pair failed. Start the plugin and retry.");
|
|
136
154
|
setTimeout(() => refreshStatus(), 2000);
|
|
137
155
|
return;
|
|
138
156
|
}
|
|
@@ -142,6 +160,7 @@ const toggle = async () => {
|
|
|
142
160
|
type: isConnected ? "disconnect" : "connect"
|
|
143
161
|
});
|
|
144
162
|
setStatus(response.status);
|
|
163
|
+
setNote();
|
|
145
164
|
};
|
|
146
165
|
toggleButton.addEventListener("click", () => {
|
|
147
166
|
toggle().catch(() => {
|
|
@@ -156,7 +175,17 @@ autoPairInput.addEventListener("change", () => {
|
|
|
156
175
|
pairingTokenInput.placeholder = "Will be fetched automatically";
|
|
157
176
|
}
|
|
158
177
|
else {
|
|
159
|
-
pairingTokenInput.placeholder = "Enter token or enable
|
|
178
|
+
pairingTokenInput.placeholder = "Enter token or enable auto-pair";
|
|
179
|
+
}
|
|
180
|
+
});
|
|
181
|
+
autoConnectInput.addEventListener("change", () => {
|
|
182
|
+
const enabled = autoConnectInput.checked;
|
|
183
|
+
chrome.storage.local.set({ autoConnect: enabled });
|
|
184
|
+
if (enabled && statusEl.textContent !== "Connected") {
|
|
185
|
+
toggle().catch(() => {
|
|
186
|
+
setStatus("disconnected");
|
|
187
|
+
setNote();
|
|
188
|
+
});
|
|
160
189
|
}
|
|
161
190
|
});
|
|
162
191
|
pairingTokenInput.addEventListener("input", () => {
|
|
@@ -187,11 +216,14 @@ relayPortInput.addEventListener("input", () => {
|
|
|
187
216
|
});
|
|
188
217
|
refreshStatus().catch(() => {
|
|
189
218
|
setStatus("disconnected");
|
|
219
|
+
setNote();
|
|
190
220
|
});
|
|
191
221
|
loadSettings().catch(() => {
|
|
222
|
+
autoConnectInput.checked = DEFAULT_AUTO_CONNECT;
|
|
192
223
|
autoPairInput.checked = DEFAULT_AUTO_PAIR;
|
|
193
224
|
pairingEnabledInput.checked = DEFAULT_PAIRING_ENABLED;
|
|
194
225
|
pairingTokenInput.disabled = !DEFAULT_PAIRING_ENABLED;
|
|
195
226
|
pairingTokenInput.value = DEFAULT_PAIRING_TOKEN || "";
|
|
196
227
|
relayPortInput.value = String(DEFAULT_RELAY_PORT);
|
|
228
|
+
setNote();
|
|
197
229
|
});
|
|
@@ -2,4 +2,5 @@ export const DEFAULT_RELAY_PORT = 8787;
|
|
|
2
2
|
export const DEFAULT_DISCOVERY_PORT = 8787;
|
|
3
3
|
export const DEFAULT_PAIRING_TOKEN = null;
|
|
4
4
|
export const DEFAULT_PAIRING_ENABLED = true;
|
|
5
|
-
export const DEFAULT_AUTO_PAIR =
|
|
5
|
+
export const DEFAULT_AUTO_PAIR = true;
|
|
6
|
+
export const DEFAULT_AUTO_CONNECT = true;
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/extension/manifest.json
CHANGED