heroics 0.0.6 → 0.0.7

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
  SHA1:
3
- metadata.gz: ef1ff049152a681067bf9cd179da754105d8419c
4
- data.tar.gz: 1e98dc4aa35031eefc0734252bc1e650c969073b
3
+ metadata.gz: 57ff3e602b9779ad560f218f14288d8871402d33
4
+ data.tar.gz: 6763bba24c1ccb627963116ee6f43ed341113703
5
5
  SHA512:
6
- metadata.gz: 1b7486964a14891fcbede7250748ffd41e8b44c5f7446f4bac06260365d79b3b1b5801dc14d13706a2a61ed0cc42961ff181aff9063eadf449264cd465babbb6
7
- data.tar.gz: dd2217537e68ae2ab93fd1985c3812edaba6c0a666af6b8202ba3a560a4ac89fa3b9a5f59841e92ecd95c3a9110502383309139bbcc001720a46529924a20230
6
+ metadata.gz: 97435f7696ba084ec24a487ea3a652a880100124981e1ebf7f1e91bebf8baff64c6b281dca44e8480d550d3097ac368e36ddd8a466114841b9811b8dd2f4e072
7
+ data.tar.gz: 05282988882070b71e6cf9c9c6834bb65fc91c783da88c08e0163b54a21e97dedec950d9b187593cbed23b18c379404d0a6acb091800cb37adbdf586386c1fd9
@@ -0,0 +1,22 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'optparse'
4
+ require 'heroics'
5
+
6
+ options = {}
7
+ option_parser = OptionParser.new do |opts|
8
+ opts.banner = 'Usage: heroics-generate module_name schema_filename url'
9
+ opts.on( '-h', '--help', 'Display this screen' ) do
10
+ puts opts
11
+ exit
12
+ end
13
+ end
14
+
15
+ option_parser.parse!
16
+ module_name, schema_filename, url = ARGV
17
+ schema = Heroics::Schema.new(MultiJson.decode(File.read(schema_filename)))
18
+ options = {
19
+ default_headers: {'Accept' => 'application/vnd.heroku+json; version=3'},
20
+ cache: 'Moneta.new(:File, dir: "#{Dir.home}/.heroics/platform-api")'
21
+ }
22
+ puts Heroics.generate_client(module_name, schema, url, options)
@@ -25,8 +25,9 @@ Gem::Specification.new do |spec|
25
25
  spec.add_development_dependency 'rake'
26
26
  spec.add_development_dependency 'turn'
27
27
 
28
+ spec.add_dependency 'erubis', '~> 2.7.0'
28
29
  spec.add_dependency 'excon'
29
- spec.add_dependency 'netrc'
30
30
  spec.add_dependency 'moneta'
31
- spec.add_dependency 'multi_json'
31
+ spec.add_dependency 'multi_json', '>= 1.9.2'
32
+ spec.add_dependency 'netrc'
32
33
  end
@@ -1,4 +1,5 @@
1
1
  require 'base64'
2
+ require 'erubis'
2
3
  require 'excon'
3
4
  require 'moneta'
4
5
  require 'multi_json'
@@ -18,3 +19,4 @@ require 'heroics/client'
18
19
  require 'heroics/schema'
19
20
  require 'heroics/command'
20
21
  require 'heroics/cli'
22
+ require 'heroics/client_generator'
@@ -0,0 +1,106 @@
1
+ module Heroics
2
+ # Generate a static client that uses Heroics under the hood. This is a good
3
+ # option if you want to ship a gem or generate API documentation using Yard.
4
+ #
5
+ # @param module_name [String] The name of the module, as rendered in a Ruby
6
+ # source file, to use for the generated client.
7
+ # @param schema [Schema] The schema instance to generate the client from.
8
+ # @param url [String] The URL for the API service.
9
+ # @param options [Hash] Configuration for links. Possible keys include:
10
+ # - default_headers: Optionally, a set of headers to include in every
11
+ # request made by the client. Default is no custom headers.
12
+ # - cache: Optionally, a Moneta-compatible cache to store ETags. Default
13
+ # is no caching.
14
+ def self.generate_client(module_name, schema, url, options)
15
+ filename = File.dirname(__FILE__) + '/views/client.erb'
16
+ eruby = Erubis::Eruby.new(File.read(filename))
17
+ context = build_context(module_name, schema, url, options)
18
+ eruby.evaluate(context)
19
+ end
20
+
21
+ private
22
+
23
+ # Process the schema to build up the context needed to render the source
24
+ # template.
25
+ def self.build_context(module_name, schema, url, options)
26
+ resources = []
27
+ schema.resources.each do |resource_schema|
28
+ links = []
29
+ resource_schema.links.each do |link_schema|
30
+ links << GeneratorLink.new(link_schema.name.gsub('-', '_'),
31
+ link_schema.description,
32
+ link_schema.parameter_details,
33
+ link_schema.needs_request_body?)
34
+ end
35
+ resources << GeneratorResource.new(resource_schema.name.gsub('-', '_'),
36
+ resource_schema.description,
37
+ links)
38
+ end
39
+
40
+ context = {module_name: module_name,
41
+ url: url,
42
+ default_headers: options.fetch(:default_headers, {}),
43
+ cache: options.fetch(:cache, {}),
44
+ description: schema.description,
45
+ schema: MultiJson.dump(schema.schema),
46
+ resources: resources}
47
+ end
48
+
49
+ # A representation of a resource for use when generating source code in the
50
+ # template.
51
+ class GeneratorResource
52
+ attr_reader :name, :description, :links
53
+
54
+ def initialize(name, description, links)
55
+ @name = name
56
+ @description = description
57
+ @links = links
58
+ end
59
+
60
+ # The name of the resource class in generated code.
61
+ def class_name
62
+ Heroics.camel_case(name)
63
+ end
64
+ end
65
+
66
+ # A representation of a link for use when generating source code in the
67
+ # template.
68
+ class GeneratorLink
69
+ attr_reader :name, :description, :parameters, :takes_body
70
+
71
+ def initialize(name, description, parameters, takes_body)
72
+ @name = name
73
+ @description = description
74
+ @parameters = parameters
75
+ if takes_body
76
+ parameters << BodyParameter.new
77
+ end
78
+ end
79
+
80
+ # The list of parameters to render in generated source code for the method
81
+ # signature for the link.
82
+ def parameter_names
83
+ @parameters.map { |info| info.name }.join(', ')
84
+ end
85
+ end
86
+
87
+ # Convert a lower_case_name to CamelCase.
88
+ def self.camel_case(text)
89
+ return text if text !~ /_/ && text =~ /[A-Z]+.*/
90
+ text = text.split('_').map{ |element| element.capitalize }.join
91
+ [/^Ssl/, /^Http/, /^Xml/].each do |replace|
92
+ text.sub!(replace) { |match| match.upcase }
93
+ end
94
+ text
95
+ end
96
+
97
+ # A representation of a body parameter.
98
+ class BodyParameter
99
+ attr_reader :name, :description
100
+
101
+ def initialize
102
+ @name = 'body'
103
+ @description = 'the object to pass as the request payload'
104
+ end
105
+ end
106
+ end
@@ -14,6 +14,11 @@ module Heroics
14
14
  end
15
15
  end
16
16
 
17
+ # A description of the API.
18
+ def description
19
+ @schema['description']
20
+ end
21
+
17
22
  # Get a schema for a named resource.
18
23
  #
19
24
  # @param name [String] The name of the resource.
@@ -60,6 +65,11 @@ module Heroics
60
65
  end]
61
66
  end
62
67
 
68
+ # A description of the resource.
69
+ def description
70
+ @schema['definitions'][name]['description']
71
+ end
72
+
63
73
  # Get a schema for a named link.
64
74
  #
65
75
  # @param name [String] The name of the link.
@@ -122,7 +132,21 @@ module Heroics
122
132
  #
123
133
  # @return [Array<String>] The parameters.
124
134
  def parameters
