Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 12 additions & 2 deletions .rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,23 @@ AllCops:
TargetRubyVersion: 3.0
SuggestExtensions: false
Exclude:
- 'vendor/**/*'
- 'tasks/release/**/*'
- 'build/**/*'
- 'tasks/release/**/*'
- 'vendor/**/*'

Gemspec/RequireMFA:
Enabled: false

Layout/EmptyLinesAroundClassBody:
Exclude:
- 'projections/**/*/errors.rb'
- 'projections/**/*/types.rb'

Layout/EmptyLinesAroundModuleBody:
Exclude:
- 'projections/**/*/errors.rb'
- 'projections/**/*/types.rb'

Metrics/BlockLength:
Exclude:
- '**/spec/**/*.rb'
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ bundle exec smithy build --debug model/weather.smithy
local build using smithy-ruby executable
```
export SMITHY_PLUGIN_DIR=build/smithy/source/smithy-ruby
bundle exec smithy-ruby smith types --gem-name some_organization-weather --gem-version 1.0.0 <<< $(smithy ast model/weather.smithy)
bundle exec smithy-ruby smith client --gem-name weather --gem-version 1.0.0 --destination-root projections/weather <<< $(smithy ast model/weather.smithy)
```

IRB on weather gem
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,17 @@
# This is generated code!

module <%= namespace %>
# TODO!
class Client < Smithy::Client::Base
# self.api = API

<%- plugins.each do |p| -%>
add_plugin(<%= p %>)
<%- end %>
<%- end -%>

# TODO
# TODO!
def initialize(*args)
super(*args)
super
end

<%- operations.each do |operation| -%>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# frozen_string_literal: true

# Any customizations can be added here.
9 changes: 2 additions & 7 deletions gems/smithy/lib/smithy/anvil/client/templates/errors.erb
Original file line number Diff line number Diff line change
Expand Up @@ -34,17 +34,12 @@ module <%= namespace %>

<%= error.documentation %>
class <%= error.name %> < Smithy::Client::Errors::ServiceError
# @param [Smithy::Client::HandlerContext] context
# @param [String] message
# @param [<%= namespace %>::Types::<%= error.name %>] data
def initialize(context, message, data)
super(context, message, data)
end
<%- error.member_names.each do |member| -%>

<%- error.member_names.each do |member| -%>
def <%= member %>
@data[:<%= member %>]
end

<%- end -%>
end
<%- end -%>
Expand Down
2 changes: 2 additions & 0 deletions gems/smithy/lib/smithy/anvil/client/templates/gemspec.erb
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,6 @@ Gem::Specification.new do |s|
s.files = Dir['lib/**/*.rb', base: __dir__]

s.add_dependency('smithy-client', '~> 1')

s.required_ruby_version = '>= 3.0'
end
1 change: 1 addition & 0 deletions gems/smithy/lib/smithy/anvil/client/views.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# frozen_string_literal: true

require_relative 'views/client_class'
require_relative 'views/customizations'
require_relative 'views/errors'
require_relative 'views/gemspec'
require_relative 'views/module'
Expand Down
12 changes: 12 additions & 0 deletions gems/smithy/lib/smithy/anvil/client/views/customizations.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# frozen_string_literal: true

module Smithy
module Anvil
module Client
module Views
# @api private
class Customizations < View; end
end
end
end
end
2 changes: 1 addition & 1 deletion gems/smithy/lib/smithy/anvil/client/views/module.rb
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ def requires
if @plan.type == :types
[:types]
else
%i[client errors types]
%i[client customizations errors types]
end
end
end
Expand Down
9 changes: 0 additions & 9 deletions gems/smithy/lib/smithy/forge/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,6 @@ def initialize(plan)
self.options = { force: true }
self.destination_root = plan.options[:destination_root]
end

# @return [Enumerable<String, String>] The file paths and their contents to generate.
def forge
files = source_files
files.each do |file, content|
create_file file, content
end
files
end
end
end
end
50 changes: 45 additions & 5 deletions gems/smithy/lib/smithy/forge/client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,57 @@ def initialize(plan)
super
end

# @return [Enumerable<String, String>] The file paths and their contents to generate.
def forge
files = source_files
files.each do |file, content|
next if file == "lib/#{@gem_name}/customizations.rb" && should_skip_customizations?

create_file file, content
end
files
end

private

def source_files
Enumerator.new do |e|
e.yield "#{@gem_name}.gemspec", Anvil::Client::Views::Gemspec.new(@plan).hammer
e.yield "lib/#{@gem_name}.rb", Anvil::Client::Views::Module.new(@plan).hammer
e.yield "lib/#{@gem_name}/types.rb", Anvil::Client::Views::Types.new(@plan).hammer
e.yield "lib/#{@gem_name}/errors.rb", Anvil::Client::Views::Errors.new(@plan).hammer
e.yield "lib/#{@gem_name}/client.rb", Anvil::Client::Views::ClientClass.new(@plan).hammer
e.yield "#{@gem_name}.gemspec", render_gemspec
e.yield "lib/#{@gem_name}.rb", render_module
e.yield "lib/#{@gem_name}/client.rb", render_client
e.yield "lib/#{@gem_name}/customizations.rb", render_customizations
e.yield "lib/#{@gem_name}/types.rb", render_types
e.yield "lib/#{@gem_name}/errors.rb", render_errors
end
end

def render_gemspec
Anvil::Client::Views::Gemspec.new(@plan).hammer
end

def render_module
Anvil::Client::Views::Module.new(@plan).hammer
end

def render_client
Anvil::Client::Views::ClientClass.new(@plan).hammer
end

