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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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