cannot find a module from a different database in marklogic - javascript

OK i have a MarkLogic 9.0.2 database in which I have two applications deployed. Lets say A and B. Now I want to run some code inside B from A, we can do this with the xdmp.eval() but the code I want to run needs to find a module deployed in the modules database of B.
I cannot seem to get this working.
Code run inside database B works :
declareUpdate();
var prj = require('/root/lib/project-lib.xqy');
prj.createProject('giraffe', 'A project about giraffes');
finds and runs the createProject function in the module library...
Now from database A I try to run this by an xdmp.eval() like so:
declareUpdate();
var options = { "isolation" : "different-transaction",
"database" : xdmp.database("data-hub-FINAL"),
"modules" : xdmp.database("data-hub-MODULES")
}
xdmp.eval("declareUpdate();var prj = require('/root/lib/project-lib.xqy');prj.createProject('fromcluey giraffe', 'A project about giraffes from cluey');"
, options);
But gives me:
[javascript] XDMP-MODNOTFOUND: declareUpdate();var prj = require('/root/lib/project-lib.xqy');prj.createProject('fromcluey giraffe', 'A project about giraffes from cluey'); -- Module /root/lib/project-lib.xqy not found
Can someone tell me how I am supposed to find the project-lib.xqy module from inside A?

Document permissions was the first thing I was thinking of, which also applies to modules, schemas, triggers etc, not just to documents. Privileges second. Modules root can definitely be important as well.
However, there is a simple typo in the above xdmp.eval that is the biggest culprit here: the function takes 3 arguments, not 2. And options is the 3rd, not the second.
It should be: xdmp:eval("...", null, options).
HTH!

Related

Is there a way to read JS code as part of a JS file from another JS file ? (The app uses NodeJS)

I am working on a web app using NodeJS. The concept is : the main structure, to which you add the tools you want depending on what you want in your app.
To achieve that, I want my main JS file (index.js) to read the content of another file (tool.js) as if it was part of the code.
I know I can require a module in NodeJS and call a function from it, but this isn't what I want as I don't want to put the content of the file in a function. Here is an example of what I would like to achieve :
tool.js :
// tool.js
// This executes various actions.
var web_func = require(web_funcs.js); // another module, not important
web_func.executeAction();
console.log('whatever');
index.js :
// index.js
// This is the main file
/*Here I want to call tool.js*/
The goal is to have index.js be read as this :
// index.js
// This is the main file
// tool.js
// This executes various actions.
var web_func = require(web_funcs.js); // another module, not important
web_func.executeAction();
console.log('whatever');
The reason behind this is that I want my mainframe to be easy to deploy with minimal adjustments, and everything regarding the tools to be handled in a different file to make it easier to read.
And since there are several tools and the number will probably grow, I want it to be easily set-up.
If you have any idea or solution, please let me know, as it would be of great help. I've tried looking around but didn't find anything.
EDIT : changed the title of the question for better clarity.
You can read the file first and then use the eval() method to execute the code in string.
Read the code and call eval using this sample:
my-file.js
var a = "test";
console.log(a);
Code:
var fs = require('fs');
var code = fs.readFileSync('my-file.js', 'utf8');
eval(code);
Output:
test
Edit 1:
You can also reuse the variables from the other file in this way. For example, add console.log(a) after the eval(code) line.
...
eval(code);
console.log(a);
The output will be:
test
test

Marklogic Server Side Javascript: XDMP-CONFLICTINGUPDATES while using explicit commit

I've been having problems with conflicting updates in Marklogic. I'm aware of the cause, but I don't know how to fix it.
I have 1 main (.sjs) file which calls two different (.sjs) files which both update a set of documents. In the main file I use: declareUpdate({explicitCommit: true}); and then in the separate files I use the command xdmp.commit(); after updating the documents. However, I'm still getting: XDMP-CONFLICTINGUPDATES.
Part of the code: Main.sjs:
function main(){
declareUpdate({explicitCommit: true});
function.to.file.1();
function.to.file.2();
}
file1.sjs:
//make some docs and insert them into ML
function file1Function(){
for (let d of someCollectionOfData) {
xdmp.documentInsert('/a/uri/filexx.json', d, {collections: aCollectionName1});
};
xdmp.commit();
}
file2.sjs:
//adjust docs made in file1 and put them back into ML
funtion file2Function(){
for (let d of xdmp.directory('/location/of/aCollectionName1/','infinity')) {
let dObj = d.toObject();
dObj.addSomething = 'something';
xdmp.documentInsert(fn.documentUri(d), dObj, {collections: aCollectionName1});
}
xdmp.commit();
}
It must mean your file1 is located inside '/location/of/aCollectionName1/'. Keep in mind that MarkLogic doesn't commit immediately when you invoke xdmp.commit(). Actual persisting is always postponed until after all code has executed. It therefor doesn't make much sense to invoke xdmp.commit() more than once in one request. You won't be able to read your updates after xdmp.commit().
HTH!

Execute 'fc -ln -1' (bash history) in node.js spawn

