Is it possible to change any app's icon with NodeJS - javascript

Is it possible to change the icon of any application on macOS with NodeJS...
I've been searching for a bit but I've been unable to find anything useful.
Much like dragging a .icns file onto the icon in the "Get Info" menu for any app but instead with NodeJS .

You just need to replace the icon file inside the app.
Treat the app as a folder, look for the Info.plist file in the app inside its Contents folder.
In the Info.plist file (it's an xml file) look for the CFBundleIconFile key. It's value is the icon file for the app.
Here you have two choices - you can either:
3a. replace this value with your icon or
3b. just replace the icon file with your own icon with the same name.
Here's an example of replacing the icon file with another file with the same name:
const plist = require('simple-plist');
const path = require('path');
const fs = require('fs');
function (appPath, newIconFile) {
plist.readFile(path.join(appPath, 'Contents/Info.plist'), (err, data) => {
const iconName = path.join(appPath, 'Contents/Resources', data.CFBundleIconFile);
fs.copyFile(newIconFile, iconName, (err) => {
console.log('icon changed!');
});
});
}
The simple-plist library also supports saving the plist data back to disk so I will leave replacing the CFBundleIconFile value as an exercise for the reader.

Related

Uploading images to AWS S3 bucket - specifying file path for randomly generated file names

I'm working on an automated testing project using PuppeteerJS in headless Chrome and trying to integrate existing screenshot functionality with AWS-SDK to upload images to an AWS S3 bucket on test failure.
The problem i'm having is the sub directories in a screenshots folder and the image file names are generated randomly in another file based on the current date and test environment, and run every time a test runs. The format of the generated directories/files is "screenshots/year/month/day/randomname.png".
The next step in the test is after the screenshots are generated, the folder containing the newly created images should be uploaded to AWS, and I've tried to achieve this using a glob to get every subdirectory and file with a png extension, like "screenshots/**/**/**/*.png", but i get a "no such file or directory" error". The folders/file names will be different everytime the tests run.
I've just started using AWS and I haven't been able to find a specific answer to my problem while researching.
import { PutObjectCommand } from "#aws-sdk/client-s3";
import { s3Client } from "../libs/s3Client.js";
import path from "path";
import fs from "fs";
const file = "../../screenshots/**/**/**/*.png";
const fileStream = fs.createReadStream(file);
// Set the parameters
export const uploadParams = {
Bucket: "bucket-name",
Key: path.basename(file),
// Add the required 'Body' parameter
Body: fileStream,
};
// Upload file to specified bucket.
export const run = async () => {
try {
const data = await s3Client.send(new PutObjectCommand(uploadParams));
console.log("Success", data);
return data; // For unit tests.
} catch (err) {
console.log("Error", err);
}
};
run();
Worked this out with the help of Jarmod. I needed to use the nodeJS:fs module to get the file paths recursively and returns a string which can be passed into the AWS fileStream variable for it to be uploaded to AWS. Jarmod shared the webmound article and i found the coder rocket fuel article hepful also.
https://www.webmound.com/nodejs-get-files-in-directories-recursively/
https://coderrocketfuel.com/article/recursively-list-all-the-files-in-a-directory-using-node-js

download file starting with period

I have code to create a download link for dynamicly created data. It works except that I want the filename to be .env I can download a file called env or config.env but not plain .env is this a browser restriction?
function fileDownload(data: string, fileName: string, mimeType: string) {
const dataStr = `data:${mimeType};charset=utf-8,${encodeURIComponent(
data
)}`;
const downloadAnchorNode = document.createElement('a');
downloadAnchorNode.setAttribute('href', dataStr);
downloadAnchorNode.setAttribute('download', fileName);
document.body.appendChild(downloadAnchorNode); // required for firefox
downloadAnchorNode.click();
downloadAnchorNode.remove();
}
export function plainFileDownload(data: string, fileName: string) {
fileDownload(data, fileName, 'application/x-empty');
}
textFileDownload('some dynamic text', '.env'); // Called on button click
Whether the access to dot files is restricted or not really depends on your server config.
It is unclear from the question what is your server config or even what you use on server-side.
In my experience most of the tools/frameworks will not serve files/folders prefixed with a dot by default (for instance, express & Apache will not) however you can configure them to do so:
Check this if you use Express
Check this if you use Apache
Be sure that you know what you are doing. Dot-prefixed file are hidden by default because they tend to contain some sensitive information that you normally wouldn't like to share with everyone.

Electron store my app datas in 'userData' path

I'm building and trying do deploying a packaged electron app. FOr the packaging i used
electron-packager
electron-installer-debian
electron-installer-dmg
electron-winstaller
and I'm facing a little issue where I have to store tha appa datas somewhere in my user computer.
I saw that the good practice is to use the the folder in the path that is returned by the electron method app.getPath('userData').
from the docs
It is The directory for storing the app's configuration files, which by default it is the appData directory appended with the app name.
%APPDATA% on Windows
$XDG_CONFIG_HOME or ~/.config on Linux
~/Library/Application Support on macOS
By my tests sometimes this folder is not created automatically when the app is installed and other times yes and I'm wondering if i should create it or not.
Right now i'm quitting the app if this folder isn't present in the pc with the following code
var DatasPath = app.getPath('userData')
if (!fs.existsSync(DatasPath)){
process.exit()
}
So the question is
should i create the DatasPath folder with fs.mkdirSync(DatasPath); when it is not present or it is 'bad practice to do so', and if I can create the folder i have to warning the user the i have just added that folder?
(Expanding my reply from a "comment" to an "answer")
i don't know if i'm supposed to create it or not so i automatically
make the app quit if there is not that folder
It seems you are taking "userData" too literally? It is not an actual "folder" named "userData – it is a path to where the operating system stores data for that application. Electron currently runs on 3 operating systems and each one does things differently. For our convenience, Electron hides those differences by creating the wrapper method app.getPath(name) so the same code will work on each OS.
Try this: put the line below in your main.js script:
console.log(app.getPath('userData'));
/Users/*********/Library/Application Support/MyCoolApp
(the "*********" will be your user account name.)
UPDATED:
Run the code below in main.js and then look in the folder specified by the "userData" path
const fs = require("fs");
const path = require('path');
var datasPath = app.getPath('userData')
var data = "I am the cheese"
var filePath = path.join(datasPath, "savedData.txt")
fs.writeFileSync(filePath, data)
At pathConfig.js
function getAppDataPath() {
switch (process.platform) {
case "darwin": {
return path.join(process.env.HOME, "Library", "Application Support", "myApp");
}
case "win32": {
return path.join(process.env.APPDATA, "myApp");
}
case "linux": {
return path.join(process.env.HOME, ".myApp");
}
default: {
console.log("Unsupported platform!");
process.exit(1);
}
}
}
const appPath = __dirname;
const appDataPath =
!process.env.NODE_ENV || process.env.NODE_ENV === "production"
? getAppDataPath() // Live Mode
: path.join(appPath, "AppData"); // Dev Mode
if (!fs.existsSync(appDataPath)) {
// If the AppData dir doesn't exist at expected Path. Then Create
// Maybe the case when the user runs the app first.
fs.mkdirSync(appDataPath);
}
In each operating system the appData folder has a different path and the perfect way of getting this path is by calling app.getPath('userData') in the main process.
But there is a package that can handle this for you, it stores data in a JSON file and update it in every change.
In my opinion this package is much better than handling everything by your self.
Read more :
https://www.npmjs.com/package/electron-data-holder

Why Node.js only recognizes absolute paths? [duplicate]

This question already has answers here:
What is the difference between __dirname and ./ in node.js?
(2 answers)
Closed 3 years ago.
I created a file called nodes, then initialized the file with npm init and the main js file is called main.js. I also created index.html and index.css in the file, after that I want to use Node.js Render this index.html, so I wrote in main.js:
const http = require('http');
const fs = require('fs');
const hostname = '127.0.0.1';
const port = 9000;
const mainHTML = './index.html';
const server = http.createServer((req, res) => {
fs.stat(`./${mainHTML}`, (err, stats) => {
if(stats) {
res.statusCode = 200;
res.setHeader('Content-Type', 'text/html');
fs.createReadStream(mainHTML).pipe(res);
}
});
});
server.listen(port, hostname, () => {
console.log(`Server running at http://${hostname}:${port}/`);
});
I opened the server with the node desktop/nodes command, but node.js could not find the file.
Until I changed the relative path to an absolute path, Node.js will recognize it:
const mainHTML = 'desktop/nodes/index.html';
Why is this? If I want to use a relative path, how do I do it?
When you access a file in node.js with a relative path, the file is accessed relative to the value of the current working directory for the process. Note, in the modular world of node.js, the current working directory may or may not be the same as the directory where your module was located. And, your code can change the current working directory to be whatever you want it to be.
It is common in modular node.js code to have a programming desire to access things relative to the directory where the current module's code was loaded from. This gives you the ability to use relative paths so the app/module can work anywhere, but it gives you certainty that you'll get the files you want. To do this, one typically uses the module-specific variable __dirname. This is the directory that the current module was loaded from. If it's the main script that node.js was started with then, it's the directory of that script.
So, to get a file from the same directory as the script you are current in, you would do this:
const mainHTML = 'index.html';
fs.createReadStream(path.join(__dirname, mainHTML)).pipe(res);
To access a file in a subdirectory public below where the script is, you could do this:
const mainHTML = 'public/index.html';
fs.createReadStream(path.join(__dirname, mainHTML)).pipe(res);
To access a file in a different subdirectory at the same level (common parent directory) as where the script is, you could do this:
const mainHTML = '../public/index.html';
fs.createReadStream(path.join(__dirname, mainHTML)).pipe(res);
All of these use paths that are relative to where the script itself is located and do not depend upon how the module/script was loaded or what the current working directory of the app is.
You are creating http server, which creates it's path as base, so it understands only paths taking that base path as relative path. If you want to use relative path, then you need to resolve that path.
You can use 'path' library.
const path = require('path')
// To resolve parent path
path.resolve('..', __dirname__)

Saving files locally with electron

I have some template files that contain a few variable strings each, I'd like to build a very simple input form with Electron (https://www.electronjs.org/) and I want to save the composed output file on the user's computer.
Is there any module I can use to let Electron save files locally?
If you are targeting multiple platforms, I answered a similar question here. Basically app.getPath(name), app.setPath(name, path), and app.getAppPath() are very useful in saving files to the the right place regardless of the OS.
You may also want to check out these Nodejs packages which help simplify saving files directly to the host machine...
fs-jetpack
graceful-fs
Node.js fs
If you intend for users to save files you might also have a look at the Dialog api where you can specifically invoke a save dialog for that purpose.
A sample code is :
const fs = require('fs');
try { fs.writeFileSync('myfile.txt', 'the text to write in the file', 'utf-8'); }
catch(e) { alert('Failed to save the file !'); }
You can of course store the file's name as well as the content's name in variables.
This will save the content in myfile.txt, which is located inside the current working directory (which you can get through process.cwd()). If you want to write, let's say in the user's home directory, you can use the app.getPath function.
const {dialog} = require('electron').remote;
var fs = require('fs');
export default {
methods: {
save: function () {
var options = {
title: "Save file",
defaultPath : "my_filename",
buttonLabel : "Save",
filters :[
{name: 'txt', extensions: ['txt']},
{name: 'All Files', extensions: ['*']}
]
};
dialog.showSaveDialog(null, options).then(({ filePath }) => {
fs.writeFileSync(filePath, "hello world", 'utf-8');
});
},
}
}

Categories