NodeJS reading and producing SAS files: xport and sas7bdat - javascript

I have been looking around for a way to digest and export SAS files using NodeJS. I guess it can be done by means of:
C++ extension to NodeJS
Some sort of JavaScript framework
I couldn't find anything ready made on the Internet. I haven't tried to cook one up myself. I am not considering other options such as to get SAS to export CSVs. I assume that SAS is not available to NodeJS.
Does anyone know of any ready made way of making NodeJS to work with xport and sas7bdat files?
Regards,
Vasilij

I just made this for sas7bdat files: https://github.com/dumbmatter/sas7bdat-js
It's a pure JS module for reading sas7bdat files in NodeJS. Install with:
npm install sas7bdat
Then load the module:
const SAS7BDAT = require('sas7bdat');
SAS7BDAT.createReadStream returns a stream that emits individual rows, one at a time:
const stream = SAS7BDAT.createReadStream('test.sas7bdat');
stream.on('data', row => console.log(row));
stream.on('end', () => console.log('Done!'));
stream.on('error', err => console.log(err));
SAS7BDAT.parse returns a promise that resolves to an array containing all the rows:
SAS7BDAT.parse('test.sas7bdat')
.then(rows => console.log(rows))
.catch(err => console.log(err));

Related

Javascript promise never resolves

I am using rotateByDegrees from a library called node-poweredup in a typescript project:
motor.rotateByDegrees(20,10).then(function(value) {console.log("test");}, function(value) {console.log("error");});
I would expect to see "test" after successful completion, but the promise never resolves. If I use await, it hangs on the await line forever.
Replicating the syntax that appears to be used in the rotateByDegrees function:
let promise = new Promise((resolve) => { return resolve(); });
does not compile, I get error TS2794: Expected 1 arguments, but got 0. Did you forget to include 'void' in your type argument to 'Promise'? I can make it compile and behave as expected with resolve(true), but how does it compile in the library then? Do I misunderstand promises? Some feature in typescript? A bug in the library? I am a newbie to JavaScript, I don't want to over-complicate this question by including irrelevant details. If you can give me hints on what I am missing and how to debug this, I can provide all relevant details.
Thanks to the helpful comments I was able to narrow it down to the compilation of the library. I did in fact not use a pre-compiled binary but had to compile the library myself using electron-rebuild to make the bluetooth adapter work. I did the following test:
git clone https://github.com/nathankellenicki/node-poweredup.git
cd node-poweredup
npm install
npm run build
this compiles without error. I created the following test file
const PoweredUP = require("node-poweredup");
const poweredUP = new PoweredUP.PoweredUP();
poweredUP.scan(); // Start scanning for hubs
console.log("Looking for Hubs...");
poweredUP.on("discover", async (hub) => { // Wait to discover hubs
await hub.connect(); // Connect to hub
console.log(`Connected to ${hub.name}!`);
const motorA = await hub.waitForDeviceAtPort("A"); // Make sure a motor is plugged into port A
motorA.rotateByDegrees(20,10).then(function(value) {console.log("test");});
});
and get the expected output:
node-poweredup$ node test.js
Looking for Hubs...
Connected to MyHub2!
test
Connected to MyHub3!
test
When I changed the first line to
const PoweredUP = require(".");
to make it use my self-compiled binary I get
node-poweredup$ node test.js
Looking for Hubs...
Connected to MyHub2!
Connected to MyHub3!
Of course this is only a partial answer because I still don't know why it compiles differently on my machine, but at least I have an idea where to start searching for the problem.

How to select the test I want to run via Nightwatch Programmatic API

I am currently working on creating a web app that allows me to run Nightwatch tests from a graphic interface. Right now I can run all my tests with a post request from my web app I am using Nightwatch Programmatic API.
My question is can I chose the folder of tests I want to run from a post request, here is my code,
Thank you.
router.post('/exec', function (req, res) {
Nightwatch.cli(function (argv) {
argv.config = 'nightwatch.conf.js';
argv.source= 'folder of tests i want to run';
const runner = Nightwatch.CliRunner(argv);
runner
.setup()
.startWebDriver()
.then(() => {
return runner.runTests()
})
.then(() => {
return runner.stopWebDriver()
})
.catch(err => console.error(err));
});
})
As you know, the config file is exported as an object. If you are able to read the file contents and store it into a variable, you can try to override the property src_folders.
const red = require('../nightwatch.conf');
console.log(red.src_folders)

How can I call a Javascript function in python?

