scheming 0.3.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +58 -8
- data/Gemfile.lock +1 -1
- data/README.md +20 -5
- data/lib/scheming/dsl/data_builder.rb +8 -5
- data/lib/scheming/dsl/tagging.rb +47 -0
- data/lib/scheming/dsl.rb +1 -0
- data/lib/scheming/generic.rb +41 -0
- data/lib/scheming/version.rb +1 -1
- data/lib/scheming.rb +4 -0
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b21c99fc59c9fe7da35644b47be93b2d6bba2f13f4ef814008a64c92f2235323
|
4
|
+
data.tar.gz: c0ff8026a852f0b8e4c91bf86aa4a172502a12b3c89dcd693527863dc7cf58aa
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 93fa8e2cd04de2c77495754fe04aa2cbd84070a862835c83ef535a7830b6e41337b401f2e35dbf297434397523e24b50c8cb97063745fe58d61f881114187424
|
7
|
+
data.tar.gz: 61c3cf8462b6d9075e593d00fa76921bbb7958e1ac2590f2a4683ff5c2aeac40b28209e579270eff279cea0261d6d1ea8194a0a87d2ebd3b56f93f8bfc8a2966
|
data/CHANGELOG.md
CHANGED
@@ -1,14 +1,39 @@
|
|
1
1
|
## [Unreleased]
|
2
2
|
|
3
|
-
## [0.
|
3
|
+
## [0.5.0] - 2024-05-02
|
4
4
|
|
5
|
-
|
5
|
+
### Added
|
6
6
|
|
7
|
-
|
7
|
+
- Support for `generic` definitions
|
8
8
|
|
9
|
-
|
9
|
+
# Example
|
10
|
+
```ruby
|
11
|
+
Point = Scheming.generic do |(type)|
|
12
|
+
Object(x: type, y: type)
|
13
|
+
end
|
10
14
|
|
11
|
-
|
15
|
+
Scheming::Schema.json(Point)
|
16
|
+
# =>
|
17
|
+
{
|
18
|
+
type: 'object',
|
19
|
+
additionalProperties: false,
|
20
|
+
required: %i[x y],
|
21
|
+
properties: {
|
22
|
+
x: { type: 'number' },
|
23
|
+
y: { type: 'number' }
|
24
|
+
}
|
25
|
+
}
|
26
|
+
```
|
27
|
+
|
28
|
+
## [0.4.0] - 2024-05-02
|
29
|
+
|
30
|
+
### Breaking Change
|
31
|
+
|
32
|
+
- Opting for a `tag` system to work with attributes instead
|
33
|
+
of a blanket lexical scope like `optional` to work with
|
34
|
+
attributes. The long term goal is to expand out the tagging
|
35
|
+
system so that it can support much more than we can
|
36
|
+
anticipate today.
|
12
37
|
|
13
38
|
# Example:
|
14
39
|
```ruby
|
@@ -18,12 +43,12 @@
|
|
18
43
|
attribute :taxable, :bool
|
19
44
|
attribute :price, Float
|
20
45
|
|
21
|
-
optional
|
22
|
-
|
46
|
+
tag(:optional)
|
23
47
|
attribute :desc, Nullable(String)
|
48
|
+
|
49
|
+
tag(:optional)
|
24
50
|
attribute :item_type, Enum('entertainment', 'staple')
|
25
51
|
end
|
26
|
-
```
|
27
52
|
|
28
53
|
## [0.3.0] - 2024-05-01
|
29
54
|
|
@@ -36,3 +61,28 @@
|
|
36
61
|
### Enhancement
|
37
62
|
|
38
63
|
- Ensure all types produce valid JSON Schema
|
64
|
+
|
65
|
+
## [0.2.0] - 2024-05-01
|
66
|
+
|
67
|
+
### Added
|
68
|
+
|
69
|
+
- Support for `optional` fields
|
70
|
+
|
71
|
+
# Example:
|
72
|
+
```ruby
|
73
|
+
LineItem = Scheming.object do
|
74
|
+
attribute :id, Integer
|
75
|
+
attribute :name, String
|
76
|
+
attribute :taxable, :bool
|
77
|
+
attribute :price, Float
|
78
|
+
|
79
|
+
optional
|
80
|
+
|
81
|
+
attribute :desc, Nullable(String)
|
82
|
+
attribute :item_type, Enum('entertainment', 'staple')
|
83
|
+
end
|
84
|
+
```
|
85
|
+
|
86
|
+
## [0.1.0] - 2024-04-26
|
87
|
+
|
88
|
+
- Initial release
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -20,15 +20,21 @@ LineItem = Scheming.object do
|
|
20
20
|
attribute :taxable, :bool
|
21
21
|
attribute :price, Float
|
22
22
|
|
23
|
-
optional
|
24
|
-
|
23
|
+
tag(:optional)
|
25
24
|
attribute :desc, Nullable(String)
|
25
|
+
|
26
|
+
tag(:optional)
|
26
27
|
attribute :item_type, Enum('entertainment', 'staple')
|
27
28
|
end
|
28
29
|
|
30
|
+
Point = Scheming.generic do |(type)|
|
31
|
+
Object(x: type, y: type)
|
32
|
+
end
|
33
|
+
|
29
34
|
Receipt = Scheming.object do
|
30
35
|
attribute :line_items, Array(LineItem)
|
31
36
|
attribute :total, Float
|
37
|
+
attribute :location, Point[Float]
|
32
38
|
end
|
33
39
|
```
|
34
40
|
|
@@ -39,7 +45,7 @@ Scheming::Schema.json(Receipt)
|
|
39
45
|
{
|
40
46
|
type: 'object',
|
41
47
|
additionalProperties: false,
|
42
|
-
required: %i[line_items total],
|
48
|
+
required: %i[line_items total location],
|
43
49
|
properties: {
|
44
50
|
line_items: {
|
45
51
|
type: 'array',
|
@@ -60,12 +66,21 @@ Scheming::Schema.json(Receipt)
|
|
60
66
|
price: { type: 'number' },
|
61
67
|
item_type: {
|
62
68
|
type: 'string',
|
63
|
-
enum: [
|
69
|
+
enum: %w[entertainment staple]
|
64
70
|
}
|
65
71
|
}
|
66
72
|
}
|
67
73
|
},
|
68
|
-
total: { type: 'number' }
|
74
|
+
total: { type: 'number' },
|
75
|
+
location: {
|
76
|
+
type: 'object',
|
77
|
+
additionalProperties: false,
|
78
|
+
required: %i[x y],
|
79
|
+
properties: {
|
80
|
+
x: { type: 'number' },
|
81
|
+
y: { type: 'number' }
|
82
|
+
}
|
83
|
+
}
|
69
84
|
}
|
70
85
|
}
|
71
86
|
```
|
@@ -7,7 +7,7 @@ class Scheming::DSL::DataBuilder
|
|
7
7
|
def initialize(builder = Scheming::Attribute::ListBuilder.new)
|
8
8
|
@builder = builder
|
9
9
|
@resolver = Scheming::DSL::TypeResolver
|
10
|
-
@
|
10
|
+
@tagging = Scheming::DSL::Tagging.new
|
11
11
|
end
|
12
12
|
|
13
13
|
# @param field_name [Symbol]
|
@@ -18,14 +18,17 @@ class Scheming::DSL::DataBuilder
|
|
18
18
|
@builder = @builder.attribute(
|
19
19
|
field_name,
|
20
20
|
type: @resolver.resolve(type_spec),
|
21
|
-
|
21
|
+
**@tagging.attribute_params
|
22
22
|
)
|
23
|
+
@tagging.reset!
|
23
24
|
nil
|
24
25
|
end
|
25
26
|
|
26
|
-
#
|
27
|
-
|
28
|
-
|
27
|
+
# @param name [Symbol]
|
28
|
+
# @param args [Hash<Symbol, Object>]
|
29
|
+
def tag(name, **args)
|
30
|
+
@tagging.tag!(name, args)
|
31
|
+
nil
|
29
32
|
end
|
30
33
|
|
31
34
|
# @return [Class]
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# = Type Resolver
|
4
|
+
class Scheming::DSL::Tagging
|
5
|
+
# = Attribute Tag
|
6
|
+
#
|
7
|
+
# Simple representation of a concept
|
8
|
+
# that can be used to aid in the
|
9
|
+
# creation of an [Scheming::Attribute]
|
10
|
+
#
|
11
|
+
class Tag
|
12
|
+
# @param name [Symbo]
|
13
|
+
# @data [Hash<Symbol, Object>]
|
14
|
+
def initialize(name, data)
|
15
|
+
@name = name
|
16
|
+
@data = data
|
17
|
+
end
|
18
|
+
end
|
19
|
+
private_constant :Tag
|
20
|
+
|
21
|
+
def initialize
|
22
|
+
# @type [Hash<Symbol, Tag>]
|
23
|
+
@tags = {}
|
24
|
+
end
|
25
|
+
|
26
|
+
# @return [void]
|
27
|
+
def reset!
|
28
|
+
@tags.clear
|
29
|
+
nil
|
30
|
+
end
|
31
|
+
|
32
|
+
# @param taglist [Hash<Symbol, Object>]
|
33
|
+
# @param name [Symbol]
|
34
|
+
# @return [Tag]
|
35
|
+
def tag!(name, data)
|
36
|
+
@tags[name] = Tag.new(name, data)
|
37
|
+
end
|
38
|
+
|
39
|
+
def attribute_params
|
40
|
+
{
|
41
|
+
is_required: missing?(:optional)
|
42
|
+
}
|
43
|
+
end
|
44
|
+
|
45
|
+
def missing?(name) = !has?(name)
|
46
|
+
def has?(name) = @tags.key?(name)
|
47
|
+
end
|
data/lib/scheming/dsl.rb
CHANGED
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# = Generic
|
4
|
+
#
|
5
|
+
# Many types can be "templated" in a way where
|
6
|
+
# some types get swapped in and out. Perhaps
|
7
|
+
# the most common example for this is with a
|
8
|
+
# two dimensional `Point` structure. We could
|
9
|
+
# have a point with `Float` coordinates OR they
|
10
|
+
# could also be `Integer`:
|
11
|
+
#
|
12
|
+
# ```ruby
|
13
|
+
# Object(x: Float, y: Float)
|
14
|
+
# Object(x: Integer, y: Integer)
|
15
|
+
# ```
|
16
|
+
#
|
17
|
+
# Instead of having two defintions we can have
|
18
|
+
# a single generic that defins both:
|
19
|
+
#
|
20
|
+
# ```ruby
|
21
|
+
# Point = Scheming::Generic.new do |(t)|
|
22
|
+
# Object(x: t, y: t)
|
23
|
+
# end
|
24
|
+
#
|
25
|
+
# Point[Float]
|
26
|
+
#
|
27
|
+
# Point[Integer]
|
28
|
+
# ```
|
29
|
+
#
|
30
|
+
class Scheming::Generic
|
31
|
+
def initialize(&proto_type)
|
32
|
+
@proto_type = proto_type
|
33
|
+
end
|
34
|
+
|
35
|
+
# @param types [Scheming::Type::Base]
|
36
|
+
def [](*types)
|
37
|
+
Scheming::DSL::DataBuilder
|
38
|
+
.new
|
39
|
+
.instance_exec(types, &@proto_type)
|
40
|
+
end
|
41
|
+
end
|
data/lib/scheming/version.rb
CHANGED
data/lib/scheming.rb
CHANGED
@@ -10,6 +10,7 @@ module Scheming
|
|
10
10
|
require_relative 'scheming/attribute'
|
11
11
|
require_relative 'scheming/type'
|
12
12
|
require_relative 'scheming/schema'
|
13
|
+
require_relative 'scheming/generic'
|
13
14
|
require_relative 'scheming/dsl'
|
14
15
|
|
15
16
|
# @return [Class]
|
@@ -18,4 +19,7 @@ module Scheming
|
|
18
19
|
builder.instance_exec(&)
|
19
20
|
builder.build
|
20
21
|
end
|
22
|
+
|
23
|
+
# @return [Scheming::Generic]
|
24
|
+
def self.generic(&) = Scheming::Generic.new(&)
|
21
25
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: scheming
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ben Falk
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-05-
|
11
|
+
date: 2024-05-03 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: Ergonomic Data Design for the Masses
|
14
14
|
email:
|
@@ -32,8 +32,10 @@ files:
|
|
32
32
|
- lib/scheming/dsl.rb
|
33
33
|
- lib/scheming/dsl/data_builder.rb
|
34
34
|
- lib/scheming/dsl/object_type_def.rb
|
35
|
+
- lib/scheming/dsl/tagging.rb
|
35
36
|
- lib/scheming/dsl/type_resolver.rb
|
36
37
|
- lib/scheming/dsl/type_specs.rb
|
38
|
+
- lib/scheming/generic.rb
|
37
39
|
- lib/scheming/schema.rb
|
38
40
|
- lib/scheming/schema/json.rb
|
39
41
|
- lib/scheming/type.rb
|