aws-sdk-code-generator 0.1.0.pre → 0.2.0.pre

Sign up to get free protection for your applications and to get access to all the features.
Files changed (131) hide show
  1. checksums.yaml +5 -5
  2. data/lib/aws-sdk-code-generator.rb +68 -75
  3. data/lib/aws-sdk-code-generator/api.rb +130 -0
  4. data/lib/aws-sdk-code-generator/apply_docs.rb +15 -2
  5. data/lib/aws-sdk-code-generator/client_constructor.rb +39 -0
  6. data/lib/aws-sdk-code-generator/client_operation_documentation.rb +268 -0
  7. data/lib/aws-sdk-code-generator/client_operation_list.rb +148 -0
  8. data/lib/aws-sdk-code-generator/client_response_structure_example.rb +108 -0
  9. data/lib/aws-sdk-code-generator/code_builder.rb +146 -133
  10. data/lib/aws-sdk-code-generator/crosslink.rb +42 -0
  11. data/lib/aws-sdk-code-generator/docstring.rb +199 -0
  12. data/lib/aws-sdk-code-generator/error_list.rb +77 -0
  13. data/lib/aws-sdk-code-generator/errors.rb +2 -0
  14. data/lib/aws-sdk-code-generator/eventstream_example.rb +220 -0
  15. data/lib/aws-sdk-code-generator/gem_builder.rb +19 -25
  16. data/lib/aws-sdk-code-generator/hash_formatter.rb +5 -2
  17. data/lib/aws-sdk-code-generator/helper.rb +77 -61
  18. data/lib/aws-sdk-code-generator/plugin_list.rb +146 -0
  19. data/lib/aws-sdk-code-generator/resource_action.rb +69 -0
  20. data/lib/aws-sdk-code-generator/resource_action_code.rb +57 -0
  21. data/lib/aws-sdk-code-generator/resource_association.rb +37 -0
  22. data/lib/aws-sdk-code-generator/resource_attribute.rb +76 -0
  23. data/lib/aws-sdk-code-generator/resource_batch_action.rb +56 -0
  24. data/lib/aws-sdk-code-generator/resource_batch_action_code.rb +136 -0
  25. data/lib/aws-sdk-code-generator/resource_batch_action_documentation.rb +108 -0
  26. data/lib/aws-sdk-code-generator/resource_batch_builder.rb +212 -0
  27. data/lib/aws-sdk-code-generator/resource_builder.rb +48 -0
  28. data/lib/aws-sdk-code-generator/resource_client_request.rb +62 -0
  29. data/lib/aws-sdk-code-generator/resource_client_request_documentation.rb +81 -0
  30. data/lib/aws-sdk-code-generator/resource_client_request_params.rb +86 -0
  31. data/lib/aws-sdk-code-generator/resource_data_method.rb +60 -0
  32. data/lib/aws-sdk-code-generator/resource_has_association.rb +117 -0
  33. data/lib/aws-sdk-code-generator/resource_has_many_association.rb +52 -0
  34. data/lib/aws-sdk-code-generator/resource_has_many_association_code.rb +76 -0
  35. data/lib/aws-sdk-code-generator/resource_identifier.rb +44 -0
  36. data/lib/aws-sdk-code-generator/resource_identifiers_method.rb +29 -0
  37. data/lib/aws-sdk-code-generator/resource_load_method.rb +68 -0
  38. data/lib/aws-sdk-code-generator/resource_method.rb +22 -0
  39. data/lib/aws-sdk-code-generator/resource_skip_params.rb +36 -0
  40. data/lib/aws-sdk-code-generator/resource_value_source.rb +68 -0
  41. data/lib/aws-sdk-code-generator/resource_waiter.rb +80 -0
  42. data/lib/aws-sdk-code-generator/service.rb +30 -7
  43. data/lib/aws-sdk-code-generator/shared_example.rb +131 -0
  44. data/lib/aws-sdk-code-generator/syntax_example.rb +60 -0
  45. data/lib/aws-sdk-code-generator/syntax_example_hash.rb +174 -0
  46. data/lib/aws-sdk-code-generator/underscore.rb +10 -5
  47. data/lib/aws-sdk-code-generator/view.rb +33 -0
  48. data/lib/aws-sdk-code-generator/views.rb +2 -0
  49. data/lib/aws-sdk-code-generator/views/apig_endpoint_class.rb +25 -0
  50. data/lib/aws-sdk-code-generator/views/apig_readme.rb +32 -0
  51. data/lib/aws-sdk-code-generator/views/async_client_class.rb +68 -0
  52. data/lib/aws-sdk-code-generator/views/authorizer_class.rb +17 -0
  53. data/lib/aws-sdk-code-generator/views/client_api_module.rb +583 -0
  54. data/lib/aws-sdk-code-generator/views/client_class.rb +93 -0
  55. data/lib/aws-sdk-code-generator/views/docstring.rb +27 -0
  56. data/lib/aws-sdk-code-generator/views/errors_module.rb +32 -0
  57. data/lib/aws-sdk-code-generator/views/event_streams_module.rb +149 -0
  58. data/lib/aws-sdk-code-generator/views/features/env.rb +9 -0
  59. data/lib/aws-sdk-code-generator/views/features/smoke.rb +51 -0
  60. data/lib/aws-sdk-code-generator/views/features/smoke_step_definitions.rb +26 -0
  61. data/lib/aws-sdk-code-generator/views/features/step_definitions.rb +2 -0
  62. data/lib/aws-sdk-code-generator/views/gemspec.rb +39 -5
  63. data/lib/aws-sdk-code-generator/views/resource_class.rb +122 -0
  64. data/lib/aws-sdk-code-generator/views/root_resource_class.rb +58 -0
  65. data/lib/aws-sdk-code-generator/views/service_module.rb +30 -14
  66. data/lib/aws-sdk-code-generator/views/spec/spec_helper.rb +9 -0
  67. data/lib/aws-sdk-code-generator/views/types_module.rb +294 -0
  68. data/lib/aws-sdk-code-generator/views/version.rb +2 -0
  69. data/lib/aws-sdk-code-generator/views/waiters_module.rb +37 -0
  70. data/lib/aws-sdk-code-generator/waiter.rb +95 -0
  71. data/lib/aws-sdk-code-generator/yard_option_tag.rb +43 -0
  72. metadata +61 -68
  73. data/lib/aws-sdk-code-generator/dsl/access_control_statement.rb +0 -23
  74. data/lib/aws-sdk-code-generator/dsl/attribute_accessor.rb +0 -43
  75. data/lib/aws-sdk-code-generator/dsl/attribute_reader.rb +0 -11
  76. data/lib/aws-sdk-code-generator/dsl/attribute_writer.rb +0 -11
  77. data/lib/aws-sdk-code-generator/dsl/autoload_statement.rb +0 -15
  78. data/lib/aws-sdk-code-generator/dsl/block_param.rb +0 -11
  79. data/lib/aws-sdk-code-generator/dsl/class.rb +0 -27
  80. data/lib/aws-sdk-code-generator/dsl/code_literal.rb +0 -66
  81. data/lib/aws-sdk-code-generator/dsl/code_object.rb +0 -33
  82. data/lib/aws-sdk-code-generator/dsl/docstring.rb +0 -36
  83. data/lib/aws-sdk-code-generator/dsl/eigenclass.rb +0 -15
  84. data/lib/aws-sdk-code-generator/dsl/extend_statement.rb +0 -12
  85. data/lib/aws-sdk-code-generator/dsl/formatter.rb +0 -25
  86. data/lib/aws-sdk-code-generator/dsl/include_statement.rb +0 -17
  87. data/lib/aws-sdk-code-generator/dsl/main.rb +0 -105
  88. data/lib/aws-sdk-code-generator/dsl/method.rb +0 -108
  89. data/lib/aws-sdk-code-generator/dsl/module.rb +0 -167
  90. data/lib/aws-sdk-code-generator/dsl/option_tag.rb +0 -36
  91. data/lib/aws-sdk-code-generator/dsl/param.rb +0 -43
  92. data/lib/aws-sdk-code-generator/dsl/param_list.rb +0 -38
  93. data/lib/aws-sdk-code-generator/dsl/return_tag.rb +0 -19
  94. data/lib/aws-sdk-code-generator/dsl/tag_default.rb +0 -20
  95. data/lib/aws-sdk-code-generator/dsl/tag_docstring.rb +0 -27
  96. data/lib/aws-sdk-code-generator/dsl/tag_type.rb +0 -18
  97. data/lib/aws-sdk-code-generator/generators/client_api_module.rb +0 -334
  98. data/lib/aws-sdk-code-generator/generators/client_class.rb +0 -389
  99. data/lib/aws-sdk-code-generator/generators/client_operation_documentation.rb +0 -166
  100. data/lib/aws-sdk-code-generator/generators/errors_module.rb +0 -25
  101. data/lib/aws-sdk-code-generator/generators/resource/action.rb +0 -88
  102. data/lib/aws-sdk-code-generator/generators/resource/batch_builder.rb +0 -211
  103. data/lib/aws-sdk-code-generator/generators/resource/builder.rb +0 -50
  104. data/lib/aws-sdk-code-generator/generators/resource/client_getter.rb +0 -15
  105. data/lib/aws-sdk-code-generator/generators/resource/client_request.rb +0 -49
  106. data/lib/aws-sdk-code-generator/generators/resource/client_request_docs.rb +0 -97
  107. data/lib/aws-sdk-code-generator/generators/resource/client_request_params.rb +0 -88
  108. data/lib/aws-sdk-code-generator/generators/resource/collection_class.rb +0 -180
  109. data/lib/aws-sdk-code-generator/generators/resource/data_attribute_getter.rb +0 -24
  110. data/lib/aws-sdk-code-generator/generators/resource/data_loaded_method.rb +0 -18
  111. data/lib/aws-sdk-code-generator/generators/resource/data_method.rb +0 -49
  112. data/lib/aws-sdk-code-generator/generators/resource/exists_method.rb +0 -29
  113. data/lib/aws-sdk-code-generator/generators/resource/extract_identifier_method.rb +0 -32
  114. data/lib/aws-sdk-code-generator/generators/resource/has_association.rb +0 -101
  115. data/lib/aws-sdk-code-generator/generators/resource/has_many_association.rb +0 -108
  116. data/lib/aws-sdk-code-generator/generators/resource/identifier_getter.rb +0 -26
  117. data/lib/aws-sdk-code-generator/generators/resource/identifiers_method.rb +0 -28
  118. data/lib/aws-sdk-code-generator/generators/resource/initialize_method.rb +0 -67
  119. data/lib/aws-sdk-code-generator/generators/resource/load_method.rb +0 -65
  120. data/lib/aws-sdk-code-generator/generators/resource/value_source.rb +0 -68
  121. data/lib/aws-sdk-code-generator/generators/resource/waiter_method.rb +0 -61
  122. data/lib/aws-sdk-code-generator/generators/resource_class.rb +0 -325
  123. data/lib/aws-sdk-code-generator/generators/response_structure_example.rb +0 -83
  124. data/lib/aws-sdk-code-generator/generators/root_resource_class.rb +0 -42
  125. data/lib/aws-sdk-code-generator/generators/service_documentation.rb +0 -64
  126. data/lib/aws-sdk-code-generator/generators/shared_example.rb +0 -132
  127. data/lib/aws-sdk-code-generator/generators/structure_type_class.rb +0 -95
  128. data/lib/aws-sdk-code-generator/generators/syntax_example.rb +0 -169
  129. data/lib/aws-sdk-code-generator/generators/types_module.rb +0 -52
  130. data/lib/aws-sdk-code-generator/generators/waiter_class.rb +0 -62
  131. data/lib/aws-sdk-code-generator/generators/waiters_module.rb +0 -20
