atum 0.5.0
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 +7 -0
- data/.gitignore +16 -0
- data/.rspec +2 -0
- data/.rubocop.yml +9 -0
- data/.rubocop_todo.yml +25 -0
- data/.travis.yml +9 -0
- data/Appraisals +9 -0
- data/CHANGELOG.md +5 -0
- data/CONTRIBUTING.md +9 -0
- data/CONTRIBUTORS.md +15 -0
- data/Gemfile +4 -0
- data/Guardfile +23 -0
- data/LICENSE.txt +22 -0
- data/README.md +95 -0
- data/Rakefile +13 -0
- data/TODO +3 -0
- data/atum.gemspec +37 -0
- data/bin/atum +41 -0
- data/circle.yml +7 -0
- data/gemfiles/faraday_0.8.9.gemfile +8 -0
- data/gemfiles/faraday_0.9.gemfile +8 -0
- data/lib/atum.rb +15 -0
- data/lib/atum/core.rb +13 -0
- data/lib/atum/core/client.rb +45 -0
- data/lib/atum/core/errors.rb +20 -0
- data/lib/atum/core/link.rb +77 -0
- data/lib/atum/core/paginator.rb +32 -0
- data/lib/atum/core/request.rb +55 -0
- data/lib/atum/core/resource.rb +15 -0
- data/lib/atum/core/response.rb +53 -0
- data/lib/atum/core/schema.rb +12 -0
- data/lib/atum/core/schema/api_schema.rb +62 -0
- data/lib/atum/core/schema/link_schema.rb +121 -0
- data/lib/atum/core/schema/parameter.rb +27 -0
- data/lib/atum/core/schema/parameter_choice.rb +28 -0
- data/lib/atum/core/schema/resource_schema.rb +51 -0
- data/lib/atum/generation.rb +15 -0
- data/lib/atum/generation/erb_context.rb +17 -0
- data/lib/atum/generation/errors.rb +6 -0
- data/lib/atum/generation/generator_link.rb +39 -0
- data/lib/atum/generation/generator_resource.rb +31 -0
- data/lib/atum/generation/generator_service.rb +73 -0
- data/lib/atum/generation/generators/base_generator.rb +57 -0
- data/lib/atum/generation/generators/client_generator.rb +16 -0
- data/lib/atum/generation/generators/module_generator.rb +17 -0
- data/lib/atum/generation/generators/resource_generator.rb +23 -0
- data/lib/atum/generation/generators/views/client.erb +26 -0
- data/lib/atum/generation/generators/views/module.erb +104 -0
- data/lib/atum/generation/generators/views/resource.erb +33 -0
- data/lib/atum/generation/options_parameter.rb +12 -0
- data/lib/atum/version.rb +3 -0
- data/spec/atum/core/client_spec.rb +26 -0
- data/spec/atum/core/errors_spec.rb +19 -0
- data/spec/atum/core/link_spec.rb +80 -0
- data/spec/atum/core/paginator_spec.rb +72 -0
- data/spec/atum/core/request_spec.rb +110 -0
- data/spec/atum/core/resource_spec.rb +66 -0
- data/spec/atum/core/response_spec.rb +127 -0
- data/spec/atum/core/schema/api_schema_spec.rb +49 -0
- data/spec/atum/core/schema/link_schema_spec.rb +91 -0
- data/spec/atum/core/schema/parameter_choice_spec.rb +40 -0
- data/spec/atum/core/schema/parameter_spec.rb +24 -0
- data/spec/atum/core/schema/resource_schema_spec.rb +24 -0
- data/spec/atum/generation/generator_link_spec.rb +62 -0
- data/spec/atum/generation/generator_resource_spec.rb +44 -0
- data/spec/atum/generation/generator_service_spec.rb +41 -0
- data/spec/atum/generation/generators/base_generator_spec.rb +75 -0
- data/spec/atum/generation/generators/client_generator_spec.rb +30 -0
- data/spec/atum/generation/generators/module_generator_spec.rb +37 -0
- data/spec/atum/generation/generators/resource_generator_spec.rb +46 -0
- data/spec/atum/generation/options_parameter_spec.rb +27 -0
- data/spec/fixtures/fruity_schema.json +161 -0
- data/spec/fixtures/sample_schema.json +139 -0
- data/spec/integration/client_integration_spec.rb +91 -0
- data/spec/spec_helper.rb +11 -0
- metadata +303 -0
@@ -0,0 +1,27 @@
|
|
1
|
+
module Atum
|
2
|
+
module Core
|
3
|
+
module Schema
|
4
|
+
class Parameter
|
5
|
+
attr_reader :resource_name
|
6
|
+
|
7
|
+
def initialize(resource_name, name, description)
|
8
|
+
@resource_name = resource_name
|
9
|
+
@name = name
|
10
|
+
@description = description
|
11
|
+
end
|
12
|
+
|
13
|
+
def name
|
14
|
+
[@resource_name, @name].compact.join('_')
|
15
|
+
end
|
16
|
+
|
17
|
+
def description
|
18
|
+
@description || ''
|
19
|
+
end
|
20
|
+
|
21
|
+
def inspect
|
22
|
+
"Parameter(name=#{name}, description=#{description})"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Atum
|
2
|
+
module Core
|
3
|
+
module Schema
|
4
|
+
class ParameterChoice
|
5
|
+
attr_reader :resource_name, :parameters
|
6
|
+
|
7
|
+
def initialize(resource_name, parameters)
|
8
|
+
@resource_name = resource_name
|
9
|
+
@parameters = parameters
|
10
|
+
end
|
11
|
+
|
12
|
+
def description
|
13
|
+
@parameters.map(&:description).join(' or ')
|
14
|
+
end
|
15
|
+
|
16
|
+
def name
|
17
|
+
@parameters.map do |parameter|
|
18
|
+
if parameter.resource_name
|
19
|
+
parameter.name
|
20
|
+
else
|
21
|
+
"#{@resource_name}_#{parameter.name}"
|
22
|
+
end
|
23
|
+
end.join('_or_')
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module Atum
|
2
|
+
module Core
|
3
|
+
module Schema
|
4
|
+
class ResourceSchema
|
5
|
+
attr_reader :name
|
6
|
+
|
7
|
+
# Instantiate a resource schema.
|
8
|
+
#
|
9
|
+
# @param schema [ApiSchema] The whole document's schema
|
10
|
+
# @param name [String] The name of the resource to identify in the schema.
|
11
|
+
def initialize(schema, definition, name)
|
12
|
+
@schema = schema
|
13
|
+
@name = name
|
14
|
+
@definition = definition
|
15
|
+
end
|
16
|
+
|
17
|
+
%w(description definitions properties).each do |key|
|
18
|
+
define_method(key) { @definition[key] }
|
19
|
+
end
|
20
|
+
|
21
|
+
# Get a schema for a named link.
|
22
|
+
#
|
23
|
+
# @param name [String] The name of the link.
|
24
|
+
# @raise [SchemaError] Raised if an unknown link name is provided.
|
25
|
+
def link_schema_for(name)
|
26
|
+
link_schema = link_schema_hash[name]
|
27
|
+
raise SchemaError, "Unknown link '#{name}'." unless link_schema
|
28
|
+
link_schema
|
29
|
+
end
|
30
|
+
|
31
|
+
# The link schema children that are part of this resource schema.
|
32
|
+
#
|
33
|
+
# @return [Array<LinkSchema>] The link schema children.
|
34
|
+
def link_schemas
|
35
|
+
link_schema_hash.values
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def link_schema_hash
|
41
|
+
@link_schema_hash ||= Hash[
|
42
|
+
@definition['links'].map do |link|
|
43
|
+
[link['title'].downcase.gsub(' ', '_'),
|
44
|
+
LinkSchema.new(@schema, self, link)]
|
45
|
+
end
|
46
|
+
]
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Atum
|
2
|
+
module Generation
|
3
|
+
end
|
4
|
+
end
|
5
|
+
|
6
|
+
require 'atum/generation/errors'
|
7
|
+
require 'atum/generation/erb_context'
|
8
|
+
require 'atum/generation/options_parameter'
|
9
|
+
require 'atum/generation/generator_link'
|
10
|
+
require 'atum/generation/generator_resource'
|
11
|
+
require 'atum/generation/generator_service'
|
12
|
+
require 'atum/generation/generators/base_generator'
|
13
|
+
require 'atum/generation/generators/module_generator'
|
14
|
+
require 'atum/generation/generators/client_generator'
|
15
|
+
require 'atum/generation/generators/resource_generator'
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Atum
|
2
|
+
module Generation
|
3
|
+
class ErbContext < Erubis::Context
|
4
|
+
def commentify(comment, tabs)
|
5
|
+
starter = (' ' * tabs) + '# '
|
6
|
+
max_line_length = 78 - (tabs * 2)
|
7
|
+
comment.split("\n")
|
8
|
+
.map { |l| l.scan(/.{1,#{max_line_length}}/) }
|
9
|
+
.flatten.map { |l| starter + l.strip }.join("\n")
|
10
|
+
end
|
11
|
+
|
12
|
+
def method(name, params)
|
13
|
+
"#{name}" + (params.length > 0 ? "(#{params})" : '')
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Atum
|
2
|
+
module Generation
|
3
|
+
class GeneratorLink
|
4
|
+
def initialize(link_schema)
|
5
|
+
@link_schema = link_schema
|
6
|
+
end
|
7
|
+
|
8
|
+
def name
|
9
|
+
@link_schema.name
|
10
|
+
end
|
11
|
+
|
12
|
+
def description
|
13
|
+
@link_schema.description
|
14
|
+
end
|
15
|
+
|
16
|
+
def parameters
|
17
|
+
@parameters ||= begin
|
18
|
+
params = @link_schema.parameters
|
19
|
+
params << OptionsParameter.new
|
20
|
+
params
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# The list of parameters to render in generated source code for the method
|
25
|
+
# signature for the link.
|
26
|
+
def parameter_names_with_defaults
|
27
|
+
parameters.map do |param|
|
28
|
+
s = param.name
|
29
|
+
s += " = #{param.default}" if param.respond_to?(:default)
|
30
|
+
s
|
31
|
+
end.join(', ')
|
32
|
+
end
|
33
|
+
|
34
|
+
def parameter_names
|
35
|
+
parameters.map(&:name).join(', ')
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Atum
|
2
|
+
module Generation
|
3
|
+
class GeneratorResource
|
4
|
+
def initialize(resource_schema)
|
5
|
+
@resource_schema = resource_schema
|
6
|
+
end
|
7
|
+
|
8
|
+
# The name of the resource, in snake case.
|
9
|
+
def name
|
10
|
+
@resource_schema.name.gsub('-', '_')
|
11
|
+
end
|
12
|
+
|
13
|
+
# Description of the resource.
|
14
|
+
def description
|
15
|
+
@resource_schema.description
|
16
|
+
end
|
17
|
+
|
18
|
+
# Links available on this resource.
|
19
|
+
def links
|
20
|
+
@links ||= @resource_schema.link_schemas.map do |link_schema|
|
21
|
+
GeneratorLink.new(link_schema)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# The name of the resource class in generated code.
|
26
|
+
def class_name
|
27
|
+
name.camelcase
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
module Atum
|
4
|
+
module Generation
|
5
|
+
class GeneratorService
|
6
|
+
def initialize(module_name, schema_file, url, options)
|
7
|
+
@module_name = module_name
|
8
|
+
@schema = schema_from_file(schema_file)
|
9
|
+
@url = url
|
10
|
+
@options = options
|
11
|
+
end
|
12
|
+
|
13
|
+
def generate_files
|
14
|
+
generate_namespace_folder
|
15
|
+
generated_files.each do |gf|
|
16
|
+
File.open("#{gf.path}.rb", 'w') do |f|
|
17
|
+
f.write(gf.generator.generate)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def schema_from_file(file)
|
25
|
+
Atum::Core::Schema::ApiSchema.new(JSON.parse(File.read(file)))
|
26
|
+
end
|
27
|
+
|
28
|
+
def generate_namespace_folder
|
29
|
+
FileUtils.mkdir_p namespace_path
|
30
|
+
FileUtils.mkdir_p File.join(namespace_path, 'resources')
|
31
|
+
end
|
32
|
+
|
33
|
+
def resources
|
34
|
+
@schema.resource_schemas.map { |r| GeneratorResource.new(r) }
|
35
|
+
end
|
36
|
+
|
37
|
+
def generated_files
|
38
|
+
files = []
|
39
|
+
|
40
|
+
files << GeneratedFile.new(namespace_path,
|
41
|
+
Generators::ModuleGenerator.new(*generator_args))
|
42
|
+
|
43
|
+
files << GeneratedFile.new(File.join(namespace_path, 'client'),
|
44
|
+
Generators::ClientGenerator.new(*generator_args))
|
45
|
+
|
46
|
+
resources.each do |resource|
|
47
|
+
files << GeneratedFile.new(
|
48
|
+
File.join(namespace_path, 'resources', resource.name.underscore),
|
49
|
+
Generators::ResourceGenerator.new(resource, *generator_args))
|
50
|
+
end
|
51
|
+
|
52
|
+
files
|
53
|
+
end
|
54
|
+
|
55
|
+
def namespace
|
56
|
+
@module_name.downcase.underscore
|
57
|
+
end
|
58
|
+
|
59
|
+
def namespace_path
|
60
|
+
s = []
|
61
|
+
s << @options[:path] if @options.key?(:path)
|
62
|
+
s << namespace
|
63
|
+
File.join(*s)
|
64
|
+
end
|
65
|
+
|
66
|
+
def generator_args
|
67
|
+
[@module_name, @schema, @url, @options]
|
68
|
+
end
|
69
|
+
|
70
|
+
class GeneratedFile < Struct.new(:path, :generator); end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module Atum
|
2
|
+
module Generation
|
3
|
+
module Generators
|
4
|
+
class BaseGenerator
|
5
|
+
TEMPLATE_NAME = nil
|
6
|
+
|
7
|
+
# Generate a static client that uses Atum under the hood. This is a good
|
8
|
+
# option if you want to ship a gem or generate API documentation using Yard.
|
9
|
+
#
|
10
|
+
# @param module_name [String] The name of the module, as rendered in a Ruby
|
11
|
+
# source file, to use for the generated client.
|
12
|
+
# @param schema [Schema] The schema instance to generate the client from.
|
13
|
+
# @param url [String] The URL for the API service.
|
14
|
+
# @param options [Hash] Configuration for links. Possible keys include:
|
15
|
+
# - default_headers: Optionally, a set of headers to include in every
|
16
|
+
# request made by the client. Default is no custom headers.
|
17
|
+
def initialize(module_name, schema, url, options)
|
18
|
+
@module_name = module_name
|
19
|
+
@schema = schema
|
20
|
+
@url = url
|
21
|
+
@options = options
|
22
|
+
end
|
23
|
+
|
24
|
+
def context
|
25
|
+
ErbContext.new(context_hash.merge(module_name: @module_name))
|
26
|
+
end
|
27
|
+
|
28
|
+
def context_hash
|
29
|
+
raise NotImplementedError, 'Subclasses must define context_hash'
|
30
|
+
end
|
31
|
+
|
32
|
+
def template
|
33
|
+
@template ||= Erubis::Eruby.new(File.read(template_path))
|
34
|
+
end
|
35
|
+
|
36
|
+
def generate
|
37
|
+
template.evaluate(context)
|
38
|
+
end
|
39
|
+
|
40
|
+
def resources
|
41
|
+
@schema.resource_schemas.map { |r| GeneratorResource.new(r) }
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def template_path
|
47
|
+
File.expand_path(File.join(File.dirname(__FILE__), 'views',
|
48
|
+
"#{template_name}.erb"))
|
49
|
+
end
|
50
|
+
|
51
|
+
def template_name
|
52
|
+
raise NotImplementedError, 'Subclasses must define template_name'
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Atum
|
2
|
+
module Generation
|
3
|
+
module Generators
|
4
|
+
class ClientGenerator < BaseGenerator
|
5
|
+
def context_hash
|
6
|
+
{ description: @schema.description,
|
7
|
+
resources: resources }
|
8
|
+
end
|
9
|
+
|
10
|
+
def template_name
|
11
|
+
'client'
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Atum
|
2
|
+
module Generation
|
3
|
+
module Generators
|
4
|
+
class ModuleGenerator < BaseGenerator
|
5
|
+
def context_hash
|
6
|
+
{ default_headers: @options.fetch(:default_headers, {}),
|
7
|
+
schema: JSON.dump(@schema.schema),
|
8
|
+
resources: resources }
|
9
|
+
end
|
10
|
+
|
11
|
+
def template_name
|
12
|
+
'module'
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Atum
|
2
|
+
module Generation
|
3
|
+
module Generators
|
4
|
+
class ResourceGenerator < BaseGenerator
|
5
|
+
def initialize(resource, *args)
|
6
|
+
super(*args)
|
7
|
+
@resource = resource
|
8
|
+
end
|
9
|
+
|
10
|
+
def context_hash
|
11
|
+
{ description: @resource.description,
|
12
|
+
class_name: @resource.class_name,
|
13
|
+
links: @resource.links,
|
14
|
+
resource_name: @resource.name }
|
15
|
+
end
|
16
|
+
|
17
|
+
def template_name
|
18
|
+
'resource'
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#
|
3
|
+
# WARNING: Do not edit by hand, this file was generated by Atum:
|
4
|
+
#
|
5
|
+
# https://github.com/gocardless/atum
|
6
|
+
#
|
7
|
+
require 'atum'
|
8
|
+
require 'uri'
|
9
|
+
|
10
|
+
module <%= @module_name %>
|
11
|
+
<%= commentify(@description, 1) %>
|
12
|
+
class Client
|
13
|
+
def initialize(client)
|
14
|
+
@client = client
|
15
|
+
end
|
16
|
+
<% @resources.each do |resource| %>
|
17
|
+
|
18
|
+
<%= commentify(resource.description, 2) %>
|
19
|
+
#
|
20
|
+
<%= commentify("@return [" +resource.class_name + "]", 2) %>
|
21
|
+
def <%= resource.name %>
|
22
|
+
@<%= resource.name %>_resource ||= <%= resource.class_name %>.new(@client)
|
23
|
+
end
|
24
|
+
<% end %>
|
25
|
+
end
|
26
|
+
end
|