Can't use fs in heroku - node.js

I was codding a simple bot for discord, and I noticed that when i use fs, the app doesn't deploy. I need to access a file that is inside a folder. But when I use:
const commandFiles = fs.readdirSync('./commands').filter(file => file.endsWith('.js'));
for (const file of commandFiles) {
const command = require(`./commands/${file}`);
client.commands.set(command.name, command);
}
The app doesn't deploy, I tried to do everything in one .js file, but i really need to use modules.export
I cant even use:
const configFile = require('./config')

If whatever look here with same case as me:
console error looking as bad directory on heroku, my manually app working.
Local node.js need using / or
On Heroku you must use /
So I change this line:
const folderPath = __dirname + "\\my_modules";
to this:
const folderPath = __dirname + "\\my_modules";
I used type module so __dirname is my variable setup by package URL and path.

Related

How to load images in express js hosted on vercel

I am trying to make a GitHub banner generator using express js, my code works fine locally but when I try to host it on vercel all the image files go missing and I get no such file or directory found error.
app.get('/api',async(req,res)=>{
const title = req.query.title || "Github Banner Generator"
const subTitle = req.query.subtitle || ""
const theme = req.query.theme || "default"
const _theme = require(`./themes/${theme}/${theme}.json`)
const image = await loadImage(fs.readFileSync('themes/default/image1.png'))
const img = await new Canvas(1280, 520)
.printImage(image,0,0)
.setColor(_theme.primaryColor)
.setTextFont('bold 60px Serif')
.setTextAlign('center')
.printText(title,1280/2,520/2)
.setTextFont('20px Serif')
.setTextAlign('center')
.printText(subTitle,1280/2,(520/2)+60)
.toBuffer();
res.set({'Content-Type':'image/png'})
res.send(img)
})
I think the image path isn't right because of you didn't used an absolute path. You should read more about the difference between ./ and __dirname in NodeJS.
My solution would be to use __dirname + (the file location depending on the current file folder)
const image = await loadImage(fs.readFileSync(__dirname
+ '/themes/default/image1.png'));
Here, I assume that your project structure looks something like this...
/package.json
/index.js (contains the code)
/themes/default/image1.png

not getting data from .env file in node.js

js and i'm getting error with accessing data from .env file.
my file structure looks like this:
enter image description here
in .utils folder i have file mail.js where i need to access port and other data from .env
mail.js
require("dotenv").config({ path: "../.env" });
const port = process.env.email_port;
const host = process.env.email_host;
const user = process.env.email_user;
const pass = process.env.email_pass;
console.log("port", port); //undefined
getting undefined here.
Note: path is correct to .env and variable names are also correct.
Try to add require("dotenv").config() to the server app or to remove the { path: "../.env" } from the require-statement.

With Node.js why might dotenv trigger an error if it is not included in additional files besides app.js?

Environment: Node.js, dotenv
require('dotenv').config() is typically only required in the main file such as app.js. With that one call process.env can be referenced in every file in the app. This answer agrees with that, https://stackoverflow.com/a/58697426/12582054
However I just ran across an instance where I get an error if I don't include require('dotenv').config() in an additional file and I'm not sure why.
Simplified Example:
app.js
const path = require('path');
// Custom path to .env file.
require('dotenv').config({ path: path.join(__dirname, '/models/.env')});
const middlewareFile = require('./controllers/middleware-file');
middleware-file.js
const USPS = require('usps-webtools-promise').default;
const usps = new USPS({
userId: process.env.USPS_USER_ID,
properCase: Boolean
});
usps-webtools-promise appears to be the module triggering the error.
If I don't include the dotenv reference at the top of middleware-file.js the USPS module throws an error. It points exactly at the first letter of the value process.env.USPS_USER_ID.
throw new error_1.default("Must pass USPS userId");
USPSError [USPS Webtools Error]: Must pass USPS userId
at Object. (c:\website\controllers\middleware-file.js:35:14)
I can solve the error by adding dotenv to the top of the file.
const path = require('path');
require('dotenv').config({ path: path.join(__dirname, '../models/.env')});
Make sure to call require('dotenv').config({ path: path.join(__dirname, '../models/.env')}); as early as possible in your application. Further you can log the results or check for errors with:
const dotenv = require('dotenv').config({ path: path.join(__dirname, '/models/.env')});
if (dotenv.error) {
// Something went wrong
console.error(dotenv.error);
} else {
// Log parsed values
console.log(dotenv.parsed);
}