@@ -0,0 +1,174 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'set'
4
+
5
+ module AwsSdkCodeGenerator
6
+ class SyntaxExampleHash
7
+
8
+ include Helper
9
+
10
+ # @option options [required, Hash] :api
11
+ # @option options [required, Hash] :shape_ref
12
+ def initialize(options = {})
13
+ @api = options.fetch(:api)
14
+ @shape = options.fetch(:shape)
15
+ @async = options[:async] || false
16
+ end
17
+
18
+ def format(indent = '')
19
+ struct(@shape, indent, [])
20
+ end
21
+
22
+ private
23
+
24
+ def ref_value(ref, i, visited)
25
+ if visited.include?(ref['shape'])
26
+ return "{\n#{i} # recursive #{ref['shape']}\n#{i}}"
27
+ else
28
+ visited = visited + [ref['shape']]
29
+ end
30
+
31
+ s = shape(ref)
32
+ case s['type']
33
+ when 'structure'
34
+ if ref['shape'] == 'AttributeValue'
35
+ '"value"'
36
+ else
37
+ struct(s, i, visited)
38
+ end
39
+
40
+ when 'blob'
41
+ if ref['streaming']
42
+ 'source_file'
43
+ else
44
+ '"data"'
45
+ end
46
+
47
+ when 'list' then list(s, i, visited)
48
+ when 'map' then map(s, i, visited)
49
+ when 'boolean' then "false"
50
+ when 'integer', 'long' then '1'
51
+ when 'float', 'double' then '1.0'
52
+ when 'byte' then '97'
53
+ when 'character' then '"a"'
54
+ when 'string' then string(ref)
55
+ when 'timestamp' then 'Time.now'
56
+ else raise "unsupported shape #{s['type'].inspect}"
57
+ end
58
+ end
59
+
60
+ def struct(struct_shape, i, visited)
61
+ lines = ['{']
62
+ unless struct_shape['members'].nil?
63
+ struct_shape['members'].each_pair do |member_name, member_ref|
64
+ next if member_ref['documented'] === false
65
+ # input eventstream shouldn't be provided from params
66
+ if @api['shapes'][member_ref['shape']]['eventstream'] === true
67
+ lines << "#{i} input_event_stream_hander: EventStreams::#{member_ref['shape']}.new,"
68
+ else
69
+ lines << struct_member(struct_shape, member_name, member_ref, i, visited)
70
+ end
71
+ end
72
+ end
73
+ lines << "#{i}}"
74
+ lines.join("\n")
75
+ end
76
+
77
+ def struct_member(struct, member_name, member_ref, i, visited)
78
+ entry = "#{i} #{underscore(member_name)}: #{ref_value(member_ref, i + ' ', visited)},"
79
+ required = (struct['required'] || []).include?(member_name)
80
+ apply_comments(member_ref, entry, required: required)
81
+ end
82
+
83
+ def list(list_shape, i, visited)
84
+ member_ref = list_shape['member']
85
+ if complex?(member_ref)
86
+ complex_list(member_ref, i, visited)
87
+ else
88
+ scalar_list(member_ref, i, visited)
89
+ end
90
+ end
91
+
92
+ def scalar_list(member_ref, i, visited)
93
+ "[#{ref_value(member_ref, i, visited)}]"
94
+ end
95
+
96
+ def complex_list(member_ref, i, visited)
97
+ "[\n#{i} #{ref_value(member_ref, i + ' ', visited)},\n#{i}]"
98
+ end
99
+
100
+ def map(map_shape, i, visited)
101
+ key = string(map_shape['key'])
102
+ value = ref_value(map_shape['value'], i + ' ', visited)
103
+ "{\n#{i} #{key} => #{value},#{comments(map_shape['value'], false)}\n#{i}}"
104
+ end
105
+
106
+ def string(ref)
107
+ string_shape = shape(ref)
108
+ if string_shape['enum']
109
+ string_shape['enum'].first.inspect
110
+ else ref['shape']
111
+ ref['shape'].inspect
112
+ end
113
+ end
114
+
115
+ def apply_comments(ref, text, options = {})
116
+ required = options.fetch(:required)
117
+ lines = text.lines.to_a
118
+ if lines[0].match(/\n$/)
119
+ lines[0] = lines[0].sub(/\n$/, comments(ref, required) + "\n")
120
+ else
121
+ lines[0] += comments(ref, required)
122
+ end
123
+ lines.join
124
+ end
125
+
126
+ def comments(ref, required)
127
+ comments = []
128
+ if ref[:response_target]
129
+ comments << 'where to write response data, file path, or IO object'
130
+ end
131
+ if ref[:streaming]
132
+ comments << 'file/IO object, or string data'
133
+ end
134
+ if required
135
+ comments << 'required'
136
+ end
137
+ if enum = enum_values(ref)
138
+ comments << "accepts #{enum.to_a.join(', ')}"
139
+ end
140
+ if ddb_av?(ref)
141
+ comments << 'value <Hash,Array,String,Numeric,Boolean,IO,Set,nil>'
142
+ end
143
+ comments == [] ? '' : " # #{comments.join(', ')}"
144
+ end
145
+
146
+ def enum_values(ref)
147
+ s = shape(ref)
148
+ case s['type']
149
+ when 'list' then enum_values(s['member'])
150
+ when 'string' then s['enum']
151
+ else nil
152
+ end
153
+ end
154
+
155
+ def complex?(ref)
156
+ s = shape(ref)
157
+ if s['type'] == 'structure'
158
+ !ddb_av?(ref)
159
+ else
160
+ s['type'] == 'list' || s['type'] == 'map'
161
+ end
162
+ end
163
+
164
+ def ddb_av?(ref)
165
+ s = shape(ref)
166
+ case s['type']
167
+ when 'list' then ddb_av?(s['member'])
168
+ when 'structure' then ref['shape'] == 'AttributeValue'
169
+ else false
170
+ end
171
+ end
172
+
173
+ end
174
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module AwsSdkCodeGenerator
2
4
  module Underscore