I'm trying to make a snake game with Electron and deep reinforcement learning. The reinforcement learning stuff I do in python and the game in Javascript. Now how can I call a function like this in python?
makeSomeThing(x) {
}
or
getValue() {
return x;
}
Please build your python script to an executable binary file. You can use pyinstaller to package your python scripts to a standalone executable file.
Then you can spawn this binary file at your Electron project like this.
import { spawn } from 'child_process';
// in my case I'm storing the file at bin directory at the root path of the application
// You can change this whatever you want
const pythonPath = const basicURL = process.env.NODE_ENV === 'development'
? path.join(__dirname, './bin/xxxx')
: path.join(process.resourcesPath, 'bin', 'xxxx');
const params = ['arg1', 'arg2']; // params that your python scripts need.
const pythonChildProcess = spawn(pythonPath, params);
pythonChildProcess.stdout.on('data', data => {
console.log(`stdout: ${data}`);
// Here is where the output goes
});
pythonChildProcess.stderr.on('data', data => {
console.log(`tderr: ${data}`);
// Here is where the error output goes
});
pythonChildProcess.on('close', code => {
console.log(`closing code: ${code}`);
// Here you can get the exit code of the script
});
Well, I don't know if it is the answer that you expect, but I would create a standalone python service that exposes some API.
Create a client in electron and use python API to send data and get processed information from the Python service
You cant call Javascript API from python. You need something in the middle anyway.

Use Octokit or the GitHub Rest API to upload multiple files

I'm trying to write a method which takes files from a path and uploads them to a GitHub repo. The files have to remain intact and separate (can't zip them). This is what I've got so far:
addFiles(branch) {
const filePath = this.filePath
fs.readdirSync(filePath).forEach((file, index) => {
if (file.match('.txt')) {
const fileData = fs.readFileSync(path.resolve(filePath, file));
this.octokit.repos.createOrUpdateFile({
owner,
repo,
path: `test/${file}`,
branch,
message: `Commit ${index}`,
content: encode(fileData)
})
.catch(err => console.log(err))
}
})
}
This works to a point but it will only upload one file and then fails with the following error:
PUT /path/to/repo/contents/test/example.txt - 201 in 1224ms
PUT /path/to/repo/contents/test/example-2.txt - 409 in 1228ms
{ HttpError: is at 90db2dadca8d061e77ca06fe7196197ada6f6687 but expected b7933883cbed4ff91cc2762e24c183b797db0b74
at response.text.then.message (/project/node_modules/#octokit/request/dist-node/index.js:66:23)
Even if this worked fine though, it still wouldn't be ideal as this project is likely to scale to the point where hundreds of files are being uploaded at once, is there a way to just upload a directory or upload multiple files per commit? Failing that, can anyone solve my error?
I worked it out in the end. createFile isn't the right way to go, it should be done with createTree: https://octokit.github.io/rest.js/#octokit-routes-git-create-tree
It wasn't as simple as creating just the tree though, you also have to create a commit and then update the reference, I followed this GitHub issue for guidance:
https://github.com/octokit/rest.js/issues/1308

Execute a JS file (with logs, etc...) inside another NodeJS process

Here is my problem, I want to create a CLI that automatically runs a test. Without the CLI, I'm able to run everything perfectly with the node command:
node test.js
Basically, I want to do the exact same thing as the command before, so I googled for a technique that does this. I found this:
#!/usr/bin/env node
'use strict';
const options = process.argv;
const { execFile } = require('child_process');
const child = execFile('node', ['../dist/test.js'], (error, stdout, stderr) => {
if (error) {
throw error;
}
console.log(stdout);
});
This method doesn't work for me because, in the test.js file, I'm using the ora package. And because this package is making real-time animations, it doesn't come in stdout.
Is there any way of executing in real time (without subprocess) my test.js using Node? I'm open to other methods, but I want to publish the CLI on NPM, so keep in mind that it has to be in JavaScript 😊.
You can find every file that I've talked here on GitHub. Normally, you wouldn't need this link, but I'm giving it to you if you need to have a closer look.
You should simply call your test() function from your CLI code, after requiring the module that defines it. Have a look at mocha and jasmine: you will see that while both tools provide a CLI, they also provide instructions for invoking the test frameworks from arbitrary JS code.
I can't think of a way without a sub-process. but this may help.
The child process exec will not work with the continuous output commands as it buffers the output the process will halt when that buffer is full.
The suitable solution is spwan :
var spwan = require('child_process').spwan
var child = spwan('node', ['../dist/test.js'])
child.stdout.on('data', function(data) {
console.log(data)
})
child.stderr.on('data', function(data) {
console.log(data)
})
Here is my solution, you can use the fs library to get the code of the file, and then, you simply use eval to execute in the same process.
const fs = require("fs");
function run(file) {
fs.readFile(file, (err, data) => {
eval(data.toString('utf8'))
})
}

Categories