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

Sign up to get free protection for your applications and to get access to all the features.
Files changed (155) hide show
  1. checksums.yaml +5 -5
  2. data/lib/aws-sdk-code-generator/api.rb +150 -0
  3. data/lib/aws-sdk-code-generator/apply_docs.rb +15 -2
  4. data/lib/aws-sdk-code-generator/client_constructor.rb +39 -0
  5. data/lib/aws-sdk-code-generator/client_operation_documentation.rb +282 -0
  6. data/lib/aws-sdk-code-generator/client_operation_list.rb +148 -0
  7. data/lib/aws-sdk-code-generator/client_response_structure_example.rb +115 -0
  8. data/lib/aws-sdk-code-generator/code_builder.rb +146 -133
  9. data/lib/aws-sdk-code-generator/crosslink.rb +42 -0
  10. data/lib/aws-sdk-code-generator/docstring.rb +199 -0
  11. data/lib/aws-sdk-code-generator/error_list.rb +77 -0
  12. data/lib/aws-sdk-code-generator/errors.rb +2 -0
  13. data/lib/aws-sdk-code-generator/eventstream_example.rb +220 -0
  14. data/lib/aws-sdk-code-generator/gem_builder.rb +42 -25
  15. data/lib/aws-sdk-code-generator/hash_formatter.rb +5 -2
  16. data/lib/aws-sdk-code-generator/helper.rb +86 -119
  17. data/lib/aws-sdk-code-generator/plugin_list.rb +147 -0
  18. data/lib/aws-sdk-code-generator/resource_action.rb +69 -0
  19. data/lib/aws-sdk-code-generator/resource_action_code.rb +57 -0
  20. data/lib/aws-sdk-code-generator/resource_association.rb +37 -0
  21. data/lib/aws-sdk-code-generator/resource_attribute.rb +76 -0
  22. data/lib/aws-sdk-code-generator/resource_batch_action.rb +56 -0
  23. data/lib/aws-sdk-code-generator/resource_batch_action_code.rb +136 -0
  24. data/lib/aws-sdk-code-generator/resource_batch_action_documentation.rb +108 -0
  25. data/lib/aws-sdk-code-generator/resource_batch_builder.rb +212 -0
  26. data/lib/aws-sdk-code-generator/resource_builder.rb +48 -0
  27. data/lib/aws-sdk-code-generator/resource_client_request.rb +62 -0
  28. data/lib/aws-sdk-code-generator/resource_client_request_documentation.rb +81 -0
  29. data/lib/aws-sdk-code-generator/resource_client_request_params.rb +86 -0
  30. data/lib/aws-sdk-code-generator/resource_data_method.rb +60 -0
  31. data/lib/aws-sdk-code-generator/resource_has_association.rb +117 -0
  32. data/lib/aws-sdk-code-generator/resource_has_many_association.rb +52 -0
  33. data/lib/aws-sdk-code-generator/resource_has_many_association_code.rb +76 -0
  34. data/lib/aws-sdk-code-generator/resource_identifier.rb +44 -0
  35. data/lib/aws-sdk-code-generator/resource_identifiers_method.rb +29 -0
  36. data/lib/aws-sdk-code-generator/resource_load_method.rb +68 -0
  37. data/lib/aws-sdk-code-generator/resource_method.rb +22 -0
  38. data/lib/aws-sdk-code-generator/resource_skip_params.rb +36 -0
  39. data/lib/aws-sdk-code-generator/resource_value_source.rb +68 -0
  40. data/lib/aws-sdk-code-generator/resource_waiter.rb +80 -0
  41. data/lib/aws-sdk-code-generator/service.rb +30 -7
  42. data/lib/aws-sdk-code-generator/shared_example.rb +131 -0
  43. data/lib/aws-sdk-code-generator/syntax_example.rb +60 -0
  44. data/lib/aws-sdk-code-generator/syntax_example_hash.rb +174 -0
  45. data/lib/aws-sdk-code-generator/underscore.rb +10 -5
  46. data/lib/aws-sdk-code-generator/view.rb +33 -0
  47. data/lib/aws-sdk-code-generator/views/apig_endpoint_class.rb +25 -0
  48. data/lib/aws-sdk-code-generator/views/apig_readme.rb +32 -0
  49. data/lib/aws-sdk-code-generator/views/async_client_class.rb +68 -0
  50. data/lib/aws-sdk-code-generator/views/authorizer_class.rb +17 -0
  51. data/lib/aws-sdk-code-generator/views/client_api_module.rb +602 -0
  52. data/lib/aws-sdk-code-generator/views/client_class.rb +93 -0
  53. data/lib/aws-sdk-code-generator/views/docstring.rb +27 -0
  54. data/lib/aws-sdk-code-generator/views/errors_module.rb +32 -0
  55. data/lib/aws-sdk-code-generator/views/event_streams_module.rb +149 -0
  56. data/lib/aws-sdk-code-generator/views/features/env.rb +9 -0
  57. data/lib/aws-sdk-code-generator/views/features/smoke.rb +52 -0
  58. data/lib/aws-sdk-code-generator/views/features/smoke_step_definitions.rb +26 -0
  59. data/lib/aws-sdk-code-generator/views/features/step_definitions.rb +6 -2
  60. data/lib/aws-sdk-code-generator/views/gemspec.rb +39 -5
  61. data/lib/aws-sdk-code-generator/views/resource_class.rb +122 -0
  62. data/lib/aws-sdk-code-generator/views/root_resource_class.rb +58 -0
  63. data/lib/aws-sdk-code-generator/views/service_module.rb +38 -14
  64. data/lib/aws-sdk-code-generator/views/spec/spec_helper.rb +9 -0
  65. data/lib/aws-sdk-code-generator/views/types_module.rb +329 -0
  66. data/lib/aws-sdk-code-generator/views/version.rb +2 -0
  67. data/lib/aws-sdk-code-generator/views/waiters_module.rb +37 -0
  68. data/lib/aws-sdk-code-generator/views.rb +2 -0
  69. data/lib/aws-sdk-code-generator/waiter.rb +95 -0
  70. data/lib/aws-sdk-code-generator/yard_option_tag.rb +43 -0
  71. data/lib/aws-sdk-code-generator.rb +68 -75
  72. data/templates/apig_endpoint_class.mustache +16 -0
  73. data/templates/apig_readme.mustache +62 -0
  74. data/templates/async_client_class.mustache +125 -0
  75. data/templates/authorizer_class.mustache +37 -0
  76. data/templates/client_api_module.mustache +106 -0
  77. data/templates/client_class.mustache +295 -0
  78. data/templates/code.mustache +4 -0
  79. data/templates/documentation.mustache +4 -0
  80. data/templates/errors_module.mustache +70 -0
  81. data/templates/event_streams_module.mustache +76 -0
  82. data/templates/features/env.mustache +15 -0
  83. data/templates/features/smoke.mustache +22 -0
  84. data/templates/features/smoke_step_definitions.mustache +31 -0
  85. data/templates/features/step_definitions.mustache +13 -0
  86. data/templates/gemspec.mustache +31 -0
  87. data/templates/license.txt +202 -0
  88. data/templates/method.mustache +7 -0
  89. data/templates/resource_class.mustache +304 -0
  90. data/templates/root_resource_class.mustache +51 -0
  91. data/templates/service_module.mustache +58 -0
  92. data/templates/spec/spec_helper.mustache +15 -0
  93. data/templates/types_module.mustache +53 -0
  94. data/templates/version.mustache +1 -0
  95. data/templates/waiters_module.mustache +112 -0
  96. metadata +115 -70
  97. data/lib/aws-sdk-code-generator/dsl/access_control_statement.rb +0 -23
  98. data/lib/aws-sdk-code-generator/dsl/attribute_accessor.rb +0 -43
  99. data/lib/aws-sdk-code-generator/dsl/attribute_reader.rb +0 -11
  100. data/lib/aws-sdk-code-generator/dsl/attribute_writer.rb +0 -11
  101. data/lib/aws-sdk-code-generator/dsl/autoload_statement.rb +0 -15
  102. data/lib/aws-sdk-code-generator/dsl/block_param.rb +0 -11
  103. data/lib/aws-sdk-code-generator/dsl/class.rb +0 -27
  104. data/lib/aws-sdk-code-generator/dsl/code_literal.rb +0 -66
  105. data/lib/aws-sdk-code-generator/dsl/code_object.rb +0 -33
  106. data/lib/aws-sdk-code-generator/dsl/docstring.rb +0 -36
  107. data/lib/aws-sdk-code-generator/dsl/eigenclass.rb +0 -15
  108. data/lib/aws-sdk-code-generator/dsl/extend_statement.rb +0 -12
  109. data/lib/aws-sdk-code-generator/dsl/formatter.rb +0 -25
  110. data/lib/aws-sdk-code-generator/dsl/include_statement.rb +0 -17
  111. data/lib/aws-sdk-code-generator/dsl/main.rb +0 -105
  112. data/lib/aws-sdk-code-generator/dsl/method.rb +0 -108
  113. data/lib/aws-sdk-code-generator/dsl/module.rb +0 -167
  114. data/lib/aws-sdk-code-generator/dsl/option_tag.rb +0 -36
  115. data/lib/aws-sdk-code-generator/dsl/param.rb +0 -43
  116. data/lib/aws-sdk-code-generator/dsl/param_list.rb +0 -38
  117. data/lib/aws-sdk-code-generator/dsl/return_tag.rb +0 -19
  118. data/lib/aws-sdk-code-generator/dsl/tag_default.rb +0 -20
  119. data/lib/aws-sdk-code-generator/dsl/tag_docstring.rb +0 -27
  120. data/lib/aws-sdk-code-generator/dsl/tag_type.rb +0 -18
  121. data/lib/aws-sdk-code-generator/generators/client_api_module.rb +0 -334
  122. data/lib/aws-sdk-code-generator/generators/client_class.rb +0 -389
  123. data/lib/aws-sdk-code-generator/generators/client_operation_documentation.rb +0 -166
  124. data/lib/aws-sdk-code-generator/generators/errors_module.rb +0 -25
  125. data/lib/aws-sdk-code-generator/generators/resource/action.rb +0 -88
  126. data/lib/aws-sdk-code-generator/generators/resource/batch_builder.rb +0 -211
  127. data/lib/aws-sdk-code-generator/generators/resource/builder.rb +0 -50
  128. data/lib/aws-sdk-code-generator/generators/resource/client_getter.rb +0 -15
  129. data/lib/aws-sdk-code-generator/generators/resource/client_request.rb +0 -49
  130. data/lib/aws-sdk-code-generator/generators/resource/client_request_docs.rb +0 -97
  131. data/lib/aws-sdk-code-generator/generators/resource/client_request_params.rb +0 -88
  132. data/lib/aws-sdk-code-generator/generators/resource/collection_class.rb +0 -180
  133. data/lib/aws-sdk-code-generator/generators/resource/data_attribute_getter.rb +0 -24
  134. data/lib/aws-sdk-code-generator/generators/resource/data_loaded_method.rb +0 -18
  135. data/lib/aws-sdk-code-generator/generators/resource/data_method.rb +0 -49
  136. data/lib/aws-sdk-code-generator/generators/resource/exists_method.rb +0 -29
  137. data/lib/aws-sdk-code-generator/generators/resource/extract_identifier_method.rb +0 -32
  138. data/lib/aws-sdk-code-generator/generators/resource/has_association.rb +0 -101
  139. data/lib/aws-sdk-code-generator/generators/resource/has_many_association.rb +0 -108
  140. data/lib/aws-sdk-code-generator/generators/resource/identifier_getter.rb +0 -26
  141. data/lib/aws-sdk-code-generator/generators/resource/identifiers_method.rb +0 -28
  142. data/lib/aws-sdk-code-generator/generators/resource/initialize_method.rb +0 -67
  143. data/lib/aws-sdk-code-generator/generators/resource/load_method.rb +0 -65
  144. data/lib/aws-sdk-code-generator/generators/resource/value_source.rb +0 -68
  145. data/lib/aws-sdk-code-generator/generators/resource/waiter_method.rb +0 -61
  146. data/lib/aws-sdk-code-generator/generators/resource_class.rb +0 -325
  147. data/lib/aws-sdk-code-generator/generators/response_structure_example.rb +0 -83
  148. data/lib/aws-sdk-code-generator/generators/root_resource_class.rb +0 -42
  149. data/lib/aws-sdk-code-generator/generators/service_documentation.rb +0 -64
  150. data/lib/aws-sdk-code-generator/generators/shared_example.rb +0 -132
  151. data/lib/aws-sdk-code-generator/generators/structure_type_class.rb +0 -95
  152. data/lib/aws-sdk-code-generator/generators/syntax_example.rb +0 -169
  153. data/lib/aws-sdk-code-generator/generators/types_module.rb +0 -52
  154. data/lib/aws-sdk-code-generator/generators/waiter_class.rb +0 -62
  155. data/lib/aws-sdk-code-generator/generators/waiters_module.rb +0 -20