3
5
  class << self
@@ -10,11 +12,12 @@ module AwsSdkCodeGenerator
10
12
  # @param [String] string
11
13
  # @return [String] Returns the underscored version of the given string.
12
14
  def underscore(string)
13
- string.
14
- gsub(@irregular_regex) { |word| '_' + @irregular_inflections[word] }.
15
- gsub(/([A-Z0-9]+)([A-Z][a-z])/, '\1_\2').
16
- scan(/[a-z0-9]+|\d+|[A-Z0-9]+[a-z]*/).
17
- join('_').downcase
15
+ new_string = string.dup
16
+ new_string.gsub!(@irregular_regex) { |word| "_#{@irregular_inflections[word]}" }
17
+ new_string.gsub!(/([A-Z0-9]+)([A-Z][a-z])/, '\1_\2'.freeze)
18
+ new_string = new_string.scan(/[a-z0-9]+|\d+|[A-Z0-9]+[a-z]*/).join('_'.freeze)
19
+ new_string.downcase!
20
+ new_string
18
21
  end
19
22
 
20
23
  # @param [String<JMESPath>]
@@ -38,6 +41,8 @@ module AwsSdkCodeGenerator
38
41
  'iSCSI' => 'iscsi',
39
42
  'ACLs' => 'acls',
