openc-asana 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 +7 -0
- data/.codeclimate.yml +4 -0
- data/.gitignore +13 -0
- data/.rspec +4 -0
- data/.rubocop.yml +11 -0
- data/.travis.yml +12 -0
- data/.yardopts +5 -0
- data/CODE_OF_CONDUCT.md +13 -0
- data/Gemfile +21 -0
- data/Guardfile +86 -0
- data/LICENSE.txt +21 -0
- data/README.md +355 -0
- data/Rakefile +65 -0
- data/examples/Gemfile +6 -0
- data/examples/Gemfile.lock +59 -0
- data/examples/api_token.rb +21 -0
- data/examples/cli_app.rb +25 -0
- data/examples/events.rb +38 -0
- data/examples/omniauth_integration.rb +54 -0
- data/lib/asana.rb +12 -0
- data/lib/asana/authentication.rb +8 -0
- data/lib/asana/authentication/oauth2.rb +42 -0
- data/lib/asana/authentication/oauth2/access_token_authentication.rb +51 -0
- data/lib/asana/authentication/oauth2/bearer_token_authentication.rb +32 -0
- data/lib/asana/authentication/oauth2/client.rb +50 -0
- data/lib/asana/authentication/token_authentication.rb +20 -0
- data/lib/asana/client.rb +124 -0
- data/lib/asana/client/configuration.rb +165 -0
- data/lib/asana/errors.rb +92 -0
- data/lib/asana/http_client.rb +155 -0
- data/lib/asana/http_client/environment_info.rb +53 -0
- data/lib/asana/http_client/error_handling.rb +103 -0
- data/lib/asana/http_client/response.rb +32 -0
- data/lib/asana/resource_includes/attachment_uploading.rb +33 -0
- data/lib/asana/resource_includes/collection.rb +68 -0
- data/lib/asana/resource_includes/event.rb +51 -0
- data/lib/asana/resource_includes/event_subscription.rb +14 -0
- data/lib/asana/resource_includes/events.rb +103 -0
- data/lib/asana/resource_includes/registry.rb +63 -0
- data/lib/asana/resource_includes/resource.rb +103 -0
- data/lib/asana/resource_includes/response_helper.rb +14 -0
- data/lib/asana/resources.rb +14 -0
- data/lib/asana/resources/attachment.rb +44 -0
- data/lib/asana/resources/project.rb +154 -0
- data/lib/asana/resources/story.rb +64 -0
- data/lib/asana/resources/tag.rb +120 -0
- data/lib/asana/resources/task.rb +300 -0
- data/lib/asana/resources/team.rb +55 -0
- data/lib/asana/resources/user.rb +72 -0
- data/lib/asana/resources/workspace.rb +91 -0
- data/lib/asana/ruby2_0_0_compatibility.rb +3 -0
- data/lib/asana/version.rb +5 -0
- data/lib/templates/index.js +8 -0
- data/lib/templates/resource.ejs +225 -0
- data/openc-asana.gemspec +32 -0
- data/package.json +7 -0
- metadata +200 -0
@@ -0,0 +1,72 @@
|
|
1
|
+
### WARNING: This file is auto-generated by the asana-api-meta repo. Do not
|
2
|
+
### edit it manually.
|
3
|
+
|
4
|
+
module Asana
|
5
|
+
module Resources
|
6
|
+
# A _user_ object represents an account in Asana that can be given access to
|
7
|
+
# various workspaces, projects, and tasks.
|
8
|
+
#
|
9
|
+
# Like other objects in the system, users are referred to by numerical IDs.
|
10
|
+
# However, the special string identifier `me` can be used anywhere
|
11
|
+
# a user ID is accepted, to refer to the current authenticated user.
|
12
|
+
class User < Resource
|
13
|
+
|
14
|
+
|
15
|
+
attr_reader :id
|
16
|
+
|
17
|
+
attr_reader :email
|
18
|
+
|
19
|
+
attr_reader :photo
|
20
|
+
|
21
|
+
attr_reader :workspaces
|
22
|
+
|
23
|
+
class << self
|
24
|
+
# Returns the plural name of the resource.
|
25
|
+
def plural_name
|
26
|
+
'users'
|
27
|
+
end
|
28
|
+
|
29
|
+
# Returns the full user record for the currently authenticated user.
|
30
|
+
#
|
31
|
+
# options - [Hash] the request I/O options.
|
32
|
+
def me(client, options: {})
|
33
|
+
|
34
|
+
Resource.new(parse(client.get("/users/me", options: options)).first, client: client)
|
35
|
+
end
|
36
|
+
|
37
|
+
# Returns the full user record for a single user.
|
38
|
+
#
|
39
|
+
# id - [Id] Globally unique identifier for the user.
|
40
|
+
#
|
41
|
+
# options - [Hash] the request I/O options.
|
42
|
+
def find_by_id(client, id, options: {})
|
43
|
+
|
44
|
+
self.new(parse(client.get("/users/#{id}", options: options)).first, client: client)
|
45
|
+
end
|
46
|
+
|
47
|
+
# Returns the user records for all users in all workspaces and organizations
|
48
|
+
# accessible to the authenticated user.
|
49
|
+
#
|
50
|
+
# workspace - [Id] The workspace in which to get users.
|
51
|
+
# per_page - [Integer] the number of records to fetch per page.
|
52
|
+
# options - [Hash] the request I/O options.
|
53
|
+
def find_by_workspace(client, workspace: required("workspace"), per_page: 20, options: {})
|
54
|
+
params = { limit: per_page }.reject { |_,v| v.nil? || Array(v).empty? }
|
55
|
+
Collection.new(parse(client.get("/workspaces/#{workspace}/users", params: params, options: options)), type: self, client: client)
|
56
|
+
end
|
57
|
+
|
58
|
+
# Returns the user records for all users in the specified workspace or
|
59
|
+
# organization.
|
60
|
+
#
|
61
|
+
# workspace - [Id] The workspace or organization to filter users on.
|
62
|
+
# per_page - [Integer] the number of records to fetch per page.
|
63
|
+
# options - [Hash] the request I/O options.
|
64
|
+
def find_all(client, workspace: nil, per_page: 20, options: {})
|
65
|
+
params = { workspace: workspace, limit: per_page }.reject { |_,v| v.nil? || Array(v).empty? }
|
66
|
+
Collection.new(parse(client.get("/users", params: params, options: options)), type: self, client: client)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
### WARNING: This file is auto-generated by the asana-api-meta repo. Do not
|
2
|
+
### edit it manually.
|
3
|
+
|
4
|
+
module Asana
|
5
|
+
module Resources
|
6
|
+
# A _workspace_ is the highest-level organizational unit in Asana. All projects
|
7
|
+
# and tasks have an associated workspace.
|
8
|
+
#
|
9
|
+
# An _organization_ is a special kind of workspace that represents a company.
|
10
|
+
# In an organization, you can group your projects into teams. You can read
|
11
|
+
# more about how organizations work on the Asana Guide.
|
12
|
+
# To tell if your workspace is an organization or not, check its
|
13
|
+
# `is_organization` property.
|
14
|
+
#
|
15
|
+
# Over time, we intend to migrate most workspaces into organizations and to
|
16
|
+
# release more organization-specific functionality. We may eventually deprecate
|
17
|
+
# using workspace-based APIs for organizations. Currently, and until after
|
18
|
+
# some reasonable grace period following any further announcements, you can
|
19
|
+
# still reference organizations in any `workspace` parameter.
|
20
|
+
class Workspace < Resource
|
21
|
+
|
22
|
+
|
23
|
+
attr_reader :id
|
24
|
+
|
25
|
+
attr_reader :name
|
26
|
+
|
27
|
+
attr_reader :is_organization
|
28
|
+
|
29
|
+
class << self
|
30
|
+
# Returns the plural name of the resource.
|
31
|
+
def plural_name
|
32
|
+
'workspaces'
|
33
|
+
end
|
34
|
+
|
35
|
+
# Returns the full workspace record for a single workspace.
|
36
|
+
#
|
37
|
+
# id - [Id] Globally unique identifier for the workspace or organization.
|
38
|
+
#
|
39
|
+
# options - [Hash] the request I/O options.
|
40
|
+
def find_by_id(client, id, options: {})
|
41
|
+
|
42
|
+
self.new(parse(client.get("/workspaces/#{id}", options: options)).first, client: client)
|
43
|
+
end
|
44
|
+
|
45
|
+
# Returns the compact records for all workspaces visible to the authorized user.
|
46
|
+
#
|
47
|
+
# per_page - [Integer] the number of records to fetch per page.
|
48
|
+
# options - [Hash] the request I/O options.
|
49
|
+
def find_all(client, per_page: 20, options: {})
|
50
|
+
params = { limit: per_page }.reject { |_,v| v.nil? || Array(v).empty? }
|
51
|
+
Collection.new(parse(client.get("/workspaces", params: params, options: options)), type: self, client: client)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
# Update properties on a workspace. Returns the complete, updated workspace record.
|
56
|
+
#
|
57
|
+
# options - [Hash] the request I/O options.
|
58
|
+
# data - [Hash] the attributes to post.
|
59
|
+
def update(options: {}, **data)
|
60
|
+
|
61
|
+
refresh_with(parse(client.put("/workspaces/#{id}", body: data, options: options)).first)
|
62
|
+
end
|
63
|
+
|
64
|
+
# Retrieves objects in the workspace based on an auto-completion/typeahead
|
65
|
+
# search algorithm. This feature is meant to provide results quickly, so do
|
66
|
+
# not rely on this API to provide extremely accurate search results. The
|
67
|
+
# result set is limited to a single page of results with a maximum size,
|
68
|
+
# so you won't be able to fetch large numbers of results.
|
69
|
+
#
|
70
|
+
# type - [Enum] The type of values the typeahead should return.
|
71
|
+
# Note that unlike in the names of endpoints, the types listed here are
|
72
|
+
# in singular form (e.g. `task`). Using multiple types is not yet supported.
|
73
|
+
#
|
74
|
+
# query - [String] The string that will be used to search for relevant objects. If an
|
75
|
+
# empty string is passed in, the API will currently return an empty
|
76
|
+
# result set.
|
77
|
+
#
|
78
|
+
# count - [Number] The number of results to return. The default is `20` if this
|
79
|
+
# parameter is omitted, with a minimum of `1` and a maximum of `100`.
|
80
|
+
# If there are fewer results found than requested, all will be returned.
|
81
|
+
#
|
82
|
+
# per_page - [Integer] the number of records to fetch per page.
|
83
|
+
# options - [Hash] the request I/O options.
|
84
|
+
def typeahead(type: required("type"), query: nil, count: nil, per_page: 20, options: {})
|
85
|
+
params = { type: type, query: query, count: count, limit: per_page }.reject { |_,v| v.nil? || Array(v).empty? }
|
86
|
+
Collection.new(parse(client.get("/workspaces/#{id}/typeahead", params: params, options: options)), type: Resource, client: client)
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,225 @@
|
|
1
|
+
<%
|
2
|
+
var singularName = resource.name,
|
3
|
+
pluralName = plural(singularName),
|
4
|
+
mixins = {
|
5
|
+
task: ["AttachmentUploading", "EventSubscription"],
|
6
|
+
project: ["EventSubscription"]
|
7
|
+
},
|
8
|
+
skip = { attachment: ["createOnTask"] },
|
9
|
+
formatComment = function formatComment(text, indentation) {
|
10
|
+
var indent = Array(indentation + 1).join(" ")
|
11
|
+
return text.trim().split("\n").map(function(line) {
|
12
|
+
return indent + (line.length > 0 ? "# " : "#") + line
|
13
|
+
}).join("\n")
|
14
|
+
}
|
15
|
+
|
16
|
+
|
17
|
+
function Action(action) {
|
18
|
+
var that = this
|
19
|
+
this.action = action
|
20
|
+
this.collection = action.collection == true
|
21
|
+
this.requiresData = action.method == "POST" || action.method == "PUT"
|
22
|
+
this.isInstanceAction = (action.method == "PUT" || action.method == "DELETE")
|
23
|
+
this.method = action.method
|
24
|
+
this.methodName = snake(action.name)
|
25
|
+
this.clientMethod = action.method.toLowerCase()
|
26
|
+
this.returnsUpdatedRecord = action.method == 'PUT' || action.comment.match(/Returns[a-z\W]+updated/) !== null
|
27
|
+
this.returnsNothing = action.comment.match(/Returns an empty/) !== null
|
28
|
+
|
29
|
+
// Params and idParams
|
30
|
+
var params = action.params || []
|
31
|
+
this.idParams = _.filter(params, function(p) { return p.type == "Id" })
|
32
|
+
|
33
|
+
// If it looks like an instance action but it's not, make it one
|
34
|
+
if (!this.isInstanceAction) {
|
35
|
+
var mainIdParam = _.find(this.idParams, function(p) { return p.name == singularName })
|
36
|
+
if (mainIdParam !== undefined && !action.name.match(/Id/)) {
|
37
|
+
this.isInstanceAction = true
|
38
|
+
this.mainIdParam = mainIdParam
|
39
|
+
}
|
40
|
+
}
|
41
|
+
|
42
|
+
if (this.idParams.length == 1 &&
|
43
|
+
action.path.match(/%d/) &&
|
44
|
+
(action.name.match(/Id/) || (this.isInstanceAction && this.mainIdParam == undefined))) {
|
45
|
+
var mainIdParam = this.idParams[0]
|
46
|
+
this.mainIdParam = mainIdParam
|
47
|
+
this.inferredReturnType = this.isInstanceAction ? 'self.class' : 'self'
|
48
|
+
}
|
49
|
+
|
50
|
+
if (mainIdParam !== undefined) {
|
51
|
+
this.params = _.reject(params, function(p) { return p.name == mainIdParam.name })
|
52
|
+
} else {
|
53
|
+
this.params = params
|
54
|
+
}
|
55
|
+
|
56
|
+
if (!this.inferredReturnType) {
|
57
|
+
// Infer return type
|
58
|
+
var name = action.path.match(/\/([a-zA-Z]+)$/)
|
59
|
+
if (name !== null) {
|
60
|
+
name = name[1]
|
61
|
+
|
62
|
+
// Desugarize 'addProject' to 'project'
|
63
|
+
var camelCaseTail = name.match(/.*([A-Z][a-z]+)$/)
|
64
|
+
if (camelCaseTail !== null) { name = decap(camelCaseTail[1]) }
|
65
|
+
|
66
|
+
name = single(name)
|
67
|
+
|
68
|
+
var explicit = _.find(resources, function(p) { return p == name })
|
69
|
+
|
70
|
+
if (name == singularName || name == 'parent' || name == 'children' || name.match(/^sub/) !== null) {
|
71
|
+
this.inferredReturnType = this.isInstanceAction ? 'self.class' : 'self'
|
72
|
+
} else if (explicit !== undefined) {
|
73
|
+
this.inferredReturnType = cap(explicit)
|
74
|
+
} else {
|
75
|
+
this.inferredReturnType = 'Resource'
|
76
|
+
}
|
77
|
+
} else {
|
78
|
+
this.inferredReturnType = 'Resource'
|
79
|
+
}
|
80
|
+
}
|
81
|
+
|
82
|
+
// Endpoint path
|
83
|
+
this.path = _.reduce(this.idParams, function(acc, id) {
|
84
|
+
var localName = that.mainIdParam == id ? "id" : id.name
|
85
|
+
return acc.replace("\%d", "#{" + localName + "}")
|
86
|
+
}, action.path)
|
87
|
+
|
88
|
+
// Extra params (not in the URL) to be passed in the body of the call
|
89
|
+
this.extraParams = _.reject(this.params, function(p) {
|
90
|
+
return that.path.match(new RegExp("#{" + p.name + "}"))
|
91
|
+
})
|
92
|
+
|
93
|
+
// Params processing
|
94
|
+
var paramsLocal = "data"
|
95
|
+
if (this.collection) { this.extraParams.push({ name: "per_page", apiParamName: "limit" }) }
|
96
|
+
if (this.extraParams.length > 0) {
|
97
|
+
var paramNames = _.map(this.extraParams, function(p) { return (p.apiParamName || p.name) + ": " + p.name })
|
98
|
+
if (this.requiresData) {
|
99
|
+
var paramsProcessing = "with_params = data.merge(" + paramNames.join(", ") + ")"
|
100
|
+
paramsLocal = "with_params"
|
101
|
+
} else {
|
102
|
+
var paramsProcessing = "params = { " + paramNames.join(", ") + " }"
|
103
|
+
paramsLocal = "params"
|
104
|
+
}
|
105
|
+
paramsProcessing += ".reject { |_,v| v.nil? || Array(v).empty? }"
|
106
|
+
}
|
107
|
+
|
108
|
+
this.paramsProcessing = paramsProcessing
|
109
|
+
this.paramsLocal = paramsLocal
|
110
|
+
|
111
|
+
// Method argument names
|
112
|
+
var argumentNames = Array()
|
113
|
+
if (!this.isInstanceAction) { argumentNames.push("client") }
|
114
|
+
if (this.mainIdParam !== undefined && !this.isInstanceAction) { argumentNames.push("id") }
|
115
|
+
_.forEach(this.params, function(param) {
|
116
|
+
argumentNames.push(param.name + ":" + (param.required ? " required(\"" + param.name + "\")" : " nil"))
|
117
|
+
})
|
118
|
+
if (this.collection) { argumentNames.push("per_page: 20") }
|
119
|
+
if (this.method != 'DELETE') { argumentNames.push("options: {}") }
|
120
|
+
if (this.requiresData) { argumentNames.push("**data") }
|
121
|
+
this.argumentNames = argumentNames
|
122
|
+
|
123
|
+
// API request params
|
124
|
+
var requestParams = Array()
|
125
|
+
requestParams.push('"' + this.path + '"')
|
126
|
+
if (this.paramsProcessing || this.argumentNames.indexOf("**data") != -1) {
|
127
|
+
var argument = this.requiresData ? "body" : "params"
|
128
|
+
requestParams.push(argument + ": " + paramsLocal)
|
129
|
+
}
|
130
|
+
if (this.method != 'DELETE') { requestParams.push("options: options") }
|
131
|
+
this.requestParams = requestParams
|
132
|
+
this.documentation = this.renderDocumentation()
|
133
|
+
|
134
|
+
// Constructor
|
135
|
+
this.constructor = function(body) {
|
136
|
+
var pre = '', post = ''
|
137
|
+
var wrapWithParsing = function(body) {
|
138
|
+
var pre = '', post = ''
|
139
|
+
if (!that.returnsNothing) {
|
140
|
+
pre = 'parse('
|
141
|
+
post = ')' + (that.collection ? '' : '.first')
|
142
|
+
}
|
143
|
+
return pre + body + post
|
144
|
+
}
|
145
|
+
|
146
|
+
if (!that.returnsNothing) {
|
147
|
+
if (that.isInstanceAction && that.returnsUpdatedRecord) {
|
148
|
+
pre = "refresh_with("
|
149
|
+
post = ')'
|
150
|
+
} else {
|
151
|
+
pre = that.collection ? "Collection.new(" : that.inferredReturnType + ".new("
|
152
|
+
post = (that.collection ? ', type: ' + that.inferredReturnType : '') + ', client: client)'
|
153
|
+
}
|
154
|
+
} else { post = ' && true' }
|
155
|
+
return pre + wrapWithParsing(body) + post
|
156
|
+
}
|
157
|
+
|
158
|
+
this.request = this.constructor("client." + this.clientMethod + "(" + this.requestParams.join(", ") + ")")
|
159
|
+
}
|
160
|
+
|
161
|
+
Action.prototype.renderDocumentation = function () {
|
162
|
+
var formatParamNotes = function(params) {
|
163
|
+
var trimmed = _.flatten(_.map(params, function(p) {
|
164
|
+
return _.map(p.notes, function(note) { return note.trim() })
|
165
|
+
}))
|
166
|
+
return (trimmed.length > 0 ? "\nNotes:\n\n" + trimmed.join("\n\n") : "")
|
167
|
+
}
|
168
|
+
|
169
|
+
var formatParam = function(p, name) {
|
170
|
+
return (name !== undefined ? name : p.name) + " - [" + p.type + "] " + p.comment
|
171
|
+
}
|
172
|
+
var lines = _.map(this.params, function(p) { return formatParam(p) })
|
173
|
+
if (this.mainIdParam !== undefined && !this.isInstanceAction) { lines.unshift(formatParam(this.mainIdParam, "id")) }
|
174
|
+
if (this.collection) { lines.push("per_page - [Integer] the number of records to fetch per page.") }
|
175
|
+
if (this.method != 'DELETE') { lines.push("options - [Hash] the request I/O options.") }
|
176
|
+
if (this.requiresData) { lines.push("data - [Hash] the attributes to post.") }
|
177
|
+
return this.action.comment + "\n" + lines.join("\n") + formatParamNotes(this.params)
|
178
|
+
}
|
179
|
+
|
180
|
+
var actionsToSkip = skip[resource.name] || []
|
181
|
+
var actionsToGen = _.reject(resource.actions, function(action) {
|
182
|
+
return actionsToSkip.indexOf(action.name) != -1
|
183
|
+
})
|
184
|
+
|
185
|
+
var allActions = _.map(actionsToGen, function(action) { return new Action(action) }),
|
186
|
+
instanceActions = _.filter(allActions, function(action) { return action.isInstanceAction }),
|
187
|
+
classActions = _.reject(allActions, function(action) { return action.isInstanceAction })
|
188
|
+
|
189
|
+
var mixinsToInclude = mixins[resource.name] || []
|
190
|
+
|
191
|
+
%>### WARNING: This file is auto-generated by the asana-api-meta repo. Do not
|
192
|
+
### edit it manually.
|
193
|
+
|
194
|
+
module Asana
|
195
|
+
module Resources
|
196
|
+
<%= formatComment(resource.comment, 4) %>
|
197
|
+
class <%= cap(singularName) %> < Resource
|
198
|
+
<% _.forEach(mixinsToInclude, function(mixin) { %>
|
199
|
+
include <%= mixin %>
|
200
|
+
<% }) %>
|
201
|
+
<% _.forEach(resource.properties, function(property) { %>
|
202
|
+
attr_reader :<%= property.name %>
|
203
|
+
<% }) %>
|
204
|
+
class << self
|
205
|
+
# Returns the plural name of the resource.
|
206
|
+
def plural_name
|
207
|
+
'<%= pluralName %>'
|
208
|
+
end
|
209
|
+
<% _.forEach(classActions, function(action) { %>
|
210
|
+
<%= formatComment(action.documentation, 8) %>
|
211
|
+
def <%= action.methodName %>(<%= action.argumentNames.join(", ") %>)
|
212
|
+
<% if (action.paramsProcessing) { %> <%= action.paramsProcessing %><% } %>
|
213
|
+
<%= action.request %>
|
214
|
+
end
|
215
|
+
<% }) %> end
|
216
|
+
<% _.forEach(instanceActions, function(action) { %>
|
217
|
+
<%= formatComment(action.documentation, 6) %>
|
218
|
+
def <%= action.methodName %>(<%= action.argumentNames.join(", ") %>)
|
219
|
+
<% if (action.paramsProcessing) { %> <%= action.paramsProcessing %><% } %>
|
220
|
+
<%= action.request %>
|
221
|
+
end
|
222
|
+
<% }) %>
|
223
|
+
end
|
224
|
+
end
|
225
|
+
end
|
data/openc-asana.gemspec
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'asana/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "openc-asana"
|
8
|
+
spec.version = Asana::VERSION
|
9
|
+
spec.authors = ["Txus"]
|
10
|
+
spec.email = ["me@txus.io"]
|
11
|
+
|
12
|
+
spec.summary = %q{Fork of Official Ruby client for the Asana API}
|
13
|
+
spec.description = %q{Fork of Official Ruby client for the Asana API}
|
14
|
+
spec.homepage = "https://github.com/openc/ruby-asana"
|
15
|
+
spec.license = "MIT"
|
16
|
+
|
17
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
18
|
+
spec.bindir = "exe"
|
19
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
20
|
+
spec.require_paths = ["lib"]
|
21
|
+
|
22
|
+
spec.required_ruby_version = '>= 2.0'
|
23
|
+
|
24
|
+
spec.add_dependency "oauth2", "~> 1.0"
|
25
|
+
spec.add_dependency "faraday", "~> 0.9"
|
26
|
+
spec.add_dependency "faraday_middleware", "~> 0.9"
|
27
|
+
spec.add_dependency "faraday_middleware-multi_json", "~> 0.0"
|
28
|
+
|
29
|
+
spec.add_development_dependency "bundler", "~> 1.7"
|
30
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
31
|
+
spec.add_development_dependency "rspec", "~> 3.2"
|
32
|
+
end
|