|
1 | 1 | defmodule JS2E do
|
2 | 2 | @moduledoc ~S"""
|
3 |
| - Parses JSON schemas and prints Elm types and decoders. |
| 3 | + Transforms one or more JSON schema files into their corresponding |
| 4 | + Elm types and JSON decoders. |
| 5 | +
|
| 6 | + Expects a PATH to one or more JSON schema files from which to generate |
| 7 | + Elm code. |
| 8 | +
|
| 9 | + js2e PATH [--module-name NAME] |
| 10 | +
|
| 11 | + The JSON schema(s) at the given PATH will be converted to Elm types |
| 12 | + and JSON decoders. |
| 13 | +
|
| 14 | + ## Options |
| 15 | +
|
| 16 | + * `--module-name` - the module name prefix for the printed Elm modules \ |
| 17 | + default value is 'Domain'. |
4 | 18 | """
|
5 | 19 |
|
6 | 20 | require Logger
|
7 | 21 | alias JS2E.{Parser, Printer}
|
8 | 22 |
|
| 23 | + @spec main([String.t]) :: :ok |
| 24 | + def main(args) do |
| 25 | + Logger.debug "Arguments: #{inspect args}" |
| 26 | + |
| 27 | + {options, paths, errors} = |
| 28 | + OptionParser.parse(args, switches: [module_name: :string]) |
| 29 | + |
| 30 | + if length(paths) == 0 do |
| 31 | + IO.puts @moduledoc |
| 32 | + exit(:normal) |
| 33 | + end |
| 34 | + |
| 35 | + if length(errors) > 0 do |
| 36 | + IO.puts "Error: Found one or more errors in the supplied options" |
| 37 | + exit({:unknown_arguments, errors}) |
| 38 | + end |
| 39 | + |
| 40 | + files = resolve_all_paths(paths) |
| 41 | + Logger.debug "Files: #{inspect files}" |
| 42 | + |
| 43 | + if length(files) == 0 do |
| 44 | + IO.puts "Error: Could not find any JSON files in path: #{inspect paths}" |
| 45 | + exit(:no_files) |
| 46 | + end |
| 47 | + |
| 48 | + output_path = create_output_dir(options) |
| 49 | + JS2E.generate(files, output_path) |
| 50 | + end |
| 51 | + |
| 52 | + @spec resolve_all_paths([String.t]) :: [String.t] |
| 53 | + defp resolve_all_paths(paths) do |
| 54 | + paths |
| 55 | + |> Enum.filter(&File.exists?/1) |
| 56 | + |> Enum.reduce([], fn (filename, files) -> |
| 57 | + cond do |
| 58 | + File.dir? filename -> |
| 59 | + walk_directory(filename) ++ files |
| 60 | + |
| 61 | + String.ends_with?(filename, ".json") -> |
| 62 | + [filename | files] |
| 63 | + |
| 64 | + true -> |
| 65 | + files |
| 66 | + end |
| 67 | + end) |
| 68 | + end |
| 69 | + |
| 70 | + @spec walk_directory(String.t) :: [String.t] |
| 71 | + defp walk_directory(dir) do |
| 72 | + dir |
| 73 | + |> File.ls! |
| 74 | + |> Enum.reduce([], fn file, files -> |
| 75 | + filename = "#{dir}/#{file}" |
| 76 | + |
| 77 | + cond do |
| 78 | + File.dir? filename -> |
| 79 | + walk_directory(filename) ++ files |
| 80 | + |
| 81 | + String.ends_with?(file, ".json") -> |
| 82 | + [filename | files] |
| 83 | + |
| 84 | + true -> |
| 85 | + files |
| 86 | + end |
| 87 | + end) |
| 88 | + end |
| 89 | + |
| 90 | + @spec create_output_dir(list) :: String.t |
| 91 | + defp create_output_dir(options) do |
| 92 | + |
| 93 | + output_path = if Keyword.has_key?(options, :module_name) do |
| 94 | + Keyword.get(options, :module_name) |
| 95 | + else |
| 96 | + "Domain" |
| 97 | + end |
| 98 | + |
| 99 | + output_path |
| 100 | + |> Path.join("Decoders") |
| 101 | + |> File.mkdir_p!() |
| 102 | + |
| 103 | + output_path |
| 104 | + end |
| 105 | + |
9 | 106 | @spec generate([String.t], String.t) :: :ok
|
10 | 107 | def generate(json_schema_paths, module_name) do
|
11 | 108 |
|
|
0 commit comments