improvement: update CI to staple-actions and get (most) checks passing.

This commit is contained in:
James Harton 2022-10-26 10:43:45 +13:00
parent 20290e061e
commit a3d3593028
23 changed files with 309 additions and 348 deletions

View file

@ -5,7 +5,7 @@
min_module_spec_coverage: 0,
min_overall_doc_coverage: 50,
min_overall_spec_coverage: 0,
moduledoc_required: true,
min_overall_moduledoc_coverage: 100,
exception_moduledoc_required: true,
raise: false,
reporter: Doctor.Reporters.Full,

View file

@ -1,8 +1,8 @@
[
import_deps: [:ash],
import_deps: [:spark],
inputs: [
"*.{ex,exs}",
"{config,lib,test}/**/*.{ex,exs}"
],
plugins: [Ash.ResourceFormatter]
plugins: [Spark.Formatter]
]

154
.github/workflows/elixir_lib.yml vendored Normal file
View file

@ -0,0 +1,154 @@
name: Elixir Library
on:
push:
jobs:
deps:
name: mix deps.get
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: team-alembic/staple-actions/actions/mix-deps-get@main
auditor:
name: mix hex.audit
runs-on: ubuntu-latest
needs: deps
steps:
- uses: actions/checkout@v3
- uses: team-alembic/staple-actions/actions/mix-hex-audit@main
build-test:
name: MIX_ENV=test mix.compile
runs-on: ubuntu-latest
needs: deps
steps:
- uses: actions/checkout@v3
- uses: team-alembic/staple-actions/actions/install-elixir@main
- uses: team-alembic/staple-actions/actions/mix-compile@main
with:
mix-env: test
formatter:
name: mix format --check-formatted
runs-on: ubuntu-latest
needs: build-test
steps:
- uses: actions/checkout@v3
- uses: team-alembic/staple-actions/actions/mix-format@main
with:
mix-env: test
credo:
name: mix credo --strict
runs-on: ubuntu-latest
needs: build-test
steps:
- uses: actions/checkout@v3
- uses: team-alembic/staple-actions/actions/mix-credo@main
with:
mix-env: test
doctor:
name: mix doctor --full --raise
runs-on: ubuntu-latest
needs: build-test
steps:
- uses: actions/checkout@v3
- uses: team-alembic/staple-actions/actions/mix-doctor@main
with:
mix-env: test
test:
name: mix test
runs-on: ubuntu-latest
needs: build-test
services:
postgres:
image: postgres
env:
POSTGRES_HOST_AUTH_METHOD: trust
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 5432:5432
steps:
- uses: actions/checkout@v3
- uses: team-alembic/staple-actions/actions/mix-test@main
with:
mix-env: test
env:
PGUSER: postgres
PGPASS: postgres
PGHOST: postgres
dialyzer:
name: mix dialyzer
runs-on: ubuntu-latest
needs: build-test
steps:
- uses: actions/checkout@v3
- uses: team-alembic/staple-actions/actions/mix-dialyzer@main
with:
mix-env: test
build-dev:
name: MIX_ENV=dev mix.compile
runs-on: ubuntu-latest
needs:
- credo
- doctor
- formatter
- auditor
- test
- dialyzer
if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }}
steps:
- uses: actions/checkout@v3
- uses: team-alembic/staple-actions/actions/mix-compile@main
with:
mix-env: dev
build-docs:
name: mix docs
runs-on: ubuntu-latest
needs: build-dev
steps:
- uses: actions/checkout@v3
- uses: team-alembic/staple-actions/actions/mix-docs@main
with:
mix-env: dev
- uses: actions/upload-pages-artifact@v1
with:
path: doc/
deploy-docs:
name: Deploy docs to GitHub pages.
runs-on: ubuntu-latest
needs: build-docs
permissions:
pages: write
id-token: write
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- name: Deploy to GitHub pages
id: deployment
uses: actions/deploy-pages@v1
git-ops:
name: mix git-ops.release
runs-on: ubuntu-latest
needs: build-dev
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- uses: team-alembic/staple-actions/actions/git-ops@main
with:
mix-env: dev

View file

