apiwork 0.0.0.pre → 0.1.2

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 +638 -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,339 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Apiwork
4
+ module Introspection
5
+ module Dump
6
+ class Type
7
+ def initialize(api_class)
8
+ @api_class = api_class
9
+ end
10
+
11
+ def to_h
12
+ {
13
+ enums: enums,
14
+ types: types,
15
+ }
16
+ end
17
+
18
+ def types
19
+ @api_class.type_registry.each_pair
20
+ .reject { |_, type_definition| type_definition.fragment? }
21
+ .sort_by do |name, _type_definition|
22
+ name.to_s
23
+ end.each_with_object({}) do |(qualified_name, type_definition), result|
24
+ result[qualified_name] = build_type(qualified_name, type_definition)
25
+ end
26
+ end
27
+
28
+ def enums
29
+ @api_class.enum_registry.each_pair.sort_by do |name, _enum_definition|
30
+ name.to_s
31
+ end.each_with_object({}) do |(qualified_name, enum_definition), result|
32
+ result[qualified_name] = build_enum(qualified_name, enum_definition)
33
+ end
34
+ end
35
+
36
+ def build_type(qualified_name, type_definition)
37
+ if type_definition.union?
38
+ {
39
+ deprecated: type_definition.deprecated?,
40
+ description: resolve_type_description(qualified_name, type_definition),
41
+ discriminator: type_definition.discriminator,
42
+ example: type_definition.example,
43
+ extends: [],
44
+ shape: {},
45
+ type: :union,
46
+ variants: build_variants(type_definition),
47
+ }
48
+ else
49
+ {
50
+ deprecated: type_definition.deprecated?,
51
+ description: resolve_type_description(qualified_name, type_definition),
52
+ discriminator: nil,
53
+ example: type_definition.example,
54
+ extends: resolve_extends(type_definition.shape.extends, type_definition.scope),
55
+ shape: build_params(type_definition),
56
+ type: :object,
57
+ variants: [],
58
+ }
59
+ end
60
+ end
61
+
62
+ def resolve_extends(extends, scope)
63
+ extends.map { |name| resolve_scoped_type_name(name, scope) || name }
64
+ end
65
+
66
+ def build_params(type_definition)
67
+ return {} unless type_definition.params
68
+
69
+ result = {}
70
+
71
+ expand_merged_types(type_definition, result)
72
+
73
+ type_definition.params.sort_by { |name, _| name.to_s }.each do |name, param_options|
74
+ result[name] = build_param(name, param_options, type_definition.scope)
75
+ end
76
+ result
77
+ end
78
+
79
+ def expand_merged_types(type_definition, result)
80
+ return unless type_definition.shape.respond_to?(:merged)
81
+
82
+ type_definition.shape.merged.each do |merged_name|
83
+ resolved_name = resolve_scoped_type_name(merged_name, type_definition.scope) || merged_name
84
+ merged_type = @api_class.type_registry[resolved_name]
85
+ next unless merged_type&.params
86
+
87
+ merged_type.params.each do |name, param_options|
88
+ result[name] = build_param(name, param_options, type_definition.scope)
89
+ end
90
+ end
91
+ end
92
+
93
+ def build_variants(type_definition)
94
+ return [] unless type_definition.variants
95
+
96
+ type_definition.variants.map do |variant|
97
+ build_variant(variant, type_definition.scope)
98
+ end
99
+ end
100
+
101
+ def build_param(name, options, scope)
102
+ reference = resolve_type_reference(options[:type], scope)
103
+
104
+ {
105
+ reference:,
106
+ as: options[:as],
107
+ default: options[:default],
108
+ deprecated: options[:deprecated] == true,
109
+ description: resolve_param_description(name, options, scope),
110
+ discriminator: nil,
111
+ enum: resolve_enum(options, scope),
112
+ example: options[:example],
113
+ format: options[:format],
114
+ max: options[:max],
115
+ min: options[:min],
116
+ nullable: options[:nullable] == true,
117
+ of: resolve_of(options, scope),
118
+ optional: options[:optional] == true,
119
+ partial: options[:partial] == true,
120
+ shape: resolve_param_shape(options),
121
+ tag: nil,
122
+ type: reference ? :reference : (options[:type] || :unknown),
123
+ value: options[:type] == :literal ? options[:value] : nil,
124
+ variants: build_nested_variants(options[:shape]),
125
+ }
126
+ end
127
+
128
+ def build_variant(variant, scope)
129
+ reference = resolve_type_reference(variant[:custom_type] || variant[:type], scope)
130
+ resolved_type = reference ? :reference : (variant[:type] || :unknown)
131
+
132
+ {
133
+ reference:,
134
+ as: nil,
135
+ default: nil,
136
+ deprecated: false,
137
+ description: nil,
138
+ discriminator: nil,
139
+ enum: resolve_variant_enum(variant, scope),
140
+ example: nil,
141
+ format: nil,
142
+ max: nil,
143
+ min: nil,
144
+ nullable: false,
145
+ of: resolve_variant_of(variant, scope),
146
+ optional: false,
147
+ partial: variant[:partial] == true,
148
+ shape: build_nested_shape(variant[:shape]),
149
+ tag: variant[:tag],
150
+ type: resolved_type,
151
+ value: variant[:value],
152
+ variants: [],
153
+ }
154
+ end
155
+
156
+ def build_nested_shape(shape)
157
+ return {} unless shape
158
+ return {} unless shape.respond_to?(:params)
159
+
160
+ result = {}
161
+ shape.params.sort_by { |name, _| name.to_s }.each do |name, param_options|
162
+ result[name] = build_param(name, param_options, nil)
163
+ end
164
+ result
165
+ end
166
+
167
+ def build_nested_variants(shape)
168
+ return [] unless shape
169
+ return [] unless shape.respond_to?(:variants)
170
+
171
+ shape.variants.map { |variant| build_variant(variant, nil) }
172
+ end
173
+
174
+ def resolve_param_shape(options)
175
+ return build_nested_shape(options[:shape]) if options[:shape]
176
+
177
+ of = options[:of]
178
+ return {} unless of
179
+ return {} unless of.respond_to?(:shape)
180
+
181
+ of.shape ? build_nested_shape(of.shape) : {}
182
+ end
183
+
184
+ def resolve_type_reference(type_value, scope)
185
+ return nil unless type_value
186
+
187
+ resolve_scoped_type_name(type_value, scope)
188
+ end
189
+
190
+ def resolve_enum(options, scope)
191
+ return nil unless options[:enum]
192
+
193
+ if options[:enum].is_a?(Symbol)
194
+ @api_class.scoped_enum_name(scope, options[:enum])
195
+ else
196
+ options[:enum]
197
+ end
198
+ end
199
+
200
+ def resolve_of(options, scope)
201
+ of = options[:of]
202
+ return nil unless of
203
+
204
+ type_value = of.type
205
+ scoped_name = resolve_scoped_type_name(type_value, scope)
206
+ resolved_shape = of.shape ? build_nested_shape(of.shape) : {}
207
+
208
+ result = {
209
+ enum: of.enum,
210
+ format: of.format,
211
+ max: of.max,
212
+ min: of.min,
213
+ reference: scoped_name,
214
+ shape: resolved_shape,
215
+ type: scoped_name ? :reference : type_value,
216
+ }
217
+ result[:of] = resolve_of({ of: of.inner }, scope) if of.type == :array && of.inner
218
+ result
219
+ end
220
+
221
+ def resolve_variant_enum(variant, scope)
222
+ return nil unless variant[:enum]
223
+
224
+ if variant[:enum].is_a?(Symbol)
225
+ @api_class.scoped_enum_name(scope, variant[:enum])
226
+ else
227
+ variant[:enum]
228
+ end
229
+ end
230
+
231
+ def resolve_variant_of(variant, scope)
232
+ of = variant[:of]
233
+ return nil unless of
234
+
235
+ type_value = of.type
236
+ scoped_name = resolve_scoped_type_name(type_value, scope)
237
+ resolved_shape = of.shape ? build_nested_shape(of.shape) : {}
238
+
239
+ result = {
240
+ enum: of.enum,
241
+ format: of.format,
242
+ max: of.max,
243
+ min: of.min,
244
+ reference: scoped_name,
245
+ shape: resolved_shape,
246
+ type: scoped_name ? :reference : type_value,
247
+ }
248
+ result[:of] = resolve_variant_of({ of: of.inner }, scope) if of.type == :array && of.inner
249
+ result
250
+ end
251
+
252
+ def build_enum(qualified_name, enum_definition)
253
+ {
254
+ deprecated: enum_definition.deprecated?,
255
+ description: resolve_enum_description(qualified_name, enum_definition),
256
+ example: enum_definition.example,
257
+ values: enum_definition.values || [],
258
+ }
259
+ end
260
+
261
+ private
262
+
263
+ def resolve_param_description(name, options, scope)
264
+ return options[:description] if options[:description]
265
+ return nil unless scope
266
+ return nil unless scope.respond_to?(:representation_class)
267
+
268
+ representation_class = scope.representation_class
269
+ return nil unless representation_class
270
+
271
+ if (attribute = representation_class.attributes[name])
272
+ description = i18n_attribute_description(attribute)
273
+ return description if description
274
+ end
275
+
276
+ if (association = representation_class.associations[name])
277
+ description = i18n_association_description(association)
278
+ return description if description
279
+ end
280
+
281
+ nil
282
+ end
283
+
284
+ def i18n_attribute_description(attribute)
285
+ representation_name = attribute.representation_class_name
286
+ attribute_name = attribute.name
287
+
288
+ @api_class.translate(:representations, representation_name, :attributes, attribute_name, :description)
289
+ end
290
+
291
+ def i18n_association_description(association)
292
+ representation_name = association.representation_class_name
293
+ association_name = association.name
294
+
295
+ @api_class.translate(:representations, representation_name, :associations, association_name, :description)
296
+ end
297
+
298
+ def resolve_type_description(type_name, type_definition)
299
+ return type_definition.description if type_definition.description
300
+
301
+ result = @api_class.translate(:types, type_name, :description)
302
+ return result if result
303
+
304
+ I18n.translate(:"apiwork.types.#{type_name}.description", default: nil)
305
+ end
306
+
307
+ def resolve_enum_description(enum_name, enum_definition)
308
+ return enum_definition.description if enum_definition.description
309
+
310
+ result = @api_class.translate(:enums, enum_name, :description)
311
+ return result if result
312
+
313
+ I18n.translate(:"apiwork.enums.#{enum_name}.description", default: nil)
314
+ end
315
+
316
+ def resolve_scoped_type_name(type_name, scope)
317
+ return nil unless type_name.is_a?(Symbol)
318
+ return nil unless @api_class
319
+
320
+ return type_name if @api_class.type_registry.key?(type_name) || @api_class.enum_registry.key?(type_name)
321
+
322
+ return nil unless scope
323
+
324
+ scoped_name = @api_class.scoped_type_name(scope, type_name)
325
+ return scoped_name if @api_class.type_registry.key?(scoped_name) || @api_class.enum_registry.key?(scoped_name)
326
+
327
+ nil
328
+ end
329
+
330
+ def registered_type?(type_name)
331
+ return false unless type_name.is_a?(Symbol)
332
+ return false unless @api_class
333
+
334
+ @api_class.type_registry.key?(type_name) || @api_class.enum_registry.key?(type_name)
335
+ end
336
+ end
337
+ end
338
+ end
339
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Apiwork
4
+ module Introspection
5
+ module Dump
6
+ class << self
7
+ def api(api_class)
8
+ API.new(api_class).to_h
9
+ end
10
+
11
+ def contract(contract_class, expand: false)
12
+ Contract.new(contract_class, expand:).to_h
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Apiwork
4
+ module Introspection
5
+ # @api public
6
+ # Wraps enum type definitions.
7
+ #
8
+ # @example
9
+ # api.enums[:status].values # => ["draft", "published", "archived"]
10
+ # api.enums[:status].description # => "Document status"
11
+ # api.enums[:status].deprecated? # => false
12
+ class Enum
13
+ def initialize(dump)
14
+ @dump = dump
15
+ end
16
+
17
+ # @api public
18
+ # The values for this enum.
19
+ #
20
+ # @return [Array<String>]
21
+ def values
22
+ @dump[:values]
23
+ end
24
+
25
+ # @api public
26
+ # The description for this enum.
27
+ #
28
+ # @return [String, nil]
29
+ def description
30
+ @dump[:description]
31
+ end
32
+
33
+ # @api public
34
+ # The example for this enum.
35
+ #
36
+ # @return [String, nil]
37
+ def example
38
+ @dump[:example]
39
+ end
40
+
41
+ # @api public
42
+ # Whether this enum is deprecated.
43
+ #
44
+ # @return [Boolean]
45
+ def deprecated?
46
+ @dump[:deprecated]
47
+ end
48
+
49
+ # @api public
50
+ # Converts this enum to a hash.
51
+ #
52
+ # @return [Hash]
53
+ def to_h
54
+ {
55
+ deprecated: deprecated?,
56
+ description: description,
57
+ example: example,
58
+ values: values,
59
+ }
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Apiwork
4
+ module Introspection
5
+ # @api public
6
+ # Wraps error code definitions.
7
+ #
8
+ # @example
9
+ # api.error_codes[:not_found].status # => 404
10
+ # api.error_codes[:not_found].description # => "Resource not found"
11
+ class ErrorCode
12
+ def initialize(dump)
13
+ @dump = dump
14
+ end
15
+
16
+ # @api public
17
+ # The description for this error code.
18
+ #
19
+ # @return [String, nil]
20
+ def description
21
+ @dump[:description]
22
+ end
23
+
24
+ # @api public
25
+ # The status for this error code.
26
+ #
27
+ # @return [Integer]
28
+ def status
29
+ @dump[:status]
30
+ end
31
+
32
+ # @api public
33
+ # Converts this error code to a hash.
34
+ #
35
+ # @return [Hash]
36
+ def to_h
37
+ {
38
+ description: description,
39
+ status: status,
40
+ }
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,88 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Apiwork
4
+ module Introspection
5
+ module Param
6
+ # @api public
7
+ # Array param representing ordered collections.
8
+ #
9
+ # @example Basic usage
10
+ # param.type # => :array
11
+ # param.array? # => true
12
+ # param.scalar? # => false
13
+ #
14
+ # @example Element type
15
+ # param.of # => Param (element type) or nil
16
+ # param.shape # => {} or { field: Param, ... }
17
+ #
18
+ # @example Constraints
19
+ # param.min # => 1 or nil
20
+ # param.max # => 10 or nil
21
+ # param.boundable? # => true
22
+ class Array < Base
23
+ # @api public
24
+ # The of for this param.
25
+ #
26
+ # @return [Param::Base, nil]
27
+ def of
28
+ @of ||= @dump[:of] ? Param.build(@dump[:of]) : nil
29
+ end
30
+
31
+ # @api public
32
+ # The shape for this param.
33
+ #
34
+ # @return [Hash{Symbol => Param::Base}]
35
+ def shape
36
+ return @shape if defined?(@shape)
37
+
38
+ @shape = @dump[:shape]&.transform_values { |dump| Param.build(dump) } || {}
39
+ end
40
+
41
+ # @api public
42
+ # The minimum for this param.
43
+ #
44
+ # @return [Integer, nil]
45
+ def min
46
+ @dump[:min]
47
+ end
48
+
49
+ # @api public
50
+ # The maximum for this param.
51
+ #
52
+ # @return [Integer, nil]
53
+ def max
54
+ @dump[:max]
55
+ end
56
+
57
+ # @api public
58
+ # Whether this param is an array.
59
+ #
60
+ # @return [Boolean]
61
+ def array?
62
+ true
63
+ end
64
+
65
+ # @api public
66
+ # Whether this param is boundable.
67
+ #
68
+ # @return [Boolean]
69
+ def boundable?
70
+ true
71
+ end
72
+
73
+ # @api public
74
+ # Converts this param to a hash.
75
+ #
76
+ # @return [Hash]
77
+ def to_h
78
+ result = super
79
+ result[:max] = max
80
+ result[:min] = min
81
+ result[:of] = of&.to_h
82
+ result[:shape] = shape.transform_values(&:to_h)
83
+ result
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end