rootDirName returning wrong part of the path - node.js

I have a Gulpfile which runs in the 'theme' folder of my project.
C:\wamp\www\mywebsitename\wp-content\themes\mythemename\gulpfile.js
In the gulpfiule, need to get the local website URL, which is basically just the 'mywebsitename' part of this path.
I have historically used this code to get it successfully:
"var rootDirName = path.basename(__dirname, '../../../');"
However I recently re-installed Windows, Node and Gulp, and now that line of code returns 'mythemename' instead of 'mywebsitename', ignoring the '../../../' argument.
If I remove that argument, it stil returns 'mythemename'.
I'm guessing some newer version of Gulp, Node or something in Windows has changed how this method works. Please can anyone suggest why this no longer works, or if there is a better way to always go 3 levels up the file tree from the gulpfile.js directory?

Worked it out myself.
const path = require('path');
var rootDirPath = path.join(__dirname, '../../../');
var rootDirName = path.basename(rootDirPath);
var url = 'http://localhost/' + rootDirName;
This will allow you to get the website's URL on localhost in Gulp and do what you need to with it (in my case, using the Critical CSS tool to scan the website and inline all the header CSS).

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"

require('../') in a script in the node_modules/.bin

I am trying to figure out how the sequelize auto script works in the node_modules directory of a node project.
The very first statement has me stumped:
var sequelizeAuto = require('../');
I don't understand why or how this works [how can you include a whole directory as a package?
Perhaps the runner (npx sequelize-auto) provides a special environment? How do I figure it out?
github: sequelize-auto script
Relative paths fallback to index.js if no file is mentioned.
var sequelizeAuto = require('../');
The above line is essentially a shorthand for :
var sequelizeAuto = require('../index.js');

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');

Overcome differences in node and browserify path resolving

I'm writing a module for a react app that needs to be included on both the backend and frontend.
At some point in my code, I'm requiring some svg file (for which I use a browserify module, but this has nothing to do with the question).
For example I have in my ./src/js/components/tools/svg.js the following bit of code:
// ...
var BACKEND = /* code to detect if this is running on browser or on node */;
var svg;
if ( BACKEND ) {
svg = require("./../../../icon/" + this.props.icon + ".svg");
} else {
svg = require("./src/icon/" + this.props.icon + ".svg");
}
// ....
I use browserify's require option to require all the svg files at bundle-time:
browserify({
paths: ['./src/icon'],
})
.transform(/* svg tansformer */)
.require(glob.sync("./src/icon/*.svg")) // <-- svg's get added here
.add("./src/main.js"); // main entry point
However this conflicts with how node resolves the filenames. It cannot find ./src/icon/ from ./src/js/components/tools/svg.js.
This is why I have to guard the require with the BACKEN clause. This breaks my eyes though and I would like to just be able to write:
var svg = require('./src/icon/' + this.props.icon + '.svg');
I've tried two things so far:
fix node to find ./src/icon
I can use export NODE_PATH=`cwd` to allow node to look for src/icon from ./. This allows me to write:
var svg = require('src/icon/' + this.props.icon + '.svg');
in the backend. But, since browserify only accepts paths that start with ./ (thus, ignoring src/icon) this will not resolve on the frontend.
fix browserify to use ../../../icon/
Haven't got this to work either because of the same reason: browserify only accepts paths that start with ./.
It's considered bad practice doing conditional requires when using Browserify because it can't evaluate the code at "compile time" and will always attempt to load all the files.
To load different files in the browser environment than on node is easy:
Add a "browser" field to your package.json that points to the browser main file. Use "main" for the node main file. Then just require the module.
You can do the same thing with sub folders within your project. Just add a package.json file with "private": true and both, the main and the browser properties and require the folder path.

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

Resources