@ -1,36 +0,0 @@
name: mix credo --strict
on:
pull_request:
branches:
- main
jobs:
test:
runs-on: ubuntu-latest
env:
MIX_ENV: test
strategy:
matrix:
elixir: [1.13.4]
otp: [25.0.3]
steps:
- uses: actions/checkout@v2
- uses: erlef/setup-beam@v1
with:
elixir-version: ${{ matrix.elixir }}
otp-version: ${{ matrix.otp }}
- name: Retrieve Mix Dependencies Cache
uses: actions/cache@v1
id: mix-cache
with:
path: deps
key: ${{ runner.os }}-${{ matrix.otp }}-${{ matrix.elixir }}-mix-${{ hashFiles(format('{0}{1}', github.workspace, '/mix.lock')) }}
- name: Install Mix Dependencies
if: steps.mix-cache.outputs.cache-hit != 'true'
run: |
mix local.rebar --force
mix local.hex --force
mix deps.get
- run: mix credo --strict

View file

@ -1,36 +0,0 @@
name: mix doctor
on:
pull_request:
branches:
- main
jobs:
test:
runs-on: ubuntu-latest
env:
MIX_ENV: test
strategy:
matrix:
elixir: [1.13.4]
otp: [25.0.3]
steps:
- uses: actions/checkout@v2
- uses: erlef/setup-beam@v1
with:
elixir-version: ${{ matrix.elixir }}
otp-version: ${{ matrix.otp }}
- name: Retrieve Mix Dependencies Cache
uses: actions/cache@v1
id: mix-cache
with:
path: deps
key: ${{ runner.os }}-${{ matrix.otp }}-${{ matrix.elixir }}-mix-${{ hashFiles(format('{0}{1}', github.workspace, '/mix.lock')) }}
- name: Install Mix Dependencies
if: steps.mix-cache.outputs.cache-hit != 'true'
run: |
mix local.rebar --force
mix local.hex --force
mix deps.get
- run: mix doctor --full --raise

View file

@ -1,37 +0,0 @@
name: mix format --check-formatted
on:
pull_request:
branches:
- main
jobs:
test:
runs-on: ubuntu-latest
env:
MIX_ENV: test
strategy:
matrix:
elixir: [1.13.4]
otp: [25.0.3]
steps:
- uses: actions/checkout@v2
- uses: erlef/setup-beam@v1
with:
elixir-version: ${{ matrix.elixir }}
otp-version: ${{ matrix.otp }}
- name: Retrieve Mix Dependencies Cache
uses: actions/cache@v1
id: mix-cache
with:
path: deps
key: ${{ runner.os }}-${{ matrix.otp }}-${{ matrix.elixir }}-mix-${{ hashFiles(format('{0}{1}', github.workspace, '/mix.lock')) }}
- name: Install Mix Dependencies
if: steps.mix-cache.outputs.cache-hit != 'true'
run: |
mix local.rebar --force
mix local.hex --force
mix deps.get
- name: Check Formatting
run: mix format --check-formatted

View file

