Packages
ash_graphql
1.4.7
1.10.0
1.9.4
1.9.3
1.9.2
1.9.1
1.9.0
1.8.5
1.8.4
1.8.3
1.8.2
1.8.1
1.8.0
1.7.17
1.7.16
1.7.15
1.7.14
1.7.13
1.7.12
1.7.11
1.7.10
1.7.9
1.7.8
1.7.7
1.7.6
1.7.5
1.7.4
1.7.3
1.7.2
1.7.1
1.7.0
1.6.0
1.5.1
1.5.0
1.4.7
1.4.6
1.4.5
1.4.4
1.4.3
1.4.2
1.4.1
1.4.0
1.3.4
1.3.3
1.3.2
1.3.1
1.3.0
1.2.1
1.2.0
1.1.1
1.1.0
1.0.1
1.0.0
1.0.0-rc.5
1.0.0-rc.4
retired
1.0.0-rc.3
1.0.0-rc.2
1.0.0-rc.1
1.0.0-rc.0
0.28.1
0.28.0
0.27.1
0.27.0
0.26.9
0.26.8
0.26.7
0.26.6
0.26.5
0.26.4
0.26.3
0.26.2
0.26.0
0.25.13
0.25.12
0.25.10
0.25.9
0.25.8
0.25.7
0.25.6
0.25.5
0.25.4
0.25.3
0.25.2
0.25.1
0.25.0
0.24.1
0.24.0
0.23.3
0.23.2
0.23.1
0.23.0
0.22.13
0.22.12
0.22.11
0.22.10
0.22.9
0.22.8
0.22.7
0.22.6
0.22.4
0.22.3
0.22.2
0.22.1
0.22.0
0.21.0
retired
0.20.5
0.20.4
0.20.3
0.20.2
0.20.1
0.20.0-rc.3
0.20.0-rc.2
0.20.0-rc.1
0.20.0-rc.0
0.19.0
0.18.0-rc0
0.17.5
0.17.5-rc0
0.17.4
0.17.2
0.17.1
0.17.0
0.16.28
0.16.27
0.16.26
0.16.25
0.16.24
0.16.23
0.16.22
0.16.21
0.16.20
0.16.18-rc5
0.16.18-rc4
0.16.18-rc3
0.16.18-rc2
0.16.18-rc1
0.16.18-rc0
0.16.17
0.16.16
0.16.15
0.16.14
0.16.13
0.16.12
0.16.11
0.16.10
0.16.9
0.16.8
0.16.7
0.16.6
0.16.5
0.16.4
0.16.3
0.16.2
0.16.1
0.16.0
0.15.10
0.15.9
0.15.8
0.15.7
0.15.6
0.15.5
0.15.4
0.15.3
0.15.2
0.15.1
0.15.0
0.14.1
0.14.0
0.13.1
0.13.0
0.12.5
0.12.4
0.12.3
0.12.1
0.12.0
0.10.0
0.9.5
0.9.4
0.9.3
0.9.2
0.9.1
0.9.0
0.8.0
0.7.5
0.7.4
0.7.3
0.7.2
0.7.1
0.7.0
0.6.3
0.6.2
0.6.1
0.6.0
0.5.0
0.4.0
0.3.2
0.3.1
0.3.0
0.2.1
0.2.0
0.1.3
0.1.2
The extension for building GraphQL APIs with Ash
Current section
Files
Jump to
Current section
Files
lib/codegen.ex
defmodule AshGraphql.Codegen do
@moduledoc false
# sobelow_skip ["Traversal.FileModule"]
def generate_sdl_file(schema, opts) do
target = schema.generate_sdl_file()
case Mix.Tasks.Absinthe.Schema.Sdl.generate_schema(%Mix.Tasks.Absinthe.Schema.Sdl.Options{
schema: schema,
filename: target
}) do
{:ok, contents} ->
if opts[:check?] do
target_contents = File.read!(target)
if String.trim(target_contents) != String.trim(contents) do
raise "Generated SDL file for #{} does not match existing file. Please run `mix ash.codegen` to generate the new file."
end
else
File.write!(target, contents)
end
end
end
def schemas do
apps =
if Code.ensure_loaded?(Mix.Project) do
if apps_paths = Mix.Project.apps_paths() do
apps_paths |> Map.keys() |> Enum.sort()
else
[Mix.Project.config()[:app]]
end
else
[]
end
apps()
|> Stream.concat(apps)
|> Stream.uniq()
|> Task.async_stream(
fn app ->
app
|> :application.get_key(:modules)
|> case do
:undefined ->
[]
{_, mods} ->
mods
|> List.wrap()
|> Enum.filter(&ash_graphql_schema?/1)
end
end,
timeout: :infinity
)
|> Stream.map(&elem(&1, 1))
|> Stream.flat_map(& &1)
|> Stream.uniq()
|> Enum.to_list()
end
defp ash_graphql_schema?(module) do
Code.ensure_compiled!(module)
function_exported?(module, :ash_graphql_schema?, 0) && module.ash_graphql_schema?()
end
Code.ensure_loaded!(Mix.Project)
if function_exported?(Mix.Project, :deps_tree, 0) do
# for our app, and all dependency apps, we want to find extensions
# the benefit of not just getting all loaded applications is that this
# is actually a surprisingly expensive thing to do for every single built
# in application for elixir/erlang. Instead we get anything w/ a dependency on ash or spark
# this could miss things, but its unlikely. And if it misses things, it actually should be
# fixed in the dependency that is relying on a transitive dependency :)
defp apps do
Mix.Project.deps_tree()
|> Stream.filter(fn {_, nested_deps} ->
Enum.any?(nested_deps, &(&1 == :spark || &1 == :ash))
end)
|> Stream.map(&elem(&1, 0))
end
else
defp apps do
Logger.warning(
"Mix.Project.deps_tree/0 not available, falling back to loaded_applications/0. Upgrade to Elixir 1.15+ to make this *much* faster."
)
:application.loaded_applications()
|> Stream.map(&elem(&1, 0))
end
end
end