zf

zenflows testing
git clone https://s.sonu.ch/~srfsh/zf.git
Log | Files | Refs | Submodules | README | LICENSE

compiled.ex (6176B)


      1 defmodule Absinthe.Plug.DocumentProvider.Compiled do
      2   @moduledoc """
      3 
      4   Provide pre-compiled documents for retrieval by request parameter key.
      5 
      6   Important: This module shouldn't be used as a document provider itself, but
      7   as a toolkit to build one. See the examples below.
      8 
      9   ### Examples
     10 
     11   Define a new module and `use Absinthe.Plug.DocumentProvider.Compiled`:
     12 
     13       defmodule MyAppWeb.Schema.Documents do
     14         use Absinthe.Plug.DocumentProvider.Compiled
     15 
     16         # ... Configure here
     17 
     18       end
     19 
     20   You can provide documents as literals within the module, by key, using the
     21   `provide/2` macro:
     22 
     23       provide "item", "query Item($id: ID!) { item(id: $id) { name } }"
     24 
     25   You can also load a map of key value pairs using `provide/1`.
     26 
     27       provide %{
     28         "item" => "query Item($id: ID!) { item(id: $id) { name } }",
     29         "time" => "{ currentTime }"
     30       }
     31 
     32   This can be used to support loading documents extracted using Apollo's
     33   [persistgraphql](https://github.com/apollographql/persistgraphql) tool by
     34   parsing the file and inverting the key/value pairs.
     35 
     36       provide File.read!("/path/to/extracted_queries.json")
     37       |> Jason.decode!
     38       |> Map.new(fn {k, v} -> {v, k} end)
     39 
     40   By default, the request parameter that will be used to lookup documents is
     41   `"id"`. You can change this by passing a `:key_param` option to `use`, e.g.:
     42 
     43       use Absinthe.Plug.DocumentProvider.Compiled, key_param: "lookup_key"
     44 
     45   ## Configuring
     46 
     47   You need to configure `Absinthe.Plug` to use any document providers that you create.
     48   (Only `Absinthe.Plug.DocumentProviders.Default` is configured by default.)
     49 
     50   Make sure that a `Compiled` document provider is placed before the `Default` provider.
     51 
     52   See the documentation on `Absinthe.Plug.init/1` for more details. Look for the
     53   `:document_providers` option.
     54   """
     55 
     56   defmacro __using__(opts) do
     57     key_param = Keyword.get(opts, :key_param, "id") |> to_string
     58 
     59     quote do
     60       @behaviour Absinthe.Plug.DocumentProvider
     61 
     62       @before_compile {unquote(__MODULE__.Writer), :write}
     63       @absinthe_documents_to_compile %{}
     64 
     65       # Can be overridden in the document provider module
     66       @compilation_pipeline Absinthe.Pipeline.for_document(nil, jump_phases: false)
     67                             |> Absinthe.Pipeline.before(Absinthe.Phase.Document.Variables)
     68                             |> Absinthe.Pipeline.without(Absinthe.Phase.Telemetry)
     69 
     70       import unquote(__MODULE__), only: [provide: 2, provide: 1]
     71 
     72       def process(request, _) do
     73         do_process(request)
     74       end
     75 
     76       defp do_process(%{params: %{unquote(key_param) => document_key}} = request) do
     77         case __absinthe_plug_doc__(:compiled, document_key) do
     78           nil ->
     79             {:cont, request}
     80 
     81           document ->
     82             {:halt, %{request | document: document, document_provider_key: document_key}}
     83         end
     84       end
     85 
     86       defp do_process(request) do
     87         {:cont, request}
     88       end
     89 
     90       @doc """
     91       Determine the remaining pipeline for an request with a pre-compiled
     92       document.
     93 
     94       Usually this can be changed simply by setting `@compilation_pipeline` in
     95       your document provider. This may need to be overridden if your compilation
     96       phase is not a subset of the full pipeline.
     97       """
     98       def pipeline(%{pipeline: as_configured}) do
     99         remaining_pipeline_marker = __absinthe_plug_doc__(:remaining_pipeline)
    100         telemetry_phase = {Absinthe.Phase.Telemetry, event: [:execute, :operation, :start]}
    101 
    102         as_configured
    103         |> Absinthe.Pipeline.from(remaining_pipeline_marker)
    104         |> Absinthe.Pipeline.insert_before(remaining_pipeline_marker, telemetry_phase)
    105       end
    106 
    107       defoverridable pipeline: 1, process: 2
    108     end
    109   end
    110 
    111   @doc ~s"""
    112   Provide a GraphQL document for a given key.
    113 
    114   Note that the key will be coerced to a string to ensure compatibility with the expected request parameter.
    115 
    116   For more information, see the module-level documentation.
    117 
    118   ## Examples
    119 
    120       provide "foo", \"""
    121         query ShowItem($id: ID!) {
    122           item(id: $id) { name }
    123         }
    124       \"""
    125 
    126   """
    127   @spec provide(any, String.t()) :: Macro.t()
    128   defmacro provide(document_key, document_source) do
    129     quote do
    130       @absinthe_documents_to_compile Map.put(
    131                                        @absinthe_documents_to_compile,
    132                                        to_string(unquote(document_key)),
    133                                        unquote(document_source)
    134                                      )
    135     end
    136   end
    137 
    138   @doc ~s"""
    139   Provide multiple GraphQL documents by key.
    140 
    141   Note that keys will be coerced to strings to ensure compatibility with the expected request parameter.
    142 
    143   For more information, see the module-level documentation.
    144 
    145   ## Examples
    146 
    147       provide %{
    148         "item" => "query Item($id: ID!) { item(id: $id) { name } }",
    149         "time" => "{ currentTime }"
    150       }
    151 
    152   """
    153   @spec provide(%{any => String.t()}) :: Macro.t()
    154   defmacro provide(documents) do
    155     quote do
    156       @absinthe_documents_to_compile Map.merge(
    157                                        @absinthe_documents_to_compile,
    158                                        Map.new(
    159                                          unquote(documents),
    160                                          &{to_string(elem(&1, 0)), elem(&1, 1)}
    161                                        )
    162                                      )
    163     end
    164   end
    165 
    166   @doc """
    167   Lookup a document by id.
    168 
    169   ## Examples
    170 
    171   Get a compiled document:
    172 
    173       iex> get(CompiledProvider, "provided")
    174       #Absinthe.Blueprint<>
    175 
    176   With an explicit `:compiled` flag:
    177 
    178       iex> get(CompiledProvider, "provided", :compiled)
    179       #Absinthe.Blueprint<>
    180 
    181   Get the source:
    182 
    183       iex> get(CompiledProvider, "provided", :source)
    184       "query Item { item { name } }"
    185 
    186   When a value isn't present:
    187 
    188       iex> get(CompiledProvider, "not-provided")
    189       nil
    190 
    191   """
    192   @spec get(module, String.t(), :compiled | :source) :: nil | Absinthe.Blueprint.t()
    193   def get(dp, id, format \\ :compiled)
    194 
    195   def get(dp, id, :compiled) do
    196     dp.__absinthe_plug_doc__(:compiled, id)
    197   end
    198 
    199   def get(dp, id, :source) do
    200     dp.__absinthe_plug_doc__(:source, id)
    201   end
    202 end