def render_customizations
Anvil::Client::Views::Customizations.new.hammer
end

def render_types
Anvil::Client::Views::Types.new(@plan).hammer
end

def render_errors
Anvil::Client::Views::Errors.new(@plan).hammer
end

def should_skip_customizations?
Dir["#{destination_root}/**/*"].any? { |f| f.include?('/customizations.rb') }
end
end
end
end
9 changes: 9 additions & 0 deletions gems/smithy/lib/smithy/forge/types.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,15 @@ def initialize(plan)
super
end

# @return [Enumerable<String, String>] The file paths and their contents to generate.
def forge
files = source_files
files.each do |file, content|
create_file file, content
end
files
end

private

def source_files
Expand Down
34 changes: 34 additions & 0 deletions gems/smithy/spec/interfaces/client/customizations_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# frozen_string_literal: true

describe 'Component: Customizations' do
before(:all) do
@tmpdir = SpecHelper.generate(['Weather'], :client)
end

after(:all) do
SpecHelper.cleanup(['Weather'], @tmpdir)
end

subject { Weather::Client.new(endpoint: 'https://example.com') }

it 'should have a customizations file' do
expect(File).to exist(File.join(@tmpdir, 'lib', 'weather', 'customizations.rb'))
end

it 'should require the customizations file' do
expect(require('weather/customizations')).to eq(false)
end

it 'does not overwrite an existing customizations file' do
customization = <<~RUBY
module Weather
module Customizations; end
end
RUBY
customizations_file = File.join(@tmpdir, 'lib', 'weather', 'customizations.rb')
expect(File.read(customizations_file)).to_not include(customization)
File.write(customizations_file, customization)
SpecHelper.generate(['Weather'], :client, destination_root: @tmpdir)
expect(File.read(customizations_file)).to include(customization)
end
end
10 changes: 5 additions & 5 deletions gems/smithy/spec/spec_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class << self
# written to.
def generate(modules, type, options = {})
model = load_model(modules, options)
plan = create_plan(model, type, modules)
plan = create_plan(modules, model, type, options)

Smithy.smith(plan)
$LOAD_PATH << ("#{plan.options[:destination_root]}/lib")
Expand Down Expand Up @@ -52,11 +52,11 @@ def load_model(modules, options)
JSON.load_file(File.join(model_dir, 'model.json'))
end

def create_plan(model, type, modules)
def create_plan(modules, model, type, options)
plan_options = {
gem_name: Smithy::Tools::Namespace.gem_name_from_namespaces(modules),
gem_version: '1.0.0',
destination_root: Dir.mktmpdir
gem_name: options[:gem_name] || Smithy::Tools::Namespace.gem_name_from_namespaces(modules),
gem_version: options[:gem_version] || '1.0.0',
destination_root: options[:destination_root] || Dir.mktmpdir
}
Smithy::Plan.new(model, type, plan_options)
end
Expand Down
14 changes: 14 additions & 0 deletions projections/weather/lib/weather.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# frozen_string_literal: true

# This is generated code!

require 'smithy-client'

module Weather
VERSION = '1.0.0'
end

require_relative 'weather/client'
require_relative 'weather/customizations'
require_relative 'weather/errors'
require_relative 'weather/types'
57 changes: 57 additions & 0 deletions projections/weather/lib/weather/client.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# frozen_string_literal: true

# This is generated code!

module Weather
# TODO!
class Client < Smithy::Client::Base
# self.api = API

add_plugin(Smithy::Client::Plugins::NetHTTP)

# TODO!
def initialize(*args)
super
end

# TODO!
def get_city(params = {}, options = {})
input = build_input(:get_city, params)
input.send_request(options)
end

# TODO!
def get_current_time(params = {}, options = {})
input = build_input(:get_current_time, params)
input.send_request(options)
end

# TODO!
def get_forecast(params = {}, options = {})
input = build_input(:get_forecast, params)
input.send_request(options)
end

# TODO!
def list_cities(params = {}, options = {})
input = build_input(:list_cities, params)
input.send_request(options)
end

private

def build_input(operation_name, params)
handlers = @handlers.for(operation_name)
context = Smithy::Client::HandlerContext.new(
operation_name: operation_name,
operation: config.api.operation(operation_name),
client: self,
params: params,
config: config
)
context[:gem_name] = 'weather'
context[:gem_version] = '1.0.0'
Smithy::Client::Input.new(handlers, context)
end
end
end
10 changes: 10 additions & 0 deletions projections/weather/lib/weather/customizations.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# frozen_string_literal: true

# Any customizations can be added here.

module Weather
# Weather customization
module Customizations
# I should always exist!
end
end
41 changes: 41 additions & 0 deletions projections/weather/lib/weather/errors.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# frozen_string_literal: true

# This is generated code!

module Weather
# When this service returns an error response, the SDK constructs and raises an error.
# These errors all extend Weather::Errors::ServiceError < {Smithy::Client::Errors::ServiceError}
#
# You can rescue all errors using the ServiceError:
#
# begin
# # do stuff
# rescue Weather::Errors::ServiceError
# # rescues all API errors
# end
#
# ## Request Context
#
# ServiceError objects have a {Smithy::Client::Errors::ServiceError#context #context} method
# that returns information about the request that generated the error.
# See {Smithy::Client::HandlerContext} for more information.
#
# ## Error Classes
#
# * {NoSuchResource}
#
# Additionally, error classes are dynamically generated for service errors based on the error code
# if they are not defined above.
module Errors
extend Smithy::Client::Errors::DynamicErrors

# TODO!
class NoSuchResource < Smithy::Client::Errors::ServiceError

def resource_type
@data[:resource_type]
end

end
end
end
Loading