smithy 2.0.0.pre0 → 2.0.0.pre1
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/VERSION +1 -1
- data/bin/smithy-ruby +1 -4
- data/lib/smithy/command.rb +68 -0
- data/lib/smithy/generators/base.rb +19 -0
- data/lib/smithy/generators/client.rb +106 -0
- data/lib/smithy/generators/schema.rb +61 -0
- data/lib/smithy/generators.rb +29 -0
- data/lib/smithy/model/flattener.rb +114 -0
- data/lib/smithy/model/operation_parser.rb +42 -0
- data/lib/smithy/model/rbs.rb +57 -0
- data/lib/smithy/model/service_index.rb +51 -0
- data/lib/smithy/model/service_parser.rb +74 -0
- data/lib/smithy/model/shape.rb +49 -0
- data/lib/smithy/model/structure_parser.rb +43 -0
- data/lib/smithy/model/yard.rb +100 -0
- data/lib/smithy/model.rb +54 -0
- data/lib/smithy/plan.rb +79 -3
- data/lib/smithy/templates/client/auth_parameters.erb +29 -0
- data/lib/smithy/templates/client/auth_parameters_rbs.erb +14 -0
- data/lib/smithy/templates/client/auth_plugin.erb +115 -0
- data/lib/smithy/templates/client/auth_resolver.erb +16 -0
- data/lib/smithy/templates/client/auth_resolver_rbs.erb +5 -0
- data/lib/smithy/templates/client/client.erb +142 -0
- data/lib/smithy/templates/client/client_rbs.erb +29 -0
- data/lib/smithy/templates/client/customizations.erb +3 -0
- data/lib/smithy/templates/client/endpoint_parameters.erb +65 -0
- data/lib/smithy/templates/client/endpoint_parameters_rbs.erb +13 -0
- data/lib/smithy/templates/client/endpoint_plugin.erb +58 -0
- data/lib/smithy/templates/client/endpoint_provider.erb +15 -0
- data/lib/smithy/templates/client/endpoint_provider_rbs.erb +5 -0
- data/lib/smithy/templates/client/endpoint_provider_spec.erb +70 -0
- data/lib/smithy/templates/client/errors.erb +69 -0
- data/lib/smithy/templates/client/errors_rbs.erb +17 -0
- data/lib/smithy/templates/client/gemspec.erb +17 -0
- data/lib/smithy/templates/client/module.erb +22 -0
- data/lib/smithy/templates/client/module_rbs.erb +7 -0
- data/lib/smithy/templates/client/paginators.erb +33 -0
- data/lib/smithy/templates/client/protocol_spec.erb +144 -0
- data/lib/smithy/templates/client/rubocop_yml.erb +33 -0
- data/lib/smithy/templates/client/schema.erb +76 -0
- data/lib/smithy/templates/client/schema_rbs.erb +13 -0
- data/lib/smithy/templates/client/spec_helper.erb +10 -0
- data/lib/smithy/templates/client/types.erb +64 -0
- data/lib/smithy/templates/client/types_rbs.erb +47 -0
- data/lib/smithy/templates/client/waiters.erb +42 -0
- data/lib/smithy/util/hash_formatter.rb +124 -0
- data/lib/smithy/util/underscore.rb +18 -0
- data/lib/smithy/util.rb +9 -0
- data/lib/smithy/views/client/auth_parameter.rb +29 -0
- data/lib/smithy/views/client/auth_parameters.rb +23 -0
- data/lib/smithy/views/client/auth_parameters_rbs.rb +23 -0
- data/lib/smithy/views/client/auth_plugin.rb +35 -0
- data/lib/smithy/views/client/auth_resolver.rb +125 -0
- data/lib/smithy/views/client/auth_resolver_rbs.rb +19 -0
- data/lib/smithy/views/client/client.rb +208 -0
- data/lib/smithy/views/client/client_rbs.rb +231 -0
- data/lib/smithy/views/client/customizations.rb +10 -0
- data/lib/smithy/views/client/endpoint_parameter.rb +156 -0
- data/lib/smithy/views/client/endpoint_parameters.rb +43 -0
- data/lib/smithy/views/client/endpoint_parameters_rbs.rb +28 -0
- data/lib/smithy/views/client/endpoint_plugin.rb +27 -0
- data/lib/smithy/views/client/endpoint_provider.rb +241 -0
- data/lib/smithy/views/client/endpoint_provider_rbs.rb +19 -0
- data/lib/smithy/views/client/endpoint_provider_spec.rb +137 -0
- data/lib/smithy/views/client/errors.rb +88 -0
- data/lib/smithy/views/client/errors_rbs.rb +12 -0
- data/lib/smithy/views/client/gemspec.rb +36 -0
- data/lib/smithy/views/client/module.rb +107 -0
- data/lib/smithy/views/client/module_rbs.rb +20 -0
- data/lib/smithy/views/client/operation_examples.rb +157 -0
- data/lib/smithy/views/client/paginators.rb +108 -0
- data/lib/smithy/views/client/plugin.rb +29 -0
- data/lib/smithy/views/client/plugin_list.rb +57 -0
- data/lib/smithy/views/client/protocol_spec.rb +254 -0
- data/lib/smithy/views/client/request_response_example.rb +179 -0
- data/lib/smithy/views/client/rubocop_yml.rb +19 -0
- data/lib/smithy/views/client/schema.rb +356 -0
- data/lib/smithy/views/client/schema_rbs.rb +84 -0
- data/lib/smithy/views/client/shape_to_hash.rb +99 -0
- data/lib/smithy/views/client/spec_helper.rb +19 -0
- data/lib/smithy/views/client/types.rb +293 -0
- data/lib/smithy/views/client/types_rbs.rb +67 -0
- data/lib/smithy/views/client/waiters.rb +82 -0
- data/lib/smithy/views/client.rb +47 -0
- data/lib/smithy/views/view.rb +30 -0
- data/lib/smithy/views.rb +9 -0
- data/lib/smithy/weld.rb +109 -0
- data/lib/smithy/welds/auth/anonymous_auth.rb +31 -0
- data/lib/smithy/welds/auth/http_api_key_auth.rb +34 -0
- data/lib/smithy/welds/auth/http_basic_auth.rb +34 -0
- data/lib/smithy/welds/auth/http_bearer_auth.rb +34 -0
- data/lib/smithy/welds/auth/http_digest_auth.rb +34 -0
- data/lib/smithy/welds/plugins.rb +54 -0
- data/lib/smithy/welds/rpc_v2_cbor.rb +20 -0
- data/lib/smithy/welds/rubocop.rb +33 -0
- data/lib/smithy/welds/transforms/default_endpoint_rules.json +35 -0
- data/lib/smithy/welds/transforms/default_endpoint_tests.json +24 -0
- data/lib/smithy/welds/transforms/endpoints.rb +68 -0
- data/lib/smithy/welds/transforms/synthetic_input_output.rb +60 -0
- data/lib/smithy/welds.rb +29 -0
- data/lib/smithy.rb +33 -2
- metadata +144 -9
@@ -0,0 +1,208 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Smithy
|
4
|
+
module Views
|
5
|
+
module Client
|
6
|
+
# @api private
|
7
|
+
class Client < View
|
8
|
+
def initialize(plan, code_generated_plugins)
|
9
|
+
@plan = plan
|
10
|
+
@model = plan.model
|
11
|
+
_, @service = plan.service.first
|
12
|
+
@plugins = PluginList.new(plan, code_generated_plugins)
|
13
|
+
super()
|
14
|
+
end
|
15
|
+
|
16
|
+
def require_plugins
|
17
|
+
requires = []
|
18
|
+
@plugins.each do |plugin|
|
19
|
+
next if !@plan.destination_root && plugin.require_relative?
|
20
|
+
|
21
|
+
requires << "require#{'_relative' if plugin.require_relative?} '#{plugin.require_path}'"
|
22
|
+
end
|
23
|
+
requires
|
24
|
+
end
|
25
|
+
|
26
|
+
def module_name
|
27
|
+
@plan.module_name
|
28
|
+
end
|
29
|
+
|
30
|
+
def service_name
|
31
|
+
id, = @plan.service.first
|
32
|
+
Model::Shape.name(id).camelize
|
33
|
+
end
|
34
|
+
|
35
|
+
def add_plugins
|
36
|
+
@plugins.map(&:class_name)
|
37
|
+
end
|
38
|
+
|
39
|
+
def docstrings
|
40
|
+
options = @plugins.map(&:options).flatten.sort_by(&:name)
|
41
|
+
documentation = {}
|
42
|
+
options.each do |option|
|
43
|
+
documentation[option.name] = option_docstrings(option) if option.docstring
|
44
|
+
end
|
45
|
+
lines = []
|
46
|
+
documentation.each_value { |value| lines.concat(value) }
|
47
|
+
lines
|
48
|
+
end
|
49
|
+
|
50
|
+
def operations
|
51
|
+
Model::ServiceIndex
|
52
|
+
.new(@model)
|
53
|
+
.operations_for(@plan.service)
|
54
|
+
.map { |id, operation| Operation.new(@service, @model, id, operation) }
|
55
|
+
end
|
56
|
+
|
57
|
+
def gem_name
|
58
|
+
@plan.gem_name
|
59
|
+
end
|
60
|
+
|
61
|
+
def gem_version
|
62
|
+
@plan.gem_version
|
63
|
+
end
|
64
|
+
|
65
|
+
# TODO: re-evaluate this approach - perhaps plugins should register protocol classes with options
|
66
|
+
def protocols
|
67
|
+
@protocols ||= @plan.welds.map(&:protocols).reduce({}, :merge)
|
68
|
+
end
|
69
|
+
|
70
|
+
def waiters
|
71
|
+
waiters = Views::Client::Waiters.new(@plan).waiters
|
72
|
+
return ['{}'] if waiters.empty?
|
73
|
+
|
74
|
+
lines = ['{']
|
75
|
+
waiters.each do |waiter|
|
76
|
+
lines << " #{waiter.name.underscore}: Waiters::#{waiter.name},"
|
77
|
+
end
|
78
|
+
lines.last.chomp!(',') if lines.last.end_with?(',')
|
79
|
+
lines << '}'
|
80
|
+
lines
|
81
|
+
end
|
82
|
+
|
83
|
+
private
|
84
|
+
|
85
|
+
def option_docstrings(option)
|
86
|
+
lines = []
|
87
|
+
lines << option_tag(option)
|
88
|
+
documentation = option.docstring.split("\n").map { |line| " #{line}" }
|
89
|
+
lines.concat(documentation)
|
90
|
+
lines
|
91
|
+
end
|
92
|
+
|
93
|
+
def option_tag(option)
|
94
|
+
tag = StringIO.new
|
95
|
+
tag << '@option options'
|
96
|
+
tag << " [#{option.doc_type}]" if option.doc_type
|
97
|
+
tag << " :#{option.name}"
|
98
|
+
default = option_default(option)
|
99
|
+
tag << " (#{default})" if default
|
100
|
+
tag.string
|
101
|
+
end
|
102
|
+
|
103
|
+
def option_default(option)
|
104
|
+
default = option.doc_default || option.default
|
105
|
+
return default unless option.name == :protocol
|
106
|
+
|
107
|
+
default.gsub('<DEFAULT_PROTOCOL>', protocols.keys.first || 'nil')
|
108
|
+
end
|
109
|
+
|
110
|
+
# @api private
|
111
|
+
class Operation
|
112
|
+
def initialize(service, model, id, operation)
|
113
|
+
@service = service
|
114
|
+
@model = model
|
115
|
+
@id = id
|
116
|
+
@operation = operation
|
117
|
+
@traits = operation.fetch('traits', {})
|
118
|
+
end
|
119
|
+
|
120
|
+
def docstrings # rubocop:disable Metrics/AbcSize
|
121
|
+
lines = []
|
122
|
+
lines.concat(documentation_docstrings)
|
123
|
+
lines.concat(params_docstrings)
|
124
|
+
lines.concat(OperationExamples.new(@model, method_name, @operation).docstrings)
|
125
|
+
lines.concat(RequestResponseExample.new(@model, method_name, @operation).docstrings)
|
126
|
+
lines.concat(deprecated_docstrings)
|
127
|
+
lines.concat(external_documentation_docstrings)
|
128
|
+
lines.concat(since_docstrings)
|
129
|
+
lines.concat(unstable_docstrings)
|
130
|
+
lines.concat(return_docstrings)
|
131
|
+
lines
|
132
|
+
end
|
133
|
+
|
134
|
+
def method_name
|
135
|
+
Model::Shape.name(@id).underscore
|
136
|
+
end
|
137
|
+
|
138
|
+
private
|
139
|
+
|
140
|
+
def documentation_docstrings
|
141
|
+
@traits.fetch('smithy.api#documentation', '').split("\n")
|
142
|
+
end
|
143
|
+
|
144
|
+
def params_docstrings
|
145
|
+
input_target = @operation['input']['target']
|
146
|
+
input = Model.shape(@model, input_target)
|
147
|
+
|
148
|
+
lines = []
|
149
|
+
lines << Model::YARD.param_docstring(@service, @model, input_target, input)
|
150
|
+
input['members'].each do |member_name, member_shape|
|
151
|
+
target = Model.shape(@model, member_shape['target'])
|
152
|
+
docstrings = Model::YARD.option_docstrings(
|
153
|
+
@service,
|
154
|
+
@model,
|
155
|
+
member_shape['target'],
|
156
|
+
target,
|
157
|
+
member_name.underscore,
|
158
|
+
param_docstrings(member_shape, target)
|
159
|
+
)
|
160
|
+
lines.concat(docstrings)
|
161
|
+
end
|
162
|
+
lines
|
163
|
+
end
|
164
|
+
|
165
|
+
def param_docstrings(member_shape, target)
|
166
|
+
documentation = member_shape.fetch('traits', {}).fetch('smithy.api#documentation', '').split("\n")
|
167
|
+
return documentation unless documentation.empty?
|
168
|
+
|
169
|
+
target.fetch('traits', {}).fetch('smithy.api#documentation', '').split("\n")
|
170
|
+
end
|
171
|
+
|
172
|
+
def deprecated_docstrings
|
173
|
+
return [] unless @traits.key?('smithy.api#deprecated')
|
174
|
+
|
175
|
+
message = @traits['smithy.api#deprecated'].fetch('message', '')
|
176
|
+
since = @traits['smithy.api#deprecated'].fetch('since', '')
|
177
|
+
Model::YARD.deprecated_docstrings(message, since)
|
178
|
+
end
|
179
|
+
|
180
|
+
def external_documentation_docstrings
|
181
|
+
return [] unless @traits.key?('smithy.api#externalDocumentation')
|
182
|
+
|
183
|
+
hash = @traits.fetch('smithy.api#externalDocumentation', {})
|
184
|
+
Model::YARD.external_documentation_docstrings(hash)
|
185
|
+
end
|
186
|
+
|
187
|
+
def since_docstrings
|
188
|
+
return [] unless @traits.key?('smithy.api#since')
|
189
|
+
|
190
|
+
[Model::YARD.since_docstring(@traits['smithy.api#since'])]
|
191
|
+
end
|
192
|
+
|
193
|
+
def unstable_docstrings
|
194
|
+
return [] unless @traits.key?('smithy.api#unstable')
|
195
|
+
|
196
|
+
[Model::YARD.unstable_docstring]
|
197
|
+
end
|
198
|
+
|
199
|
+
def return_docstrings
|
200
|
+
output_target = @operation['output']['target']
|
201
|
+
output = Model.shape(@model, output_target)
|
202
|
+
[Model::YARD.return_docstring(@service, @model, output_target, output)]
|
203
|
+
end
|
204
|
+
end
|
205
|
+
end
|
206
|
+
end
|
207
|
+
end
|
208
|
+
end
|
@@ -0,0 +1,231 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Smithy
|
4
|
+
module Views
|
5
|
+
module Client
|
6
|
+
# @api private
|
7
|
+
class ClientRbs < View
|
8
|
+
def initialize(plan, code_generated_plugins)
|
9
|
+
@plan = plan
|
10
|
+
@model = plan.model
|
11
|
+
@plugins = PluginList.new(plan, code_generated_plugins)
|
12
|
+
super()
|
13
|
+
end
|
14
|
+
|
15
|
+
def module_name
|
16
|
+
@plan.module_name
|
17
|
+
end
|
18
|
+
|
19
|
+
def option_types
|
20
|
+
@plugins
|
21
|
+
.map(&:options)
|
22
|
+
.flatten
|
23
|
+
.sort_by(&:name)
|
24
|
+
.select(&:docstring)
|
25
|
+
.to_h { |o| [o.name, rbs_type(o)] }
|
26
|
+
end
|
27
|
+
|
28
|
+
def operations
|
29
|
+
Model::ServiceIndex
|
30
|
+
.new(@model)
|
31
|
+
.operations_for(@plan.service)
|
32
|
+
.map { |id, operation| Operation.new(@model, id, operation) }
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def rbs_type(option)
|
38
|
+
return option.rbs_type if option.rbs_type
|
39
|
+
|
40
|
+
return doc_to_rbs_types(option.doc_type) if option.doc_type
|
41
|
+
|
42
|
+
'untyped'
|
43
|
+
end
|
44
|
+
|
45
|
+
# doc types may specify multiple types combined with ","
|
46
|
+
def doc_to_rbs_types(doc_type)
|
47
|
+
doc_type
|
48
|
+
.to_s
|
49
|
+
.split(',')
|
50
|
+
.map(&:strip)
|
51
|
+
.map { |t| doc_to_rbs_type(t) }
|
52
|
+
.join(' | ')
|
53
|
+
end
|
54
|
+
|
55
|
+
def doc_to_rbs_type(doc_type)
|
56
|
+
case doc_type
|
57
|
+
when 'Boolean' then 'bool'
|
58
|
+
else
|
59
|
+
doc_type
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
# @api private
|
64
|
+
class Operation
|
65
|
+
def initialize(model, id, operation)
|
66
|
+
@model = model
|
67
|
+
@id = id
|
68
|
+
@operation = operation
|
69
|
+
@input = Input.new(model, operation['input']['target'])
|
70
|
+
@output = Output.new(model, operation['output']['target'])
|
71
|
+
end
|
72
|
+
|
73
|
+
attr_reader :input, :output
|
74
|
+
|
75
|
+
def response_interface
|
76
|
+
"_#{Model::Shape.name(@id)}Response"
|
77
|
+
end
|
78
|
+
|
79
|
+
def name
|
80
|
+
Model::Shape.name(@id).underscore
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
# @api private
|
85
|
+
class Output
|
86
|
+
def initialize(model, id)
|
87
|
+
@model = model
|
88
|
+
@id = id
|
89
|
+
@shape = Model.shape(model, id)
|
90
|
+
end
|
91
|
+
|
92
|
+
def type
|
93
|
+
Model::RBS.type(@model, @id, @shape)
|
94
|
+
end
|
95
|
+
|
96
|
+
def member_types
|
97
|
+
@shape.fetch('members', {}).to_h do |member_name, member|
|
98
|
+
target = Model.shape(@model, member['target'])
|
99
|
+
[member_name.underscore, Model::RBS.type(@model, member['target'], target)]
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
# @api private
|
105
|
+
class Input
|
106
|
+
def initialize(model, id)
|
107
|
+
@model = model
|
108
|
+
@id = id
|
109
|
+
@shape = Model.shape(model, id)
|
110
|
+
end
|
111
|
+
|
112
|
+
def members?
|
113
|
+
@shape.fetch('members', {}).any?
|
114
|
+
end
|
115
|
+
|
116
|
+
# @return [Array<String>]
|
117
|
+
def keyword_args
|
118
|
+
lines = []
|
119
|
+
@shape.fetch('members', {}).each do |name, member|
|
120
|
+
member_lines = kwargs_structure_member(name, member['target'])
|
121
|
+
# top level members all need to be considered optional
|
122
|
+
member_lines[0] = "?#{member_lines[0].strip}"
|
123
|
+
lines += member_lines
|
124
|
+
end
|
125
|
+
lines.last&.chomp!(',')
|
126
|
+
lines
|
127
|
+
end
|
128
|
+
|
129
|
+
private
|
130
|
+
|
131
|
+
def kwargs_structure_member(name, id, level = 0, visited = Set.new)
|
132
|
+
return indent(["#{name.underscore}: untyped,"], level) if visited.include?(id)
|
133
|
+
|
134
|
+
visited << id
|
135
|
+
shape = Model.shape(@model, id)
|
136
|
+
if complex?(shape)
|
137
|
+
kwargs_complex_structure_member(level, name, shape, visited)
|
138
|
+
else
|
139
|
+
indent(["#{name.underscore}: #{Model::RBS.type(@model, nil, shape)},"], level)
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
def kwargs_complex_structure_member(level, name, shape, visited)
|
144
|
+
lines = kwargs_complex_shape(shape, level, visited)
|
145
|
+
lines[0] = indent("#{name.underscore}: #{lines[0].strip}", level)
|
146
|
+
lines[lines.size - 1] = "#{lines.last},"
|
147
|
+
lines
|
148
|
+
end
|
149
|
+
|
150
|
+
def kwargs_complex_shape(shape, level, visited)
|
151
|
+
case shape['type']
|
152
|
+
when 'list'
|
153
|
+
kwargs_list(shape, level, visited)
|
154
|
+
when 'map'
|
155
|
+
kwargs_map(shape, level, visited)
|
156
|
+
when 'structure', 'union'
|
157
|
+
kwargs_structure(shape, level, visited)
|
158
|
+
else
|
159
|
+
['untyped']
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
def kwargs_structure(shape, level, visited)
|
164
|
+
lines = [indent('{', level)]
|
165
|
+
shape.fetch('members', {}).each do |name, member|
|
166
|
+
lines += kwargs_structure_member(name, member['target'], level + 1, visited)
|
167
|
+
end
|
168
|
+
lines[lines.size - 1] = lines.last.chomp(',')
|
169
|
+
lines << indent('}', level)
|
170
|
+
lines
|
171
|
+
end
|
172
|
+
|
173
|
+
def kwargs_list(shape, level, visited)
|
174
|
+
member_target = Model.shape(@model, shape['member']['target'])
|
175
|
+
if complex?(member_target)
|
176
|
+
lines = [indent('Array[', level)]
|
177
|
+
lines += kwargs_complex_shape(member_target, level + 1, visited)
|
178
|
+
lines << indent(']', level)
|
179
|
+
lines
|
180
|
+
else
|
181
|
+
sparse = shape.fetch('traits', {}).key?('smithy.api#sparse')
|
182
|
+
indent(
|
183
|
+
["Array[#{Model::RBS.type(@model, shape['member']['target'], member_target)}#{'?' if sparse}]"],
|
184
|
+
level
|
185
|
+
)
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
def kwargs_map(shape, level, visited)
|
190
|
+
key_target = Model.shape(@model, shape['key']['target'])
|
191
|
+
key_type = Model::RBS.type(@model, shape['key']['target'], key_target)
|
192
|
+
value_target = Model.shape(@model, shape['value']['target'])
|
193
|
+
if complex?(value_target)
|
194
|
+
kwargs_complex__map(key_type, level, value_target, visited)
|
195
|
+
else
|
196
|
+
kwargs_simple_map(key_type, level, shape, value_target)
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
def kwargs_simple_map(key_type, level, shape, value_target)
|
201
|
+
sparse = shape.fetch('traits', {}).key?('smithy.api#sparse')
|
202
|
+
value_type = Model::RBS.type(@model, shape['value']['target'], value_target)
|
203
|
+
indent(
|
204
|
+
["Hash[#{key_type}, #{value_type}#{'?' if sparse}]"],
|
205
|
+
level
|
206
|
+
)
|
207
|
+
end
|
208
|
+
|
209
|
+
def kwargs_complex__map(key_type, level, value_target, visited)
|
210
|
+
lines = [indent("Hash[#{key_type},", level)]
|
211
|
+
lines += kwargs_complex_shape(value_target, level + 1, visited)
|
212
|
+
lines << indent(']', level)
|
213
|
+
lines
|
214
|
+
end
|
215
|
+
|
216
|
+
def complex?(shape)
|
217
|
+
%w[list map structure union].include?(shape['type'])
|
218
|
+
end
|
219
|
+
|
220
|
+
def indent(str, level)
|
221
|
+
case str
|
222
|
+
when Array then str.map { |s| indent(s, level) }
|
223
|
+
else
|
224
|
+
(' ' * level) + str
|
225
|
+
end
|
226
|
+
end
|
227
|
+
end
|
228
|
+
end
|
229
|
+
end
|
230
|
+
end
|
231
|
+
end
|
@@ -0,0 +1,156 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Smithy
|
4
|
+
module Views
|
5
|
+
module Client
|
6
|
+
# @api private
|
7
|
+
class EndpointParameter
|
8
|
+
def initialize(id, data, plan, operation = nil)
|
9
|
+
@id = id
|
10
|
+
@data = data
|
11
|
+
@plan = plan
|
12
|
+
@model = @plan.model
|
13
|
+
@service = @plan.service.values.first
|
14
|
+
|
15
|
+
@operation = operation
|
16
|
+
|
17
|
+
@name = @id.underscore
|
18
|
+
@value, @source = endpoint_parameter_value(operation)
|
19
|
+
end
|
20
|
+
|
21
|
+
attr_reader :id, :data, :name, :source, :value
|
22
|
+
|
23
|
+
def docstrings
|
24
|
+
@data['documentation'].split("\n")
|
25
|
+
end
|
26
|
+
|
27
|
+
def documentation_type
|
28
|
+
case @data['type'].downcase
|
29
|
+
when 'stringarray' then 'Array<String>'
|
30
|
+
when 'string' then 'String'
|
31
|
+
when 'boolean' then 'Boolean'
|
32
|
+
else
|
33
|
+
@data['type']
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def rbs_type
|
38
|
+
case @data['type'].downcase
|
39
|
+
when 'stringarray' then 'Array[String]'
|
40
|
+
when 'string' then 'String'
|
41
|
+
when 'boolean' then 'bool'
|
42
|
+
else
|
43
|
+
@data['type']
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def default_value
|
48
|
+
default = @data['default']
|
49
|
+
case default
|
50
|
+
when String then "\"#{default}\""
|
51
|
+
when nil then 'nil'
|
52
|
+
else
|
53
|
+
default
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def validate_required?
|
58
|
+
@data['required'] && !@data['default']
|
59
|
+
end
|
60
|
+
|
61
|
+
def create_from_config?
|
62
|
+
@source == 'config'
|
63
|
+
end
|
64
|
+
|
65
|
+
def built_in?
|
66
|
+
@data['builtIn']
|
67
|
+
end
|
68
|
+
|
69
|
+
def built_in_binding
|
70
|
+
@built_in_binding ||=
|
71
|
+
@plan.welds
|
72
|
+
.map(&:endpoint_built_in_bindings)
|
73
|
+
.map { |b| b[@data['builtIn']] }
|
74
|
+
.find { |b| !b.nil? }
|
75
|
+
end
|
76
|
+
|
77
|
+
def client_context?
|
78
|
+
@service['traits']['smithy.rules#clientContextParams']&.key?(@id) && !@data['builtIn']
|
79
|
+
end
|
80
|
+
|
81
|
+
def client_context_doc
|
82
|
+
@service['traits']['smithy.rules#clientContextParams'][@id]['documentation']
|
83
|
+
end
|
84
|
+
|
85
|
+
private
|
86
|
+
|
87
|
+
# Highest to lowest priority:
|
88
|
+
# 1. staticContextParams
|
89
|
+
# 2. contextParam
|
90
|
+
# 3. operationContextParams
|
91
|
+
# 4. clientContextParams (always sourced from config)
|
92
|
+
# 5. Built-In Bindings (sourced from config in most cases)
|
93
|
+
# @return [value, source]. source may be one of [operation, config, default]
|
94
|
+
def endpoint_parameter_value(operation)
|
95
|
+
unless operation.nil?
|
96
|
+
value = static_context_param(operation)
|
97
|
+
value = context_param_value(operation) if value.nil?
|
98
|
+
value = operation_context_param_value(operation) if value.nil?
|
99
|
+
source = 'operation' unless value.nil?
|
100
|
+
end
|
101
|
+
|
102
|
+
value, source = client_context_param_value if value.nil?
|
103
|
+
value, source = built_in_param_value if value.nil?
|
104
|
+
|
105
|
+
[value, source]
|
106
|
+
end
|
107
|
+
|
108
|
+
def static_context_param(operation)
|
109
|
+
value = operation.dig('traits', 'smithy.rules#staticContextParams', @id, 'value')
|
110
|
+
if !value.nil? && value.is_a?(String)
|
111
|
+
"\"#{value}\""
|
112
|
+
else
|
113
|
+
value
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
def context_param_value(operation)
|
118
|
+
return nil unless operation['input']
|
119
|
+
|
120
|
+
input = Model.shape(@model, operation['input']['target'])
|
121
|
+
context_param_member(input['members'])
|
122
|
+
end
|
123
|
+
|
124
|
+
def context_param_member(members)
|
125
|
+
members.find do |(member_name, member_def)|
|
126
|
+
context_param = member_def.fetch('traits', {}).fetch('smithy.rules#contextParam', {})
|
127
|
+
break "params[:#{member_name.underscore}]" if context_param.fetch('name', nil) == @id
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
def operation_context_param_value(operation)
|
132
|
+
return nil unless operation['input']
|
133
|
+
|
134
|
+
binding = operation.fetch('traits', {}).fetch('smithy.rules#operationContextParams', {})[@id]
|
135
|
+
|
136
|
+
return nil unless binding
|
137
|
+
|
138
|
+
"JMESPath.search(\"#{Util::Underscore.underscore_jmespath(binding['path'])}\", params)"
|
139
|
+
end
|
140
|
+
|
141
|
+
def client_context_param_value
|
142
|
+
return unless client_context?
|
143
|
+
|
144
|
+
["config.#{name}", 'config']
|
145
|
+
end
|
146
|
+
|
147
|
+
def built_in_param_value
|
148
|
+
return unless @data['builtIn']
|
149
|
+
raise ArgumentError, "Endpoint built-in not available for #{@data['builtIn']}" unless built_in_binding
|
150
|
+
|
151
|
+
[built_in_binding[:render_build].call(@plan, nil), 'config']
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Smithy
|
4
|
+
module Views
|
5
|
+
module Client
|
6
|
+
# @api private
|
7
|
+
class EndpointParameters < View
|
8
|
+
def initialize(plan)
|
9
|
+
@plan = plan
|
10
|
+
@model = plan.model
|
11
|
+
service = @plan.service
|
12
|
+
@endpoint_rules = service.values.first['traits']['smithy.rules#endpointRuleSet']
|
13
|
+
@operations = Model::ServiceIndex.new(@model).operations_for(@plan.service)
|
14
|
+
@parameters = @endpoint_rules['parameters']
|
15
|
+
.map { |id, data| EndpointParameter.new(id, data, @plan) }
|
16
|
+
@operation_params = build_operation_params
|
17
|
+
|
18
|
+
super()
|
19
|
+
end
|
20
|
+
|
21
|
+
attr_reader :parameters, :operation_params
|
22
|
+
|
23
|
+
def module_name
|
24
|
+
@plan.module_name
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def build_operation_params
|
30
|
+
operation_params = {}
|
31
|
+
@operations.each do |operation_id, operation|
|
32
|
+
name = operation_id.split('#').last.underscore
|
33
|
+
params = @endpoint_rules['parameters']
|
34
|
+
.map { |id, data| EndpointParameter.new(id, data, @plan, operation) }
|
35
|
+
.select { |p| p.source == 'operation' }
|
36
|
+
operation_params[name] = params unless params.empty?
|
37
|
+
end
|
38
|
+
operation_params
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Smithy
|
4
|
+
module Views
|
5
|
+
module Client
|
6
|
+
# @api private
|
7
|
+
class EndpointParametersRbs < View
|
8
|
+
def initialize(plan)
|
9
|
+
@plan = plan
|
10
|
+
@model = plan.model
|
11
|
+
service = @plan.service
|
12
|
+
@endpoint_rules = service.values.first['traits']['smithy.rules#endpointRuleSet']
|
13
|
+
@operations = Model::ServiceIndex.new(@model).operations_for(@plan.service)
|
14
|
+
@parameters = @endpoint_rules['parameters']
|
15
|
+
.map { |id, data| EndpointParameter.new(id, data, @plan) }
|
16
|
+
|
17
|
+
super()
|
18
|
+
end
|
19
|
+
|
20
|
+
attr_reader :parameters
|
21
|
+
|
22
|
+
def module_name
|
23
|
+
@plan.module_name
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Smithy
|
4
|
+
module Views
|
5
|
+
module Client
|
6
|
+
# @api private
|
7
|
+
class EndpointPlugin < View
|
8
|
+
def initialize(plan)
|
9
|
+
@plan = plan
|
10
|
+
@model = plan.model
|
11
|
+
service = @plan.service.values.first
|
12
|
+
@endpoint_rules = service['traits']['smithy.rules#endpointRuleSet']
|
13
|
+
@parameters = @endpoint_rules['parameters']
|
14
|
+
.map { |id, data| EndpointParameter.new(id, data, @plan) }
|
15
|
+
|
16
|
+
super()
|
17
|
+
end
|
18
|
+
|
19
|
+
attr_reader :plan, :parameters
|
20
|
+
|
21
|
+
def module_name
|
22
|
+
@plan.module_name
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|