sober_swag 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.github/workflows/ruby.yml +33 -0
- data/.gitignore +11 -0
- data/.rspec +3 -0
- data/.rubocop.yml +7 -0
- data/.ruby-version +1 -0
- data/.travis.yml +7 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +92 -0
- data/LICENSE.txt +21 -0
- data/README.md +7 -0
- data/Rakefile +8 -0
- data/bin/console +38 -0
- data/bin/setup +8 -0
- data/example/.gitignore +24 -0
- data/example/.ruby-version +1 -0
- data/example/Gemfile +42 -0
- data/example/Gemfile.lock +212 -0
- data/example/README.md +24 -0
- data/example/Rakefile +6 -0
- data/example/app/controllers/application_controller.rb +2 -0
- data/example/app/controllers/concerns/.keep +0 -0
- data/example/app/controllers/people_controller.rb +74 -0
- data/example/app/jobs/application_job.rb +7 -0
- data/example/app/models/application_record.rb +3 -0
- data/example/app/models/concerns/.keep +0 -0
- data/example/app/models/person.rb +2 -0
- data/example/bin/bundle +114 -0
- data/example/bin/rails +9 -0
- data/example/bin/rake +9 -0
- data/example/bin/setup +33 -0
- data/example/bin/spring +17 -0
- data/example/config/application.rb +37 -0
- data/example/config/boot.rb +4 -0
- data/example/config/credentials.yml.enc +1 -0
- data/example/config/database.yml +25 -0
- data/example/config/environment.rb +5 -0
- data/example/config/environments/development.rb +44 -0
- data/example/config/environments/production.rb +91 -0
- data/example/config/environments/test.rb +38 -0
- data/example/config/initializers/application_controller_renderer.rb +8 -0
- data/example/config/initializers/backtrace_silencers.rb +7 -0
- data/example/config/initializers/cors.rb +16 -0
- data/example/config/initializers/filter_parameter_logging.rb +4 -0
- data/example/config/initializers/inflections.rb +16 -0
- data/example/config/initializers/mime_types.rb +4 -0
- data/example/config/initializers/wrap_parameters.rb +14 -0
- data/example/config/locales/en.yml +33 -0
- data/example/config/puma.rb +38 -0
- data/example/config/routes.rb +6 -0
- data/example/config/spring.rb +6 -0
- data/example/config.ru +5 -0
- data/example/db/migrate/20200311152021_create_people.rb +12 -0
- data/example/db/schema.rb +23 -0
- data/example/db/seeds.rb +7 -0
- data/example/lib/tasks/.keep +0 -0
- data/example/log/.keep +0 -0
- data/example/person.json +4 -0
- data/example/public/robots.txt +1 -0
- data/example/test/controllers/.keep +0 -0
- data/example/test/fixtures/.keep +0 -0
- data/example/test/fixtures/files/.keep +0 -0
- data/example/test/fixtures/people.yml +11 -0
- data/example/test/integration/.keep +0 -0
- data/example/test/models/.keep +0 -0
- data/example/test/models/person_test.rb +7 -0
- data/example/test/test_helper.rb +13 -0
- data/example/tmp/.keep +0 -0
- data/example/vendor/.keep +0 -0
- data/lib/sober_swag/blueprint/field.rb +36 -0
- data/lib/sober_swag/blueprint/field_syntax.rb +17 -0
- data/lib/sober_swag/blueprint/view.rb +44 -0
- data/lib/sober_swag/blueprint.rb +113 -0
- data/lib/sober_swag/compiler/error.rb +5 -0
- data/lib/sober_swag/compiler/path.rb +80 -0
- data/lib/sober_swag/compiler/paths.rb +54 -0
- data/lib/sober_swag/compiler/type.rb +235 -0
- data/lib/sober_swag/compiler.rb +107 -0
- data/lib/sober_swag/controller/route.rb +136 -0
- data/lib/sober_swag/controller/undefined_body_error.rb +6 -0
- data/lib/sober_swag/controller/undefined_path_error.rb +6 -0
- data/lib/sober_swag/controller/undefined_query_error.rb +6 -0
- data/lib/sober_swag/controller.rb +157 -0
- data/lib/sober_swag/nodes/array.rb +30 -0
- data/lib/sober_swag/nodes/attribute.rb +31 -0
- data/lib/sober_swag/nodes/base.rb +51 -0
- data/lib/sober_swag/nodes/binary.rb +44 -0
- data/lib/sober_swag/nodes/enum.rb +28 -0
- data/lib/sober_swag/nodes/list.rb +40 -0
- data/lib/sober_swag/nodes/nullable_primitive.rb +6 -0
- data/lib/sober_swag/nodes/object.rb +12 -0
- data/lib/sober_swag/nodes/one_of.rb +12 -0
- data/lib/sober_swag/nodes/primitive.rb +29 -0
- data/lib/sober_swag/nodes/sum.rb +6 -0
- data/lib/sober_swag/nodes.rb +20 -0
- data/lib/sober_swag/parser.rb +73 -0
- data/lib/sober_swag/path/integer.rb +21 -0
- data/lib/sober_swag/path/lit.rb +41 -0
- data/lib/sober_swag/path/literal.rb +29 -0
- data/lib/sober_swag/path/param.rb +33 -0
- data/lib/sober_swag/path.rb +8 -0
- data/lib/sober_swag/serializer/array.rb +21 -0
- data/lib/sober_swag/serializer/base.rb +38 -0
- data/lib/sober_swag/serializer/conditional.rb +49 -0
- data/lib/sober_swag/serializer/field_list.rb +44 -0
- data/lib/sober_swag/serializer/mapped.rb +29 -0
- data/lib/sober_swag/serializer/optional.rb +29 -0
- data/lib/sober_swag/serializer/primitive.rb +15 -0
- data/lib/sober_swag/serializer.rb +23 -0
- data/lib/sober_swag/types.rb +5 -0
- data/lib/sober_swag/version.rb +5 -0
- data/lib/sober_swag.rb +29 -0
- data/sober_swag.gemspec +40 -0
- metadata +269 -0
@@ -0,0 +1,29 @@
|
|
1
|
+
module SoberSwag
|
2
|
+
module Nodes
|
3
|
+
##
|
4
|
+
# Root node of the tree
|
5
|
+
class Primitive < Base
|
6
|
+
def initialize(value)
|
7
|
+
@value = value
|
8
|
+
end
|
9
|
+
|
10
|
+
attr_reader :value
|
11
|
+
|
12
|
+
def map(&block)
|
13
|
+
self.class.new(block.call(value))
|
14
|
+
end
|
15
|
+
|
16
|
+
def deconstruct
|
17
|
+
[value]
|
18
|
+
end
|
19
|
+
|
20
|
+
def deconstruct_keys(_)
|
21
|
+
{ value: value }
|
22
|
+
end
|
23
|
+
|
24
|
+
def cata(&block)
|
25
|
+
block.call(self.class.new(value))
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module SoberSwag
|
2
|
+
##
|
3
|
+
# Base namespace for all nodes.
|
4
|
+
# These nodes are compiled into an actual swagger definition
|
5
|
+
# via a catamorphism, which I promise is not nearly as scary as it sounds.
|
6
|
+
# Sort of.
|
7
|
+
module Nodes
|
8
|
+
autoload :Base, 'sober_swag/nodes/base'
|
9
|
+
autoload :Enum, 'sober_swag/nodes/enum'
|
10
|
+
autoload :Binary, 'sober_swag/nodes/binary'
|
11
|
+
autoload :Primitive, 'sober_swag/nodes/primitive'
|
12
|
+
autoload :NullablePrimitive, 'sober_swag/nodes/nullable_primitive'
|
13
|
+
autoload :Sum, 'sober_swag/nodes/sum'
|
14
|
+
autoload :Array, 'sober_swag/nodes/array'
|
15
|
+
autoload :Object, 'sober_swag/nodes/object'
|
16
|
+
autoload :Attribute, 'sober_swag/nodes/attribute'
|
17
|
+
autoload :OneOf, 'sober_swag/nodes/one_of'
|
18
|
+
autoload :List, 'sober_swag/nodes/list'
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
module SoberSwag
|
2
|
+
class Parser
|
3
|
+
def initialize(node)
|
4
|
+
@node = node
|
5
|
+
@found = Set.new
|
6
|
+
end
|
7
|
+
|
8
|
+
def to_syntax
|
9
|
+
case @node
|
10
|
+
when Dry::Types::Array::Member
|
11
|
+
Nodes::List.new(bind(Parser.new(@node.member)))
|
12
|
+
when Dry::Types::Enum
|
13
|
+
Nodes::Enum.new(@node.values)
|
14
|
+
when Dry::Types::Schema
|
15
|
+
Nodes::Object.new(
|
16
|
+
@node.map { |attr| bind(Parser.new(attr)) }
|
17
|
+
)
|
18
|
+
when Dry::Types::Schema::Key
|
19
|
+
Nodes::Attribute.new(
|
20
|
+
@node.name,
|
21
|
+
@node.required?,
|
22
|
+
bind(Parser.new(@node.type))
|
23
|
+
)
|
24
|
+
when Dry::Types::Sum
|
25
|
+
left = bind(Parser.new(@node.left))
|
26
|
+
right = bind(Parser.new(@node.right))
|
27
|
+
# special case booleans to just return the left value
|
28
|
+
# this is because modeling a boolean as a sum type of
|
29
|
+
# TrueClass and FalseClass is kinda weird, because they're
|
30
|
+
# considered different types instead of different constructors,
|
31
|
+
# which we don't want to do
|
32
|
+
is_bool = [left, right].all? do |e|
|
33
|
+
e.respond_to?(:value) && [TrueClass, FalseClass].include?(e.value)
|
34
|
+
end
|
35
|
+
if is_bool
|
36
|
+
left
|
37
|
+
else
|
38
|
+
Nodes::Sum.new(left, right)
|
39
|
+
end
|
40
|
+
when Dry::Types::Constrained
|
41
|
+
bind(Parser.new(@node.type))
|
42
|
+
when Dry::Types::Nominal
|
43
|
+
# start off with the moral equivalent of NodeTree[String]
|
44
|
+
Nodes::Primitive.new(@node.primitive)
|
45
|
+
else
|
46
|
+
# Inside of this case we have a class that is some user-defined type
|
47
|
+
# We put it in our array of found types, and consider it a primitive
|
48
|
+
@found.add(@node)
|
49
|
+
Nodes::Primitive.new(@node)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def run_parser
|
54
|
+
[to_syntax, found]
|
55
|
+
end
|
56
|
+
|
57
|
+
##
|
58
|
+
# What other types did we find while parsing this type?
|
59
|
+
attr_reader :found
|
60
|
+
|
61
|
+
##
|
62
|
+
# Call `.to_syntax` on another node, putting any new classes it finds
|
63
|
+
# in the list of classes we found in the process.
|
64
|
+
#
|
65
|
+
# If you're a big Haskell nerd, then this is >>=.
|
66
|
+
def bind(other)
|
67
|
+
result = other.to_syntax
|
68
|
+
@found += other.found
|
69
|
+
result
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module SoberSwag
|
2
|
+
class Path
|
3
|
+
class Lit
|
4
|
+
##
|
5
|
+
# Parse a literal path fragment
|
6
|
+
def initialize(lit)
|
7
|
+
@lit = lit
|
8
|
+
end
|
9
|
+
|
10
|
+
attr_reader :lit
|
11
|
+
|
12
|
+
def param?
|
13
|
+
false
|
14
|
+
end
|
15
|
+
|
16
|
+
def param_type
|
17
|
+
nil
|
18
|
+
end
|
19
|
+
|
20
|
+
def param_key
|
21
|
+
nil
|
22
|
+
end
|
23
|
+
|
24
|
+
##
|
25
|
+
# Constant to avoid a bunch of array allocation
|
26
|
+
MATCH_SUCC = [:match, nil].freeze
|
27
|
+
##
|
28
|
+
# Constant to avoid a bunch of array allocation
|
29
|
+
MATHC_FAIL = [:fail].freeze
|
30
|
+
|
31
|
+
def match(param)
|
32
|
+
if param == lit
|
33
|
+
MATCH_SUCC
|
34
|
+
else
|
35
|
+
MATCH_FAIL
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module SoberSwag
|
2
|
+
module Path
|
3
|
+
##
|
4
|
+
# One literal text fragment, basically
|
5
|
+
class Literal < Node
|
6
|
+
##
|
7
|
+
# Make a new text node
|
8
|
+
# @param text [String]
|
9
|
+
def initialize(text)
|
10
|
+
@text = text
|
11
|
+
end
|
12
|
+
|
13
|
+
attr_reader :text
|
14
|
+
|
15
|
+
##
|
16
|
+
# We can make a jump table out of this node!
|
17
|
+
def jumpable?
|
18
|
+
true
|
19
|
+
end
|
20
|
+
|
21
|
+
##
|
22
|
+
# This doesn't read a parameter type.
|
23
|
+
def param?
|
24
|
+
false
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module SoberSwag
|
2
|
+
class Path
|
3
|
+
##
|
4
|
+
# Parse a parameter
|
5
|
+
class Param
|
6
|
+
def initialize(name, type)
|
7
|
+
@name = name
|
8
|
+
@type = type
|
9
|
+
end
|
10
|
+
|
11
|
+
def param?
|
12
|
+
true
|
13
|
+
end
|
14
|
+
|
15
|
+
def param_key
|
16
|
+
@name
|
17
|
+
end
|
18
|
+
|
19
|
+
def param_type
|
20
|
+
@type
|
21
|
+
end
|
22
|
+
|
23
|
+
def match(param)
|
24
|
+
if (m = @type.try(param)).success?
|
25
|
+
[:match, m]
|
26
|
+
else
|
27
|
+
[:fail]
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module SoberSwag
|
2
|
+
module Serializer
|
3
|
+
##
|
4
|
+
# Make a serialize of arrays out of a serializer of the elements
|
5
|
+
class Array < Base
|
6
|
+
def initialize(element_serializer)
|
7
|
+
@element_serializer = element_serializer
|
8
|
+
end
|
9
|
+
|
10
|
+
attr_reader :element_serializer
|
11
|
+
|
12
|
+
def serialize(object, options = {})
|
13
|
+
object.map { |a| element_serializer.serialize(a, options) }
|
14
|
+
end
|
15
|
+
|
16
|
+
def type
|
17
|
+
SoberSwag::Types::Array.of(element_serializer.type)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module SoberSwag
|
2
|
+
module Serializer
|
3
|
+
class Base
|
4
|
+
|
5
|
+
##
|
6
|
+
# Return a new serializer that is an *array* of elements of this serializer.
|
7
|
+
def array
|
8
|
+
SoberSwag::Serializer::Array.new(self)
|
9
|
+
end
|
10
|
+
|
11
|
+
##
|
12
|
+
# Returns a serializer that will pass `nil` values on unscathed
|
13
|
+
def optional
|
14
|
+
SoberSwag::Serializer::Optional.new(self)
|
15
|
+
end
|
16
|
+
|
17
|
+
##
|
18
|
+
# If I am a serializer for type 'a', and you give me a way to turn 'a's into 'b's,
|
19
|
+
# I can give you a serializer for type 'b' by running the funciton you gave.
|
20
|
+
# For example, if I am a serializer for {String}, and you know how to turn
|
21
|
+
# an {Int} into a {String}, I can now serialize {Int}s (by turning them into a string).
|
22
|
+
#
|
23
|
+
# Note that the *declared* type of this is *not* changed: from a user's perspective,
|
24
|
+
# they see a "string"
|
25
|
+
def via_map(&block)
|
26
|
+
SoberSwag::Serializer::Mapped.new(self, block)
|
27
|
+
end
|
28
|
+
|
29
|
+
##
|
30
|
+
# Serializer lets you get a serializer from things that might be classes
|
31
|
+
# because of the blueprint naming hack.
|
32
|
+
def serializer
|
33
|
+
self
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module SoberSwag
|
2
|
+
module Serializer
|
3
|
+
##
|
4
|
+
# Conditionally serialize one thing *or* the other thing via deciding on a condition.
|
5
|
+
# This works by taking three elements: a "decision" proc, a "left" serializer, and a "right" serializer.
|
6
|
+
# The decision proc takes in both the object to be serialized *and* the options hash, and returns a
|
7
|
+
# `[:left, val]` object, or a `[:right, val]` object, which
|
8
|
+
# then get passed on to the appropriate serializer.
|
9
|
+
#
|
10
|
+
# This is a very weird, not-very-Ruby-like abstraction, *upon which* we can build abstractions that are actually use for users.
|
11
|
+
# It lets you build abstractions like "Use this serializer if a type has this class, otherwise use this other one."
|
12
|
+
# When composed together, you can make arbitrary decision trees.
|
13
|
+
class Conditional < Base
|
14
|
+
##
|
15
|
+
# Error thrown when a chooser proc returns a non left-or-right value.
|
16
|
+
class BadChoiceError < Error; end
|
17
|
+
|
18
|
+
def initialize(chooser, left, right)
|
19
|
+
@chooser = chooser
|
20
|
+
@left = left
|
21
|
+
@right = right
|
22
|
+
end
|
23
|
+
|
24
|
+
attr_reader :chooser, :left, :right
|
25
|
+
|
26
|
+
def serialize(object, options = {})
|
27
|
+
tag, val = chooser.call(object, options)
|
28
|
+
if tag == :left
|
29
|
+
left.serialize(val, options)
|
30
|
+
elsif tag == :right
|
31
|
+
right.serialize(val, options)
|
32
|
+
else
|
33
|
+
raise BadChoiceError, "result of chooser proc was not a left or right, but a #{val.class}"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
##
|
38
|
+
# Since this could potentially serialize one of two alternatives,
|
39
|
+
# the "type" we serialize two is *either* one alternative or the other.
|
40
|
+
def type
|
41
|
+
if left.type == right.type
|
42
|
+
left.type
|
43
|
+
else
|
44
|
+
left.type | right.type
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module SoberSwag
|
2
|
+
module Serializer
|
3
|
+
##
|
4
|
+
# Extract out a hash from a list of
|
5
|
+
# name/serializer pairs.
|
6
|
+
class FieldList < Base
|
7
|
+
|
8
|
+
def initialize(field_list)
|
9
|
+
@field_list = field_list
|
10
|
+
end
|
11
|
+
|
12
|
+
attr_reader :field_list
|
13
|
+
|
14
|
+
##
|
15
|
+
# Alias to make writing primitive stuff much easier
|
16
|
+
def primitive(symbol)
|
17
|
+
SoberSwag::Serializer.Primitive(SoberSwag::Types.const_get(symbol))
|
18
|
+
end
|
19
|
+
|
20
|
+
|
21
|
+
def serialize(object, options)
|
22
|
+
field_list.map { |field|
|
23
|
+
[field.name, field.serializer.serialize(object, options)]
|
24
|
+
}.to_h
|
25
|
+
end
|
26
|
+
|
27
|
+
def type
|
28
|
+
@type ||= make_struct_type!
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def make_struct_type!
|
34
|
+
f = field_list
|
35
|
+
Class.new(Dry::Struct) do
|
36
|
+
f.each do |field|
|
37
|
+
attribute field.name, field.serializer.type
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module SoberSwag
|
2
|
+
module Serializer
|
3
|
+
##
|
4
|
+
# A new serializer by mapping over the serialization function
|
5
|
+
class Mapped < Base
|
6
|
+
|
7
|
+
def initialize(base, map_f)
|
8
|
+
@base = base
|
9
|
+
@map_f = map_f
|
10
|
+
end
|
11
|
+
|
12
|
+
def serialize(object, options)
|
13
|
+
@base.serialize(@map_f.call(object), options)
|
14
|
+
end
|
15
|
+
|
16
|
+
def type
|
17
|
+
@base.type
|
18
|
+
end
|
19
|
+
|
20
|
+
##
|
21
|
+
# I have no freaking clue if ruby optimizes proc composition,
|
22
|
+
# but we at least save some node traversals here
|
23
|
+
def via_map(&block)
|
24
|
+
SoberSwag::Serializer::Mapped.new(@base, @map_f >> block)
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module SoberSwag
|
2
|
+
module Serializer
|
3
|
+
class Optional < Base
|
4
|
+
|
5
|
+
def initialize(inner)
|
6
|
+
@inner = inner
|
7
|
+
end
|
8
|
+
|
9
|
+
attr_reader :inner
|
10
|
+
|
11
|
+
def serialize(object, options = {})
|
12
|
+
if object.nil?
|
13
|
+
object
|
14
|
+
else
|
15
|
+
inner.serialize(object, options)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def type
|
20
|
+
inner.type.optional
|
21
|
+
end
|
22
|
+
|
23
|
+
def optional(*)
|
24
|
+
raise ArgumentError, 'no nesting optionals please'
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module SoberSwag
|
2
|
+
module Serializer
|
3
|
+
autoload(:Base, 'sober_swag/serializer/base')
|
4
|
+
autoload(:Primitive, 'sober_swag/serializer/primitive')
|
5
|
+
autoload(:Conditional, 'sober_swag/serializer/conditional')
|
6
|
+
autoload(:Array, 'sober_swag/serializer/array')
|
7
|
+
autoload(:Mapped, 'sober_swag/serializer/mapped')
|
8
|
+
autoload(:Optional, 'sober_swag/serializer/optional')
|
9
|
+
autoload(:FieldList, 'sober_swag/serializer/field_list')
|
10
|
+
|
11
|
+
class << self
|
12
|
+
##
|
13
|
+
# Use a "Primitive" serializer, which *does not* actually do any type-changing, and instead passes
|
14
|
+
# in values raw.
|
15
|
+
#
|
16
|
+
# @param contained {Class} Dry::Type to use
|
17
|
+
def Primitive(contained)
|
18
|
+
SoberSwag::Serializer::Primitive.new(contained)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
data/lib/sober_swag.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bundler'
|
4
|
+
Bundler.setup
|
5
|
+
require 'dry-struct'
|
6
|
+
require 'dry-types'
|
7
|
+
require 'sober_swag/types'
|
8
|
+
require 'sober_swag/version'
|
9
|
+
require 'active_support/inflector'
|
10
|
+
|
11
|
+
##
|
12
|
+
# Root namespace
|
13
|
+
module SoberSwag
|
14
|
+
class Error < StandardError; end
|
15
|
+
|
16
|
+
autoload :Parser, 'sober_swag/parser'
|
17
|
+
autoload :Serializer, 'sober_swag/serializer'
|
18
|
+
autoload :Blueprint, 'sober_swag/blueprint'
|
19
|
+
autoload :Nodes, 'sober_swag/nodes'
|
20
|
+
autoload :Compiler, 'sober_swag/compiler'
|
21
|
+
autoload :Controller, 'sober_swag/controller'
|
22
|
+
|
23
|
+
##
|
24
|
+
# Define a struct of something.
|
25
|
+
# Useful to prevent weirdness from autoloading.
|
26
|
+
def self.struct(parent = Dry::Struct, &block)
|
27
|
+
Class.new(parent, &block)
|
28
|
+
end
|
29
|
+
end
|
data/sober_swag.gemspec
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
lib = File.expand_path('lib', __dir__)
|
4
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
5
|
+
require 'sober_swag/version'
|
6
|
+
|
7
|
+
Gem::Specification.new do |spec|
|
8
|
+
spec.name = 'sober_swag'
|
9
|
+
spec.version = SoberSwag::VERSION
|
10
|
+
spec.authors = ['Anthony Super']
|
11
|
+
spec.email = ['asuper@sondermind.com']
|
12
|
+
|
13
|
+
spec.summary = 'Generate swagger types from dry-types'
|
14
|
+
spec.description = 'Parse data, don\'t write docs'
|
15
|
+
spec.homepage = 'https://github.com/SonderMindOrg/sober_swag'
|
16
|
+
spec.license = 'MIT'
|
17
|
+
|
18
|
+
spec.metadata['allowed_push_host'] = "https://rubygems.org"
|
19
|
+
|
20
|
+
spec.metadata['homepage_uri'] = spec.homepage
|
21
|
+
|
22
|
+
# Specify which files should be added to the gem when it is released.
|
23
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
24
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
25
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
26
|
+
end
|
27
|
+
spec.bindir = 'exe'
|
28
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
29
|
+
spec.require_paths = ['lib']
|
30
|
+
|
31
|
+
spec.add_dependency 'dry-struct', '~> 1.0'
|
32
|
+
spec.add_dependency 'dry-types', '~> 1.2'
|
33
|
+
spec.add_dependency 'activesupport'
|
34
|
+
|
35
|
+
spec.add_development_dependency 'pry'
|
36
|
+
spec.add_development_dependency 'simplecov'
|
37
|
+
spec.add_development_dependency 'bundler', '~> 2.0'
|
38
|
+
spec.add_development_dependency 'rake', '~> 13.0'
|
39
|
+
spec.add_development_dependency 'rspec', '~> 3.0'
|
40
|
+
end
|