chaplin 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 913d6d26f30963578fc07305f2a8c3165fcc54c5
4
+ data.tar.gz: 9651466b98f18f4ad9d9c746304f5f834a2598a1
5
+ SHA512:
6
+ metadata.gz: 7748940639a04dd6cb00fc53fbf61646a69ff71fb7c72617ce831b1aa0b777342b0f7f1e164626498a3c44f61e8b046edbbf273946014f29ad49a6c104a68ce7
7
+ data.tar.gz: 387add2e988ad1800459294ce1acaf4d20da74dcab09199ba5b061945679ffa4f47f82121f468b8febb22957e81d29a0ed2bbe3d4f3b8df5c98c4744f7ee8878
data/bin/chaplin ADDED
@@ -0,0 +1,23 @@
1
+ #!/usr/bin/env ruby
2
+ require "rack"
3
+ require_relative '../lib/chaplin'
4
+
5
+ if ARGV[0].nil?
6
+ puts "usage:"
7
+ puts "$ chaplin my_chaplin_project_directory_name"
8
+ puts "or"
9
+ puts "$ chaplin new my_chaplin_project_directory_name"
10
+ elsif ARGV[0] == 'new'
11
+ new_project_path = ARGV[1]
12
+
13
+ FileUtils.mkdir(new_project_path)
14
+ FileUtils.cp_r("#{__dir__}/../sample_project/.", new_project_path)
15
+
16
+ puts "New chaplin project created in #{new_project_path}"
17
+ puts "Start the server with '$ chaplin #{new_project_path}'"
18
+ else
19
+ project_directory = ARGV[0]
20
+ chaplin_server = Chaplin.new(project_directory).server
21
+
22
+ Rack::Server.start(app: chaplin_server, Port: 8081)
23
+ end
@@ -0,0 +1,69 @@
1
+ require 'json'
2
+
3
+ require 'faraday'
4
+ require 'mustache'
5
+
6
+ require_relative 'endpoint'
7
+
8
+ class Chaplin
9
+ ApiEndpoint = Struct.new(:http_method, :path, :params, :headers) do
10
+
11
+ def initialize(http_method, path, params, headers = {})
12
+ super(http_method, path, params || {}, headers)
13
+ end
14
+
15
+ def self.configure(api_url, default_headers, basic_auth)
16
+ @@client = Faraday.new(url: api_url) do |client|
17
+ client.adapter Faraday.default_adapter
18
+ if basic_auth
19
+ client.basic_auth(basic_auth['user'], basic_auth['password'])
20
+ end
21
+ end
22
+ @@default_headers = default_headers || {}
23
+ end
24
+
25
+ def render(request_params)
26
+ response_body = api_response(request_params).body
27
+ return nil if (response_body == 'null' or response_body == '')
28
+ JSON.parse(response_body)
29
+ end
30
+
31
+ private
32
+
33
+ def api_response(request_params)
34
+ @@client.send(
35
+ http_method,
36
+ parsed_path(request_params),
37
+ api_request_params(request_params),
38
+ @@default_headers
39
+ )
40
+ end
41
+
42
+ def api_request_params(chaplin_request_params)
43
+ if json_request? && [:post, :put, :patch].include?(http_method)
44
+ Mustache.render(params.to_json, chaplin_request_params)
45
+ else
46
+ rendered_params(chaplin_request_params)
47
+ end
48
+ end
49
+
50
+ def json_request?
51
+ request_headers['Content-Type'] == 'application/json'
52
+ end
53
+
54
+ def request_headers
55
+ @@default_headers.merge(headers)
56
+ end
57
+
58
+ def rendered_params(request_params)
59
+ params.each_with_object({}) do |(key, value), rendered_params|
60
+ rendered_params[key] = Mustache.render(value, request_params)
61
+ end
62
+ end
63
+
64
+ def parsed_path(request_params)
65
+ Mustache.render(path, request_params)
66
+ end
67
+ end
68
+ end
69
+
@@ -0,0 +1 @@
1
+ Endpoint = Struct.new(:http_method, :path)
@@ -0,0 +1,46 @@
1
+ require_relative '../api_endpoint'
2
+
3
+ class Chaplin
4
+
5
+ module Parser
6
+
7
+ class ApiEndpoints
8
+
9
+ def self.build(api_endpoint_declaration)
10
+ new(api_endpoint_declaration).build
11
+ end
12
+
13
+ def initialize(api_endpoint_declaration)
14
+ @api_endpoint_declaration = [api_endpoint_declaration].flatten
15
+ end
16
+
17
+ def build
18
+ ApiEndpoint.new(http_method, path, params, headers)
19
+ end
20
+
21
+ private
22
+
23
+ def http_method
24
+ api_route.first.downcase.to_sym
25
+ end
26
+
27
+ def path
28
+ api_route.last
29
+ end
30
+
31
+ def api_route
32
+ @api_endpoint_declaration.first.split(" ")
33
+ end
34
+
35
+ def params
36
+ @api_endpoint_declaration[1] || {}
37
+ end
38
+
39
+ def headers
40
+ @api_endpoint_declaration[2] || {}
41
+ end
42
+
43
+ end
44
+ end
45
+ end
46
+
@@ -0,0 +1,50 @@
1
+ require 'json'
2
+
3
+ class Chaplin
4
+ module Parser
5
+
6
+ Config = Struct.new(:project_path) do
7
+
8
+ DEFAULT_API_URL = "http://localhost:8080"
9
+
10
+ def api_url
11
+ config['api_url'] || DEFAULT_API_URL
12
+ end
13
+
14
+ def default_headers
15
+ config['headers']
16
+ end
17
+
18
+ def basic_auth
19
+ config['basic_auth']
20
+ end
21
+
22
+ private
23
+
24
+ def config
25
+ @config ||= load_yaml || load_json || {}
26
+ end
27
+
28
+ def load_yaml
29
+ if File.exists?(yaml_filename)
30
+ YAML.load_file(yaml_filename)
31
+ end
32
+ end
33
+
34
+ def yaml_filename
35
+ "#{project_path}/chaplin_config.yml"
36
+ end
37
+
38
+ def load_json
39
+ if File.exists?(json_filename)
40
+ JSON.load(File.open(json_filename))
41
+ end
42
+ end
43
+
44
+ def json_filename
45
+ "#{project_path}/chaplin_config.json"
46
+ end
47
+
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,45 @@
1
+ require 'pathname'
2
+ require 'json'
3
+ require 'yaml'
4
+
5
+ class Chaplin
6
+ module Parser
7
+ DeclarationFile = Struct.new(:project_path) do
8
+
9
+ def self.app_declaration(project_path)
10
+ new(project_path).app_declaration
11
+ end
12
+
13
+ def app_declaration
14
+ load_json || load_yaml || no_file_found
15
+ end
16
+
17
+ private
18
+
19
+ def load_json
20
+ if File.exists?(json_filename)
21
+ JSON.load(File.open(json_filename))
22
+ end
23
+ end
24
+
25
+ def json_filename
26
+ project_path + "/routes.json"
27
+ end
28
+
29
+ def load_yaml
30
+ if File.exists?(yml_filename)
31
+ YAML.load_file(yml_filename)
32
+ end
33
+ end
34
+
35
+ def yml_filename
36
+ project_path + "/app.yml"
37
+ end
38
+
39
+ def no_file_found
40
+ raise "Could not find #{yml_filename} or #{json_filename}"
41
+ end
42
+
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,76 @@
1
+ require_relative '../responses/page'
2
+ require_relative 'api_endpoints'
3
+
4
+ class Chaplin
5
+ module Parser
6
+
7
+ Pages = Struct.new(:pages_data, :project_path, :layout_name) do
8
+
9
+ def self.load(pages_data, project_path, layout_name = nil)
10
+ new(pages_data, project_path, layout_name).tap do |pages|
11
+ pages.load
12
+ end
13
+ end
14
+
15
+ def load
16
+ @pages = {}
17
+
18
+ pages_data.each do |template_name, raw_data_hash|
19
+ @pages[template_name] = build_page(template_name, raw_data_hash)
20
+ end
21
+
22
+ return unless layout_name
23
+ @pages = @pages.each_with_object({}) do |(page_name, page), pages_in_layout|
24
+ pages_in_layout[page_name] = embed_in_layout(page)
25
+ end
26
+ end
27
+
28
+ def [](page_name)
29
+ @pages[page_name] || build_templated_page(page_name)
30
+ end
31
+
32
+ private
33
+
34
+ def embed_in_layout(page)
35
+ Responses::Page.new(layout_path, { content: page })
36
+ end
37
+
38
+ def build_page(template_name, raw_data_hash)
39
+ Responses::Page.new(template_path(template_name), data_hash(raw_data_hash))
40
+ end
41
+
42
+ def build_templated_page(page_name, raw_data_hash: {})
43
+ page = build_page(page_name, raw_data_hash)
44
+ layout_name ? embed_in_layout(page) : page
45
+ end
46
+
47
+ def template_path(template_name)
48
+ project_path + '/templates/' + template_name
49
+ end
50
+
51
+ def layout_path
52
+ @layout_path ||= template_path(layout_name)
53
+ end
54
+
55
+ def data_hash(raw_data_hash)
56
+ raw_data_hash.each_with_object({}) do |(key, raw_data_value), data_hash|
57
+ data_hash[key] = build_data(raw_data_value)
58
+ end
59
+ end
60
+
61
+ def build_data(raw_data_value)
62
+ if partial?(raw_data_value)
63
+ @pages[raw_data_value]
64
+ else
65
+ ApiEndpoints.build(raw_data_value)
66
+ end
67
+ end
68
+
69
+ def partial?(raw_data_value)
70
+ raw_data_value.is_a?(String) && !raw_data_value.include?(' ')
71
+ end
72
+
73
+ end
74
+
75
+ end
76
+ end
@@ -0,0 +1,29 @@
1
+ require_relative '../responses/redirect'
2
+ require_relative 'api_endpoints'
3
+
4
+ class Chaplin
5
+ module Parser
6
+
7
+ Redirects = Struct.new(:redirect_declarations) do
8
+
9
+ def self.load(redirect_declarations)
10
+ new(redirect_declarations).load
11
+ end
12
+
13
+ def load
14
+ redirect_declarations.each_with_object({}) do |(redirect_name, redirect_data), redirects_hash|
15
+ redirects_hash[redirect_name.to_s] = Responses::Redirect.new(redirect_data['path'], api_requests(redirect_data['requests']))
16
+ end
17
+ end
18
+
19
+ private
20
+
21
+ def api_requests(raw_requests_data)
22
+ raw_requests_data.each_with_object({}) do |(key, request_declaration), data_hash|
23
+ data_hash[key] = ApiEndpoints.build(request_declaration)
24
+ end
25
+ end
26
+
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,47 @@
1
+ require 'json'
2
+
3
+ require_relative '../endpoint'
4
+
5
+ class Chaplin
6
+ module Parser
7
+
8
+ class Router
9
+
10
+ def initialize(routes_declarations, pages, redirects)
11
+ @routes_declarations = routes_declarations
12
+ @pages = pages
13
+ @redirects = redirects
14
+ end
15
+
16
+ def routes
17
+ {}.tap do |routes|
18
+ @routes_declarations.each do |endpoint, response_name|
19
+ routes[build_endpoint(endpoint)] = response(response_name)
20
+ end
21
+ end
22
+ end
23
+
24
+ private
25
+
26
+ def response(response_name)
27
+ if redirect?(response_name)
28
+ redirect_name = response_name.split(' ').last
29
+ @redirects[redirect_name]
30
+ else
31
+ @pages[response_name]
32
+ end
33
+ end
34
+
35
+ def redirect?(response)
36
+ response.start_with?("redirect")
37
+ end
38
+
39
+ def build_endpoint(raw_endpoint_data)
40
+ http_method = raw_endpoint_data.split(' ').first.downcase.to_sym
41
+ path = raw_endpoint_data.split(' ').last
42
+ Endpoint.new(http_method, path)
43
+ end
44
+
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,55 @@
1
+ require_relative 'parser/declaration_file'
2
+ require_relative 'parser/router'
3
+ require_relative 'parser/pages'
4
+ require_relative 'parser/redirects'
5
+
6
+ class Chaplin
7
+ module Parser
8
+
9
+ def self.routes(project_path)
10
+ parser.routes(project_path)
11
+ end
12
+
13
+ def self.parser
14
+ Object.new.extend(self)
15
+ end
16
+
17
+ def routes(project_path)
18
+ self.project_path = project_path
19
+ Router.new(routes_declaration, pages, redirects).routes
20
+ end
21
+
22
+ private
23
+
24
+ attr_accessor :project_path
25
+
26
+ def pages
27
+ Pages.load(pages_declaration, project_path, layout_name)
28
+ end
29
+
30
+ def redirects
31
+ Redirects.load(redirects_declaration)
32
+ end
33
+
34
+ def pages_declaration
35
+ app_declaration['pages'] || []
36
+ end
37
+
38
+ def redirects_declaration
39
+ app_declaration['redirects'] || {}
40
+ end
41
+
42
+ def layout_name
43
+ app_declaration['layout']
44
+ end
45
+
46
+ def routes_declaration
47
+ app_declaration['routes']
48
+ end
49
+
50
+ def app_declaration
51
+ @app_declaration ||= DeclarationFile.app_declaration(project_path)
52
+ end
53
+
54
+ end
55
+ end
@@ -0,0 +1,29 @@
1
+ require 'mustache'
2
+
3
+ class Chaplin
4
+ module Responses
5
+
6
+ # data is a hash with symbols as keys and api endpoints or other pages as values
7
+ Page = Struct.new(:template_path, :data) do
8
+
9
+ def execute(request_params, sinatra_server)
10
+ render(request_params)
11
+ end
12
+
13
+ def render(request_params)
14
+ page = Mustache.new
15
+ page.template_file = template_path
16
+ page.render(rendered_data(request_params).merge({params: request_params}))
17
+ end
18
+
19
+ private
20
+
21
+ def rendered_data(request_params)
22
+ data.each_with_object({}) do |(key, response), rendered_data|
23
+ rendered_data[key] = response.render(request_params)
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+
@@ -0,0 +1,28 @@
1
+ require 'mustache'
2
+
3
+ class Chaplin
4
+ module Responses
5
+
6
+ Redirect = Struct.new(:redirect_path, :api_requests_hash) do
7
+
8
+ def execute(request_params, sinatra_server)
9
+ rendered_api_data = rendered_data(request_params)
10
+
11
+ sinatra_server.redirect(rendered_path(rendered_api_data, request_params))
12
+ end
13
+
14
+ private
15
+
16
+ def rendered_data(request_params)
17
+ api_requests_hash.each_with_object({}) do |(key, value), rendered_data|
18
+ rendered_data[key] = value.render(request_params)
19
+ end
20
+ end
21
+
22
+ def rendered_path(rendered_data, request_params)
23
+ Mustache.render(redirect_path, rendered_data.merge(request_params))
24
+ end
25
+
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,16 @@
1
+ require 'sinatra/base'
2
+
3
+ class Chaplin
4
+ class Server < Sinatra::Base
5
+
6
+ def self.setup(project_path)
7
+ set :public_folder, project_path + '/public'
8
+ end
9
+
10
+ def self.add_route(endpoint, response)
11
+ send(endpoint.http_method, endpoint.path) do
12
+ response.execute(params, self)
13
+ end
14
+ end
15
+ end
16
+ end
data/lib/chaplin.rb ADDED
@@ -0,0 +1,29 @@
1
+ require_relative 'chaplin/parser'
2
+ require_relative 'chaplin/parser/config'
3
+ require_relative 'chaplin/server'
4
+ require_relative 'chaplin/api_endpoint'
5
+
6
+ class Chaplin
7
+
8
+ def initialize(project_path)
9
+ @project_path = project_path
10
+ @config = Parser::Config.new(@project_path)
11
+ end
12
+
13
+ def server
14
+ ApiEndpoint.configure(@config.api_url, @config.default_headers, @config.basic_auth)
15
+ Server.setup(@project_path)
16
+ build_server
17
+ Server.new
18
+ end
19
+
20
+ private
21
+
22
+ def build_server
23
+ Parser.routes(@project_path).each do |endpoint, response|
24
+ Server.add_route(endpoint, response)
25
+ end
26
+ end
27
+
28
+ end
29
+
metadata ADDED
@@ -0,0 +1,256 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: chaplin
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Victor Mours
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-04-24 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rack
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: sinatra
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: faraday
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: mustache
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: pry
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rake
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rack-test
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: rspec
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: rspec-preloader
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: vcr
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
153
+ - !ruby/object:Gem::Dependency
154
+ name: webmock
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - ">="
158
+ - !ruby/object:Gem::Version
159
+ version: '0'
160
+ type: :development
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - ">="
165
+ - !ruby/object:Gem::Version
166
+ version: '0'
167
+ - !ruby/object:Gem::Dependency
168
+ name: cucumber
169
+ requirement: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - ">="
172
+ - !ruby/object:Gem::Version
173
+ version: '0'
174
+ type: :development
175
+ prerelease: false
176
+ version_requirements: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - ">="
179
+ - !ruby/object:Gem::Version
180
+ version: '0'
181
+ - !ruby/object:Gem::Dependency
182
+ name: relish
183
+ requirement: !ruby/object:Gem::Requirement
184
+ requirements:
185
+ - - ">="
186
+ - !ruby/object:Gem::Version
187
+ version: '0'
188
+ type: :development
189
+ prerelease: false
190
+ version_requirements: !ruby/object:Gem::Requirement
191
+ requirements:
192
+ - - ">="
193
+ - !ruby/object:Gem::Version
194
+ version: '0'
195
+ - !ruby/object:Gem::Dependency
196
+ name: childprocess
197
+ requirement: !ruby/object:Gem::Requirement
198
+ requirements:
199
+ - - ">="
200
+ - !ruby/object:Gem::Version
201
+ version: '0'
202
+ type: :development
203
+ prerelease: false
204
+ version_requirements: !ruby/object:Gem::Requirement
205
+ requirements:
206
+ - - ">="
207
+ - !ruby/object:Gem::Version
208
+ version: '0'
209
+ description: Chaplin maps JSON APIs to Mustache templates to quickly create HTML apps,
210
+ without writing glue code.
211
+ email: victor.mours@gmail.com
212
+ executables:
213
+ - chaplin
214
+ extensions: []
215
+ extra_rdoc_files: []
216
+ files:
217
+ - bin/chaplin
218
+ - lib/chaplin.rb
219
+ - lib/chaplin/api_endpoint.rb
220
+ - lib/chaplin/endpoint.rb
221
+ - lib/chaplin/parser.rb
222
+ - lib/chaplin/parser/api_endpoints.rb
223
+ - lib/chaplin/parser/config.rb
224
+ - lib/chaplin/parser/declaration_file.rb
225
+ - lib/chaplin/parser/pages.rb
226
+ - lib/chaplin/parser/redirects.rb
227
+ - lib/chaplin/parser/router.rb
228
+ - lib/chaplin/responses/page.rb
229
+ - lib/chaplin/responses/redirect.rb
230
+ - lib/chaplin/server.rb
231
+ homepage: https://github.com/victormours/chaplin
232
+ licenses:
233
+ - MIT
234
+ metadata: {}
235
+ post_install_message:
236
+ rdoc_options: []
237
+ require_paths:
238
+ - lib
239
+ required_ruby_version: !ruby/object:Gem::Requirement
240
+ requirements:
241
+ - - ">="
242
+ - !ruby/object:Gem::Version
243
+ version: '0'
244
+ required_rubygems_version: !ruby/object:Gem::Requirement
245
+ requirements:
246
+ - - ">="
247
+ - !ruby/object:Gem::Version
248
+ version: '0'
249
+ requirements: []
250
+ rubyforge_project:
251
+ rubygems_version: 2.2.2
252
+ signing_key:
253
+ specification_version: 4
254
+ summary: Build HTML apps from JSON APIs in no time
255
+ test_files: []
256
+ has_rdoc: