smithy 2.0.0.pre0 → 2.0.0.pre1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (103) hide show
  1. checksums.yaml +4 -4
  2. data/VERSION +1 -1
  3. data/bin/smithy-ruby +1 -4
  4. data/lib/smithy/command.rb +68 -0
  5. data/lib/smithy/generators/base.rb +19 -0
  6. data/lib/smithy/generators/client.rb +106 -0
  7. data/lib/smithy/generators/schema.rb +61 -0
  8. data/lib/smithy/generators.rb +29 -0
  9. data/lib/smithy/model/flattener.rb +114 -0
  10. data/lib/smithy/model/operation_parser.rb +42 -0
  11. data/lib/smithy/model/rbs.rb +57 -0
  12. data/lib/smithy/model/service_index.rb +51 -0
  13. data/lib/smithy/model/service_parser.rb +74 -0
  14. data/lib/smithy/model/shape.rb +49 -0
  15. data/lib/smithy/model/structure_parser.rb +43 -0
  16. data/lib/smithy/model/yard.rb +100 -0
  17. data/lib/smithy/model.rb +54 -0
  18. data/lib/smithy/plan.rb +79 -3
  19. data/lib/smithy/templates/client/auth_parameters.erb +29 -0
  20. data/lib/smithy/templates/client/auth_parameters_rbs.erb +14 -0
  21. data/lib/smithy/templates/client/auth_plugin.erb +115 -0
  22. data/lib/smithy/templates/client/auth_resolver.erb +16 -0
  23. data/lib/smithy/templates/client/auth_resolver_rbs.erb +5 -0
  24. data/lib/smithy/templates/client/client.erb +142 -0
  25. data/lib/smithy/templates/client/client_rbs.erb +29 -0
  26. data/lib/smithy/templates/client/customizations.erb +3 -0
  27. data/lib/smithy/templates/client/endpoint_parameters.erb +65 -0
  28. data/lib/smithy/templates/client/endpoint_parameters_rbs.erb +13 -0
  29. data/lib/smithy/templates/client/endpoint_plugin.erb +58 -0
  30. data/lib/smithy/templates/client/endpoint_provider.erb +15 -0
  31. data/lib/smithy/templates/client/endpoint_provider_rbs.erb +5 -0
  32. data/lib/smithy/templates/client/endpoint_provider_spec.erb +70 -0
  33. data/lib/smithy/templates/client/errors.erb +69 -0
  34. data/lib/smithy/templates/client/errors_rbs.erb +17 -0
  35. data/lib/smithy/templates/client/gemspec.erb +17 -0
  36. data/lib/smithy/templates/client/module.erb +22 -0
  37. data/lib/smithy/templates/client/module_rbs.erb +7 -0
  38. data/lib/smithy/templates/client/paginators.erb +33 -0
  39. data/lib/smithy/templates/client/protocol_spec.erb +144 -0
  40. data/lib/smithy/templates/client/rubocop_yml.erb +33 -0
  41. data/lib/smithy/templates/client/schema.erb +76 -0
  42. data/lib/smithy/templates/client/schema_rbs.erb +13 -0
  43. data/lib/smithy/templates/client/spec_helper.erb +10 -0
  44. data/lib/smithy/templates/client/types.erb +64 -0
  45. data/lib/smithy/templates/client/types_rbs.erb +47 -0
  46. data/lib/smithy/templates/client/waiters.erb +42 -0
  47. data/lib/smithy/util/hash_formatter.rb +124 -0
  48. data/lib/smithy/util/underscore.rb +18 -0
  49. data/lib/smithy/util.rb +9 -0
  50. data/lib/smithy/views/client/auth_parameter.rb +29 -0
  51. data/lib/smithy/views/client/auth_parameters.rb +23 -0
  52. data/lib/smithy/views/client/auth_parameters_rbs.rb +23 -0
  53. data/lib/smithy/views/client/auth_plugin.rb +35 -0
  54. data/lib/smithy/views/client/auth_resolver.rb +125 -0
  55. data/lib/smithy/views/client/auth_resolver_rbs.rb +19 -0
  56. data/lib/smithy/views/client/client.rb +208 -0
  57. data/lib/smithy/views/client/client_rbs.rb +231 -0
  58. data/lib/smithy/views/client/customizations.rb +10 -0
  59. data/lib/smithy/views/client/endpoint_parameter.rb +156 -0
  60. data/lib/smithy/views/client/endpoint_parameters.rb +43 -0
  61. data/lib/smithy/views/client/endpoint_parameters_rbs.rb +28 -0
  62. data/lib/smithy/views/client/endpoint_plugin.rb +27 -0
  63. data/lib/smithy/views/client/endpoint_provider.rb +241 -0
  64. data/lib/smithy/views/client/endpoint_provider_rbs.rb +19 -0
  65. data/lib/smithy/views/client/endpoint_provider_spec.rb +137 -0
  66. data/lib/smithy/views/client/errors.rb +88 -0
  67. data/lib/smithy/views/client/errors_rbs.rb +12 -0
  68. data/lib/smithy/views/client/gemspec.rb +36 -0
  69. data/lib/smithy/views/client/module.rb +107 -0
  70. data/lib/smithy/views/client/module_rbs.rb +20 -0
  71. data/lib/smithy/views/client/operation_examples.rb +157 -0
  72. data/lib/smithy/views/client/paginators.rb +108 -0
  73. data/lib/smithy/views/client/plugin.rb +29 -0
  74. data/lib/smithy/views/client/plugin_list.rb +57 -0
  75. data/lib/smithy/views/client/protocol_spec.rb +254 -0
  76. data/lib/smithy/views/client/request_response_example.rb +179 -0
  77. data/lib/smithy/views/client/rubocop_yml.rb +19 -0
  78. data/lib/smithy/views/client/schema.rb +356 -0
  79. data/lib/smithy/views/client/schema_rbs.rb +84 -0
  80. data/lib/smithy/views/client/shape_to_hash.rb +99 -0
  81. data/lib/smithy/views/client/spec_helper.rb +19 -0
  82. data/lib/smithy/views/client/types.rb +293 -0
  83. data/lib/smithy/views/client/types_rbs.rb +67 -0
  84. data/lib/smithy/views/client/waiters.rb +82 -0
  85. data/lib/smithy/views/client.rb +47 -0
  86. data/lib/smithy/views/view.rb +30 -0
  87. data/lib/smithy/views.rb +9 -0
  88. data/lib/smithy/weld.rb +109 -0
  89. data/lib/smithy/welds/auth/anonymous_auth.rb +31 -0
  90. data/lib/smithy/welds/auth/http_api_key_auth.rb +34 -0
  91. data/lib/smithy/welds/auth/http_basic_auth.rb +34 -0
  92. data/lib/smithy/welds/auth/http_bearer_auth.rb +34 -0
  93. data/lib/smithy/welds/auth/http_digest_auth.rb +34 -0
  94. data/lib/smithy/welds/plugins.rb +54 -0
  95. data/lib/smithy/welds/rpc_v2_cbor.rb +20 -0
  96. data/lib/smithy/welds/rubocop.rb +33 -0
  97. data/lib/smithy/welds/transforms/default_endpoint_rules.json +35 -0
  98. data/lib/smithy/welds/transforms/default_endpoint_tests.json +24 -0
  99. data/lib/smithy/welds/transforms/endpoints.rb +68 -0
  100. data/lib/smithy/welds/transforms/synthetic_input_output.rb +60 -0
  101. data/lib/smithy/welds.rb +29 -0
  102. data/lib/smithy.rb +33 -2
  103. metadata +144 -9
