Node cli argument parser for git-like commands - javascript

I am looking for a simple git-like cli argument parser like this:
$ app [global-options] command [command-options]
I tried commander, gitlike-cli, and few other cli parser libs---none of them seem to support segregation of global options from command-options.
commander seems to be supporting it. But when I delved deeper, I found issues. For example, I wanted a -v global option that would enable verbosity at global level. All I did was to set global.verbose = true; in index.js, and in the command specific index-subcmd.js, when I read global.verbose, it is not set!
Am I missing something obvious, or is my understanding correct that node ecosystem is lacking a lib with this functionality? Coming from Java background, I really miss airline.

I wrote a cli parsing library to support the usecase: wiz-cliparse.

I would also like to point out a library I wrote after being disappointed with the popular CLI tools. I created wily-cli to compete against those big name tools by providing more customization and CLI features, and attempting to be easier to use. Subhash's wiz-cliparse should definitely be able to help your use case, but if you need to create a more powerful CLI, I might recommend looking into wily-cli. For your use case, those "global options" would essentially be the the options of your initial command (from your example, that would be app). When creating an option, you would set the passThrough flag in the option configuration...
.option('example', 'Example option', { passThrough: true });
This will set the option to also be passed down to children/gandchildren/etc. commands

Related

How to use node Buffer module in a client side browser - detailed explanation required please

First things first. I know that there are other questions that are similar to this e.g. use NodeJs Buffer class from client side or
How can I use node.js buffer library in client side javascript
However, I don't understand how to make use of the reference to use browserify though it is given approval.
Here is my Node code:
import { Buffer } from 'buffer/';
I know this is the ES6 equivalent of require.
I would like a javaScript file implementation of this module so that I can simply use the standard html file reference:
<script src=./js/buffer.js></script>
And then use it as in for example
return new Buffer(temp).toString('utf-8');
This simply falls over with the
Uncaught ReferenceError: Buffer is not defined
no matter how I create the buffer.js file.
So using the browserify idea I've tried using the standalone script (from the https://www.npmjs.com/package/buffer as https://bundle.run/buffer#6.0.3 )
I've created a test.js file and put
var Buffer = require('buffer/').Buffer
in it and then run browserify on it as
browserify test.js -o buffer.js
and many other variations.
I'm not getting anywhere. I know I must be doing something silly that reflects my ignorance. Maybe you can help educate me please.
These instructions worked for me. Cheers!
Here are the instructions you can look at the web section.
https://github.com/feross/buffer
Here is what the instructions state about using it in the browser without browserify. So from what you tried
browserify test.js -o buffer.js
I would just use the version directly that does not require browserify
To use this module directly (without browserify), install it:
npm install buffer
To depend on this module explicitly (without browserify), require it like this:
var Buffer = require('buffer/').Buffer // note: the trailing slash is important!

can I run a package that is installed on the "client" project from my own project?

I know this sounds like a weird question, let me try explaining it further with examples:
First of all, I'm trying to add some functionality to JSDoc in a simple library. Let's call it jsdoc-extra.
When a project includes my library, it should also have jsdoc installed. I have listed jsdoc as a dependency on my own library as well.
jsdoc-extra > package.json
{
[...]
"dependencies": {
[...]
"jsdoc": "^3.6.6",
[...]
}
}
And let's suppose a "sample" project is trying to use my library (this is what I actually have running for now, installed from the file)
{
[...]
"dependencies": {
"jsdoc": "^3.6.6",
"jsdoc-cov": "file:../jsdoc-cov",
"jsdoc-ts-utils": "^1.1.2"
}
}
From my jsdoc-extra code I can search and find the sample/node_modules/jsdoc/jsdoc.js that is installed on the "client" application (sample), or use my own jsdoc-extra/node_modules/jsdoc/jsdoc.js instead when the first one is not available. I can then execute it with spawn
So far so good. However:
The "client" (sample project in this case) might be using some plugins on their jsdoc setup, like you can see in the previous code snippet, I have ts-utils installed as an example.
So when I'm inside the sample project, and try running:
node_modules/jsdoc/jsdoc-extra.js -c jsdoc.json
(jsdoc.json is the standard jsdoc config file that I just pass through to it)
I get this kind of errors:
(node:3961) UnhandledPromiseRejectionWarning: Error: ERROR: Unable to find the plugin "jsdoc-ts-utils"
It seems my app (jsdoc-extra) cannot use jsdoc-ts-utils that is installed on the client (sample) project, even when I run sample's own installed jsdoc.
I want to be able to execute it like this so the "client" project can execute jsdoc-extra without extra jsdoc configuration, it will use whatever it's already using for regular jsdoc operations.
I'm beginning to think that my best options is to actually write a jsdoc plugin...
I know this is a lot, and probably confusing, I'll gladly provide more info if you think it's necessary. Thanks!
I decided to close this and instead just write a jsdoc plugin. It's the easier way to hack into the data it generates to do what I want. My extra functionality will be tied in with the doc generation, which is not ideal, but I'll deal with it...