@ -1,82 +0,0 @@
name: mix git_ops.release
on:
push:
branches:
- main
jobs:
maybe_release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: erlef/setup-beam@v1
with:
elixir-version: "1.13.4"
otp-version: "25.0.3"
- name: Retrieve Mix Dependencies Cache
uses: actions/cache@v1
id: mix-cache
with:
path: deps
key: ${{ runner.os }}-${{ matrix.otp }}-${{ matrix.elixir }}-mix-${{ hashFiles(format('{0}{1}', github.workspace, '/mix.lock')) }}
- name: Install Mix Dependencies
if: steps.mix-cache.outputs.cache-hit != 'true'
run: |
mix local.rebar --force
mix local.hex --force
mix deps.get
- name: Configure git author
run: git config user.email '25500012+github-actions[bot]@users.noreply.github.com' ; git config user.name 'github-actions'
- name: Retrieving the current app version
id: original-app-info
run: MIX_ENV=test mix git_ops.project_info --format github-actions
- name: Run mix git_ops.release
run: MIX_ENV=test mix git_ops.release --yes || true
- name: Checking for new app version
id: app-info
run: MIX_ENV=test mix git_ops.project_info --format github-actions
- name: Building hex package
if: ${{ steps.original-app-info.outputs.app_version != steps.app-info.outputs.app_version }}
run: mix hex.build -o ${{ steps.app-info.outputs.app_name }}-${{ steps.app-info.outputs.app_version }}.tar
- name: Building hex docs
if: ${{ steps.original-app-info.outputs.app_version != steps.app-info.outputs.app_version }}
run: MIX_ENV=test mix docs && tar zcvf ${{ steps.app-info.outputs.app_name }}-${{ steps.app-info.outputs.app_version }}-docs.tar.gz doc/
- name: Pushing new tag
if: ${{ steps.original-app-info.outputs.app_version != steps.app-info.outputs.app_version }}
run: git push "https://${{ github.actor }}:${{ github.token }}@github.com/${{ github.repository }}" HEAD:${{ github.ref }} refs/tags/v${{ steps.app-info.outputs.app_version }}
- name: Creating new Github release
if: ${{ steps.original-app-info.outputs.app_version != steps.app-info.outputs.app_version }}
id: create-release
uses: actions/create-release@v1
env:
GITHUB_TOKEN: ${{ github.token }}
with:
tag_name: v${{ steps.app-info.outputs.app_version }}
release_name: Release ${{ steps.app-info.outputs.app_name }} ${{ steps.app-info.outputs.app_version }}
body: Autogenerated by git_ops release.
- name: Uploading hex package as release artifact
if: ${{ steps.original-app-info.outputs.app_version != steps.app-info.outputs.app_version }}
id: upload-package
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ github.token }}
with:
upload_url: ${{ steps.create-release.outputs.upload_url }}
asset_path: ${{ steps.app-info.outputs.app_name }}-${{ steps.app-info.outputs.app_version }}.tar
asset_name: ${{ steps.app-info.outputs.app_name }}-${{ steps.app-info.outputs.app_version }}.tar
asset_content_type: application/x-tar
- name: Uploading documentation as release artifact
if: ${{ steps.original-app-info.outputs.app_version != steps.app-info.outputs.app_version }}
id: upload-docs
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ github.token }}
with:
upload_url: ${{ steps.create-release.outputs.upload_url }}
asset_path: ${{ steps.app-info.outputs.app_name }}-${{ steps.app-info.outputs.app_version }}-docs.tar.gz
asset_name: ${{ steps.app-info.outputs.app_name }}-${{ steps.app-info.outputs.app_version }}-docs.tar.gz
asset_content_type: application/gzip
# - name: Publishing hex package
# if: ${{ steps.original-app-info.outputs.app_version != steps.app-info.outputs.app_version }}
# run: mix hex.publish --yes

View file

@ -1,35 +0,0 @@
name: mix hex.audit
on:
pull_request:
branches:
- main
jobs:
test:
runs-on: ubuntu-latest
env:
MIX_ENV: test
strategy:
matrix:
elixir: [1.13.4]
otp: [25.0.3]
steps:
- uses: actions/checkout@v2
- uses: erlef/setup-beam@v1
with:
elixir-version: ${{ matrix.elixir }}
otp-version: ${{ matrix.otp }}
- name: Retrieve Mix Dependencies Cache
uses: actions/cache@v1
id: mix-cache
with:
path: deps
key: ${{ runner.os }}-${{ matrix.otp }}-${{ matrix.elixir }}-mix-${{ hashFiles(format('{0}{1}', github.workspace, '/mix.lock')) }}
- name: Install Mix Dependencies
if: steps.mix-cache.outputs.cache-hit != 'true'
run: |
mix local.rebar --force
mix local.hex --force
mix deps.get
- run: mix hex.audit

View file

@ -1,54 +0,0 @@
name: mix test
on:
pull_request:
branches:
- main
jobs:
test:
runs-on: ubuntu-latest
env:
MIX_ENV: test
strategy:
matrix:
elixir: [1.13.4]
otp: [25.0.3]
services:
postgres:
image: postgres
env:
POSTGRES_HOST_AUTH_METHOD: trust
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 5432:5432
steps:
- uses: actions/checkout@v2
- uses: erlef/setup-beam@v1
with:
elixir-version: ${{ matrix.elixir }}
otp-version: ${{ matrix.otp }}
- name: Retrieve Mix Dependencies Cache
uses: actions/cache@v1
id: mix-cache
with:
path: deps
key: ${{ runner.os }}-${{ matrix.otp }}-${{ matrix.elixir }}-mix-${{ hashFiles(format('{0}{1}', github.workspace, '/mix.lock')) }}
- name: Install Mix Dependencies
if: steps.mix-cache.outputs.cache-hit != 'true'
run: |
mix local.rebar --force
mix local.hex --force
mix deps.get
- run: mix test
env:
MIX_ENV: test
PGUSER: postgres
PGPASS: postgres
PGHOST: postgres