@@ -0,0 +1,199 @@
1
+ # frozen_string_literal: true
2
+
3
+ # kramdown
4
+ require 'kramdown'
5
+ # end kramdown
6
+
7
+ module AwsSdkCodeGenerator
8
+ module Docstring
9
+ class << self
10
+
11
+ # Prefixes each line of `text` with a pound sign. Given the string
12
+ #
13
+ # Hello
14
+ # World
15
+ #
16
+ # The following string would be returned:
17
+ #
18
+ # # Hello
19
+ # # World
20
+ #
21
+ # @param [String, nil] text
22
+ # @option options [String] :gap (' ')
23
+ # @return [String, nil]
24
+ def block_comment(text, options = {})
25
+ if text
26
+ gap = options.fetch(:gap, ' ')
27
+ text.lines.map do |line|
28
+ line = line.rstrip
29
+ if line == ''
30
+ "#"
31
+ else
32
+ "##{gap}#{line}"
33
+ end
34
+ end.join("\n")
35
+ end
36
+ end
37
+
38
+ # Joins multiple doc strings into a single doc block. Each entry
39
+ # in the given `docstrings` array can be a string, nil, or an another array.
40
+ # Arrays are flattened, and nils are compacted out.
41
+ #
42
+ # Given the following `docstrings`:
43
+ #
44
+ # [
45
+ # "First doc block",
46
+ # nil,
47
+ # "Second doc block\nthat contains\nmultiple lines\n",
48
+ # [
49
+ # "Third doc block\n",
50
+ # "Last doc block\n",
51
+ # ],
52
+ # ]
53
+ #
54
+ # The following joined doc block would be returned:
55
+ #
56
+ # # First doc block
57
+ # #
58
+ # # Second doc block
59
+ # # that contains
60
+ # # multiple lines
61
+ # #
62
+ # # Third doc block
63
+ # #
64
+ # # Last doc block
65
+ #
66
+ # @param [Array<String>] docstrings
67
+ #
68
+ # @option options [Boolean] :block_comment (true)
69
+ # By default, each docstring is commented by passing
70
+ # it to {Docstring.block_comment}. Setting `:block_comment` to
71
+ # false disables this behavior.
72
+ #
73
+ # @option options [String] :gap (' ')
74
+ # This option is given to {Docstring.block_comment} when
75
+ # `:block_comment` is `true`.
76
+ #
77
+ # @option options [String] :separator (true)
78
+ # When `true`, a blank line is inserted between
79
+ # each documentation section.
80
+ #
81
+ # @return [String, nil] If the given `docstrings` is empty,
82
+ # then a `nil` is returned.
83
+ #
84
+ def join_docstrings(docstrings, options = {})
85
+ docs = docstrings.flatten.inject([]) do |sections, section|
86
+ if section.nil? || section.size == 0
87
+ sections
88
+ else
89
+ sections << (options.fetch(:block_comment, true) ?
90
+ block_comment(section, options) :
91
+ section)
92
+ sections << (options.fetch(:separator, true) ? "\n#\n" : "\n")
93
+ sections
94
+ end
95
+ end
96
+ if docs.empty?
97
+ nil
98
+ else
99
+ docs[-1] = docs[-1].rstrip
100
+ docs.join
101
+ end
102
+ end
103
+
104
+ # @param [String]
105
+ # @return [String]
106
+ def escape_html(string)
107
+ string.to_s.encode(:xml => :text)
108
+ end
109
+
110
+ # kramdown html
111
+ # @param [String<HTML>, nil] html
112
+ # @option options [Integer] :line_width (70)
113
+ # @return [String<Markdown>, nil]
114
+ def html_to_markdown(html, options = {})
115
+ line_width = options.fetch(:line_width, 70)
116
+ # TODO : this section of code is **very slow** and runs many times
117
+ # while building a service.
118
+ if html
119
+ html = "<p>#{html}</p>" unless html.match(/<\w+>/)
120
+
121
+ # unescaped curly braces cause YARD errors, they are interpreted
122
+ # as code links.
123
+ html = html.gsub('{', "\\{").gsub('}', "\\}")
124
+
125
+ # Kramdown generates invalid markup when there are attributes
126
+ # on the code tag, have to reduce these down to get the proper markdown.
127
+ html = html.gsub(/<code.*?>(.+?)<\/code>/) { "<code>#{$1}</code>" }
128
+
129
+ # Kramdown creates invalid markup with target="_blank" attributes.
130
+ html = html.gsub(' target="_blank"', '')
131
+
132
+ # There are quite a few empty <a> tags. These appear to be code names,
133
+ # such as structure member names, or structure type names. We should
134
+ # investigate if it is possible to inflect these properly and then
135
+ # turn them into YARD links.
136
+ html = html.gsub(/<a>(.+?)<\/a>/) { $1 }
137
+
138
+ # For span tags, it can contain customized attributes, e.g. data-target
139
+ # keeping text context only for now
140
+ html = html.gsub(/<span.*?>(.+?)<\/span>/) { $1 }
141
+
142
+ # <important> tag doesn't render well
143
+ html = html.gsub(/<important>(.+?)<\/important>/){ "<p>#{$1}</p>" }
144
+
145
+ # <replaceable> doesn't render anything, so sub it out for italic
146
+ html = html.gsub(/<replaceable>(.+?)<\/replaceable>/) { "<i>#{$1}</i>" }
147
+
148
+ markdown = Kramdown::Document.new(
149
+ html,
150
+ input: 'html',
151
+ line_width: line_width,
152
+ auto_ids: false
153
+ ).to_kramdown.strip
154
+
155
+ # remove extra escape
156
+ markdown.gsub(/\\(\*|`|'|")/, '\1')
157
+ end
158
+ end
159
+ # end kramdown html
160
+
161
+ # @param [Array<Array<String>>]
162
+ def markdown_table(table)
163
+ # compute the width of each column by scanning for longest values
164
+ column_width = lambda do |col|
165
+ table.map { |row| row[col].size }.max
166
+ end
167
+ widths = [
168
+ column_width.call(0),
169
+ column_width.call(1),
170
+ column_width.call(2),
171
+ column_width.call(3),
172
+ ]
173
+
174
+ # insert a dashed line after the header row
175
+ table = [
176
+ table[0],
177
+ ['-' * widths[0], '-' * widths[1], '-' * widths[2], '-' * widths[3]]
178
+ ] + table[1..-1]
179
+
180
+ # build the final table
181
+ line = "| #{widths.map{|n| "%-#{n}s" }.join(' | ')} |"
182
+ table.map { |row| line % row }.join("\n")
183
+ end
184
+
185
+ def ucfirst(string)
186
+ if string
187
+ string[0].upcase + string[1..-1]
188
+ end
189
+ end
190
+
191
+ def indent(string, space = ' ')
192
+ string.lines.map do |line|
193
+ "#{space}#{line}"
194
+ end.join.lstrip
195
+ end
196
+
197
+ end
198
+ end
199
+ end
@@ -0,0 +1,77 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AwsSdkCodeGenerator
4
+ class ErrorList
5
+
6
+ include Enumerable
7
+
8
+ def initialize(options)
9
+ @api = options[:api]
10
+ @module_name = options[:module_name]
11
+ @errors = @api['shapes'].inject([]) do |es, (name, shape)|
12
+ # only generate error shape with non empty members
13
+ # excluding event shapes marked as error
14
+ if error_struct?(shape)
15
+ members = shape['members'].inject([]) do |arr, (k, v)|
16
+ arr << {
17
+ name: Underscore.underscore(k),
18
+ type: Docstring.ucfirst(v['type'] ||'String'),
19
+ shared: k.downcase == 'message' || k.downcase == 'code'
20
+ }
21
+ arr
22
+ end
23
+ es << Error.new(
24
+ name: name,
25
+ members: members,
26
+ data_type: "#{@module_name}::Types::#{name}",
27
+ retryable: !!shape['retryable'],
28
+ throttling: throttling?(shape)
29
+ )
30
+ end
31
+ es
32
+ end
33
+ end
34
+
35
+ def error_struct?(shape)
36
+ shape['type'] == 'structure' && !!!shape['event'] &&
37
+ (shape['error'] || shape['exception'])
38
+ end
39
+
40
+ def each(&block)
41
+ @errors.each(&block)
42
+ end
43
+
44
+ def throttling?(shape)
45
+ shape['retryable'] && shape['retryable'].kind_of?(Hash) && shape['retryable']['throttling']
46
+ end
47
+
48
+
49
+ class Error
50
+
51
+ def initialize(options)
52
+ @name = options.fetch(:name)
53
+ @data_type = options[:data_type]
54
+ @members = options[:members]
55
+ @retryable = options[:retryable]
56
+ @throttling = options[:throttling]
57
+ end
58
+
59
+ # @return [String]
60
+ attr_reader :name
61
+
62
+ # @return [String]
63
+ attr_reader :data_type
64
+
65
+ # @return [Array<Hash>]
66
+ attr_reader :members
67
+
68
+ # @return [Boolean]
69
+ attr_reader :retryable
70
+
71
+ # @return [Boolean]
72
+ attr_reader :throttling
73
+
74
+ end
75
+
76
+ end
77
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module AwsSdkCodeGenerator
2
4
  module Errors
3
5
 
@@ -0,0 +1,220 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AwsSdkCodeGenerator
4
+ class EventStreamExample
5
+
6
+ def initialize(options = {})
7
+ @api = options.fetch(:api)
8
+ @method_name = options.fetch(:method_name)
9
+ @module_name = options.fetch(:module_name)
10
+ @receiver = options.fetch(:receiver)
11
+ @resp_var = options.fetch(:resp_var)
12
+ @operation = options.fetch(:operation)
13
+ @input_eventstream_member, @input_eventstream_shape = input_eventstream_shape
14
+ @output_eventstream_member, @output_eventstream_shape = output_eventstream_shape
15
+ if @input_eventstream_shape && @output_eventstream_shape &&
16
+ @input_eventstream_shape == @output_eventstream_shape
17
+ # input and output sharing same eventstream
18
+ # renaming, see EventStreamModules
19
+ @input_eventstream = "#{@module_name}::EventStreams::Input#{@input_eventstream_shape}"
20
+ @output_eventstream = "#{@module_name}::EventStreams::Output#{@output_eventstream_shape}"
21
+ else
22
+ @input_eventstream = "#{@module_name}::EventStreams::#{@input_eventstream_shape}" if @input_eventstream_shape
23
+ @output_eventstream = "#{@module_name}::EventStreams::#{@output_eventstream_shape}" if @output_eventstream_shape
24
+ end
25
+ end
26
+
27
+ def format
28
+ if @input_eventstream_member && @output_eventstream_member
29
+ bi_directional_format
30
+ elsif @output_eventstream_member
31
+ output_format
32
+ # elsif @input_eventstream_member
33
+ # input stream only is supported naturally, but
34
+ # unclear usage when just input streaming, so pending for now
35
+ end
36
+ end
37
+
38
+ def bi_directional_format
39
+ <<-EXAMPLE.strip
40
+ # @example Bi-directional EventStream Operation Example
41
+ #
42
+ # You can signal input events after initial request is
43
+ # established, events will be sent to stream
44
+ # immediately (once stream connection is established successfully).
45
+ #
46
+ # To signal events, you can call #signal methods from an #{@input_eventstream} object.
47
+ # Make sure signal events before calling #wait or #join! at async response.
48
+ #
49
+ # input_stream = #{@input_eventstream}.new
50
+ #
51
+ # async_resp = #{@receiver}.#{@method_name}( # params input,
52
+ # input_event_stream_handler: input_stream) do |out_stream|
53
+ #
54
+ # # register callbacks for events arrival
55
+ #{event_entry(:output, 'out_stream', 2)}
56
+ #
57
+ # end
58
+ # # => returns Aws::Seahorse::Client::AsyncResponse
59
+ #
60
+ # # signal events
61
+ #{event_entry(:input, 'input_stream')}
62
+ #
63
+ # # make sure signaling :end_stream in the end
64
+ # input_stream.signal_end_stream
65
+ #
66
+ # # wait until stream is closed before finalizing sync response
67
+ # resp = async_resp.wait
68
+ # # Or close stream and finalizing sync response immediately
69
+ # # resp = async_resp.join!
70
+ #
71
+ # Inorder to streamingly processing events received, you can also provide an #{@output_eventstream}
72
+ # object to register callbacks before initializing request instead of processing from request block
73
+ #
74
+ # output_stream = #{@output_eventstream}.new
75
+ # # register callbacks for events arrival
76
+ #{event_entry(:output, 'output_stream')}
77
+ #{error_event_entry('output_stream')}
78
+ #
79
+ # async_resp = #{@receiver}.#{@method_name} ( #params input,
80
+ # input_event_stream_handler: input_stream
81
+ # output_event_stream_handler: output_stream
82
+ # )
83
+ #
84
+ # resp = async_resp.wait!
85
+ #
86
+ # Besides above usage patterns for process events when they arrive immediately, you can also
87
+ # iterate through events after response complete.
88
+ #
89
+ # Events are available at #{@resp_var}.#{@output_eventstream_member} # => Enumerator
90
+ EXAMPLE
91
+ end
92
+
93
+ def output_format
94
+ <<-EXAMPLE.strip
95
+ # @example EventStream Operation Example
96
+ #
97
+ # You can process event once it arrives immediately, or wait until
98
+ # full response complete and iterate through eventstream enumerator.
99
+ #
100
+ # To interact with event immediately, you need to register ##{@method_name}
101
+ # with callbacks, callbacks can be register for specifc events or for all events,
102
+ # callback for errors in the event stream is also available for register.
103
+ #
104
+ # Callbacks can be passed in by `:event_stream_handler` option or within block
105
+ # statement attached to ##{@method_name} call directly. Hybrid pattern of both
106
+ # is also supported.
107
+ #
108
+ # `:event_stream_handler` option takes in either Proc object or
109
+ # #{@output_eventstream} object.
110
+ #
111
+ # Usage pattern a): callbacks with a block attached to ##{@method_name}
112
+ # Example for registering callbacks for all event types and error event
113
+ #
114
+ # #{@receiver}.#{@method_name}( # params input# ) do |stream|
115
+ #{error_event_entry('stream', 2)}
116
+ #
117
+ # stream.on_event do |event|
118
+ # # process all events arrive
119
+ # puts event.event_type
120
+ # ...
121
+ # end
122
+ #
123
+ # end
124
+ #
125
+ # Usage pattern b): pass in `:event_stream_handler` for ##{@method_name}
126
+ #
127
+ # 1) create a #{@output_eventstream} object
128
+ # Example for registering callbacks with specific events
129
+ #
130
+ # handler = #{@output_eventstream}.new
131
+ #{event_entry(:output, 'handler', 2)}
132
+ #
133
+ # #{@receiver}.#{@method_name}( # params input #, event_stream_handler: handler)
134
+ #
135
+ # 2) use a Ruby Proc object
136
+ # Example for registering callbacks with specific events
137
+ #
138
+ # handler = Proc.new do |stream|
139
+ #{event_entry(:output, 'stream', 2)}
140
+ # end
141
+ #
142
+ # #{@receiver}.#{@method_name}( # params input #, event_stream_handler: handler)
143
+ #
144
+ # Usage pattern c): hybird pattern of a) and b)
145
+ #
146
+ # handler = #{@output_eventstream}.new
147
+ #{event_entry(:output, 'handler', 2)}
148
+ #
149
+ # #{@receiver}.#{@method_name}( # params input #, event_stream_handler: handler) do |stream|
150
+ #{error_event_entry('stream', 2)}
151
+ # end
152
+ #
153
+ # Besides above usage patterns for process events when they arrive immediately, you can also
154
+ # iterate through events after response complete.
155
+ #
156
+ # Events are available at #{@resp_var}.#{@output_eventstream_member} # => Enumerator
157
+ # For parameter input example, please refer to following request syntax
158
+ EXAMPLE
159
+ end
160
+
161
+ def event_entry(type, ctx, indent = 0)
162
+ case type
163
+ when :input then input_event_entries(ctx, indent)
164
+ when :output then output_event_entries(ctx, indent)
165
+ end
166
+ end
167
+
168
+ def error_event_entry(ctx, indent = 0)
169
+ entries = []
170
+ entries << "# #{' ' * indent}#{ctx}.on_error_event do |event|"
171
+ entries << "# #{' ' * indent} # catch unmodeled error event in the stream"
172
+ entries << "# #{' ' * indent} raise event"
173
+ entries << "# #{' ' * indent} # => Aws::Errors::EventError"
174
+ entries << "# #{' ' * indent} # event.event_type => :error"
175
+ entries << "# #{' ' * indent} # event.error_code => String"
176
+ entries << "# #{' ' * indent} # event.error_message => String"
177
+ entries << "# #{' ' * indent}end"
178
+ entries.join("\n")
179
+ end
180
+
181
+ def input_event_entries(ctx, indent = 0)
182
+ @api['shapes'][@input_eventstream_shape]['members'].each.inject([]) do |entries, (name, _)|
183
+ event_type = Underscore.underscore(name)
184
+ # TODO, place holder values
185
+ entries << "# #{' ' * indent}#{ctx}.signal_#{event_type}_event( ... )"
186
+ entries
187
+ end.join("\n")
188
+ end
189
+
190
+ def output_event_entries(ctx, indent = 0)
191
+ @api['shapes'][@output_eventstream_shape]['members'].keys.each.inject([]) do |entry, name|
192
+ event_type = Underscore.underscore(name)
193
+ entry << "# #{' ' * indent}#{ctx}.on_#{event_type}_event do |event|"
194
+ entry << "# #{' ' * indent}event # => #{@module_name}::Types::#{name}"
195
+ entry << "# #{' ' * indent}end"
196
+ end.join("\n")
197
+ end
198
+
199
+ def input_eventstream_shape
200
+ input_shape = @api['shapes'][@operation['input']['shape']] if @operation['input']
201
+ if input_shape
202
+ input_shape['members'].each do |name, ref|
203
+ return [Underscore.underscore(name), ref['shape']] if Api.eventstream?(ref, @api)
204
+ end
205
+ end
206
+ nil
207
+ end
208
+
209
+ def output_eventstream_shape
210
+ output_shape = @api['shapes'][@operation['output']['shape']] if @operation['output']
211
+ if output_shape
212
+ output_shape['members'].each do |name, ref|
213
+ return [Underscore.underscore(name), ref['shape']] if Api.eventstream?(ref, @api)
214
+ end
215
+ end
216
+ nil
217
+ end
218
+ end
219
+
220
+ end
@@ -1,25 +1,37 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module AwsSdkCodeGenerator
2
4
  class GemBuilder
3
5
 
4
6
  # @param [Hash] options
5
- # @option options [required, Service] :service
7
+ # @option (see CodeBuilder#initialize)
6
8
  def initialize(options)
7
9
  @options = options
8
10
  @service = options.fetch(:service)
11
+ validate_model!
9
12
  end
10
13
 
11
14
  # @return [Hash]
12
15
  attr_reader :options
13
16
 
17
+ def validate_model!
18
+ validate_document_support!
19
+ end
20
+
14
21
  def each(&block)
15
22
  Enumerator.new do |y|
16
- y.yield(gemspec_path, gemspec_file)
17
- y.yield(features_env_path, features_env_file)
18
- y.yield(features_step_definitions_path, features_step_definitions_file)
19
- y.yield(spec_helper_path, spec_helper_file)
20
- y.yield(version_path, version_file)
23
+ y.yield("#{@service.gem_name}.gemspec", gemspec_file)
24
+ y.yield('features/env.rb', features_env_file)
25
+ y.yield('features/step_definitions.rb', features_step_definitions_file)
26
+ y.yield('spec/spec_helper.rb', spec_helper_file)
27
+ if @service.smoke_tests
28
+ y.yield('features/smoke.feature', smoke_file)
29
+ y.yield('features/smoke_step_definitions.rb', smoke_step_definitions_file)
30
+ end
31
+ y.yield('VERSION', version_file)
32
+ y.yield('LICENSE.txt', license_file)
21
33
  code = CodeBuilder.new(@options)
22
- code.source_files(prefix: @service.gem_name).each do |path, code|
34
+ code.source_files.each do |path, code|
23
35
  y.yield("lib/#{path}", code)
24
36
  end
25
37
  end.each(&block)
@@ -27,45 +39,50 @@ module AwsSdkCodeGenerator
27
39
 
28
40
  private
29
41
 
30
- def gemspec_path
31
- "#{@service.gem_name}.gemspec"
32
- end
33
-
34
42
  def gemspec_file
35
43
  Views::Gemspec.new(options).render
36
44
  end
37
45
 
38
- def features_env_path
39
- 'features/env.rb'
40
- end
41
-
42
46
  def features_env_file
43
47
  Views::Features::Env.new(options).render
44
48
  end
45
49
 
46
- def features_step_definitions_path
47
- 'features/step_definitions.rb'
50
+ def smoke_file
51
+ Views::Features::Smoke.new(options).render
48
52
  end
49
53
 
50
- def features_step_definitions_file
51
- Views::Features::StepDefinitions.new(options).render
54
+ def smoke_step_definitions_file
55
+ Views::Features::SmokeStepDefinitions.new(options).render
52
56
  end
53
57
 
54
- def spec_helper_path
55
- 'spec/spec_helper.rb'
58
+ def features_step_definitions_file
59
+ Views::Features::StepDefinitions.new(options).render
56
60
  end
57
61
 
58
62
  def spec_helper_file
59
63
  Views::Spec::SpecHelper.new(options).render
60
64
  end
61
65
 
62
- def version_path
63
- 'VERSION'
64
- end
65
-
66
66
  def version_file
67
67
  Views::Version.new(options).render
68
68
  end
69
69
 
70
+ def license_file
71
+ File.read(File.expand_path('../../../templates/license.txt',__FILE__ ))
72
+ end
73
+
74
+ private
75
+
76
+ # document types are only supported for rest-json and json
77
+ def validate_document_support!
78
+ return if ['rest-json', 'json'].include?(@service.protocol)
79
+
80
+ # Check all shapes and raise if any are Document types
81
+ @service.api.fetch('shapes', {}).each do |name, shape|
82
+ if shape['type'] == 'structure' && shape['document']
83
+ raise "Shape #{name} is a document type. Document types are only supported in json protocols."
84
+ end
85
+ end
86
+ end
70
87
  end
71
88
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module AwsSdkCodeGenerator
2
4
  class HashFormatter
3
5
 
@@ -15,10 +17,11 @@ module AwsSdkCodeGenerator
15
17
  @wrap = options.fetch(:wrap, true)
16
18
  @inline = options.fetch(:inline, false)
17
19
  @quote_strings = options.fetch(:quote_strings, false)
20
+ @indent = options.fetch(:indent, '')
18
21
  end
19
22
 
20
23
  def format(obj)
21
- result = hash(obj, i:'', inline:@inline)
24
+ result = hash(obj, i: @indent, inline:@inline)
22
25
  result = unwrap(result, obj.size) if !@wrap
23
26
  result = result.strip if @inline && result.lines.to_a.length == 1
24
27
  result
@@ -34,7 +37,7 @@ module AwsSdkCodeGenerator
34
37
  when Array then array(obj, i:i)
35
38
  when String then @quote_strings ? obj.inspect : obj
36
39
  when Symbol then obj.inspect
37
- when Fixnum, true, false then obj.inspect
40
+ when Integer, true, false then obj.inspect
38
41
  else raise ArgumentError, "unsupported value `#{obj.class}'"
39
42
  end
40
43
  end