mirror of
https://github.com/team-alembic/ash_gen_server.git
synced 2024-09-19 12:53:34 +12:00
improvement: update CI to staple-actions and get (most) checks passing.
This commit is contained in:
parent
20290e061e
commit
a3d3593028
23 changed files with 309 additions and 348 deletions
|
@ -5,7 +5,7 @@
|
||||||
min_module_spec_coverage: 0,
|
min_module_spec_coverage: 0,
|
||||||
min_overall_doc_coverage: 50,
|
min_overall_doc_coverage: 50,
|
||||||
min_overall_spec_coverage: 0,
|
min_overall_spec_coverage: 0,
|
||||||
moduledoc_required: true,
|
min_overall_moduledoc_coverage: 100,
|
||||||
exception_moduledoc_required: true,
|
exception_moduledoc_required: true,
|
||||||
raise: false,
|
raise: false,
|
||||||
reporter: Doctor.Reporters.Full,
|
reporter: Doctor.Reporters.Full,
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
[
|
[
|
||||||
import_deps: [:ash],
|
import_deps: [:spark],
|
||||||
inputs: [
|
inputs: [
|
||||||
"*.{ex,exs}",
|
"*.{ex,exs}",
|
||||||
"{config,lib,test}/**/*.{ex,exs}"
|
"{config,lib,test}/**/*.{ex,exs}"
|
||||||
],
|
],
|
||||||
plugins: [Ash.ResourceFormatter]
|
plugins: [Spark.Formatter]
|
||||||
]
|
]
|
||||||
|
|
154
.github/workflows/elixir_lib.yml
vendored
Normal file
154
.github/workflows/elixir_lib.yml
vendored
Normal 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
|
36
.github/workflows/mix_credo.yml
vendored
36
.github/workflows/mix_credo.yml
vendored
|
@ -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
|
|
36
.github/workflows/mix_doctor.yml
vendored
36
.github/workflows/mix_doctor.yml
vendored
|
@ -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
|
|
37
.github/workflows/mix_format.yml
vendored
37
.github/workflows/mix_format.yml
vendored
|
@ -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
|
|
82
.github/workflows/mix_git_ops.yml
vendored
82
.github/workflows/mix_git_ops.yml
vendored
|
@ -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
|
|
35
.github/workflows/mix_hex_audit.yml
vendored
35
.github/workflows/mix_hex_audit.yml
vendored
|
@ -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
|
|
54
.github/workflows/mix_test.yml
vendored
54
.github/workflows/mix_test.yml
vendored
|
@ -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
2
.gitignore
vendored
|
@ -24,3 +24,5 @@ ash_gen_server-*.tar
|
||||||
|
|
||||||
# Temporary files, for example, from tests.
|
# Temporary files, for example, from tests.
|
||||||
/tmp/
|
/tmp/
|
||||||
|
|
||||||
|
/priv/plts
|
||||||
|
|
18
LICENSE
Normal file
18
LICENSE
Normal 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.
|
59
README.md
59
README.md
|
@ -2,31 +2,38 @@
|
||||||
|
|
||||||
An Ash Datalayer backed by individual GenServers.
|
An Ash Datalayer backed by individual GenServers.
|
||||||
|
|
||||||
If you want in-memory storage of resources then take a look at
|
This package provides an
|
||||||
`Ash.DataLayer.Ets`.
|
[`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
|
## Caveats
|
||||||
|
|
||||||
* When a resource using this datalayer is created it spawns an instance of
|
* When a resource using this datalayer is created it spawns an instance of
|
||||||
`AshGenServer.Server` and performs all operations on the data within it.
|
`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
|
This means that your actions must pay the price of a `GenServer.call/3` to
|
||||||
read or modify the data.
|
read or modify the data.
|
||||||
|
|
||||||
* When destroying a resource it's process is terminated and it's internal
|
* When destroying a resource it's process is terminated and it's internal
|
||||||
state is lost.
|
state is lost.
|
||||||
|
|
||||||
* If, for some reason, the `AshGenServer.Server` process crashes or exits for
|
* If, for some reason, the `AshGenServer.Server` process crashes or exits for
|
||||||
an abnormal reason the supervisor will restart it **with the changeset used
|
an abnormal reason the supervisor will restart it **with the changeset used
|
||||||
by the `create` action** - this means that any updates performed since
|
by the `create` action** - this means that any updates performed since
|
||||||
creation will be lost.
|
creation will be lost.
|
||||||
|
|
||||||
* Any resource using this data source **must** have at least one primary key
|
* Any resource using this data source **must** have at least one primary key
|
||||||
field.
|
field.
|
||||||
|
|
||||||
* Retrieving a resource by primary key is an optimised case, but any other
|
* 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`
|
queries will pay the price of having to query every `AshGenServer.Server`
|
||||||
process in sequence.
|
process in sequence.
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
If [available in Hex](https://hex.pm/docs/publish), the package can be installed
|
If [available in Hex](https://hex.pm/docs/publish), the package can be installed
|
||||||
|
@ -40,7 +47,37 @@ def deps do
|
||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
Documentation can be generated with [ExDoc](https://github.com/elixir-lang/ex_doc)
|
## Usage
|
||||||
and published on [HexDocs](https://hexdocs.pm). Once published, the docs can
|
|
||||||
be found at <https://hexdocs.pm/ash_gen_server>.
|
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).
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
defmodule AshGenServer.Application do
|
defmodule AshGenServer.Application do
|
||||||
# See https://hexdocs.pm/elixir/Application.html
|
|
||||||
# for more information on OTP Applications
|
|
||||||
@moduledoc false
|
@moduledoc false
|
||||||
|
|
||||||
use Application
|
use Application
|
||||||
|
|
||||||
|
@doc false
|
||||||
@impl true
|
@impl true
|
||||||
def start(_type, _args) do
|
def start(_type, _args) do
|
||||||
children()
|
children()
|
||||||
|
|
|
@ -6,27 +6,27 @@ defmodule AshGenServer.DataLayer do
|
||||||
`Ash.DataLayer.Ets`.
|
`Ash.DataLayer.Ets`.
|
||||||
|
|
||||||
## Caveats
|
## Caveats
|
||||||
|
|
||||||
* When a resource using this datalayer is created it spawns an instance of
|
* When a resource using this datalayer is created it spawns an instance of
|
||||||
`AshGenServer.Server` and performs all operations on the data within it.
|
`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
|
This means that your actions must pay the price of a `GenServer.call/3` to
|
||||||
read or modify the data.
|
read or modify the data.
|
||||||
|
|
||||||
* When destroying a resource it's process is terminated and it's internal
|
* When destroying a resource it's process is terminated and it's internal
|
||||||
state is lost.
|
state is lost.
|
||||||
|
|
||||||
* If, for some reason, the `AshGenServer.Server` process crashes or exits for
|
* If, for some reason, the `AshGenServer.Server` process crashes or exits for
|
||||||
an abnormal reason the supervisor will restart it **with the changeset used
|
an abnormal reason the supervisor will restart it **with the changeset used
|
||||||
by the `create` action** - this means that any updates performed since
|
by the `create` action** - this means that any updates performed since
|
||||||
creation will be lost.
|
creation will be lost.
|
||||||
|
|
||||||
* Any resource using this data source **must** have at least one primary key
|
* Any resource using this data source **must** have at least one primary key
|
||||||
field.
|
field.
|
||||||
|
|
||||||
* Retrieving a resource by primary key is an optimised case, but any other
|
* 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`
|
queries will pay the price of having to query every `AshGenServer.Server`
|
||||||
process in sequence.
|
process in sequence.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@gen_server %Spark.Dsl.Section{
|
@gen_server %Spark.Dsl.Section{
|
||||||
|
@ -85,7 +85,7 @@ defmodule AshGenServer.DataLayer do
|
||||||
|
|
||||||
@doc false
|
@doc false
|
||||||
@impl true
|
@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),
|
def filter(%{resource: resource, filter: nil} = query, filter, resource),
|
||||||
do: {:ok, %{query | filter: filter}}
|
do: {:ok, %{query | filter: filter}}
|
||||||
|
|
||||||
|
@ -96,23 +96,23 @@ defmodule AshGenServer.DataLayer do
|
||||||
|
|
||||||
@doc false
|
@doc false
|
||||||
@impl true
|
@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}}
|
def limit(%{resource: resource} = query, limit, resource), do: {:ok, %{query | limit: limit}}
|
||||||
|
|
||||||
@doc false
|
@doc false
|
||||||
@impl true
|
@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),
|
def offset(%{resource: resource} = query, offset, resource),
|
||||||
do: {:ok, %{query | offset: offset}}
|
do: {:ok, %{query | offset: offset}}
|
||||||
|
|
||||||
@doc false
|
@doc false
|
||||||
@impl true
|
@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}}
|
def sort(%{resource: resource} = query, sort, resource), do: {:ok, %{query | sort: sort}}
|
||||||
|
|
||||||
@doc false
|
@doc false
|
||||||
@impl true
|
@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),
|
def run_query(%Query{resource: resource, filter: nil} = query, resource),
|
||||||
do: do_slow_query(query, resource)
|
do: do_slow_query(query, resource)
|
||||||
|
|
||||||
|
|
|
@ -6,10 +6,10 @@ defmodule AshGenServer.Query do
|
||||||
|
|
||||||
@type t :: %__MODULE__{
|
@type t :: %__MODULE__{
|
||||||
resource: Ash.Resource.t(),
|
resource: Ash.Resource.t(),
|
||||||
filter: Ash.Filter.t(),
|
filter: nil | Ash.Filter.t(),
|
||||||
api: Ash.Api.t(),
|
api: Ash.Api.t(),
|
||||||
limit: non_neg_integer(),
|
limit: nil | non_neg_integer(),
|
||||||
offset: non_neg_integer(),
|
offset: nil | non_neg_integer(),
|
||||||
sort: Ash.Sort.t()
|
sort: nil | Ash.Sort.t()
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
|
@ -14,7 +14,7 @@ defmodule AshGenServer.Registry do
|
||||||
|
|
||||||
This is the key that's actually stored in the Registry.
|
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 """
|
@typedoc """
|
||||||
A map containing the primary key field(s) and value(s) for a the resource.
|
A map containing the primary key field(s) and value(s) for a the resource.
|
||||||
|
@ -51,7 +51,7 @@ defmodule AshGenServer.Registry do
|
||||||
@doc """
|
@doc """
|
||||||
Find all the processes registered to the provided resource.
|
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
|
def find_servers_by_resource(resource) do
|
||||||
Registry.select(__MODULE__, [
|
Registry.select(__MODULE__, [
|
||||||
{
|
{
|
||||||
|
|
|
@ -42,7 +42,7 @@ defmodule AshGenServer.Server do
|
||||||
|
|
||||||
@doc false
|
@doc false
|
||||||
@impl true
|
@impl true
|
||||||
@spec init(list) :: {:ok, t} | {:error, any}
|
@spec init(list) :: {:ok, t} | {:stop, {:error, any}}
|
||||||
def init([resource, changeset]) do
|
def init([resource, changeset]) do
|
||||||
primary_key = primary_key_from_resource_and_changeset(resource, changeset)
|
primary_key = primary_key_from_resource_and_changeset(resource, changeset)
|
||||||
|
|
||||||
|
@ -67,7 +67,7 @@ defmodule AshGenServer.Server do
|
||||||
{:ok, state}
|
{:ok, state}
|
||||||
else
|
else
|
||||||
{:error, {:already_registered, _}} -> {:stop, :already_exists}
|
{:error, {:already_registered, _}} -> {:stop, :already_exists}
|
||||||
{:error, reason} -> {:error, reason}
|
{:error, reason} -> {:stop, {:error, reason}}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
33
mix.exs
33
mix.exs
|
@ -9,10 +9,25 @@ defmodule AshGenServer.MixProject do
|
||||||
version: @version,
|
version: @version,
|
||||||
elixir: "~> 1.13",
|
elixir: "~> 1.13",
|
||||||
start_permanent: Mix.env() == :prod,
|
start_permanent: Mix.env() == :prod,
|
||||||
|
preferred_cli_env: [ci: :test],
|
||||||
|
aliases: aliases(),
|
||||||
deps: deps(),
|
deps: deps(),
|
||||||
package: package(),
|
package: package(),
|
||||||
elixirc_paths: elixirc_paths(Mix.env()),
|
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
|
end
|
||||||
|
|
||||||
|
@ -47,9 +62,23 @@ defmodule AshGenServer.MixProject do
|
||||||
[
|
[
|
||||||
{:ash, "~> 2.2"},
|
{:ash, "~> 2.2"},
|
||||||
{:credo, "~> 1.6", only: [:dev, :test]},
|
{: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]},
|
{:doctor, "~> 0.18", only: [:dev, :test]},
|
||||||
|
{:ex_doc, ">= 0.0.0", only: [:dev, :test]},
|
||||||
{:git_ops, "~> 2.4", only: [:dev, :test], runtime: false}
|
{:git_ops, "~> 2.4", only: [:dev, :test], runtime: false}
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp aliases do
|
||||||
|
[
|
||||||
|
ci: [
|
||||||
|
"format --check-formatted",
|
||||||
|
"doctor --full --raise",
|
||||||
|
"credo --strict",
|
||||||
|
"dialyzer",
|
||||||
|
"hex.audit",
|
||||||
|
"test"
|
||||||
|
]
|
||||||
|
]
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
2
mix.lock
2
mix.lock
|
@ -6,10 +6,12 @@
|
||||||
"comparable": {:hex, :comparable, "1.0.0", "bb669e91cedd14ae9937053e5bcbc3c52bb2f22422611f43b6e38367d94a495f", [:mix], [{:typable, "~> 0.1", [hex: :typable, repo: "hexpm", optional: false]}], "hexpm", "277c11eeb1cd726e7cd41c6c199e7e52fa16ee6830b45ad4cdc62e51f62eb60c"},
|
"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"},
|
"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"},
|
"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"},
|
"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"},
|
"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"},
|
"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"},
|
"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"},
|
"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"},
|
"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"},
|
"file_system": {:hex, :file_system, "0.2.10", "fb082005a9cd1711c05b5248710f8826b02d7d1784e7c3451f9c1231d4fc162d", [:mix], [], "hexpm", "41195edbfb562a593726eda3b3e8b103a309b733ad25f3d642ba49696bf715dc"},
|
||||||
|
|
|
@ -5,6 +5,6 @@ defmodule TimeTravel do
|
||||||
use Ash.Api, otp_app: :ash_gen_server
|
use Ash.Api, otp_app: :ash_gen_server
|
||||||
|
|
||||||
resources do
|
resources do
|
||||||
registry TimeTravel.Registry
|
registry(TimeTravel.Registry)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -12,29 +12,29 @@ defmodule TimeTravel.Character do
|
||||||
}
|
}
|
||||||
|
|
||||||
actions do
|
actions do
|
||||||
create :create
|
create(:create)
|
||||||
|
|
||||||
read :read do
|
read :read do
|
||||||
primary? true
|
primary?(true)
|
||||||
end
|
end
|
||||||
|
|
||||||
destroy :destroy
|
destroy(:destroy)
|
||||||
|
|
||||||
update :travel_in_time do
|
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
|
||||||
end
|
end
|
||||||
|
|
||||||
attributes do
|
attributes do
|
||||||
uuid_primary_key :id
|
uuid_primary_key(:id)
|
||||||
|
|
||||||
attribute :name, :string, allow_nil?: false
|
attribute(:name, :string, allow_nil?: false)
|
||||||
attribute :nickname, :string
|
attribute(:nickname, :string)
|
||||||
attribute :current_year, :integer, allow_nil?: false
|
attribute(:current_year, :integer, allow_nil?: false)
|
||||||
|
|
||||||
create_timestamp :created_at
|
create_timestamp(:created_at)
|
||||||
update_timestamp :updated_at
|
update_timestamp(:updated_at)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -14,40 +14,40 @@ defmodule TimeTravel.Machine do
|
||||||
}
|
}
|
||||||
|
|
||||||
actions do
|
actions do
|
||||||
create :create
|
create(:create)
|
||||||
|
|
||||||
read :read do
|
read :read do
|
||||||
primary? true
|
primary?(true)
|
||||||
end
|
end
|
||||||
|
|
||||||
destroy :destroy
|
destroy(:destroy)
|
||||||
|
|
||||||
update :travel_in_time do
|
update :travel_in_time do
|
||||||
argument :occupants, {:array, TimeTravel.Character}
|
argument(:occupants, {:array, TimeTravel.Character})
|
||||||
argument :target_year, :integer, allow_nil?: false
|
argument(:target_year, :integer, allow_nil?: false)
|
||||||
change TimeTravel.MachineTravelChange
|
change(TimeTravel.MachineTravelChange)
|
||||||
end
|
end
|
||||||
|
|
||||||
update :retrofit do
|
update :retrofit do
|
||||||
argument :power_source, :string, allow_nil?: false
|
argument(:power_source, :string, allow_nil?: false)
|
||||||
change TimeTravel.MachineRetrofitChange
|
change(TimeTravel.MachineRetrofitChange)
|
||||||
end
|
end
|
||||||
|
|
||||||
update :charge do
|
update :charge do
|
||||||
change TimeTravel.MachineChargeChange
|
change(TimeTravel.MachineChargeChange)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
attributes do
|
attributes do
|
||||||
uuid_primary_key :id
|
uuid_primary_key(:id)
|
||||||
|
|
||||||
attribute :name, :string, allow_nil?: false
|
attribute(:name, :string, allow_nil?: false)
|
||||||
attribute :model, :string
|
attribute(:model, :string)
|
||||||
attribute :manufacturer, :string
|
attribute(:manufacturer, :string)
|
||||||
attribute :power_source, :string
|
attribute(:power_source, :string)
|
||||||
attribute :has_power?, :boolean, allow_nil?: false, default: false
|
attribute(:has_power?, :boolean, allow_nil?: false, default: false)
|
||||||
|
|
||||||
create_timestamp :created_at
|
create_timestamp(:created_at)
|
||||||
update_timestamp :updated_at
|
update_timestamp(:updated_at)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,7 +3,7 @@ defmodule TimeTravel.Registry do
|
||||||
use Ash.Registry, extensions: [Ash.Registry.ResourceValidations]
|
use Ash.Registry, extensions: [Ash.Registry.ResourceValidations]
|
||||||
|
|
||||||
entries do
|
entries do
|
||||||
entry TimeTravel.Character
|
entry(TimeTravel.Character)
|
||||||
entry TimeTravel.Machine
|
entry(TimeTravel.Machine)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue