zilla 0.1.1 → 0.1.2

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3cfb7c21cb7e5af74461ab0c8caeb711368a7f8548e228fad039578dc3d1e42b
4
- data.tar.gz: d2f8730e425912ab9ba43cdfb19190e59b446d64c123d84dfc392a7fd2bf2e02
3
+ metadata.gz: b2a5bdb6b217e29a2a4c21caa1ce01231500f2ca70c989684b6890000822f807
4
+ data.tar.gz: a0ee0fb62e290e75d5ff76f604245b80ed487cf22f749fbcf69efe26addda88a
5
5
  SHA512:
6
- metadata.gz: aa3973517ead3d94119eeeefaa0549c47697f1f5ea4c1f5262c4bcfed55808dce4dcbcfac11b362f9b6465fd0aeee3eb3f0c3a1b4ab221e9a418628834c11ddd
7
- data.tar.gz: 856bcf5b69ece2888f4b1b157cada1307b6cad333970581cf43a449cf2fb50c6cd3e59d6b794c027a16d2b9771572c79560f635741b168fa97926d9c2d28480d
6
+ metadata.gz: e0b298023b39eef460dc2a6c5af35f744c00c0dcef12666346e5526da9afbdd290dbaf01bac969ce457abd0668822bf2baa11d492b6311e59ff6ddc8501d89ef
7
+ data.tar.gz: bf3bf4a7bede9991cedc7eea25946d693387594d002efdf2650b69402658ce39d7123a08a65e118867e35b40e3f7f26d7ae667912b1475202ad6c870b2f78345
data/.rspec CHANGED
@@ -1,3 +1,4 @@
1
1
  --format progress
2
2
  --color
3
3
  --require spec_helper
4
+ --order random
data/.rubocop.yml CHANGED
@@ -44,4 +44,4 @@ Style/ClassAndModuleChildren:
44
44
  EnforcedStyle: compact
45
45
 
46
46
  RSpec/NestedGroups:
47
- Max: 5
47
+ Max: 6
data/Gemfile CHANGED
@@ -2,7 +2,6 @@
2
2
 
3
3
  source "https://rubygems.org"
4
4
 
5
- # Specify your gem's dependencies in async-openapi.gemspec
6
5
  gemspec
7
6
 
8
7
  gem "rake", "~> 13.0"
@@ -13,7 +12,6 @@ gem "rubocop", "~> 1.21"
13
12
  gem "rubocop-performance"
14
13
  gem "rubocop-rspec"
15
14
 
16
- gem "async-rspec"
17
15
  gem "simplecov"
18
16
  gem "webmock"
19
17
 
data/Gemfile.lock CHANGED
@@ -1,9 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- zilla (0.1.1)
5
- async (~> 2.3.0)
6
- async-http-faraday (~> 0.11)
4
+ zilla (0.1.2)
7
5
  faraday (~> 2.7.0)
8
6
  json_schemer (~> 0.2.0)
9
7
  memery (~> 1.4.0)
@@ -16,34 +14,9 @@ GEM
16
14
  addressable (2.8.1)
17
15
  public_suffix (>= 2.0.2, < 6.0)
18
16
  ast (2.4.2)
19
- async (2.3.1)
20
- console (~> 1.10)
21
- io-event (~> 1.1)
22
- timers (~> 4.1)
23
- async-http (0.59.4)
24
- async (>= 1.25)
25
- async-io (>= 1.28)
26
- async-pool (>= 0.2)
27
- protocol-http (~> 0.23.1)
28
- protocol-http1 (~> 0.14.0)
29
- protocol-http2 (~> 0.14.0)
30
- traces (>= 0.8.0)
31
- async-http-faraday (0.11.0)
32
- async-http (~> 0.42)
33
- faraday
34
- async-io (1.34.1)
35
- async
36
- async-pool (0.3.12)
37
- async (>= 1.25)
38
- async-rspec (1.16.1)
39
- rspec (~> 3.0)
40
- rspec-files (~> 1.0)
41
- rspec-memory (~> 1.0)
42
17
  backport (1.2.0)
