【问题标题】:Getall dependencies of an npm package with recursion Elixir使用递归 Elixir 获取 npm 包的所有依赖项
【发布时间】:2019-07-18 21:52:16
【问题描述】:

我有这个 url @registry "http://registry.npmjs.org/" 当你附加包名称和 /latest 时,它会返回一些关于包的详细信息,我需要获取我所做的所有依赖项并且它工作正常,但我需要更高级下来,有了它。比如。

如果您检查 http://registry.npmjs.org/handlebars/latest 并且它有 4 个依赖项,我想要这些 deps 以及进一步使用 neo-async 以及其他 depsdeps 这些 deps 得到什么是他们的依赖。这个我试过了。

defmodule Deep do
  @registry "http://registry.npmjs.org/"

  alias HTTPoison.Response, as: Resp

  def go(package, complete_deps \\ []) do
    HTTPoison.get(@registry <> package <> "/latest")
    |> handle_response()
    |> get_deps()
  end

  defp get_deps(nil),  do: []
  defp get_deps(deps),  do: Enum.map(deps, fn({k, _v}) -> k end)

  defp handle_response({:ok, %Resp{status_code: 200, body: body}}), do:
    Poison.decode!(body)["dependencies"]
  defp handle_response(_), do: nil
end

但我最终还是在第一级,我试过了

get_deps 结果做 head 和 tail,与 deps 一起走得更远,但我不知道在哪里可以保存 tail 或所有 deps。

基本上,我想使用递归在一个列表中获取车把、deps 及其所有 deps 的 deps,我可以看到 Enum.map 的解决方案,但它会有点难看。任何帮助将不胜感激

【问题讨论】:

    标签: elixir


    【解决方案1】:

    以下代码将构建依赖关系树。

    它依赖于jason Elixir 包并使用Erlang 标准库中提供的httpc HTTP 客户端。使用这些与使用poisonhttpoison 相比,优势在于将代码依赖的数量从8 降低到1

    defmodule Deep do
      @registry 'http://registry.npmjs.org/'
    
      def go([]), do: []
      def go([dep | other_deps]), do: [go(dep) | go(other_deps)]
      def go(package) do
        deps =
          [@registry, to_charlist(package), '/latest']
          |> :httpc.request()
          |> handle_response()
          |> get_deps()
    
        if Enum.empty?(deps), do: package, else: {package, go(deps)}
      end
    
      defp get_deps(nil), do: []
      defp get_deps(deps), do: Map.keys(deps)
    
      defp handle_response({:ok, {{_, 200, _}, _headers, body}}),
        do: Jason.decode!(body)["dependencies"]
    
      defp handle_response(_), do: nil
    end
    

    输出:

    iex(1)> Deep.go("handlebars")
    {"handlebars",
     [
       "neo-async",
       {"optimist", ["minimist", "wordwrap"]},
       "source-map",
       {"uglify-js", ["commander", "source-map"]}
     ]}
    iex(2)>
    

    【讨论】:

    • 你不觉得这太过分了吗?
    • @JunaidFarooq 你觉得这个解决方案有什么过分之处?
    • 那个干净和版本的部分。
    • @JunaidFarooq 你是否建议为每个依赖包获取latest 版本?
    • 是的,然后你也不需要把 latest 放在元组中
    【解决方案2】:

    在一个平面列表中获取所有唯一依赖项:

    defmodule Deep do
      @registry "http://registry.npmjs.org/"
    
      alias HTTPoison.Response, as: Resp
    
      def go(package) do
        HTTPoison.get(@registry <> package <> "/latest")
        |> handle_response()
        |> get_deps()
        |> List.flatten()
        |> Enum.uniq()
      end
    
      defp get_deps(nil),  do: []
      defp get_deps(deps),  do: Enum.map(deps, fn({k, _v}) -> [k | go(k)] end)
    
      defp handle_response({:ok, %Resp{status_code: 200, body: body}}), do:
        Poison.decode!(body)["dependencies"]
      defp handle_response(_), do: nil
    end
    

    用法:

    iex(11)> Deep.go("handlebars")             
    ["neo-async", "optimist", "minimist", "wordwrap", "source-map", "uglify-js",
     "commander"]
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-01-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-05-11
      • 2013-08-07
      • 2018-06-19
      相关资源
      最近更新 更多