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.
- checksums.yaml +4 -4
- data/LICENSE.txt +2 -2
- data/README.md +117 -1
- data/Rakefile +5 -3
- data/app/controllers/apiwork/errors_controller.rb +13 -0
- data/app/controllers/apiwork/exports_controller.rb +22 -0
- data/lib/apiwork/abstractable.rb +26 -0
- data/lib/apiwork/adapter/base.rb +369 -0
- data/lib/apiwork/adapter/builder/api/base.rb +66 -0
- data/lib/apiwork/adapter/builder/contract/base.rb +86 -0
- data/lib/apiwork/adapter/capability/api/base.rb +51 -0
- data/lib/apiwork/adapter/capability/api/scope.rb +64 -0
- data/lib/apiwork/adapter/capability/base.rb +291 -0
- data/lib/apiwork/adapter/capability/contract/base.rb +37 -0
- data/lib/apiwork/adapter/capability/contract/scope.rb +110 -0
- data/lib/apiwork/adapter/capability/operation/base.rb +172 -0
- data/lib/apiwork/adapter/capability/operation/metadata_shape.rb +165 -0
- data/lib/apiwork/adapter/capability/result.rb +21 -0
- data/lib/apiwork/adapter/capability/runner.rb +56 -0
- data/lib/apiwork/adapter/capability/transformer/request/base.rb +72 -0
- data/lib/apiwork/adapter/capability/transformer/response/base.rb +45 -0
- data/lib/apiwork/adapter/registry.rb +16 -0
- data/lib/apiwork/adapter/serializer/error/base.rb +72 -0
- data/lib/apiwork/adapter/serializer/error/default/api_builder.rb +32 -0
- data/lib/apiwork/adapter/serializer/error/default.rb +37 -0
- data/lib/apiwork/adapter/serializer/resource/base.rb +84 -0
- data/lib/apiwork/adapter/serializer/resource/default/contract_builder.rb +209 -0
- data/lib/apiwork/adapter/serializer/resource/default.rb +39 -0
- data/lib/apiwork/adapter/standard/capability/filtering/api_builder.rb +75 -0
- data/lib/apiwork/adapter/standard/capability/filtering/constants.rb +37 -0
- data/lib/apiwork/adapter/standard/capability/filtering/contract_builder.rb +193 -0
- data/lib/apiwork/adapter/standard/capability/filtering/operation/filter/builder.rb +47 -0
- data/lib/apiwork/adapter/standard/capability/filtering/operation/filter/operator_builder.rb +36 -0
- data/lib/apiwork/adapter/standard/capability/filtering/operation/filter.rb +462 -0
- data/lib/apiwork/adapter/standard/capability/filtering/operation.rb +22 -0
- data/lib/apiwork/adapter/standard/capability/filtering/request_transformer.rb +47 -0
- data/lib/apiwork/adapter/standard/capability/filtering.rb +18 -0
- data/lib/apiwork/adapter/standard/capability/including/contract_builder.rb +169 -0
- data/lib/apiwork/adapter/standard/capability/including/operation.rb +20 -0
- data/lib/apiwork/adapter/standard/capability/including.rb +16 -0
- data/lib/apiwork/adapter/standard/capability/pagination/api_builder.rb +34 -0
- data/lib/apiwork/adapter/standard/capability/pagination/contract_builder.rb +35 -0
- data/lib/apiwork/adapter/standard/capability/pagination/operation/paginate/cursor.rb +84 -0
- data/lib/apiwork/adapter/standard/capability/pagination/operation/paginate/offset.rb +66 -0
- data/lib/apiwork/adapter/standard/capability/pagination/operation/paginate.rb +24 -0
- data/lib/apiwork/adapter/standard/capability/pagination/operation.rb +24 -0
- data/lib/apiwork/adapter/standard/capability/pagination.rb +21 -0
- data/lib/apiwork/adapter/standard/capability/sorting/api_builder.rb +19 -0
- data/lib/apiwork/adapter/standard/capability/sorting/contract_builder.rb +84 -0
- data/lib/apiwork/adapter/standard/capability/sorting/operation/sort.rb +83 -0
- data/lib/apiwork/adapter/standard/capability/sorting/operation.rb +22 -0
- data/lib/apiwork/adapter/standard/capability/sorting.rb +17 -0
- data/lib/apiwork/adapter/standard/capability/writing/constants.rb +15 -0
- data/lib/apiwork/adapter/standard/capability/writing/contract_builder.rb +253 -0
- data/lib/apiwork/adapter/standard/capability/writing/operation/issue_mapper.rb +210 -0
- data/lib/apiwork/adapter/standard/capability/writing/operation.rb +32 -0
- data/lib/apiwork/adapter/standard/capability/writing/request_transformer.rb +37 -0
- data/lib/apiwork/adapter/standard/capability/writing.rb +17 -0
- data/lib/apiwork/adapter/standard/includes_resolver.rb +106 -0
- data/lib/apiwork/adapter/standard.rb +22 -0
- data/lib/apiwork/adapter/wrapper/base.rb +70 -0
- data/lib/apiwork/adapter/wrapper/collection/base.rb +60 -0
- data/lib/apiwork/adapter/wrapper/collection/default.rb +47 -0
- data/lib/apiwork/adapter/wrapper/error/base.rb +30 -0
- data/lib/apiwork/adapter/wrapper/error/default.rb +34 -0
- data/lib/apiwork/adapter/wrapper/member/base.rb +58 -0
- data/lib/apiwork/adapter/wrapper/member/default.rb +40 -0
- data/lib/apiwork/adapter/wrapper/shape.rb +203 -0
- data/lib/apiwork/adapter.rb +50 -0
- data/lib/apiwork/api/base.rb +802 -0
- data/lib/apiwork/api/element.rb +110 -0
- data/lib/apiwork/api/enum_registry/definition.rb +51 -0
- data/lib/apiwork/api/enum_registry.rb +98 -0
- data/lib/apiwork/api/info/contact.rb +67 -0
- data/lib/apiwork/api/info/license.rb +50 -0
- data/lib/apiwork/api/info/server.rb +50 -0
- data/lib/apiwork/api/info.rb +221 -0
- data/lib/apiwork/api/object.rb +235 -0
- data/lib/apiwork/api/registry.rb +33 -0
- data/lib/apiwork/api/representation_registry.rb +76 -0
- data/lib/apiwork/api/resource/action.rb +41 -0
- data/lib/apiwork/api/resource.rb +648 -0
- data/lib/apiwork/api/router.rb +104 -0
- data/lib/apiwork/api/type_registry/definition.rb +117 -0
- data/lib/apiwork/api/type_registry.rb +99 -0
- data/lib/apiwork/api/union.rb +49 -0
- data/lib/apiwork/api.rb +85 -0
- data/lib/apiwork/configurable.rb +71 -0
- data/lib/apiwork/configuration/option.rb +125 -0
- data/lib/apiwork/configuration/validatable.rb +25 -0
- data/lib/apiwork/configuration.rb +95 -0
- data/lib/apiwork/configuration_error.rb +6 -0
- data/lib/apiwork/constraint_error.rb +20 -0
- data/lib/apiwork/contract/action/request.rb +79 -0
- data/lib/apiwork/contract/action/response.rb +87 -0
- data/lib/apiwork/contract/action.rb +258 -0
- data/lib/apiwork/contract/base.rb +714 -0
- data/lib/apiwork/contract/element.rb +130 -0
- data/lib/apiwork/contract/object/coercer.rb +194 -0
- data/lib/apiwork/contract/object/deserializer.rb +101 -0
- data/lib/apiwork/contract/object/transformer.rb +95 -0
- data/lib/apiwork/contract/object/validator/result.rb +27 -0
- data/lib/apiwork/contract/object/validator.rb +734 -0
- data/lib/apiwork/contract/object.rb +566 -0
- data/lib/apiwork/contract/request_parser/result.rb +25 -0
- data/lib/apiwork/contract/request_parser.rb +72 -0
- data/lib/apiwork/contract/response_parser/result.rb +25 -0
- data/lib/apiwork/contract/response_parser.rb +35 -0
- data/lib/apiwork/contract/union.rb +56 -0
- data/lib/apiwork/contract_error.rb +9 -0
- data/lib/apiwork/controller.rb +300 -0
- data/lib/apiwork/domain_error.rb +13 -0
- data/lib/apiwork/element.rb +386 -0
- data/lib/apiwork/engine.rb +20 -0
- data/lib/apiwork/error.rb +6 -0
- data/lib/apiwork/error_code/definition.rb +63 -0
- data/lib/apiwork/error_code/registry.rb +18 -0
- data/lib/apiwork/error_code.rb +132 -0
- data/lib/apiwork/export/base.rb +291 -0
- data/lib/apiwork/export/open_api.rb +600 -0
- data/lib/apiwork/export/pipeline/writer.rb +66 -0
- data/lib/apiwork/export/pipeline.rb +84 -0
- data/lib/apiwork/export/registry.rb +16 -0
- data/lib/apiwork/export/surface_resolver.rb +189 -0
- data/lib/apiwork/export/type_analysis.rb +170 -0
- data/lib/apiwork/export/type_script.rb +23 -0
- data/lib/apiwork/export/type_script_mapper.rb +349 -0
- data/lib/apiwork/export/zod.rb +39 -0
- data/lib/apiwork/export/zod_mapper.rb +421 -0
- data/lib/apiwork/export.rb +80 -0
- data/lib/apiwork/http_error.rb +16 -0
- data/lib/apiwork/introspection/action/request.rb +66 -0
- data/lib/apiwork/introspection/action/response.rb +57 -0
- data/lib/apiwork/introspection/action.rb +124 -0
- data/lib/apiwork/introspection/api/info/contact.rb +59 -0
- data/lib/apiwork/introspection/api/info/license.rb +49 -0
- data/lib/apiwork/introspection/api/info/server.rb +50 -0
- data/lib/apiwork/introspection/api/info.rb +107 -0
- data/lib/apiwork/introspection/api/resource.rb +83 -0
- data/lib/apiwork/introspection/api.rb +92 -0
- data/lib/apiwork/introspection/contract.rb +63 -0
- data/lib/apiwork/introspection/dump/action.rb +101 -0
- data/lib/apiwork/introspection/dump/api.rb +119 -0
- data/lib/apiwork/introspection/dump/contract.rb +129 -0
- data/lib/apiwork/introspection/dump/param.rb +486 -0
- data/lib/apiwork/introspection/dump/resource.rb +112 -0
- data/lib/apiwork/introspection/dump/type.rb +339 -0
- data/lib/apiwork/introspection/dump.rb +17 -0
- data/lib/apiwork/introspection/enum.rb +63 -0
- data/lib/apiwork/introspection/error_code.rb +44 -0
- data/lib/apiwork/introspection/param/array.rb +88 -0
- data/lib/apiwork/introspection/param/base.rb +285 -0
- data/lib/apiwork/introspection/param/binary.rb +73 -0
- data/lib/apiwork/introspection/param/boolean.rb +73 -0
- data/lib/apiwork/introspection/param/date.rb +73 -0
- data/lib/apiwork/introspection/param/date_time.rb +73 -0
- data/lib/apiwork/introspection/param/decimal.rb +121 -0
- data/lib/apiwork/introspection/param/integer.rb +131 -0
- data/lib/apiwork/introspection/param/literal.rb +45 -0
- data/lib/apiwork/introspection/param/number.rb +121 -0
- data/lib/apiwork/introspection/param/object.rb +59 -0
- data/lib/apiwork/introspection/param/reference.rb +45 -0
- data/lib/apiwork/introspection/param/string.rb +122 -0
- data/lib/apiwork/introspection/param/time.rb +73 -0
- data/lib/apiwork/introspection/param/union.rb +57 -0
- data/lib/apiwork/introspection/param/unknown.rb +26 -0
- data/lib/apiwork/introspection/param/uuid.rb +73 -0
- data/lib/apiwork/introspection/param.rb +31 -0
- data/lib/apiwork/introspection/type.rb +129 -0
- data/lib/apiwork/introspection.rb +28 -0
- data/lib/apiwork/issue.rb +80 -0
- data/lib/apiwork/json_pointer.rb +21 -0
- data/lib/apiwork/object.rb +1618 -0
- data/lib/apiwork/reference_generator.rb +622 -0
- data/lib/apiwork/registry.rb +56 -0
- data/lib/apiwork/representation/association.rb +391 -0
- data/lib/apiwork/representation/attribute.rb +335 -0
- data/lib/apiwork/representation/base.rb +819 -0
- data/lib/apiwork/representation/deserializer.rb +95 -0
- data/lib/apiwork/representation/element.rb +128 -0
- data/lib/apiwork/representation/inheritance.rb +78 -0
- data/lib/apiwork/representation/model_detector.rb +75 -0
- data/lib/apiwork/representation/root_key.rb +35 -0
- data/lib/apiwork/representation/serializer.rb +127 -0
- data/lib/apiwork/request.rb +79 -0
- data/lib/apiwork/response.rb +56 -0
- data/lib/apiwork/union.rb +102 -0
- data/lib/apiwork/version.rb +2 -2
- data/lib/apiwork.rb +61 -3
- data/lib/generators/apiwork/api_generator.rb +38 -0
- data/lib/generators/apiwork/contract_generator.rb +25 -0
- data/lib/generators/apiwork/install_generator.rb +27 -0
- data/lib/generators/apiwork/representation_generator.rb +25 -0
- data/lib/generators/apiwork/templates/api/api.rb.tt +4 -0
- data/lib/generators/apiwork/templates/contract/contract.rb.tt +6 -0
- data/lib/generators/apiwork/templates/install/application_contract.rb.tt +5 -0
- data/lib/generators/apiwork/templates/install/application_representation.rb.tt +5 -0
- data/lib/generators/apiwork/templates/representation/representation.rb.tt +6 -0
- data/lib/tasks/apiwork.rake +102 -0
- metadata +319 -19
- data/.rubocop.yml +0 -8
- 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
|