Node module for finding file paths with multiple possible roots - node.js

Is there a Node module which allows you to specify multiple roots, give it a file, and it tries to find the file?
A know a lot of libraries/modules do this sort of thing, but my Google-fu failed to turn up an existing module for it, which was kind of surprising.
To clarify, basically if I had some config like this:
roots: ['node_modules', 'bower_components', 'src']
And I asked it to find "my-file.js", it would search the following:
node_modules/my-file.js
bower_components/my-file.js
src/my-file.js
And return the first one that resolves to an existing file, or return an error saying it couldn't resolve it.

I dont know any library for this either, but what youre asking for can be done in a few lines of code :
const fs = require('fs');
const path = require('path');
const roots = ['node_modules', 'bower_components', 'src'];
const myFile = 'my-file.js';
const result = roots.map(root => path.resolve(path.join(root,myFile))).map(fs.existsSync);
This will give you an array of true/false values corresponding to each element in roots. So if src/my-file.js and node_modules/my-file.js exist, you would get result as
[true, false, true]

Related

can't find regex for my usecase in nodeJS

I'm trying to register a property from a const in a .ts file. I stringified the file through readFileSync.
The const look like this :
environment = {
prop1: value,
prop2: env.prop,
propArray: ['','',''],
prop: host + 'somestring',
cancelLink: 'myvaluetocatch'
};
What regex would match with 'myvaluetocatch' associated with the cancelLink prop ?
If you have a way to parse a const from a .ts file without using import, could be great too :p
Thanks for your help.
You could use cancelLink: '(.*?)', but this is fragile and depends greatly on the style of the code you have written in your file and may produce false matches.
Live regex tester with your specific example here.

How to develop an Import/Export Functionality for my node application