2
.gitignore vendored
View file

@ -24,3 +24,5 @@ ash_gen_server-*.tar
# Temporary files, for example, from tests.
/tmp/
/priv/plts

18
LICENSE Normal file
View file

@ -0,0 +1,18 @@
Copyright 2022 Alembic Pty Ltd.
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View file

@ -2,31 +2,38 @@
An Ash Datalayer backed by individual GenServers.
If you want in-memory storage of resources then take a look at
`Ash.DataLayer.Ets`.
This package provides an
[`Ash.DataLayer`](https://ash-hq.org/docs/module/ash/latest/ash-datalayer) which
stores resources in emphemeral GenServers. The main use-case for this is two fold:
1. Ability to automatically remove resources after an inactivity timeout.
2. (Potential) ability to migrate resources across a cluster during deploys to
allow access to continue without failure.
3. before and after hooks for changesets and queries are run within the server
process, making registration, etc, possible.
## Caveats
* When a resource using this datalayer is created it spawns an instance of
`AshGenServer.Server` and performs all operations on the data within it.
This means that your actions must pay the price of a `GenServer.call/3` to
read or modify the data.
* When destroying a resource it's process is terminated and it's internal
state is lost.
* If, for some reason, the `AshGenServer.Server` process crashes or exits for
an abnormal reason the supervisor will restart it **with the changeset used
by the `create` action** - this means that any updates performed since
creation will be lost.
* Any resource using this data source **must** have at least one primary key
field.
* Retrieving a resource by primary key is an optimised case, but any other
queries will pay the price of having to query every `AshGenServer.Server`
process in sequence.
## Installation
If [available in Hex](https://hex.pm/docs/publish), the package can be installed
@ -40,7 +47,37 @@ def deps do
end
```
Documentation can be generated with [ExDoc](https://github.com/elixir-lang/ex_doc)
and published on [HexDocs](https://hexdocs.pm). Once published, the docs can
be found at <https://hexdocs.pm/ash_gen_server>.
## Usage
This package assumes that you have [Ash](https://ash-hq.org) installed and
configured. See the Ash documentation for details.
Once installed you can easily define a resource which is backed by a GenServer:
```elixir
defmodule MyApp.EphemeralResource do
use Ash.Resource, data_layer: AshGenServer.DataLayer
attributes do
uuid_primary_key :id
attribute :temporary_data, :string
end
end
```
## Documentation
Documentation for the latest release will be [available on
hexdocs](https://hexdocs.pm/ash_gen_server) and for the [`main`
branch](https://team-alembic.github.io/ash_gen_server).
## Contributing
* To contribute updates, fixes or new features please fork and open a
pull-request against `main`.
* Please use [conventional
commits](https://www.conventionalcommits.org/en/v1.0.0/) - this allows us to
dynamically generate the changelog.
* Feel free to ask any questions on out [GitHub discussions
page](https://github.com/team-alembic/ash_gen_server/discussions).

View file

@ -1,10 +1,9 @@
defmodule AshGenServer.Application do
# See https://hexdocs.pm/elixir/Application.html
# for more information on OTP Applications
@moduledoc false
use Application
@doc false
@impl true
def start(_type, _args) do
children()

View file

@ -6,27 +6,27 @@ defmodule AshGenServer.DataLayer do
`Ash.DataLayer.Ets`.
## Caveats
* When a resource using this datalayer is created it spawns an instance of
`AshGenServer.Server` and performs all operations on the data within it.
This means that your actions must pay the price of a `GenServer.call/3` to
read or modify the data.
* When destroying a resource it's process is terminated and it's internal
state is lost.
* If, for some reason, the `AshGenServer.Server` process crashes or exits for
an abnormal reason the supervisor will restart it **with the changeset used
by the `create` action** - this means that any updates performed since
creation will be lost.
* Any resource using this data source **must** have at least one primary key
field.
* Retrieving a resource by primary key is an optimised case, but any other
queries will pay the price of having to query every `AshGenServer.Server`
process in sequence.
"""
@gen_server %Spark.Dsl.Section{
@ -85,7 +85,7 @@ defmodule AshGenServer.DataLayer do
@doc false
@impl true
@spec filter(Query.t(), Filter.t(), Resource.t()) :: Query.t()
@spec filter(Query.t(), Filter.t(), Resource.t()) :: {:ok, Query.t()}
def filter(%{resource: resource, filter: nil} = query, filter, resource),
do: {:ok, %{query | filter: filter}}
@ -96,23 +96,23 @@ defmodule AshGenServer.DataLayer do
@doc false
@impl true
@spec limit(Query.t(), limit, Resource.t()) :: Query.t() when limit: non_neg_integer()
@spec limit(Query.t(), limit, Resource.t()) :: {:ok, Query.t()} when limit: non_neg_integer()
def limit(%{resource: resource} = query, limit, resource), do: {:ok, %{query | limit: limit}}
@doc false
@impl true
@spec offset(Query.t(), offset, Resource.t()) :: Query.t() when offset: non_neg_integer()
@spec offset(Query.t(), offset, Resource.t()) :: {:ok, Query.t()} when offset: non_neg_integer()
def offset(%{resource: resource} = query, offset, resource),
do: {:ok, %{query | offset: offset}}
@doc false
@impl true
@spec sort(Query.t(), Sort.t(), Resource.t()) :: Query.t()
@spec sort(Query.t(), Sort.t(), Resource.t()) :: {:ok, Query.t()}
def sort(%{resource: resource} = query, sort, resource), do: {:ok, %{query | sort: sort}}
@doc false
@impl true
@spec run_query(Query.t(), Resource.t()) :: {:ok, Enum.t(Resource.t())} | {:error, any}
@spec run_query(Query.t(), Resource.t()) :: {:ok, [Resource.record()]} | {:error, any}
def run_query(%Query{resource: resource, filter: nil} = query, resource),
do: do_slow_query(query, resource)

View file

@ -6,10 +6,10 @@ defmodule AshGenServer.Query do
@type t :: %__MODULE__{
resource: Ash.Resource.t(),
filter: Ash.Filter.t(),
filter: nil | Ash.Filter.t(),
api: Ash.Api.t(),
limit: non_neg_integer(),
offset: non_neg_integer(),
sort: Ash.Sort.t()
limit: nil | non_neg_integer(),
offset: nil | non_neg_integer(),
sort: nil | Ash.Sort.t()
}
end

View file

@ -14,7 +14,7 @@ defmodule AshGenServer.Registry do
This is the key that's actually stored in the Registry.
"""
@type resource_key :: {Ash.resource(), primary_key}
@type resource_key :: {Ash.Resource.t(), primary_key}
@typedoc """
A map containing the primary key field(s) and value(s) for a the resource.
@ -51,7 +51,7 @@ defmodule AshGenServer.Registry do
@doc """
Find all the processes registered to the provided resource.
"""
@spec find_servers_by_resource(Ash.resource()) :: [{primary_key, pid}]
@spec find_servers_by_resource(Ash.Resource.t()) :: [{primary_key, pid}]
def find_servers_by_resource(resource) do
Registry.select(__MODULE__, [
{

View file

@ -42,7 +42,7 @@ defmodule AshGenServer.Server do
@doc false
@impl true
@spec init(list) :: {:ok, t} | {:error, any}
@spec init(list) :: {:ok, t} | {:stop, {:error, any}}
def init([resource, changeset]) do
primary_key = primary_key_from_resource_and_changeset(resource, changeset)
@ -67,7 +67,7 @@ defmodule AshGenServer.Server do
{:ok, state}
else
{:error, {:already_registered, _}} -> {:stop, :already_exists}
{:error, reason} -> {:error, reason}
{:error, reason} -> {:stop, {:error, reason}}
end
end

33
mix.exs
View file

@ -9,10 +9,25 @@ defmodule AshGenServer.MixProject do
version: @version,
elixir: "~> 1.13",
start_permanent: Mix.env() == :prod,
preferred_cli_env: [ci: :test],
aliases: aliases(),
deps: deps(),
package: package(),
elixirc_paths: elixirc_paths(Mix.env()),
consolidate_protocols: Mix.env() != :test
consolidate_protocols: Mix.env() != :test,
dialyzer: [
plt_add_apps: [:mix, :ex_unit, :ash],
plt_core_path: "priv/plts",
plt_file: {:no_warn, "priv/plts/dialyzer.plt"}
],
docs: [
main: "readme",
extras: ["README.md"],
formatters: ["html"],
filter_modules: ~r/^Elixir.AshGenServer/,
source_url_pattern:
"https://github.com/team-alembic/ash_gen_server/blob/main/%{path}#L%{line}"
]
]
end
@ -47,9 +62,23 @@ defmodule AshGenServer.MixProject do
[
{:ash, "~> 2.2"},
{:credo, "~> 1.6", only: [:dev, :test]},
{:ex_doc, ">= 0.0.0", only: [:dev, :test]},
{:dialyxir, "~> 1.2", only: [:dev, :test], runtime: false},
{:doctor, "~> 0.18", only: [:dev, :test]},
{:ex_doc, ">= 0.0.0", only: [:dev, :test]},
{:git_ops, "~> 2.4", only: [:dev, :test], runtime: false}
]
end
defp aliases do
[
ci: [
"format --check-formatted",
"doctor --full --raise",
"credo --strict",
"dialyzer",
"hex.audit",
"test"
]
]
end
end

View file

@ -6,10 +6,12 @@
"comparable": {:hex, :comparable, "1.0.0", "bb669e91cedd14ae9937053e5bcbc3c52bb2f22422611f43b6e38367d94a495f", [:mix], [{:typable, "~> 0.1", [hex: :typable, repo: "hexpm", optional: false]}], "hexpm", "277c11eeb1cd726e7cd41c6c199e7e52fa16ee6830b45ad4cdc62e51f62eb60c"},
"credo": {:hex, :credo, "1.6.7", "323f5734350fd23a456f2688b9430e7d517afb313fbd38671b8a4449798a7854", [:mix], [{:bunt, "~> 0.2.1", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2.8", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "41e110bfb007f7eda7f897c10bf019ceab9a0b269ce79f015d54b0dcf4fc7dd3"},
"decimal": {:hex, :decimal, "2.0.0", "a78296e617b0f5dd4c6caf57c714431347912ffb1d0842e998e9792b5642d697", [:mix], [], "hexpm", "34666e9c55dea81013e77d9d87370fe6cb6291d1ef32f46a1600230b1d44f577"},
"dialyxir": {:hex, :dialyxir, "1.2.0", "58344b3e87c2e7095304c81a9ae65cb68b613e28340690dfe1a5597fd08dec37", [:mix], [{:erlex, ">= 0.2.6", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "61072136427a851674cab81762be4dbeae7679f85b1272b6d25c3a839aff8463"},
"doctor": {:hex, :doctor, "0.20.0", "2a8ff8f87eaf3fc78f20ffcfa7a3181f2bdb6a115a4abd52582e6156a89649a5", [:mix], [{:decimal, "~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}], "hexpm", "36ba43bdf7d799c41e1dc00b3429eb48bc5d4dc3f63b181ca1aa8829ec638862"},
"earmark_parser": {:hex, :earmark_parser, "1.4.29", "149d50dcb3a93d9f3d6f3ecf18c918fb5a2d3c001b5d3305c926cddfbd33355b", [:mix], [], "hexpm", "4902af1b3eb139016aed210888748db8070b8125c2342ce3dcae4f38dcc63503"},
"ecto": {:hex, :ecto, "3.9.1", "67173b1687afeb68ce805ee7420b4261649d5e2deed8fe5550df23bab0bc4396", [: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 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "c80bb3d736648df790f7f92f81b36c922d9dd3203ca65be4ff01d067f54eb304"},
"elixir_make": {:hex, :elixir_make, "0.6.3", "bc07d53221216838d79e03a8019d0839786703129599e9619f4ab74c8c096eac", [:mix], [], "hexpm", "f5cbd651c5678bcaabdbb7857658ee106b12509cd976c2c2fca99688e1daf716"},
"erlex": {:hex, :erlex, "0.2.6", "c7987d15e899c7a2f34f5420d2a2ea0d659682c06ac607572df55a43753aa12e", [:mix], [], "hexpm", "2ed2e25711feb44d52b17d2780eabf998452f6efda104877a3881c2f8c0c0c75"},
"ets": {:hex, :ets, "0.8.1", "8ff9bcda5682b98493f8878fc9dbd990e48d566cba8cce59f7c2a78130da29ea", [:mix], [], "hexpm", "6be41b50adb5bc5c43626f25ea2d0af1f4a242fb3fad8d53f0c67c20b78915cc"},
"ex_doc": {:hex, :ex_doc, "0.29.0", "4a1cb903ce746aceef9c1f9ae8a6c12b742a5461e6959b9d3b24d813ffbea146", [:mix], [{:earmark_parser, "~> 1.4.19", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "f096adb8bbca677d35d278223361c7792d496b3fc0d0224c9d4bc2f651af5db1"},
"file_system": {:hex, :file_system, "0.2.10", "fb082005a9cd1711c05b5248710f8826b02d7d1784e7c3451f9c1231d4fc162d", [:mix], [], "hexpm", "41195edbfb562a593726eda3b3e8b103a309b733ad25f3d642ba49696bf715dc"},

View file

@ -5,6 +5,6 @@ defmodule TimeTravel do
use Ash.Api, otp_app: :ash_gen_server
resources do
registry TimeTravel.Registry
registry(TimeTravel.Registry)
end
end

View file

@ -12,29 +12,29 @@ defmodule TimeTravel.Character do
}
actions do
create :create
create(:create)
read :read do
primary? true
primary?(true)
end
destroy :destroy
destroy(:destroy)
update :travel_in_time do
argument :target_year, :integer, allow_nil?: false
argument(:target_year, :integer, allow_nil?: false)
change TimeTravel.CharacterTravelChange
change(TimeTravel.CharacterTravelChange)
end
end
attributes do
uuid_primary_key :id
uuid_primary_key(:id)
attribute :name, :string, allow_nil?: false
attribute :nickname, :string
attribute :current_year, :integer, allow_nil?: false
attribute(:name, :string, allow_nil?: false)
attribute(:nickname, :string)
attribute(:current_year, :integer, allow_nil?: false)
create_timestamp :created_at
update_timestamp :updated_at
create_timestamp(:created_at)
update_timestamp(:updated_at)
end
end

View file

@ -14,40 +14,40 @@ defmodule TimeTravel.Machine do
}
actions do
create :create
create(:create)
read :read do
primary? true
primary?(true)
end
destroy :destroy
destroy(:destroy)
update :travel_in_time do
argument :occupants, {:array, TimeTravel.Character}
argument :target_year, :integer, allow_nil?: false
change TimeTravel.MachineTravelChange
argument(:occupants, {:array, TimeTravel.Character})
argument(:target_year, :integer, allow_nil?: false)
change(TimeTravel.MachineTravelChange)
end
update :retrofit do
argument :power_source, :string, allow_nil?: false
change TimeTravel.MachineRetrofitChange
argument(:power_source, :string, allow_nil?: false)
change(TimeTravel.MachineRetrofitChange)
end
update :charge do
change TimeTravel.MachineChargeChange
change(TimeTravel.MachineChargeChange)
end
end
attributes do
uuid_primary_key :id
uuid_primary_key(:id)
attribute :name, :string, allow_nil?: false
attribute :model, :string
attribute :manufacturer, :string
attribute :power_source, :string
attribute :has_power?, :boolean, allow_nil?: false, default: false
attribute(:name, :string, allow_nil?: false)
attribute(:model, :string)
attribute(:manufacturer, :string)
attribute(:power_source, :string)
attribute(:has_power?, :boolean, allow_nil?: false, default: false)
create_timestamp :created_at
update_timestamp :updated_at
create_timestamp(:created_at)
update_timestamp(:updated_at)
end
end

View file

@ -3,7 +3,7 @@ defmodule TimeTravel.Registry do
use Ash.Registry, extensions: [Ash.Registry.ResourceValidations]
entries do
entry TimeTravel.Character
entry TimeTravel.Machine
entry(TimeTravel.Character)
entry(TimeTravel.Machine)
end
end