Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/bottleneko/dtrans
Erlang data-transformation and validation micro library
https://github.com/bottleneko/dtrans
data-transformation erlang not-production-ready validation
Last synced: about 1 month ago
JSON representation
Erlang data-transformation and validation micro library
- Host: GitHub
- URL: https://github.com/bottleneko/dtrans
- Owner: bottleneko
- License: mit
- Created: 2018-12-20T19:09:14.000Z (almost 6 years ago)
- Default Branch: master
- Last Pushed: 2018-12-30T14:53:36.000Z (almost 6 years ago)
- Last Synced: 2024-09-30T03:42:11.419Z (about 2 months ago)
- Topics: data-transformation, erlang, not-production-ready, validation
- Language: Erlang
- Homepage:
- Size: 39.1 KB
- Stars: 4
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
dtrans [![Build Status](https://travis-ci.org/bottleneko/dtrans.svg?branch=master)](https://travis-ci.org/bottleneko/dtrans)
=====Data transformation and validation micro library. Not production ready.
Breaking changes is comingTake a wow-effect from coverage
-----```sh
$ rebar3 ct --cover && rebar3 cover --verbose
```# Short documentation
## Field properties
### Internal
Association `internal => true` means that this field be constructed
without input data using only functions with /0 arity and other
from fields values throught tuple:`{depends_on, [other_field_name], fun(OtherFieldValue) -> {ok, 42} end}`
> Note: lambda-function above will be called with validated and constructed values
> Warning: when this property is set as `true` - `required`, `validator`, `default_value` being ignored
```erlang
1> {ok, Model} = dtrans:new(#{
timestamp =>
#{internal => true,
constructor =>
fun() ->
{ok, erlang:apply(erlang, timestamp, [])}
end
}
}).
2> dtrans:extract(#{}, Model).
{ok,#{timestamp => {1545,494367,679728}}}
```> Note: default value of this property is `false`
### Required
Correctly set `required` field give the opportunity checks model
while building in future this will be used in compile-time models
checks```erlang
1> dtrans:new(#{
a =>
#{required => false,
default_value => 0
},
b =>
#{required => false,
default_value => 0
},
sum_of_a_and_b =>
#{internal => true,
required => true,
constructor =>
{depends_on,
[a, b],
fun(A, B) -> {ok, A + B} end}
}
}).
{error,dependency_tree_model_cannot_be_resolved}
```And this field property using while data extracting
```erlang
1> {ok, Model} = dtrans:new(#{
required_field =>
#{required => true}
}).
2> dtrans:extract(#{}, Model).
{error,{no_data,required_field}}
```> Note: default value of this property is `false`
### ValidatorThis field may be set validation lambda-function with /1 arity.
This function should be return `ok` or `{error, Reason :: any()}` values```erlang
1> {ok, Model} = dtrans:new(#{
invalid_field =>
#{validator =>
fun
(42 = _Value) -> ok;
(_Value) -> {error, "Expected value is 42"}
end
}
}).
2> dtrans:extract(#{invalid_field => 43}, Model).
{error,{validation_error,invalid_field,"Expected value is 42"}}
```> Note: default value of this property is constant `ok`
### Default valueDefault value working only for `required => false` not internal fields
```erlang
1> {ok, Model} = dtrans:new(#{
field =>
#{default_value => 0}
}).
2> dtrans:extract(#{}, Model).
{ok,#{field => 0}}
3> dtrans:extract(#{field => 42}, Model).
{ok,#{field => 42}}
``````erlang
1> {ok, Model} = dtrans:new(#{
field => #{}
}).
2> dtrans:extract(#{}, Model).
{ok,#{}}
3> dtrans:extract(#{field => 42}, Model).
{ok,#{field => 42}}
```## Constructor
You can change final value of field throught set property `constructor` by lambda function with /1 arity
or tuple for using other fields values:`{depends_on, [other_field_name], fun(MainFieldValue, OtherFieldValue) -> {ok, 42} end}`
Construction functions must be returns `{ok, Value :: any()}` or `{error, Reason :: any()}` values
> Note: lambda-function above will be called with validated and constructed values
> Warning: by using `depends_on` you may be show `{error, {cyclic_dependency, [...]} while building model`
```erlang
1> {ok, Model} = dtrans:new(#{
field =>
#{constructor =>
fun(Value) ->
{ok, Value + 41}
end
}
}).
2> dtrans:extract(#{field => 1}, Model).
{ok,#{field => 42}}
```> Note: default value of this property is identity function
### Model
With `model` property you can inherit model in other model as field specification
```erlang
1> {ok, InnerModel} = dtrans:new(#{
inner_field => #{}
}).
2> {ok, OuterModel} = dtrans:new(#{
outer_field =>
#{required => true,
model => InnerModel
}
}).
3> dtrans:extract(#{outer_field => #{inner_field => 4}}, OuterModel).
{ok, #{outer_field => #{inner_field => 4}}}
```### Count
While `count` property is set to `one` lists will be processing as one
object, while is set to `many` lists processiong as list of models and
validation/extraction will be called on each element
```erlang
1> {ok, Model} = dtrans:new(#{
field =>
#{count => many,
constructor => fun(Value) -> {ok, Value + 1} end
}
})
2> dtrans:extract(#{field => [1, 2, 3]}, Model).
{ok,#{field => [2,3,4]}}
```> Note: default value of this property is `one`
# TODO
* [ ] Add compile-time build for models where possible
* [ ] Add more information to errors
* [x] Use other model as field spec
* [x] New model field property `model`
* [x] New model field property set count of models