40
43
  'Md5s' => 'md5s',
44
+ 'HIT' => 'hit',
45
+ 'URL' => 'url',
41
46
  #'SSEKMS' => 'sse_kms',
42
47
  })
43
48
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'mustache'
2
4
 
3
5
  module AwsSdkCodeGenerator
@@ -15,9 +17,40 @@ module AwsSdkCodeGenerator
15
17
  subclass.raise_on_context_miss = true
16
18
  end
17
19
 
20
+ # @param (see Underscore.underscore)
21
+ # @option (see Underscore.underscore)
22
+ # @return (see Underscore.underscore)
18
23
  def underscore(string)
19
24
  Underscore.underscore(string)
20
25
  end
21
26
 
27
+ # @param (see Underscore.underscore_jmespath)
28
+ # @option (see Underscore.underscore_jmespath)
29
+ # @return (see Underscore.underscore_jmespath)
30
+ def underscore_jmespath(string)
31
+ Underscore.underscore_jmespath(string)
32
+ end
33
+
34
+ # @param (see Docstring.html_to_markdown)
35
+ # @option (see Docstring.html_to_markdown)
36
+ # @return (see Docstring.html_to_markdown)
37
+ def html_to_markdown(html, options = {})
38
+ Docstring.html_to_markdown(html, options)
39
+ end
40
+
41
+ # @param (see Docstring.block_comment)
42
+ # @option (see Docstring.block_comment)
43
+ # @return (see Docstring.block_comment)
44
+ def block_comment(text, options = {})
45
+ Docstring.block_comment(text, options = {})
46
+ end
47
+
48
+ # @param (see Docstring.join_docstrings)
49
+ # @option (see Docstring.join_docstrings)
50
+ # @return (see Docstring.join_docstrings)
51
+ def join_docstrings(docs, options = {})
52
+ Docstring.join_docstrings(docs, options)
53
+ end
54
+
22
55
  end
23
56
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'gemspec'
2
4
 
3
5
  module Views; end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AwsSdkCodeGenerator