125
- resolve_parameters(link_schema['href'].scan(PARAMETER_REGEX))
135
+ parameter_names = link_schema['href'].scan(PARAMETER_REGEX)
136
+ resolve_parameters(parameter_names)
137
+ end
138
+
139
+ # Get the names and descriptions of the parameters this link expects.
140
+ #
141
+ # @return [Hash<String, String>] A list of hashes with `name` and
142
+ # `description` key/value pairs describing parameters.
143
+ def parameter_details
144
+ parameter_names = link_schema['href'].scan(PARAMETER_REGEX)
145
+ resolve_parameter_details(parameter_names)
146
+ end
147
+
148
+ def needs_request_body?
149
+ return link_schema.has_key?('schema')
126
150
  end
127
151
 
128
152
  # Get an example request body.
@@ -132,14 +156,14 @@ module Heroics
132
156
  if body_schema = link_schema['schema']
133
157
  definitions = @schema['definitions'][@resource_name]['definitions']
134
158
  Hash[body_schema['properties'].keys.map do |property|
135
- # FIXME This is wrong! -jkakar
136
- if definitions.has_key?(property)
137
- example = definitions[property]['example']
138
- else
139
- example = ''
140
- end
141
- [property, example]
142
- end]
159
+ # FIXME This is wrong! -jkakar
160
+ if definitions.has_key?(property)
161
+ example = definitions[property]['example']
162
+ else
163
+ example = ''
164
+ end
165
+ [property, example]
166
+ end]
143
167
  end
144
168
  end
145
169
 
@@ -173,7 +197,7 @@ module Heroics
173
197
  private
174
198
 
175
199
  # Match parameters in definition strings.
176
- PARAMETER_REGEX = /\{\([%\/a-zA-Z0-9_]*\)\}/
200
+ PARAMETER_REGEX = /\{\([%\/a-zA-Z0-9_-]*\)\}/
177
201
 
178
202
  # Get the raw link schema.
179
203
  #
@@ -188,10 +212,8 @@ module Heroics
188
212
  # convert to parameter names.
189
213
  # @return [Array<String>] The parameters.
190
214
  def resolve_parameters(parameters)
191
- # FIXME This is all pretty terrible. It'd be much better to
192
- # automatically resolve $ref's based on the path instead of special
193
- # casing everything. -jkakar
194
215
  properties = @schema['definitions'][@resource_name]['properties']
216
+ return [''] if properties.nil?
195
217
  definitions = Hash[properties.each_pair.map do |key, value|
196
218
  [value['$ref'], key]
197
219
  end]
@@ -216,6 +238,72 @@ module Heroics
216
238
  end
217
239
  end
218
240
 
241
+ # Get the parameters this link expects.
242
+ #
243
+ # @param parameters [Array] The names of the parameter definitions to
244
+ # convert to parameter names.
245
+ # @return [Array<Parameter|ParameterChoice>] A list of parameter instances
246
+ # that represent parameters to be injected into the link URL.
247
+ def resolve_parameter_details(parameters)
248
+ properties = @schema['definitions'][@resource_name]['properties']
249
+ return [] if properties.nil?
250
+
251
+ # URI decode parameters and strip the leading '{(' and trailing ')}'.
252
+ parameters = parameters.map { |parameter| URI.unescape(parameter[2..-3]) }
253
+ parameters.map do |parameter|
254
+ # Split the path into components and discard the leading '#' that
255
+ # represents the root of the schema.
256
+ path = parameter.split('/')[1..-1]
257
+ info = lookup_parameter(path, @schema)
258
+ # The reference can be one of several values.
259
+ resource_name = path[1].gsub('-', '_')
260
+ if info.has_key?('anyOf')
261
+ ParameterChoice.new(resource_name,
262
+ unpack_multiple_parameters(info['anyOf']))
263
+ elsif info.has_key?('oneOf')
264
+ ParameterChoice.new(resource_name,
265
+ unpack_multiple_parameters(info['oneOf']))
266
+ else
267
+ name = path[-1]
268
+ Parameter.new(resource_name, name, info['description'])
269
+ end
270
+ end
271
+ end
272
+
273
+ # Unpack an 'anyOf' or 'oneOf' multi-parameter blob.
274
+ #
275
+ # @param parameters [Array<Hash>] An array of hashes containing '$ref'
276
+ # keys and definition values.
277
+ # @return [Array<Parameter>] An array of parameters extracted from the
278
+ # blob.
279
+ def unpack_multiple_parameters(parameters)
280
+ parameters.map do |info|
281
+ parameter = info['$ref']
282
+ path = parameter.split('/')[1..-1]
283
+ info = lookup_parameter(path, @schema)
284
+ resource_name = path[1].gsub('-', '_')
285
+ name = path[-1]
286
+ Parameter.new(resource_name, name, info['description'])
287
+ end
288
+ end
289
+
290
+ # Recursively walk the object hierarchy in the schema to resolve a given
291
+ # path. This is used to find property information related to definitions
292
+ # in link hrefs.
293
+ #
294
+ # @param path [Array<String>] An array of paths to walk, such as
295
+ # ['definitions', 'resource', 'definitions', 'property'].
296
+ # @param schema [Hash] The schema to walk.
297
+ def lookup_parameter(path, schema)
298
+ key = path[0]
299
+ remaining = path[1..-1]
300
+ if remaining.empty?
301
+ return schema[key]
302
+ else
303
+ lookup_parameter(remaining, schema[key])
304
+ end
305
+ end
306
+
219
307
  # Convert a path parameter to a format suitable for use in a path.
