diff --git a/.formatter.exs b/.formatter.exs index cdf16df..2ff9403 100644 --- a/.formatter.exs +++ b/.formatter.exs @@ -1,5 +1,25 @@ -# Used by "mix format" -[ - import_deps: [:absinthe, :ash], - inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"] +# THIS FILE IS AUTOGENERATED USING `mix ash.formatter` +# DONT MODIFY IT BY HAND +locals_without_parens = [ + authorize?: 1, + create: 2, + create: 3, + destroy: 2, + destroy: 3, + fields: 1, + get: 2, + get: 3, + list: 2, + list: 3, + type: 1, + update: 2, + update: 3 +] + +[ + inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"], + locals_without_parens: locals_without_parens, + export: [ + locals_without_parens: locals_without_parens + ] ] diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..4868af9 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,15 @@ +# Change Log + +All notable changes to this project will be documented in this file. +See [Conventional Commits](Https://conventionalcommits.org) for commit guidelines. + + + +## [v0.1.0](https://github.com/ash-project/ash_graphql/compare/v0.1.0...v0.1.0) (2020-08-13) + + + + +### Features: + +* initial POC release diff --git a/README.md b/README.md index 9035edd..7a26c50 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,12 @@ # AshGraphql +![Elixir CI](https://github.com/ash-project/ash_graphql/workflows/Elixir%20CI/badge.svg) +[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) +[![Coverage Status](https://coveralls.io/repos/github/ash-project/ash_graphql/badge.svg?branch=master)](https://coveralls.io/github/ash-project/ash_graphql?branch=master) +[![Hex version badge](https://img.shields.io/hexpm/v/ash_graphql.svg)](https://hex.pm/packages/ash_graphql) -**TODO: Add description** +AshGraphql is a graphql front extension for the Ash framework. V + +See the getting started guide for information on setting it up, and see the `AshGraphql.Resource` documentation for docs on its DSL. See the hexdocs for more information. ## Installation diff --git a/documentation/introduction/getting_started.md b/documentation/introduction/getting_started.md new file mode 100644 index 0000000..fd131e2 --- /dev/null +++ b/documentation/introduction/getting_started.md @@ -0,0 +1,71 @@ +# Getting Started + +## Get familiar with Ash resources + +If you haven't already, read the getting started guide for Ash. This assumes that you already have resources set up, and only gives you the steps to *add* AshGraphql to your resources/apis. + +## Add the API Extension + +```elixir +defmodule MyApi do + use Ash.Api, extensions: [ + AshGraphql.Api + ] + + graphql do + authorize? false # Defaults to `true`, use this to disable authorization for the entire API (you probably only want this while prototyping) + end +end +``` + +## Add graphql to your resources + +```elixir +defmodule Post do + use Ash.Resource, + extensions: [ + AshGraphql.Resource + ] + + graphql do + type :post + + fields [:name, :count_of_comments, :comments] # <- a list of all of the attributes/relationships/aggregates to include in the graphql API + + queries do + get :get_post, :default # <- create a field called `get_post` that uses the `default` read action to fetch a single post + list :list_posts, :default # <- create a field called `list_posts` that uses the `default` read action to fetch a list of posts + end + + mutations do + # And so on + create :create_post, :default + update :update_post, :default + destroy :destroy_post, :default + end + end +end +``` + +## Add AshGraphql to your schema + +If you don't have an absinthe schema, you can create one just for ash + +If you don't have any queries or mutations in your schema, you may +need to add empty query and mutation blocks. If you have no mutations, +don't add an empty mutations block, same for queries. + +```elixir +defmodule MyApp.Schema do + use Absinthe.Schema + + use AshGraphql, api: AshExample.Api + + query do + end + + mutation do + end +end + +``` diff --git a/lib/ash_graphql.ex b/lib/ash_graphql.ex index 629c579..e063138 100644 --- a/lib/ash_graphql.ex +++ b/lib/ash_graphql.ex @@ -1,6 +1,9 @@ defmodule AshGraphql do @moduledoc """ - Documentation for `AshGraphql`. + AshGraphql is a graphql front extension for the Ash framework. + + See the getting started guide for information on setting it up, and + see the `AshGraphql.Resource` documentation for docs on its DSL """ defmacro __using__(opts) do diff --git a/lib/graphql/resolver.ex b/lib/graphql/resolver.ex index 8fdb534..d152bf8 100644 --- a/lib/graphql/resolver.ex +++ b/lib/graphql/resolver.ex @@ -1,4 +1,5 @@ defmodule AshGraphql.Graphql.Resolver do + @moduledoc false def resolve( %{arguments: %{id: id}, context: context} = resolution, {api, resource, :get, action} @@ -63,7 +64,7 @@ defmodule AshGraphql.Graphql.Resolver do |> api.read(opts) |> case do {:ok, results} -> - {:ok, %AshGraphql.Paginator{results: results, count: Enum.count(results)}} + {:ok, %{results: results, count: Enum.count(results)}} error -> error @@ -229,7 +230,7 @@ defmodule AshGraphql.Graphql.Resolver do def resolve_assoc(%{source: parent} = resolution, {:many, name}) do values = Map.get(parent, name) - paginator = %AshGraphql.Paginator{results: values, count: Enum.count(values)} + paginator = %{results: values, count: Enum.count(values)} Absinthe.Resolution.put_result(resolution, {:ok, paginator}) end diff --git a/lib/paginator.ex b/lib/paginator.ex deleted file mode 100644 index 389579c..0000000 --- a/lib/paginator.ex +++ /dev/null @@ -1,3 +0,0 @@ -defmodule AshGraphql.Paginator do - defstruct [:results, :count] -end diff --git a/lib/test_schema.ex b/lib/test_schema.ex deleted file mode 100644 index 616d43f..0000000 --- a/lib/test_schema.ex +++ /dev/null @@ -1,37 +0,0 @@ -defmodule AshGraphql.TestSchema do - use Absinthe.Schema - # filename: myapp/schema.ex - @desc "An item" - object :item do - field :id, :id - field :name, :string - end - - # Example data - @items %{ - "foo" => %{id: "foo", name: "Foo"}, - "bar" => %{id: "bar", name: "Bar"} - } - - query do - field :item, :item do - arg :id, non_null(:id) - - resolve fn %{id: item_id}, _ -> - {:ok, @items[item_id]} - end - end - - field :items, non_null(list_of(non_null(:item))) do - resolve fn -> - {:ok, @items} - end - end - end - - mutation do - field :create_item, type: :item do - arg :id, non_null(:id) - end - end -end diff --git a/logos/.gitkeep b/logos/.gitkeep new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/logos/.gitkeep @@ -0,0 +1 @@ + diff --git a/logos/cropped-for-header.png b/logos/cropped-for-header.png new file mode 100644 index 0000000..118c318 Binary files /dev/null and b/logos/cropped-for-header.png differ diff --git a/logos/logo-black-text.png b/logos/logo-black-text.png new file mode 100644 index 0000000..536e3d4 Binary files /dev/null and b/logos/logo-black-text.png differ diff --git a/logos/logo-only.png b/logos/logo-only.png new file mode 100644 index 0000000..cf6366e Binary files /dev/null and b/logos/logo-only.png differ diff --git a/logos/logo-white-text.png b/logos/logo-white-text.png new file mode 100644 index 0000000..9180074 Binary files /dev/null and b/logos/logo-white-text.png differ diff --git a/logos/small-logo.png b/logos/small-logo.png new file mode 100644 index 0000000..9fc9aa1 Binary files /dev/null and b/logos/small-logo.png differ diff --git a/mix.exs b/mix.exs index 8043b82..c6f8236 100644 --- a/mix.exs +++ b/mix.exs @@ -1,13 +1,59 @@ defmodule AshGraphql.MixProject do use Mix.Project + @description """ + An absinthe-backed graphql extension for Ash + """ + + @version "0.1.0" + def project do [ app: :ash_graphql, - version: "0.1.0", + version: @version, elixir: "~> 1.10", start_permanent: Mix.env() == :prod, - deps: deps() + package: package(), + aliases: aliases(), + deps: deps(), + test_coverage: [tool: ExCoveralls], + preferred_cli_env: [ + coveralls: :test, + "coveralls.github": :test + ], + docs: docs(), + description: @description, + source_url: "https://github.com/ash-project/ash_graphql", + homepage_url: "https://github.com/ash-project/ash_graphql" + ] + end + + defp docs do + [ + main: "AshGraphql", + source_ref: "v#{@version}", + logo: "logos/small-logo.png", + extra_section: "GUIDES", + extras: [ + "documentation/introduction/getting_started.md" + ], + groups_for_extras: [ + Introduction: Path.wildcard("documentation/introduction/*.md") + ], + groups_for_modules: [ + "Resource DSL": ~r/AshGraphql.Resource/, + "Api DSL": ~r/AshGraphql.Api/ + ] + ] + end + + defp package do + [ + name: :ash_graphql, + licenses: ["MIT"], + links: %{ + GitHub: "https://github.com/ash-project/ash_graphql" + } ] end @@ -21,21 +67,24 @@ defmodule AshGraphql.MixProject do # Run "mix help deps" to learn about dependencies. defp deps do [ + {:ash, "~> 1.6.2"}, {:absinthe, "~> 1.5.2"}, {:jason, "~> 1.2"}, - {:ash, path: "../ash"} + {:ex_doc, "~> 0.22", only: :dev, runtime: false}, + {:ex_check, "~> 0.11.0", only: :dev}, + {:credo, ">= 0.0.0", only: :dev, runtime: false}, + {:dialyxir, ">= 0.0.0", only: :dev, runtime: false}, + {:sobelow, ">= 0.0.0", only: :dev, runtime: false}, + {:git_ops, "~> 2.0.1", only: :dev}, + {:excoveralls, "~> 0.13.0", only: [:dev, :test]} + ] + end + + defp aliases do + [ + sobelow: "sobelow --skip", + credo: "credo --strict", + "ash.formatter": "ash.formatter --extensions AshGraphql.Resource,AshGraphql.Api" ] end end - -# defmodule Foo do -# use Absinthe.Schema.Notation - -# object :foo do -# field :item, :string do -# resolve fn _, _, _ -> -# "hello" -# end -# end -# end -# end diff --git a/mix.lock b/mix.lock index 271f126..daaba03 100644 --- a/mix.lock +++ b/mix.lock @@ -1,14 +1,36 @@ %{ "absinthe": {:hex, :absinthe, "1.5.2", "2f9449b0c135ea61c09c11968d3d4fe6abd5bed38cf9be1c6d6b7c5ec858cfa0", [:mix], [{:dataloader, "~> 1.0.0", [hex: :dataloader, repo: "hexpm", optional: true]}, {:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: true]}, {:nimble_parsec, "~> 0.5", [hex: :nimble_parsec, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "669c84879629b7fffdc6cda9361ab9c81c9c7691e65418ba089b912a227963ac"}, + "ash": {:hex, :ash, "1.6.2", "9d99fbd9c541c993db711e15ebbe349d3700ac6ab5b50bb9aa832f8845a41186", [:mix], [{:ecto, "~> 3.4", [hex: :ecto, repo: "hexpm", optional: false]}, {:ets, "~> 0.8.0", [hex: :ets, repo: "hexpm", optional: false]}, {:nimble_options, "~> 0.3.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:picosat_elixir, "~> 0.1.4", [hex: :picosat_elixir, repo: "hexpm", optional: false]}], "hexpm", "b8c6436cbc476568fa1b8113635c23252454e6c85b22f2bb8b5f909c65aff72d"}, "ashton": {:hex, :ashton, "0.4.1", "d0f7782ac44fa22da7ce544028ee3d2078592a834d8adf3e5b4b6aeb94413a55", [:mix], [], "hexpm", "24db667932517fdbc3f2dae777f28b8d87629271387d4490bc4ae8d9c46ff3d3"}, + "bunt": {:hex, :bunt, "0.2.0", "951c6e801e8b1d2cbe58ebbd3e616a869061ddadcc4863d0a2182541acae9a38", [:mix], [], "hexpm", "7af5c7e09fe1d40f76c8e4f9dd2be7cebd83909f31fee7cd0e9eadc567da8353"}, + "certifi": {:hex, :certifi, "2.5.2", "b7cfeae9d2ed395695dd8201c57a2d019c0c43ecaf8b8bcb9320b40d6662f340", [:rebar3], [{:parse_trans, "~>3.3", [hex: :parse_trans, repo: "hexpm", optional: false]}], "hexpm", "3b3b5f36493004ac3455966991eaf6e768ce9884693d9968055aeeeb1e575040"}, + "credo": {:hex, :credo, "1.4.0", "92339d4cbadd1e88b5ee43d427b639b68a11071b6f73854e33638e30a0ea11f5", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "1fd3b70dce216574ce3c18bdf510b57e7c4c85c2ec9cad4bff854abaf7e58658"}, "decimal": {:hex, :decimal, "1.8.1", "a4ef3f5f3428bdbc0d35374029ffcf4ede8533536fa79896dd450168d9acdf3c", [:mix], [], "hexpm", "3cb154b00225ac687f6cbd4acc4b7960027c757a5152b369923ead9ddbca7aec"}, + "dialyxir": {:hex, :dialyxir, "1.0.0", "6a1fa629f7881a9f5aaf3a78f094b2a51a0357c843871b8bc98824e7342d00a5", [:mix], [{:erlex, ">= 0.2.6", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "aeb06588145fac14ca08d8061a142d52753dbc2cf7f0d00fc1013f53f8654654"}, + "earmark_parser": {:hex, :earmark_parser, "1.4.10", "6603d7a603b9c18d3d20db69921527f82ef09990885ed7525003c7fe7dc86c56", [:mix], [], "hexpm", "8e2d5370b732385db2c9b22215c3f59c84ac7dda7ed7e544d7c459496ae519c0"}, "ecto": {:hex, :ecto, "3.4.3", "3a14c2500c3964165245a4f24a463e080762f7ccd0c632c763ea589f75ca205f", [:mix], [{:decimal, "~> 1.6 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "9b6f18dea95f2004d0369f6a8346513ca3f706614f4ede219a5f3fe5db5dd962"}, "elixir_make": {:hex, :elixir_make, "0.6.0", "38349f3e29aff4864352084fc736fa7fa0f2995a819a737554f7ebd28b85aaab", [:mix], [], "hexpm", "d522695b93b7f0b4c0fcb2dfe73a6b905b1c301226a5a55cb42e5b14d509e050"}, + "erlex": {:hex, :erlex, "0.2.6", "c7987d15e899c7a2f34f5420d2a2ea0d659682c06ac607572df55a43753aa12e", [:mix], [], "hexpm", "2ed2e25711feb44d52b17d2780eabf998452f6efda104877a3881c2f8c0c0c75"}, "ets": {:hex, :ets, "0.8.0", "90153faafd289bb0801a537d5b05661f46d5e70b2bb55cccf5ab7f0d41d07832", [:mix], [], "hexpm", "bda4e05b16eada36798cfda16db551dc5243c0adc9a6dfe655b1bc1279b99cb8"}, + "ex_check": {:hex, :ex_check, "0.11.0", "6d878d9ae30d19168157bcbf346b527825284e14e77a07ec0492b19cf0036479", [:mix], [], "hexpm", "d41894aa6193f089a05e3abb43ca457e289619fcfbbdd7b60d070b7a62b26832"}, + "ex_doc": {:hex, :ex_doc, "0.22.2", "03a2a58bdd2ba0d83d004507c4ee113b9c521956938298eba16e55cc4aba4a6c", [:mix], [{:earmark_parser, "~> 1.4.0", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}], "hexpm", "cf60e1b3e2efe317095b6bb79651f83a2c1b3edcb4d319c421d7fcda8b3aff26"}, + "excoveralls": {:hex, :excoveralls, "0.13.1", "b9f1697f7c9e0cfe15d1a1d737fb169c398803ffcbc57e672aa007e9fd42864c", [:mix], [{:hackney, "~> 1.16", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "b4bb550e045def1b4d531a37fb766cbbe1307f7628bf8f0414168b3f52021cce"}, + "git_cli": {:hex, :git_cli, "0.3.0", "a5422f9b95c99483385b976f5d43f7e8233283a47cda13533d7c16131cb14df5", [:mix], [], "hexpm", "78cb952f4c86a41f4d3511f1d3ecb28edb268e3a7df278de2faa1bd4672eaf9b"}, + "git_ops": {:hex, :git_ops, "2.0.1", "9d3df6c710a80a8779dbb144c79fb24c777660ae862cc454ab3193afd0c02a37", [:mix], [{:git_cli, "~> 0.2", [hex: :git_cli, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 0.4", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "cd499a72523ba338c20973eadb707d25a42e4a77c46d2ff5c45e61e7adae6190"}, + "hackney": {:hex, :hackney, "1.16.0", "5096ac8e823e3a441477b2d187e30dd3fff1a82991a806b2003845ce72ce2d84", [:rebar3], [{:certifi, "2.5.2", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "6.0.1", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "1.0.1", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~>1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:parse_trans, "3.3.0", [hex: :parse_trans, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "1.1.6", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}], "hexpm", "3bf0bebbd5d3092a3543b783bf065165fa5d3ad4b899b836810e513064134e18"}, + "idna": {:hex, :idna, "6.0.1", "1d038fb2e7668ce41fbf681d2c45902e52b3cb9e9c77b55334353b222c2ee50c", [:rebar3], [{:unicode_util_compat, "0.5.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "a02c8a1c4fd601215bb0b0324c8a6986749f807ce35f25449ec9e69758708122"}, "jason": {:hex, :jason, "1.2.1", "12b22825e22f468c02eb3e4b9985f3d0cb8dc40b9bd704730efa11abd2708c44", [:mix], [{:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "b659b8571deedf60f79c5a608e15414085fa141344e2716fbd6988a084b5f993"}, "machinery": {:hex, :machinery, "1.0.0", "df6968d84c651b9971a33871c78c10157b6e13e4f3390b0bee5b0e8bdea8c781", [:mix], [{:ecto, "~> 3.0", [hex: :ecto, repo: "hexpm", optional: false]}], "hexpm", "4f6eb4185a48e7245360bedf653af4acc6fa6ae8ff4690619395543fa1a8395f"}, + "makeup": {:hex, :makeup, "1.0.3", "e339e2f766d12e7260e6672dd4047405963c5ec99661abdc432e6ec67d29ef95", [:mix], [{:nimble_parsec, "~> 0.5", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "2e9b4996d11832947731f7608fed7ad2f9443011b3b479ae288011265cdd3dad"}, + "makeup_elixir": {:hex, :makeup_elixir, "0.14.1", "4f0e96847c63c17841d42c08107405a005a2680eb9c7ccadfd757bd31dabccfb", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "f2438b1a80eaec9ede832b5c41cd4f373b38fd7aa33e3b22d9db79e640cbde11"}, + "metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm", "69b09adddc4f74a40716ae54d140f93beb0fb8978d8636eaded0c31b6f099f16"}, + "mimerl": {:hex, :mimerl, "1.2.0", "67e2d3f571088d5cfd3e550c383094b47159f3eee8ffa08e64106cdf5e981be3", [:rebar3], [], "hexpm", "f278585650aa581986264638ebf698f8bb19df297f66ad91b18910dfc6e19323"}, "nimble_options": {:hex, :nimble_options, "0.3.0", "1872911bf50a048f04da26e02704e6aeafc362c2daa7636b6dbfda9492ccfcfa", [:mix], [], "hexpm", "180790a8644fea402452bc15bb54b9bf2c8e5c1fdeb6b39d8072e59c324edf7f"}, "nimble_parsec": {:hex, :nimble_parsec, "0.6.0", "32111b3bf39137144abd7ba1cce0914533b2d16ef35e8abc5ec8be6122944263", [:mix], [], "hexpm", "27eac315a94909d4dc68bc07a4a83e06c8379237c5ea528a9acff4ca1c873c52"}, + "parse_trans": {:hex, :parse_trans, "3.3.0", "09765507a3c7590a784615cfd421d101aec25098d50b89d7aa1d66646bc571c1", [:rebar3], [], "hexpm", "17ef63abde837ad30680ea7f857dd9e7ced9476cdd7b0394432af4bfc241b960"}, "picosat_elixir": {:hex, :picosat_elixir, "0.1.4", "d259219ae27148c07c4aa3fdee61b1a14f4bc7f83b0ebdf2752558d06b302c62", [:make, :mix], [{:elixir_make, "~> 0.4", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "eb41cb16053a45c8556de32f065084af98ea0b13a523fb46dfb4f9cff4152474"}, + "sobelow": {:hex, :sobelow, "0.10.4", "44ba642da120d84fedb9e85473375084034330c8f15a992351dd164a82963103", [:mix], [], "hexpm", "fea62a94a4112de45ee9c9d076fd636fbbc10b7c7c2ea99a928e7c289b8498d1"}, + "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.6", "cf344f5692c82d2cd7554f5ec8fd961548d4fd09e7d22f5b62482e5aeaebd4b0", [:make, :mix, :rebar3], [], "hexpm", "bdb0d2471f453c88ff3908e7686f86f9be327d065cc1ec16fa4540197ea04680"}, "telemetry": {:hex, :telemetry, "0.4.2", "2808c992455e08d6177322f14d3bdb6b625fbcfd233a73505870d8738a2f4599", [:rebar3], [], "hexpm", "2d1419bd9dda6a206d7b5852179511722e2b18812310d304620c7bd92a13fcef"}, + "unicode_util_compat": {:hex, :unicode_util_compat, "0.5.0", "8516502659002cec19e244ebd90d312183064be95025a319a6c7e89f4bccd65b", [:rebar3], [], "hexpm", "d48d002e15f5cc105a696cf2f1bbb3fc72b4b770a184d8420c8db20da2674b38"}, }