@@ -0,0 +1,109 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Smithy
4
+ # Base class that all welds must inherit from. Includes hooks for code generation.
5
+ class Weld
6
+ include Thor::Base
7
+ include Thor::Actions
8
+
9
+ # @param [Plan] plan The plan that is being executed.
10
+ def initialize(plan)
11
+ @plan = plan
12
+ # Necessary for Thor::Base and Thor::Actions
13
+ self.options = { force: true, quiet: plan.quiet }
14
+ self.destination_root = plan.destination_root
15
+ shell.base = self
16
+ end
17
+
18
+ # Called to determine if the weld should be applied for this model.
19
+ # @param [Hash] service Service shape
20
+ # @return [Boolean] (true) True if the weld should be applied, false otherwise.
21
+ def for?(service) # rubocop:disable Lint/UnusedMethodArgument
22
+ true
23
+ end
24
+
25
+ # Pre-process the model. Called before the model is loaded.
26
+ # @param [Hash] model
27
+ def pre_process(model)
28
+ model
29
+ end
30
+
31
+ # Post-process the artifacts after they are generated.
32
+ # @param [Array<String>] artifacts The files that were generated.
33
+ def post_process(artifacts)
34
+ artifacts
35
+ end
36
+
37
+ # Called when constructing the module and gemspec. Any dependencies defined
38
+ # here will be merged with other dependencies. The key is the name of the
39
+ # dependency and the value is the version constraint.
40
+ def add_dependencies
41
+ {}
42
+ end
43
+
44
+ # Called when constructing the module and gemspec. Any dependencies defined
45
+ # here will be removed from the module and gemspec. Each element in the
46
+ # array is the name of the dependency.
47
+ def remove_dependencies
48
+ []
49
+ end
50
+
51
+ # Called when constructing endpoint parameters. Any bindings defined here will
52
+ # be merged with other built-in bindings. The key is the name of the binding, and
53
+ # the value is the binding definition, which is a hash with keys :render_config,
54
+ # :render_build and :render_test_set.
55
+ # @return [Hash<String, Hash>] endpoint built in bindings for use in endpoint rules.
56
+ def endpoint_built_in_bindings
57
+ {}
58
+ end
59
+
60
+ # Called when constructing the endpoint provider. Any bindings defined here will
61
+ # be merged with other function bindings. The key is the name of the binding, and
62
+ # the value is the function to call.
63
+ # @return [Hash<String, String>] endpoint function bindings for use in endpoint rules.
64
+ def endpoint_function_bindings
65
+ {}
66
+ end
67
+
68
+ # Called when constructing the client. Any plugins defined here will be merged
69
+ # with other plugins. The key is the fully qualified class name of the plugin,
70
+ # and the value is a hash with any of the following keys:
71
+ # * :source - the source code of the plugin
72
+ # * :require_path - the path to require the plugin from the client
73
+ # * :require_relative - true if the path should be required relative to the client
74
+ # @return [Hash<String, Hash>] a mapping of fully qualified class names as the
75
+ # key, and the plugin
76
+ def add_plugins
77
+ {}
78
+ end
79
+
80
+ # Called when constructing the client. Any plugins defined here will be removed
81
+ # from the client. Each element in the array is the fully qualified class name.
82
+ def remove_plugins
83
+ []
84
+ end
85
+
86
+ # Called when resolving the available protocols for the client. The key is the
87
+ # protocol's configuration name, typically the shape ID, and the value is a class
88
+ # that will be initialized. The first protocol in the hash will be the default protocol.
89
+ # @return [Hash<String, Class>] protocols
90
+ def protocols
91
+ {}
92
+ end
93
+
94
+ # Called when creating the auth resolver and auth schemes. The key is the absolute shape
95
+ # id of the auth scheme trait, and the value is a hash with the following keys:
96
+ # * :auth_scheme_config_option - the client config option for the auth scheme.
97
+ # * :identity_provider_config_option - the client config option for the identity provider.
98
+ # * :identity_type - the identity type that the identity provider expects.
99
+ def add_auth_schemes
100
+ {}
101
+ end
102
+
103
+ # Called when creating the auth resolver and auth schemes. The value is the
104
+ # absolute shape id of the auth scheme trait.
105
+ def remove_auth_schemes
106
+ []
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'smithy-client/plugins/anonymous_auth'
4
+
5
+ module Smithy
6
+ module Welds
7
+ # Adds default Anonymous (optional) auth.
8
+ class AnonymousAuth < Weld
9
+ def for?(_service)
10
+ say_status :insert, 'Adding the AnonymousAuth plugin', :yellow unless @plan.quiet
11
+ true
12
+ end
13
+
14
+ def add_plugins
15
+ {
16
+ Smithy::Client::Plugins::AnonymousAuth => { require_path: 'smithy-client/plugins/anonymous_auth' }
17
+ }
18
+ end
19
+
20
+ def add_auth_schemes
21
+ {
22
+ 'smithy.api#noAuth' => {
23
+ auth_scheme_config_option: :anonymous_auth_scheme,
24
+ identity_provider_config_option: :anonymous_provider,
25
+ identity_type: Smithy::Client::Identities::Anonymous
26
+ }
27
+ }
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'smithy-client/plugins/http_api_key_auth'
4
+
5
+ module Smithy
6
+ module Welds
7
+ # Adds the HTTP API key Auth plugin if the service requires it.
8
+ class HttpApiKeyAuth < Weld
9
+ def for?(service)
10
+ _id, service = service.first
11
+ return false unless service.fetch('traits', {}).key?('smithy.api#httpApiKeyAuth')
12
+
13
+ say_status :insert, 'Adding the HttpApiKeyAuth plugin', :yellow unless @plan.quiet
14
+ true
15
+ end
16
+
17
+ def add_plugins
18
+ {
19
+ Smithy::Client::Plugins::HttpApiKeyAuth => { require_path: 'smithy-client/plugins/http_api_key_auth' }
20
+ }
21
+ end
22
+
23
+ def add_auth_schemes
24
+ {
25
+ 'smithy.api#httpApiKeyAuth' => {
26
+ auth_scheme_config_option: :http_api_key_auth_scheme,
27
+ identity_provider_config_option: :http_api_key_provider,
28
+ identity_type: Smithy::Client::Identities::HttpApiKey
29
+ }
30
+ }
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'smithy-client/plugins/http_basic_auth'
4
+
5
+ module Smithy
6
+ module Welds
7
+ # Adds the HTTP Basic Auth plugin if the service requires it.
8
+ class HttpBasicAuth < Weld
9
+ def for?(service)
10
+ _id, service = service.first
11
+ return false unless service.fetch('traits', {}).key?('smithy.api#httpBasicAuth')
12
+
13
+ say_status :insert, 'Adding the HttpBasicAuth plugin', :yellow unless @plan.quiet
14
+ true
15
+ end
16
+
17
+ def add_plugins
18
+ {
19
+ Smithy::Client::Plugins::HttpBasicAuth => { require_path: 'smithy-client/plugins/http_basic_auth' }
20
+ }
21
+ end
22
+
23
+ def add_auth_schemes
24
+ {
25
+ 'smithy.api#httpBasicAuth' => {
26
+ auth_scheme_config_option: :http_basic_auth_scheme,
27
+ identity_provider_config_option: :http_login_provider,
28
+ identity_type: Smithy::Client::Identities::HttpLogin
29
+ }
30
+ }
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'smithy-client/plugins/http_bearer_auth'
4
+
5
+ module Smithy
6
+ module Welds
7
+ # Adds the HTTP Bearer Auth plugin if the service requires it.
8
+ class HttpBearerAuth < Weld
9
+ def for?(service)
10
+ _id, service = service.first
11
+ return false unless service.fetch('traits', {}).key?('smithy.api#httpBearerAuth')
12
+
13
+ say_status :insert, 'Adding the HttpBearerAuth plugin', :yellow unless @plan.quiet
14
+ true
15
+ end
16
+
17
+ def add_plugins
18
+ {
19
+ Smithy::Client::Plugins::HttpBearerAuth => { require_path: 'smithy-client/plugins/http_bearer_auth' }
20
+ }
21
+ end
22
+
23
+ def add_auth_schemes
24
+ {
25
+ 'smithy.api#httpBearerAuth' => {
26
+ auth_scheme_config_option: :http_bearer_auth_scheme,
27
+ identity_provider_config_option: :http_bearer_provider,
28
+ identity_type: Smithy::Client::Identities::HttpBearer
29
+ }
30
+ }
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'smithy-client/plugins/http_digest_auth'
4
+
5
+ module Smithy
6
+ module Welds
7
+ # Adds the HTTP Digest Auth plugin if the service requires it.
8
+ class HttpDigestAuth < Weld
9
+ def for?(service)
10
+ _id, service = service.first
11
+ return false unless service.fetch('traits', {}).key?('smithy.api#httpDigestAuth')
12
+
13
+ say_status :insert, 'Adding the HttpDigestAuth plugin', :yellow unless @plan.quiet
14
+ true
15
+ end
16
+
17
+ def add_plugins
18
+ {
19
+ Smithy::Client::Plugins::HttpDigestAuth => { require_path: 'smithy-client/plugins/http_digest_auth' }
20
+ }
21
+ end
22
+
23
+ def add_auth_schemes
24
+ {
25
+ 'smithy.api#httpDigestAuth' => {
26
+ auth_scheme_config_option: :http_digest_auth_scheme,
27
+ identity_provider_config_option: :http_login_provider,
28
+ identity_type: Smithy::Client::Identities::HttpLogin
29
+ }
30
+ }
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'smithy-client/plugins/checksum_required'
4
+ require 'smithy-client/plugins/content_length'
5
+ require 'smithy-client/plugins/default_params'
6
+ require 'smithy-client/plugins/host_prefix'
7
+ require 'smithy-client/plugins/idempotency_token'
8
+ require 'smithy-client/plugins/logging'
9
+ require 'smithy-client/plugins/net_http'
10
+ require 'smithy-client/plugins/pageable_response'
11
+ require 'smithy-client/plugins/param_converter'
12
+ require 'smithy-client/plugins/param_validator'
13
+ require 'smithy-client/plugins/protocol'
14
+ require 'smithy-client/plugins/raise_response_errors'
15
+ require 'smithy-client/plugins/request_compression'
16
+ require 'smithy-client/plugins/response_target'
17
+ require 'smithy-client/plugins/retry_errors'
18
+ require 'smithy-client/plugins/sign_requests'
19
+ require 'smithy-client/plugins/stub_responses'
20
+
21
+ module Smithy
22
+ module Welds
23
+ # Provides default plugins.
24
+ class Plugins < Weld
25
+ def for?(_service)
26
+ say_status :insert, 'Adding default plugins', :yellow unless @plan.quiet
27
+ true
28
+ end
29
+
30
+ def add_plugins
31
+ base_path = 'smithy-client/plugins'
32
+ {
33
+ Smithy::Client::Plugins::ChecksumRequired => { require_path: "#{base_path}/checksum_required" },
34
+ Smithy::Client::Plugins::ContentLength => { require_path: "#{base_path}/content_length" },
35
+ Smithy::Client::Plugins::DefaultParams => { require_path: "#{base_path}/default_params" },
36
+ Smithy::Client::Plugins::HostPrefix => { require_path: "#{base_path}/host_prefix" },
37
+ Smithy::Client::Plugins::IdempotencyToken => { require_path: "#{base_path}/idempotency_token" },
38
+ Smithy::Client::Plugins::Logging => { require_path: "#{base_path}/logging" },
39
+ Smithy::Client::Plugins::NetHTTP => { require_path: "#{base_path}/net_http" },
40
+ Smithy::Client::Plugins::PageableResponse => { require_path: "#{base_path}/pageable_response" },
41
+ Smithy::Client::Plugins::ParamConverter => { require_path: "#{base_path}/param_converter" },
42
+ Smithy::Client::Plugins::ParamValidator => { require_path: "#{base_path}/param_validator" },
43
+ Smithy::Client::Plugins::Protocol => { require_path: "#{base_path}/protocol" },
44
+ Smithy::Client::Plugins::RaiseResponseErrors => { require_path: "#{base_path}/raise_response_errors" },
45
+ Smithy::Client::Plugins::RequestCompression => { require_path: "#{base_path}/request_compression" },
46
+ Smithy::Client::Plugins::ResponseTarget => { require_path: "#{base_path}/response_target" },
47
+ Smithy::Client::Plugins::RetryErrors => { require_path: "#{base_path}/retry_errors" },
48
+ Smithy::Client::Plugins::SignRequests => { require_path: "#{base_path}/sign_requests" },
49
+ Smithy::Client::Plugins::StubResponses => { require_path: "#{base_path}/stub_responses" }
50
+ }
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Smithy
4
+ module Welds
5
+ # Adds the RPCv2 CBOR protocol to the client if the service has the trait.
6
+ class RPCv2CBOR < Weld
7
+ def for?(service)
8
+ _, service = service.first
9
+ return false unless service.fetch('traits', {}).key?('smithy.protocols#rpcv2Cbor')
10
+
11
+ say_status :insert, 'Adding the RPCv2 CBOR protocol', :yellow unless @plan.quiet
12
+ true
13
+ end
14
+
15
+ def protocols
16
+ { 'rpcv2Cbor' => Smithy::Client::RPCv2CBOR::Protocol }
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Smithy
4
+ module Welds
5
+ # Runs RuboCop autocorrect-all on the generated projections.
6
+ class Rubocop < Weld
7
+ TEST_NAMESPACES = [
8
+ Regexp.new('smithy.tests.*?'),
9
+ Regexp.new('smithy.protocoltests.*?'),
10
+ Regexp.new('smithy.ruby.tests.*?')
11
+ ].freeze
12
+
13
+ def for?(service)
14
+ namespace = Model::Shape.namespace(service.keys.first).to_s
15
+ TEST_NAMESPACES.none? { |test_namespace| namespace.match?(test_namespace) }
16
+ end
17
+
18
+ def post_process(_artifacts)
19
+ require 'rubocop'
20
+ puts "Running RuboCop --autocorrect-all on #{destination_root}"
21
+ rubocop = ::RuboCop::CLI.new
22
+ args = [
23
+ '--autocorrect-all',
24
+ '--display-only-fail-level-offenses',
25
+ '--config',
26
+ "#{destination_root}/.rubocop.yml",
27
+ destination_root
28
+ ]
29
+ rubocop.run(args)
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,35 @@
1
+ {
2
+ "version": "1.0",
3
+ "parameters": {
4
+ "endpoint": {
5
+ "type": "string",
6
+ "builtIn": "SDK::Endpoint",
7
+ "documentation": "Endpoint used for making requests. Should be formatted as a URI."
8
+ }
9
+ },
10
+ "rules": [
11
+ {
12
+ "conditions": [
13
+ {
14
+ "fn": "isSet",
15
+ "argv": [
16
+ {
17
+ "ref": "endpoint"
18
+ }
19
+ ]
20
+ }
21
+ ],
22
+ "endpoint": {
23
+ "url": {
24
+ "ref": "endpoint"
25
+ }
26
+ },
27
+ "type": "endpoint"
28
+ },
29
+ {
30
+ "conditions": [],
31
+ "error": "Endpoint is not set - you must configure an endpoint.",
32
+ "type": "error"
33
+ }
34
+ ]
35
+ }
@@ -0,0 +1,24 @@
1
+ {
2
+ "version": "1.0",
3
+ "testCases": [
4
+ {
5
+ "documentation": "Endpoint set",
6
+ "expect": {
7
+ "endpoint": {
8
+ "url": "https://example.com"
9
+ }
10
+ },
11
+ "params": {
12
+ "endpoint": "https://example.com"
13
+ }
14
+ },
15
+ {
16
+ "documentation": "Endpoint not set",
17
+ "expect": {
18
+ "error": "Endpoint is not set - you must configure an endpoint."
19
+ },
20
+ "params": {
21
+ }
22
+ }
23
+ ]
24
+ }
@@ -0,0 +1,68 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Smithy
4
+ module Welds
5
+ # Provides default endpoint builtin/function bindings.
6
+ class Endpoints < Weld
7
+ def pre_process(model)
8
+ id, service = model['shapes'].select { |_k, s| s['type'] == 'service' }.first
9
+ return if service['traits'] && service['traits']['smithy.rules#endpointRuleSet']
10
+
11
+ say_status :insert, "Adding default endpoint rules to service #{id}", :yellow unless @plan.quiet
12
+ add_default_endpoints(service)
13
+ end
14
+
15
+ def endpoint_built_in_bindings
16
+ {
17
+ 'SDK::Endpoint' => {
18
+ render_config: proc do |_plan|
19
+ <<~ADD_OPTION
20
+ option(
21
+ :endpoint,
22
+ doc_type: String,
23
+ docstring: 'Custom Endpoint'
24
+ )
25
+ ADD_OPTION
26
+ end,
27
+ render_build: proc do |_plan|
28
+ 'config.endpoint'
29
+ end,
30
+ render_test_set: proc do |_plan, value|
31
+ { 'endpoint' => value }
32
+ end
33
+ }
34
+ }
35
+ end
36
+
37
+ def endpoint_function_bindings
38
+ {
39
+ 'isValidHostLabel' => 'Smithy::Client::EndpointRules.valid_host_label?',
40
+ 'parseURL' => 'Smithy::Client::EndpointRules.parse_url',
41
+ 'substring' => 'Smithy::Client::EndpointRules.substring',
42
+ 'uriEncode' => 'Smithy::Client::EndpointRules.uri_encode',
43
+ 'isSet' => 'Smithy::Client::EndpointRules.set?',
44
+ 'not' => 'Smithy::Client::EndpointRules.not?',
45
+ 'getAttr' => 'Smithy::Client::EndpointRules.attr',
46
+ 'stringEquals' => 'Smithy::Client::EndpointRules.string_equals?',
47
+ 'booleanEquals' => 'Smithy::Client::EndpointRules.boolean_equals?'
48
+ }
49
+ end
50
+
51
+ private
52
+
53
+ def add_default_endpoints(service)
54
+ service['traits'] ||= {}
55
+ service['traits']['smithy.rules#endpointRuleSet'] = default_endpoint_rules
56
+ service['traits']['smithy.rules#endpointTests'] = default_endpoint_tests
57
+ end
58
+
59
+ def default_endpoint_rules
60
+ ::JSON.load_file(File.join(__dir__.to_s, 'default_endpoint_rules.json'))
61
+ end
62
+
63
+ def default_endpoint_tests
64
+ ::JSON.load_file(File.join(__dir__.to_s, 'default_endpoint_tests.json'))
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_support/core_ext/object/deep_dup'
4
+
5
+ module Smithy
6
+ module Welds
7
+ # Creates synthetic input and output shapes for operations that do not have them.
8
+ class SyntheticInputOutput < Weld
9
+ def pre_process(model)
10
+ say_status :modify, 'Creating synthetic input and output shapes', :yellow unless @plan.quiet
11
+ create_synthetic_input_output_shapes(model)
12
+ end
13
+
14
+ private
15
+
16
+ def create_synthetic_input_output_shapes(model)
17
+ Model::ServiceIndex.new(model).operations_for(@plan.service).each do |operation_id, operation|
18
+ create_synthetic_input_shape(model, operation_id, operation) if operation['input']
19
+ create_synthetic_output_shape(model, operation_id, operation) if operation['output']
20
+ end
21
+ end
22
+
23
+ def create_synthetic_input_shape(model, operation_id, operation)
24
+ input_target = operation['input']['target']
25
+ target = Model.shape(model, input_target)
26
+ return if target.fetch('traits', {}).key?('smithy.api#input') || input_target == 'smithy.api#Unit'
27
+
28
+ input_target = new_shape_id(model, operation_id, 'Input')
29
+ operation['input']['target'] = input_target
30
+ input_shape = target.deep_dup
31
+ model['shapes'][input_target] = input_shape
32
+ input_shape['traits'] = input_shape.fetch('traits', {}).merge({ 'smithy.api#input' => {} })
33
+ end
34
+
35
+ def create_synthetic_output_shape(model, operation_id, operation)
36
+ output_target = operation['output']['target']
37
+ target = Model.shape(model, output_target)
38
+ return if target.fetch('traits', {}).key?('smithy.api#output') || output_target == 'smithy.api#Unit'
39
+
40
+ output_target = new_shape_id(model, operation_id, 'Output')
41
+ operation['output']['target'] = output_target
42
+ output_shape = target.deep_dup
43
+ model['shapes'][output_target] = output_shape
44
+ output_shape['traits'] = output_shape.fetch('traits', {}).merge({ 'smithy.api#output' => {} })
45
+ end
46
+
47
+ def new_shape_id(model, operation_id, suffix)
48
+ namespace = Model::Shape.namespace(operation_id)
49
+ operation_name = Model::Shape.name(operation_id)
50
+ id = "#{namespace}##{operation_name}#{suffix}"
51
+ return id unless model['shapes'].key?(id)
52
+
53
+ id = "#{namespace}##{operation_name}Operation#{suffix}"
54
+ return id unless model['shapes'].key?(id)
55
+
56
+ raise "unable to generate a unique synthetic #{suffix} shape ID for #{operation_id}"
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'welds/auth/anonymous_auth'
4
+ require_relative 'welds/auth/http_api_key_auth'
5
+ require_relative 'welds/auth/http_basic_auth'
6
+ require_relative 'welds/auth/http_bearer_auth'
7
+ require_relative 'welds/auth/http_digest_auth'
8
+
9
+ require_relative 'welds/transforms/endpoints'
10
+ require_relative 'welds/transforms/synthetic_input_output'
11
+
12
+ require_relative 'welds/plugins'
13
+ require_relative 'welds/rpc_v2_cbor'
14
+ # require_relative 'welds/rubocop'
15
+
16
+ module Smithy
17
+ # @api private
18
+ module Welds
19
+ @welds = {}
20
+
21
+ def self.load!(plan)
22
+ Weld.subclasses.each { |weld| @welds[weld] = weld.new(plan) }
23
+ end
24
+
25
+ def self.for(service)
26
+ @welds.each_value.select { |weld| weld.for?(service) }
27
+ end
28
+ end
29
+ end
data/lib/smithy.rb CHANGED
@@ -1,7 +1,38 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'rails/railtie'
4
+ require 'smithy-client'
5
+ require 'thor'
6
+
7
+ require_relative 'smithy/command'
8
+ require_relative 'smithy/generators'
9
+ require_relative 'smithy/model'
3
10
  require_relative 'smithy/plan'