220
308
  #
221
309
  # @param [Fixnum,String,TrueClass,FalseClass,Time] The parameter to format.
@@ -243,6 +331,54 @@ module Heroics
243
331
  def self.download_schema(url, options={})
244
332
  default_headers = options.fetch(:default_headers, {})
245
333
  response = Excon.get(url, headers: default_headers, expects: [200, 201])
246
- Schema.new(MultiJson.decode(response.body))
334
+ Schema.new(MultiJson.load(response.body))
335
+ end
336
+
337
+ # A representation of a parameter.
338
+ class Parameter
339
+ attr_reader :resource_name, :description
340
+
341
+ def initialize(resource_name, name, description)
342
+ @resource_name = resource_name
343
+ @name = name
344
+ @description = description
345
+ end
346
+
347
+ # The name of the parameter, with the resource included, suitable for use
348
+ # in a function signature.
349
+ def name
350
+ "#{@resource_name}_#{@name}"
351
+ end
352
+
353
+ # A pretty representation of this instance.
354
+ def inspect
355
+ "Parameter(name=#{@name}, description=#{@description})"
356
+ end
357
+ end
358
+
359
+ # A representation of a set of parameters.
360
+ class ParameterChoice
361
+ attr_reader :resource_name, :parameters
362
+
363
+ def initialize(resource_name, parameters)
364
+ @resource_name = resource_name
365
+ @parameters = parameters
366
+ end
367
+
368
+ # A name created by merging individual parameter descriptions, suitable
369
+ # for use in a function signature.
370
+ def name
371
+ @parameters.map { |parameter| parameter.name }.join('_or_')
372
+ end
373
+
374
+ # A description created by merging individual parameter descriptions.
375
+ def description
376
+ @parameters.map { |parameter| parameter.description }.join(' or ')
377
+ end
378
+
379
+ # A pretty representation of this instance.
380
+ def inspect
381
+ "ParameterChoice(parameters=#{@parameters})"
382
+ end
247
383
  end
248
384
  end
@@ -1,3 +1,3 @@
1
1
  module Heroics
2
- VERSION = '0.0.6'
2
+ VERSION = '0.0.7'
3
3
  end