Using Jest, getting internal function

I am just re-looking at Jest as it's been getting a lot of good reports. However struggling to find a good way the access internal functions to test them.
So if I have:
const Add2 = (n)=> n+2;
export default (list)=>{
return list.map(Add2());
}
Then if I was using Jasmine or Mocha I'd use rewire or babel-plugin-rewire to get the internal Add2 function like this:
var rewire = require('rewire');
var Add2 = rewire('./Adder').__get__('Add2');
it('Should add 2 to number', ()=>{
let val = Add2(1);
expect(val).toEqual(3);
});
However neither of them seem to work with jest and while there looks like an excellent mocking syntax I can't see any way to get internal function.
Is there a good way to do this, something I'm missing on the jest api or set up?
You can actually achieve this if you are willing to use babel to transform your files before each test. Here's what you need to do (I'll assume you know how to get babel itself up and running, if not there are multiple tutorials available for that):
First, we need to install the babel-jest plugin for jest, and babel-plugin-rewire for babel:
npm install --save-dev babel-jest babel-plugin-rewire
Then you need to add a .babelrc file to your root directory. It should look something like this:
{
"plugin": ["rewire"]
}
And that should be it (assuming you have babel set up correctly). babel-jest will automatically pick up the .babelrc, so no additional config needed there unless you have other transforms in place already.
Babel will transform all the files before jest runs them, and speedskater's rewire plugin will take care of exposing the internals of your modules via the rewire API.
I was struggling with this problem for some time, and I don't think the problem is specific to Jest.
I know it's not ideal, but in many situations, I actually just decided to export the internal function, just for testing purposes:
export const Add2 = x => x + 2;
Previously, I would hate the idea of changing my code, just to make testing possible/easier. This was until I learned that this an important practice in hardware design; they add certain connection points to their piece of hardware they're designing, just so they can test whether it works properly. They are changing their design to facilitate testing.
Yes, you could totally do this with something like rewire. In my opinion, the additional complexity (and with it, mental overhead) that you introduce with such tools is not worth the payoff of having "more correct" code.
It's a trade-off, I value testing and simplicity, so for me, exporting private functions for testing purposes is fine.
This is not possible with jest. Also you should not test the internals of a module, but only the public API, cause this is what other module consume. They don't care how Add2 is implemented as long as yourModule([1,2,3]) returns [3,4,5].

How to use ember.js without module support

The guides for ember.js are assuming one has the full ES6 support e.g. http://guides.emberjs.com/v2.2.0/routing/specifying-a-routes-model/ shows using the export default construct and doesn't specify any alternative way to achieve the goals. However the module feature is not implemented in all browsers that ember is supporting.
How can I use these features with a browser that doesn't support modules? How would the code in these examples translate to ES5?
Documentation assumes you are using a transpiling tool, because the recommended tool, ember-cli does. Unless you have good reasons not to use it, you definitely should look into it.
It is, however, perfectly fine to work without it. For instance, without a module system, Ember will map controller:posts.index to App.PostsIndexController. So this should work for the example you linked:
App.Router.map(function() {
this.route('favorite-posts');
});
App.FavoritePostsRoute = Ember.Route.extend({
model() {
return this.store.query('post', { favorite: true });
}
});
You may also use Ember with your own module support. I successfully have an Ember project based on rollup. It does require a bit more work though, to have the resolver find your classes (that resolver link also documents how ember relates does the name mapping). Nothing hard, but you must build a short script to generate registrations.
Edit for blessenm: Ember with rollup
Unfortunately I cannot share this code, but it works like this:
A script scans the project directory and compiles templates by invoking ember-template-compiler.js on every .hbs file it encounters.
A script (the same one, actually) scans the project directory and generates the main entry point. It's pretty simple, if it sees, say gallery/models/collection.js and `gallery/routes/picture.js', it will generate a main file that looks like this:
import r1 from 'gallery/models/collection.js';
import r2 from 'gallery/routes/picture/index.js';
// ...
Ember.Application.initializer({
name: 'registrations',
initialize: function (app) {
app.register("model:collection", r1);
app.register("route:picture.index", r2);
// ...
}
});
It should just map your filenames to resolver names. As a bonus, you get to control how your directories are organized.
Invoke rollup on the generated file. It will pull everything together. I use IIFE export format, skipping all the run-time resolution mess. I suggest you setup rollup to work with babel so you can use ES6 syntax.
I don't use any ember-specific module, but it should not be too hard to add. My guess is it's mostly a matter of setting up rollup import resolution properly. For all I know, it may work out of the box.
You should look into using Ember CLI http://ember-cli.com/
You write your code in ES6 and it transpiles down to ES5.

