42

Until now we could get the absolute path of a file to open later as readStream with this code snippet:

var base = path.resolve('.');
var file = base + '/data/test.csv';

fs.createReadStream(file)

Since Meteor 0.6.5 the base path is pointing to .meteor/local/build/programs/...

There is also the Assets API, which but can not give us back a path but only the read document. We but need a stream to process some bigger data files?

loomi
  • 2,936
  • 3
  • 25
  • 28
  • Hi Loomi, can you please clarify your question a bit - what is the problem created by the new base path? – Stephan Tual Aug 22 '13 at 22:17
  • @stephan-tual Hi Stephan, due to changes in Meteor, if I understand this correctly, the files are copied to a build directory before run. This means there is no realible possibility to access files manualy with nodejs internals. I am looking for a way to refer to files inside the project directory which is stable. The Assets API is doing that if I see this correctly. But it directly delivers the file. I on the other hand would need just to get the path back that I could open the file form e.g. /private/something.csv than by fs.createReadStream. – loomi Aug 23 '13 at 16:01
  • Hi Loomi, have you had a look at this package: https://atmosphere.meteor.com/package/fs ? – Stephan Tual Aug 24 '13 at 14:28
  • It was useful to know that the base path changed to .meteor/local/build/programs. Helped me find a file I'd blindly written without a full path :-) – Rikki Apr 27 '15 at 15:14
  • There's a [feature request](https://github.com/meteor/meteor/issues/3705) for getting the absolute path of an asset. – Adam Monsen May 13 '15 at 20:07
  • Good things come to those who wait: Assets.absoluteFilePath() https://github.com/meteor/meteor/pull/6440 https://github.com/meteor/meteor/blob/be986fd70926c9dd8eff6d8866205f236c8562c4/tools/static-assets/server/boot.js#L242 – loomi Jun 02 '16 at 11:15

7 Answers7

72

Another way to find your project's root directory now is this:

var base = process.env.PWD

Note that this is not the same as process.cwd(). Instead it is the directory where you ran the meteor command, which is typically what you are looking for. Note also that this probably won't be very helpful when running your app from a deployed bundle.

Christian Fritz
  • 20,641
  • 3
  • 42
  • 71
  • I don't know. I only just discovered this myself in the current version. – Christian Fritz Dec 02 '13 at 16:48
  • 4
    Its not Node application root path. only directory path and depends where you are executing this code. – anshuman Feb 24 '14 at 09:25
  • @anshuman: can you explain what you mean by "directory path"? also, which places are you thinking about when saying that it depends on where it is executed? clearly, this is not meant for the client, if that's what you are thinking. – Christian Fritz Feb 25 '14 at 17:16
  • 1
    @ChristianFritz , The Op question is to find absolute base path of 'project' directory not current working directory. Your solution would give path for current working directory only. as process.env.PWD is nothing but PWD env variable being set for current working directory (at least on linux. not sure about windows though.) – anshuman Mar 01 '14 at 11:44
  • @ChristianFritz Thank you for the advice. However this only seems to work when running my Meteor app locally. The bundled app deployed at *.meteor.com doesn't seem to accept this method. Any thoughts? – zch Apr 18 '14 at 16:22
  • On windows it is undefined. – Konard Mar 11 '16 at 20:03
  • Yeah, what is for windows? – eomeroff Mar 16 '16 at 18:23
  • This one http://stackoverflow.com/questions/18378809/find-absolute-base-path-of-the-project-directory-after-meteor-0-6-5/35948996#35948996 works for Windows – Konard Mar 18 '16 at 15:14
17

I ran into the same predicament when I updated to 0.6.5.

What I'm currently doing is getting the path like this:

var meteor_root = Npm.require('fs').realpathSync( process.cwd() + '/../' );

This returns on dev mode:

/my/application/.meteor/local/build/programs

and on bundled mode:

/my/application/build/app/programs

So from here I'm getting to my application's "root" path like so:

var application_root = Npm.require('fs').realpathSync( meteor_root + '/../' );

// if running on dev mode
if( Npm.require('path').basename( Npm.require('fs').realpathSync( meteor_root + '/../../../' ) ) == '.meteor' ){
    application_root =  Npm.require('fs').realpathSync( meteor_root + '/../../../../' );
}

The only case in which this would fail is if you happen to name your application's folder ".meteor" but that's an edge case.

Relative to that you can access whatever else you need to.

Additionally, you can also get direct access to to the assets folder that the meteor bundler creates:

var assets_folder = meteor_root + '/server/assets/' + Npm.require('path').basename( application_root );

This is likely to be temporary as I expect better file/path interaction APIs to be added eventually..

Hope that helps

0x6A75616E
  • 4,696
  • 2
  • 33
  • 57
  • Nice solution, but definitely something the framework needs to handle in the future. Are we on the same page here? – loomi Sep 27 '13 at 07:06
  • @loomi Yes, absolutely. I think they'll need better than "get file contents" APIs to make this a more usable framework. The good news is there's always reasonable workarounds ;) – 0x6A75616E Sep 27 '13 at 16:41