I've been searching for an answer and I couldn't find one (perhaps I'm not searching well). The issue is as follows:
var spawn = require('child_process').spawn;
var proc = spawn('fc', ['-ln', '-1']);
proc.stdout.on('data', function (data) {
console.log(data.toString('utf-8'));
});
proc.stderr.on('data', function (data) {
console.log('Error: ' + data.toString('utf-8'));
});
proc.on('close', function (code) {
console.log(code);
});
When I run this node script, it outputs '0' and nothing else. Apparently spawn works, but it doesn't output the history. I've tried with many combinations, but fc command simply doesn't output anything. I've also tried with exec and execSync. Neither output anything.
Is there a way to get the bash history from node.js? What am I missing?
Update:
According to this, bash history commands can't be output inside a shell script. That might mean that from spawned child processes, it still holds true. I gave up trying to get the last used command, since Etan made me realize that there's no easy way to tell the "last used command" in interactive multi sessions. I am now trying to read the $HISTFILE shell var (history file location) from inside Node with no luck yet.
Any ideas?
Update 2:
I just hardcoded most used shells history routes (bash, zsh, fish) and read the file directly. However I'll leave this open since I learned a lot about shell scripting, and hopefully this will help someone else. The key vars to use in Node (at least in Mac) are process.env.SHELL and process.env.HOME, to build the file route.

pre-processing data into a hard-coded array

I have a question about hard-coded arrays. I looked at several previously posed questions about hard-coded arrays in hopes of getting my answer that way. But, for the most part, I don't understand the answers, and this is the only one that seems like it might be relevant:
glob() to build array of files, or hardcode array? Speed is key, but automation is nice
My question is a lot simpler, though. I have several worksheets in an OpenOffice spreadsheet which I have chosen to pre-process into a large hard-coded array which I will then store inside my 'server' dir. In order to test this, I put the following lines of code into a file called 'distances.js' and placed that file in a 'server' folder directly inside my app directory:
var distances = {};
distances['Salt Lake City.Washington, DC'] = 2080;
distances['Salt Lake City.Cheyenne'] = 434;
distances['Salt Lake City.Denver'] = 536;
distances['Salt Lake City.Carson City'] = 534;
Then I ran the following command in my console to see if I'd be able to access these array values in my app:
console.log(distances['Salt Lake City.Carson City']);
The result I got was:
Uncaught ReferenceError: scores is not defined(…)
I then attemped to insert those lines inside the regular project.js file inside the Meteor.startup function inside of Meteor.isServer:
if (Meteor.isServer) {
Meteor.startup(function () {
// code to run on server at startup
var distances = {};
distances['Salt Lake City.Washington, DC'] = 2080;
distances['Salt Lake City.Cheyenne'] = 434;
distances['Salt Lake City.Denver'] = 536;
distances['Salt Lake City.Carson City'] = 534;
});
}
This resulted in the same error.
I have the 'insecure' package installed in my project, so security shouldn't be an issue. I think I'm just missing something fundamental about where code needs to go in order to be seen by the compiler/interpreter. Can anyone help?
I'm sort of half expecting someone to suggest that I put all of this information into a collection. I don't currently understand why it would be advantageous to do so, but maybe I'm missing something fundamental about the usefulness of doing it this way. If so, could someone explain or point me to a place where I can read about this for myself? I have worked through a couple of meteor tutorials, most recently Your Second Meteor Application. And these are excellent tutorials from which I've learned a lot. But I feel like there are still holes in my knowledge which need to be addressed, this being a prime example.
My plan is to access these hard-coded array elements through a function call which looks something like this:
getDistance('Salt Lake City','Cheyenne')
Because I don't store backwards values, eg. the distance from Cheyenne to Salt Lake City, I intend to set up the function so that, if a specific reference is undefined, it will turn the two elements around and call the function again the same way but with those inverted values (ie. getDistance('right','left') in place of getDistance('left','right')).
But, currently, I can't even get past step one.
Thanks in advance for any assistance you can provide me with.
The answer would seem to be to use the fs module to read data out of your textfile and into your collection. I'm still working on getting that going, but there's more info here: Using nodejs fs module within my meteor app

node.js: How to include external .js from another server?

I am trying to include .js files that are located on another server into my node.js program. Is this possible?
I can´t use require('./local_file.js') and get something over the Internet like this: require('http://www.server.com/path/file.js');
I´ve tried to make a http.request and then use eval(), but the scope is all wrong and the functions inside the external file remain undefined:
var source_string = load_contents_via_http('http://www.server.com/folder/file.js');
var source_string += '\n run_my_function();';
eval(source_string);
Does anyone have any suggestions?
Edit (Solution):
I solved my problem by repacking the essential parts into the script that runs on my local server, as mentioned by #zackehh. Then I used http.request to load and eval specific parts from the remote server when needed. Since the most important code was running on the server locally, the imported extra code was easier to add.
Here is a example on how I solved the problem:
var EssentialObject = {};
EssentialObject.ServerFunctions = {};
EssentialObject.ServerFunctions.Init = function (){
var external_code = load_contents_via_http('http://www.server.com/file.js');
var eval_this = external_code.substr(
external_code.indexOf('EssentialObject.Addons = {}'),
external_code.indexOf('// End of EssentialObject.Addons')-external_code.indexOf('EssentialObject.Addons = {}')
);
eval ( eval_this );
eval ( "EssentialObject.Addons.test=true; console.log('Eval Done')" ); // Check if it works
};
Disclaimer: this technically isn't an answer to the question, I feel it should be classed as one, as it moves towards a solution to the problem.
You could do it with a simple http request, but I don't recommend it. You would be better off repacking the things you need on both servers in npm modules and requiring them in. This allows you share your code pretty painlessly. If you don't want your code public, npm also has new private module options.

Categories

Resources