Node saving to external folder - node.js

I'd like to save all files to an external folder outside of my node application. I'm getting an error, ENOTDIR: not a directory.
backend
├──routes
│ └──savefiles.js
│
externalFolder
How do you write to the external folder?
fs.writeFileSync('../../externalFolder/report.docx', buffer);.

If backend and externalFolder are at the same level and the current working directory is the directory containing savefiles.js, then you need to up one more level with:
fs.writeFileSync('../../../externalFolder/report.docx', buffer);
The first .. gets you to the routes directory. The second one gets you to the backend directory. You need to get to the backend parent with the third .. so you can then reach into the externalFolder directory.
Note, you can debug this yourself with:
console.log(path.resolve('../../externalFolder'));
Also, you can remove a dependence on the current working directory by constructing a path using the module's directory such as:
fs.writeFileSync(path.join(__dirname, '../../../externalFolder/report.docx'), buffer);

Related

Symlink node_modules for files outside src

In my project I use a JSON file as a database (which is currently stored in local on my computer). It is modified by Node.js and some pieces of information are rendered with React in an import : import Data from 'myPath/appData.json';
I cannot have my database in the src folder because the build is static, and my databse must be dynamic.
I get this error :
Failed to compile.
./src/components/Ligne1.jsx
Module not found: You attempted to import myPath/appData.json which falls outside of the project src/ directory. Relative imports outside of src/ are not supported. You can either move it inside src/, or add a symlink to it from project's node_modules/.
I am now asking your help on how to add the symlink. I created the folder "appData" in node_modules with :
const fs=require('fs');
fs.symlink('.src/','.node_modules/app/',e=>{});
import Data from 'myPath/appData.json';
And using it in my component like :
import Data from 'appData';
but I also get the error :
Failed to compile.
export 'default' (imported as 'Data') was not found in 'appData'
I'm looking for a solution to ignore the restriction of the import outside src folder (symlink or something else : I already tried to change the configs of webpack but it didn't change anything) or another solution to get the information from my JSON file (which is currently stored in local on my computer).
Thank you for your time.
This restriction makes sure all files or modules (exports) are inside src/ directory, the implementation is in ./node_modules/react-dev-utils/ModuleScopePlugin.js, in following lines of code.
// Resolve the issuer from our appSrc and make sure it's one of our files
// Maybe an indexOf === 0 would be better?
const relative = path.relative(appSrc, request.context.issuer);
// If it's not in src/ or a subdirectory, not our request!
if (relative.startsWith('../') || relative.startsWith('..\\')) {
return callback();
}
You can remove this restriction by
either changing this piece of code (not recommended)
or do eject then remove ModuleScopePlugin.js from the directory.
or comment/remove const ModuleScopePlugin = require('react-dev-utils/ModuleScopePlugin'); from ./node_modules/react-scripts/config/webpack.config.dev.js
PS: beware of the consequences of eject.

NodeJS/CloudFoundry - failed: The app upload is invalid: Symlink(s) point outside of root folder

I'm testing CloudFoundry on IBM and are running NodeJS.
When trying to cf push my application I get the following error:
failed: The app upload is invalid: Symlink(s) point outside of root folder
In my appllcation I have the following code:
return res.sendFile(path.join(__dirname +'/tvshows/'+ guide +'.html'));
When not using path.join and simply use:
return res.sendFile(path.join('./tvshows/'+ guide +'.html'));
I get this error instead:
TypeError: path must be absolute or specify root to res.sendFile
What to do?
I've also tried stuff like path.join((process.env.BUILD_DIR || __dirname), and return res.sendFile('index.html', { root: path.join(__dirname, 'tvshows', guide) }); but no luck.
The fail came from my node_modules folder.
Adding .cfignore with node_modules/ fixed the issue.
You didn't mention the version of the cf cli that you're using, but I think that this is expected behavior starting with version 6.34.0.
push now preserves relative symlinks in app files. This makes it easier to work with Node.js apps using npm link, but note that it now errors when it detects a symlink pointing outside the app folder (e.g. a node_modules folder containing external symlinks).
https://github.com/cloudfoundry/cli/releases/tag/v6.34.0
I think you're running into the second part, "how errors when it detects a symlink pointing outside the app folder". It's nothing to do with the code in your app, but rather somewhere in your project folder there is a symlink which references another file that is not under the root of your project.
If you're on a unix-like system you can run find . -type l to find all the symlinks under the current directory. Then you just need to figure out which one is pointing outside of the project root.
Options are to remove that symlink, point it to something under your project root or use .cfignore to ignore that file (which is what you ended up doing).
Hope that helps!

