#!/usr/bin/env ruby require 'fileutils' require 'methadone' require 'tomograph' require 'tomograph/version' include Methadone::Main include Methadone::CLILogging version Tomograph::VERSION description 'Converts API Blueprint to JSON Schema' on('-d DRAFTER_VERSION', '--drafter', 'Choose drafter version: crafter, 3 or 4. Default: use drafter v.3.') on('-f INPUT_FORMAT', '--format', 'Force input format: "apib" or "yaml". Default: detect by file extension.') on('--exclude-description', 'Exclude "description" keys.') on('--split', 'Split output into files by method.') arg :input, 'path/to/doc.apib (API Blueprint) or path/to/doc.yaml (API Elements)' arg :output, 'path/to/doc.json or path/to/dir if --split is used.' def prune!(obj, unwanted_key) if obj.is_a?(Hash) obj.delete(unwanted_key) obj.each_value { |value| prune!(value, unwanted_key) } elsif obj.is_a?(Array) obj.each { |value| prune!(value, unwanted_key) } end end def guess_format(opt_format, input) case opt_format && opt_format.downcase when 'apib' :apib when 'yaml' :yaml when nil case File.extname(input).downcase when '.apib' :apib when '.yaml', '.yml' :yaml else fail 'Unsupported input file extension!' end else fail 'Unsupported input format!' end end def choose_drafter(opt_parser) case opt_parser when 'crafter' :crafter when '3' :drafter_3 when '4' :drafter_4 when nil :drafter_3 else raise 'Unsupported drafter version!' end end def write_split_json(actions, output) FileUtils.mkdir_p(output) actions.clone.each do |action| json_name = "#{action.delete("path").to_s} #{action.delete("method")}.json" [['/', '#'], ['{', '('], ['}', ')']].each do |pattern, replacement| json_name.gsub!(pattern, replacement) end write_json(action, File.join(output, json_name)) end end def write_json(obj, path) json = MultiJson.dump(obj, pretty: true) File.open(path, 'w') do |file| file.write(json) end end main do |input, output| format = guess_format(options['format'], input) version = choose_drafter(options['drafter']) format_key = case format when :apib if version == :drafter_3 :apib_path elsif version == :crafter :crafter_apib_path else :drafter_4_apib_path end when :yaml if version == :drafter_3 :drafter_yaml_path elsif version == :crafter :crafter_yaml_path else :drafter_4_yaml_path end else fail NotImplementedError end tomogram = Tomograph::Tomogram.new(format_key => input) actions = tomogram.to_a.map(&:to_hash) prune!(actions, 'description') if options['exclude-description'] if options['split'] write_split_json(actions, output) else write_json(actions, output) end 0 end go!