apiwork 0.0.0.pre → 0.1.1

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.
Files changed (202) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +2 -2
  3. data/README.md +117 -1
  4. data/Rakefile +5 -3
  5. data/app/controllers/apiwork/errors_controller.rb +13 -0
  6. data/app/controllers/apiwork/exports_controller.rb +22 -0
  7. data/lib/apiwork/abstractable.rb +26 -0
  8. data/lib/apiwork/adapter/base.rb +369 -0
  9. data/lib/apiwork/adapter/builder/api/base.rb +66 -0
  10. data/lib/apiwork/adapter/builder/contract/base.rb +86 -0
  11. data/lib/apiwork/adapter/capability/api/base.rb +51 -0
  12. data/lib/apiwork/adapter/capability/api/scope.rb +64 -0
  13. data/lib/apiwork/adapter/capability/base.rb +291 -0
  14. data/lib/apiwork/adapter/capability/contract/base.rb +37 -0
  15. data/lib/apiwork/adapter/capability/contract/scope.rb +110 -0
  16. data/lib/apiwork/adapter/capability/operation/base.rb +172 -0
  17. data/lib/apiwork/adapter/capability/operation/metadata_shape.rb +165 -0
  18. data/lib/apiwork/adapter/capability/result.rb +21 -0
  19. data/lib/apiwork/adapter/capability/runner.rb +56 -0
  20. data/lib/apiwork/adapter/capability/transformer/request/base.rb +72 -0
  21. data/lib/apiwork/adapter/capability/transformer/response/base.rb +45 -0
  22. data/lib/apiwork/adapter/registry.rb +16 -0
  23. data/lib/apiwork/adapter/serializer/error/base.rb +72 -0
  24. data/lib/apiwork/adapter/serializer/error/default/api_builder.rb +32 -0
  25. data/lib/apiwork/adapter/serializer/error/default.rb +37 -0
  26. data/lib/apiwork/adapter/serializer/resource/base.rb +84 -0
  27. data/lib/apiwork/adapter/serializer/resource/default/contract_builder.rb +209 -0
  28. data/lib/apiwork/adapter/serializer/resource/default.rb +39 -0
  29. data/lib/apiwork/adapter/standard/capability/filtering/api_builder.rb +75 -0
  30. data/lib/apiwork/adapter/standard/capability/filtering/constants.rb +37 -0
  31. data/lib/apiwork/adapter/standard/capability/filtering/contract_builder.rb +193 -0
  32. data/lib/apiwork/adapter/standard/capability/filtering/operation/filter/builder.rb +47 -0
  33. data/lib/apiwork/adapter/standard/capability/filtering/operation/filter/operator_builder.rb +36 -0
  34. data/lib/apiwork/adapter/standard/capability/filtering/operation/filter.rb +462 -0
  35. data/lib/apiwork/adapter/standard/capability/filtering/operation.rb +22 -0
  36. data/lib/apiwork/adapter/standard/capability/filtering/request_transformer.rb +47 -0
  37. data/lib/apiwork/adapter/standard/capability/filtering.rb +18 -0
  38. data/lib/apiwork/adapter/standard/capability/including/contract_builder.rb +169 -0
  39. data/lib/apiwork/adapter/standard/capability/including/operation.rb +20 -0
  40. data/lib/apiwork/adapter/standard/capability/including.rb +16 -0
  41. data/lib/apiwork/adapter/standard/capability/pagination/api_builder.rb +34 -0
  42. data/lib/apiwork/adapter/standard/capability/pagination/contract_builder.rb +35 -0
  43. data/lib/apiwork/adapter/standard/capability/pagination/operation/paginate/cursor.rb +84 -0
  44. data/lib/apiwork/adapter/standard/capability/pagination/operation/paginate/offset.rb +66 -0
  45. data/lib/apiwork/adapter/standard/capability/pagination/operation/paginate.rb +24 -0
  46. data/lib/apiwork/adapter/standard/capability/pagination/operation.rb +24 -0
  47. data/lib/apiwork/adapter/standard/capability/pagination.rb +21 -0
  48. data/lib/apiwork/adapter/standard/capability/sorting/api_builder.rb +19 -0
  49. data/lib/apiwork/adapter/standard/capability/sorting/contract_builder.rb +84 -0
  50. data/lib/apiwork/adapter/standard/capability/sorting/operation/sort.rb +83 -0
  51. data/lib/apiwork/adapter/standard/capability/sorting/operation.rb +22 -0
  52. data/lib/apiwork/adapter/standard/capability/sorting.rb +17 -0
  53. data/lib/apiwork/adapter/standard/capability/writing/constants.rb +15 -0
  54. data/lib/apiwork/adapter/standard/capability/writing/contract_builder.rb +253 -0
  55. data/lib/apiwork/adapter/standard/capability/writing/operation/issue_mapper.rb +210 -0
  56. data/lib/apiwork/adapter/standard/capability/writing/operation.rb +32 -0
  57. data/lib/apiwork/adapter/standard/capability/writing/request_transformer.rb +37 -0
  58. data/lib/apiwork/adapter/standard/capability/writing.rb +17 -0
  59. data/lib/apiwork/adapter/standard/includes_resolver.rb +106 -0
  60. data/lib/apiwork/adapter/standard.rb +22 -0
  61. data/lib/apiwork/adapter/wrapper/base.rb +70 -0
  62. data/lib/apiwork/adapter/wrapper/collection/base.rb +60 -0
  63. data/lib/apiwork/adapter/wrapper/collection/default.rb +47 -0
  64. data/lib/apiwork/adapter/wrapper/error/base.rb +30 -0
  65. data/lib/apiwork/adapter/wrapper/error/default.rb +34 -0
  66. data/lib/apiwork/adapter/wrapper/member/base.rb +58 -0
  67. data/lib/apiwork/adapter/wrapper/member/default.rb +40 -0
  68. data/lib/apiwork/adapter/wrapper/shape.rb +203 -0
  69. data/lib/apiwork/adapter.rb +50 -0
  70. data/lib/apiwork/api/base.rb +802 -0
  71. data/lib/apiwork/api/element.rb +110 -0
  72. data/lib/apiwork/api/enum_registry/definition.rb +51 -0
  73. data/lib/apiwork/api/enum_registry.rb +98 -0
  74. data/lib/apiwork/api/info/contact.rb +67 -0
  75. data/lib/apiwork/api/info/license.rb +50 -0
  76. data/lib/apiwork/api/info/server.rb +50 -0
  77. data/lib/apiwork/api/info.rb +221 -0
  78. data/lib/apiwork/api/object.rb +235 -0
  79. data/lib/apiwork/api/registry.rb +33 -0
  80. data/lib/apiwork/api/representation_registry.rb +76 -0
  81. data/lib/apiwork/api/resource/action.rb +41 -0
  82. data/lib/apiwork/api/resource.rb +648 -0
  83. data/lib/apiwork/api/router.rb +104 -0
  84. data/lib/apiwork/api/type_registry/definition.rb +117 -0
  85. data/lib/apiwork/api/type_registry.rb +99 -0
  86. data/lib/apiwork/api/union.rb +49 -0
  87. data/lib/apiwork/api.rb +85 -0
  88. data/lib/apiwork/configurable.rb +71 -0
  89. data/lib/apiwork/configuration/option.rb +125 -0
  90. data/lib/apiwork/configuration/validatable.rb +25 -0
  91. data/lib/apiwork/configuration.rb +95 -0
  92. data/lib/apiwork/configuration_error.rb +6 -0
  93. data/lib/apiwork/constraint_error.rb +20 -0
  94. data/lib/apiwork/contract/action/request.rb +79 -0
  95. data/lib/apiwork/contract/action/response.rb +87 -0
  96. data/lib/apiwork/contract/action.rb +258 -0
  97. data/lib/apiwork/contract/base.rb +714 -0
  98. data/lib/apiwork/contract/element.rb +130 -0
  99. data/lib/apiwork/contract/object/coercer.rb +194 -0
  100. data/lib/apiwork/contract/object/deserializer.rb +101 -0
  101. data/lib/apiwork/contract/object/transformer.rb +95 -0
  102. data/lib/apiwork/contract/object/validator/result.rb +27 -0
  103. data/lib/apiwork/contract/object/validator.rb +734 -0
  104. data/lib/apiwork/contract/object.rb +566 -0
  105. data/lib/apiwork/contract/request_parser/result.rb +25 -0
  106. data/lib/apiwork/contract/request_parser.rb +72 -0
  107. data/lib/apiwork/contract/response_parser/result.rb +25 -0
  108. data/lib/apiwork/contract/response_parser.rb +35 -0
  109. data/lib/apiwork/contract/union.rb +56 -0
  110. data/lib/apiwork/contract_error.rb +9 -0
  111. data/lib/apiwork/controller.rb +300 -0
  112. data/lib/apiwork/domain_error.rb +13 -0
  113. data/lib/apiwork/element.rb +386 -0
  114. data/lib/apiwork/engine.rb +20 -0
  115. data/lib/apiwork/error.rb +6 -0
  116. data/lib/apiwork/error_code/definition.rb +63 -0
  117. data/lib/apiwork/error_code/registry.rb +18 -0
  118. data/lib/apiwork/error_code.rb +132 -0
  119. data/lib/apiwork/export/base.rb +291 -0
  120. data/lib/apiwork/export/open_api.rb +600 -0
  121. data/lib/apiwork/export/pipeline/writer.rb +66 -0
  122. data/lib/apiwork/export/pipeline.rb +84 -0
  123. data/lib/apiwork/export/registry.rb +16 -0
  124. data/lib/apiwork/export/surface_resolver.rb +189 -0
  125. data/lib/apiwork/export/type_analysis.rb +170 -0
  126. data/lib/apiwork/export/type_script.rb +23 -0
  127. data/lib/apiwork/export/type_script_mapper.rb +349 -0
  128. data/lib/apiwork/export/zod.rb +39 -0
  129. data/lib/apiwork/export/zod_mapper.rb +421 -0
  130. data/lib/apiwork/export.rb +80 -0
  131. data/lib/apiwork/http_error.rb +16 -0
  132. data/lib/apiwork/introspection/action/request.rb +66 -0
  133. data/lib/apiwork/introspection/action/response.rb +57 -0
  134. data/lib/apiwork/introspection/action.rb +124 -0
  135. data/lib/apiwork/introspection/api/info/contact.rb +59 -0
  136. data/lib/apiwork/introspection/api/info/license.rb +49 -0
  137. data/lib/apiwork/introspection/api/info/server.rb +50 -0
  138. data/lib/apiwork/introspection/api/info.rb +107 -0
  139. data/lib/apiwork/introspection/api/resource.rb +83 -0
  140. data/lib/apiwork/introspection/api.rb +92 -0
  141. data/lib/apiwork/introspection/contract.rb +63 -0
  142. data/lib/apiwork/introspection/dump/action.rb +101 -0
  143. data/lib/apiwork/introspection/dump/api.rb +119 -0
  144. data/lib/apiwork/introspection/dump/contract.rb +129 -0
  145. data/lib/apiwork/introspection/dump/param.rb +486 -0
  146. data/lib/apiwork/introspection/dump/resource.rb +112 -0
  147. data/lib/apiwork/introspection/dump/type.rb +339 -0
  148. data/lib/apiwork/introspection/dump.rb +17 -0
  149. data/lib/apiwork/introspection/enum.rb +63 -0
  150. data/lib/apiwork/introspection/error_code.rb +44 -0
  151. data/lib/apiwork/introspection/param/array.rb +88 -0
  152. data/lib/apiwork/introspection/param/base.rb +285 -0
  153. data/lib/apiwork/introspection/param/binary.rb +73 -0
  154. data/lib/apiwork/introspection/param/boolean.rb +73 -0
  155. data/lib/apiwork/introspection/param/date.rb +73 -0
  156. data/lib/apiwork/introspection/param/date_time.rb +73 -0
  157. data/lib/apiwork/introspection/param/decimal.rb +121 -0
  158. data/lib/apiwork/introspection/param/integer.rb +131 -0
  159. data/lib/apiwork/introspection/param/literal.rb +45 -0
  160. data/lib/apiwork/introspection/param/number.rb +121 -0
  161. data/lib/apiwork/introspection/param/object.rb +59 -0
  162. data/lib/apiwork/introspection/param/reference.rb +45 -0
  163. data/lib/apiwork/introspection/param/string.rb +122 -0
  164. data/lib/apiwork/introspection/param/time.rb +73 -0
  165. data/lib/apiwork/introspection/param/union.rb +57 -0
  166. data/lib/apiwork/introspection/param/unknown.rb +26 -0
  167. data/lib/apiwork/introspection/param/uuid.rb +73 -0
  168. data/lib/apiwork/introspection/param.rb +31 -0
  169. data/lib/apiwork/introspection/type.rb +129 -0
  170. data/lib/apiwork/introspection.rb +28 -0
  171. data/lib/apiwork/issue.rb +80 -0
  172. data/lib/apiwork/json_pointer.rb +21 -0
  173. data/lib/apiwork/object.rb +1618 -0
  174. data/lib/apiwork/reference_generator.rb +622 -0
  175. data/lib/apiwork/registry.rb +56 -0
  176. data/lib/apiwork/representation/association.rb +391 -0
  177. data/lib/apiwork/representation/attribute.rb +335 -0
  178. data/lib/apiwork/representation/base.rb +819 -0
  179. data/lib/apiwork/representation/deserializer.rb +95 -0
  180. data/lib/apiwork/representation/element.rb +128 -0
  181. data/lib/apiwork/representation/inheritance.rb +78 -0
  182. data/lib/apiwork/representation/model_detector.rb +75 -0
  183. data/lib/apiwork/representation/root_key.rb +35 -0
  184. data/lib/apiwork/representation/serializer.rb +127 -0
  185. data/lib/apiwork/request.rb +79 -0
  186. data/lib/apiwork/response.rb +56 -0
  187. data/lib/apiwork/union.rb +102 -0
  188. data/lib/apiwork/version.rb +2 -2
  189. data/lib/apiwork.rb +61 -3
  190. data/lib/generators/apiwork/api_generator.rb +38 -0
  191. data/lib/generators/apiwork/contract_generator.rb +25 -0
  192. data/lib/generators/apiwork/install_generator.rb +27 -0
  193. data/lib/generators/apiwork/representation_generator.rb +25 -0
  194. data/lib/generators/apiwork/templates/api/api.rb.tt +4 -0
  195. data/lib/generators/apiwork/templates/contract/contract.rb.tt +6 -0
  196. data/lib/generators/apiwork/templates/install/application_contract.rb.tt +5 -0
  197. data/lib/generators/apiwork/templates/install/application_representation.rb.tt +5 -0
  198. data/lib/generators/apiwork/templates/representation/representation.rb.tt +6 -0
  199. data/lib/tasks/apiwork.rake +102 -0
  200. metadata +319 -19
  201. data/.rubocop.yml +0 -8
  202. data/sig/apiwork.rbs +0 -4
