UNPKG

apple-js-stable

Version:

Apple js is the extension of osascript to javascript , run applescript commands via node js ,and implement js-like logic

448 lines (395 loc) 13.7 kB
/** * @class AppleScript * @classdesc * A lightweight utility class for generating AppleScript code from JavaScript. * Useful for building AppleScript snippets programmatically or compiling JS-like logic * into AppleScript-compatible statements. * * Each static method returns a valid AppleScript string representing that specific command. * * @example * const script = [ * AppleScript.set("greeting", "Hello world"), * AppleScript.displayVar("greeting"), * AppleScript.speak("Hello world", "Alex") * ].join("\n"); * * // Output: * // set greeting to "Hello world" * // display dialog greeting * // say "Hello world" using "Alex" */ class AppleScript { /** Equivalent of: display dialog "message" */ static display(msg) { return `display dialog "${msg}"`; } /** Equivalent of: log "message" (for Script Editor console) */ static log(msg) { return `log "${msg}"`; } /** Gets the button returned from a dialog result variable */ static buttonReturnOf(varName) { return `button returned of ${varName}`; } /** Gets a specific property (e.g. 'text returned') of a variable */ static returnOf(property, varName) { return `${property} of ${varName}`; } /** Variable assignment: set name to "John" */ static set(varName, value) { const quoted = typeof value === "string" ? `"${value}"` : value; return `set ${varName} to ${quoted}`; } /** If statement: if condition then ... end if */ static if(condition, bodyLines = []) { const body = bodyLines.map(line => `\t${line}`).join("\n"); return `if ${condition} then\n${body}\nend if`; } /** If-else block */ static ifElse(condition, ifLines = [], elseLines = []) { const ifBody = ifLines.map(l => `\t${l}`).join("\n"); const elseBody = elseLines.map(l => `\t${l}`).join("\n"); return `if ${condition} then\n${ifBody}\nelse\n${elseBody}\nend if`; } /** Repeat with i from 1 to 5 */ static repeatWith(varName, from, to, bodyLines = []) { const body = bodyLines.map(line => `\t${line}`).join("\n"); return `repeat with ${varName} from ${from} to ${to}\n${body}\nend repeat`; } /** Repeat while condition */ static repeatWhile(condition, bodyLines = []) { const body = bodyLines.map(line => `\t${line}`).join("\n"); return `repeat while ${condition}\n${body}\nend repeat`; } /** Delay in seconds */ static delay(seconds) { return `delay ${seconds}`; } /** Run shell command */ static shell(cmd) { return `do shell script "${cmd.replace(/"/g, '\\"')}"`; } /** Activate application */ static activateApp(appName) { return `tell application "${appName}" to activate`; } /** Open a file using full POSIX path */ static openFile(posixPath) { return `open POSIX file "${posixPath}"`; } /** Comment line */ static comment(text) { return `-- ${text}`; } /** Speak text out loud */ static speak(text, voice = null) { const safeText = `"${text}"`; if (voice) { return `say ${safeText} using "${voice}"`; } return `say ${safeText}`; } /** * Toggles full screen of the frontmost app window. */ static fullscreenFrontApp() { return `tell application "System Events" tell application process (name of first application process whose frontmost is true) tell window 1 set value of attribute "AXFullScreen" to not (value of attribute "AXFullScreen") end tell end tell end tell`; } /** * Waits until the given application becomes frontmost. * @param {string} appName - The name of the application to wait for. * @returns {string} AppleScript code that polls until the app is frontmost. */ static awaitAppIsFrontmost(appName) { return [ `repeat until frontmost of application "${appName}" is true`, `\tdelay 0.1`, `end repeat` ].join("\n"); } static activateAndAwait(appName) { return [ AppleScript.activateApp(appName), AppleScript.awaitAppIsFrontmost(appName) ].join("\n"); } static AppleCodeBlock(...statements){ return [...statements] } /**Disaptches a named event triggering the system-events functionality */ static dispatchSystemEvent(eventName) { const map = { // Navigation gestures "swipe-left": `tell application "System Events" to key code 124 using {control down}`, "swipe-right": `tell application "System Events" to key code 123 using {control down}`, "swipe-up": `tell application "System Events" to key code 126 using {control down}`, "swipe-down": `tell application "System Events" to key code 125 using {control down}`, // Desktop switching "switch-desktop-left": `tell application "System Events" to key code 123 using {control down}`, "switch-desktop-right": `tell application "System Events" to key code 124 using {control down}`, // Mission control & expose "mission-control": `tell application "System Events" to key code 126 using {control down}`, "app-expose": `tell application "System Events" to key code 125 using {control down}`, // System control "lock-screen": `do shell script "pmset displaysleepnow"`, "start-screensaver": `tell application "System Events" to start current screen saver`, "empty-trash": `tell application "Finder" to empty the trash`, "take-screenshot": `do shell script "screencapture -x ~/Desktop/osascript-taken-shot_$(date +%s).png"`, "toggle-dark-mode": `do shell script "osascript -e 'tell application \\"System Events\\" to tell appearance preferences to set dark mode to not dark mode'"`, "do-not-disturb-on": `do shell script "defaults -currentHost write com.apple.notificationcenterui doNotDisturb -boolean true && killall NotificationCenter"`, "do-not-disturb-off": `do shell script "defaults -currentHost write com.apple.notificationcenterui doNotDisturb -boolean false && killall NotificationCenter"` }; return map[eventName] || `-- Unknown system event: ${eventName}`; } /** * Browser automation commands * Safari is AppleScript-native, Chrome support depends on scripting permissions being enabled. */ static browser = { /** * Open a URL in Safari (creates a new document if none exists). * @param {string} url - The URL to open. * @returns {string} AppleScript code */ openInSafari(url) { return [ `tell application "Safari"`, `\tactivate`, `\tif (count of windows) = 0 then`, `\t\tmake new document with properties {URL:"${url}"}`, `\telse`, `\t\tset URL of front document to "${url}"`, `\tend if`, `end tell` ].join("\n"); }, /** * Open a URL in Google Chrome (requires accessibility scripting). * @param {string} url - The URL to open. */ openInChrome(url) { return [ `tell application "Google Chrome"`, `\tactivate`, `\tif (count of windows) = 0 then`, `\t\tmake new window`, `\tend if`, `\ttell front window`, `\t\tset newTab to make new tab with properties {URL: "${url}"}`, `\tend tell`, `end tell` ].join("\n"); }, /** * Gets the current URL from Safari's front tab. * @returns {string} AppleScript code to get the current URL. */ getCurrentURLFromSafari() { return `tell application "Safari" to return URL of front document`; }, /** * Activates Safari. */ activateSafari() { return `tell application "Safari" to activate`; }, /** * Creates a new tab in Safari. * @param {string} url - URL to load in the new tab (optional). */ newSafariTab(url = null) { if (url) { return [ `tell application "Safari"`, `\ttell window 1`, `\t\tmake new tab at end of tabs with properties {URL:"${url}"}`, `\tend tell`, `end tell` ].join("\n"); } return [ `tell application "Safari"`, `\ttell window 1`, `\t\tmake new tab at end of tabs`, `\tend tell`, `end tell` ].join("\n"); } }; /** * Finder-related AppleScript commands. */ static finder = { /** * Opens a folder in Finder. * @param {string} path - POSIX path to the folder. */ openFolder(path) { return `tell application "Finder" to open POSIX file "${path}"`; }, /** * Reveals a file or folder in Finder. * @param {string} path - POSIX path to the item. */ revealInFinder(path) { return `tell application "Finder" to reveal POSIX file "${path}"`; }, /** * Moves a file or folder to the trash. * @param {string} path - POSIX path to the item. */ moveToTrash(path) { return `tell application "Finder" to delete POSIX file "${path}"`; }, /** * Creates a new folder inside a directory. * @param {string} path - POSIX path where the new folder should be created. * @param {string} name - Name of the new folder. */ createFolder(path, name) { return `tell application "Finder" to make new folder at POSIX file "${path}" with properties {name:"${name}"}`; }, /** * Gets the paths of selected items in the front Finder window. */ getSelectedItems() { return `tell application "Finder" to get selection`; }, /** * Sets desktop wallpaper. * @param {string} imagePath - POSIX path to the image file. */ setDesktopWallpaper(imagePath) { return [ `tell application "System Events"`, `\ttell every desktop`, `\t\tset picture to "${imagePath}"`, `\tend tell`, `end tell` ].join("\n"); } }; /** * System control utilities using `do shell script` and AppleScript. * Useful for shutdown, logout, volume, brightness, screenshots, etc. */ static systemControl = { /** * Shuts down the computer after confirmation. */ shutdown() { return [ `display dialog "Are you sure you want to shut down the computer?" buttons {"Cancel", "OK"} default button "Cancel"`, `if button returned of result is "OK" then`, `\ttell application "System Events" to shut down`, `end if` ].join("\n"); }, /** * Restarts the computer (no confirmation). */ restart() { return `tell application "System Events" to restart`; }, /** * Logs out the current user after confirmation. */ logout() { return [ `display dialog "Are you sure you want to log out?" buttons {"Cancel", "OK"} default button "Cancel"`, `if button returned of result is "OK" then`, `\ttell application "System Events" to log out`, `end if` ].join("\n"); }, /** * Locks the screen after confirmation. */ lockScreen() { return [ `display dialog "Do you want to lock the screen?" buttons {"Cancel", "OK"} default button "Cancel"`, `if button returned of result is "OK" then`, `\tdo shell script "pmset displaysleepnow"`, `end if` ].join("\n"); }, /** * Starts the screensaver immediately. */ startScreensaver() { return `tell application "System Events" to start current screen saver`; }, /** * Empties the trash after confirmation. */ emptyTrash() { return [ `display dialog "Are you sure you want to empty the Trash?" buttons {"Cancel", "OK"} default button "Cancel"`, `if button returned of result is "OK" then`, `\ttell application "Finder" to empty the trash`, `end if` ].join("\n"); }, /** * Ejects all mounted external volumes. */ ejectAllDisks() { return `do shell script "diskutil eject /Volumes/*"`; }, /** * Takes a screenshot and saves it to Desktop. */ screenshotToDesktop() { return `do shell script "screencapture -x ~/Desktop/screenshot_$(date +%s).png"`; }, /** * Sets system volume (0–100). * @param {number} volume */ setVolume(volume) { const level = Math.max(0, Math.min(100, volume)); return `set volume output volume ${level}`; }, /** * Toggles system mute. * @param {boolean} mute */ toggleMute(mute = true) { return `set volume ${mute ? "with" : "without"} output muted`; }, /** * Enables or disables Do Not Disturb (older macOS versions only). * @param {boolean} enable */ toggleDoNotDisturb(enable = true) { const flag = enable ? "true" : "false"; return `do shell script "defaults -currentHost write com.apple.notificationcenterui doNotDisturb -boolean ${flag} && killall NotificationCenter"`; }, /** * Enables dark mode using shell. */ enableDarkMode() { return `do shell script "osascript -e 'tell application \\"System Events\\" to tell appearance preferences to set dark mode to true'"`; }, /** * Disables dark mode using shell. */ disableDarkMode() { return `do shell script "osascript -e 'tell application \\"System Events\\" to tell appearance preferences to set dark mode to false'"`; }, /** * Toggles dark mode state. */ toggleDarkMode() { return `do shell script "osascript -e 'tell application \\"System Events\\" to tell appearance preferences to set dark mode to not dark mode'"`; } }; } module.exports={AppleScript}