@@ -0,0 +1,102 @@
1
+ # encoding: utf-8
2
+
3
+ #
4
+ # WARNING: Do not edit by hand, this file was generated by Heroics:
5
+ #
6
+ # https://github.com/heroku/heroics
7
+ #
8
+
9
+ require 'uri'
10
+
11
+ module <%= @module_name %>
12
+ # Get a Client configured to use HTTP Basic authentication.
13
+ #
14
+ # @param username [String] The username to use with the API.
15
+ # @param password [String] The password to use with the API.
16
+ # @param headers [Hash<String,String>] Optionally, custom to headers to
17
+ # include with every response.
18
+ # @return [Client] A client configured to use the API with HTTP Basic
19
+ # authentication.
20
+ def self.connect(username, password, headers=nil)
21
+ url = URI.parse("<%= @url %>")
22
+ url.user = username
23
+ url.password = password
24
+ default_headers = <%= @default_headers %>
25
+ unless headers.nil?
26
+ default_headers.merge!(headers)
27
+ end
28
+ cache = <%= @cache %>
29
+ options = {
30
+ options: {default_headers: default_headers,
31
+ cache: cache}
32
+ }
33
+ client = Heroics.client_from_schema(SCHEMA, url.to_s, options)
34
+ Client.new(client)
35
+ end
36
+
37
+ # Get a Client configured to use OAuth authentication.
38
+ #
39
+ # @param oauth_token [String] The OAuth token to use with the API.
40
+ # @param headers [Hash<String,String>] Optionally, custom to headers to
41
+ # include with every response.
42
+ # @return [Client] A client configured to use the API with OAuth
43
+ # authentication.
44
+ def self.connect_oauth(oauth_token, headers=nil)
45
+ url = "<%= @url %>"
46
+ default_headers = <%= @default_headers %>
47
+ unless headers.nil?
48
+ default_headers.merge!(headers)
49
+ end
50
+ cache = <%= @cache %>
51
+ options = {
52
+ options: {default_headers: default_headers,
53
+ cache: cache}
54
+ }
55
+ client = Heroics.client_from_schema(oauth_token, SCHEMA, url, options)
56
+ Client.new(client)
57
+ end
58
+
59
+ # <%= @description %>
60
+ class Client
61
+ def initialize(client)
62
+ @client = client
63
+ end
64
+ <% for resource in @resources %>
65
+
66
+ # <%= resource.description %>
67
+ #
68
+ # @return [<%= resource.class_name %>]
69
+ def <%= resource.name %>
70
+ @<%= resource.name %>_resource ||= <%= resource.class_name %>.new(@client)
71
+ end
72
+ <% end %>
73
+ end
74
+
75
+ private
76
+ <% for resource in @resources %>
77
+
78
+ # <%= resource.description %>
79
+ class <%= resource.class_name %>
80
+ def initialize(client)
81
+ @client = client
82
+ end
83
+ <% for link in resource.links %>
84
+
85
+ # <%= link.description %>
86
+ <% unless link.parameters.empty? %>
87
+ #
88
+ <% for parameter in link.parameters %>
89
+ # @param <%= parameter.name %>: <%= parameter.description %>
90
+ <% end %>
91
+ <% end %>
92
+ def <%= link.name %>(<%= link.parameter_names %>)
93
+ @client.<%= resource.name %>.<%= link.name %>(<%= link.parameter_names %>)
94
+ end
95
+ <% end %>
96
+ end
97
+ <% end %>
98
+
99
+ SCHEMA = Heroics::Schema.new(MultiJson.load(<<-'HEROICS_SCHEMA'))
100
+ <%= @schema %>
101
+ HEROICS_SCHEMA
102
+ end
@@ -0,0 +1,34 @@
1
+ require 'helper'
2
+ require 'netrc'
3
+ require 'stringio'
4
+
5
+ class GenerateClientTest < MiniTest::Unit::TestCase
6
+ include ExconHelper
7
+
8
+ # generate_client takes a module, schema, API URL and options and returns a
9
+ # string containing generated Ruby client code.
10
+ def test_generate_client
11
+ Excon.stub(method: :get) do |request|
12
+ assert_equal('example.com', request[:host])
13
+ assert_equal('/schema', request[:path])
14
+ assert_equal('application/vnd.example+json; version=3',
15
+ request[:headers]['Accept'])
16
+ Excon.stubs.pop
17
+ {status: 200, headers: {'Content-Type' => 'application/json'},
18
+ body: MultiJson.dump(SAMPLE_SCHEMA)}
19
+ end
20
+
21
+ netrc = Netrc.read
22
+ username, token = netrc['example.com']
23
+ schema_url = "https://example.com/schema"
24
+ options = {
25
+ default_headers: {'Accept' => 'application/vnd.example+json; version=3'},
26
+ cache: 'Moneta.new(:File, dir: "#{Dir.home}/.heroics/example")'
27
+ }
28
+ schema = Heroics.download_schema(schema_url, options)
29
+ client_source = Heroics.generate_client("ExampleAPI", schema,
30
+ "api.example.com", options)
31
+ # Ensure the generated code is syntactically valid.
32
+ eval(client_source)
33
+ end
34
+ end
@@ -50,7 +50,7 @@ class ResourceSchemaTest < MiniTest::Unit::TestCase
50
50
  assert_equal("Unknown link 'unknown-link'.", error.message)