@@ -0,0 +1,110 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Apiwork
4
+ module API
5
+ # @api public
6
+ # Block context for defining a single type expression.
7
+ #
8
+ # Used inside `array do` and `variant do` blocks where
9
+ # exactly one element type must be defined.
10
+ #
11
+ # @see API::Object Block context for object params
12
+ # @see API::Union Block context for union variants
13
+ #
14
+ # @example instance_eval style
15
+ # array :ids do
16
+ # integer
17
+ # end
18
+ #
19
+ # @example yield style
20
+ # array :ids do |element|
21
+ # element.integer
22
+ # end
23
+ #
24
+ # @example Array of references
25
+ # array :items do |element|
26
+ # element.reference :item
27
+ # end
28
+ class Element < Apiwork::Element
29
+ # @api public
30
+ # Defines the element type.
31
+ #
32
+ # This is the verbose form. Prefer sugar methods (string, integer, etc.)
33
+ # for static definitions. Use `of` for dynamic element generation.
34
+ #
35
+ # @param type [Symbol] [:array, :binary, :boolean, :date, :datetime, :decimal, :integer, :literal, :number, :object, :string, :time, :union, :uuid]
36
+ # The element type. Custom type references are also allowed.
37
+ # @param discriminator [Symbol, nil] (nil)
38
+ # The discriminator field name. Unions only.
39
+ # @param enum [Array, Symbol, nil] (nil)
40
+ # The allowed values. Strings and integers only.
41
+ # @param format [Symbol, nil] (nil) [:date, :datetime, :double, :email, :float, :hostname, :int32, :int64, :ipv4, :ipv6, :password, :url, :uuid]
42
+ # Format hint for exports. Does not change the type, but exports may add validation or documentation based on it.
43
+ # Valid formats by type: `:decimal`/`:number` (`:double`, `:float`), `:integer` (`:int32`, `:int64`),
44
+ # `:string` (`:date`, `:datetime`, `:email`, `:hostname`, `:ipv4`, `:ipv6`, `:password`, `:url`, `:uuid`).
45
+ # @param max [Integer, nil] (nil)
46
+ # The maximum. For `:decimal`, `:integer`, `:number`: value. For `:string`: length.
47
+ # @param min [Integer, nil] (nil)
48
+ # The minimum. For `:decimal`, `:integer`, `:number`: value. For `:string`: length.
49
+ # @param value [Object, nil] (nil)
50
+ # The literal value. Literals only.
51
+ # @yield block for defining nested structure
52
+ # @yieldparam shape [API::Object, API::Union, API::Element]
53
+ # @return [void]
54
+ #
55
+ # @example Dynamic element type
56
+ # element_type = :string
57
+ # array :values do
58
+ # of element_type
59
+ # end
60
+ #
61
+ # @example Object with block
62
+ # array :tags do
63
+ # of :object do
64
+ # string :name
65
+ # end
66
+ # end
67
+ def of(type, discriminator: nil, enum: nil, format: nil, max: nil, min: nil, value: nil, &block)
68
+ case type
69
+ when :string, :integer, :decimal, :boolean, :number, :datetime, :date, :uuid, :time, :binary
70
+ set_type(type, enum:, format:, max:, min:)
71
+ when :literal
72
+ @type = :literal
73
+ @value = value
74
+ @defined = true
75
+ when :object
76
+ @type = :object
77
+ if block
78
+ shape = Object.new
79
+ block.arity.positive? ? yield(shape) : shape.instance_eval(&block)
80
+ @shape = shape
81
+ end
82
+ @defined = true
83
+ when :array
84
+ raise ConfigurationError, 'array requires a block' unless block
85
+
86
+ inner = Element.new
87
+ block.arity.positive? ? yield(inner) : inner.instance_eval(&block)
88
+ inner.validate!
89
+ @type = :array
90
+ @inner = inner
91
+ @shape = inner.shape
92
+ @defined = true
93
+ when :union
94
+ raise ConfigurationError, 'union requires a block' unless block
95
+
96
+ shape = Union.new(discriminator:)
97
+ block.arity.positive? ? yield(shape) : shape.instance_eval(&block)
98
+ @type = :union
99
+ @shape = shape
100
+ @discriminator = discriminator
101
+ @defined = true
102
+ else
103
+ @type = type
104
+ @custom_type = type
105
+ @defined = true
106
+ end
107
+ end
108
+ end
109
+ end
110
+ end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Apiwork
4
+ module API
5
+ class EnumRegistry
6
+ class Definition
7
+ attr_reader :description,
8
+ :example,
9
+ :name,
10
+ :scope,
11
+ :values
12
+
13
+ def initialize(
14
+ name,
15
+ scope: nil,
16
+ deprecated: false,
17
+ description: nil,
18
+ example: nil,
19
+ values: nil
20
+ )
21
+ @name = name
22
+ @scope = scope
23
+ @deprecated = deprecated
24
+ @description = description
25
+ @example = example
26
+ @values = values
27
+ end
28
+
29
+ def deprecated?
30
+ @deprecated == true
31
+ end
32
+
33
+ def merge(
34
+ deprecated:,
35
+ description:,
36
+ example:,
37
+ values:
38
+ )
39
+ Definition.new(
40
+ @name,
41
+ deprecated: deprecated || @deprecated,
42
+ description: description || @description,
43
+ example: example || @example,
44
+ scope: @scope,
45
+ values: values || @values,
46
+ )
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,98 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Apiwork
4
+ module API
5
+ class EnumRegistry
6
+ def initialize
7
+ @store = {}
8
+ end
9
+
10
+ def register(
11
+ name,
12
+ values = nil,
13
+ scope: nil,
14
+ deprecated: false,
15
+ description: nil,
16
+ example: nil
17
+ )
18
+ key = scoped_name(scope, name)
19
+
20
+ if @store.key?(key)
21
+ merge(
22
+ key,
23
+ deprecated:,
24
+ description:,
25
+ example:,
26
+ values:,
27
+ )
28
+ else
29
+ @store[key] = Definition.new(
30
+ key,
31
+ deprecated:,
32
+ description:,
33
+ example:,
34
+ scope:,
35
+ values:,
36
+ )
37
+ end
38
+ end
39
+
40
+ def [](name)
41
+ @store[name]
42
+ end
43
+
44
+ def key?(name)
45
+ @store.key?(name)
46
+ end
47
+
48
+ def each_pair(&block)
49
+ @store.each_pair(&block)
50
+ end
51
+
52
+ def exists?(name, scope: nil)
53
+ find(name, scope:).present?
54
+ end
55
+
56
+ def find(name, scope: nil)
57
+ (scope ? @store[scoped_name(scope, name)] : nil) || @store[name]
58
+ end
59
+
60
+ def values(name, scope: nil)
61
+ find(name, scope:)&.values
62
+ end
63
+
64
+ def scoped_name(scope, name)
65
+ return name unless scope
66
+
67
+ prefix = scope.respond_to?(:scope_prefix) ? scope.scope_prefix : nil
68
+ return name unless prefix
69
+ return prefix.to_sym if name.nil?
70
+ return prefix.to_sym if name.to_s.empty?
71
+ return name.to_sym if name.to_s == prefix
72
+
73
+ [prefix, name].join('_').to_sym
74
+ end
75
+
76
+ def clear!
77
+ @store.clear
78
+ end
79
+
80
+ private
81
+
82
+ def merge(
83
+ key,
84
+ deprecated:,
85
+ description:,
86
+ example:,
87
+ values:
88
+ )
89
+ @store[key] = @store[key].merge(
90
+ deprecated:,
91
+ description:,
92
+ example:,
93
+ values:,
94
+ )
95
+ end
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,67 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Apiwork
4
+ module API
5
+ class Info
6
+ # @api public
7
+ # Contact information block.
8
+ #
9
+ # Used within the `contact` block in {API::Info}.
10
+ class Contact
11
+ def initialize
12
+ @email = nil
13
+ @name = nil
14
+ @url = nil
15
+ end
16
+
17
+ # @api public
18
+ # The contact name.
19
+ #
20
+ # @param value [String, nil] (nil)
21
+ # The name.
22
+ # @return [String, nil]
23
+ #
24
+ # @example
25
+ # name 'API Support'
26
+ # contact.name # => "API Support"
27
+ def name(value = nil)
28
+ return @name if value.nil?
29
+
30
+ @name = value
31
+ end
32
+
33
+ # @api public
34
+ # The contact email.
35
+ #
36
+ # @param value [String, nil] (nil)
37
+ # The email.
38
+ # @return [String, nil]
39
+ #
40
+ # @example
41
+ # email 'support@example.com'
42
+ # contact.email # => "support@example.com"
43
+ def email(value = nil)
44
+ return @email if value.nil?
45
+
46
+ @email = value
47
+ end
48
+
49
+ # @api public
50
+ # The contact URL.
51
+ #
52
+ # @param value [String, nil] (nil)
53
+ # The URL.
54
+ # @return [String, nil]
55
+ #
56
+ # @example
57
+ # url 'https://example.com/support'
58
+ # contact.url # => "https://example.com/support"
59
+ def url(value = nil)
60
+ return @url if value.nil?
61
+
62
+ @url = value
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Apiwork
4
+ module API
5
+ class Info
6
+ # @api public
7
+ # License information block.
8
+ #
9
+ # Used within the `license` block in {API::Info}.
10
+ class License
11
+ def initialize
12
+ @name = nil
13
+ @url = nil
14
+ end
15
+
16
+ # @api public
17
+ # The license name.
18
+ #
19
+ # @param value [String, nil] (nil)
20
+ # The name.
21
+ # @return [String, nil]
22
+ #
23
+ # @example
24
+ # name 'MIT'
25
+ # license.name # => "MIT"
26
+ def name(value = nil)
27
+ return @name if value.nil?
28
+
29
+ @name = value
30
+ end
31
+
32
+ # @api public
33
+ # The license URL.
34
+ #
35
+ # @param value [String, nil] (nil)
36
+ # The URL.
37
+ # @return [String, nil]
38
+ #
39
+ # @example
40
+ # url 'https://opensource.org/licenses/MIT'
41
+ # license.url # => "https://opensource.org/licenses/MIT"
42
+ def url(value = nil)
43
+ return @url if value.nil?
44
+
45
+ @url = value
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Apiwork
4
+ module API
5
+ class Info
6
+ # @api public
7
+ # Server definition block.
8
+ #
9
+ # Used within the `server` block in {API::Info}.
10
+ class Server
11
+ def initialize
12
+ @description = nil
13
+ @url = nil
14
+ end
15
+
16
+ # @api public
17
+ # The server URL.
18
+ #
19
+ # @param value [String, nil] (nil)
20
+ # The URL.
21
+ # @return [String, nil]
22
+ #
23
+ # @example
24
+ # url 'https://api.example.com'
25
+ # server.url # => "https://api.example.com"
26
+ def url(value = nil)
27
+ return @url if value.nil?
28
+
29
+ @url = value
30
+ end
31
+
32
+ # @api public
33
+ # The server description.
34
+ #
35
+ # @param value [String, nil] (nil)
36
+ # The description.
37
+ # @return [String, nil]
38
+ #
39
+ # @example
40
+ # description 'Production'
41
+ # server.description # => "Production"
42
+ def description(value = nil)
43
+ return @description if value.nil?
44
+
45
+ @description = value
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,221 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Apiwork
4
+ module API
5
+ # @api public
6
+ # Block context for defining API metadata.
7
+ #
8
+ # Used within the `info` block in {API::Base}.
9
+ class Info
10
+ def initialize
11
+ @contact = nil
12
+ @deprecated = false
13
+ @description = nil
14
+ @license = nil
15
+ @servers = []
16
+ @summary = nil
17
+ @tags = []
18
+ @terms_of_service = nil
19
+ @title = nil
20
+ @version = nil
21
+ end
22
+
23
+ # @api public
24
+ # The API title.
25
+ #
26
+ # @param value [String, nil] (nil)
27
+ # The title.
28
+ # @return [String, nil]
29
+ #
30
+ # @example
31
+ # title 'Invoice API'
32
+ # info.title # => "Invoice API"
33
+ def title(value = nil)
34
+ return @title if value.nil?
35
+
36
+ @title = value
37
+ end
38
+
39
+ # @api public
40
+ # The API version.
41
+ #
42
+ # @param value [String, nil] (nil)
43
+ # The version.
44
+ # @return [String, nil]
45
+ #
46
+ # @example
47
+ # version '1.0.0'
48
+ # info.version # => "1.0.0"
49
+ def version(value = nil)
50
+ return @version if value.nil?
51
+
52
+ @version = value
53
+ end
54
+
55
+ # @api public
56
+ # The API terms of service.
57
+ #
58
+ # @param value [String, nil] (nil)
59
+ # The URL to terms of service.
60
+ # @return [String, nil]
61
+ #
62
+ # @example
63
+ # terms_of_service 'https://example.com/terms'
64
+ # info.terms_of_service # => "https://example.com/terms"
65
+ def terms_of_service(value = nil)
66
+ return @terms_of_service if value.nil?
67
+
68
+ @terms_of_service = value
69
+ end
70
+
71
+ # @api public
72
+ # The API contact.
73
+ #
74
+ # @yield block for defining contact info
75
+ # @yieldparam contact [Contact]
76
+ # @return [Contact, nil]
77
+ #
78
+ # @example instance_eval style
79
+ # contact do
80
+ # name 'Support'
81
+ # email 'support@example.com'
82
+ # end
83
+ #
84
+ # @example yield style
85
+ # contact do |contact|
86
+ # contact.name 'Support'
87
+ # contact.email 'support@example.com'
88
+ # end
89
+ def contact(&block)
90
+ return @contact unless block
91
+
92
+ @contact = Contact.new
93
+ block.arity.positive? ? yield(@contact) : @contact.instance_eval(&block)
94
+ @contact
95
+ end
96
+
97
+ # @api public
98
+ # The API license.
99
+ #
100
+ # @yield block for defining license info
101
+ # @yieldparam license [License]
102
+ # @return [License, nil]
103
+ #
104
+ # @example instance_eval style
105
+ # license do
106
+ # name 'MIT'
107
+ # url 'https://opensource.org/licenses/MIT'
108
+ # end
109
+ #
110
+ # @example yield style
111
+ # license do |license|
112
+ # license.name 'MIT'
113
+ # license.url 'https://opensource.org/licenses/MIT'
114
+ # end
115
+ def license(&block)
116
+ return @license unless block
117
+
118
+ @license = License.new
119
+ block.arity.positive? ? yield(@license) : @license.instance_eval(&block)
120
+ @license
121
+ end
122
+
123
+ # @api public
124
+ # Defines a server for the API.
125
+ #
126
+ # Can be called multiple times.
127
+ #
128
+ # @yield block for defining server info
129
+ # @yieldparam server [Server]
130
+ # @return [Array<Server>]
131
+ #
132
+ # @example instance_eval style
133
+ # server do
134
+ # url 'https://api.example.com'
135
+ # description 'Production'
136
+ # end
137
+ #
138
+ # @example yield style
139
+ # server do |server|
140
+ # server.url 'https://api.example.com'
141
+ # server.description 'Production'
142
+ # end
143
+ def server(&block)
144
+ return @servers unless block
145
+
146
+ server = Server.new
147
+ block.arity.positive? ? yield(server) : server.instance_eval(&block)
148
+ @servers << server
149
+ end
150
+
151
+ # @api public
152
+ # The API summary.
153
+ #
154
+ # @param value [String, nil] (nil)
155
+ # The summary.
156
+ # @return [String, nil]
157
+ #
158
+ # @example
159
+ # summary 'Invoice management API'
160
+ # info.summary # => "Invoice management API"
161
+ def summary(value = nil)
162
+ return @summary if value.nil?
163
+
164
+ @summary = value
165
+ end
166
+
167
+ # @api public
168
+ # The API description.
169
+ #
170
+ # @param value [String, nil] (nil)
171
+ # The description.
172
+ # @return [String, nil]
173
+ #
174
+ # @example
175
+ # description 'Full-featured API for managing invoices and payments.'
176
+ # info.description # => "Full-featured..."
177
+ def description(value = nil)
178
+ return @description if value.nil?
179
+
180
+ @description = value
181
+ end
182
+
183
+ # @api public
184
+ # The API tags.
185
+ #
186
+ # @param values [Array<String>]
187
+ # The tags.
188
+ # @return [Array<String>]
189
+ #
190
+ # @example
191
+ # tags 'invoices', 'payments'
192
+ # info.tags # => ["invoices", "payments"]
193
+ def tags(*values)
194
+ return @tags if values.empty?
195
+
196
+ @tags = values.flatten
197
+ end
198
+
199
+ # @api public
200
+ # Marks the API as deprecated.
201
+ #
202
+ # @return [void]
203
+ #
204
+ # @example
205
+ # info do
206
+ # deprecated!
207
+ # end
208
+ def deprecated!
209
+ @deprecated = true
210
+ end
211
+
212
+ # @api public
213
+ # Whether the API is deprecated.
214
+ #
215
+ # @return [Boolean]
216
+ def deprecated?
217
+ @deprecated
218
+ end
219
+ end
220
+ end
221
+ end