43
18
  benchmark (0.2.1)
44
19
  childprocess (4.1.0)
45
- console (1.16.2)
46
- fiber-local
47
20
  crack (0.4.5)
48
21
  rexml
49
22
  diff-lcs (1.5.0)
@@ -55,11 +28,9 @@ GEM
55
28
  faraday-net_http (>= 2.0, < 3.1)
56
29
  ruby2_keywords (>= 0.0.4)
57
30
  faraday-net_http (3.0.2)
58
- fiber-local (1.0.0)
59
31
  hana (1.3.7)
60
32
  hashdiff (1.0.1)
61
33
  iniparse (1.5.0)
62
- io-event (1.1.6)
63
34
  jaro_winkler (1.5.4)
64
35
  json (2.6.3)
65
36
  json_schemer (0.2.24)
@@ -83,13 +54,6 @@ GEM
83
54
  parallel (1.22.1)
84
55
  parser (3.2.0.0)
85
56
  ast (~> 2.4.1)
86
- protocol-hpack (1.4.2)
87
- protocol-http (0.23.12)
88
- protocol-http1 (0.14.6)
89
- protocol-http (~> 0.22)
90
- protocol-http2 (0.14.2)
91
- protocol-hpack (~> 1.4)
92
- protocol-http (~> 0.18)
93
57
  public_suffix (5.0.1)
94
58
  racc (1.6.2)
95
59
  rainbow (3.1.1)
@@ -107,10 +71,6 @@ GEM
107
71
  rspec-expectations (3.12.2)
108
72
  diff-lcs (>= 1.2.0, < 2.0)
109
73
  rspec-support (~> 3.12.0)
110
- rspec-files (1.1.3)
111
- rspec (~> 3.0)
112
- rspec-memory (1.0.3)
113
- rspec (~> 3.0)
114
74
  rspec-mocks (3.12.3)
115
75
  diff-lcs (>= 1.2.0, < 2.0)
116
76
  rspec-support (~> 3.12.0)
@@ -160,8 +120,6 @@ GEM
160
120
  yard (~> 0.9, >= 0.9.24)
161
121
  thor (1.2.1)
162
122
  tilt (2.0.11)
163
- timers (4.3.5)
164
- traces (0.8.0)
165
123
  unicode-display_width (2.4.2)
166
124
  uri_template (0.7.0)
167
125
  webmock (3.18.1)
@@ -177,7 +135,6 @@ PLATFORMS
177
135
  x86_64-linux
178
136
 
179
137
  DEPENDENCIES
180
- async-rspec
181
138
  overcommit
182
139
  rake (~> 13.0)
183
140
  rspec (~> 3.0)
@@ -8,15 +8,15 @@ module Zilla::ClientFactory
8
8
  }.freeze
9
9
 
10
10
  class << self
11
- def build(input)
12
- definition = Zilla::LoaderFactory.build(input).load
11
+ def build(input, host: nil, scheme: nil, &block)
12
+ definition = Zilla::LoaderFactory.build(input, &block).load
13
13
 
14
14
  version = definition["swagger"]
15
15
 
16
16
  raise ArgumentError, "#{input.inspect} is not an OpenAPI definition" if version.nil?
17
17
  raise UnsupportedVersion, "usupported version #{version.inspect}" if version && CLIENTS[version].nil?
18
18
 
19
- CLIENTS[version].new(definition)
19
+ CLIENTS[version].new(definition, host:, scheme:, faraday_config_block: block)
20
20
  end
21
21
  end
22
22
  end
@@ -4,13 +4,13 @@ module Zilla::LoaderFactory
4
4
  class UnknownLoader < Zilla::Error; end
5
5
 
6
6
  class << self
7
- def build(input)
7
+ def build(input, &block)
8
8
  case input
