json-schema-faker-cli icon indicating copy to clipboard operation
json-schema-faker-cli copied to clipboard

add usage(), user-friendly error messages, and support for the various options offered by the underling json-schema-faker library

Open liquidaty opened this issue 4 years ago • 10 comments

I did not see any way to pass command-line options corresponding to the various options offered by the underling json-schema-faker library, so I made some changes for it to do so.

In addition, the CLI does not provide any usage message or user-friendly error messages if, for example, it is run with an insufficient number of arguments.

Lastly, if no output file is specified, it should output to stdout.

Could you please incorporate these changes to address these issues? They are pretty simple, so I didn't bother with a PR. This will allow you to do the following:

generate-json # outputs error message and usage message
generate-json --alwaysFakeOptionals my.schema.json > my-fake.json # saves to my-fake.json
generate-json --notAValidOption my.schema.json # outputs error message and usage message

The changes were to two files, generate.js and generate-json:

// --- app/generate.js ---

const _ = require('lodash');
const jsonfile = require('jsonfile');

function generate(inputPath, outputPath, itemsLength, options) {
  var faker = require('json-schema-faker');
  const inputObject = jsonfile.readFileSync(inputPath);
  if(options)
    faker.option(options);

  const output = itemsLength === undefined
    ? faker(inputObject)
    : _.times(itemsLength, () => faker(inputObject));

  if(!outputPath)
    console.log(JSON.stringify(output));
  else
    jsonfile.writeFileSync(outputPath, output);
}

module.exports = generate;

// --- .bin/generate_json

#!/usr/bin/env node
const generate = require('./app/generate');
const supportedOptions = {
  failOnInvalidTypes: true,
  defaultInvalidTypeProduct: null,
  useDefaultValue: false,
  requiredOnly: false,
  maxItems: null,
  maxLength: null,
  defaultMinItems: 0,
  defaultRandExpMax: 10,
  alwaysFakeOptionals: false
};

const optionUsage = Object.keys(supportedOptions).map(function(optName) {
  return '  --' + optName + '=' + JSON.stringify(supportedOptions[optName]);
});

const usage = [
  'Example:', '  ' + process.argv[1] + ' --alwaysFakeOptionals[=true] schema.json [output.json]',
  'Options and default values:'
].concat(optionUsage).join('\n') + '\n';

var options = {};
var files = [];
for(var i = 2; i < process.argv.length; i++) {
  var arg = process.argv[i];
  if(!arg.startsWith('--'))
    files.push(arg);
  else {
    var parts = arg.slice(2).split('=');
    var optName = parts[0];
    var optValue = parts[1];
    var showUsage = false;
    if(optName == 'help')
      showUsage = true;
    else if(!(optName in supportedOptions)) {
      console.error('Option ' + optName + ' not recognized');
      showUsage = true;
    }

    if(showUsage) {
      console.log(usage);
      return;
    }

    if(!optValue)
      options[optName] = true;
    else {
      try {
        options[optName] = JSON.parse(optValue);
      } catch(e) {
        options[optName] = optValue;
      }
    }
  }
}

if(!files[0])
  console.error('Input schema file not provided\n' + usage);
else
  generate(files[0], files[1], files[2], options);

liquidaty avatar Jan 04 '21 21:01 liquidaty

Thanks for these suggestions but I'm not sure whether I'll have time to implement that.

oprogramador avatar Jan 09 '21 22:01 oprogramador

OK thanks for the response. We will fork it ourselves and start a separate repo.

Before doing so, just wanted to confirm: you did see that all the code needed for the requested change is already there, and all that is needed to make these changes is to copy/paste those two snippets, and entirely replace the target files (probably all of 3 minutes)? Just don't want to duplicate a repo if not needed to do so

liquidaty avatar Jan 09 '21 23:01 liquidaty

@liquidaty

Maybe it's easy to integrate this code but it's needed to check whether it works.

Generally, it's simpler if you open a PR. I don't promise to merge it as I'll need to check it but it'll be simpler for me than to copy-paste your code.

oprogramador avatar May 02 '21 14:05 oprogramador

@liquidaty

I see that nobody has voted for resolving this issue with :+1: or :heart:, and there are no comments from people other than you and me.

Neither I need these updates.

Your code contains no tests and no descriptive README update.

Your updates seem to contain much more code than my current business logic (when we count only JS files, excluding tests).

Therefore, I decided to close this issue, without implementing it.

Anyway, thanks for this proposal and your code.

oprogramador avatar Oct 03 '21 16:10 oprogramador

Regarding the output, maybe it would be better if this library supported only stdout so we could write to a file with the > bash operator.

However, currently, it doesn't seem to be a major problem as you can use cat e.g. generate-json schema.json output.json && cat output.json or possibly if you don't want any file created at the end: generate-json schema.json output.json && cat output.json && rm output.json

oprogramador avatar Oct 03 '21 17:10 oprogramador

Btw. If I decided to use your code, I would change some parts like:

  • const or let instead of var
  • array spread operator (...) instead of .concat(
  • curlies after each if and else

oprogramador avatar Oct 03 '21 17:10 oprogramador

I agree. CLI usage and a way to provide options would be very useful.

reubano avatar Jan 19 '22 03:01 reubano

This would be of great interest to my org as well.

sectoreleven avatar Feb 16 '22 22:02 sectoreleven

@liquidaty @reubano @sectoreleven

Could you check [email protected]?

oprogramador avatar Jul 07 '22 00:07 oprogramador

@liquidaty @reubano @sectoreleven

Could you check [email protected]?

We've been using the @liquidaty fork successfully, so changing that will be a bit low on our list currently.

sectoreleven avatar Jul 07 '22 00:07 sectoreleven