api_def 1.0.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 2cf0a8c51de632e9b5a12ad9aa40733cbf39c0f7
4
+ data.tar.gz: 74351fd28942fc015d13048ae8e9343b749db347
5
+ SHA512:
6
+ metadata.gz: 3419a50a596b5e0d68461a82f8451a82880e48877b692c1dd253b294b42ab5972190b4686bd2ded9002018116daa8140900a64f173b77749732efa6403b9da0a
7
+ data.tar.gz: 3399a162a124f985c2acce996f55e253520f060ec672178ecceb5561a3624c4bfd98ec4c08196360d5422e6dd60ae9857287150ef664e9f9c7554cf128f85c91
data/bin/api_def ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ #TODO: remove after development finished
4
+ $LOAD_PATH << File.expand_path('../../lib', __FILE__)
5
+
6
+ require 'api_def'
7
+
8
+ ApiDef::CLI.start(ARGV)
@@ -0,0 +1,33 @@
1
+ require 'thor'
2
+
3
+ class ApiDef::CLI < Thor
4
+ desc "build FILE", "build API specification for FILE"
5
+ option :template, {
6
+ aliases: '-t',
7
+ default: 'markdown',
8
+ required: true,
9
+ type: :string,
10
+ enum: ['markdown', 'html'],
11
+ desc: 'Output template'
12
+ }
13
+ def build(file)
14
+ spec = load_spec file
15
+ tpl = ApiDef::Template.find(options[:template]).new
16
+ STDOUT.write tpl.render(spec)
17
+ end
18
+
19
+ desc "mock FILE", "start a mock server for FILE"
20
+ def mock(file)
21
+ spec = load_spec file
22
+ app = ApiDef::Mock.create_application spec
23
+ app.run!
24
+ end
25
+
26
+ private
27
+ def load_spec(file)
28
+ content = File.open(file).read.to_s
29
+ spec = ApiDef::Specification.new
30
+ spec.instance_eval content, file
31
+ end
32
+
33
+ end
@@ -0,0 +1,17 @@
1
+ class ApiDef::Element
2
+ include ApiDef::Support::AttrUno
3
+ include ApiDef::Support::AttrArray
4
+ include ApiDef::Support::AttrUnoArray
5
+
6
+ attr_uno :name, :desc
7
+
8
+ def initialize(name = nil, options = {})
9
+ self.name name
10
+ self.on_options(options)
11
+ yield self if block_given?
12
+ end
13
+
14
+ def on_options(options)
15
+ self.desc options[:desc]
16
+ end
17
+ end
@@ -0,0 +1,7 @@
1
+ # ApiDef::Entry means a entry of api
2
+ class ApiDef::Entry < ApiDef::Element
3
+ attr_uno :method, :path
4
+
5
+ attr_uno_array :request, class: 'ApiDef::Request'
6
+ attr_uno_array :response,class: 'ApiDef::Response'
7
+ end
@@ -0,0 +1,4 @@
1
+ # ApiDef::Group means a group of api entries
2
+ class ApiDef::Group < ApiDef::Element
3
+ attr_uno_array :entry, store: :entries, class: 'ApiDef::Entry'
4
+ end
@@ -0,0 +1,32 @@
1
+ require 'sinatra/base'
2
+
3
+ class ApiDef::Mock
4
+
5
+ def self.create_application(spec)
6
+ Class.new(Sinatra::Base) do
7
+ configure do
8
+ set :public_folder, File.expand_path("../../public", __FILE__)
9
+ disable :protection
10
+ settings.add_charset << "application/json"
11
+ end
12
+ before do
13
+ content_type :json
14
+ end
15
+ # root for description
16
+ get "/" do
17
+ content_type :html
18
+ tpl = ApiDef::Template::Html.new
19
+ tpl.render spec
20
+ end
21
+ # entries
22
+ spec.groups.each do |group|
23
+ group.entries.each do |entry|
24
+ self.send(entry.method.to_sym, entry.path) do
25
+ JSON.pretty_generate(entry.responses.sample.body)
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+
32
+ end
@@ -0,0 +1,9 @@
1
+ class ApiDef::Parameter < ApiDef::Element
2
+ attr_uno :optional, :type
3
+
4
+ def on_options(options)
5
+ super
6
+ self.optional options[:optional]
7
+ self.type options[:type]
8
+ end
9
+ end
@@ -0,0 +1,4 @@
1
+ # ApiDef::Request means a request made to a api entry
2
+ class ApiDef::Request < ApiDef::Element
3
+ attr_uno_array :param, class: 'ApiDef::Parameter'
4
+ end
@@ -0,0 +1,13 @@
1
+ require 'jbuilder'
2
+
3
+ # ApiDef::Response means a response api returned
4
+ class ApiDef::Response < ApiDef::Element
5
+
6
+ def body(&block)
7
+ if block
8
+ @body = Jbuilder.new(&block).attributes!
9
+ else
10
+ @body
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,5 @@
1
+ class ApiDef::Specification < ApiDef::Element
2
+ attr_uno :version
3
+ attr_uno_array :group, class: 'ApiDef::Group'
4
+ attr_uno_array :element, class: 'ApiDef::Element'
5
+ end
@@ -0,0 +1,22 @@
1
+ module ApiDef::Support::AttrArray
2
+
3
+ def self.included(mod)
4
+
5
+ mod.class_eval do
6
+
7
+ # Create method +name+ with +@name+ for array storage
8
+ def self.attr_array(*names)
9
+ names.flatten.each do |name|
10
+ self.class_eval <<-EOF
11
+ def #{name}
12
+ @#{name} ||= []
13
+ end
14
+ EOF
15
+ end
16
+ end
17
+
18
+ end
19
+
20
+ end
21
+
22
+ end
@@ -0,0 +1,26 @@
1
+ module ApiDef::Support::AttrUno
2
+
3
+ def self.included(mod)
4
+
5
+ mod.class_eval do
6
+
7
+ # Create method +name+ with +name(value)+ for setter and +name+ for getter
8
+ def self.attr_uno(*names)
9
+ names.flatten.each do |name|
10
+ self.class_eval <<-EOF
11
+ def #{name}(value = nil)
12
+ if value
13
+ @#{name} = value
14
+ else
15
+ @#{name}
16
+ end
17
+ end
18
+ EOF
19
+ end
20
+ end
21
+
22
+ end
23
+
24
+ end
25
+
26
+ end
@@ -0,0 +1,29 @@
1
+ module ApiDef::Support::AttrUnoArray
2
+
3
+ def self.included(mod)
4
+
5
+ mod.class_eval do
6
+
7
+ def self.attr_uno_array(name, opts)
8
+ clazz = opts[:class]
9
+ raise "Please specify a class" unless clazz
10
+ store = opts[:store] || (name.to_s + "s")
11
+
12
+ self.attr_array store
13
+ self.class_eval <<-EOF
14
+
15
+ def #{name}(value = nil, opts = {})
16
+ obj = #{clazz}.new(value, opts)
17
+ yield obj if block_given?
18
+ self.#{store} << obj
19
+ self
20
+ end
21
+
22
+ EOF
23
+ end
24
+
25
+ end
26
+
27
+ end
28
+
29
+ end
@@ -0,0 +1,37 @@
1
+ require 'redcarpet'
2
+
3
+ class ApiDef::Template::Html < ApiDef::Template
4
+
5
+ def render(spec)
6
+ tpl = ApiDef::Template::Markdown.new
7
+ md = tpl.render(spec)
8
+ content = Redcarpet::Markdown.new(Redcarpet::Render::HTML,
9
+ :autolink => true,
10
+ :space_after_headers => true,
11
+ :fenced_code_blocks => true
12
+ ).render(md)
13
+ %{
14
+ <!doctype html>
15
+ <html>
16
+ <head>
17
+ <meta name="content-type" content="text/html;charset=utf-8">
18
+ <meta name="viewport" content="width=device-width, initial-scale=1, minimal-ui">
19
+ <title>#{spec.name}</title>
20
+ <style>
21
+ body {
22
+ min-width: 200px;
23
+ max-width: 790px;
24
+ margin: 0 auto;
25
+ padding: 30px;
26
+ }
27
+ </style>
28
+ </head>
29
+ <body>
30
+ <article class="markdown-body">
31
+ #{content}
32
+ </article>
33
+ </body>
34
+ </html>
35
+ }
36
+ end
37
+ end
@@ -0,0 +1,64 @@
1
+ require 'erb'
2
+ require 'json'
3
+
4
+ class ApiDef::Template::Markdown < ApiDef::Template
5
+ TEMPLATE_FILE= %{
6
+ # <%= spec.name %>
7
+ # <%= spec.version %>
8
+
9
+ <% spec.elements.each do |ele| -%>
10
+ ## <%= ele.name %>
11
+
12
+ <%= ele.desc %>
13
+ <% end -%>
14
+
15
+ <% spec.groups.each do |group| -%>
16
+ ## <%= group.name %>
17
+
18
+ <%= group.desc %>
19
+ <% group.entries.each do |entry| %>
20
+ ### <%= entry.name %>
21
+
22
+ <%= entry.desc %>
23
+
24
+ #### `<%= entry.path %>` [<%= entry.method.to_s.upcase %>]
25
+ <% entry.requests.each do |request| -%>
26
+
27
+ ##### Request <%= request.name %>
28
+
29
+ <%= request.desc %>
30
+
31
+ <% request.params.each do |param| -%>
32
+ + `<%= param.name %>`, <%= param.type %>, <%="Optional, " if param.optional%><%= param.desc %>
33
+ <% end -%>
34
+
35
+ <% end -%>
36
+
37
+ <% entry.responses.each do |response| -%>
38
+
39
+ ##### Response <%= response.name %>
40
+
41
+ <%= response.desc %>
42
+
43
+ ```json
44
+ <%= JSON.pretty_generate(response.body) %>
45
+ ```
46
+ <% end -%>
47
+ <% end -%>
48
+ <% end -%>
49
+ }
50
+
51
+ def render(_spec)
52
+ clazz = ::ERB.new(TEMPLATE_FILE, nil, "-").def_class
53
+ clazz.class_eval do
54
+ def initialize(_spec)
55
+ @spec = _spec
56
+ end
57
+
58
+ def spec
59
+ @spec
60
+ end
61
+ end
62
+ clazz.new(_spec).result
63
+ end
64
+ end
@@ -0,0 +1,17 @@
1
+ class ApiDef::Template
2
+ autoload :Markdown, 'api_def/template/markdown'
3
+ autoload :Html, 'api_def/template/html'
4
+
5
+ def self.find(name)
6
+ case name.to_s
7
+ when 'html'
8
+ ApiDef::Template::Html
9
+ when 'markdown'
10
+ ApiDef::Template::Markdown
11
+ end
12
+ end
13
+
14
+ def render(spec)
15
+ raise "Implementation required"
16
+ end
17
+ end
data/lib/api_def.rb ADDED
@@ -0,0 +1,28 @@
1
+ module ApiDef
2
+ VERSION="1.0.0"
3
+ # CLI
4
+ autoload :CLI, 'api_def/cli'
5
+ autoload :Template, 'api_def/template'
6
+
7
+ # Specification and DSL
8
+ autoload :Specification, 'api_def/specification'
9
+
10
+ # ApiDef models
11
+ autoload :Element, 'api_def/element'
12
+
13
+ autoload :Group, 'api_def/group'
14
+ autoload :Entry, 'api_def/entry'
15
+ autoload :Request, 'api_def/request'
16
+ autoload :Parameter,'api_def/parameter'
17
+ autoload :Response, 'api_def/response'
18
+
19
+ # Mock Server
20
+ autoload :Mock, 'api_def/mock'
21
+
22
+ # Supports
23
+ module Support
24
+ autoload :AttrUno, 'api_def/support/attr_uno'
25
+ autoload :AttrUnoArray, 'api_def/support/attr_uno_array'
26
+ autoload :AttrArray, 'api_def/support/attr_array'
27
+ end
28
+ end
metadata ADDED
@@ -0,0 +1,117 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: api_def
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - YANKE Guo
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-07-21 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: thor
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '0.19'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '0.19'
27
+ - !ruby/object:Gem::Dependency
28
+ name: jbuilder
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: 2.3.1
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: 2.3.1
41
+ - !ruby/object:Gem::Dependency
42
+ name: sinatra
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ~>
46
+ - !ruby/object:Gem::Version
47
+ version: 1.4.6
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: 1.4.6
55
+ - !ruby/object:Gem::Dependency
56
+ name: redcarpet
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: 3.3.2
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ~>
67
+ - !ruby/object:Gem::Version
68
+ version: 3.3.2
69
+ description: Ruby DSL based API definition tool.
70
+ email: me@yanke.io
71
+ executables:
72
+ - api_def
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - lib/api_def/cli.rb
77
+ - lib/api_def/element.rb
78
+ - lib/api_def/entry.rb
79
+ - lib/api_def/group.rb
80
+ - lib/api_def/mock.rb
81
+ - lib/api_def/parameter.rb
82
+ - lib/api_def/request.rb
83
+ - lib/api_def/response.rb
84
+ - lib/api_def/specification.rb
85
+ - lib/api_def/support/attr_array.rb
86
+ - lib/api_def/support/attr_uno.rb
87
+ - lib/api_def/support/attr_uno_array.rb
88
+ - lib/api_def/template/html.rb
89
+ - lib/api_def/template/markdown.rb
90
+ - lib/api_def/template.rb
91
+ - lib/api_def.rb
92
+ - bin/api_def
93
+ homepage: http://rubygems.org/gems/api_def
94
+ licenses:
95
+ - MIT
96
+ metadata: {}
97
+ post_install_message:
98
+ rdoc_options: []
99
+ require_paths:
100
+ - lib
101
+ required_ruby_version: !ruby/object:Gem::Requirement
102
+ requirements:
103
+ - - '>='
104
+ - !ruby/object:Gem::Version
105
+ version: '0'
106
+ required_rubygems_version: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - '>='
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ requirements: []
112
+ rubyforge_project:
113
+ rubygems_version: 2.0.14
114
+ signing_key:
115
+ specification_version: 4
116
+ summary: API definition tool
117
+ test_files: []