51
51
  end
52
52
 
53
- # ResourceSchema.links returns a list of LinkSchema children.
53
+ # ResourceSchema.links returns an array of LinkSchema children.
54
54
  def test_links
55
55
  schema = Heroics::Schema.new(SAMPLE_SCHEMA)
56
56
  assert_equal(
@@ -80,7 +80,7 @@ class LinkSchemaTest < MiniTest::Unit::TestCase
80
80
  schema.resource('resource').link('list').description)
81
81
  end
82
82
 
83
- # LinkSchema.parameters returns an empty list if the link doesn't require
83
+ # LinkSchema.parameters returns an empty array if the link doesn't require
84
84
  # parameters.
85
85
  def test_parameters_without_parameters
86
86
  schema = Heroics::Schema.new(SAMPLE_SCHEMA)
@@ -88,8 +88,8 @@ class LinkSchemaTest < MiniTest::Unit::TestCase
88
88
  assert_equal([], link.parameters)
89
89
  end
90
90
 
91
- # LinkSchema.parameters returns a list of named parameter required to invoke
92
- # the link correctly.
91
+ # LinkSchema.parameters returns an array of named parameter required to
92
+ # invoke the link correctly.
93
93
  def test_parameters
94
94
  schema = Heroics::Schema.new(SAMPLE_SCHEMA)
95
95
  link = schema.resource('resource').link('info')
@@ -105,6 +105,40 @@ class LinkSchemaTest < MiniTest::Unit::TestCase
105
105
  assert_equal(['uuid_field|email_field'], link.parameters)
106
106
  end
107
107
 
108
+ # LinkSchema.parameter_details returns an empty array if the link doesn't
109
+ # require parameters.
110
+ def test_parameter_details_without_parameters
111
+ schema = Heroics::Schema.new(SAMPLE_SCHEMA)
112
+ link = schema.resource('resource').link('list')
113
+ assert_equal([], link.parameter_details)
114
+ end
115
+
116
+ # LinkSchema.parameter_details returns an array of Parameter with information
117
+ # about the parameters accepted by the link.
118
+ def test_parameter_details
119
+ schema = Heroics::Schema.new(SAMPLE_SCHEMA)
120
+ link = schema.resource('resource').link('info')
121
+ parameters = link.parameter_details
122
+ assert_equal(1, parameters.length)
123
+ parameter = parameters[0]
124
+ assert_equal('resource_uuid_field', parameter.name)
125
+ assert_equal('A sample UUID field', parameter.description)
126
+ end
127
+
128
+ # LinkSchema.parameter_details returns an array of ParameterChoices, when
129
+ # more than one value may be used with a property, with information about
130
+ # the parameters accepted by the link.
131
+ def test_parameter_details_with_one_of_field
132
+ schema = Heroics::Schema.new(SAMPLE_SCHEMA)
133
+ link = schema.resource('resource').link('identify_resource')
134
+ parameters = link.parameter_details
135
+ assert_equal(1, parameters.length)
136
+ parameter = parameters[0]
137
+ assert_equal('resource_uuid_field_or_resource_email_field', parameter.name)
138
+ assert_equal('A sample UUID field or A sample email address field',
139
+ parameter.description)
140
+ end
141
+
108
142
  # LinkSchema.body returns nil if the link doesn't accept a request body.
109
143
  def test_example_body_without_body
110
144
  schema = Heroics::Schema.new(SAMPLE_SCHEMA)
@@ -125,7 +159,7 @@ class LinkSchemaTest < MiniTest::Unit::TestCase
125
159
  link.example_body)
126
160
  end
127
161
 
128
- # LinkSchema.format_path converts a list of parameters into a path.
162
+ # LinkSchema.format_path converts an array of parameters into a path.
129
163
  def test_format_path
130
164
  schema = Heroics::Schema.new(SAMPLE_SCHEMA)
131
165
  link = schema.resource('resource').link('info')
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: heroics
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.6
4
+ version: 0.0.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - geemus
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-04-09 00:00:00.000000000 Z
12
+ date: 2014-04-29 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
@@ -67,6 +67,20 @@ dependencies:
67
67
  - - '>='
68
68
  - !ruby/object:Gem::Version
69
69
  version: '0'
70
+ - !ruby/object:Gem::Dependency
71
+ name: erubis
72
+ requirement: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ~>
75
+ - !ruby/object:Gem::Version
76
+ version: 2.7.0
77
+ type: :runtime
78
+ prerelease: false
79
+ version_requirements: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ~>
82
+ - !ruby/object:Gem::Version
83
+ version: 2.7.0
70
84
  - !ruby/object:Gem::Dependency
71
85
  name: excon
72
86
  requirement: !ruby/object:Gem::Requirement
@@ -82,7 +96,7 @@ dependencies:
82
96
  - !ruby/object:Gem::Version
83
97
  version: '0'
84
98
  - !ruby/object:Gem::Dependency
85
- name: netrc
99
+ name: moneta
86
100
  requirement: !ruby/object:Gem::Requirement
87
101
  requirements:
88
102
  - - '>='
@@ -96,21 +110,21 @@ dependencies:
96
110
  - !ruby/object:Gem::Version
97
111
  version: '0'
98
112
  - !ruby/object:Gem::Dependency
99
- name: moneta
113
+ name: multi_json
100
114
  requirement: !ruby/object:Gem::Requirement
101
115
  requirements:
102
116
  - - '>='
103
117
  - !ruby/object:Gem::Version
104
- version: '0'
118
+ version: 1.9.2
105
119
  type: :runtime
106
120
  prerelease: false
107
121
  version_requirements: !ruby/object:Gem::Requirement
108
122
  requirements:
109
123
  - - '>='
110
124
  - !ruby/object:Gem::Version
111
- version: '0'
125
+ version: 1.9.2
112
126
  - !ruby/object:Gem::Dependency
113
- name: multi_json
127
+ name: netrc
114
128
  requirement: !ruby/object:Gem::Requirement
115
129
  requirements:
116
130
  - - '>='
@@ -128,6 +142,7 @@ email:
128
142
  - geemus@gmail.com
129
143
  - jkakar@kakar.ca
130
144
  executables:
145
+ - heroics-generate
131
146
  - heroku-api
132
147
  extensions: []
133
148
  extra_rdoc_files: []
@@ -139,11 +154,13 @@ files:
139
154
  - README.md
140
155
  - Rakefile
141
156
  - TODO
157
+ - bin/heroics-generate
142
158
  - bin/heroku-api
143
159
  - heroics.gemspec
144
160
  - lib/heroics.rb
145
161
  - lib/heroics/cli.rb
146
162
  - lib/heroics/client.rb
163
+ - lib/heroics/client_generator.rb
147
164
  - lib/heroics/command.rb
148
165
  - lib/heroics/errors.rb
149
166
  - lib/heroics/link.rb
@@ -151,8 +168,10 @@ files:
151
168
  - lib/heroics/resource.rb
152
169
  - lib/heroics/schema.rb
153
170
  - lib/heroics/version.rb
171
+ - lib/heroics/views/client.erb
154
172
  - test.rb
155
173
  - test/cli_test.rb
174
+ - test/client_generator_test.rb
156
175
  - test/client_test.rb
157
176
  - test/command_test.rb
158
177
  - test/helper.rb