How do I serve static files for my node-js server which are in my application root directory

Using app.use(express.static('public')) serves the files located under public folder
But if my files are outside the public folder in my application root directly how to serve them.
If you want to serve files in a folder outside of the current working directory, './../<dir_name>' is the way to go.
If you want to serve individual files instead of a directory, then you can use either,
app.use("/<some_url>", express.static(__dirname + '<path_to_file>'));
or
res.sendFile('<path_to_file>');
or use a simple library like, https://www.npmjs.com/package/connect-static-file.
I recommend the first approach though.
Note: replace the <text> with your file names and path names as required.
You can use ./../ to go the parent of the current folder. If you have the following structure:
project
- public
- app_folder
-- app.js
You can use './../public' as the static folder.

Requiring files in nodejs

I'm still starting out with node and learning it so excuse this if it's a stupid question. You can see my file structure in the screenshot above:
- index.js
-- app
--- dbcon.js
--- functions
---- random.s
I am trying to require app/dbcon.js from inside app/functions/random.js, if I copy this require line in app/index.js it works and if I understand correctly all of this is in relevance to the location of index.js on the root.
What am I doing wrong?
Requiring a file in Javascript is done in relative to the file in which you write the actual require statement.
No dot or slash(relative path) indicates require from node modules, single dot ./ indicates the current directory while double dot ../ indicates step back into parent directory.
Therefore, requiring dbcon.js in random.js would be ./../dbcon.js
dbcon.js is in the parent folder of random.js so you must include it by:
require('./../dbcon.js')

NodeJitsu error: Error: ENOENT, stat '/opt/run/snapshot/

My app’s folder structure for NodeJitsu is as follows (i.e., when i do a jitsu deploy, I'm in the folder that contains "server.js" - i.e., the "server" folder).
Root server
|___server.js
|___package.json
client
|___www
|___index.html
|___css
|___js
|___etc.
So at the root is the folder "server", containing the starting script, “server.js”. Then there’s a folder called “client”, parallel to "server", with a folder within that called “www”, and within “www” is the main “index.html”.
In my “server.js” file, I have the following code:
app.get(‘/’, function(req,res)
{
var aPath = path.resolve(“../client/www/”, “index.html”);
res.sendFile(aPath);
});
I don’t have a app.use(express.static(__dirname + '/somefolder'). And when I start the app, I get this error:
Error: ENOENT, stat '/opt/run/snapshot/client/www/index.html'
My process.cwd() is /opt/run/snapshot/package. Obviously the above path isn’t pointing to the location where “index.html” resides. But I thought the way I do the path.resolve(…) should point to “index.html”. I can’t see where the problem is. If “server.js” is in the root, then to get to “index.html”, which is in “client/www/index.html”, then I should need to write “../client/www”, relative to the excuting script, to get to “index.html”, right?.
Do you have any insights as to where the path is not set up correctly? What should /opt/run/snapshot/ be pointing to? Or, what changes do I need to make in the get(‘/’) handler to correctly point to my “index.html”?
EDIT
I incorrectly drew the folder structure. Now it's correct.
I also turned off the app.get() and turned on the app.use(express.static(__dirname + '/../client/www/'). But to no avail: now i get a Cannot GET / error.
What I'm ultimately after is to have the "server.js" file be the Node server that, mostly, just serves AngularJS HTML files to the browser, with attendant images, stylesheets, etc., from the "client" folder. This is the server's main role, with an additional role of authenticating the app's users, employing the very nice Satellizer module. And that's it. I have a MongoDB attached, but otherwise this is a very common and straightforward Node.js server app.
Thanks!
Try it without rooting, resolving and log out to double check:
// notice no leading / which is root. __dirname should be the dir of current file running
var staticPath = path.resolve(__dirname, '../client/www');
console.log(staticPath);
Then pass that into express.static
app.use(express.static(staticPath);
I would probably recommend following the layout and convention of express generated apps with app in the root and static files under public
/public
<static files>
app.js
Then do what the generated app does:
app.use(express.static(path.join(__dirname, 'public')));

Resources