I have a configuration application in Nodejs. It has a Component with name and uuid. A Component can have many Schemas. A Schema has a uuid, name, componentId, json. A Schema can have many Configurations. A Configuration has name, schemaId, json and uuid. A Schema can contain reference of many other Schemas in it. Now I want to create a functionality of exporting all the data from one instance of the application and import it in another. What should be the simplest way to do it? a few questions are
How to tell application what to export. for now i think there should be separate arrays for components, schemas and configurations. Like
{
components: ['id1', 'id2'],
schemas: ['s1', 's2'],
configuration: ['c1', 'c2'],
}
this data should be sent to application to return a file with all information that will later be used for importing in another instance
The real question is how should my export file look like keeping in mind that dependencies are also involved and dependencies can also overlap. for example a schema can have many other schemas referenced in its json field. eg schema1 has schema2 and schema4 as its dependencies. so there is another schema schema5 that also require schema2. so while importing we have to make sure that schema2 should be saved first before saving schema1 and schema5. how to represent such file that requires order as well as overlapped dependencies, making sure that schema2 is not saved twice while importing. json of schema1 is shown below as an example
{
"$schema": "http://json-schema.org/draft-04/schema#",
"p1": {
"$ref": "link-to-schema2"
},
"p2": {
"$ref": "link-to-schema4"
},
}
What should be the step wise sudo algorithm i should follow while importing.
This is a perfect occasion for a topological sort.
Taking away components, schemas and configurations terminology, what you have is objects (of various kinds) which depend on other objects existing first. A topological sort will create an order that has only forward dependencies (assuming you don't have circular ones, in which case it is impossible).
But the complication is that you have dependency information in a mix of directions. A component has to be created before its schema. A schema has to be created after the schemas that it depends on. It is not impossible that those schemas may belong to other components that have to be created as well.
The first step is to write a function that takes an object and returns a set of dependency relationships discoverable from the object itself. So we want dependencyRelations(object1 to give something like [[object1, object2], [object3, object1], [object1, object4]]. Where object1 depends on object2 existing. (Note, object1 will be in each pair but can be first or second.)
If every object has a method named uniqueName that uniquely identifies it then we can write a method that works something like this (apologies, all code was typed here and not tested, there are probably syntax errors but the idea is right):
function dependencyInfo (startingObject) {
const nameToObject = {};
const dependencyOf = {};
const todo = [startingObject];
const visited = {};
while (0 < todo.length) {
let obj = todo.pop();
let objName = obj.uniqueName();
if (! visited[ objName ]) {
visited[ objName ] = true;
nameToObject[objName] = obj;
dependencyRelations(obj).forEach((pair) => {
const [from, to] = pair;
// It is OK to put things in todo that are visited, we just don't process again.
todo.push(from);
todo.push(to);
if (! dependencyOf[from.uniqueName()]) {
dependencyOf[from.uniqueName()] = {}
}
dependencyOf[from.uniqueName()] = to.uniqueName();
});
}
}
return [nameToObject, dependencyOf];
}
This function will construct the dependency graph. But we still need to do a topological sort to get dependencies first.
function objectsInOrder (nameToObject, dependencyOf) {
const answer = [];
visited = {};
// Trick for a recursive function local to my environment.
let addObject = undefined;
addObject = function (objName) {
if (! visited[objName]) {
visited[objName] = true; // Only process once.
// Add dependencies
Object.keys(dependencyOf[objName]).forEach(addObject);
answer.push(nameToObject[objName]);
}
};
Object.keys(dependencyOf).forEach(addObject);
return answer;
}
And now we have an array of objects such that each depends on the previous ones only. Send that, and at the other end you just inflate each object in turn.

Cannot pass array of string to function

I have this function:
function proc(unames: Array<string>){}
I try to pass it this:
import _ = require('lodash');
const usernames = _.flattenDeep([unames]).filter(function (item, index, arr) {
return item && arr.indexOf(item) === index;
});
const recipient = 'foobarbaz';
proc(usernames.concat(recipient));
I get this error:
Does anyone know how to mitigate this?
I tried this, and I get an even longer and crazier error:
function proc(unames: Array<string | ReadonlyArray<string>>){}
however, this made the error go away:
function proc(unames: Array<string | ReadonlyArray<any>>){}
not really sure what's going on.
The warning seems to be referring to the use of .concat() rather than proc().
When called on an Array, such as usernames, TypeScript is validating that the arguments given to .concat() are also Arrays.
To resolve the warning, you have a few options:
Since you're using Lodash, its own _.concat() allows for appending individual values, and TypeScript's validation should be aware of that:
const recipient = 'foobarbaz';
proc(_.concat(usernames, recipient));
Define recipient as an Array or wrap it when calling .concat():
const recipient = [ 'foobarbaz' ];
proc(usernames.concat(recipient));
const recipient = 'foobarbaz';
proc(usernames.concat( [recipient] ));
You may also be able to configure TypeScript to validate for a later version of ECMAScript. Between 5.1 and 2015 (6th edition) of the standard, the behavior of the built-in .concat() was changed to support individual values (by detecting spreadable).
For now, TypeScript is validating .concat() for 5.1 or older.

require "d3-select-multi" as node module not working

I installed d3 via npm and require it in my script directly (for some reason)
So:
npm install d3
and then
var d3 = require("d3");
works fine.
The problem is now, that I need the "d3-selection-multi"-module.
I installed it also via npm
npm install d3-selection-multi
In the d3-Doku I read you could require different modules like so:
var d3 = Object.assign({}, require("d3-format"), require("d3-geo"), require("d3-geo-projection"));
I changed that to my needs which would be to have the standard-d3-bundle (that worked already above) and add the d3-selection-multi.
var d3 = Object.assign({}, require("d3"), require("d3-selection-multi"));
That does not work however.
So I tested it by printing out the resulting object:
console.log(d3)
The result is correctly:
{version: "4.11.0", bisect: ƒ, bisectRight: ƒ, bisectLeft: ƒ, ascending: ƒ, …}
But the "d3-selection-multi"-module is not there. I can see that, because it doesn't recognize d3.selectAll().styles as a function.
I tried the following:
instead of
var d3 = Object.assign({}, require("d3"), require("d3-selection-multi"));
I just required the d3-selection-multi to see whether it works:
var d3 = require("d3-selection-multi");
and the result of console.log(d3) is
{ } An empty object.
So if this object does not contain anything the Object.assign obviously also doesn't add anything to the d3-standard-bundle. But why is it empty? Am I missing sth?
From your question, it's a little difficult to determine exactly what you're encountering that's convinced you this isn't working, so I'm working on a guess that it's this:
But the "d3-selection-multi"-module is not there. I can see that, because it doesn't recognize d3.selectAll().styles as a function.
Let's start from the beginning.
Object.assign copies enumerable properties of one or more source objects to a single target object. This is useful for creating shallow copies of objects--for example, allowing you to manipulate the target object without necessarily manipulating the source object--or to compose a new object with properties from the source objects.
const foo = { a: 1 };
const bar = { b: 2 };
const baz = Object.assign({}, foo, bar);
console.log(baz.a);
// 1
d3-selection-multi exports an empty object, as you observed. Thus, your attempt to use Object.assign resulted in the creation of an empty object, the copying of d3 enumerable properties to that empty object, and the copying of the empty d3-selection-multi object's enumerable properties--nothing--to that initial empty object.
What d3-selection-multi does, in fact, is modify the selection and transition prototypes from d3-selection and d3-transition directly.
You should be able to verify this by the following trivial example:
const d3 = require('d3');
require('d3-selection-multi');
console.log(d3.selectAll().styles);
console.log(d3.selectAll().attrs);
// [Function: selection_styles]
// [Function: selection_attrs]
That stated, you should see the same result given your original method as well:
const d3 = Object.assign({}, require('d3'), require('d3-selection-multi'));
If you are indeed able to access d3.selectAll().styles and attrs this way but still having problems, we'll need to see the exact implementing code along with console output.

Nodejs difference between two paths

I am trying to get the difference between two path. I've come with a solution, but I am not really happy about it, even if it works. Is there a better / easier way to do this?
var firstPath = '/my/first/path'
, secondPath = '/my/first/path/but/longer'
// what I want to get is: '/but/longer'
// my code:
var firstPathDeconstruct = firstPath.split(path.sep)
, secondPathDeconstruct = secondPath.split(path.sep)
, diff = []
secondPathDeconstruct.forEach(function(chunk) {
if (firstPathDeconstruct.indexOf(chunk) < 0) {
diff.push(chunk)
}
})
console.log(diff)
// output ['but', 'longer']
Node provides a standard function, path.relative, which does exactly this and also handles all of the various relative path edge cases that you might encounter:
From the online docs:
path.relative(from, to)
Solve the relative path from from to to.
Examples:
path.relative('C:\\orandea\\test\\aaa', 'C:\\orandea\\impl\\bbb')
// returns
'..\\..\\impl\\bbb'
path.relative('/data/orandea/test/aaa', '/data/orandea/impl/bbb')
// returns
'../../impl/bbb'

Resources