Calling Node.js script from Rails app using ExecJS

I have a Rails application that needs to run a node script. I imagine that using the ExecJS gem is the cleanest way to run JavaScript from a Rails app. However, so far, ExecJS has proved to be very frustrating to use.
Here is the script I need to run:
// Generated by CoffeeScript 1.7.1
(function() {
var PDFDocument, doc, fs;
fs = require("fs");
PDFDocument = require('pdfkit');
doc = new PDFDocument;
doc.pipe(fs.createWriteStream('output.pdf'));
doc.addPage().fontSize(25).text('Here is some vector graphics...', 100, 100);
doc.save().moveTo(100, 150).lineTo(100, 250).lineTo(200, 250).fill("#FF3300");
doc.scale(0.6).translate(470, -380).path('M 250,75 L 323,301 131,161 369,161 177,301 z').fill('red', 'even-odd').restore();
doc.addPage().fillColor("blue").text('Here is a link!', 100, 100).underline(100, 100, 160, 27, {
color: "#0000FF"
}).link(100, 100, 160, 27, 'http://google.com/');
doc.end();
}).call(this)
From my Rails console, I try this:
[2] pry(main)> file = File.open('test.js').read
[3] pry(main)> ExecJS.eval(file)
ExecJS::ProgramError: TypeError: undefined is not a function
from /Users/matt/.rvm/gems/ruby-2.1.0/gems/execjs-2.0.2/lib/execjs/external_runtime.rb:68:in `extract_result'
Note that I can run this script successfully using 'node test.js' and I am also able to run run the script using the backtick syntax Ruby offers:
`node test.js`
But that feels like a hack...
It's erroring out because require() is not supported by EvalJS. 'require' is undefined, and undefined is not a function. ;)
I'm not sure of the answer but maybe you need to precise the exec_js_runtime environment variable to be node.
Something like ENV['EXECJS_RUNTIME'] = 'Node' You can try to put it in the config/boot.rb or just to define the EXECJS_RUNTIME in your environment, something like export EXECJS_RUNTIME=Node
Hope it helps
ExecJS people say use commonjs.rb https://github.com/cowboyd/commonjs.rb
Why can't I use CommonJS require() inside ExecJS?
ExecJS provides a lowest common denominator interface to any
JavaScript runtime. Use ExecJS when it doesn't matter which JavaScript
interpreter your code runs in. If you want to access the Node API, you
should check another library like commonjs.rb designed to provide a
consistent interface.
But this doesn't work basically. The require acts completely erratically - I had to execute npm -g install pdfkit fs between env = and env.require in
require 'v8'
require 'commonjs'
env = CommonJS::Environment.new(V8::Context.new, path: ::Rails.root )
env.require 'script'
for the module lookup to work O.o and if I tried pointing path to the node_modules folder then it would be impossible for the gem to find script (not to mention that the #new and require are basically the only documented methods - only methods afaik - and #new is misdocumented :P)
Your options as far as I can tell:
system(node ...) - you can use Cocaine to escape some gotcha's (piping output, error handling, performance tweaks, ...) and run a cleaner syntax - this is not as bad as it looks - this is how paperclip does image postprocessing (imagemagick system package + cocaine) so I guess it's very stable and very doable
expose to web api and run a separate worker on a free heroku dyno for example to do this and similar stuff you want to do with node libs
use prawn :)
Get rid of ExecJS and anything that depends on ExecJS. I tried all the other suggestions, but this actually fixed it.
ES6 has been around since 2015. Any tool worth using supports it by now. MICROSOFT EDGE supports it by now. Seriously.

Categories