9
9
  when Hash
10
10
  Zilla::Loaders::Hash
11
11
  when String
12
12
  for_string(input)
13
- end.new(input)
13
+ end.new(input, faraday_config_block: block)
14
14
  rescue NoMethodError
15
15
  raise UnknownLoader, "cannot find loader for #{input.inspect}"
16
16
  end
@@ -3,7 +3,7 @@
3
3
  class Zilla::Loaders::HTTP < Zilla::Loaders::Loader
4
4
  def load_string
5
5
  Faraday.new(input) do |f|
6
- f.adapter :async_http
6
+ @faraday_config_block.call(f, :loader)
7
7
  f.response :raise_error
8
8
  end.get.body
9
9
  end
@@ -5,8 +5,9 @@ class Zilla::Loaders::Loader
5
5
 
6
6
  attr_reader :input
7
7
 
8
- def initialize(input)
8
+ def initialize(input, faraday_config_block: nil)
9
9
  @input = input
10
+ @faraday_config_block = faraday_config_block || ->(_f, _target) {}
10
11
  end
11
12
 
12
13
  def load
data/lib/zilla/version.rb CHANGED
@@ -4,5 +4,5 @@ module Zilla
4
4
  module Version
5
5
  end
6
6
 
7
- VERSION = "0.1.1"
7
+ VERSION = "0.1.2"
8
8
  end
@@ -5,14 +5,15 @@ class Zilla::Versions::V20::Client
5
5
 
6
6
  include Memery
7
7
 
8
- attr_reader :json, :host, :scheme
8
+ attr_reader :json, :host, :scheme, :faraday_config_block
9
9
 
10
- def initialize(json, host: nil, scheme: :https)
10
+ def initialize(json, host: nil, scheme: nil, faraday_config_block: nil) # rubocop:disable Metrics/AbcSize
11
11
  @json = json
12
12
  @host = host || api.host || raise(ArgumentError, ":host must be specified")
13
- @scheme = scheme.to_s
13
+ @scheme = (scheme || :https).to_s
14
+ @faraday_config_block = faraday_config_block || ->(_f, _target) {}
14
15
 
15
- unless api.schemes.include?(@scheme)
16
+ if api.schemes && !api.schemes.include?(@scheme)
16
17
  raise ArgumentError, "unsupported scheme #{@scheme.inspect}. Supported: #{api.schemes}"
17
18
  end
18
19
 
@@ -21,7 +22,7 @@ class Zilla::Versions::V20::Client
21
22
 
22
23
  memoize def api = API.new(json)
23
24
 
24
- memoize def executor = Executor.new(scheme, host)
25
+ memoize def executor = Executor.new(scheme, host, faraday_config_block:)
25
26
 
26
27
  private
27
28
 
@@ -8,6 +8,8 @@ class Zilla::Versions::V20::Endpoint
8
8
  attr_reader :path, :method, :json, :definitions
9
9
 
10
10
  def initialize(path, method, json, definitions: {})
11
+ raise ArgumentError, "json must be a Hash, given: #{json.class.inspect}" unless json.instance_of?(Hash)
12
+
11
13
  @path = path
12
14
  @method = method
13
15
  @json = json
@@ -23,4 +25,5 @@ class Zilla::Versions::V20::Endpoint
23
25
  memoize def path_template = PathTemplate.new(path)
24
26
 
25
27
  memoize def parameters = Parameters.new(json["parameters"], definitions:)
28
+ memoize def responses = json["responses"].transform_values { |v| JSONSchemer.schema(v) }
26
29
  end
@@ -5,24 +5,26 @@ class Zilla::Versions::V20::Executor
5
5
 
6
6
  attr_reader :scheme, :host
7
7
 
8
- def initialize(scheme, host)
8
+ def initialize(scheme, host, faraday_config_block:)
9
9
  @scheme = scheme
10
10
  @host = host
11
+ @faraday_config_block = faraday_config_block || ->(_, _target) {}
11
12
  end
12
13
 
13
14
  def call(endpoint, *args, **params)
14
- path_parameters = endpoint.path_template.path_parameters(*args, **params)
15
- validate_path_params!(endpoint, path_parameters)
15
+ normalized = endpoint.parameters.normalize!(*args, **params)
16
16
 
17
- path = endpoint.path_template.render(*args, **path_parameters)
18
- connection.public_send(endpoint.method, path)
17
+ path = endpoint.path_template.render(*args, **normalized[:path])
18
+ response = connection.public_send(endpoint.method, path, **normalized[:query])
19
+
20
+ validate_response!(endpoint, response)
19
21
  end
20
22
 
21
23
  private
22
24
 
23
25
  memoize def connection
24
26
  Faraday.new("#{scheme}://#{host}") do |f|
25
- f.adapter :async_http
27
+ @faraday_config_block.call(f, :client)
26
28
  f.response :raise_error
27
29
  end
28
30
  end
@@ -32,4 +34,14 @@ class Zilla::Versions::V20::Executor
32
34
  endpoint.parameters[k].validate!(v)
33
35
  end
34
36
  end
37
+
38
+ def validate_response!(endpoint, response)
39
+ schema = endpoint.responses[response.status.to_s]
40
+ parsed_body = JSON.parse(response.body)
41
+ errors = schema.validate(parsed_body)
42
+
43
+ raise ArgumentError, errors.to_a.to_s if errors.any?
44
+
45
+ parsed_body
46
+ end
35
47
  end
@@ -16,6 +16,9 @@ class Zilla::Versions::V20::Parameter
16
16
  end
17
17
  end
18
18
 
19
+ def in?(location) = json["in"] == location
20
+ def required? = !!@json["required"]
21
+
19
22
  def validate!(value)
20
23
  errors = schema.validate(value)
21
24
 
@@ -4,6 +4,15 @@ class Zilla::Versions::V20::Parameters
4
4
  include Zilla::Versions::V20
5
5
 
6
6
  include Memery
7
+ include Enumerable
8
+
9
+ LOCATIONS = {
10
+ path: "path",
11
+ query: "query",
12
+ body: "body",
13
+ header: "header",
14
+ form_data: "formData"
15
+ }.freeze
7
16
 
8
17
  attr_reader :json, :definitions
9
18
 
@@ -12,13 +21,75 @@ class Zilla::Versions::V20::Parameters
12
21
  @definitions = definitions
13
22
  end
14
23
 
24
+ def normalize!(*args, **params)
25
+ normalized = LOCATIONS.keys.inject({}) do |acc, location|
26
+ acc.merge(location => send("normalize_#{location}_params!", args, params))
27
+ end
28
+ validate!(normalized, params)
29
+ end
30
+
15
31
  memoize def parameters
16
32
  json.map { Parameter.new(_1, definitions:) }
17
33
  .group_by(&:name)
18
- .transform_values(&:first)
34
+ .transform_values do |params|
35
+ raise(ArgumentError, "parameter names must be unique: #{params}") if params.count > 1
36
+
37
+ params.first
38
+ end
39
+ end
40
+
41
+ LOCATIONS.each do |name, key|
42
+ memoize(define_method("#{name}_parameters") do
43
+ parameters.filter { |_k, param| param.in?(key) }
44
+ end)
19
45
  end
20
46
 
21
- def empty? = parameters.empty?
22
47
  def names = parameters.keys
23
48
  def [](name) = parameters[name]
