mirror of
https://github.com/ash-project/ash.git
synced 2024-09-19 21:13:10 +12:00
docs: greatly improved DSL documentation in hex
This commit is contained in:
parent
c33f66a4ce
commit
6e2d1fd0ac
63 changed files with 4221 additions and 449 deletions
|
@ -11,8 +11,8 @@
|
|||
## ...or adjusted (e.g. use one-line formatter for more compact credo output)
|
||||
# {:credo, "mix credo --format oneline"},
|
||||
|
||||
{:check_formatter, command: "mix spark.formatter --check"}
|
||||
# {:doctor, false}
|
||||
{:check_formatter, command: "mix spark.formatter --check"},
|
||||
{:doctor, false}
|
||||
|
||||
## custom new tools may be added (mix tasks or arbitrary commands)
|
||||
# {:my_mix_task, command: "mix release", env: %{"MIX_ENV" => "prod"}},
|
||||
|
|
|
@ -125,7 +125,7 @@
|
|||
{Credo.Check.Refactor.MatchInCondition, false},
|
||||
{Credo.Check.Refactor.NegatedConditionsInUnless, []},
|
||||
{Credo.Check.Refactor.NegatedConditionsWithElse, []},
|
||||
{Credo.Check.Refactor.Nesting, [max_nesting: 7]},
|
||||
{Credo.Check.Refactor.Nesting, [max_nesting: 9]},
|
||||
{Credo.Check.Refactor.UnlessWithElse, []},
|
||||
{Credo.Check.Refactor.WithClauses, []},
|
||||
|
||||
|
|
145
documentation/dsls/DSL:-Ash.Api.cheatmd
Normal file
145
documentation/dsls/DSL:-Ash.Api.cheatmd
Normal file
|
@ -0,0 +1,145 @@
|
|||
# DSL: Ash.Api.Dsl
|
||||
|
||||
Apis are the entrypoints for working with your resources.
|
||||
|
||||
Apis may optionally include a list of resources, in which case they can be
|
||||
used as an `Ash.Registry` in various places. This is for backwards compatibility,
|
||||
but if at all possible you should define an `Ash.Registry` if you are using an extension
|
||||
that requires a list of resources. For example, most extensions look for two application
|
||||
environment variables called `:ash_apis` and `:ash_registries` to find any potential registries
|
||||
|
||||
|
||||
## api
|
||||
General Api configuration
|
||||
|
||||
---
|
||||
|
||||
|
||||
|
||||
### Examples
|
||||
```
|
||||
api do
|
||||
description """
|
||||
Resources related to the flux capacitor.
|
||||
"""
|
||||
end
|
||||
|
||||
```
|
||||
|
||||
|
||||
### Reference
|
||||
| Name | Type | Docs |
|
||||
| --- | --- | --- |
|
||||
| description | `String.t` | A description for the api. |
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## resources
|
||||
List the resources present in this API
|
||||
|
||||
---
|
||||
|
||||
* [resource](#resources-resource)
|
||||
|
||||
### Examples
|
||||
```
|
||||
resources do
|
||||
registry MyApp.Registry
|
||||
en
|
||||
|
||||
```
|
||||
|
||||
|
||||
### Reference
|
||||
| Name | Type | Default | Docs |
|
||||
| --- | --- | --- | --- |
|
||||
| allow | `mfa` | | Support a dynamic resource list by providing a callback that checks whether or not the resource should be allowed. |
|
||||
| allow_unregistered? | `boolean` | false | Whether the Api will support only registered entries or not. |
|
||||
| registry | `module` | | Configure the registry that contains the resources. It is recommended to use application config for this, to help with compile times. See the quick start guide for more. |
|
||||
|
||||
|
||||
|
||||
## resources.resource
|
||||
|
||||
Introspection Target: `Ash.Api.Dsl.ResourceReference`
|
||||
|
||||
A resource present in the API
|
||||
|
||||
---
|
||||
|
||||
|
||||
|
||||
### Examples
|
||||
```
|
||||
resource Foo
|
||||
```
|
||||
|
||||
|
||||
### Reference
|
||||
| Name | Type | Docs |
|
||||
| --- | --- | --- |
|
||||
| resource | `module` | |
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## execution
|
||||
Options for how requests are executed using this Api
|
||||
|
||||
---
|
||||
|
||||
|
||||
|
||||
### Examples
|
||||
```
|
||||
execution do
|
||||
timeout :timer.seconds(30)
|
||||
end
|
||||
|
||||
```
|
||||
|
||||
|
||||
### Reference
|
||||
| Name | Type | Default | Docs |
|
||||
| --- | --- | --- | --- |
|
||||
| timeout | `timeout` | 30000 | The default timeout to use for requests using this API. See the [timeouts guide](/documentation/topics/timeouts.md) for more. |
|
||||
| trace_name | `String.t` | | The name to use in traces. Defaults to the last part of the module. See the [monitoring guide](/documentation/topics/monitoring.md) for more |
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## authorization
|
||||
Options for how requests are authorized using this Api. See the [security guide](/documentation/topics/security.md) for more.
|
||||
|
||||
|
||||
---
|
||||
|
||||
|
||||
|
||||
### Examples
|
||||
```
|
||||
authorization do
|
||||
authorize :by_default
|
||||
end
|
||||
|
||||
```
|
||||
|
||||
|
||||
### Reference
|
||||
| Name | Type | Default | Docs |
|
||||
| --- | --- | --- | --- |
|
||||
| require_actor? | `boolean` | false | Requires that an actor has been supplied. |
|
||||
| authorize | `:always \| :by_default \| :when_requested` | :when_requested | When to run authorization for a given request. |
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
37
documentation/dsls/DSL:-Ash.DataLayer.Ets.cheatmd
Normal file
37
documentation/dsls/DSL:-Ash.DataLayer.Ets.cheatmd
Normal file
|
@ -0,0 +1,37 @@
|
|||
# DSL: Ash.DataLayer.Ets
|
||||
|
||||
An ETS (Erlang Term Storage) backed Ash Datalayer, for testing and lightweight usage.
|
||||
|
||||
Remember, this does not have support for transactions! This is not recommended for production
|
||||
use, especially in multi-user applications. It can, however, be great for prototyping.
|
||||
|
||||
|
||||
## ets
|
||||
A section for configuring the ets data layer
|
||||
|
||||
|
||||
---
|
||||
|
||||
|
||||
|
||||
### Examples
|
||||
```
|
||||
ets do
|
||||
# Used in testing
|
||||
private? true
|
||||
end
|
||||
|
||||
```
|
||||
|
||||
|
||||
### Reference
|
||||
| Name | Type | Default | Docs |
|
||||
| --- | --- | --- | --- |
|
||||
| private? | `boolean` | false | Sets the ets table protection to private, and scopes it to only this process. The table name will not be used directly if this is true, to allow multiple processes to use this resource separately. |
|
||||
| table | `atom` | | The name of the table. Defaults to the resource name. |
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
40
documentation/dsls/DSL:-Ash.DataLayer.Mnesia.cheatmd
Normal file
40
documentation/dsls/DSL:-Ash.DataLayer.Mnesia.cheatmd
Normal file
|
@ -0,0 +1,40 @@
|
|||
# DSL: Ash.DataLayer.Mnesia
|
||||
|
||||
An Mnesia backed Ash Datalayer.
|
||||
|
||||
In your application initialization, you will need to call `Mnesia.create_schema([node()])`.
|
||||
|
||||
Additionally, you will want to create your mnesia tables there.
|
||||
|
||||
This data layer is *unoptimized*, fetching all records from a table and filtering them
|
||||
in memory. For that reason, it is not recommended to use it with large amounts of data. It can be
|
||||
great for prototyping or light usage, though.
|
||||
|
||||
|
||||
## mnesia
|
||||
A section for configuring the mnesia data layer
|
||||
|
||||
|
||||
---
|
||||
|
||||
|
||||
|
||||
### Examples
|
||||
```
|
||||
mnesia do
|
||||
table :custom_table
|
||||
end
|
||||
|
||||
```
|
||||
|
||||
|
||||
### Reference
|
||||
| Name | Type | Docs |
|
||||
| --- | --- | --- |
|
||||
| table | `atom` | The table name to use, defaults to the name of the resource |
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
549
documentation/dsls/DSL:-Ash.Flow.cheatmd
Normal file
549
documentation/dsls/DSL:-Ash.Flow.cheatmd
Normal file
|
@ -0,0 +1,549 @@
|
|||
# DSL: Ash.Flow.Dsl
|
||||
|
||||
The built in flow DSL.
|
||||
|
||||
## Halting
|
||||
|
||||
Steps can be halted, which will stop the flow from continuing and return a halted flow. To attach a specific reason, use a `halt_reason`.
|
||||
If you need more complex halting logic, then you'd want to use a custom step, and return `{:error, Ash.Error.Flow.Halted.exception(...)}`
|
||||
|
||||
|
||||
## flow
|
||||
Details about the flow itself, like description and the successful return type.
|
||||
|
||||
|
||||
---
|
||||
|
||||
* [argument](#flow-argument)
|
||||
|
||||
### Examples
|
||||
|
||||
|
||||
### Reference
|
||||
| Name | Type | Docs |
|
||||
| --- | --- | --- |
|
||||
| api | `module` | An api to use by default when calling actions |
|
||||
| description | `String.t` | A description of the flow |
|
||||
| trace_name | `String.t` | The name to use when creating traces. Defaults to the short name. |
|
||||
| short_name | `atom` | A short name to use for the flow. Defaults to the last to parts of the module name, underscored. |
|
||||
| returns | ``any`` | The step or step that should constitute the return value. |
|
||||
|
||||
|
||||
|
||||
## flow.argument
|
||||
|
||||
Introspection Target: `Ash.Flow.Argument`
|
||||
|
||||
An argument to be passed into the flow
|
||||
|
||||
|
||||
---
|
||||
|
||||
|
||||
|
||||
### Examples
|
||||
```
|
||||
argument :params, :map do
|
||||
default %{}
|
||||
end
|
||||
|
||||
```
|
||||
|
||||
|
||||
```
|
||||
argument :retries, :integer do
|
||||
allow_nil? false
|
||||
end
|
||||
|
||||
```
|
||||
|
||||
|
||||
### Reference
|
||||
| Name | Type | Default | Docs |
|
||||
| --- | --- | --- | --- |
|
||||
| name | `atom` | | The name to use for the argument |
|
||||
| type | `module` | | The type of the argument. See `Ash.Type` for more. |
|
||||
| default | `(-> any) \| mfa \| any()` | | A default value to use for the argument if not provided |
|
||||
| allow_nil? | `boolean` | true | Whether or not the argument value may be nil |
|
||||
| constraints | `Keyword.t` | [] | Constraints to provide to the type when casting the value. See the type's documentation for more information. |
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## steps
|
||||
|
||||
---
|
||||
|
||||
* [map](#steps-map)
|
||||
|
||||
* [branch](#steps-branch)
|
||||
|
||||
* [transaction](#steps-transaction)
|
||||
|
||||
* [create](#steps-create)
|
||||
* [debug](#steps-debug)
|
||||
* [update](#steps-update)
|
||||
* [destroy](#steps-destroy)
|
||||
* [validate](#steps-validate)
|
||||
* [read](#steps-read)
|
||||
* [run_flow](#steps-run_flow)
|
||||
* [custom](#steps-custom)
|
||||
|
||||
### Examples
|
||||
```
|
||||
steps do
|
||||
# invokes a create action
|
||||
create :create_post, MyApp.Post, :create
|
||||
end
|
||||
|
||||
```
|
||||
|
||||
|
||||
|
||||
## steps.map
|
||||
|
||||
Introspection Target: `Ash.Flow.Step.Map`
|
||||
|
||||
Runs a set of steps for each item in a provided list.
|
||||
|
||||
|
||||
---
|
||||
|
||||
|
||||
|
||||
### Examples
|
||||
```
|
||||
map :create_users, range(1, arg(:count)) do
|
||||
output :create_user
|
||||
|
||||
create :create_user, Org, :create do
|
||||
input %{
|
||||
first_name: {Faker.Person, :first_name, []},
|
||||
last_name: {Faker.Person, :last_name, []}
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
```
|
||||
|
||||
|
||||
### Reference
|
||||
| Name | Type | Default | Docs |
|
||||
| --- | --- | --- | --- |
|
||||
| over | ``any`` | | The value to be iterated over. Will be available inside the `map` step as `element(:map_step_name)` |
|
||||
| output | `atom` | | Which step to use when constructing the output list. Defaults to the last step. |
|
||||
| name | `atom` | | The name of the step. Will be used when expressing dependencies, and step inputs. |
|
||||
| short_name | `String.t` | | Set a short name for the step. Will be used when building things like mermaid charts. |
|
||||
| wait_for | ``any`` | | Ensures that the step happens after the configured step or steps. This is a template who's results are not used, only awaited. |
|
||||
| touches_resources | `list(atom)` | | A list of resources touched by any custom logic in this step. This is used in the case that this step is run in a transaction. This is primarily only needed for `custom` steps. |
|
||||
| halt_if | ``any`` | | Halts the step by emitting an error (with an `Ash.Error.Flow.Halted`). Can use template variables. See the section on Halting for more. |
|
||||
| halt_reason | ``any`` | :halted | Configures the reason for the `halt_if` clause. |
|
||||
| description | `String.t` | | A description for the step. |
|
||||
|
||||
|
||||
|
||||
## steps.branch
|
||||
|
||||
Introspection Target: `Ash.Flow.Step.Branch`
|
||||
|
||||
Runs a set of steps based on a given value.
|
||||
|
||||
|
||||
---
|
||||
|
||||
|
||||
|
||||
### Examples
|
||||
```
|
||||
branch :create_users, result(:create_users?) do
|
||||
output :create_user
|
||||
|
||||
create :create_user, Org, :create do
|
||||
input %{
|
||||
first_name: {Faker.Person, :first_name, []},
|
||||
last_name: {Faker.Person, :last_name, []}
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
```
|
||||
|
||||
|
||||
### Reference
|
||||
| Name | Type | Default | Docs |
|
||||
| --- | --- | --- | --- |
|
||||
| condition | ``any`` | | A template that must evaluate to `true` for the branch to be executed. |
|
||||
| output | `atom` | | Which step to use as the output. Defaults to the last step. |
|
||||
| name | `atom` | | The name of the step. Will be used when expressing dependencies, and step inputs. |
|
||||
| short_name | `String.t` | | Set a short name for the step. Will be used when building things like mermaid charts. |
|
||||
| wait_for | ``any`` | | Ensures that the step happens after the configured step or steps. This is a template who's results are not used, only awaited. |
|
||||
| touches_resources | `list(atom)` | | A list of resources touched by any custom logic in this step. This is used in the case that this step is run in a transaction. This is primarily only needed for `custom` steps. |
|
||||
| halt_if | ``any`` | | Halts the step by emitting an error (with an `Ash.Error.Flow.Halted`). Can use template variables. See the section on Halting for more. |
|
||||
| halt_reason | ``any`` | :halted | Configures the reason for the `halt_if` clause. |
|
||||
| description | `String.t` | | A description for the step. |
|
||||
|
||||
|
||||
|
||||
## steps.transaction
|
||||
|
||||
Introspection Target: `Ash.Flow.Step.Transaction`
|
||||
|
||||
Runs a set of steps in a transaction.
|
||||
|
||||
|
||||
---
|
||||
|
||||
|
||||
|
||||
### Examples
|
||||
```
|
||||
transaction :create_users do
|
||||
create :create_user, User, :create do
|
||||
input %{
|
||||
first_name: {Faker.Person, :first_name, []},
|
||||
last_name: {Faker.Person, :last_name, []}
|
||||
}
|
||||
end
|
||||
|
||||
create :create_user, Org, :create do
|
||||
input %{
|
||||
first_name: {Faker.Person, :first_name, []},
|
||||
last_name: {Faker.Person, :last_name, []}
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
```
|
||||
|
||||
|
||||
### Reference
|
||||
| Name | Type | Default | Docs |
|
||||
| --- | --- | --- | --- |
|
||||
| output | ``any`` | | Which step or steps to use when constructing the output. Defaults to the last step. |
|
||||
| timeout | `timeout` | | A timeout to apply to the transaction. |
|
||||
| resource | `module \| list(module)` | | The Ash resource to use for the transaction. |
|
||||
| name | `atom` | | The name of the step. Will be used when expressing dependencies, and step inputs. |
|
||||
| short_name | `String.t` | | Set a short name for the step. Will be used when building things like mermaid charts. |
|
||||
| wait_for | ``any`` | | Ensures that the step happens after the configured step or steps. This is a template who's results are not used, only awaited. |
|
||||
| touches_resources | `list(atom)` | | A list of resources touched by any custom logic in this step. This is used in the case that this step is run in a transaction. This is primarily only needed for `custom` steps. |
|
||||
| halt_if | ``any`` | | Halts the step by emitting an error (with an `Ash.Error.Flow.Halted`). Can use template variables. See the section on Halting for more. |
|
||||
| halt_reason | ``any`` | :halted | Configures the reason for the `halt_if` clause. |
|
||||
| description | `String.t` | | A description for the step. |
|
||||
|
||||
|
||||
|
||||
## steps.create
|
||||
|
||||
Introspection Target: `Ash.Flow.Step.Create`
|
||||
|
||||
Declares a step that will call a create action on a resource.
|
||||
|
||||
|
||||
---
|
||||
|
||||
|
||||
|
||||
### Examples
|
||||
```
|
||||
create :create_post, MyApp.Post, :create
|
||||
|
||||
```
|
||||
|
||||
|
||||
### Reference
|
||||
| Name | Type | Default | Docs |
|
||||
| --- | --- | --- | --- |
|
||||
| upsert? | `boolean` | false | Wether or not this action is always an upsert. |
|
||||
| upsert_identity | `atom` | | The identity to use for the upsert. |
|
||||
| name | `atom` | | The name of the step. Will be used when expressing dependencies, and step inputs. |
|
||||
| short_name | `String.t` | | Set a short name for the step. Will be used when building things like mermaid charts. |
|
||||
| wait_for | ``any`` | | Ensures that the step happens after the configured step or steps. This is a template who's results are not used, only awaited. |
|
||||
| touches_resources | `list(atom)` | | A list of resources touched by any custom logic in this step. This is used in the case that this step is run in a transaction. This is primarily only needed for `custom` steps. |
|
||||
| halt_if | ``any`` | | Halts the step by emitting an error (with an `Ash.Error.Flow.Halted`). Can use template variables. See the section on Halting for more. |
|
||||
| halt_reason | ``any`` | :halted | Configures the reason for the `halt_if` clause. |
|
||||
| description | `String.t` | | A description for the step. |
|
||||
| resource | ``any`` | | The resource to call the action on. |
|
||||
| action | ``any`` | | The action to call on the resource. |
|
||||
| api | ``any`` | | The api to use when calling the action. Defaults to the api set in the `flow` section. |
|
||||
| tenant | ``any`` | | A tenant to use for the operation. May be a template or a literal value. |
|
||||
| input | ``any`` | | A template for the input. |
|
||||
|
||||
|
||||
|
||||
## steps.debug
|
||||
|
||||
Introspection Target: `Ash.Flow.Step.Debug`
|
||||
|
||||
Declares a step that will inspect its input and provide
|
||||
additional debug information.
|
||||
|
||||
|
||||
---
|
||||
|
||||
|
||||
|
||||
### Examples
|
||||
```
|
||||
debug :show_some_information do
|
||||
input %{post: result(:create_post)}
|
||||
end
|
||||
|
||||
```
|
||||
|
||||
|
||||
### Reference
|
||||
| Name | Type | Default | Docs |
|
||||
| --- | --- | --- | --- |
|
||||
| input | ``any`` | | A template for the input. |
|
||||
| name | `atom` | | The name of the step. Will be used when expressing dependencies, and step inputs. |
|
||||
| short_name | `String.t` | | Set a short name for the step. Will be used when building things like mermaid charts. |
|
||||
| wait_for | ``any`` | | Ensures that the step happens after the configured step or steps. This is a template who's results are not used, only awaited. |
|
||||
| halt_if | ``any`` | | Halts the step by emitting an error (with an `Ash.Error.Flow.Halted`). Can use template variables. See the section on Halting for more. |
|
||||
| halt_reason | ``any`` | :halted | Configures the reason for the `halt_if` clause. |
|
||||
| description | `String.t` | | A description for the step. |
|
||||
|
||||
|
||||
|
||||
## steps.update
|
||||
|
||||
Introspection Target: `Ash.Flow.Step.Update`
|
||||
|
||||
Declares a step that will call a update action on a resource.
|
||||
|
||||
|
||||
---
|
||||
|
||||
|
||||
|
||||
### Examples
|
||||
```
|
||||
update :update_post, MyApp.Post, :update do
|
||||
record result(:get_post)
|
||||
end
|
||||
|
||||
```
|
||||
|
||||
|
||||
### Reference
|
||||
| Name | Type | Default | Docs |
|
||||
| --- | --- | --- | --- |
|
||||
| record | ``any`` | | The record to be updated, can use template helpers, e.g `result(:step_name)`. |
|
||||
| name | `atom` | | The name of the step. Will be used when expressing dependencies, and step inputs. |
|
||||
| short_name | `String.t` | | Set a short name for the step. Will be used when building things like mermaid charts. |
|
||||
| wait_for | ``any`` | | Ensures that the step happens after the configured step or steps. This is a template who's results are not used, only awaited. |
|
||||
| touches_resources | `list(atom)` | | A list of resources touched by any custom logic in this step. This is used in the case that this step is run in a transaction. This is primarily only needed for `custom` steps. |
|
||||
| halt_if | ``any`` | | Halts the step by emitting an error (with an `Ash.Error.Flow.Halted`). Can use template variables. See the section on Halting for more. |
|
||||
| halt_reason | ``any`` | :halted | Configures the reason for the `halt_if` clause. |
|
||||
| description | `String.t` | | A description for the step. |
|
||||
| resource | ``any`` | | The resource to call the action on. |
|
||||
| action | ``any`` | | The action to call on the resource. |
|
||||
| api | ``any`` | | The api to use when calling the action. Defaults to the api set in the `flow` section. |
|
||||
| tenant | ``any`` | | A tenant to use for the operation. May be a template or a literal value. |
|
||||
| input | ``any`` | | A template for the input. |
|
||||
|
||||
|
||||
|
||||
## steps.destroy
|
||||
|
||||
Introspection Target: `Ash.Flow.Step.Destroy`
|
||||
|
||||
Declares a step that will call a destroy action on a resource.
|
||||
|
||||
|
||||
---
|
||||
|
||||
|
||||
|
||||
### Examples
|
||||
```
|
||||
destroy :destroy_post, MyApp.Post, :destroy
|
||||
|
||||
```
|
||||
|
||||
|
||||
### Reference
|
||||
| Name | Type | Default | Docs |
|
||||
| --- | --- | --- | --- |
|
||||
| record | ``any`` | | The record to be updated, can use template helpers, e.g `result(:step_name)`. |
|
||||
| name | `atom` | | The name of the step. Will be used when expressing dependencies, and step inputs. |
|
||||
| short_name | `String.t` | | Set a short name for the step. Will be used when building things like mermaid charts. |
|
||||
| wait_for | ``any`` | | Ensures that the step happens after the configured step or steps. This is a template who's results are not used, only awaited. |
|
||||
| touches_resources | `list(atom)` | | A list of resources touched by any custom logic in this step. This is used in the case that this step is run in a transaction. This is primarily only needed for `custom` steps. |
|
||||
| halt_if | ``any`` | | Halts the step by emitting an error (with an `Ash.Error.Flow.Halted`). Can use template variables. See the section on Halting for more. |
|
||||
| halt_reason | ``any`` | :halted | Configures the reason for the `halt_if` clause. |
|
||||
| description | `String.t` | | A description for the step. |
|
||||
| resource | ``any`` | | The resource to call the action on. |
|
||||
| action | ``any`` | | The action to call on the resource. |
|
||||
| api | ``any`` | | The api to use when calling the action. Defaults to the api set in the `flow` section. |
|
||||
| tenant | ``any`` | | A tenant to use for the operation. May be a template or a literal value. |
|
||||
| input | ``any`` | | A template for the input. |
|
||||
|
||||
|
||||
|
||||
## steps.validate
|
||||
|
||||
Introspection Target: `Ash.Flow.Step.Update`
|
||||
|
||||
Validates some input against an action.
|
||||
|
||||
|
||||
---
|
||||
|
||||
|
||||
|
||||
### Examples
|
||||
```
|
||||
validate :update_post, MyApp.Post, :update do
|
||||
record result(:get_post)
|
||||
only_keys [:name]
|
||||
end
|
||||
|
||||
```
|
||||
|
||||
|
||||
### Reference
|
||||
| Name | Type | Default | Docs |
|
||||
| --- | --- | --- | --- |
|
||||
| record | ``any`` | | The record to be created/updated/destroyed. If the value is `nil` and would be required by the action type, the step is skipped and `nil` is the result of the step. |
|
||||
| only_keys | `list(atom \| list(atom))` | | A list of keys or paths to keys that should be validated. Others will be ignored, and errors generated for other fields will be ignored. |
|
||||
| name | `atom` | | The name of the step. Will be used when expressing dependencies, and step inputs. |
|
||||
| short_name | `String.t` | | Set a short name for the step. Will be used when building things like mermaid charts. |
|
||||
| wait_for | ``any`` | | Ensures that the step happens after the configured step or steps. This is a template who's results are not used, only awaited. |
|
||||
| touches_resources | `list(atom)` | | A list of resources touched by any custom logic in this step. This is used in the case that this step is run in a transaction. This is primarily only needed for `custom` steps. |
|
||||
| halt_if | ``any`` | | Halts the step by emitting an error (with an `Ash.Error.Flow.Halted`). Can use template variables. See the section on Halting for more. |
|
||||
| halt_reason | ``any`` | :halted | Configures the reason for the `halt_if` clause. |
|
||||
| description | `String.t` | | A description for the step. |
|
||||
| resource | ``any`` | | The resource to call the action on. |
|
||||
| action | ``any`` | | The action to call on the resource. |
|
||||
| api | ``any`` | | The api to use when calling the action. Defaults to the api set in the `flow` section. |
|
||||
| tenant | ``any`` | | A tenant to use for the operation. May be a template or a literal value. |
|
||||
| input | ``any`` | | A template for the input. |
|
||||
|
||||
|
||||
|
||||
## steps.read
|
||||
|
||||
Introspection Target: `Ash.Flow.Step.Read`
|
||||
|
||||
Declares a step that will call a read action on a resource.
|
||||
|
||||
|
||||
---
|
||||
|
||||
|
||||
|
||||
### Examples
|
||||
```
|
||||
read :destroy_post, MyApp.Post, :destroy
|
||||
|
||||
```
|
||||
|
||||
|
||||
### Reference
|
||||
| Name | Type | Default | Docs |
|
||||
| --- | --- | --- | --- |
|
||||
| get? | `boolean` | false | Whether or not read action is expected to return a single result or `nil`. Set to `true` automatically if `get? true`. |
|
||||
| not_found_error? | `boolean` | true | Whether or not finding no record should result in a not found error |
|
||||
| name | `atom` | | The name of the step. Will be used when expressing dependencies, and step inputs. |
|
||||
| short_name | `String.t` | | Set a short name for the step. Will be used when building things like mermaid charts. |
|
||||
| wait_for | ``any`` | | Ensures that the step happens after the configured step or steps. This is a template who's results are not used, only awaited. |
|
||||
| touches_resources | `list(atom)` | | A list of resources touched by any custom logic in this step. This is used in the case that this step is run in a transaction. This is primarily only needed for `custom` steps. |
|
||||
| halt_if | ``any`` | | Halts the step by emitting an error (with an `Ash.Error.Flow.Halted`). Can use template variables. See the section on Halting for more. |
|
||||
| halt_reason | ``any`` | :halted | Configures the reason for the `halt_if` clause. |
|
||||
| description | `String.t` | | A description for the step. |
|
||||
| resource | ``any`` | | The resource to call the action on. |
|
||||
| action | ``any`` | | The action to call on the resource. |
|
||||
| api | ``any`` | | The api to use when calling the action. Defaults to the api set in the `flow` section. |
|
||||
| tenant | ``any`` | | A tenant to use for the operation. May be a template or a literal value. |
|
||||
| input | ``any`` | | A template for the input. |
|
||||
|
||||
|
||||
|
||||
## steps.run_flow
|
||||
|
||||
Introspection Target: `Ash.Flow.Step.RunFlow`
|
||||
|
||||
Runs another flow as part of the current flow.
|
||||
The return value of the step is the return value of the flow.
|
||||
|
||||
|
||||
---
|
||||
|
||||
|
||||
|
||||
### Examples
|
||||
```
|
||||
run_flow :get_org, GetOrgByName do
|
||||
input %{
|
||||
name: arg(:org_name)
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
|
||||
### Reference
|
||||
| Name | Type | Default | Docs |
|
||||
| --- | --- | --- | --- |
|
||||
| flow | `atom` | | The flow to run. |
|
||||
| input | ``any`` | | A template for the input. |
|
||||
| name | `atom` | | The name of the step. Will be used when expressing dependencies, and step inputs. |
|
||||
| short_name | `String.t` | | Set a short name for the step. Will be used when building things like mermaid charts. |
|
||||
| wait_for | ``any`` | | Ensures that the step happens after the configured step or steps. This is a template who's results are not used, only awaited. |
|
||||
| touches_resources | `list(atom)` | | A list of resources touched by any custom logic in this step. This is used in the case that this step is run in a transaction. This is primarily only needed for `custom` steps. |
|
||||
| halt_if | ``any`` | | Halts the step by emitting an error (with an `Ash.Error.Flow.Halted`). Can use template variables. See the section on Halting for more. |
|
||||
| halt_reason | ``any`` | :halted | Configures the reason for the `halt_if` clause. |
|
||||
| description | `String.t` | | A description for the step. |
|
||||
|
||||
|
||||
|
||||
## steps.custom
|
||||
|
||||
Introspection Target: `Ash.Flow.Step.Custom`
|
||||
|
||||
Runs a custom step module.
|
||||
|
||||
See `Ash.Flow.Step` for the necessary callbacks and more information.
|
||||
|
||||
|
||||
---
|
||||
|
||||
|
||||
|
||||
### Examples
|
||||
```
|
||||
custom :do_custom_thing, MyApp.DoCustomThing do
|
||||
input %{...}
|
||||
end
|
||||
|
||||
```
|
||||
|
||||
|
||||
```
|
||||
custom :do_custom_thing, {MyApp.DoCustomThing, opt1: :foo, opt2: :bar} do
|
||||
input %{...}
|
||||
end
|
||||
|
||||
```
|
||||
|
||||
|
||||
### Reference
|
||||
| Name | Type | Default | Docs |
|
||||
| --- | --- | --- | --- |
|
||||
| input | ``any`` | | A template for the input. |
|
||||
| custom | `(any, any -> any) \| module` | | The module that implements the step behaviour. Also accepts a 2 argument function that takes the input and the context. |
|
||||
| async? | `boolean` | false | Whether or not this step can be run outside of the current process. |
|
||||
| name | `atom` | | The name of the step. Will be used when expressing dependencies, and step inputs. |
|
||||
| short_name | `String.t` | | Set a short name for the step. Will be used when building things like mermaid charts. |
|
||||
| wait_for | ``any`` | | Ensures that the step happens after the configured step or steps. This is a template who's results are not used, only awaited. |
|
||||
| touches_resources | `list(atom)` | | A list of resources touched by any custom logic in this step. This is used in the case that this step is run in a transaction. This is primarily only needed for `custom` steps. |
|
||||
| halt_if | ``any`` | | Halts the step by emitting an error (with an `Ash.Error.Flow.Halted`). Can use template variables. See the section on Halting for more. |
|
||||
| halt_reason | ``any`` | :halted | Configures the reason for the `halt_if` clause. |
|
||||
| description | `String.t` | | A description for the step. |
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
110
documentation/dsls/DSL:-Ash.Notifier.PubSub.cheatmd
Normal file
110
documentation/dsls/DSL:-Ash.Notifier.PubSub.cheatmd
Normal file
|
@ -0,0 +1,110 @@
|
|||
# DSL: Ash.Notifier.PubSub
|
||||
|
||||
A pubsub notifier extension.
|
||||
|
||||
|
||||
## pub_sub
|
||||
A section for configuring how resource actions are published over pubsub
|
||||
|
||||
See the [PubSub](/documentation/topics/pub_sub.md) and [Notifiers](/documentation/topics/notifiers.md) guide for more.
|
||||
|
||||
|
||||
---
|
||||
|
||||
* [publish](#pub_sub-publish)
|
||||
* [publish_all](#pub_sub-publish_all)
|
||||
|
||||
### Examples
|
||||
```
|
||||
pub_sub do
|
||||
module MyEndpoint
|
||||
prefix "post"
|
||||
broadcast_type :phoenix_broadcast
|
||||
|
||||
publish :destroy, ["foo", :id]
|
||||
publish :update, ["bar", :name] event: "name_change"
|
||||
publish_all :create, "created"
|
||||
end
|
||||
|
||||
```
|
||||
|
||||
|
||||
### Reference
|
||||
| Name | Type | Default | Docs |
|
||||
| --- | --- | --- | --- |
|
||||
| module | `atom` | | The module to call `broadcast/3` on e.g module.broadcast(topic, event, message). |
|
||||
| prefix | `String.t` | | A prefix for all pubsub messages, e.g `users`. A message with `created` would be published as `users:created` |
|
||||
| broadcast_type | `:notification \| :phoenix_broadcast \| :broadcast` | :notification | What shape the event payloads will be in. See |
|
||||
| name | `atom` | | A named pub sub to pass as the first argument to broadcast. |
|
||||
|
||||
|
||||
|
||||
## pub_sub.publish
|
||||
|
||||
Introspection Target: `Ash.Notifier.PubSub.Publication`
|
||||
|
||||
Configure a given action to publish its results over a given topic.
|
||||
|
||||
See the [PubSub](/documentation/topics/pub_sub.md) and [Notifiers](/documentation/topics/notifiers.md) guides for more.
|
||||
|
||||
|
||||
---
|
||||
|
||||
|
||||
|
||||
### Examples
|
||||
```
|
||||
publish :create, "created"
|
||||
```
|
||||
|
||||
|
||||
```
|
||||
publish :assign, "assigned"
|
||||
|
||||
```
|
||||
|
||||
|
||||
### Reference
|
||||
| Name | Type | Docs |
|
||||
| --- | --- | --- |
|
||||
| action | `atom` | The name of the action that should be published |
|
||||
| topic | ``any`` | The topic to publish |
|
||||
| event | `String.t` | The name of the event to publish. Defaults to the action name |
|
||||
| dispatcher | `atom` | The module to use as a dispatcher. If none is set, the pubsub module provided is used. |
|
||||
|
||||
|
||||
|
||||
## pub_sub.publish_all
|
||||
|
||||
Introspection Target: `Ash.Notifier.PubSub.Publication`
|
||||
|
||||
Works just like `publish`, except that it takes a type
|
||||
and publishes all actions of that type
|
||||
|
||||
See the [PubSub](/documentation/topics/pub_sub.md) and [Notifiers](/documentation/topics/notifiers.md) guides for more.
|
||||
|
||||
|
||||
---
|
||||
|
||||
|
||||
|
||||
### Examples
|
||||
```
|
||||
publish_all :create, "created"
|
||||
```
|
||||
|
||||
|
||||
### Reference
|
||||
| Name | Type | Docs |
|
||||
| --- | --- | --- |
|
||||
| type | `:create \| :update \| :destroy` | Publish on all actions of a given type |
|
||||
| action | `atom` | The name of the action that should be published |
|
||||
| topic | ``any`` | The topic to publish |
|
||||
| event | `String.t` | The name of the event to publish. Defaults to the action name |
|
||||
| dispatcher | `atom` | The module to use as a dispatcher. If none is set, the pubsub module provided is used. |
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
725
documentation/dsls/DSL:-Ash.Policy.Authorizer.cheatmd
Normal file
725
documentation/dsls/DSL:-Ash.Policy.Authorizer.cheatmd
Normal file
|
@ -0,0 +1,725 @@
|
|||
# DSL: Ash.Policy.Authorizer
|
||||
|
||||
An authorization extension for ash resources.
|
||||
|
||||
To add this extension to a resource, add it to the list of `authorizers` like so:
|
||||
|
||||
```elixir
|
||||
use Ash.Resource,
|
||||
...,
|
||||
authorizers: [
|
||||
Ash.Policy.Authorizer
|
||||
]
|
||||
```
|
||||
|
||||
A resource can be given a set of policies, which are enforced on each call to a resource action.
|
||||
|
||||
For reads, policies can be configured to filter out data that the actor shouldn't see, as opposed to
|
||||
resulting in a forbidden error.
|
||||
|
||||
See the [policies guide](/documentation/topics/policies.md) for practical examples.
|
||||
|
||||
Policies are solved/managed via a boolean satisfiability solver. To read more about boolean satisfiability,
|
||||
see this page: https://en.wikipedia.org/wiki/Boolean_satisfiability_problem. At the end of
|
||||
the day, however, it is not necessary to understand exactly how Ash takes your
|
||||
authorization requirements and determines if a request is allowed. The
|
||||
important thing to understand is that Ash may or may not run any/all of your
|
||||
authorization rules as they may be deemed unnecessary. As such, authorization
|
||||
checks should have no side effects. Ideally, the checks built-in to ash should
|
||||
cover the bulk of your needs.
|
||||
|
||||
|
||||
## policies
|
||||
A section for declaring authorization policies.
|
||||
|
||||
Each policy that applies must pass independently in order for the
|
||||
request to be authorized.
|
||||
|
||||
See the [policies guide](/documentation/topics/policies.md) for more.
|
||||
|
||||
|
||||
---
|
||||
|
||||
* [policy](#policies-policy)
|
||||
* authorize_if
|
||||
* forbid_if
|
||||
* authorize_unless
|
||||
* forbid_unless
|
||||
* [bypass](#policies-bypass)
|
||||
* authorize_if
|
||||
* forbid_if
|
||||
* authorize_unless
|
||||
* forbid_unless
|
||||
|
||||
### Examples
|
||||
```
|
||||
policies do
|
||||
# Anything you can use in a condition, you can use in a check, and vice-versa
|
||||
# This policy applies if the actor is a super_user
|
||||
# Additionally, this policy is declared as a `bypass`. That means that this check is allowed to fail without
|
||||
# failing the whole request, and that if this check *passes*, the entire request passes.
|
||||
bypass actor_attribute_equals(:super_user, true) do
|
||||
authorize_if always()
|
||||
end
|
||||
|
||||
# This will likely be a common occurrence. Specifically, policies that apply to all read actions
|
||||
policy action_type(:read) do
|
||||
# unless the actor is an active user, forbid their request
|
||||
forbid_unless actor_attribute_equals(:active, true)
|
||||
# if the record is marked as public, authorize the request
|
||||
authorize_if attribute(:public, true)
|
||||
# if the actor is related to the data via that data's `owner` relationship, authorize the request
|
||||
authorize_if relates_to_actor_via(:owner)
|
||||
end
|
||||
end
|
||||
|
||||
```
|
||||
|
||||
|
||||
### Reference
|
||||
| Name | Type | Default | Docs |
|
||||
| --- | --- | --- | --- |
|
||||
| default_access_type | `:strict \| :filter \| :runtime` | :filter | The default access type of policies for this resource. |
|
||||
|
||||
|
||||
|
||||
## policies.policy
|
||||
|
||||
Introspection Target: `Ash.Policy.Policy`
|
||||
|
||||
A policy has a name, a condition, and a list of checks.
|
||||
|
||||
Checks apply logically in the order they are specified, from top to bottom.
|
||||
If no check explicitly authorizes the request, then the request is forbidden.
|
||||
This means that, if you want to "blacklist" instead of "whitelist", you likely
|
||||
want to add an `authorize_if always()` at the bottom of your policy, like so:
|
||||
|
||||
```elixir
|
||||
policy action_type(:read) do
|
||||
forbid_if not_logged_in()
|
||||
forbid_if user_is_denylisted()
|
||||
forbid_if user_is_in_denylisted_group()
|
||||
|
||||
authorize_if always()
|
||||
end
|
||||
```
|
||||
|
||||
If the policy should always run, use the `always()` check, like so:
|
||||
|
||||
```elixir
|
||||
policy always() do
|
||||
...
|
||||
end
|
||||
```
|
||||
|
||||
See the [policies guide](/documentation/topics/policies.md) for more.
|
||||
|
||||
|
||||
---
|
||||
|
||||
* [authorize_if](#policies-policy-authorize_if)
|
||||
* [forbid_if](#policies-policy-forbid_if)
|
||||
* [authorize_unless](#policies-policy-authorize_unless)
|
||||
* [forbid_unless](#policies-policy-forbid_unless)
|
||||
|
||||
### Examples
|
||||
|
||||
|
||||
### Reference
|
||||
| Name | Type | Docs |
|
||||
| --- | --- | --- |
|
||||
| description | `String.t` | A description for the policy, used when explaining authorization results |
|
||||
| access_type | `:strict \| :filter \| :runtime` | What portion of the checks inside the policy are allowed to run. See the guide for more. |
|
||||
| condition | ``any`` | A check or list of checks that must be true in order for this policy to apply. |
|
||||
|
||||
|
||||
## policies.policy.authorize_if
|
||||
|
||||
Introspection Target: `Ash.Policy.Check`
|
||||
|
||||
If the check is true, the request is authorized, otherwise run remaining checks.
|
||||
|
||||
---
|
||||
|
||||
|
||||
|
||||
### Examples
|
||||
```
|
||||
authorize_if logged_in()
|
||||
```
|
||||
|
||||
|
||||
```
|
||||
authorize_if actor_attribute_matches_record(:group, :group)
|
||||
```
|
||||
|
||||
|
||||
### Reference
|
||||
| Name | Type | Docs |
|
||||
| --- | --- | --- |
|
||||
| check | ``any`` | The check to run. See `Ash.Policy.Check` for more. |
|
||||
| name | `String.t` | A short name or description for the check, used when explaining authorization results |
|
||||
|
||||
|
||||
|
||||
## policies.policy.forbid_if
|
||||
|
||||
Introspection Target: `Ash.Policy.Check`
|
||||
|
||||
If the check is true, the request is forbidden, otherwise run remaining checks.
|
||||
|
||||
---
|
||||
|
||||
|
||||
|
||||
### Examples
|
||||
```
|
||||
forbid_if not_logged_in()
|
||||
```
|
||||
|
||||
|
||||
```
|
||||
forbid_if actor_attribute_matches_record(:group, :blacklisted_groups)
|
||||
```
|
||||
|
||||
|
||||
### Reference
|
||||
| Name | Type | Docs |
|
||||
| --- | --- | --- |
|
||||
| check | ``any`` | The check to run. See `Ash.Policy.Check` for more. |
|
||||
| name | `String.t` | A short name or description for the check, used when explaining authorization results |
|
||||
|
||||
|
||||
|
||||
## policies.policy.authorize_unless
|
||||
|
||||
Introspection Target: `Ash.Policy.Check`
|
||||
|
||||
If the check is false, the request is authorized, otherwise run remaining checks.
|
||||
|
||||
---
|
||||
|
||||
|
||||
|
||||
### Examples
|
||||
```
|
||||
authorize_unless not_logged_in()
|
||||
```
|
||||
|
||||
|
||||
```
|
||||
authorize_unless actor_attribute_matches_record(:group, :blacklisted_groups)
|
||||
```
|
||||
|
||||
|
||||
### Reference
|
||||
| Name | Type | Docs |
|
||||
| --- | --- | --- |
|
||||
| check | ``any`` | The check to run. See `Ash.Policy.Check` for more. |
|
||||
| name | `String.t` | A short name or description for the check, used when explaining authorization results |
|
||||
|
||||
|
||||
|
||||
## policies.policy.forbid_unless
|
||||
|
||||
Introspection Target: `Ash.Policy.Check`
|
||||
|
||||
If the check is true, the request is forbidden, otherwise run remaining checks.
|
||||
|
||||
---
|
||||
|
||||
|
||||
|
||||
### Examples
|
||||
```
|
||||
forbid_unless logged_in()
|
||||
```
|
||||
|
||||
|
||||
```
|
||||
forbid_unless actor_attribute_matches_record(:group, :group)
|
||||
```
|
||||
|
||||
|
||||
### Reference
|
||||
| Name | Type | Docs |
|
||||
| --- | --- | --- |
|
||||
| check | ``any`` | The check to run. See `Ash.Policy.Check` for more. |
|
||||
| name | `String.t` | A short name or description for the check, used when explaining authorization results |
|
||||
|
||||
|
||||
|
||||
|
||||
## policies.bypass
|
||||
|
||||
Introspection Target: `Ash.Policy.Policy`
|
||||
|
||||
A policy that, if passed, will skip all following policies. If failed, authorization moves on to the next policy
|
||||
|
||||
---
|
||||
|
||||
* [authorize_if](#policies-bypass-authorize_if)
|
||||
* [forbid_if](#policies-bypass-forbid_if)
|
||||
* [authorize_unless](#policies-bypass-authorize_unless)
|
||||
* [forbid_unless](#policies-bypass-forbid_unless)
|
||||
|
||||
### Examples
|
||||
|
||||
|
||||
### Reference
|
||||
| Name | Type | Docs |
|
||||
| --- | --- | --- |
|
||||
| description | `String.t` | A description for the policy, used when explaining authorization results |
|
||||
| access_type | `:strict \| :filter \| :runtime` | What portion of the checks inside the policy are allowed to run. See the guide for more. |
|
||||
| condition | ``any`` | A check or list of checks that must be true in order for this policy to apply. |
|
||||
|
||||
|
||||
## policies.bypass.authorize_if
|
||||
|
||||
Introspection Target: `Ash.Policy.Check`
|
||||
|
||||
If the check is true, the request is authorized, otherwise run remaining checks.
|
||||
|
||||
---
|
||||
|
||||
|
||||
|
||||
### Examples
|
||||
```
|
||||
authorize_if logged_in()
|
||||
```
|
||||
|
||||
|
||||
```
|
||||
authorize_if actor_attribute_matches_record(:group, :group)
|
||||
```
|
||||
|
||||
|
||||
### Reference
|
||||
| Name | Type | Docs |
|
||||
| --- | --- | --- |
|
||||
| check | ``any`` | The check to run. See `Ash.Policy.Check` for more. |
|
||||
| name | `String.t` | A short name or description for the check, used when explaining authorization results |
|
||||
|
||||
|
||||
|
||||
## policies.bypass.forbid_if
|
||||
|
||||
Introspection Target: `Ash.Policy.Check`
|
||||
|
||||
If the check is true, the request is forbidden, otherwise run remaining checks.
|
||||
|
||||
---
|
||||
|
||||
|
||||
|
||||
### Examples
|
||||
```
|
||||
forbid_if not_logged_in()
|
||||
```
|
||||
|
||||
|
||||
```
|
||||
forbid_if actor_attribute_matches_record(:group, :blacklisted_groups)
|
||||
```
|
||||
|
||||
|
||||
### Reference
|
||||
| Name | Type | Docs |
|
||||
| --- | --- | --- |
|
||||
| check | ``any`` | The check to run. See `Ash.Policy.Check` for more. |
|
||||
| name | `String.t` | A short name or description for the check, used when explaining authorization results |
|
||||
|
||||
|
||||
|
||||
## policies.bypass.authorize_unless
|
||||
|
||||
Introspection Target: `Ash.Policy.Check`
|
||||
|
||||
If the check is false, the request is authorized, otherwise run remaining checks.
|
||||
|
||||
---
|
||||
|
||||
|
||||
|
||||
### Examples
|
||||
```
|
||||
authorize_unless not_logged_in()
|
||||
```
|
||||
|
||||
|
||||
```
|
||||
authorize_unless actor_attribute_matches_record(:group, :blacklisted_groups)
|
||||
```
|
||||
|
||||
|
||||
### Reference
|
||||
| Name | Type | Docs |
|
||||
| --- | --- | --- |
|
||||
| check | ``any`` | The check to run. See `Ash.Policy.Check` for more. |
|
||||
| name | `String.t` | A short name or description for the check, used when explaining authorization results |
|
||||
|
||||
|
||||
|
||||
## policies.bypass.forbid_unless
|
||||
|
||||
Introspection Target: `Ash.Policy.Check`
|
||||
|
||||
If the check is true, the request is forbidden, otherwise run remaining checks.
|
||||
|
||||
---
|
||||
|
||||
|
||||
|
||||
### Examples
|
||||
```
|
||||
forbid_unless logged_in()
|
||||
```
|
||||
|
||||
|
||||
```
|
||||
forbid_unless actor_attribute_matches_record(:group, :group)
|
||||
```
|
||||
|
||||
|
||||
### Reference
|
||||
| Name | Type | Docs |
|
||||
| --- | --- | --- |
|
||||
| check | ``any`` | The check to run. See `Ash.Policy.Check` for more. |
|
||||
| name | `String.t` | A short name or description for the check, used when explaining authorization results |
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## field_policies
|
||||
|
||||
---
|
||||
|
||||
* [field_policy_bypass](#field_policies-field_policy_bypass)
|
||||
* authorize_if
|
||||
* forbid_if
|
||||
* authorize_unless
|
||||
* forbid_unless
|
||||
* [field_policy](#field_policies-field_policy)
|
||||
* authorize_if
|
||||
* forbid_if
|
||||
* authorize_unless
|
||||
* forbid_unless
|
||||
|
||||
### Examples
|
||||
```
|
||||
field_policies do
|
||||
field_policy :admin_only_field do
|
||||
authorize_if actor_attribute_equals(:admin, true)
|
||||
end
|
||||
end
|
||||
|
||||
```
|
||||
|
||||
|
||||
```
|
||||
# Example of denylist style
|
||||
field_policies do
|
||||
field_policy [:sensitive, :fields] do
|
||||
authorize_if actor_attribute_equals(:admin, true)
|
||||
end
|
||||
|
||||
field_policy :* do
|
||||
authorize_if always()
|
||||
end
|
||||
end
|
||||
|
||||
```
|
||||
|
||||
|
||||
|
||||
## field_policies.field_policy_bypass
|
||||
|
||||
Introspection Target: `Ash.Policy.FieldPolicy`
|
||||
|
||||
A field policy that, if passed, will skip all following field policies for that field or fields. If failed, field authorization moves on to the next policy
|
||||
|
||||
---
|
||||
|
||||
* [authorize_if](#field_policies-field_policy_bypass-authorize_if)
|
||||
* [forbid_if](#field_policies-field_policy_bypass-forbid_if)
|
||||
* [authorize_unless](#field_policies-field_policy_bypass-authorize_unless)
|
||||
* [forbid_unless](#field_policies-field_policy_bypass-forbid_unless)
|
||||
|
||||
### Examples
|
||||
|
||||
|
||||
### Reference
|
||||
| Name | Type | Docs |
|
||||
| --- | --- | --- |
|
||||
| description | `String.t` | A description for the policy, used when explaining authorization results |
|
||||
| fields | `list(atom) \| atom` | The field or fields that the policy applies to. |
|
||||
| condition | ``any`` | A check or list of checks that must be true in order for this field policy to apply. If not specified, it always applies. |
|
||||
|
||||
|
||||
## field_policies.field_policy_bypass.authorize_if
|
||||
|
||||
Introspection Target: `Ash.Policy.Check`
|
||||
|
||||
If the check is true, the request is authorized, otherwise run remaining checks.
|
||||
|
||||
---
|
||||
|
||||
|
||||
|
||||
### Examples
|
||||
```
|
||||
authorize_if logged_in()
|
||||
```
|
||||
|
||||
|
||||
```
|
||||
authorize_if actor_attribute_matches_record(:group, :group)
|
||||
```
|
||||
|
||||
|
||||
### Reference
|
||||
| Name | Type | Docs |
|
||||
| --- | --- | --- |
|
||||
| check | ``any`` | The check to run. See `Ash.Policy.Check` for more. |
|
||||
| name | `String.t` | A short name or description for the check, used when explaining authorization results |
|
||||
|
||||
|
||||
|
||||
## field_policies.field_policy_bypass.forbid_if
|
||||
|
||||
Introspection Target: `Ash.Policy.Check`
|
||||
|
||||
If the check is true, the request is forbidden, otherwise run remaining checks.
|
||||
|
||||
---
|
||||
|
||||
|
||||
|
||||
### Examples
|
||||
```
|
||||
forbid_if not_logged_in()
|
||||
```
|
||||
|
||||
|
||||
```
|
||||
forbid_if actor_attribute_matches_record(:group, :blacklisted_groups)
|
||||
```
|
||||
|
||||
|
||||
### Reference
|
||||
| Name | Type | Docs |
|
||||
| --- | --- | --- |
|
||||
| check | ``any`` | The check to run. See `Ash.Policy.Check` for more. |
|
||||
| name | `String.t` | A short name or description for the check, used when explaining authorization results |
|
||||
|
||||
|
||||
|
||||
## field_policies.field_policy_bypass.authorize_unless
|
||||
|
||||
Introspection Target: `Ash.Policy.Check`
|
||||
|
||||
If the check is false, the request is authorized, otherwise run remaining checks.
|
||||
|
||||
---
|
||||
|
||||
|
||||
|
||||
### Examples
|
||||
```
|
||||
authorize_unless not_logged_in()
|
||||
```
|
||||
|
||||
|
||||
```
|
||||
authorize_unless actor_attribute_matches_record(:group, :blacklisted_groups)
|
||||
```
|
||||
|
||||
|
||||
### Reference
|
||||
| Name | Type | Docs |
|
||||
| --- | --- | --- |
|
||||
| check | ``any`` | The check to run. See `Ash.Policy.Check` for more. |
|
||||
| name | `String.t` | A short name or description for the check, used when explaining authorization results |
|
||||
|
||||
|
||||
|
||||
## field_policies.field_policy_bypass.forbid_unless
|
||||
|
||||
Introspection Target: `Ash.Policy.Check`
|
||||
|
||||
If the check is true, the request is forbidden, otherwise run remaining checks.
|
||||
|
||||
---
|
||||
|
||||
|
||||
|
||||
### Examples
|
||||
```
|
||||
forbid_unless logged_in()
|
||||
```
|
||||
|
||||
|
||||
```
|
||||
forbid_unless actor_attribute_matches_record(:group, :group)
|
||||
```
|
||||
|
||||
|
||||
### Reference
|
||||
| Name | Type | Docs |
|
||||
| --- | --- | --- |
|
||||
| check | ``any`` | The check to run. See `Ash.Policy.Check` for more. |
|
||||
| name | `String.t` | A short name or description for the check, used when explaining authorization results |
|
||||
|
||||
|
||||
|
||||
|
||||
## field_policies.field_policy
|
||||
|
||||
Introspection Target: `Ash.Policy.FieldPolicy`
|
||||
|
||||
Field policies behave similarly to policies. See `d:Ash.Policy.Authorizer.field_policies`
|
||||
for more.
|
||||
|
||||
|
||||
---
|
||||
|
||||
* [authorize_if](#field_policies-field_policy-authorize_if)
|
||||
* [forbid_if](#field_policies-field_policy-forbid_if)
|
||||
* [authorize_unless](#field_policies-field_policy-authorize_unless)
|
||||
* [forbid_unless](#field_policies-field_policy-forbid_unless)
|
||||
|
||||
### Examples
|
||||
|
||||
|
||||
### Reference
|
||||
| Name | Type | Docs |
|
||||
| --- | --- | --- |
|
||||
| description | `String.t` | A description for the policy, used when explaining authorization results |
|
||||
| fields | `list(atom) \| atom` | The field or fields that the policy applies to. |
|
||||
| condition | ``any`` | A check or list of checks that must be true in order for this field policy to apply. If not specified, it always applies. |
|
||||
|
||||
|
||||
## field_policies.field_policy.authorize_if
|
||||
|
||||
Introspection Target: `Ash.Policy.Check`
|
||||
|
||||
If the check is true, the request is authorized, otherwise run remaining checks.
|
||||
|
||||
---
|
||||
|
||||
|
||||
|
||||
### Examples
|
||||
```
|
||||
authorize_if logged_in()
|
||||
```
|
||||
|
||||
|
||||
```
|
||||
authorize_if actor_attribute_matches_record(:group, :group)
|
||||
```
|
||||
|
||||
|
||||
### Reference
|
||||
| Name | Type | Docs |
|
||||
| --- | --- | --- |
|
||||
| check | ``any`` | The check to run. See `Ash.Policy.Check` for more. |
|
||||
| name | `String.t` | A short name or description for the check, used when explaining authorization results |
|
||||
|
||||
|
||||
|
||||
## field_policies.field_policy.forbid_if
|
||||
|
||||
Introspection Target: `Ash.Policy.Check`
|
||||
|
||||
If the check is true, the request is forbidden, otherwise run remaining checks.
|
||||
|
||||
---
|
||||
|
||||
|
||||
|
||||
### Examples
|
||||
```
|
||||
forbid_if not_logged_in()
|
||||
```
|
||||
|
||||
|
||||
```
|
||||
forbid_if actor_attribute_matches_record(:group, :blacklisted_groups)
|
||||
```
|
||||
|
||||
|
||||
### Reference
|
||||
| Name | Type | Docs |
|
||||
| --- | --- | --- |
|
||||
| check | ``any`` | The check to run. See `Ash.Policy.Check` for more. |
|
||||
| name | `String.t` | A short name or description for the check, used when explaining authorization results |
|
||||
|
||||
|
||||
|
||||
## field_policies.field_policy.authorize_unless
|
||||
|
||||
Introspection Target: `Ash.Policy.Check`
|
||||
|
||||
If the check is false, the request is authorized, otherwise run remaining checks.
|
||||
|
||||
---
|
||||
|
||||
|
||||
|
||||
### Examples
|
||||
```
|
||||
authorize_unless not_logged_in()
|
||||
```
|
||||
|
||||
|
||||
```
|
||||
authorize_unless actor_attribute_matches_record(:group, :blacklisted_groups)
|
||||
```
|
||||
|
||||
|
||||
### Reference
|
||||
| Name | Type | Docs |
|
||||
| --- | --- | --- |
|
||||
| check | ``any`` | The check to run. See `Ash.Policy.Check` for more. |
|
||||
| name | `String.t` | A short name or description for the check, used when explaining authorization results |
|
||||
|
||||
|
||||
|
||||
## field_policies.field_policy.forbid_unless
|
||||
|
||||
Introspection Target: `Ash.Policy.Check`
|
||||
|
||||
If the check is true, the request is forbidden, otherwise run remaining checks.
|
||||
|
||||
---
|
||||
|
||||
|
||||
|
||||
### Examples
|
||||
```
|
||||
forbid_unless logged_in()
|
||||
```
|
||||
|
||||
|
||||
```
|
||||
forbid_unless actor_attribute_matches_record(:group, :group)
|
||||
```
|
||||
|
||||
|
||||
### Reference
|
||||
| Name | Type | Docs |
|
||||
| --- | --- | --- |
|
||||
| check | ``any`` | The check to run. See `Ash.Policy.Check` for more. |
|
||||
| name | `String.t` | A short name or description for the check, used when explaining authorization results |
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
58
documentation/dsls/DSL:-Ash.Registry.cheatmd
Normal file
58
documentation/dsls/DSL:-Ash.Registry.cheatmd
Normal file
|
@ -0,0 +1,58 @@
|
|||
# DSL: Ash.Registry.Dsl
|
||||
|
||||
A small DSL for declaring an `Ash.Registry`. Not generally necessary any longer.
|
||||
|
||||
`Ash.Registry` can be used generically, but the main way it is used in Ash is to provide a compile-time registry for an Ash Api.
|
||||
|
||||
|
||||
## entries
|
||||
List the entries present in this registry
|
||||
|
||||
---
|
||||
|
||||
* [entry](#entries-entry)
|
||||
|
||||
### Examples
|
||||
```
|
||||
entries do
|
||||
entry MyApp.User
|
||||
entry MyApp.Post
|
||||
entry MyApp.Comment
|
||||
end
|
||||
|
||||
```
|
||||
|
||||
|
||||
### Reference
|
||||
| Name | Type | Default | Docs |
|
||||
| --- | --- | --- | --- |
|
||||
| warn_on_empty? | `boolean` | true | Set to `false` to ignore warnings about an empty registry |
|
||||
|
||||
|
||||
|
||||
## entries.entry
|
||||
|
||||
Introspection Target: `Ash.Registry.Entry`
|
||||
|
||||
A reference to an ash module (typically a resource)
|
||||
|
||||
---
|
||||
|
||||
|
||||
|
||||
### Examples
|
||||
```
|
||||
entry MyApp.User
|
||||
```
|
||||
|
||||
|
||||
### Reference
|
||||
| Name | Type | Docs |
|
||||
| --- | --- | --- |
|
||||
| entry | `atom` | The referenced module |
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
2291
documentation/dsls/DSL:-Ash.Resource.cheatmd
Normal file
2291
documentation/dsls/DSL:-Ash.Resource.cheatmd
Normal file
File diff suppressed because it is too large
Load diff
|
@ -73,7 +73,7 @@ calculations do
|
|||
end
|
||||
```
|
||||
|
||||
See the documentation for the calculations section in `Ash.Resource.Dsl` and the `Ash.Calculation` docs for more information.
|
||||
See the documentation for the calculations section in [Resource DSL docs](dsl-ash-resource.html#calculations) and the `Ash.Calculation` docs for more information.
|
||||
|
||||
The calculations declared on a resource allow for declaring a set of named calculations that can be used by extensions.
|
||||
They can also be loaded in the query using `Ash.Query.load/2`, or after the fact using `c:Ash.Api.load/3`. Calculations declared on the resource will be keys in the resource's struct.
|
||||
|
|
|
@ -89,3 +89,16 @@ User.full_name(user)
|
|||
```
|
||||
|
||||
This allows for running calculations without an instance of a resource, i.e `Api.load(user, :full_name)`
|
||||
|
||||
|
||||
By default, configured args will be provided for any matching named reference *or* argument. This is normally fine, but in the case that you have an argument and a reference with the same name, you can specify it by supplying `{:arg, :name}` and `{:ref, :name}`. For example:
|
||||
|
||||
```elixir
|
||||
define_calculation :id_matches, args: [{:arg, :id}, {:ref, :id}]
|
||||
```
|
||||
|
||||
To make arguments optional, wrap them in `{:optional, ..}`, for example:
|
||||
|
||||
```elixir
|
||||
define_calculation :id_matches, args: [{:arg, :id}, {:optional, {:ref, :id}}]
|
||||
```
|
||||
|
|
|
@ -118,7 +118,7 @@ The central concept in Ash, a resource is a domain model object in your system,
|
|||
|
||||
It is not a strict requirement that resources contain data - they can be used purely to create a standard interface for performing tasks - but in practice, most resources will be used to manage data.
|
||||
|
||||
See `Ash.Resource.Dsl` for more information.
|
||||
See the [Resource DSL docs](dsl-ash-resource.html) for DSL documentation.
|
||||
|
||||
## Tenant
|
||||
|
||||
|
|
|
@ -73,5 +73,18 @@ Would produce the following messages, given a `team_id` of 1, a `tenant` of `org
|
|||
Phoenix expects a specific shape of data to be broadcasted, and since it is so often used with Ash, instead of making you define your own notifier that creates the `%Phoenix.Socket.Broadcast` struct and publishes it, Ash has an option to do that automatically, via
|
||||
|
||||
```elixir
|
||||
broadcast_type: :phoenix_broadcast
|
||||
broadcast_type :phoenix_broadcast
|
||||
```
|
||||
|
||||
## Named Pubsub modules
|
||||
|
||||
If you are using a phoenix `Endpoint` module for pubsub then this is unnecessary. If you want to use a custom pub sub started with something like `{Phoenix.PubSub, name: MyName}`, then you can provide `MyName` to
|
||||
here.
|
||||
|
||||
## Broadcast Types
|
||||
|
||||
Configured with `broadcast_type`.
|
||||
|
||||
- `:notification` just sends the notification
|
||||
- `:phoenix_broadcast` sends a `%Phoenix.Socket.Broadcast{}` (see above)
|
||||
- `:broadcast` sends `%{topic: (topic), event: (event), notification: (notification)}`
|
||||
|
|
|
@ -271,3 +271,20 @@ followers =
|
|||
# Will load followers and followers of those followers
|
||||
YourApi.load(users, followers: followers)
|
||||
```
|
||||
|
||||
## no_attributes? true
|
||||
|
||||
This can be very useful when combined with multitenancy. Specifically, if you have a tenant resource like `Organization`,
|
||||
you can use `no_attributes?` to do things like `has_many :employees, Employee, no_attributes?: true`, which lets you avoid having an
|
||||
unnecessary `organization_id` field on `Employee`. The same works in reverse: `has_one :organization, Organization, no_attributes?: true`
|
||||
allows relating the employee to their organization.
|
||||
|
||||
Some important caveats here:
|
||||
|
||||
1. You can still manage relationships from one to the other, but "relate" and "unrelate"
|
||||
will have no effect, because there are no fields to change.
|
||||
|
||||
2. Loading the relationship on a list of resources will not behave as expected in all circumstances involving multitenancy. For example,
|
||||
if you get a list of `Organization` and then try to load `employees`, you would need to set a single tenant on the load query, meaning
|
||||
you'll get all organizations back with the set of employees from one tenant. This could eventually be solved, but for now it is considered an
|
||||
edge case.
|
||||
|
|
|
@ -4,6 +4,10 @@
|
|||
|
||||
A great thing to do early on is to be explicit about your security configuration. To that end, once you've read this guide, we highly recommend that you place the configuration found at the bottom of your guide into your api modules, even if you are simply setting them to their default values. Especially the `authorize` option.
|
||||
|
||||
## Sensitive Attributes
|
||||
|
||||
Using `sensitive? true` will cause the argument to be `** Redacted **` from the resource when logging or inspecting. In filter statements, any value used in the same expression as a sensitive attribute will also be redacted. For example, you might see: `email == "** Redacted **"` in a filter statement if `email` is marked as sensitive.
|
||||
|
||||
## Authorization
|
||||
|
||||
Authorization in Ash is done via authorizers. Generally, you won't need to create your own authorizer, as the builtin policy authorizer `Ash.Policy.Authorizer` should work well for any use case. Authorization is performed with a given actor and a query or changeset.
|
||||
|
|
|
@ -26,6 +26,7 @@ In this guide we will:
|
|||
|
||||
- [Install Elixir](https://elixir-lang.org/install.html)
|
||||
- [Philosophy Guide](/documentation/tutorials/philosophy.md)
|
||||
- [Using Hexdocs](/documentation/tutorials/using-hexdocs.md)
|
||||
|
||||
## Requirements
|
||||
|
||||
|
|
37
documentation/tutorials/using-hexdocs.md
Normal file
37
documentation/tutorials/using-hexdocs.md
Normal file
|
@ -0,0 +1,37 @@
|
|||
# Using Hexdocs
|
||||
|
||||
Ash is split across various packages. Each package has its own documentation. However, there is a global documentation search available at https://ash-hq.org. Do use it, use `Ctrl-K` or `Cmd-K` on that site.
|
||||
|
||||
## Packages
|
||||
|
||||
- [Ash](https://hexdocs.pm/ash): The core framework, providing all the features and goodies that power and enable the rest of the ecosystem.
|
||||
- [AshPostgres](https://hexdocs.pm/ash_postgres): A PostgreSQL data layer for Ash resources, allowing for rich query capabilities and seamless persistence.
|
||||
- [AshPhoenix](https://hexdocs.pm/ash_phoenix): Utilities for using Ash resources with Phoenix Framework, from building forms to running queries in sockets & LiveViews.
|
||||
- [AshGraphql](https://hexdocs.pm/ash_graphql): A GraphQL extension that allows you to build a rich and customizable GraphQL API with minimal configuration required.
|
||||
- [AshJsonApi](https://hexdocs.pm/ash_json_api): A JSON:API extension that allows you to effortlessly create a JSON:API spec compliant API.
|
||||
- [AshAuthentication](https://hexdocs.pm/ash_authentication): Provides drop-in support for user authentication with various strategies and tons of customizability.
|
||||
- [AshAuthenticationPhoenix](https://hexdocs.pm/ash_authentication_phoenix): Phoenix helpers and UI components in support of AshAuthentication.
|
||||
- [AshStateMachine](https://hexdocs.pm/ash_state_machine): An Ash.Resource extension for building finite state machines.
|
||||
- [AshCsv](https://hexdocs.pm/ash_csv): A CSV data layer allowing resources to be queried from and persisted in a CSV file.
|
||||
- [AshDoubleEntry](https://hexdocs.pm/ash_double_entry): A customizable double entry bookkeeping system backed by Ash resources.
|
||||
- [AshArchival](https://hexdocs.pm/ash_archival): A light-weight resource extension that modifies resources to simulate deletion by setting an `archived_at` attribute.
|
||||
- [Reactor](https://hexdocs.pm/reactor): Reactor is a dynamic, concurrent, dependency resolving saga orchestrator.
|
||||
- [Spark](https://hexdocs.pm/spark): The core DSL and extension tooling, allowing for powerful, extensible DSLs with minimal effort.
|
||||
|
||||
|
||||
|
||||
## DSL documentations
|
||||
Some helpful tips on using Hex Docs. DSLs are each documented in their own area. Find them in the bottom of the sidebar on the left.
|
||||
|
||||
### Searching
|
||||
|
||||
#### In the sidebar
|
||||
|
||||
When searching for a dsl, prefix your search with `DSL: `. If you know the path
|
||||
to the DSL you are looking for, use it separated by dots. For example, `DSL: attributes.attribute`. Only five results will show up in the sidebar, so be as specific as possible. If you don't find it, press enter and you will be taken to the search page.
|
||||
|
||||
#### In the search page
|
||||
|
||||
In the search page, you filter by type. By default, search terms are considered
|
||||
optional. You can prefix them with + to make them required. Something you would
|
||||
do to find a specific DSL is to search for `+type:dsl +something`.
|
|
@ -35,17 +35,14 @@ defmodule Ash.Api.Dsl do
|
|||
timeout: [
|
||||
type: :timeout,
|
||||
doc: """
|
||||
The default timeout to use for requests using this API.
|
||||
See the [timeouts guide](/documentation/topics/timeouts.md) for more.
|
||||
The default timeout to use for requests using this API. See the [timeouts guide](/documentation/topics/timeouts.md) for more.
|
||||
""",
|
||||
default: 30_000
|
||||
],
|
||||
trace_name: [
|
||||
type: :string,
|
||||
doc: """
|
||||
The name to use in traces. Defaults to the last part of the module.
|
||||
|
||||
See the [monitoring guide](/documentation/topics/monitoring.md) for more
|
||||
The name to use in traces. Defaults to the last part of the module. See the [monitoring guide](/documentation/topics/monitoring.md) for more
|
||||
"""
|
||||
]
|
||||
]
|
||||
|
@ -54,9 +51,7 @@ defmodule Ash.Api.Dsl do
|
|||
@authorization %Spark.Dsl.Section{
|
||||
name: :authorization,
|
||||
describe: """
|
||||
Options for how requests are authorized using this Api.
|
||||
|
||||
See the [security guide](/documentation/topics/security.md) for more.
|
||||
Options for how requests are authorized using this Api. See the [security guide](/documentation/topics/security.md) for more.
|
||||
""",
|
||||
examples: [
|
||||
"""
|
||||
|
@ -81,7 +76,7 @@ defmodule Ash.Api.Dsl do
|
|||
]
|
||||
}
|
||||
|
||||
defmodule Ash.Api.ResourceReference do
|
||||
defmodule ResourceReference do
|
||||
@moduledoc "A resource reference in an api"
|
||||
defstruct [:resource]
|
||||
end
|
||||
|
@ -92,7 +87,7 @@ defmodule Ash.Api.Dsl do
|
|||
examples: [
|
||||
"resource Foo"
|
||||
],
|
||||
target: Ash.Api.ResourceReference,
|
||||
target: ResourceReference,
|
||||
args: [:resource],
|
||||
no_depend_modules: [:resource],
|
||||
schema: [
|
||||
|
@ -143,8 +138,6 @@ defmodule Ash.Api.Dsl do
|
|||
@sections [@api, @resources, @execution, @authorization]
|
||||
|
||||
@moduledoc """
|
||||
A small DSL for declaring APIs
|
||||
|
||||
Apis are the entrypoints for working with your resources.
|
||||
|
||||
Apis may optionally include a list of resources, in which case they can be
|
||||
|
@ -152,19 +145,6 @@ defmodule Ash.Api.Dsl do
|
|||
but if at all possible you should define an `Ash.Registry` if you are using an extension
|
||||
that requires a list of resources. For example, most extensions look for two application
|
||||
environment variables called `:ash_apis` and `:ash_registries` to find any potential registries
|
||||
|
||||
<!--- ash-hq-hide-start --> <!--- -->
|
||||
|
||||
## DSL Documentation
|
||||
|
||||
### Index
|
||||
|
||||
#{Spark.Dsl.Extension.doc_index(@sections)}
|
||||
|
||||
### Docs
|
||||
|
||||
#{Spark.Dsl.Extension.doc(@sections)}
|
||||
<!--- ash-hq-hide-stop --> <!--- -->
|
||||
"""
|
||||
|
||||
use Spark.Dsl.Extension, sections: @sections
|
||||
|
|
|
@ -36,19 +36,6 @@ defmodule Ash.DataLayer.Ets do
|
|||
|
||||
Remember, this does not have support for transactions! This is not recommended for production
|
||||
use, especially in multi-user applications. It can, however, be great for prototyping.
|
||||
|
||||
<!--- ash-hq-hide-start--> <!--- -->
|
||||
|
||||
## DSL Documentation
|
||||
|
||||
### Index
|
||||
|
||||
#{Spark.Dsl.Extension.doc_index([@ets])}
|
||||
|
||||
### Docs
|
||||
|
||||
#{Spark.Dsl.Extension.doc([@ets])}
|
||||
<!--- ash-hq-hide-stop--> <!--- -->
|
||||
"""
|
||||
|
||||
use Spark.Dsl.Extension,
|
||||
|
|
|
@ -31,19 +31,6 @@ defmodule Ash.DataLayer.Mnesia do
|
|||
This data layer is *unoptimized*, fetching all records from a table and filtering them
|
||||
in memory. For that reason, it is not recommended to use it with large amounts of data. It can be
|
||||
great for prototyping or light usage, though.
|
||||
|
||||
<!--- ash-hq-hide-start--> <!--- -->
|
||||
|
||||
## DSL Documentation
|
||||
|
||||
### Index
|
||||
|
||||
#{Spark.Dsl.Extension.doc_index([@mnesia])}
|
||||
|
||||
### Docs
|
||||
|
||||
#{Spark.Dsl.Extension.doc([@mnesia])}
|
||||
<!--- ash-hq-hide-stop--> <!--- -->
|
||||
"""
|
||||
|
||||
use Spark.Dsl.Extension,
|
||||
|
|
|
@ -13,6 +13,7 @@ defmodule Ash.Flow.Dsl do
|
|||
"""
|
||||
],
|
||||
target: Ash.Flow.Step.Debug,
|
||||
recursive_as: :steps,
|
||||
args: [:name],
|
||||
schema: Ash.Flow.Step.Debug.schema()
|
||||
}
|
||||
|
@ -27,6 +28,7 @@ defmodule Ash.Flow.Dsl do
|
|||
create :create_post, MyApp.Post, :create
|
||||
"""
|
||||
],
|
||||
recursive_as: :steps,
|
||||
no_depend_modules: [:resource, :touches_resources],
|
||||
modules: [:manual],
|
||||
target: Ash.Flow.Step.Create,
|
||||
|
@ -49,6 +51,7 @@ defmodule Ash.Flow.Dsl do
|
|||
no_depend_modules: [:resource, :touches_resources],
|
||||
modules: [:manual],
|
||||
target: Ash.Flow.Step.Update,
|
||||
recursive_as: :steps,
|
||||
args: [:name, :resource, :action],
|
||||
schema: Ash.Flow.Step.Update.schema()
|
||||
}
|
||||
|
@ -66,6 +69,7 @@ defmodule Ash.Flow.Dsl do
|
|||
end
|
||||
"""
|
||||
],
|
||||
recursive_as: :steps,
|
||||
no_depend_modules: [:resource, :touches_resources],
|
||||
target: Ash.Flow.Step.Update,
|
||||
args: [:name, :resource, :action],
|
||||
|
@ -82,6 +86,7 @@ defmodule Ash.Flow.Dsl do
|
|||
destroy :destroy_post, MyApp.Post, :destroy
|
||||
"""
|
||||
],
|
||||
recursive_as: :steps,
|
||||
modules: [:manual],
|
||||
no_depend_modules: [:resource, :touches_resources],
|
||||
target: Ash.Flow.Step.Destroy,
|
||||
|
@ -99,6 +104,7 @@ defmodule Ash.Flow.Dsl do
|
|||
read :destroy_post, MyApp.Post, :destroy
|
||||
"""
|
||||
],
|
||||
recursive_as: :steps,
|
||||
no_depend_modules: [:resource, :touches_resources],
|
||||
modules: [:manual],
|
||||
target: Ash.Flow.Step.Read,
|
||||
|
@ -120,6 +126,7 @@ defmodule Ash.Flow.Dsl do
|
|||
}
|
||||
"""
|
||||
],
|
||||
recursive_as: :run_flow,
|
||||
no_depend_modules: [:resource, :touches_resources],
|
||||
target: Ash.Flow.Step.RunFlow,
|
||||
args: [:name, :flow],
|
||||
|
@ -145,6 +152,7 @@ defmodule Ash.Flow.Dsl do
|
|||
end
|
||||
"""
|
||||
],
|
||||
recursive_as: :steps,
|
||||
no_depend_modules: [:custom, :touches_resources],
|
||||
target: Ash.Flow.Step.Custom,
|
||||
args: [:name, :custom],
|
||||
|
@ -210,8 +218,6 @@ defmodule Ash.Flow.Dsl do
|
|||
]
|
||||
}
|
||||
|
||||
@leaf_steps [@create, @debug, @update, @destroy, @validate, @read, @run_flow, @custom]
|
||||
|
||||
@transaction %Spark.Dsl.Entity{
|
||||
name: :transaction,
|
||||
describe: """
|
||||
|
@ -222,7 +228,7 @@ defmodule Ash.Flow.Dsl do
|
|||
args: [:name, :resource],
|
||||
recursive_as: :steps,
|
||||
entities: [
|
||||
steps: @leaf_steps
|
||||
steps: []
|
||||
],
|
||||
no_depend_modules: [:touches_resources],
|
||||
examples: [
|
||||
|
@ -257,7 +263,7 @@ defmodule Ash.Flow.Dsl do
|
|||
recursive_as: :steps,
|
||||
no_depend_modules: [:touches_resources],
|
||||
entities: [
|
||||
steps: @leaf_steps
|
||||
steps: []
|
||||
],
|
||||
examples: [
|
||||
"""
|
||||
|
@ -286,7 +292,7 @@ defmodule Ash.Flow.Dsl do
|
|||
recursive_as: :steps,
|
||||
no_depend_modules: [:touches_resources],
|
||||
entities: [
|
||||
steps: @leaf_steps
|
||||
steps: []
|
||||
],
|
||||
examples: [
|
||||
"""
|
||||
|
@ -318,12 +324,19 @@ defmodule Ash.Flow.Dsl do
|
|||
"""
|
||||
],
|
||||
imports: [Ash.Flow.StepHelpers],
|
||||
entities:
|
||||
[
|
||||
entities: [
|
||||
@map,
|
||||
@branch,
|
||||
@transaction
|
||||
] ++ @leaf_steps
|
||||
@transaction,
|
||||
@create,
|
||||
@debug,
|
||||
@update,
|
||||
@destroy,
|
||||
@validate,
|
||||
@read,
|
||||
@run_flow,
|
||||
@custom
|
||||
]
|
||||
}
|
||||
|
||||
@transformers [
|
||||
|
@ -340,18 +353,11 @@ defmodule Ash.Flow.Dsl do
|
|||
|
||||
@moduledoc """
|
||||
The built in flow DSL.
|
||||
<!--- ash-hq-hide-start--> <!--- -->
|
||||
|
||||
## DSL Documentation
|
||||
## Halting
|
||||
|
||||
### Index
|
||||
|
||||
#{Spark.Dsl.Extension.doc_index(@sections)}
|
||||
|
||||
### Docs
|
||||
|
||||
#{Spark.Dsl.Extension.doc(@sections)}
|
||||
<!--- ash-hq-hide-stop--> <!--- -->
|
||||
Steps can be halted, which will stop the flow from continuing and return a halted flow. To attach a specific reason, use a `halt_reason`.
|
||||
If you need more complex halting logic, then you'd want to use a custom step, and return `{:error, Ash.Error.Flow.Halted.exception(...)}`
|
||||
"""
|
||||
|
||||
use Spark.Dsl.Extension,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
defmodule Ash.Flow.Step.Branch do
|
||||
@moduledoc false
|
||||
@moduledoc "Represents a branching set of steps in an Ash.Flow"
|
||||
use Ash.Flow.Step.BuiltinStep, [:output, :condition, steps: []]
|
||||
@shared_opts Ash.Flow.Step.shared_opts()
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
defmodule Ash.Flow.Step.Create do
|
||||
@moduledoc false
|
||||
@moduledoc "Represents a create action step in an Ash.Flow"
|
||||
use Ash.Flow.Step.BuiltinStep, [
|
||||
:resource,
|
||||
:action,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
defmodule Ash.Flow.Step.Custom do
|
||||
@moduledoc false
|
||||
@moduledoc "Represents a custom step in an Ash.Flow"
|
||||
use Ash.Flow.Step.BuiltinStep, [:input, :custom, :async?]
|
||||
@shared_opts Ash.Flow.Step.shared_opts()
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
defmodule Ash.Flow.Step.Debug do
|
||||
@moduledoc false
|
||||
@moduledoc "Represents a debug step in an Ash.Flow"
|
||||
use Ash.Flow.Step.BuiltinStep, [:input]
|
||||
@shared_opts Ash.Flow.Step.shared_opts()
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
defmodule Ash.Flow.Step.Destroy do
|
||||
@moduledoc false
|
||||
@moduledoc "Represents a destroy action step in an Ash.Flow"
|
||||
use Ash.Flow.Step.BuiltinStep, [:resource, :action, :api, :input, :tenant, :record]
|
||||
@shared_opts Ash.Flow.Step.shared_opts()
|
||||
@shared_action_opts Ash.Flow.Step.shared_action_opts()
|
||||
|
@ -12,9 +12,6 @@ defmodule Ash.Flow.Step.Destroy do
|
|||
required: true,
|
||||
doc: """
|
||||
The record to be updated, can use template helpers, e.g `result(:step_name)`.
|
||||
|
||||
If the value is `nil`, the step is skipped and `nil` is the result of the step.
|
||||
Any other value is used as an input record.
|
||||
"""
|
||||
]
|
||||
]
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
defmodule Ash.Flow.Step.Map do
|
||||
@moduledoc false
|
||||
@moduledoc "Represents a map grouping of steps in an Ash.Flow"
|
||||
use Ash.Flow.Step.BuiltinStep, [:over, :element, :output, steps: []]
|
||||
@shared_opts Ash.Flow.Step.shared_opts()
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
defmodule Ash.Flow.Step.Read do
|
||||
@moduledoc false
|
||||
@moduledoc "Represents a read action step in an Ash.Flow"
|
||||
use Ash.Flow.Step.BuiltinStep, [
|
||||
:resource,
|
||||
:action,
|
||||
|
@ -19,8 +19,7 @@ defmodule Ash.Flow.Step.Read do
|
|||
get?: [
|
||||
type: :boolean,
|
||||
doc: """
|
||||
Whether or not read action is expected to return a single result or `nil`.
|
||||
If the action is configured with `get? true` then this is automatically set to `true`.
|
||||
Whether or not read action is expected to return a single result or `nil`. Set to `true` automatically if `get? true`.
|
||||
""",
|
||||
default: false
|
||||
],
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
defmodule Ash.Flow.Step.RunFlow do
|
||||
@moduledoc false
|
||||
@moduledoc "Represents a nested flow step in an Ash.Flow"
|
||||
use Ash.Flow.Step.BuiltinStep, [:input, :flow, :built]
|
||||
@shared_opts Ash.Flow.Step.shared_opts()
|
||||
|
||||
|
|
|
@ -34,10 +34,7 @@ defmodule Ash.Flow.Step do
|
|||
wait_for: [
|
||||
type: :any,
|
||||
doc: """
|
||||
Ensures that the step happens after the configured step or steps.
|
||||
|
||||
This value is just a template that isn't used, except to determine dependencies, so you can
|
||||
use it like this `wait_for [result(:step_one), result(:step_two)]` or `wait_for result(:step)`.
|
||||
Ensures that the step happens after the configured step or steps. This is a template who's results are not used, only awaited.
|
||||
"""
|
||||
],
|
||||
touches_resources: [
|
||||
|
@ -49,11 +46,7 @@ defmodule Ash.Flow.Step do
|
|||
halt_if: [
|
||||
type: :any,
|
||||
doc: """
|
||||
Halts the step by emitting an error (with an `Ash.Error.Flow.Halted`). Can use template variables.
|
||||
|
||||
To attach a specific reason, use a `halt_reason`.
|
||||
|
||||
If you need more complex halting logic, then you'd want to use a custom step, and return `{:error, Ash.Error.Flow.Halted.exception(...)}`
|
||||
Halts the step by emitting an error (with an `Ash.Error.Flow.Halted`). Can use template variables. See the section on Halting for more.
|
||||
"""
|
||||
],
|
||||
halt_reason: [
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
defmodule Ash.Flow.Step.Transaction do
|
||||
@moduledoc false
|
||||
@moduledoc "Represents steps grouped into a transaction in an Ash.Flow"
|
||||
use Ash.Flow.Step.BuiltinStep, [:output, :resource, :timeout, steps: []]
|
||||
@shared_opts Ash.Flow.Step.shared_opts()
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
defmodule Ash.Flow.Step.Update do
|
||||
@moduledoc false
|
||||
@moduledoc "Represents an update action step in an Ash.Flow"
|
||||
use Ash.Flow.Step.BuiltinStep, [:resource, :action, :api, :input, :tenant, :record]
|
||||
@shared_opts Ash.Flow.Step.shared_opts()
|
||||
@shared_action_opts Ash.Flow.Step.shared_action_opts()
|
||||
|
@ -12,9 +12,6 @@ defmodule Ash.Flow.Step.Update do
|
|||
required: true,
|
||||
doc: """
|
||||
The record to be updated, can use template helpers, e.g `result(:step_name)`.
|
||||
|
||||
If the value is `nil`, the step is skipped and `nil` is the result of the step.
|
||||
Any other value is used as an input record.
|
||||
"""
|
||||
]
|
||||
]
|
||||
|
|
|
@ -10,18 +10,13 @@ defmodule Ash.Flow.Step.Validate do
|
|||
record: [
|
||||
type: :any,
|
||||
doc: """
|
||||
The record to be created/updated/destroyed, if relevant. can use template helpers, e.g `result(:step_name)`.
|
||||
|
||||
If the value is `nil` and would be required by the action type, the step is skipped and `nil` is the result of the step.
|
||||
Any other value is used as an input record.
|
||||
The record to be created/updated/destroyed. If the value is `nil` and would be required by the action type, the step is skipped and `nil` is the result of the step.
|
||||
"""
|
||||
],
|
||||
only_keys: [
|
||||
type: {:list, {:or, [:atom, {:list, :atom}]}},
|
||||
doc: """
|
||||
If the keys are set, the step will succeed as long as there are no errors for those specific fields.
|
||||
Additionally, only errors for those keys will be returned.
|
||||
Use a list for the key if you want to check for an error at a path, and use `:_` to allow anything at that path
|
||||
A list of keys or paths to keys that should be validated. Others will be ignored, and errors generated for other fields will be ignored.
|
||||
"""
|
||||
]
|
||||
]
|
||||
|
|
|
@ -75,19 +75,12 @@ defmodule Ash.Notifier.PubSub do
|
|||
type: {:one_of, [:notification, :phoenix_broadcast, :broadcast]},
|
||||
default: :notification,
|
||||
doc: """
|
||||
What shape the event payloads will be in. `:notification` just sends the notification, `phoenix_broadcast` sends a `%Phoenix.Socket.Broadcast{}`, and `:broadcast`
|
||||
sends `%{topic: (topic), event: (event), notification: (notification)}`
|
||||
What shape the event payloads will be in. See
|
||||
"""
|
||||
],
|
||||
name: [
|
||||
type: :atom,
|
||||
doc: """
|
||||
A named pub sub to pass as the first argument to broadcast.
|
||||
|
||||
If you are using a phoenix `Endpoint` module for pubsub then this is unnecessary. If you want to use
|
||||
a custom pub sub started with something like `{Phoenix.PubSub, name: MyName}`, then you can provide `MyName` to
|
||||
here.
|
||||
"""
|
||||
doc: "A named pub sub to pass as the first argument to broadcast."
|
||||
]
|
||||
]
|
||||
}
|
||||
|
@ -96,19 +89,6 @@ defmodule Ash.Notifier.PubSub do
|
|||
|
||||
@moduledoc """
|
||||
A pubsub notifier extension.
|
||||
|
||||
<!--- ash-hq-hide-start--> <!--- -->
|
||||
|
||||
## DSL Documentation
|
||||
|
||||
### Index
|
||||
|
||||
#{Spark.Dsl.Extension.doc_index(@sections)}
|
||||
|
||||
### Docs
|
||||
|
||||
#{Spark.Dsl.Extension.doc(@sections)}
|
||||
<!--- ash-hq-hide-stop--> <!--- -->
|
||||
"""
|
||||
|
||||
use Spark.Dsl.Extension, sections: @sections
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
defmodule Ash.Notifier.PubSub.Publication do
|
||||
@moduledoc false
|
||||
@moduledoc "Represents a configured publication from the pubsub notifier on an Ash.Resource"
|
||||
|
||||
defstruct [
|
||||
:action,
|
||||
|
|
|
@ -28,9 +28,7 @@ defmodule Ash.Policy.Authorizer do
|
|||
type: {:custom, __MODULE__, :validate_check, []},
|
||||
required: true,
|
||||
doc: """
|
||||
The check to run.
|
||||
|
||||
See `Ash.Policy.Check` for more.
|
||||
The check to run. See `Ash.Policy.Check` for more.
|
||||
"""
|
||||
],
|
||||
name: [
|
||||
|
@ -243,10 +241,8 @@ defmodule Ash.Policy.Authorizer do
|
|||
],
|
||||
condition: [
|
||||
type: {:custom, __MODULE__, :validate_condition, []},
|
||||
doc: """
|
||||
A check or list of checks that must be true in order for this field policy to apply.
|
||||
If not specified, it always applies.
|
||||
"""
|
||||
doc:
|
||||
"A check or list of checks that must be true in order for this field policy to apply. If not specified, it always applies."
|
||||
]
|
||||
],
|
||||
args: [:fields, {:optional, :condition, {Ash.Policy.Check.Static, result: true}}],
|
||||
|
@ -364,19 +360,6 @@ defmodule Ash.Policy.Authorizer do
|
|||
authorization rules as they may be deemed unnecessary. As such, authorization
|
||||
checks should have no side effects. Ideally, the checks built-in to ash should
|
||||
cover the bulk of your needs.
|
||||
|
||||
<!--- ash-hq-hide-start--> <!--- -->
|
||||
|
||||
## DSL Documentation
|
||||
|
||||
### Index
|
||||
|
||||
#{Spark.Dsl.Extension.doc_index(@sections)}
|
||||
|
||||
### Docs
|
||||
|
||||
#{Spark.Dsl.Extension.doc(@sections)}
|
||||
<!--- ash-hq-hide-stop--> <!--- -->
|
||||
"""
|
||||
|
||||
require Logger
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
defmodule Ash.Policy.FieldPolicy do
|
||||
@moduledoc false
|
||||
@moduledoc "Represents a field policy in an Ash.Resource"
|
||||
defstruct [
|
||||
:fields,
|
||||
:condition,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
defmodule Ash.Policy.Policy do
|
||||
@moduledoc false
|
||||
@moduledoc "Represents a policy on an Ash.Resource"
|
||||
|
||||
# For now we just write to `checks` and move them to `policies`
|
||||
# on build, when we support nested policies we can change that.
|
||||
|
|
|
@ -1846,7 +1846,7 @@ defmodule Ash.Query do
|
|||
Aggregations are made available on the `aggregates` field of the records returned
|
||||
|
||||
The filter option accepts either a filter or a keyword list of options to supply to build a limiting query for that aggregate.
|
||||
See the DSL docs for each aggregate type in `Ash.Resource.Dsl` for more information.
|
||||
See the DSL docs for each aggregate type in the [Resource DSL docs](dsl-ash-resource.html#aggregates) for more information.
|
||||
|
||||
Options:
|
||||
|
||||
|
@ -1887,7 +1887,7 @@ defmodule Ash.Query do
|
|||
Aggregations are made available on the `aggregates` field of the records returned
|
||||
|
||||
The filter option accepts either a filter or a keyword list of options to supply to build a limiting query for that aggregate.
|
||||
See the DSL docs for each aggregate type in `Ash.Resource.Dsl` for more information.
|
||||
See the DSL docs for each aggregate type in the [Resource DSL docs](dsl-ash-resource.html#aggregates) for more information.
|
||||
"""
|
||||
@spec aggregate(
|
||||
t() | Ash.Resource.t(),
|
||||
|
|
|
@ -45,22 +45,9 @@ defmodule Ash.Registry.Dsl do
|
|||
@transformers [Ash.Registry.Transformers.WarnOnEmpty]
|
||||
|
||||
@moduledoc """
|
||||
A small DSL for declaring an `Ash.Registry`.
|
||||
A small DSL for declaring an `Ash.Registry`. Not generally necessary any longer.
|
||||
|
||||
`Ash.Registry` can be used generically, but the main way it is used in Ash is to provide a compile-time registry for an Ash Api.
|
||||
|
||||
<!--- ash-hq-hide-start--> <!--- -->
|
||||
|
||||
## DSL Documentation
|
||||
|
||||
### Index
|
||||
|
||||
#{Spark.Dsl.Extension.doc_index(@sections)}
|
||||
|
||||
### Docs
|
||||
|
||||
#{Spark.Dsl.Extension.doc(@sections)}
|
||||
<!--- ash-hq-hide-stop--> <!--- -->
|
||||
"""
|
||||
|
||||
use Spark.Dsl.Extension, sections: @sections, transformers: @transformers
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
defmodule Ash.Registry.Entry do
|
||||
@moduledoc false
|
||||
@moduledoc "Represents an entry in an Ash.Registry"
|
||||
|
||||
defstruct [:entry]
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ defmodule Ash.Resource do
|
|||
@moduledoc """
|
||||
A resource is a static definition of an entity in your system.
|
||||
|
||||
Resource DSL documentation: `Ash.Resource.Dsl`
|
||||
[Resource DSL documentation](dsl-ash-resource.html)
|
||||
"""
|
||||
|
||||
@type t :: module
|
||||
|
|
|
@ -38,10 +38,7 @@ defmodule Ash.Resource.Actions.Action do
|
|||
constraints: [
|
||||
type: :keyword_list,
|
||||
doc: """
|
||||
Constraints for the return type.
|
||||
For more information see the specific type's documentation,
|
||||
for general type information see `Ash.Type` and
|
||||
for practical example [see the constraints topic](/documentation/topics/constraints.md).
|
||||
Constraints for the return type. See the [constriants topic](/documentation/topics/constraints.md) for more.
|
||||
"""
|
||||
],
|
||||
run: [
|
||||
|
|
|
@ -33,18 +33,14 @@ defmodule Ash.Resource.Actions.Argument do
|
|||
type: :keyword_list,
|
||||
default: [],
|
||||
doc: """
|
||||
Constraints to provide to the type when casting the value.
|
||||
For more information see the specific type's documentation,
|
||||
for general type information see `Ash.Type` and
|
||||
for practical example [see the constraints topic](/documentation/topics/constraints.md).
|
||||
Constraints to provide to the type when casting the value. For more information, see [the constraints topic](/documentation/topics/constraints.md).
|
||||
"""
|
||||
],
|
||||
allow_nil?: [
|
||||
type: :boolean,
|
||||
default: true,
|
||||
doc: """
|
||||
Whether or not the argument value may be nil (or may be not provided)
|
||||
If nil value is given error is raised.
|
||||
Whether or not the argument value may be nil (or may be not provided). If nil value is given error is raised.
|
||||
"""
|
||||
],
|
||||
private?: [
|
||||
|
@ -58,9 +54,7 @@ defmodule Ash.Resource.Actions.Argument do
|
|||
type: :boolean,
|
||||
default: false,
|
||||
doc: """
|
||||
Whether or not the argument value contains sensitive information, like PII.
|
||||
Using this option will cause the argument to be `** Redacted **` from the resource when logging or inspecting.
|
||||
See the [security guide](/documentation/topics/security.md) for more.
|
||||
Whether or not the argument value contains sensitive information, like PII. See the [security guide](/documentation/topics/security.md) for more.
|
||||
"""
|
||||
],
|
||||
default: [
|
||||
|
|
|
@ -50,8 +50,7 @@ defmodule Ash.Resource.Actions.Create do
|
|||
allow_nil_input: [
|
||||
type: {:list, :atom},
|
||||
doc: """
|
||||
A list of attributes that would normally be required, but should not be for this action. They will still be validated just before
|
||||
the record is created.
|
||||
A list of attributes that would normally be required, but should not be for this action. They will still be validated just before the record is created.
|
||||
"""
|
||||
],
|
||||
manual: [
|
||||
|
@ -59,19 +58,14 @@ defmodule Ash.Resource.Actions.Create do
|
|||
{:spark_function_behaviour, Ash.Resource.ManualCreate,
|
||||
{Ash.Resource.ManualCreate.Function, 2}},
|
||||
doc: """
|
||||
Override the creation behavior. See the manual action guides for more. Accepts a module or module and opts, or a function that takes the changeset and context.
|
||||
|
||||
See the [manual actions guide](/documentation/topics/manual-actions.md) for more.
|
||||
Override the creation behavior. Accepts a module or module and opts, or a function that takes the changeset and context. See the [manual actions guide](/documentation/topics/manual-actions.md) for more.
|
||||
"""
|
||||
],
|
||||
upsert?: [
|
||||
type: :boolean,
|
||||
default: false,
|
||||
doc: """
|
||||
Wether or not this action is always an upsert.
|
||||
|
||||
If this is false, the action can still be used as an upsert by passing `upsert?: true` when using it.
|
||||
This option forces all uses of this action to be treated as an upsert
|
||||
Forces all uses of this action to be treated as an upsert.
|
||||
"""
|
||||
],
|
||||
upsert_identity: [
|
||||
|
@ -84,8 +78,6 @@ defmodule Ash.Resource.Actions.Create do
|
|||
type: {:list, :atom},
|
||||
doc: """
|
||||
The fields to overwrite in the case of an upsert. If not provided, all fields except for fields set by defaults will be overwritten.
|
||||
|
||||
For example `uuid_primary_key :id` gets a default value, and so we would not overwrite that.
|
||||
"""
|
||||
]
|
||||
]
|
||||
|
|
|
@ -49,9 +49,7 @@ defmodule Ash.Resource.Actions.Destroy do
|
|||
{:spark_function_behaviour, Ash.Resource.ManualDestroy,
|
||||
{Ash.Resource.ManualDestroy.Function, 2}},
|
||||
doc: """
|
||||
Override the update behavior. See the manual action guides for more. Accepts a module or module and opts, or a function that takes the changeset and context.
|
||||
|
||||
See the [manual actions guide](/documentation/topics/manual-actions.md) for more.
|
||||
Override the update behavior. Accepts a module or module and opts, or a function that takes the changeset and context. See the [manual actions guide](/documentation/topics/manual-actions.md) for more.
|
||||
"""
|
||||
]
|
||||
]
|
||||
|
|
|
@ -50,42 +50,27 @@ defmodule Ash.Resource.Actions.Read do
|
|||
{:spark_function_behaviour, Ash.Resource.ManualRead,
|
||||
{Ash.Resource.ManualRead.Function, 3}},
|
||||
doc: """
|
||||
Delegates running of the query to the provided module.
|
||||
Accepts a module or module and opts, or a function that takes the changeset and context.
|
||||
|
||||
See the [manual actions guide](/documentation/topics/manual-actions.md) for more.
|
||||
Delegates running of the query to the provided module. Accepts a module or module and opts, or a function that takes the changeset and context. See the [manual actions guide](/documentation/topics/manual-actions.md) for more.
|
||||
"""
|
||||
],
|
||||
get?: [
|
||||
type: :boolean,
|
||||
default: false,
|
||||
doc: """
|
||||
Expresses that this action innately only returns a single result. Can be used by extensions to validate that you have not hooked something up that expects a list
|
||||
to an action that can only return one thing. Used by the code interface when defining functions for read actions.
|
||||
|
||||
See the [code interface guide](/documentation/topics/code-interface.md) for more.
|
||||
Expresses that this action innately only returns a single result. Used by extensions to validate and/or modify behavior. Causes code interfaces to return a single value instead of a list. See the [code interface guide](/documentation/topics/code-interface.md) for more.
|
||||
"""
|
||||
],
|
||||
modify_query: [
|
||||
type: {:or, [:mfa, {:fun, 2}]},
|
||||
doc: """
|
||||
Allows direct manipulation of the data layer query via an MFA.
|
||||
|
||||
The ash query and the data layer query will be provided as additional arguments.
|
||||
The result must be `{:ok, new_data_layer_query} | {:error, error}`.
|
||||
|
||||
Here be dragons.
|
||||
Allows direct manipulation of the data layer query via an MFA. The ash query and the data layer query will be provided as additional arguments. The result must be `{:ok, new_data_layer_query} | {:error, error}`.
|
||||
"""
|
||||
],
|
||||
get_by: [
|
||||
type: {:or, [:atom, {:list, :atom}]},
|
||||
default: nil,
|
||||
doc: """
|
||||
A helper to automatically generate a "get by X" action.
|
||||
|
||||
Using this option will set `get?` to true, add arguments
|
||||
for each of the specified fields, and add a filter to the
|
||||
underlying query for each of the arguments.
|
||||
A helper to automatically generate a "get by X" action. Sets `get?` to true, add args for each of the specified fields, and adds a filter for each of the arguments.
|
||||
"""
|
||||
]
|
||||
],
|
||||
|
|
|
@ -20,8 +20,6 @@ defmodule Ash.Resource.Actions.SharedOptions do
|
|||
type: :boolean,
|
||||
doc: """
|
||||
Whether or not the action should be run in transactions. Reads default to false, while create/update/destroy actions default to `true`.
|
||||
|
||||
Has no effect if the data layer does not support transactions, or if that data layer is already in a transaction.
|
||||
"""
|
||||
],
|
||||
touches_resources: [
|
||||
|
@ -41,8 +39,7 @@ defmodule Ash.Resource.Actions.SharedOptions do
|
|||
type: :boolean,
|
||||
default: false,
|
||||
doc: """
|
||||
If true, global validations will be done in a `before_action` hook, regardless of their configuration
|
||||
on the resource.
|
||||
If true, global validations will be done in a `before_action` hook, regardless of their configuration on the resource.
|
||||
"""
|
||||
],
|
||||
skip_global_validations?: [
|
||||
|
@ -55,18 +52,13 @@ defmodule Ash.Resource.Actions.SharedOptions do
|
|||
reject: [
|
||||
type: {:or, [in: [:all], list: :atom]},
|
||||
doc: """
|
||||
A list of attributes not to accept. This is useful if you want to say 'accept all but x'
|
||||
|
||||
If this is specified along with `accept`, then everything in the `accept` list minus any matches in the
|
||||
`reject` list will be accepted.
|
||||
A list of attributes not to accept. If this is specified along with `accept`, these are removed from the `accept` list.
|
||||
"""
|
||||
],
|
||||
require_attributes: [
|
||||
type: {:list, :atom},
|
||||
doc: """
|
||||
A list of attributes that would normally `allow_nil?`, to require for this action.
|
||||
|
||||
No need to include attributes that already do not allow nil?
|
||||
A list of attributes that would normally `allow_nil?`, to require for this action. No need to include attributes that already do not allow nil?
|
||||
"""
|
||||
],
|
||||
error_handler: [
|
||||
|
@ -76,9 +68,7 @@ defmodule Ash.Resource.Actions.SharedOptions do
|
|||
manual?: [
|
||||
type: :boolean,
|
||||
doc: """
|
||||
Instructs Ash to *skip* the actual update/create/destroy step at the data layer. See the manual action guides for more.
|
||||
|
||||
See the [manual actions guide](/documentation/topics/manual-actions.md) for more.
|
||||
Instructs Ash to *skip* the actual update/create/destroy step at the data layer. See the [manual actions guide](/documentation/topics/manual-actions.md) for more.
|
||||
"""
|
||||
]
|
||||
]
|
||||
|
|
|
@ -46,10 +46,7 @@ defmodule Ash.Resource.Actions.Update do
|
|||
{:spark_function_behaviour, Ash.Resource.ManualUpdate,
|
||||
{Ash.Resource.ManualUpdate.Function, 2}},
|
||||
doc: """
|
||||
Override the update behavior. See the manual action guides for more.
|
||||
Accepts a module or module and opts, or a function that takes the changeset and context.
|
||||
|
||||
See the [manual actions guide](/documentation/topics/manual-actions.md) for more.
|
||||
Override the update behavior. Accepts a module or module and opts, or a function that takes the changeset and context. See the [manual actions guide](/documentation/topics/manual-actions.md) for more.
|
||||
"""
|
||||
]
|
||||
]
|
||||
|
|
|
@ -28,10 +28,7 @@ defmodule Ash.Resource.Aggregate do
|
|||
read_action: [
|
||||
type: :atom,
|
||||
doc: """
|
||||
The read action to use when building the aggregate
|
||||
|
||||
Defaults to the primary read action. Keep in mind this action must not
|
||||
have any required arguments.
|
||||
The read action to use when building the aggregate. Defaults to the primary read action. Keep in mind this action must not have any required arguments.
|
||||
"""
|
||||
],
|
||||
relationship_path: [
|
||||
|
@ -87,13 +84,7 @@ defmodule Ash.Resource.Aggregate do
|
|||
type: :boolean,
|
||||
default: true,
|
||||
doc: """
|
||||
Wether or not the aggregate query should authorize based on the target action.
|
||||
|
||||
If you are using filter checks or simple checks that don't depend on arguments on the destination resource, then
|
||||
this should be set to `true`. Additionally, you can set `read_action` to a separate action that does have filter checks.
|
||||
Otherwise, you can set `authorize? false` on the aggregate.
|
||||
|
||||
If the parent query is not being authorized, then the aggregate not be authorized either regardless of the setting.
|
||||
Wether or not the aggregate query should authorize based on the target action, if the parent query is authorized. Requires filter checks on the target action.
|
||||
"""
|
||||
]
|
||||
]
|
||||
|
|
|
@ -57,10 +57,7 @@ defmodule Ash.Resource.Attribute do
|
|||
constraints: [
|
||||
type: :keyword_list,
|
||||
doc: """
|
||||
Constraints to provide to the type when casting the value.
|
||||
For more information see the specific type's documentation,
|
||||
for general type information see `Ash.Type` and
|
||||
for practical example [see the constraints topic](/documentation/topics/constraints.md).
|
||||
Constraints to provide to the type when casting the value. For more, see the [constraints topic](/documentation/topics/constraints.md).
|
||||
"""
|
||||
],
|
||||
description: [
|
||||
|
@ -71,9 +68,7 @@ defmodule Ash.Resource.Attribute do
|
|||
type: :boolean,
|
||||
default: false,
|
||||
doc: """
|
||||
Whether or not the attribute value contains sensitive information, like PII.
|
||||
Using this option will cause the attribute to be `** Redacted **` from the resource when logging or inspecting.
|
||||
See the [Security guide](/documentation/topics/security.md) for more.
|
||||
Whether or not the attribute value contains sensitive information, like PII. See the [Security guide](/documentation/topics/security.md) for more.
|
||||
"""
|
||||
],
|
||||
source: [
|
||||
|
@ -86,29 +81,21 @@ defmodule Ash.Resource.Attribute do
|
|||
type: :boolean,
|
||||
default: false,
|
||||
doc: """
|
||||
Whether or not to ensure this attribute is always selected when reading from the database.
|
||||
|
||||
When this option is true and performing a read action, the attribute will **always** be selected even if it was explicitly selected out of the query.
|
||||
For example say there is a resource with two attributes `:foo` and `:bar`.
|
||||
Say `:foo` has `always_select? true` set.
|
||||
The query `Ash.Query.select(MyResource, [:bar])` would return both `:foo` and `:bar` even though `:foo` was not selected in the query.
|
||||
Whether or not to ensure this attribute is always selected when reading from the database, regardless of applied select statements.
|
||||
"""
|
||||
],
|
||||
primary_key?: [
|
||||
type: :boolean,
|
||||
default: false,
|
||||
doc: """
|
||||
Whether the attribute is the primary key.
|
||||
Composite primary key is also possible by using `primary_key? true` in more than one attribute.
|
||||
If primary_key? is true, allow_nil? must be false.
|
||||
Whether the attribute is the primary key. Composite primary key is also possible by using `primary_key? true` in more than one attribute. If primary_key? is true, allow_nil? must be false.
|
||||
"""
|
||||
],
|
||||
allow_nil?: [
|
||||
type: :boolean,
|
||||
default: true,
|
||||
doc: """
|
||||
Whether or not the attribute can be set to nil.
|
||||
If nil value is given error is raised.
|
||||
Whether or not the attribute can be set to nil. If nil value is given error is raised.
|
||||
"""
|
||||
],
|
||||
generated?: [
|
||||
|
@ -122,20 +109,14 @@ defmodule Ash.Resource.Attribute do
|
|||
type: :boolean,
|
||||
default: true,
|
||||
doc: """
|
||||
Whether or not the value can be written to.
|
||||
If `writable? false` then attribute is read-only and cannot be written to even when creating a record.
|
||||
This can be overridden with `Ash.Changeset.force_change_attribute/3`.
|
||||
Whether or not the value can be written to. Non-writable attributes can still be written with `Ash.Changeset.force_change_attribute/3`.
|
||||
"""
|
||||
],
|
||||
private?: [
|
||||
type: :boolean,
|
||||
default: false,
|
||||
doc: """
|
||||
If `private? true` then attribute is read-only and cannot be written to even when creating a record.
|
||||
Additionally it tells other extensions (e.g. AshJsonApi or AshGraphql) not to expose these attributes through the API.
|
||||
The value of the attribute can be overridden with `Ash.Changeset.force_change_attribute/3`.
|
||||
|
||||
See the [security guide](/documentation/topics/security.md) for more.
|
||||
The attribute is not publically writable, and should not be exposed over any public interfaces. See the [security guide](/documentation/topics/security.md) for more.
|
||||
"""
|
||||
],
|
||||
default: [
|
||||
|
@ -151,17 +132,13 @@ defmodule Ash.Resource.Attribute do
|
|||
default: true,
|
||||
doc: """
|
||||
Whether or not the attribute can be referenced in filters.
|
||||
Can be used to prevent filtering on large text columns with no indexing.
|
||||
"""
|
||||
],
|
||||
match_other_defaults?: [
|
||||
type: :boolean,
|
||||
default: false,
|
||||
doc: """
|
||||
Ensures that other attributes that use the same "lazy" default (a function or an mfa), use the same default value.
|
||||
Has no effect unless `default` is a zero argument function.
|
||||
For example, create and update timestamps use this option, and have the same lazy function `&DateTime.utc_now/0`, so they
|
||||
get the same value, instead of having slightly different timestamps.
|
||||
Ensures that other attributes that use the same "lazy" default (a function or an mfa), use the same default value. Has no effect unless `default` is a zero argument function.
|
||||
"""
|
||||
]
|
||||
]
|
||||
|
|
|
@ -38,9 +38,7 @@ defmodule Ash.Resource.Calculation do
|
|||
]},
|
||||
required: true,
|
||||
doc: """
|
||||
The module or `{module, opts}` to use for the calculation.
|
||||
Also accepts a function that takes a single record and produces the result.
|
||||
IMPORTANT: This function *does not take and return lists* like the `calculate/3` callback does.
|
||||
The `module`, `{module, opts}` or `expr(...)` to use for the calculation. Also accepts a function that takes *a single record* and produces the result.
|
||||
"""
|
||||
],
|
||||
description: [
|
||||
|
@ -51,9 +49,7 @@ defmodule Ash.Resource.Calculation do
|
|||
type: :boolean,
|
||||
default: false,
|
||||
doc: """
|
||||
Whether or not the calculation will appear in any interfaces created off of this resource, e.g AshJsonApi and AshGraphql
|
||||
|
||||
See the [security guide](/documentation/topics/security.md) for more.
|
||||
Whether or not the calculation will appear in any interfaces created off of this resource, e.g AshJsonApi and AshGraphql See the [security guide](/documentation/topics/security.md) for more.
|
||||
"""
|
||||
],
|
||||
select: [
|
||||
|
|
|
@ -21,21 +21,7 @@ defmodule Ash.Resource.CalculationInterface do
|
|||
type: :any,
|
||||
default: [],
|
||||
doc: """
|
||||
Supply field or argument values referenced by the calculation.
|
||||
|
||||
By default, the value will be provided for any matching named reference *and* argument.
|
||||
This is normally fine, but in the case that you have an argument and a reference with the same name,
|
||||
you can specify it by supplying `{:arg, :name}` and `{:ref, :name}`. For example:
|
||||
|
||||
```elixir
|
||||
define_calculation :id_matches, args: [{:arg, :id}, {:ref, :id}]
|
||||
```
|
||||
|
||||
To make arguments optional, wrap them in `{:optional, ..}`, for example:
|
||||
|
||||
```elixir
|
||||
define_calculation :id_matches, args: [{:arg, :id}, {:optional, {:ref, :id}}]
|
||||
```
|
||||
Supply field or argument values referenced by the calculation, in the form of :name, `{:arg, :name}` and/or `{:ref, :name}`. See the [code interface guide](/documentation/topics/code-interface.md) for more.
|
||||
"""
|
||||
]
|
||||
]
|
||||
|
|
|
@ -40,10 +40,7 @@ defmodule Ash.Resource.Change do
|
|||
{:spark_function_behaviour, Ash.Resource.Change, Ash.Resource.Change.Builtins,
|
||||
{Ash.Resource.Change.Function, 2}},
|
||||
doc: """
|
||||
The module and options for a change.
|
||||
Also accepts a function that takes the changeset and the context.
|
||||
|
||||
See `Ash.Resource.Change.Builtins` for more.
|
||||
The module and options for a change. Also accepts a function that takes the changeset and the context. See `Ash.Resource.Change.Builtins` for builtin changes.
|
||||
""",
|
||||
required: true
|
||||
],
|
||||
|
@ -55,9 +52,7 @@ defmodule Ash.Resource.Change do
|
|||
required: false,
|
||||
default: [],
|
||||
doc: """
|
||||
Validations that should pass in order for this validation to apply.
|
||||
These validations failing will not invalidate the changes, but instead just result in this change being ignored.
|
||||
Also accepts functions take the changeset.
|
||||
Validations that should pass in order for this validation to apply. These validations failing will result in this validation being ignored.
|
||||
"""
|
||||
]
|
||||
]
|
||||
|
|
|
@ -391,19 +391,6 @@ defmodule Ash.Resource.Dsl do
|
|||
args: [:change]
|
||||
}
|
||||
|
||||
defmodule Set do
|
||||
@moduledoc false
|
||||
defstruct [:description, :where, :attribute, :expr]
|
||||
|
||||
def transform(set) do
|
||||
{:ok,
|
||||
%Ash.Resource.Change{
|
||||
change: {Ash.Resource.Change.Atomic, attribute: set.attribute, expr: set.expr}
|
||||
}
|
||||
|> Map.merge(Map.take(set, [:description, :where]))}
|
||||
end
|
||||
end
|
||||
|
||||
@validate %Spark.Dsl.Entity{
|
||||
name: :validate,
|
||||
describe: """
|
||||
|
@ -661,12 +648,7 @@ defmodule Ash.Resource.Dsl do
|
|||
defaults: [
|
||||
type: {:list, {:in, [:create, :read, :update, :destroy]}},
|
||||
doc: """
|
||||
Creates a simple action of each specified type, with the same name as the type.
|
||||
These actions will be the primary actions, unless you've declared a different action
|
||||
of the same type that is explicitly set as primary.
|
||||
|
||||
By default, resources have no default actions. Embedded resources, however, have a default
|
||||
of all resource types.
|
||||
Creates a simple action of each specified type, with the same name as the type. These will be `primary?` unless one already exists for that type. Embedded resources, however, have a default of all resource types.
|
||||
"""
|
||||
],
|
||||
default_accept: [
|
||||
|
@ -780,17 +762,13 @@ defmodule Ash.Resource.Dsl do
|
|||
trace_name: [
|
||||
type: :string,
|
||||
doc: """
|
||||
The name to use in traces. Defaults to the short_name stringified.
|
||||
|
||||
See the [monitoring guide](/documentation/topics/monitoring.md) for more.
|
||||
The name to use in traces. Defaults to the short_name stringified. See the [monitoring guide](/documentation/topics/monitoring.md) for more.
|
||||
"""
|
||||
],
|
||||
short_name: [
|
||||
type: :atom,
|
||||
doc: """
|
||||
A short identifier for the resource, which should be unique.
|
||||
|
||||
See the [monitoring guide](/documentation/topics/monitoring.md) for more.
|
||||
A short identifier for the resource, which should be unique. See the [monitoring guide](/documentation/topics/monitoring.md) for more.
|
||||
"""
|
||||
],
|
||||
plural_name: [
|
||||
|
@ -809,15 +787,7 @@ defmodule Ash.Resource.Dsl do
|
|||
required: false,
|
||||
default: true,
|
||||
doc: """
|
||||
Allow the resource to be used without any primary key fields.
|
||||
|
||||
### Warning
|
||||
|
||||
Lots of Ash and Ash extensions assume that every resource has a primary key and this is likely to break a lot of features.
|
||||
|
||||
If you run into a breakage please [open an issue](https://github.com/ash-project/ash/issues/new) and we'll take a look at it.
|
||||
|
||||
Disable at your peril.
|
||||
Allow the resource to be used without any primary key fields. Warning: this option is experimental, and should not be used unless you know what you're doing.
|
||||
"""
|
||||
]
|
||||
]
|
||||
|
@ -826,11 +796,7 @@ defmodule Ash.Resource.Dsl do
|
|||
@define_calculation %Spark.Dsl.Entity{
|
||||
name: :define_calculation,
|
||||
describe: """
|
||||
Defines a function with the corresponding name and arguments, that evaluates a calculation.
|
||||
|
||||
Use `:_record` to take an instance of a record.
|
||||
|
||||
See the [code interface guide](/documentation/topics/code-interface.md) for more.
|
||||
Defines a function with the corresponding name and arguments, that evaluates a calculation. Use `:_record` to take an instance of a record. See the [code interface guide](/documentation/topics/code-interface.md) for more.
|
||||
""",
|
||||
examples: [
|
||||
"define_calculation :referral_link, args: [:id]",
|
||||
|
@ -845,9 +811,7 @@ defmodule Ash.Resource.Dsl do
|
|||
@define %Spark.Dsl.Entity{
|
||||
name: :define,
|
||||
describe: """
|
||||
Defines a function with the corresponding name and arguments.
|
||||
|
||||
See the [code interface guide](/documentation/topics/code-interface.md) for more.
|
||||
Defines a function with the corresponding name and arguments. See the [code interface guide](/documentation/topics/code-interface.md) for more.
|
||||
""",
|
||||
examples: [
|
||||
"define :get_user_by_id, action: :get_by_id, args: [:id], get?: true"
|
||||
|
@ -861,9 +825,7 @@ defmodule Ash.Resource.Dsl do
|
|||
@code_interface %Spark.Dsl.Section{
|
||||
name: :code_interface,
|
||||
describe: """
|
||||
Functions that will be defined on the Api module to interact with this resource.
|
||||
|
||||
See the [code interface guide](/documentation/topics/code-interface.md) for more.
|
||||
Functions that will be defined on the Api module to interact with this resource. See the [code interface guide](/documentation/topics/code-interface.md) for more.
|
||||
""",
|
||||
examples: [
|
||||
"""
|
||||
|
@ -1386,21 +1348,7 @@ defmodule Ash.Resource.Dsl do
|
|||
Ash.Resource.Verifiers.EnsureAggregateFieldIsAttributeOrCalculation
|
||||
]
|
||||
|
||||
@moduledoc """
|
||||
The built in resource DSL.
|
||||
<!--- ash-hq-hide-start--> <!--- -->
|
||||
|
||||
## DSL Documentation
|
||||
|
||||
### Index
|
||||
|
||||
#{Spark.Dsl.Extension.doc_index(@sections)}
|
||||
|
||||
### Docs
|
||||
|
||||
#{Spark.Dsl.Extension.doc(@sections)}
|
||||
<!--- ash-hq-hide-stop--> <!--- -->
|
||||
"""
|
||||
@moduledoc false
|
||||
|
||||
use Spark.Dsl.Extension,
|
||||
sections: @sections,
|
||||
|
|
|
@ -25,8 +25,7 @@ defmodule Ash.Resource.Preparation do
|
|||
{:spark_function_behaviour, Ash.Resource.Preparation, Ash.Resource.Preparation.Builtins,
|
||||
{Ash.Resource.Preparation.Function, 2}},
|
||||
doc: """
|
||||
The module and options for a preparation.
|
||||
Also accepts functions take the query and the context.
|
||||
The module and options for a preparation. Also accepts functions take the query and the context.
|
||||
""",
|
||||
required: true
|
||||
]
|
||||
|
|
|
@ -70,8 +70,7 @@ defmodule Ash.Resource.Relationships.HasOne do
|
|||
type: :boolean,
|
||||
default: false,
|
||||
doc: """
|
||||
Set to `true` if this relationship is actually a `has_many` relationship with only a single match.
|
||||
This will allow data layers that do joining under the hood to properly do deduplication when necessary.
|
||||
Signal that this relationship is actually a `has_many` where the first record is given via the `sort`. This will allow data layers to properly deduplicate when necessary.
|
||||
"""
|
||||
]
|
||||
],
|
||||
|
|
|
@ -41,9 +41,7 @@ defmodule Ash.Resource.Relationships.SharedOptions do
|
|||
type: :boolean,
|
||||
default: false,
|
||||
doc: """
|
||||
Whether or not the relationship will appear in any interfaces created off of this resource, e.g AshJsonApi and AshGraphql
|
||||
|
||||
See the [security guide](/documentation/topics/security.md) for more.
|
||||
Whether or not the relationship will appear in any interfaces created off of this resource, e.g AshJsonApi and AshGraphql See the [security guide](/documentation/topics/security.md) for more.
|
||||
"""
|
||||
],
|
||||
not_found_message: [
|
||||
|
@ -99,7 +97,6 @@ defmodule Ash.Resource.Relationships.SharedOptions do
|
|||
type: :string,
|
||||
doc: """
|
||||
A message to show if there is a conflict with this relationship in the database on destroy.
|
||||
For example, if a record is deleted while related records still exist (and aren't configured to cascade deletes)
|
||||
"""
|
||||
]
|
||||
]
|
||||
|
@ -113,23 +110,7 @@ defmodule Ash.Resource.Relationships.SharedOptions do
|
|||
[
|
||||
type: :boolean,
|
||||
doc: """
|
||||
If true, all existing entities are considered related, i.e this relationship is not based on any fields, and `source_attribute` and
|
||||
`destination_attribute` are ignored.
|
||||
|
||||
This can be very useful when combined with multitenancy. Specifically, if you have a tenant resource like `Organization`,
|
||||
you can use `no_attributes?` to do things like `has_many :employees, Employee, no_attributes?: true`, which lets you avoid having an
|
||||
unnecessary `organization_id` field on `Employee`. The same works in reverse: `has_one :organization, Organization, no_attributes?: true`
|
||||
allows relating the employee to their organization.
|
||||
|
||||
Some important caveats here:
|
||||
|
||||
1. You can still manage relationships from one to the other, but "relate" and "unrelate"
|
||||
will have no effect, because there are no fields to change.
|
||||
|
||||
2. Loading the relationship on a list of resources will not behave as expected in all circumstances involving multitenancy. For example,
|
||||
if you get a list of `Organization` and then try to load `employees`, you would need to set a single tenant on the load query, meaning
|
||||
you'll get all organizations back with the set of employees from one tenant. This could eventually be solved, but for now it is considered an
|
||||
edge case.
|
||||
All existing entities are considered related, i.e this relationship is not based on any fields, and `source_attribute` and `destination_attribute` are ignored. See the See the [relationships guide](/documentation/topics/relationships.md) for more.
|
||||
"""
|
||||
]}
|
||||
end
|
||||
|
|
|
@ -62,18 +62,14 @@ defmodule Ash.Resource.Validation do
|
|||
required: false,
|
||||
default: [],
|
||||
doc: """
|
||||
Validations that should pass in order for this validation to apply.
|
||||
These validations failing will not invalidate the changes, but will instead result in this validation being ignored.
|
||||
Accepts a module, module and opts, or a 1 argument function that takes the changeset.
|
||||
Validations that should pass in order for this validation to apply. Any of these validations failing will result in this validation being ignored.
|
||||
"""
|
||||
],
|
||||
on: [
|
||||
type: {:custom, __MODULE__, :on, []},
|
||||
default: [:create, :update],
|
||||
doc: """
|
||||
The action types the validation should run on.
|
||||
|
||||
Many validations don't make sense in the context of deletion, so by default it is left out of the list.
|
||||
The action types the validation should run on. Many validations don't make sense in the context of deletion, so by default it is not included.
|
||||
"""
|
||||
],
|
||||
only_when_valid?: [
|
||||
|
|
|
@ -40,9 +40,13 @@ defmodule Mix.Tasks.Ash.ReplaceDocLinks do
|
|||
">#{contents}<"
|
||||
end)
|
||||
|> String.replace(~r</documentation/.*/.*.md>, fn "/documentation/" <> type_and_name ->
|
||||
[_, filename] = String.split(type_and_name, "/")
|
||||
|
||||
case String.split(type_and_name, "/") do
|
||||
[_, filename] ->
|
||||
filename |> String.trim_trailing(".md") |> Kernel.<>(".html")
|
||||
|
||||
_ ->
|
||||
"/documentation/" <> type_and_name
|
||||
end
|
||||
end)
|
||||
|
||||
File.write!(file, new_contents)
|
||||
|
|
49
mix.exs
49
mix.exs
|
@ -35,14 +35,16 @@ defmodule Ash.MixProject do
|
|||
end
|
||||
|
||||
defp extras do
|
||||
"documentation/**/*.md"
|
||||
"documentation/**/*.{md,livemd,cheatmd}"
|
||||
|> Path.wildcard()
|
||||
|> Enum.map(fn path ->
|
||||
title =
|
||||
path
|
||||
|> Path.basename(".md")
|
||||
|> Path.basename(".livemd")
|
||||
|> Path.basename(".cheatmd")
|
||||
|> String.split(~r/[-_]/)
|
||||
|> Enum.map_join(" ", &String.capitalize/1)
|
||||
|> Enum.map_join(" ", &capitalize/1)
|
||||
|> case do
|
||||
"F A Q" ->
|
||||
"FAQ"
|
||||
|
@ -59,6 +61,15 @@ defmodule Ash.MixProject do
|
|||
end)
|
||||
end
|
||||
|
||||
defp capitalize(string) do
|
||||
string
|
||||
|> String.split(" ")
|
||||
|> Enum.map(fn string ->
|
||||
[hd | tail] = String.graphemes(string)
|
||||
String.capitalize(hd) <> Enum.join(tail)
|
||||
end)
|
||||
end
|
||||
|
||||
defp groups_for_extras do
|
||||
[
|
||||
Tutorials: [
|
||||
|
@ -68,7 +79,8 @@ defmodule Ash.MixProject do
|
|||
~r'documentation/tutorials'
|
||||
],
|
||||
"How To": ~r'documentation/how_to',
|
||||
Topics: ~r'documentation/topics'
|
||||
Topics: ~r'documentation/topics',
|
||||
DSLs: ~r'documentation/dsls'
|
||||
]
|
||||
end
|
||||
|
||||
|
@ -149,18 +161,15 @@ defmodule Ash.MixProject do
|
|||
]
|
||||
],
|
||||
groups_for_modules: [
|
||||
"Extensions & DSLs": [
|
||||
Ash.Api.Dsl,
|
||||
Ash.Resource.Dsl,
|
||||
Ash.Flow.Dsl,
|
||||
Extensions: [
|
||||
Ash.Api,
|
||||
Ash.Resource,
|
||||
Ash.DataLayer.Ets,
|
||||
Ash.DataLayer.Mnesia,
|
||||
Ash.DataLayer.Simple,
|
||||
Ash.Notifier.PubSub,
|
||||
Ash.Policy.Authorizer,
|
||||
Ash.Registry,
|
||||
Ash.Registry.Dsl,
|
||||
Ash.Resource
|
||||
Ash.Registry
|
||||
],
|
||||
Resources: [
|
||||
Ash.Api,
|
||||
|
@ -280,24 +289,23 @@ defmodule Ash.MixProject do
|
|||
[
|
||||
{:spark, "~> 1.1 and >= 1.1.20"},
|
||||
{:ecto, "~> 3.7"},
|
||||
{:ets, "~> 0.8.0"},
|
||||
{:ets, "~> 0.8"},
|
||||
{:decimal, "~> 2.0"},
|
||||
{:picosat_elixir, "~> 0.2"},
|
||||
{:comparable, "~> 1.0"},
|
||||
{:jason, ">= 1.0.0"},
|
||||
{:earmark, "~> 1.4", optional: true},
|
||||
{:stream_data, "~> 0.5.0"},
|
||||
{:stream_data, "~> 0.5"},
|
||||
{:telemetry, "~> 1.1"},
|
||||
{:plug, ">= 0.0.0", optional: true},
|
||||
# Dev/Test dependencies
|
||||
{:ex_doc, "~> 0.22", only: [:dev, :test], runtime: false},
|
||||
{:ex_check, "~> 0.12.0", only: [:dev, :test]},
|
||||
{:ex_check, "~> 0.12", only: [:dev, :test]},
|
||||
{:credo, ">= 0.0.0", only: [:dev, :test], runtime: false},
|
||||
{:dialyxir, ">= 0.0.0", only: [:dev, :test], runtime: false},
|
||||
{:sobelow, ">= 0.0.0", only: [:dev, :test], runtime: false},
|
||||
{:git_ops, "~> 2.5", only: [:dev, :test]},
|
||||
{:mix_test_watch, "~> 1.0", only: [:dev, :test], runtime: false},
|
||||
{:parse_trans, "3.3.0", only: [:dev, :test], override: true},
|
||||
{:benchee, "~> 1.1", only: [:dev, :test]},
|
||||
{:doctor, "~> 0.21", only: [:dev, :test]}
|
||||
]
|
||||
|
@ -307,9 +315,18 @@ defmodule Ash.MixProject do
|
|||
[
|
||||
sobelow: "sobelow --skip",
|
||||
credo: "credo --strict",
|
||||
docs: ["docs", "ash.replace_doc_links"],
|
||||
docs: [
|
||||
"spark.cheat_sheets",
|
||||
"docs",
|
||||
"ash.replace_doc_links",
|
||||
"spark.cheat_sheets_in_search"
|
||||
],
|
||||
"spark.cheat_sheets_in_search":
|
||||
"spark.cheat_sheets_in_search --extensions Ash.Resource.Dsl,Ash.Api.Dsl,Ash.Flow.Dsl,Ash.Registry.Dsl,Ash.DataLayer.Ets,Ash.DataLayer.Mnesia,Ash.Notifier.PubSub,Ash.Policy.Authorizer",
|
||||
"spark.formatter":
|
||||
"spark.formatter --extensions Ash.Resource.Dsl,Ash.Api.Dsl,Ash.Flow.Dsl,Ash.Registry.Dsl,Ash.DataLayer.Ets,Ash.DataLayer.Mnesia,Ash.Notifier.PubSub,Ash.Policy.Authorizer"
|
||||
"spark.formatter --extensions Ash.Resource.Dsl,Ash.Api.Dsl,Ash.Flow.Dsl,Ash.Registry.Dsl,Ash.DataLayer.Ets,Ash.DataLayer.Mnesia,Ash.Notifier.PubSub,Ash.Policy.Authorizer",
|
||||
"spark.cheat_sheets":
|
||||
"spark.cheat_sheets --extensions Ash.Resource.Dsl,Ash.Api.Dsl,Ash.Flow.Dsl,Ash.Registry.Dsl,Ash.DataLayer.Ets,Ash.DataLayer.Mnesia,Ash.Notifier.PubSub,Ash.Policy.Authorizer"
|
||||
]
|
||||
end
|
||||
end
|
||||
|
|
49
mix.lock
49
mix.lock
|
@ -1,40 +1,39 @@
|
|||
%{
|
||||
"benchee": {:hex, :benchee, "1.1.0", "f3a43817209a92a1fade36ef36b86e1052627fd8934a8b937ac9ab3a76c43062", [:mix], [{:deep_merge, "~> 1.0", [hex: :deep_merge, repo: "hexpm", optional: false]}, {:statistex, "~> 1.0", [hex: :statistex, repo: "hexpm", optional: false]}], "hexpm", "7da57d545003165a012b587077f6ba90b89210fd88074ce3c60ce239eb5e6d93"},
|
||||
"bunt": {:hex, :bunt, "0.2.0", "951c6e801e8b1d2cbe58ebbd3e616a869061ddadcc4863d0a2182541acae9a38", [:mix], [], "hexpm", "7af5c7e09fe1d40f76c8e4f9dd2be7cebd83909f31fee7cd0e9eadc567da8353"},
|
||||
"bunt": {:hex, :bunt, "0.2.1", "e2d4792f7bc0ced7583ab54922808919518d0e57ee162901a16a1b6664ef3b14", [:mix], [], "hexpm", "a330bfb4245239787b15005e66ae6845c9cd524a288f0d141c148b02603777a5"},
|
||||
"comparable": {:hex, :comparable, "1.0.0", "bb669e91cedd14ae9937053e5bcbc3c52bb2f22422611f43b6e38367d94a495f", [:mix], [{:typable, "~> 0.1", [hex: :typable, repo: "hexpm", optional: false]}], "hexpm", "277c11eeb1cd726e7cd41c6c199e7e52fa16ee6830b45ad4cdc62e51f62eb60c"},
|
||||
"credo": {:hex, :credo, "1.6.4", "ddd474afb6e8c240313f3a7b0d025cc3213f0d171879429bf8535d7021d9ad78", [:mix], [{:bunt, "~> 0.2.0", [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", "c28f910b61e1ff829bffa056ef7293a8db50e87f2c57a9b5c3f57eee124536b7"},
|
||||
"credo": {:hex, :credo, "1.7.0", "6119bee47272e85995598ee04f2ebbed3e947678dee048d10b5feca139435f75", [: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", "6839fcf63d1f0d1c0f450abc8564a57c43d644077ab96f2934563e68b8a769d7"},
|
||||
"decimal": {:hex, :decimal, "2.1.1", "5611dca5d4b2c3dd497dec8f68751f1f1a54755e8ed2a966c2633cf885973ad6", [:mix], [], "hexpm", "53cfe5f497ed0e7771ae1a475575603d77425099ba5faef9394932b35020ffcc"},
|
||||
"deep_merge": {:hex, :deep_merge, "1.0.0", "b4aa1a0d1acac393bdf38b2291af38cb1d4a52806cf7a4906f718e1feb5ee961", [:mix], [], "hexpm", "ce708e5f094b9cd4e8f2be4f00d2f4250c4095be93f8cd6d018c753894885430"},
|
||||
"dialyxir": {:hex, :dialyxir, "1.2.0", "58344b3e87c2e7095304c81a9ae65cb68b613e28340690dfe1a5597fd08dec37", [:mix], [{:erlex, ">= 0.2.6", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "61072136427a851674cab81762be4dbeae7679f85b1272b6d25c3a839aff8463"},
|
||||
"dialyxir": {:hex, :dialyxir, "1.4.1", "a22ed1e7bd3a3e3f197b68d806ef66acb61ee8f57b3ac85fc5d57354c5482a93", [:mix], [{:erlex, ">= 0.2.6", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "84b795d6d7796297cca5a3118444b80c7d94f7ce247d49886e7c291e1ae49801"},
|
||||
"doctor": {:hex, :doctor, "0.21.0", "20ef89355c67778e206225fe74913e96141c4d001cb04efdeba1a2a9704f1ab5", [:mix], [{:decimal, "~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}], "hexpm", "a227831daa79784eb24cdeedfa403c46a4cb7d0eab0e31232ec654314447e4e0"},
|
||||
"earmark": {:hex, :earmark, "1.4.24", "1923e201c3742af421860b983560967cc3e3deacc59c12966bc991a5435565e6", [:mix], [{:earmark_parser, "~> 1.4.25", [hex: :earmark_parser, repo: "hexpm", optional: false]}], "hexpm", "9724242f241f2ad634756d8f2bb57a3d0992cedd10c51842fa655703b4da7c67"},
|
||||
"earmark_parser": {:hex, :earmark_parser, "1.4.25", "2024618731c55ebfcc5439d756852ec4e85978a39d0d58593763924d9a15916f", [:mix], [], "hexpm", "56749c5e1c59447f7b7a23ddb235e4b3defe276afc220a6227237f3efe83f51e"},
|
||||
"ecto": {:hex, :ecto, "3.10.2", "6b887160281a61aa16843e47735b8a266caa437f80588c3ab80a8a960e6abe37", [: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", "6a895778f0d7648a4b34b486af59a1c8009041fbdf2b17f1ac215eb829c60235"},
|
||||
"elixir_make": {:hex, :elixir_make, "0.6.3", "bc07d53221216838d79e03a8019d0839786703129599e9619f4ab74c8c096eac", [:mix], [], "hexpm", "f5cbd651c5678bcaabdbb7857658ee106b12509cd976c2c2fca99688e1daf716"},
|
||||
"earmark": {:hex, :earmark, "1.4.40", "ff1a0f8bf3b298113c2a257c4e7a8b29ba9db5d35f5ee6d29291cb8caa09a071", [:mix], [{:earmark_parser, "~> 1.4.35", [hex: :earmark_parser, repo: "hexpm", optional: false]}], "hexpm", "5fb622d5e36046bc313a426211e8bf769ba50db7720744859a21932c6470d75c"},
|
||||
"earmark_parser": {:hex, :earmark_parser, "1.4.35", "437773ca9384edf69830e26e9e7b2e0d22d2596c4a6b17094a3b29f01ea65bb8", [:mix], [], "hexpm", "8652ba3cb85608d0d7aa2d21b45c6fad4ddc9a1f9a1f1b30ca3a246f0acc33f6"},
|
||||
"ecto": {:hex, :ecto, "3.10.3", "eb2ae2eecd210b4eb8bece1217b297ad4ff824b4384c0e3fdd28aaf96edd6135", [: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", "44bec74e2364d491d70f7e42cd0d690922659d329f6465e89feb8a34e8cd3433"},
|
||||
"elixir_make": {:hex, :elixir_make, "0.7.7", "7128c60c2476019ed978210c245badf08b03dbec4f24d05790ef791da11aa17c", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}], "hexpm", "5bc19fff950fad52bbe5f211b12db9ec82c6b34a9647da0c2224b8b8464c7e6c"},
|
||||
"erlex": {:hex, :erlex, "0.2.6", "c7987d15e899c7a2f34f5420d2a2ea0d659682c06ac607572df55a43753aa12e", [:mix], [], "hexpm", "2ed2e25711feb44d52b17d2780eabf998452f6efda104877a3881c2f8c0c0c75"},
|
||||
"ets": {:hex, :ets, "0.8.1", "8ff9bcda5682b98493f8878fc9dbd990e48d566cba8cce59f7c2a78130da29ea", [:mix], [], "hexpm", "6be41b50adb5bc5c43626f25ea2d0af1f4a242fb3fad8d53f0c67c20b78915cc"},
|
||||
"ex_check": {:hex, :ex_check, "0.12.0", "c0e2919ecc06afeaf62c52d64f3d91bd4bc7dd8deaac5f84becb6278888c967a", [:mix], [], "hexpm", "cfafa8ef97c2596d45a1f19b5794cb5c7f700f25d164d3c9f8d7ec17ee67cf42"},
|
||||
"ex_doc": {:hex, :ex_doc, "0.28.3", "6eea2f69995f5fba94cd6dd398df369fe4e777a47cd887714a0976930615c9e6", [: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", "05387a6a2655b5f9820f3f627450ed20b4325c25977b2ee69bed90af6688e718"},
|
||||
"ets": {:hex, :ets, "0.9.0", "79c6a6c205436780486f72d84230c6cba2f8a9920456750ddd1e47389107d5fd", [:mix], [], "hexpm", "2861fdfb04bcaeff370f1a5904eec864f0a56dcfebe5921ea9aadf2a481c822b"},
|
||||
"ex_check": {:hex, :ex_check, "0.15.0", "074b94c02de11c37bba1ca82ae5cc4926e6ccee862e57a485b6ba60fca2d8dc1", [:mix], [], "hexpm", "33848031a0c7e4209c3b4369ce154019788b5219956220c35ca5474299fb6a0e"},
|
||||
"ex_doc": {:hex, :ex_doc, "0.30.6", "5f8b54854b240a2b55c9734c4b1d0dd7bdd41f71a095d42a70445c03cf05a281", [:mix], [{:earmark_parser, "~> 1.4.31", [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", "bd48f2ddacf4e482c727f9293d9498e0881597eae6ddc3d9562bd7923375109f"},
|
||||
"file_system": {:hex, :file_system, "0.2.10", "fb082005a9cd1711c05b5248710f8826b02d7d1784e7c3451f9c1231d4fc162d", [:mix], [], "hexpm", "41195edbfb562a593726eda3b3e8b103a309b733ad25f3d642ba49696bf715dc"},
|
||||
"git_cli": {:hex, :git_cli, "0.3.0", "a5422f9b95c99483385b976f5d43f7e8233283a47cda13533d7c16131cb14df5", [:mix], [], "hexpm", "78cb952f4c86a41f4d3511f1d3ecb28edb268e3a7df278de2faa1bd4672eaf9b"},
|
||||
"git_ops": {:hex, :git_ops, "2.5.5", "4f8369f3c9347e06a7f289de98fadfc95194149156335c5292479a53eddbccd2", [:mix], [{:git_cli, "~> 0.2", [hex: :git_cli, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "3b1e3b12968f9da6f79b5e2b2274477206949376e3579d05a5f3d439eda0b746"},
|
||||
"jason": {:hex, :jason, "1.4.0", "e855647bc964a44e2f67df589ccf49105ae039d4179db7f6271dfd3843dc27e6", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "79a3791085b2a0f743ca04cec0f7be26443738779d09302e01318f97bdb82121"},
|
||||
"git_ops": {:hex, :git_ops, "2.6.0", "e0791ee1cf5db03f2c61b7ebd70e2e95cba2bb9b9793011f26609f22c0900087", [:mix], [{:git_cli, "~> 0.2", [hex: :git_cli, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "b98fca849b18aaf490f4ac7d1dd8c6c469b0cc3e6632562d366cab095e666ffe"},
|
||||
"jason": {:hex, :jason, "1.4.1", "af1504e35f629ddcdd6addb3513c3853991f694921b1b9368b0bd32beb9f1b63", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "fbb01ecdfd565b56261302f7e1fcc27c4fb8f32d56eab74db621fc154604a7a1"},
|
||||
"makeup": {:hex, :makeup, "1.1.0", "6b67c8bc2882a6b6a445859952a602afc1a41c2e08379ca057c0f525366fc3ca", [:mix], [{:nimble_parsec, "~> 1.2.2 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "0a45ed501f4a8897f580eabf99a2e5234ea3e75a4373c8a52824f6e873be57a6"},
|
||||
"makeup_elixir": {:hex, :makeup_elixir, "0.16.0", "f8c570a0d33f8039513fbccaf7108c5d750f47d8defd44088371191b76492b0b", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.2.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "28b2cbdc13960a46ae9a8858c4bebdec3c9a6d7b4b9e7f4ed1502f8159f338e7"},
|
||||
"makeup_erlang": {:hex, :makeup_erlang, "0.1.1", "3fcb7f09eb9d98dc4d208f49cc955a34218fc41ff6b84df7c75b3e6e533cc65f", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "174d0809e98a4ef0b3309256cbf97101c6ec01c4ab0b23e926a9e17df2077cbb"},
|
||||
"mime": {:hex, :mime, "2.0.3", "3676436d3d1f7b81b5a2d2bd8405f412c677558c81b1c92be58c00562bb59095", [:mix], [], "hexpm", "27a30bf0db44d25eecba73755acf4068cbfe26a4372f9eb3e4ea3a45956bff6b"},
|
||||
"mix_test_watch": {:hex, :mix_test_watch, "1.1.0", "330bb91c8ed271fe408c42d07e0773340a7938d8a0d281d57a14243eae9dc8c3", [:mix], [{:file_system, "~> 0.2.1 or ~> 0.3", [hex: :file_system, repo: "hexpm", optional: false]}], "hexpm", "52b6b1c476cbb70fd899ca5394506482f12e5f6b0d6acff9df95c7f1e0812ec3"},
|
||||
"makeup_elixir": {:hex, :makeup_elixir, "0.16.1", "cc9e3ca312f1cfeccc572b37a09980287e243648108384b97ff2b76e505c3555", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.2.3 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "e127a341ad1b209bd80f7bd1620a15693a9908ed780c3b763bccf7d200c767c6"},
|
||||
"makeup_erlang": {:hex, :makeup_erlang, "0.1.2", "ad87296a092a46e03b7e9b0be7631ddcf64c790fa68a9ef5323b6cbb36affc72", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "f3f5a1ca93ce6e092d92b6d9c049bcda58a3b617a8d888f8e7231c85630e8108"},
|
||||
"mime": {:hex, :mime, "2.0.5", "dc34c8efd439abe6ae0343edbb8556f4d63f178594894720607772a041b04b02", [:mix], [], "hexpm", "da0d64a365c45bc9935cc5c8a7fc5e49a0e0f9932a761c55d6c52b142780a05c"},
|
||||
"mix_test_watch": {:hex, :mix_test_watch, "1.1.1", "eee6fc570d77ad6851c7bc08de420a47fd1e449ef5ccfa6a77ef68b72e7e51ad", [:mix], [{:file_system, "~> 0.2.1 or ~> 0.3", [hex: :file_system, repo: "hexpm", optional: false]}], "hexpm", "f82262b54dee533467021723892e15c3267349849f1f737526523ecba4e6baae"},
|
||||
"nimble_options": {:hex, :nimble_options, "1.0.2", "92098a74df0072ff37d0c12ace58574d26880e522c22801437151a159392270e", [:mix], [], "hexpm", "fd12a8db2021036ce12a309f26f564ec367373265b53e25403f0ee697380f1b8"},
|
||||
"nimble_parsec": {:hex, :nimble_parsec, "1.2.3", "244836e6e3f1200c7f30cb56733fd808744eca61fd182f731eac4af635cc6d0b", [:mix], [], "hexpm", "c8d789e39b9131acf7b99291e93dae60ab48ef14a7ee9d58c6964f59efb570b0"},
|
||||
"parse_trans": {:hex, :parse_trans, "3.3.0", "09765507a3c7590a784615cfd421d101aec25098d50b89d7aa1d66646bc571c1", [:rebar3], [], "hexpm", "17ef63abde837ad30680ea7f857dd9e7ced9476cdd7b0394432af4bfc241b960"},
|
||||
"picosat_elixir": {:hex, :picosat_elixir, "0.2.0", "1c9d2d65b32039c9e3eb600bff903579e5916f559dbf0013b3c4ca617c93ac64", [:make, :mix], [{:elixir_make, "~> 0.4", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "7900c6d58d65a9d8a2899f53019fb70e9b9678161bbb53f646e28e146aca138c"},
|
||||
"plug": {:hex, :plug, "1.13.6", "187beb6b67c6cec50503e940f0434ea4692b19384d47e5fdfd701e93cadb4cc2", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "02b9c6b9955bce92c829f31d6284bf53c591ca63c4fb9ff81dfd0418667a34ff"},
|
||||
"plug_crypto": {:hex, :plug_crypto, "1.2.3", "8f77d13aeb32bfd9e654cb68f0af517b371fb34c56c9f2b58fe3df1235c1251a", [:mix], [], "hexpm", "b5672099c6ad5c202c45f5a403f21a3411247f164e4a8fab056e5cd8a290f4a2"},
|
||||
"sobelow": {:hex, :sobelow, "0.11.1", "23438964486f8112b41e743bbfd402da3e5b296fdc9eacab29914b79c48916dd", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "9897363a7eff96f4809304a90aad819e2ad5e5d24db547af502885146746a53c"},
|
||||
"sourceror": {:hex, :sourceror, "0.12.3", "a2ad3a1a4554b486d8a113ae7adad5646f938cad99bf8bfcef26dc0c88e8fade", [:mix], [], "hexpm", "4d4e78010ca046524e8194ffc4683422f34a96f6b82901abbb45acc79ace0316"},
|
||||
"spark": {:hex, :spark, "1.1.20", "48f4dd3bed1e16d43a5084a0277f2d8c3adac9bcfa07dfdac9931b025b75480b", [:mix], [{:nimble_options, "~> 0.5 or ~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:sourceror, "~> 0.1", [hex: :sourceror, repo: "hexpm", optional: false]}], "hexpm", "b48d77cdcbc3f00a6e67f447d9860c390f790baf4e7d879d7c6bfd37109c4659"},
|
||||
"nimble_parsec": {:hex, :nimble_parsec, "1.3.1", "2c54013ecf170e249e9291ed0a62e5832f70a476c61da16f6aac6dca0189f2af", [:mix], [], "hexpm", "2682e3c0b2eb58d90c6375fc0cc30bc7be06f365bf72608804fb9cffa5e1b167"},
|
||||
"picosat_elixir": {:hex, :picosat_elixir, "0.2.3", "bf326d0f179fbb3b706bb2c15fbc367dacfa2517157d090fdfc32edae004c597", [:make, :mix], [{:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "f76c9db2dec9d2561ffaa9be35f65403d53e984e8cd99c832383b7ab78c16c66"},
|
||||
"plug": {:hex, :plug, "1.14.2", "cff7d4ec45b4ae176a227acd94a7ab536d9b37b942c8e8fa6dfc0fff98ff4d80", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "842fc50187e13cf4ac3b253d47d9474ed6c296a8732752835ce4a86acdf68d13"},
|
||||
"plug_crypto": {:hex, :plug_crypto, "1.2.5", "918772575e48e81e455818229bf719d4ab4181fcbf7f85b68a35620f78d89ced", [:mix], [], "hexpm", "26549a1d6345e2172eb1c233866756ae44a9609bd33ee6f99147ab3fd87fd842"},
|
||||
"sobelow": {:hex, :sobelow, "0.13.0", "218afe9075904793f5c64b8837cc356e493d88fddde126a463839351870b8d1e", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "cd6e9026b85fc35d7529da14f95e85a078d9dd1907a9097b3ba6ac7ebbe34a0d"},
|
||||
"sourceror": {:hex, :sourceror, "0.13.0", "c6ecc96ee3ae0e042e9082a9550a1989ea40182492dc29024a8d9d2b136e5014", [:mix], [], "hexpm", "d0a819491061cd26bfa4450d1c84301a410c19c1782a6577ce15853fc0e7e4e1"},
|
||||
"spark": {:hex, :spark, "1.1.28", "45be55a6d1cd2da611c4f5bb6fc0b345221800d1c4ab53b5bcfe32703e75facf", [:mix], [{:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}, {:nimble_options, "~> 0.5 or ~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:sourceror, "~> 0.1", [hex: :sourceror, repo: "hexpm", optional: false]}], "hexpm", "0689416ec1abd7189ea4073247ae6959bfad94c12da096c78447667a17613652"},
|
||||
"statistex": {:hex, :statistex, "1.0.0", "f3dc93f3c0c6c92e5f291704cf62b99b553253d7969e9a5fa713e5481cd858a5", [:mix], [], "hexpm", "ff9d8bee7035028ab4742ff52fc80a2aa35cece833cf5319009b52f1b5a86c27"},
|
||||
"stream_data": {:hex, :stream_data, "0.5.0", "b27641e58941685c75b353577dc602c9d2c12292dd84babf506c2033cd97893e", [:mix], [], "hexpm", "012bd2eec069ada4db3411f9115ccafa38540a3c78c4c0349f151fc761b9e271"},
|
||||
"stream_data": {:hex, :stream_data, "0.6.0", "e87a9a79d7ec23d10ff83eb025141ef4915eeb09d4491f79e52f2562b73e5f47", [:mix], [], "hexpm", "b92b5031b650ca480ced047578f1d57ea6dd563f5b57464ad274718c9c29501c"},
|
||||
"telemetry": {:hex, :telemetry, "1.2.1", "68fdfe8d8f05a8428483a97d7aab2f268aaff24b49e0f599faa091f1d4e7f61c", [:rebar3], [], "hexpm", "dad9ce9d8effc621708f99eac538ef1cbe05d6a874dd741de2e689c47feafed5"},
|
||||
"typable": {:hex, :typable, "0.3.0", "0431e121d124cd26f312123e313d2689b9a5322b15add65d424c07779eaa3ca1", [:mix], [], "hexpm", "880a0797752da1a4c508ac48f94711e04c86156f498065a83d160eef945858f8"},
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue