Reading files from a directory inside a meteor app - node.js

How can i read the public directory in a meteor application inside my /server path.
I tried using the native 'fs' package but i keep getting a file/directory not found error.
var fs = Npm.require('fs');
var files = fs.readdirSync('/public/soundfiles/');
Has anyone used the filesystem package to read static files inside a meteor application?

I learned that it is best to upload files in your private folder if you are not displaying them outside.
In my case I need to store XML uploads and process them.
At first I wrote the XML into the public folder but that would trigger a reload.
Then I renamed the the upload folder to /public/.#uploads which would stop the reload of Meteor, but then again...it completely ignored that folder during build and the uploaded folder would not exist in the build (throw ENOENT error during read).
So I figured out it is best to put the files in /private/files and then reading goes as follows:
result = fs.readdirSync('assets/app/files')
Everything in the private folder will be moved to the Assets folder where during runtime there is an APP folder available (you do not see that in your build folder structure).
It helps to just simple dump result = fs.readdirSync('.') to see what folder you in and look through the structure.
***UPDATE*****
Locally putting files in private folder still triggered meteor rebuild/update (perhaps not in production..) so I found another solution using the UploadServer just to define the upload directory:
https://github.com/tomitrescak/meteor-uploads

This works for me in Meteor 1.0:
var fs = Npm.require('fs')
var xsd = fs.readFileSync(process.cwd().split('.meteor')[0] + 'server/company.xsd', 'utf8')

Access files without the "/public" part. In a running Meteor app, the public directory becomes your root, and everything that is located at /public/whatever can be accessed at /whatever.
Additionally, if you're playing around with files, you might find these useful:
FileSaver.js
CollectionFS

This is no longer true. For Meteor 0.8, the folder "../client/app" is public. Thus, use fs.readdirSync('../client/app') to get files and folders in public.
Source: personal experience and https://stackoverflow.com/a/18405793

For meteor 1.0.2 public is /web.browser/app/
Checked by entering .meteor dir
Total path in linux /home/user/your_app_name/.meteor/local/build/programs/web.browser/app/
And to get to root is `process.env.PWD or process.cwd().
Im not sure if its work deployed.
_meteor_bootstrap_.serverDir +'/assets/app'
This is path to private folder.

For Meteor 1.4, use server Assets.
See the official docs on Assets
http://docs.meteor.com/api/assets.html

On the server you can use fs to access any part of the meteor directory tree, not just /public, for example
import fs from 'fs';
const rd = process.env.PWD;
const obj = JSON.parse(fs.readFileSync(`${rd}/private/file.json`));
would read and parse a json file located at private/file.json under your meteor app directory root.

Related

How to access the base package form a node_module

I am looking to access a JSON config file that the user would place next to their package.json from a node_module package that I created. Is there a best approach to do this. I tried a relative import but that didn't really work and I am not sure how best to accomplish dynamic imports if the config file doesn't exist because I want to allow it to not exist as well.
Here is how I tried to handle dynamic imports though:
export const overrides = (function () {
try {
return require('../../../../../../overrides.json');
} catch (_err) {
return null;
}
})();
Also I tried fs but I get a browser config error I am not sure if that is something else. I should research but I didn't understand the docs around that.
using a library
This worked for me: find-package-json
Basically on any js file who needs the base, home or workspace path, do this:
var finder = require('find-package-json');
var path = require('path');
var f = finder(__dirname);
var rootDirectory = path.dirname(f.next().filename);
rootDirectory will be the location of the folder in which the main package.json exist.
If you want to optimize, get the appRootPath variable at the start of your app and store/propagate the variable to the hole nodejs system.
no libraries
Without any library, this worked for me:
console.log("root directory: "+require('path').resolve('./'));
This will get you the root directory of your nodejs app no matter if you are using npm run start or node foo/bar/index.js
More ways to get the root directory here:
Determine project root from a running node.js application
usage
If you achieve to obtain the root directory of your nodejs app and your file is at the package.json level, use this variable like this to locate any file at root level:
rootDirectory+"/overrides.json"

How to share npm modules across projects?

I'm using windows 10 x64.
I'm using dropbox to hold all my projects, and having a 'node_modules' folder inside a dropbox folder is a disaster.
First of all not all npm packages work in a way that would allow this method , because as it says in line one " does not begin with '/', '../', or './' ", so that won't work I think.
So, I tried to make syslink, but as I figured out, windows doesn't allow creating true hard links for folders, only files.
My method to create a folder junction was to have this bat file inside each project folder, and run it as administrator.
SET dest=%~dp0node_modules
SET src=F:\work\node_modules
MKLINK /J %dest% %src%
The bat file works, it creates the syslink, but 3 problems occur.
Dropbox sees it as a real folder and starts syncing it.
That folder doesn't show in the selective syncing to prevent syncing it.
npm can't use it for some reason and when I run 'npm install', It creates a new real 'node_modules' folder to replace the syslink, I get this error output:
I would not try to use junctions, they are pretty hard to work with and can lead to data loss if you don't know what you're doing.
Instead, you could go with the following approach.
Create a json config file containing the path to your modules:
{"modules_root": "F:/work/node_modules/"}
In your code, load this json and require your modules by prepending the path from your config file:
var fs = require("fs");
var modules_root = JSON.parse(fs.readFileSync("modules_root.json")).modules_root;
var express = require(modules_root + "./express")
If you ever decide to use local modules, you could just change the config file to:
{modules_root: "./node_modules/"}

Best way to find the location of a specific file within a node dependency?

I'm trying to access a file contained within a node dependency. Previously I was hardcoding access to this file in the form require('../../node_modules/foo/bar.png') however this path cannot be relied upon with npm v3 as the place in the node_modules folder hierarchy where a given dependency sits may change. require.resolve doesn't seem to help me as it gives the main file within the dependency rather than just the folder of the dependency.
Assuming you're writing both modules you can use __dirname from inside the dependency to get the path the module is running from:
//foo/index.js
module.exports.root = __dirname;
Then use that to serve the files:
//server.js
var assets = require('foo');
fs.readFile(assets.root + '/bar.png', function(){/*whatever*/});
My solution is by using https://www.npmjs.com/package/dive and assert every files.
dive(directory[, options], action[, complete]);
A common solution I have found on github in various open source projects is to use findup/findup-sync, ie
var findup = require('findup-sync');
var filePath = findup('node_modules/foo/bar.png');

Setting Up Node.js App Directory

I'm completely new to using Node.js and even utilizing the command line, so this question may be extremely elementary, but I am unable to find a solution.
I am trying to set up an app directory using Node.js and NPM. For some reason, whenever I try to use the port:5000 I get a "Cannot GET/" error. My question is, why is my setup for my app directory not working?
I have installed connect and serve-static, and yet it will not retrieve files and listen on port 5000. I have created a server.js file in my user, kstach1. Here is the code I have within that file:
var connect = require('connect');
var serveStatic = require('serve-static');
var app = connect();
app.use(serveStatic('../angularjs'));
app.listen(5000);
So, I don't quite understand why this won't reference my folder of angularjs, where I want to store my app. I have tested it by adding a file within the folder called test.html, and entered localhost:5000/test.html, and still get the "Cannot GET/test.html" error.
I know that Node is working correctly because I can enter scripts into the command line and they give the correct output. I do this as a user (kstach1).
The only thing I can think of that I may be doing wrong, is where my files are located. I have the angularjs folder located in the root user folder on my Mac (kstach1), as well as the server.js file. Is this incorrect? If this is not the issue, is it because of where Node is installed (usr/local/bin/node)? My research to this point has led me to think that my problem could also be that I need to add the installation directory to my path. However, I don't want to mess with this unless I know that is the case.
Any help would be greatly appreciated.
I did a little research on the serve-static package and copied the code you provided.
My project folder is located at "C:\teststatic" and the folder with the static files is: "C:\angularjs", also using "text.html" that is located in the 'angularjs' folder.
When running the code you provided and going to localhost:5000 it indeed returns "Cannot GET/". This is most likely because there is no "/" file declared.
Going to localhost:5000/test.html works for me, so you could try setting a "/" like this:
app.use(serveStatic('../angularjs', {'index': ['test.html', 'index.html']}));
And see if that works for you. If not, you should double check directory names / locations.
EDIT:
From reading the comment you posted: try this instead:
app.use(serveStatic('angularjs'));
I suggest moving your angularjs folder up into your main project's directory in a public/ folder. Its a pretty standard convention to have all of your static assets in public/. You can then use the path module to automatically resolve your path, inserting this where you have '../angularjs': path.join(__dirname, 'public').
So, your code would look like this:
var connect = require('connect');
var serveStatic = require('serve-static');
var app = connect();
var path = require('path');
app.use(serveStatic(path.join(__dirname, 'public'));
app.listen(5000);
And, your directory structure would look like this:
server.js
public/
angularjs/
test.html
You should then be able to use localhost:5000/angularjs/test.html to view your test.html

why I can't sendFile() in node.js express when deployed to AWS?

I am using node.js express to serve some static file like svg and json to the client, so I used sendFile() to send the files directly.
so here is my server file structures,
/root // the root of the server
/maps // put some static files
/routes/api // put the web API
in the web API
app.get('/buildings/map',function(req,res){
var mappath = 'maps/ARM-MAP_Base.svg';
res.sendfile(mappath);
})
It works perfectly on my local server to send files to the client, so it means the server could locate the file and send it. but when the server is deployed to the AWS, this methods would encounter a error - 242:Error: ENOENT, stat node.js, looks like it can't open the file in that path
I read some solutions like combining the __dirname with mappath, it didn't work since it would bring to the path of /routes/api/maps/...
so far I have no idea why it works on my local computer but fail to work on the AWS
Relative fs paths like mappath will be resolved from the current working directory, which isn't guaranteed to be consistent. It works locally because you're executing your application with /root as your working directory.
This is why you're finding recommendations to use __dirname, which an be used to resolve paths relative to the current script.
Though, along with it, you'll want to use ../ to resolve parent directories.
var mappath = 'maps/ARM-MAP_Base.svg';
res.sendfile(__dirname + '/../../../' + mappath);
This assumes the current script is located in and __dirname would be /root/maps/routes/api as the indentation in your directory tree suggests.

Resources