8

Since version 1.3, the documented function

Assets.absoluteFilePath(assetPath)

seems to be the best way to get the project path reliably.

Meteor Github

loomi
  • 2,936
  • 3
  • 25
  • 28
  • what is `assetPath`? Can I use this even when I don't have any assets? – Christian Fritz Jun 06 '16 at 21:42
  • This function returns the path of an Asset. This is finally the clean version to find the path of a file with which you like to work in your Meteor Application. If you need the absolut path without the need to address an asset I guess you create a dummy Asset and strip the non necessary part. – loomi Jun 07 '16 at 14:37
  • well, that's nice but the original question was about the project base path, not the assets path. So actually this answer is wrong. This should not be the accepted answer. – Christian Fritz Jun 07 '16 at 18:25
  • Kinda true, but I guess most people need the basepath to access some specific files related to an application. So I think it is the most robust method longterm. (See also comments on question itself.) – loomi Jun 13 '16 at 11:41
6

Hey you do not need to hardcode like the above answers... take a look to This package

After install it you can access the root path of your meteor just wih Meteor.rootPath

svelandiag
  • 4,231
  • 1
  • 36
  • 72
  • 1
    While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes. – Mike Cluck Sep 18 '15 at 19:17
  • 1
    its not a link only answer, I told him how to access the root.path with that package... – svelandiag Sep 18 '15 at 21:08
  • Does not work on Windows as of Meteor 1.2.1: https://github.com/VeliovGroup/Meteor-root/issues/3. – Konard Mar 22 '16 at 21:10
  • 1
    Fixed at ostrio:meteor-root 1.0.3 – Konard Mar 23 '16 at 04:37
4

For Meteor 0.8.3,

__meteor_bootstrap__.serverDir gives out the working directory, when run in server mode.

example

if (Meteor.isServer) {
   console.log(__meteor_bootstrap__.serverDir);
}
nshimiye
  • 144
  • 1
  • 4
3

you could get project basic root path by

process.env.PWD
Manoj Rana
  • 3,068
  • 1
  • 24
  • 34
1

As of Meteor 1.2.1, this works for me:

var absoluteBasePath = path.resolve('../../../../../.');

The same result using split:

var absoluteBasePath = path.resolve('.').split(path.sep + '.meteor')[0];

Using process.cwd():

var absoluteBasePath = path.resolve(process.cwd(), '../../../../../');
var absoluteBasePath = path.resolve(process.cwd()).split(path.sep + '.meteor')[0];
Konard
  • 2,298
  • 28
  • 21
  • And then as of Meteor 1.2.1x it could break again if they change their conventions. Using the system to do it it much safer. – dudewad Mar 18 '16 at 23:58
  • Yes, sure. How are you going to do such system? Can you offer alternative solution? – Konard Mar 22 '16 at 10:36
  • Unless your use case is less common, I would thing that the accepted answer of process.env.PWD should do the trick. But, if you run meteor from a different directory than your base directory (if that's even something anyone would even do), then you might have to get fancier. – dudewad Mar 22 '16 at 17:58
  • `process.env.PWD` does not work on Windows. And calling meteor from different directory is also possible. So do you have any ideas on how to solve the universal case? – Konard Mar 22 '16 at 18:43
  • That's a good point. It should work everywhere. This might be a stupid idea but you could get the PWD equivalent in windows using the "solution" provided by the question of this thread: https://github.com/nodejs/node-v0.x-archive/issues/2305 -- the problem there is that it's ugly. But you could use PWD in that case by calling that function when meteor starts, and adding it to Meteor.settings. Not pretty, but potentally better than having to hunt down 40 instances of path.resolve('../../../../../../.') in a year when the directory structure changes again. – dudewad Mar 22 '16 at 19:17
  • I guess the point of what I'm saying is that hard coding paths = dangerous, IMO. Doesn't mean I know how to fix it, unfortunately. – dudewad Mar 22 '16 at 19:18
  • If you look carefully I'm actually using `process.cwd()` as suggested in https://github.com/nodejs/node-v0.x-archive/issues/2305 at every line of code at the answer. There is also a reason why I specified a Meteor version, it is working and will work forever for that specific version. So if this is the reason you downvoted the answer I strongly disagree with you. – Konard Mar 22 '16 at 20:30
  • Also `path.resolve('.').split('/.meteor')[0];` gives predictable result even if the path will change inside project's folder (as long as it is in project's folder). Because we actually need first directory that contain `.meteor` folder and it seems that this actually will work longer than `path.resolve('../../../../../../.')`. – Konard Mar 22 '16 at 20:30
  • If you need a 100% guarantee to have correct result you always can make a test, for just that part of code, and move it to function or package. So as soon test starts to fail the only thing you should do is to find a better solution and fix it in one place. Why you ever will need 40 instances of that? – Konard Mar 22 '16 at 20:35