-
Notifications
You must be signed in to change notification settings - Fork 3.9k
Update flush-dns extension #18964
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Update flush-dns extension #18964
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,7 @@ | ||
{ | ||
"$schema": "https://www.raycast.com/schemas/extension.json", | ||
"name": "flush-dns", | ||
"title": "Flush DNS", | ||
"title": "Flush Dns", | ||
"description": "Flush the DNS cache", | ||
"icon": "extension_icon.png", | ||
"author": "rasmusbe", | ||
|
@@ -16,7 +16,7 @@ | |
"commands": [ | ||
{ | ||
"name": "index", | ||
"title": "Flush DNS", | ||
"title": "Flush Dns", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 'Flush Dns' should be 'Flush DNS' since DNS is an acronym There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Linter was complaining, that why i changed |
||
"description": "Flush the DNS cache", | ||
"mode": "no-view" | ||
} | ||
|
@@ -41,6 +41,7 @@ | |
}, | ||
"version": "1.0.0", | ||
"platforms": [ | ||
"macOS" | ||
"macOS", | ||
"Windows" | ||
] | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,66 +1,142 @@ | ||
import { confirmAlert, showHUD } from "@raycast/api"; | ||
import { SpawnSyncReturns, execSync } from "node:child_process"; | ||
import { execSync } from "node:child_process"; | ||
import { platform } from "node:os"; | ||
|
||
const isSpawnReturn = (e: unknown): e is SpawnSyncReturns<Buffer> => { | ||
return typeof e === "object" && e !== null && "status" in e && "stdout" in e && "stderr" in e; | ||
}; | ||
type ShellType = string | undefined; | ||
|
||
const commands = { | ||
mDNSResponder: "sudo /usr/bin/killall -HUP mDNSResponder", | ||
dscacheutil: "sudo /usr/bin/dscacheutil -flushcache", | ||
mdnsflushcache: "sudo /usr/bin/discoveryutil mdnsflushcache", | ||
} as const satisfies Record<string, string>; | ||
interface CommandSet { | ||
commands: Record<string, string>; | ||
shell: ShellType; | ||
} | ||
|
||
const OS_COMMANDS = { | ||
darwin: { | ||
commands: { | ||
dscacheutil: "/usr/bin/dscacheutil -flushcache", | ||
mDNSResponder: "/usr/bin/killall -HUP mDNSResponder", | ||
mdnsflushcache: "/usr/bin/discoveryutil mdnsflushcache", | ||
}, | ||
shell: "/bin/bash", | ||
}, | ||
win32: { | ||
commands: { | ||
ipconfig: "ipconfig /flushdns", | ||
}, | ||
shell: undefined, // Uses cmd.exe by default | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should this be undefined or There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. raycast windows don't have showHUD api right so hard to know if throwing error, but Nodejs docs says right here node uses process.env.ComSpec as default shell as cmd.exe |
||
}, | ||
} as const satisfies Record<string, CommandSet>; | ||
|
||
type SupportedPlatform = "darwin" | "win32"; | ||
|
||
interface Win32Commands { | ||
ipconfig: string; | ||
} | ||
|
||
export default async function main() { | ||
const osVersion = execSync("sw_vers -productVersion").toString().trim(); | ||
|
||
const runCommands: (keyof typeof commands)[] = []; | ||
|
||
if (osVersion.match(/^1[1-5]/)) { | ||
console.log(`OS Version: ${osVersion} parsed as 11-15`); | ||
runCommands.push("dscacheutil", "mDNSResponder"); | ||
} else if (osVersion.match(/^10\.([7-9]|1[1-4])/) || osVersion.match(/^10\.10\.[4-5]/)) { | ||
console.log(`OS Version: ${osVersion} parsed as 10.7-9, 10.10.4-5, 10.11-14`); | ||
runCommands.push("mDNSResponder"); | ||
} else if (osVersion.match(/^10\.10\.[0-3]/)) { | ||
console.log(`OS Version: ${osVersion} parsed as 10.10.0-3`); | ||
runCommands.push("mdnsflushcache"); | ||
} else if (osVersion.startsWith("10.6")) { | ||
console.log(`OS Version: ${osVersion} parsed as 10.6`); | ||
runCommands.push("dscacheutil"); | ||
} else { | ||
const flush = await confirmAlert({ | ||
title: `OS Version ${osVersion} is not supported.`, | ||
message: "Would you like to try flushing the DNS cache anyway?", | ||
primaryAction: { | ||
title: "Flush DNS Cache", | ||
}, | ||
dismissAction: { | ||
title: "Cancel", | ||
}, | ||
}); | ||
if (!flush) return; | ||
runCommands.push("dscacheutil", "mDNSResponder"); | ||
const osPlatform = platform(); | ||
|
||
if (!["darwin", "win32"].includes(osPlatform)) { | ||
await showHUD("🚫 Unsupported operating system"); | ||
return; | ||
} | ||
|
||
const command = runCommands.map((key) => commands[key]).join("; "); | ||
const osCommandSet = OS_COMMANDS[osPlatform as SupportedPlatform]; | ||
|
||
let command: string; | ||
let shell: ShellType; | ||
|
||
switch (osPlatform) { | ||
case "darwin": { | ||
const macResult = await getMacOSCommands(osCommandSet); | ||
if (!macResult) return; | ||
|
||
const osaCommand = `osascript -e 'do shell script "${command}" with administrator privileges'`; | ||
command = macResult.command; | ||
shell = macResult.shell; | ||
break; | ||
} | ||
|
||
case "win32": { | ||
const { ipconfig } = osCommandSet.commands as Win32Commands; | ||
command = ipconfig; | ||
shell = osCommandSet.shell; | ||
break; | ||
} | ||
|
||
default: | ||
await showHUD("🚫 Unsupported OS"); | ||
return; | ||
} | ||
|
||
console.log(`Running command: ${osaCommand}`); | ||
console.log(`🚀 Executing DNS flush command: ${command} in shell: ${shell}`); | ||
|
||
await showHUD("Administrator Privileges Required"); | ||
try { | ||
execSync(osaCommand, { shell: "/bin/bash" }); | ||
await showHUD("DNS Cache Flushed"); | ||
} catch (e) { | ||
if (isSpawnReturn(e)) { | ||
console.error(`Command exited with status ${e.status}`); | ||
console.error(`stdout: ${e.stdout.toString()}`); | ||
console.error(`stderr: ${e.stderr.toString()}`); | ||
} else { | ||
console.error(e); | ||
execSync(command, { shell, stdio: "ignore" }); | ||
await showHUD("✅ DNS Cache Flushed Successfully"); | ||
} catch (error) { | ||
await handleExecutionError(error, osPlatform); | ||
} | ||
} | ||
|
||
async function getMacOSCommands(osCommandSet: CommandSet): Promise<{ command: string; shell: ShellType } | null> { | ||
try { | ||
const osVersion = execSync("sw_vers -productVersion").toString().trim(); | ||
|
||
const versionPatterns: Record<string, string[]> = { | ||
"^1[1-5]": ["dscacheutil", "mDNSResponder"], | ||
"^10\\.([7-9]|1[1-4])|^10\\.10\\.[4-5]": ["mDNSResponder"], | ||
"^10\\.10\\.[0-3]": ["mdnsflushcache"], | ||
"^10\\.6": ["dscacheutil"], | ||
}; | ||
|
||
let matched = false; | ||
let runCommands: string[] = []; | ||
|
||
for (const [pattern, cmds] of Object.entries(versionPatterns)) { | ||
if (new RegExp(pattern).test(osVersion)) { | ||
runCommands = cmds; | ||
matched = true; | ||
break; | ||
} | ||
} | ||
|
||
if (!matched) { | ||
const confirmed = await confirmAlert({ | ||
title: `⚠️ OS Version ${osVersion} Not Tested`, | ||
message: "Attempt to flush DNS cache anyway?", | ||
primaryAction: { title: "Flush DNS" }, | ||
}); | ||
|
||
if (!confirmed) return null; | ||
runCommands = ["dscacheutil", "mDNSResponder"]; | ||
} | ||
await showHUD("Error Flushing DNS Cache"); | ||
|
||
const commandList = runCommands.map((key) => osCommandSet.commands[key]).join("; "); | ||
return { | ||
command: `osascript -e 'do shell script "${commandList}" with administrator privileges'`, | ||
shell: osCommandSet.shell, | ||
}; | ||
} catch (e) { | ||
console.error("❌ Error determining macOS version:", e); | ||
await showHUD("Failed to determine macOS version"); | ||
return null; | ||
} | ||
} | ||
|
||
async function handleExecutionError(error: unknown, os: string) { | ||
let errorMessage = "⚠️ Error flushing DNS cache"; | ||
|
||
if (typeof error === "object" && error !== null && "stderr" in error) { | ||
const stderr = (error as { stderr?: Buffer }).stderr?.toString() || ""; | ||
if (stderr) { | ||
console.error(".Stderr:", stderr); | ||
if (os === "win32" && stderr.includes("The requested operation requires elevation")) { | ||
errorMessage = "⚠️ Run Raycast as Administrator"; | ||
} else { | ||
errorMessage = stderr.split("\n")[0].substring(0, 64); | ||
} | ||
} | ||
} | ||
|
||
console.error("💥 Execution failed:", error); | ||
await showHUD(errorMessage); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
style: 'Flush Dns' should be 'Flush DNS' since DNS is an acronym