Evaluating module.exports in Ruby (Rails) - javascript

Currently I'm looking to try to get something in a Hash format in Ruby from JS.
I have a JS module that looks something like this
module.exports = {
key1: "val",
key2: {
key3: "val3"
}
...
}
This is given to me as just one string. I'm aware that ExecJS could be helpful here but I'm not sure what the best way to convert it to a Hash would be.
I'm currently trying to do something like this
contents.prepend("var module = {exports: {}};\n")
context = ExecJS.compile contents
context.eval('module.exports').to_hash
But when giving it a string like above I'm getting a parsing error from the JSON gem.

I just tried putting this in a script and running it:
require 'execjs'
str = <<-JS
// Note, you could just do `var module = {}` here
var module = {exports: {}};
module.exports = {
key1: "val",
key2: {
key3: "val3"
}
}
JS
context = ExecJS.compile str
puts context.eval('module.exports').to_hash
# => {"key1"=>"val", "key2"=>{"key3"=>"val3"}}
Maybe you're getting the JSON parse error because the module contains something which can't be serialized.
Here's another approach.
Make a JS file which loads the module and exports it as JSON.
var fs = require('fs');
var hash = require('path/to/my_module.js');
fs.writeFileSync('path/to/output.json', JSON.stringify(hash), 'utf8');
Run that with nodejs my_script.js then read it from Ruby:
require 'json'
hash = JSON.parse "path/to/output.json"

If the problem is the runtime, you can use mini_racer as the runtime used by ExecJS. Just include the gem:
gem 'execjs'
gem 'mini_racer'
Then you can run:
p ExecJS.runtime
# > #<ExecJS::MiniRacerRuntime:0x00007fc44ea20bd8>
Then you would setup the context first:
require 'execjs'
jscode = <<-JS
module.exports = {
key1: "val",
key2: {
key3: "val3"
}
}
JS
context = ExecJS.compile "var module = {};"
result_hash = context.eval jscode
puts result_hash["key1"]

Related

Exclude only a top level directory in Metro Bundler using blacklist regex? (blacklistRE)

I believe this to be primarily a question about regex, but I may be wrong.
Let's say I wanted to exclude the folder in my project root called art.
My output regex in the CLI looks like:
blacklistRE: /(all|the|other|matchers|art\.*)$/
But this leads to an error:
Unable to resolve "art/core/color" from "..\..\node_modules\react-native\Libraries\ART\ReactNativeART.js"
How can I exclude the top level art directory without affecting all child directories?
From the bundler's docs
blacklistRE
Type: RegExp
A RegEx defining which paths to ignore.
https://facebook.github.io/metro/docs/configuration/#blacklistre
The code of the function I'm calling:
It's short and self-contained in this file, if anyone better than me with regex might have any insight. https://github.com/facebook/metro/blob/8c53c38932c3e396109014ac707287fbdf2500d3/packages/metro-config/src/defaults/blacklist.js#L35-L44
My full code looks like:
const blacklist = require('metro-config/src/defaults/blacklist');
const regexStrings = [
// DEFAULTS
'.*\\android\\ReactAndroid\\.*',
'.*\\versioned-react-native\\.*',
'node_modules[\\\\]react[\\\\]dist[\\\\].*',
'node_modules[\\\\].cache[\\\\].*',
'packages[\\\\]electron[\\\\].*',
'node_modules[\\\\]electron.*',
'website\\node_modules\\.*',
'heapCapture\\bundle.js',
'.*\\__tests__\\.*',
'.*\\.git\\.*',
// CUSTOM
'art\\.*',
]
const constructBlacklistRE = () => {
const formedRegexes = regexStrings.map(piece => new RegExp(piece));
console.warn(formedRegexes);
return blacklist([...formedRegexes]);
};
const config = {
blacklistRE: constructBlacklistRE(),
}
This should work:
const blacklist = require('metro-config/src/defaults/blacklist');
const path = require('path');
const ignoreTopLevelFolders = [
'art'
// add more top level folders here
].map(f => new RegExp(`${ path.resolve(f) }/.*`));
module.exports = { resolver: { blacklistRE: blacklist(ignoreTopLevelFolders) } };

JavaScript get object from json file

Im new to js and i dont understand how can i take an object from json file,
for example this file : local.json
{
"server": "myname",
"url": 10.0.0.1
}
I need to get the url to insert in in my js code like this, replace the 127.0.0.1 with what i have in json file at url:
import axios from 'axios';
import jsonFile from '../local.json';
const http = require("http");
const host = '127.0.0.1'; #should be 10.0.0.1 from json file
Your json file should be:
{
"server": "myname",
"url": "10.0.0.1"
}
(use double quotes)
and just use dot:
const host = jsonFile.url
In javascript, Specific Object value can be accessed by following three ways:
DOT (.) operator
const obj = {
"server": "myname",
"url": "10.0.0.1"
};
const url = obj.url;
console.log(url); // 10.0.0.1
Square bracket ([])
const obj = {
"server": "myname",
"url": "10.0.0.1"
};
const url = obj["url"];
console.log(url); // 10.0.0.1
De-structuring (>=ES6)
const obj = {
"server": "myname",
"url": "10.0.0.1"
};
const { url } = obj;
console.log(url); // 10.0.0.1
You need to use the "dot" syntax.
const host = jsonFile.url
I assume you need to get configurations to instantiate your server.
You may like to follow below steps to instantiate settings:
Install the dependency config
It allows you to define a json file of settings.
I define the structure
you create a directory inside your project called config inside you create a json file default.json
│
config
│--- default.json
│
inside the file you write your values
{
   "server": "myname",
   "url": "10.0.0.1"
}
and to access you do the following
file = index.js
const config = require ("config");
console.log (config.get ("url"));