4
+ module Views
5
+
6
+ class APIGEndpointClass < View
7
+
8
+ # @option options [required, String] :module_name
9
+ # @option options [required, String] :default_endpoint
10
+ def initialize(options)
11
+ @module_name = options.fetch(:module_name)
12
+ endpoint = options.fetch(:default_endpoint)
13
+ unless endpoint.start_with?('http://') || endpoint.start_with?('https://')
14
+ endpoint = "https://#{endpoint}"
15
+ end
16
+ @default_endpoint = endpoint
17
+ end
18
+
19
+ attr_reader :module_name
20
+
21
+ attr_reader :default_endpoint
22
+
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AwsSdkCodeGenerator
4
+ module Views
5
+ class APIGReadme < View
6
+
7
+ # @option options [required, String] :service_name
8
+ # @option options [required, String] :module_name
9
+ # @option options [required, String] :gem_name
10
+ # @option options [required, String] :gem_major_version
11
+ def initialize(options)
12
+ @service_name = options.fetch(:service_name)
13
+ @module_name = options.fetch(:module_name)
14
+ @gem_name = options.fetch(:gem_name)
15
+ @gem_major_version = options.fetch(:gem_major_version)
16
+ end
17
+
18
+ # @return [String]
19
+ attr_reader :module_name
20
+
21
+ # @return [String]
22
+ attr_reader :gem_major_version
23
+
24
+ # @return [String]
25
+ attr_reader :gem_name
26
+
27
+ # @return [String]
28
+ attr_reader :service_name
29
+
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,68 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AwsSdkCodeGenerator
4
+ module Views
5
+ class AsyncClientClass < View
6
+
7
+ # @option options [required, String] :service_identifier
8
+ # @option options [required, String] :service_name
9
+ # @option options [required, String] :module_name
10
+ # @option options [required, String] :gem_name
11
+ # @option options [required, String] :gem_version
12
+ # @option options [required, String] :aws_sdk_core_lib_path
13
+ # @option options [required, String] :protocol
14
+ # @option options [required, String] :signature_version
15
+ # @option options [required, Hash] :add_plugins
16
+ # @option options [required, Array] :remove_plugins
17
+ # @option options [required, Hash] :api
18
+ # @option options [Hash] :client_examples
19
+ def initialize(options)
20
+ @service_identifier = options.fetch(:service_identifier)
21
+ @service_name = options.fetch(:service_name)
22
+ @module_name = options.fetch(:module_name)
23
+ @gem_name = options.fetch(:gem_name)
24
+ @gem_version = options.fetch(:gem_version)
25
+ @plugins = PluginList.new(options)
26
+ @client_constructor = ClientConstructor.new(plugins: @plugins)
27
+ @operations = ClientOperationList.new(options).to_a
28
+ end
29
+
30
+ # @return [String]
31
+ attr_reader :service_identifier
32
+
33
+ # @return [String]
34
+ attr_reader :service_name
35
+
36
+ # @return [String]
37
+ attr_reader :module_name
38
+
39
+ # @return [String]
40
+ attr_reader :gem_name
41
+
42
+ # @return [String]
43
+ attr_reader :gem_version
44
+
45
+ # @return [ClientConstructor]
46
+ attr_reader :client_constructor
47
+
48
+ # @return [Array<Operation>]
49
+ attr_reader :operations
50
+
51
+ # @return [String|nil]
52
+ def generated_src_warning
53
+ GENERATED_SRC_WARNING
54
+ end
55
+
56
+ # @return [Array<String>]
57
+ def plugin_requires
58
+ @plugins.map(&:require_path)
59
+ end
60
+
61
+ # @return [Array<String>]
62
+ def plugin_class_names
63
+ @plugins.map(&:class_name)
64
+ end
65
+
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AwsSdkCodeGenerator
4
+ module Views
5
+
6
+ class AuthorizerClass < View
7
+
8
+ # @option options [required, String] :module_name
9
+ def initialize(options)
10
+ @module_name = options.fetch(:module_name)
11
+ end
12
+
13
+ attr_reader :module_name
14
+
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,583 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AwsSdkCodeGenerator
4
+ module Views
5
+ class ClientApiModule < View
6
+
7
+ include Helper
8
+
9
+ SKIP_TRAITS = Set.new(%w(shape deprecated location locationName documentation))
10
+
11
+ SHAPE_CLASSES = {
12
+ 'blob' => 'BlobShape',
13
+ 'byte' => 'IntegerShape',
14
+ 'boolean' => 'BooleanShape',
15
+ 'character' => 'StringShape',
16
+ 'double' => 'FloatShape',
17
+ 'float' => 'FloatShape',
18
+ 'integer' => 'IntegerShape',
19
+ 'list' => 'ListShape',
20
+ 'long' => 'IntegerShape',
21
+ 'map' => 'MapShape',
22
+ 'string' => 'StringShape',
23
+ 'structure' => 'StructureShape',
24
+ 'timestamp' => 'TimestampShape'
25
+ }
26
+
27
+ SHAPE_KEYS = {
28
+ # keep
29
+ 'flattened' => true,
30
+ 'timestampFormat' => true, # glacier api customization
31
+ 'xmlNamespace' => true,
32
+ 'streaming' => true, # transfer-encoding
33
+ 'requiresLength' => true, # transder-encoding
34
+ # event stream modeling
35
+ 'event' => false,
36
+ 'eventstream' => false,
37
+ 'eventheader' => false,
38
+ 'eventpayload' => false,
39
+ # ignore
40
+ 'synthetic' => false,
41
+ 'box' => false,
42
+ 'fault' => false,
43
+ 'error' => false,
44
+ 'deprecated' => false,
45
+ 'deprecatedMessage' => false,
46
+ 'type' => false,
47
+ 'documentation' => false,
48
+ 'members' => false,
49
+ 'member' => false,
50
+ 'key' => false,
51
+ 'locationName' => false,
52
+ 'value' => false,
53
+ 'required' => false,
54
+ 'enum' => false,
55
+ 'exception' => false,
56
+ 'payload' => false,
57
+ 'pattern' => false,
58
+ 'sensitive' => false,
59
+ 'min' => false,
60
+ 'max' => false,
61
+ 'wrapper' => false,
62
+ 'xmlOrder' => false,
63
+ 'retryable' => false
64
+ }
65
+
66
+ METADATA_KEYS = {
67
+ # keep all
68
+ 'endpointPrefix' => true,
69
+ 'signatureVersion' => true,
70
+ 'signingName' => true,
71
+ 'serviceFullName' => true,
72
+ 'protocol' => true,
73
+ 'targetPrefix' => true,
74
+ 'jsonVersion' => true,
75
+ 'errorPrefix' => true,
76
+ 'timestampFormat' => true, # glacier api customization
77
+ 'xmlNamespace' => true,
78
+ 'protocolSettings' => {}, # current unused unless for h2 exclude
79
+ 'serviceId' => true,
80
+ 'apiVersion' => true,
81
+ 'checksumFormat' => true,
82
+ 'globalEndpoint' => true,
83
+ 'serviceAbbreviation' => true,
84
+ 'uid' => true
85
+ }
86
+
87
+ # @option options [required, Service] :service
88
+ def initialize(options)
89
+ @service = options.fetch(:service)
90
+ end
91
+
92
+ # @return [String|nil]
93
+ def generated_src_warning
94
+ return if @service.protocol == 'api-gateway'
95
+ GENERATED_SRC_WARNING
96
+ end
97
+
98
+ # @return [String]
99
+ def module_name
100
+ @service.module_name
101
+ end
102
+
103
+ # @return [String<YYYY-MM-DD>]
104
+ def api_version
105
+ @service.api_version
106
+ end
107
+
108
+ # @return [Array<Shape>]
109
+ def shapes
110
+ shape_enum.map do |shape_name, shape|
111
+ # APIG model, shape can start with downcase and with "__"
112
+ if @service.protocol == 'api-gateway'
113
+ shape_name = lstrip_prefix(upcase_first(shape_name))
114
+ end
115
+ Shape.new.tap do |s|
116
+ s.name = shape_name
117
+ s.class_name, shape = shape_class_name(shape)
118
+ s.constructor_args = shape_constructor_args(shape_name, shape)
119
+ end
120
+ end
121
+ end
122
+
123
+ def shape_definitions
124
+ shape_enum.inject([]) do |groups, (shape_name, shape)|
125
+ # APIG model, shape can start with downcase and with "__"
126
+ if @service.protocol == 'api-gateway'
127
+ shape_name = lstrip_prefix(upcase_first(shape_name))
128
+ end
129
+ lines = []
130
+ if non_error_struct?(shape)
131
+ required = Set.new(shape['required'] || [])
132
+ unless shape['members'].nil?
133
+ shape['members'].each do |member_name, member_ref|
134
+ lines << "#{shape_name}.add_member(:#{underscore(member_name)}, #{shape_ref(member_ref, member_name, required)})"
135
+ end
136
+ end
137
+ lines << "#{shape_name}.struct_class = Types::#{shape_name}"
138
+ if payload = shape['payload']
139
+ lines << "#{shape_name}[:payload] = :#{underscore(payload)}"
140
+ lines << "#{shape_name}[:payload_member] = #{shape_name}.member(:#{underscore(payload)})"
141
+ end
142
+ groups << lines.join("\n")
143
+ elsif error_struct?(shape)
144
+ required = Set.new(shape['required'] || [])
145
+ unless shape['members'].nil?
146
+ shape['members'].each do |member_name, member_ref|
147
+ lines << "#{shape_name}.add_member(:#{underscore(member_name)}, #{shape_ref(member_ref, member_name, required)})"
148
+ end
149
+ end
150
+ lines << "#{shape_name}.struct_class = Types::#{shape_name}"
151
+ groups << lines.join("\n")
152
+ elsif shape['type'] == 'list'
153
+ lines << "#{shape_name}.member = #{shape_ref(shape['member'])}"
154
+ groups << lines.join("\n")
155
+ elsif shape['type'] == 'map'
156
+ lines << "#{shape_name}.key = #{shape_ref(shape['key'])}"
157
+ lines << "#{shape_name}.value = #{shape_ref(shape['value'])}"
158
+ groups << lines.join("\n")
159
+ else
160
+ groups
161
+ end
162
+ end
163
+ end
164
+
165
+ # @return [Array<Hash>]
166
+ def metadata
167
+ metadata = []
168
+ @service.api.fetch('metadata', {}).keys.sort.each do |key|
169
+ if METADATA_KEYS[key]
170
+ metadata << {
171
+ key: key.inspect,
172
+ value: @service.api['metadata'][key].inspect
173
+ }
174
+ elsif METADATA_KEYS[key].nil?
175
+ raise "unhandled metadata key #{key.inspect}"
176
+ end
177
+ end
178
+ metadata
179
+ end
180
+
181
+ def operations
182
+ @service.api['operations'].map do |operation_name, operation|
183
+ Operation.new.tap do |o|
184
+ o.name = operation['name'] || operation_name
185
+ o.method_name = underscore(operation_name)
186
+ o.http_method = operation['http']['method']
187
+ o.http_request_uri = operation['http']['requestUri']
188
+ o.http_checksum_required = true if operation['httpChecksumRequired']
189
+ %w(input output).each do |key|
190
+ if operation[key]
191
+ o.shape_references << "o.#{key} = #{operation_ref(operation[key])}"
192
+ else
193
+ o.shape_references << "o.#{key} = Shapes::ShapeRef.new(shape: Shapes::StructureShape.new(struct_class: Aws::EmptyStructure))"
194
+ end
195
+ end
196
+ o.error_shape_names = operation.fetch('errors', []).map {|e| e['shape'] }
197
+ o.deprecated = true if operation['deprecated']
198
+ o.endpoint_operation = true if operation['endpointoperation']
199
+ if operation.key?('endpointdiscovery')
200
+ # "endpointdiscovery" trait per operation
201
+ # contains hash values of configuration,
202
+ # current acked field: "required"
203
+ o.endpoint_discovery_available = true
204
+ o.endpoint_discovery = operation['endpointdiscovery'].inject([]) do |a, (k, v)|
205
+ a << { key: k.inspect, value: v.inspect }
206
+ a
207
+ end
208
+ # endpoint trait cannot be co-exist with endpoint discovery
209
+ elsif operation.key?('endpoint')
210
+ # endpoint trait per operation, cannot be enabled with endpoint discovery
211
+ o.endpoint_trait = true
212
+ o.endpoint_pattern = operation['endpoint'].inject([]) do |a, (k, v)|
213
+ a << { key: k.inspect, value: v.inspect }
214
+ a
215
+ end
216
+ end
217
+ o.authorizer = operation['authorizer'] if operation.key?('authorizer')
218
+ o.authtype = operation['authtype'] if operation.key?('authtype')
219
+ o.require_apikey = operation['requiresApiKey'] if operation.key?('requiresApiKey')
220
+ o.pager = pager(operation_name)
221
+ o.async = @service.protocol_settings['h2'] == 'eventstream' &&
222
+ AwsSdkCodeGenerator::Helper.operation_eventstreaming?(operation, @service.api)
223
+ end
224
+ end
225
+ end
226
+
227
+ def apig_authorizer
228
+ return nil unless @service.api.key? 'authorizers'
229
+ @service.api['authorizers'].map do |name, authorizer|
230
+ Authorizer.new.tap do |a|
231
+ a.name = name
232
+ a.authorizer_name = underscore(name)
233
+ a.type = authorizer['type'] if authorizer.key? 'type'
234
+ if authorizer.key? 'placement'
235
+ a.location = authorizer['placement']['location']
236
+ a.location_name = authorizer['placement']['name']
237
+ end
238
+ end
239
+ end
240
+ end
241
+
242
+ def endpoint_operation
243
+ @service.api['operations'].each do |name, ref|
244
+ return underscore(name) if ref['endpointoperation']
245
+ end
246
+ nil
247
+ end
248
+
249
+ def require_endpoint_discovery
250
+ @service.require_endpoint_discovery
251
+ end
252
+
253
+ private
254
+
255
+ def shape_class_name(shape)
256
+ type = shape['type']
257
+ # APIG time serializing difference
258
+ if @service.protocol == 'api-gateway' && type == 'timestamp'
259
+ shape['timestampFormat'] = 'iso8601'
260
+ end
261
+ if SHAPE_CLASSES.key?(type)
262
+ ["Shapes::#{SHAPE_CLASSES[type]}", shape]
263
+ else
264
+ raise ArgumentError, "unsupported shape type `#{type}'"
265
+ end
266
+ end
267
+
268
+ def shape_constructor_args(shape_name, shape)
269
+ args = []
270
+ args << "name: '#{shape_name}'"
271
+ shape.each_pair do |key, value|
272
+ if SHAPE_KEYS[key]
273
+ args << "#{key}: #{value.inspect}"
274
+ elsif SHAPE_KEYS[key].nil?
275
+ raise "unhandled shape key #{key.inspect}"
276
+ end
277
+ end
278
+ args.join(', ')
279
+ end
280
+
281
+ def shape_enum
282
+ unless @service.protocol_settings.empty?
283
+ if @service.protocol_settings['h2'] == 'eventstream'
284
+ # some event shapes shared with error shapes
285
+ # might missing event trait
286
+ @service.api['shapes'].each do |_, shape|
287
+ if shape['eventstream']
288
+ # add event trait to all members if not exists
289
+ shape['members'].each do |name, ref|
290
+ @service.api['shapes'][ref['shape']]['event'] = true
291
+ end
292
+ end
293
+ end
294
+ end
295
+ end
296
+ Enumerator.new do |y|
297
+ @service.api.fetch('shapes', {}).keys.sort.each do |shape_name|
298
+ y.yield(shape_name, @service.api['shapes'].fetch(shape_name))
299
+ end
300
+ end
301
+ end
302
+
303
+ def non_error_struct?(shape)
304
+ if !!shape['event']
305
+ shape['type'] == 'structure'
306
+ else
307
+ shape['type'] == 'structure' &&
308
+ !shape['error'] &&
309
+ !shape['exception']
310
+ end
311
+ end
312
+
313
+ def error_struct?(shape)
314
+ shape['type'] == 'structure' && !!!shape['event'] &&
315
+ (shape['error'] || shape['exception'])
316
+ end
317
+
318
+ def structure_shape_enum
319
+ Enumerator.new do |y|
320
+ shape_enum.each do |shape_name, shape|
321
+ # non error types && non empty error struct
322
+ if non_error_struct?(shape) || error_struct?(shape)
323
+ y.yield(shape_name, shape)
324
+ end
325
+ end
326
+ end
327
+ end
328
+
329
+ def shape_ref(ref, member_name = nil, required = Set.new)
330
+ ref_name = ref['shape']
331
+ if @service.protocol == 'api-gateway'
332
+ ref_name = lstrip_prefix(ref_name)
333
+ end
334
+ line = "Shapes::ShapeRef.new(shape: #{ref_name}"
335
+ line += shape_ref_required(required, member_name)
336
+ line += shape_ref_deprecated(ref)
337
+ line += shape_ref_event(ref)
338
+ line += shape_ref_eventstream(ref)
339
+ line += shape_ref_eventpayload(ref)
340
+ line += shape_ref_eventheader(ref)
341
+ line += shape_ref_location(ref)
342
+ line += shape_ref_location_name(member_name, ref)
343
+ line += shape_ref_metadata(ref, member_name)
344
+ line += ")"
345
+ line
346
+ end
347
+
348
+ def shape_ref_required(required, member_name)
349
+ if required.include?(member_name)
350
+ ", required: true"
351
+ else
352
+ ""
353
+ end
354
+ end
355
+
356
+ def shape_ref_deprecated(ref)
357
+ if ref['deprecated'] || @service.api['shapes'][ref['shape']]['deprecated']
358
+ ", deprecated: true"
359
+ else
360
+ ""
361
+ end
362
+ end
363
+
364
+ def shape_ref_eventstream(ref)
365
+ if @service.api['shapes'][ref['shape']]['eventstream']
366
+ ", eventstream: true"
367
+ else
368
+ ''
369
+ end
370
+ end
371
+
372
+ def shape_ref_event(ref)
373
+ if @service.api['shapes'][ref['shape']]['event']
374
+ ", event: true"
375
+ else
376
+ ''
377
+ end
378
+ end
379
+
380
+ def shape_ref_eventpayload(ref)
381
+ if ref['eventpayload']
382
+ type = @service.api['shapes'][ref['shape']]['type']
383
+ ", eventpayload: true, eventpayload_type: '#{type}'"
384
+ else
385
+ ''
386
+ end
387
+ end
388
+
389
+ def shape_ref_eventheader(ref)
390
+ if ref['eventheader']
391
+ type = @service.api['shapes'][ref['shape']]['type']
392
+ ", eventheader: true, eventheader_type: '#{type}'"
393
+ else
394
+ ''
395
+ end
396
+ end
397
+
398
+ def shape_ref_location(ref)
399
+ if ref['location']
400
+ ", location: #{ref['location'].inspect}"
401
+ else
402
+ ''
403
+ end
404
+ end
405
+
406
+ def shape_ref_location_name(member_name, member_ref)
407
+ location_name = member_ref['locationName']
408
+ location_name ||= member_name unless member_ref['location'] == 'headers'
409
+ location_name ? ", location_name: #{location_name.inspect}" : ""
410
+ end
411
+
412
+ def shape_ref_metadata(member_ref, member_name)
413
+ metadata = member_ref.inject({}) do |hash, (key, value)|
414
+ hash[key] = value unless SKIP_TRAITS.include?(key)
415
+ if key == 'hostLabel'
416
+ hash['hostLabelName'] = member_name
417
+ end
418
+ hash
419
+ end
420
+ if metadata.empty?
421
+ ""
422
+ else
423
+ ", metadata: #{metadata.inspect}"
424
+ end
425
+ end
426
+
427
+ def pager(operation_name)
428
+ if @service.paginators && @service.paginators['pagination'][operation_name]
429
+ p = @service.paginators['pagination'][operation_name]
430
+ input = Array(p['input_token'])
431
+ output = Array(p['output_token'])
432
+ tokens = {}
433
+ input.each.with_index do |key, n|
434
+ tokens[underscore_jmespath(output[n])] = underscore_jmespath(key)
435
+ end
436
+ options = {}
437
+ options[:more_results] = underscore_jmespath(p['more_results']) if p['more_results']
438
+ options[:limit_key] = underscore_jmespath(p['limit_key']) if p['limit_key']
439
+ options[:tokens] = tokens
440
+ options = HashFormatter.new(
441
+ quote_strings: true,
442
+ inline: true,
443
+ wrap: false,
444
+ ).format(options)
445
+ "o[:pager] = Aws::Pager.new(#{options})" unless tokens.empty?
446
+ end
447
+ end
448
+
449
+ def operation_ref(ref)
450
+ metadata = ref.dup
451
+ shape_name = metadata.delete('shape')
452
+ # APIG model, shape can start with downcase and with "__"
453
+ if @service.protocol == 'api-gateway'
454
+ shape_name = lstrip_prefix(upcase_first(shape_name))
455
+ end
456
+ if metadata.empty?
457
+ options = ''
458
+ else
459
+ options = {}
460
+ metadata.each_pair do |key, value|
461
+ next if key == 'resultWrapper'
462
+ if key == 'locationName'
463
+ options[:location_name] = value.inspect
464
+ else
465
+ options[:metadata] ||= {}
466
+ options[:metadata][key] = value.inspect
467
+ end
468
+ end
469
+ if options.empty?
470
+ options = ''
471
+ else
472
+ opts = HashFormatter.new(wrap:false).format(options)
473
+ if opts[0] == "\n"
474
+ options = ",#{opts}"
475
+ else
476
+ options = ", #{opts}"
477
+ end
478
+ end
479
+ end
480
+ "Shapes::ShapeRef.new(shape: #{shape_name}#{options})"
481
+ end
482
+
483
+
484
+ class Shape
485
+
486
+ # @return [String]
487
+ attr_accessor :name
488
+
489
+ # @return [String<ClassName>]
490
+ attr_accessor :class_name
491
+
492
+ # @return [String]
493
+ attr_accessor :constructor_args
494
+
495
+ end
496
+
497
+ class Operation
498
+
499
+ def initialize
500
+ @shape_references = []
501
+ @error_shape_names = []
502
+ end
503
+
504
+ # @return [String] The UpperCamelCase operation name.
505
+ attr_accessor :name
506
+
507
+ # @return [String] The underscored method name.
508
+ attr_accessor :method_name
509
+
510
+ # @return [String] GET, PUT, POST, etc.
511
+ attr_accessor :http_method
512
+
513
+ # @return [String] "/", "/path?query", etc.
514
+ attr_accessor :http_request_uri
515
+
516
+ # @return [Boolean]
517
+ attr_accessor :http_checksum_required
518
+
519
+ # @return [Array<String>]
520
+ attr_accessor :shape_references
521
+
522
+ # @return [Array<String>]
523
+ attr_accessor :error_shape_names
524
+
525
+ # @return [Boolean]
526
+ attr_accessor :deprecated
527
+
528
+ # @return [Boolean]
529
+ attr_accessor :endpoint_discovery_available
530
+
531
+ # @return [Boolean]
532
+ attr_accessor :endpoint_operation
533
+
534
+ # @return [Array]
535
+ attr_accessor :endpoint_discovery
536
+
537
+ # @return [String,nil]
538
+ attr_accessor :authtype
539
+
540
+ # @return [Boolean]
541
+ attr_accessor :endpoint_trait
542
+
543
+ # @return [Array]
544
+ attr_accessor :endpoint_pattern
545
+
546
+ # APIG only
547
+ # @return [Boolean]
548
+ attr_accessor :require_apikey
549
+
550
+ # APIG only
551
+ # @return [String, nil]
552
+ attr_accessor :authorizer
553
+
554
+ # @return [Pager, nil]
555
+ attr_accessor :pager
556
+
557
+ # @return [Boolean]
558
+ attr_accessor :async
559
+
560
+ end
561
+
562
+ # APIG SDK only
563
+ class Authorizer
564
+
565
+ # @return [String]
566
+ attr_accessor :name
567
+
568
+ # @return [String]
569
+ attr_accessor :authorizer_name
570
+
571
+ # @return [String]
572
+ attr_accessor :type
573
+
574
+ # @return [String]
575
+ attr_accessor :location
576
+
577
+ # @return [String]
578
+ attr_accessor :location_name
579
+
580
+ end
581
+ end
582
+ end
583
+ end