11
+ require_relative 'smithy/util'
12
+ require_relative 'smithy/views'
13
+ require_relative 'smithy/weld'
14
+ require_relative 'smithy/welds'
4
15
 
16
+ # Smithy is a modeling language created by AWS. This gem provides a Ruby
17
+ # implementation of the Smithy language and generates clients, servers, and schemas.
5
18
  module Smithy
6
- VERSION = File.read(File.expand_path('../VERSION', __dir__)).strip
7
- end
19
+ VERSION = File.read(File.expand_path('../VERSION', __dir__.to_s)).strip
20
+
21
+ # Generates Ruby code from a Smithy model and writes them to files.
22
+ # @param [Plan] plan The plan to generate the artifacts from.
23
+ # @return [Array<String>] The generated files.
24
+ def self.generate(plan)
25
+ plan.welds.each { |weld| weld.pre_process(plan.model) }
26
+ artifacts = Smithy::Generators.generate(plan)
27
+ plan.welds.each { |weld| weld.post_process(artifacts) }
28
+ artifacts
29
+ end
30
+
31
+ # Generates minimal Ruby code from a Smithy model and returns the source code.
32
+ # @param [Plan] plan The plan to generate the source from.
33
+ # @return [String] The generated source code.
34
+ def self.source(plan)
35
+ plan.welds.each { |weld| weld.pre_process(plan.model) }
36
+ Smithy::Generators.source(plan)
37
+ end
38
+ end