How to get front end to see .env contents?

I'm working on an app that has client side and server side hosted on two seperate heroku deployments. When I hard code the url in the axios call from the front end to the back end it works in the production environment:
auth.js file:
const baseUrl = 'https://url.herokuapp.com/'
function Auth() {
axios.get(baseUrl + 'api/user', test)
But if I add the following to the .env file and change the code as below it doesn't work:
auth.js file:
const baseUrl = process.env.REACT_APP_SERVER_URL || '/'
function Auth() {
axios.get(baseUrl + 'api/user', test)
.env file:
if (process.env.NODE_ENV !== 'production') {
REACT_APP_SERVER_URL = "http://localhost:3001/"
} else {
REACT_APP_SERVER_URL = "https://url.herokuapp.com/"
}
I've tried adding and installing dotenv to a route server.js file on the front end but now luck
require('dotenv').config();
Any ideas?
.env file is not a js file that you can write code. It is just plain text.
So you can use it like:
.env
REACT_APP_SERVER_URL=http://example.com
NODE_ENV=production
Then you can read it.
require('dotenv').config();
console.log(process.env.NODE_ENV);
console.log(process.env.REACT_APP_SERVER_URL );
const baseUrl = process.env.REACT_APP_SERVER_URL || '/'
axios.get(baseUrl + 'api/user', test)
In this documentation, you can find how to apply env variables via heroku config vars. https://devcenter.heroku.com/articles/config-vars

Do not see the reason I am getting a NOENT returned when I can see the file at the exact spot I am calling for it to be

I know this is very similar to other questions that have been asked on the same error. In the case I have seen though, the file name had been left off of the url. In my case (as far as I know) the url is specified as it should be and I can see the file on my localhost using other tools.
I have a need in a node.js app to perform I/O on json files without the benefit of using express routing. This is an API that has only one route (processor.js). It is accessed by a menu selection on the GUI by selecting 'Process'. From that point on everything happens within that route including multiple GETs/PUTs to json (for ids to data and then using the ids to get the data) and the building of SQL rows for populating SQL-Server Tables from the parsed json data. That, at least is the concept I am testing now. It is the hand I have been dealt, so I don't have other options.
I am using fs-extra rather than request or axios etc., because they all seem to expect express routes to accomplish the I/O. I appear to be able to directly read and write the json using fs-extra. I am using sequelize (or will be) for the SQL side.
That's the background.
Here is my processor.js (I am merely validating that I can in fact get idsList returned to me at this point):
'use strict';
// node_modules
const express = require('express');
const router = express.Router();
const fse = require('fs-extra')
// local modules
const idsList = require('../functions/getIds');
router.get('/', (req, res) => {
console.log(idsList);
});
module.exports = router;
Here is my getIds function:
'use strict';
// library modules
const express = require('express');
const router = express.Router();
const fse = require('fs-extra');
const uri = require('../uri');
// initialize general variables
let baseURL = `http://localhost:5000${uri}/`;
let idsID = 'ids.json';
const getIds = async () => {
let url = `${baseURL}${idsID}`;
try {
const idsList = await fse.readJson(url);
console.log('fse.readJson',idsList);
} catch (err) {
console.error(err);
}
}
module.exports = getIds();
And, here is my error, output to the console (it didn't format very well):
Listening on port 5000...
{ [Error: ENOENT: no such file or directory, open
'http://localhost:5000/Users/doug5solas/sandbox/libertyMutual/playground/api/ids.json']
errno: -2,
code: 'ENOENT',
syscall: 'open',
path:
'http://localhost:5000/Users/doug5solas/sandbox/libertyMutual/playground/api/ids.json' }
What am I missing?
You can use fs-extra to manipulate files and directories in your local file system only.
If you want to read files hosted on other machine over http, try using an http client like: axios.
I moved away from fs-extra to fs.readFileSync and solved the problem. It is not my preference. But it does work and the file is small, and only once.

Resources