JSON.parse(fs.readFileSync()) returning a buffer - string of numbers

I'm using a simple Node.js to pull information from a valid jsonfile (checked with JSLint), but the code i'm using doesn't return the expected value:
squadJSON = JSON.parse(fs.readFileSync('./squads/squad' + whichSquad + '.json'));
and it returns:
{ type: 'Buffer', data:
[ 123,
10,
32,
32,
34,
97,
99,
... 548 more items ] }
Any reason as to why this happens?
fs.readFileSync() returns a Buffer if you don't specify an encoding.
https://nodejs.org/api/fs.html#fs_fs_readfilesync_path_options
So, tell fs.readFileSync() what encoding to use:
squadJSON = JSON.parse(fs.readFileSync('./squads/squad' + whichSquad + '.json', 'utf8'));
The "why" has been answered by Sidney, but a better "what to do" would be to use require(), which supports parsing valid JSON files synchronously and returning the result as an object:
squadJSON = require('./squads/squad' + whichSquad + '.json');
or even nicer, using an ES6 template literal:
squadJSON = require(`./squads/squad${whichSquad}.json`);
One notable difference using require() is that it resolves relative paths from __dirname, which is the directory path of the current module, whereas fs methods resolve relative paths using process.cwd(), or "current working directory". It is the directory within a shell session from which the main module of the program is executed by node.
Hopefully the examples below demonstrate how their relative path resolution differs:
To make require(...) behave like JSON.parse(fs.readFileSync(..., 'utf8')):
const { resolve } = require('path');
function readFileSyncJson (path) {
return require(resolve(process.cwd(), path));
}
And to make JSON.parse(fs.readFileSync(..., 'utf8')) behave like require(...):
const { resolve } = require('path');
function requireJson (path) {
return JSON.parse(fs.readFileSync(resolve(__dirname, path), 'utf8'));
}

Passing input to predefined URL path parameter in js

I am new to react, redux and axios. I am using the library to make calls to a backend. I would like to make a request with a template like /api/posts/:id. After reading the documentation it seems that axios support only query string parameters by using the params property. Is there any solution in which I could pass the parameters using the library, aside from the obvious solution of adding the parameters myself to the url?
What I understand is you want to send to api/posts/:id and not in query string like api/posts?id=someid and if that is the case then you can create the url yourself and hit it as :
const url = 'api/posts/' + id;
axios.get(url)
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
Unfortunately, at the time of this writing, there's no native predefined string formatting by object in js. You'll have to rely on string templating library such as lodash.template, mustache.js, handlebar.js.
Example:
/**
* Formatting string using lodash
* install it by:
* $ npm i lodash.template
*/
const template = require('lodash.template');
const compiled = template('/api/posts/<%= id %>/other/filter/<%= encodeURIComponent(name) %>/<%= nested.id %>');
let output = compiled({id: "12345678", name: "<good bot>", nested: {id: "777"}});
console.log(output); //output: "/api/posts/12345678/other/filter/<good bot>/777"
But in your case, this pose a problem: lodash doesn't offer an option to escape strings other than HTML, you'll have to escape it either in your template (as demonstrated with encodeURIComponent(name) in code above), or your object's value.
Another option is using mustache.js, overwrite the mustache HTML's escape function:
/**
* Formatting string using mustache
* install it by:
* $ npm install mustache --save
*/
const mustache = require('mustache');
mustache.escape = (value) => encodeURIComponent(value);
const output = mustache.render(
'/api/posts/{{id}}/other/filter/{{name}}/{{nested.id}}',
{id: "12345678", name: "<good bot>", nested: {id: "777"}}
);
console.log(output); //output: "/api/posts/12345678/other/filter/%3Cgood%20bot%3E/777"
Then you can now pass output to axios.
You can send GET parameter as a second argument in axios.
The Syntax:
axios.get(url[, config])
An example:
axios.get('/api/posts/', {
params: {
id: 12345
}
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});

Using a JSON file in JavaScript

I'm looking to use a JSON file in a Node.js project, but it doesn't seem to be working-
var JsonPath = '../../folderOfjsonFiles';
var JsonFile = JsonPath + 'test.json';
var parseThis = JSON.parse(JsonFile);
console.dir(parseThis);
Any suggestions as to what I'm doing wrong? Running this yields this error:
"test1": {
^
uncaught: SyntaxError: Unexpected token :
at Module._compile (module.js:399:25)
at Object..js (module.js:410:10)
at Module.load (module.js:336:31)
at Function._load (module.js:297:12)
at require (module.js:348:19)
Where test1 is the first JSON object in my file.
This is my JSON file-
{
"test1": {
"testname": "alpha",
"password": "password"
}
}
Even before the JSON parsing, how do I read from a file that I will store locally on the server-side? I feel like I'm overcomplicating this.
A JSON object has to be included in {} or [] at top level, so you cant do
"test1": {...},
"test2": {...}
Use
{
"test1": {...},
"test2": {...}
}
instead.
I store my Express server config in a file and read it like this:
var fs = require('fs');
var path = require('path');
var conf = fs.readFileSync(path.join(__dirname, './config.json'), 'utf8');

Categories