49
+ def each(*, **, &) = parameters.each(*, **, &)
50
+
51
+ private
52
+
53
+ def normalize_path_params!(args, params)
54
+ params = params.transform_keys(&:to_s).slice(*path_parameters.keys)
55
+
56
+ if args.any?
57
+ raise ArgumentError, "path params must be passed EITHER in args OR in params" if params.any?
58
+
59
+ params = normalize_path_args(args)
60
+ end
61
+
62
+ return params if params.count == path_parameters.count
63
+
64
+ raise ArgumentError,
65
+ "there must be exactly #{path_parameters.count} path parameters in params. Given: #{params.count}"
66
+ end
67
+
68
+ def normalize_query_params!(_args, params) = params.transform_keys(&:to_s).slice(*query_parameters.keys)
69
+ def normalize_body_params!(_args, _params) = {}
70
+ def normalize_form_data_params!(_args, _params) = {}
71
+ def normalize_header_params!(_args, _params) = {}
72
+
73
+ def validate!(normalized, params)
74
+ params.each_key do |k|
75
+ raise ArgumentError, "unknown parameter #{k.inspect}" unless parameters[k.to_s]
76
+ end
77
+
78
+ parameters.each_value do |parameter|
79
+ p = normalized.dig(parameter.in.to_sym, parameter.name)
80
+ parameter.validate!(p) if parameter.required? || p
81
+ end
82
+ normalized
83
+ end
84
+
85
+ def normalize_path_args(args)
86
+ if args.count == path_parameters.count
87
+ return path_parameters.each_key.with_index.with_object({}) do |(k, i), acc|
88
+ acc[k] = args[i]
89
+ end
90
+ end
91
+
92
+ raise ArgumentError,
93
+ "there must be exactly #{path_parameters.count} path parameters in args. Given: #{args.count}"
94
+ end
24
95
  end
@@ -5,6 +5,8 @@ class Zilla::Versions::V20::Path
5
5
 
6
6
  include Memery
7
7
 
8
+ VERBS = ["get", "post", "put", "patch", "delete", "head", "options"].freeze
9
+
8
10
  attr_reader :path, :json, :definitions
9
11
 
10
12
  def initialize(path, json, definitions: {})
@@ -14,7 +16,13 @@ class Zilla::Versions::V20::Path
14
16
  end
15
17
 
16
18
  memoize def endpoints
19
+ parameters = json.fetch("parameters", []) # weird kubernetes API definition
20
+
17
21
  json.each_with_object({}) do |(k, v), acc|
22
+ next unless VERBS.include?(k)
23
+
24
+ v = v.merge("parameters" => v.fetch("parameters", []) + parameters)
25
+
18
26
  acc[k] = Endpoint.new(path, k, v, definitions:)
19
27
  end
20
28
  end
@@ -28,7 +28,7 @@ class Zilla::Versions::V20::PathTemplate
28
28
 
29
29
  return validate!(params.transform_keys(&:to_s)) if params.any?
30
30
 
31
- @parameters.keys.each.with_index.with_object({}) do |(k, i), acc|
31
+ @parameters.each_key.with_index.with_object({}) do |(k, i), acc|
32
32
  acc[k] = args[i]
33
33
  end
34
34
  end
data/lib/zilla.rb CHANGED
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "async"
4
- require "async/http/faraday"
5
3
  require "faraday"
6
4
  require "oj"
7
5
  require "zeitwerk"
metadata CHANGED
@@ -1,43 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: zilla
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gleb Sinyavskiy
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-01-29 00:00:00.000000000 Z
11
+ date: 2023-01-30 00:00:00.000000000 Z
12
12
  dependencies:
13
- - !ruby/object:Gem::Dependency
14
- name: async
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - "~>"
18
- - !ruby/object:Gem::Version
19
- version: 2.3.0
20
- type: :runtime
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - "~>"
25
- - !ruby/object:Gem::Version
26
- version: 2.3.0
27
- - !ruby/object:Gem::Dependency
28
- name: async-http-faraday
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - "~>"
32
- - !ruby/object:Gem::Version
33
- version: '0.11'
34
- type: :runtime
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - "~>"
39
- - !ruby/object:Gem::Version
40
- version: '0.11'
41
13
  - !ruby/object:Gem::Dependency
42
14
  name: faraday
43
15
  requirement: !ruby/object:Gem::Requirement