Skip to content

Commit e851042

Browse files
committed
Add Prettier config and improve extension stability
- Add .prettierrc with 80 character line width - Update manifest permissions and remove activeTab requirement - Implement service worker heartbeat to prevent termination - Remove ping/pong connection health mechanism - Sort mutations by submission time in ListView - Update memory-bank submodule and dependencies
1 parent 75eb49e commit e851042

11 files changed

Lines changed: 70 additions & 100 deletions

File tree

.prettierrc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"printWidth": 80
3+
}

memory-bank

package-lock.json

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

public/manifest.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
{
2+
"$schema": "https://json.schemastore.org/chrome-manifest",
23
"manifest_version": 3,
34
"name": "TanStack Query DevTools",
45
"version": "0.6.0",
56
"description": "Chrome DevTools extension for debugging TanStack Query applications. Inspect queries, mutations, and cache state in real-time.",
6-
"permissions": ["activeTab"],
7+
"permissions": ["storage"],
78
"devtools_page": "devtools.html",
89
"content_scripts": [
910
{
1011
"matches": ["<all_urls>"],
11-
"js": ["content.js"],
12-
"run_at": "document_start"
12+
"js": ["content.js"]
1313
}
1414
],
1515
"background": {

src/background/background.ts

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ interface TabConnection {
99
inspectedTabId: number;
1010
connectionId: string;
1111
connectedAt: number;
12-
lastPing: number;
1312
}
1413

1514
// Track DevTools connections per inspected tab
@@ -59,7 +58,6 @@ chrome.runtime.onConnect.addListener((port) => {
5958
inspectedTabId,
6059
connectionId,
6160
connectedAt: Date.now(),
62-
lastPing: Date.now(),
6361
};
6462

6563
tabConnections.set(inspectedTabId, connection);
@@ -90,19 +88,6 @@ chrome.runtime.onConnect.addListener((port) => {
9088
return;
9189
}
9290

93-
// Handle ping messages for connection health
94-
if (message.type === "PING" && inspectedTabId) {
95-
const connection = tabConnections.get(inspectedTabId);
96-
if (connection) {
97-
connection.lastPing = Date.now();
98-
port.postMessage({
99-
type: "PONG",
100-
timestamp: Date.now(),
101-
});
102-
}
103-
return;
104-
}
105-
10691
// Forward other messages to the inspected tab's content script
10792
if (inspectedTabId && message.type) {
10893
chrome.tabs
@@ -208,6 +193,13 @@ chrome.tabs.onRemoved.addListener((tabId) => {
208193
tabConnections.delete(tabId);
209194
});
210195

196+
// https://developer.chrome.com/docs/extensions/develop/migrate/to-service-workers#keep_a_service_worker_alive_continuously
197+
setInterval(
198+
() =>
199+
void chrome.storage.local.set({ "last-heartbeat": new Date().getTime() }),
200+
20000,
201+
);
202+
211203
// Extension lifecycle
212204
chrome.runtime.onStartup.addListener(() => {});
213205

src/components/layout/ListView.tsx

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,9 +63,13 @@ export function ListView({
6363
if (aQuery.isActive && !bQuery.isActive) return -1;
6464
return 0;
6565
})
66-
: filteredData;
66+
: [...filteredData].sort((a, b) => {
67+
const aMutation = a as MutationData;
68+
const bMutation = b as MutationData;
69+
70+
return bMutation.submittedAt - aMutation.submittedAt;
71+
});
6772

68-
// Update keyboard navigation item count when sorted data changes
6973
useEffect(() => {
7074
if (currentView === "queries" && queryKeyboardNavigation) {
7175
queryKeyboardNavigation.updateItemCount(sortedData.length);
@@ -126,7 +130,7 @@ export function ListView({
126130
No mutations found.
127131
</div>
128132
) : (
129-
filteredData.map((item, index) => {
133+
sortedData.map((item, index) => {
130134
const mutation = item as MutationData;
131135
const originalIndex = mutations.indexOf(mutation);
132136
return (

src/hooks/useConnection.ts

Lines changed: 11 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ export const useConnection = (): UseConnectionReturn => {
1919
>(null);
2020
const [queries, setQueries] = useState<QueryData[]>([]);
2121
const [mutations, setMutations] = useState<MutationData[]>([]);
22-
const [reconnectAttempts, setReconnectAttempts] = useState(0);
2322
// Track artificial states triggered by DevTools
2423
const [artificialStates, setArtificialStates] = useState<
2524
Map<string, "loading" | "error">
@@ -28,7 +27,6 @@ export const useConnection = (): UseConnectionReturn => {
2827
// Connection management
2928
const portRef = useRef<chrome.runtime.Port | null>(null);
3029
const reconnectTimeoutRef = useRef<NodeJS.Timeout | null>(null);
31-
const heartbeatIntervalRef = useRef<NodeJS.Timeout | null>(null);
3230

3331
// Send message function
3432
const sendMessage = useCallback((message: unknown) => {
@@ -58,28 +56,7 @@ export const useConnection = (): UseConnectionReturn => {
5856
});
5957

6058
port.onMessage.addListener((message) => {
61-
if (message.type === "CONNECTION_ESTABLISHED") {
62-
setReconnectAttempts(0);
63-
64-
// Start heartbeat
65-
if (heartbeatIntervalRef.current) {
66-
clearInterval(heartbeatIntervalRef.current);
67-
}
68-
heartbeatIntervalRef.current = setInterval(() => {
69-
if (portRef.current) {
70-
try {
71-
portRef.current.postMessage({
72-
type: "PING",
73-
timestamp: Date.now(),
74-
});
75-
} catch (error) {
76-
console.warn("Failed to send ping:", error);
77-
}
78-
}
79-
}, 10000); // Ping every 10 seconds
80-
} else if (message.type === "PONG") {
81-
// Connection is healthy
82-
} else if (message.type === "INITIAL_STATE") {
59+
if (message.type === "INITIAL_STATE") {
8360
// Clear previous data when connecting to a different tab
8461
setQueries([]);
8562
setMutations([]);
@@ -110,9 +87,13 @@ export const useConnection = (): UseConnectionReturn => {
11087
switch (message.subtype) {
11188
case "QUERY_CLIENT_DETECTED":
11289
setTanStackQueryDetected(true);
90+
// Clear artificial states when TanStack Query is detected (page refresh/reload)
91+
setArtificialStates(new Map());
11392
break;
11493
case "QUERY_CLIENT_NOT_FOUND":
11594
setTanStackQueryDetected(false);
95+
// Clear artificial states when TanStack Query is not found
96+
setArtificialStates(new Map());
11697
break;
11798
case "QUERY_STATE_UPDATE":
11899
break;
@@ -161,50 +142,21 @@ export const useConnection = (): UseConnectionReturn => {
161142
}
162143
}
163144
});
164-
165-
port.onDisconnect.addListener(() => {
166-
portRef.current = null;
167-
168-
// Clear heartbeat
169-
if (heartbeatIntervalRef.current) {
170-
clearInterval(heartbeatIntervalRef.current);
171-
heartbeatIntervalRef.current = null;
172-
}
173-
174-
// Attempt reconnection with exponential backoff
175-
const attempt = reconnectAttempts + 1;
176-
setReconnectAttempts(attempt);
177-
178-
if (attempt <= 5) {
179-
const delay = Math.min(1000 * Math.pow(2, attempt - 1), 10000); // Max 10s delay
180-
181-
reconnectTimeoutRef.current = setTimeout(() => {
182-
connectToBackground();
183-
}, delay);
184-
} else {
185-
console.error("Failed to reconnect after 5 attempts");
186-
}
187-
});
188145
} catch (error) {
189146
console.error("Failed to connect to background script:", error);
190147
}
191-
}, [reconnectAttempts]);
148+
}, []);
192149

193150
useEffect(() => {
194151
connectToBackground();
195152

153+
const reconnectTimeout = reconnectTimeoutRef.current;
154+
196155
// Cleanup function
197156
return () => {
198-
if (portRef.current) {
199-
portRef.current.disconnect();
200-
portRef.current = null;
201-
}
202-
if (reconnectTimeoutRef.current) {
203-
clearTimeout(reconnectTimeoutRef.current);
204-
}
205-
if (heartbeatIntervalRef.current) {
206-
clearInterval(heartbeatIntervalRef.current);
207-
}
157+
portRef.current?.disconnect();
158+
portRef.current = null;
159+
if (reconnectTimeout) clearTimeout(reconnectTimeout);
208160
};
209161
}, [connectToBackground]);
210162

src/hooks/useKeyboardNavigation.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ interface UseKeyboardNavigationOptions {
44
enabled?: boolean;
55
itemCount: number;
66
enableWrapAround?: boolean;
7+
onActivate?: (index: number) => void;
78
}
89

910
interface UseKeyboardNavigationReturn {
@@ -120,6 +121,15 @@ export function useKeyboardNavigation(
120121
break;
121122
}
122123

124+
case " ":
125+
case "Enter": {
126+
event.preventDefault();
127+
if (focusedIndex !== null && options.onActivate) {
128+
options.onActivate(focusedIndex);
129+
}
130+
break;
131+
}
132+
123133
case "Tab": {
124134
// Allow normal tab behavior but reset keyboard navigation state
125135
setKeyboardFocused(false);
@@ -132,7 +142,7 @@ export function useKeyboardNavigation(
132142
break;
133143
}
134144
},
135-
[enabled, currentItemCount, focusedIndex, enableWrapAround],
145+
[enabled, currentItemCount, focusedIndex, enableWrapAround, options],
136146
);
137147

138148
// Reset focus

src/hooks/useViewState.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,18 @@ export const useViewState = (): UseViewStateReturn => {
3636
enabled: currentView === "queries",
3737
itemCount: 0, // Item count will be updated by the component with filtered data
3838
enableWrapAround: true,
39+
onActivate: (index: number) => {
40+
setSelectedQueryIndex(index);
41+
},
3942
});
4043

4144
const mutationKeyboardNavigation = useKeyboardNavigation({
4245
enabled: currentView === "mutations",
4346
itemCount: 0, // Item count will be updated by the component with filtered data
4447
enableWrapAround: true,
48+
onActivate: (index: number) => {
49+
setSelectedMutationIndex(index);
50+
},
4551
});
4652

4753
// Handle view changes with automatic selection clearing

src/injected/injected.ts

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,8 @@ function performEnhancedDetection() {
297297
subtype: "QUERY_CLIENT_NOT_FOUND",
298298
});
299299
}
300+
301+
return detected;
300302
}
301303

302304
// Query action handlers
@@ -534,23 +536,23 @@ if (typeof window !== "undefined") {
534536
window.__TANSTACK_QUERY_DEVTOOLS_INJECTED__ = true;
535537

536538
// Perform initial detection
537-
performEnhancedDetection();
538-
539-
// Also check periodically in case TanStack Query is loaded dynamically
540-
// Continue checking until TanStack Query is found (no artificial limit)
541-
let detectionFound = false;
542-
const interval = setInterval(() => {
543-
if (!detectionFound && detectTanStackQuery()) {
544-
detectionFound = true;
545-
performEnhancedDetection();
546-
clearInterval(interval);
547-
}
548-
}, 1000);
539+
if (!performEnhancedDetection()) {
540+
// Also check periodically in case TanStack Query is loaded dynamically
541+
// Continue checking until TanStack Query is found (no artificial limit)
542+
let detectionFound = false;
543+
const interval = setInterval(() => {
544+
if (!detectionFound && detectTanStackQuery()) {
545+
detectionFound = true;
546+
performEnhancedDetection();
547+
clearInterval(interval);
548+
}
549+
}, 1000);
549550

550-
// Stop checking after 2 minutes to avoid infinite polling
551-
setTimeout(() => {
552-
if (!detectionFound) {
553-
clearInterval(interval);
554-
}
555-
}, 120000);
551+
// Stop checking after 2 minutes to avoid infinite polling
552+
setTimeout(() => {
553+
if (!detectionFound) {
554+
clearInterval(interval);
555+
}
556+
}, 120000);
557+
}
556558
}

0 commit comments

Comments
 (0)