UNPKG

create-desktop-shortcuts

Version:
318 lines (284 loc) 9.09 kB
'use strict'; /** * @file The core functionality of the library. * @author TheJaredWilcurt */ const fs = require('fs'); const path = require('path'); const exec = require('child_process').execSync; const spawn = require('child_process').spawnSync; const helpers = require('./helpers.js'); const { OPTIONS } = require('../api-type-definitions.js'); const library = { // LINUX /** * Creates the text to be stored in the shortcut file based on * the user's options. * * @example * let fileData = generateLinuxFileData(options); * * @param {OPTIONS} options User's options object * @return {string} The data to be stored in the shortcut file */ generateLinuxFileData: function (options) { if (!options || !options.linux || !options.linux.filePath) { return ''; } // Set defaults let type = 'Type=Application'; let terminal = 'Terminal=false'; let exec = 'Exec="' + options.linux.filePath + '"'; let name = 'Name=' + path.parse(options.linux.filePath).name; let comment = ''; let icon = ''; // Replace defaults if value passed in if (options.linux.type) { type = 'Type=' + options.linux.type; } if (options.linux.terminal) { terminal = 'Terminal=' + options.linux.terminal; } if (options.linux.name) { name = 'Name=' + options.linux.name; } if (options.linux.comment) { comment = 'comment=' + options.linux.comment; } if (options.linux.icon) { icon = 'Icon=' + options.linux.icon; } if (options.linux.arguments) { exec = exec + ' ' + options.linux.arguments; } // File format details: // https://wiki.archlinux.org/index.php/Desktop_entries const fileContents = [ '#!/user/bin/env xdg-open', '[Desktop Entry]', 'Version=1.0', type, terminal, exec, name, comment, icon ].filter(Boolean).join('\n'); return fileContents; }, /** * Saves a file to disk with the correct content based on * the User's options. Optionally runs chmod to adjust * execution permissions on the shortcut. * * @example * let success = makeLinuxShortcut(options); * * @param {OPTIONS} options User's options object * @return {boolean} true = successfully made Linux shortcut */ makeLinuxShortcut: function (options) { const fileContents = this.generateLinuxFileData(options); let success = true; try { fs.writeFileSync(options.linux.outputPath, fileContents); } catch (error) { success = false; helpers.throwError( options, 'ERROR: Could not create LINUX shortcut.\n' + 'PATH: ' + options.linux.outputPath + '\n' + 'DATA:\n' + fileContents, error ); } if (success && options.linux.chmod) { try { fs.chmodSync(options.linux.outputPath, '755'); } catch (error) { success = false; helpers.throwError(options, 'ERROR attempting to change permisions of ' + options.linux.outputPath, error); } } return success; }, // WINDOWS /** * Returns the path to the windows.vbs file. Usefull for unit tests. * * @example * let vbsPath = produceWindowsVBSPath(); * * @return {string} The file path to the windows.vbs file */ produceWindowsVBSPath: function () { return path.join(__dirname, 'windows.vbs'); }, /** * Creates the data to be passed in to the VBScript based on user options. * Spawns a wscript child process to create the shortcut and log if error. * * @example * let success = makeWindowsShortcut(options); * * @param {OPTIONS} options User's options object * @return {boolean} true = successfully made Windows shortcut */ makeWindowsShortcut: function (options) { let success = true; const vbsScript = options.windows.VBScriptPath || this.produceWindowsVBSPath(); if (!fs.existsSync(vbsScript)) { helpers.throwError(options, 'Could not locate required "windows.vbs" file.'); success = false; return success; } const windowModes = { normal: 1, maximized: 3, minimized: 7 }; let outputPath = options.windows.outputPath; let filePath = options.windows.filePath; let args = options.windows.arguments || ''; let comment = options.windows.comment || ''; let cwd = options.windows.workingDirectory || ''; let icon = options.windows.icon; let windowMode = windowModes[options.windows.windowMode] || windowModes.normal; let hotkey = options.windows.hotkey || ''; // Double quotes (") are used as an escape character in VBScript, and are stripped out of any arguments passed in function replaceDoubleQuotes (str) { return str.split('"').join('__DOUBLEQUOTE__'); } args = replaceDoubleQuotes(args); comment = replaceDoubleQuotes(comment); hotkey = replaceDoubleQuotes(hotkey); if (!icon) { if ( filePath.endsWith('.dll') || filePath.endsWith('.exe') ) { icon = options.windows.filePath + ',0'; } else { icon = options.windows.filePath; } } let wscriptArguments = [ vbsScript, // '/NoLogo', // Apparently this stops it from displaying a logo in the console, even though I haven't actually ever seen one // '/B', // silent mode, but doesn't actually stop dialog alert windows from popping up on errors outputPath, filePath, args, comment, cwd, icon, windowMode, hotkey ]; try { spawn('wscript', wscriptArguments); } catch (error) { success = false; helpers.throwError( options, 'ERROR: Could not create WINDOWS shortcut.\n' + 'TARGET: ' + options.windows.filePath + '\n' + 'PATH: ' + options.windows.outputPath + '\n', error ); } return success; }, // OSX /** * Creates the CLI arguments based on user options. Executes command. * Handles errors. * * @example * let success = makeOSXShortcut(options); * * @param {OPTIONS} options User's options object * @return {boolean} true = successfully made OSX shortcut */ makeOSXShortcut: function (options) { let success = true; // Global OSX command to create symbolic links const link = 'ln'; const symbolic = '-s'; let overwrite = ''; if (options.osx.overwrite) { overwrite = '-f'; } if (overwrite || (!overwrite && !fs.existsSync(options.osx.outputPath))) { // https://ss64.com/osx/ln.html let command = [ link, overwrite, symbolic, '"' + options.osx.filePath + '"', '"' + options.osx.outputPath + '"' ].filter(Boolean).join(' '); try { // ln -s "/Applications/Sublime Text.app" "/Users/owner/Desktop/Sublime Text" exec(command); } catch (error) { success = false; helpers.throwError( options, 'ERROR: Could not create OSX shortcut.\n' + 'TARGET: ' + options.osx.filePath + '\n' + 'PATH: ' + options.osx.outputPath + '\n', error ); } } else { helpers.throwError(options, 'Could not create OSX shortcut because matching outputPath already exists and overwrite is false.'); } return success; }, // RUN /** * Checks the user's options and runs all desired OS scripts to create * shortcuts. Returns true if all shortcuts were created successfully * or false if any failed. * * @example * let success = runCorrectOSs(options); * * @param {OPTIONS} options User's options object * @return {boolean} true = all shortcuts created successfully */ runCorrectOSs: function (options) { if (!options.windows && !options.linux && !options.osx) { helpers.throwError(options, 'No shortcuts were created due to lack of accurate details passed in to options object', options); return false; } if (options.onlyCurrentOS) { if (process.platform === 'win32' && options.windows) { return this.makeWindowsShortcut(options); } if (process.platform === 'linux' && options.linux) { return this.makeLinuxShortcut(options); } if (process.platform === 'darwin' && options.osx) { return this.makeOSXShortcut(options); } helpers.throwError(options, 'Unsupported platform. This library only supports process.platform of "win32", "linux" and "darwin".', options); return false; } let windowsSuccess = true; let linuxSuccess = true; let osxSuccess = true; if (options.windows) { windowsSuccess = this.makeWindowsShortcut(options); } if (options.linux) { linuxSuccess = this.makeLinuxShortcut(options); } if (options.osx) { osxSuccess = this.makeOSXShortcut(options); } return windowsSuccess && linuxSuccess && osxSuccess; } }; module.exports = library;