haveapi 0.22.0 → 0.23.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 321e49887ffa5dc763ebc2eb535ee04c5776fc5bcec813feadc0444da1736d9c
4
- data.tar.gz: e8b1045190e92e6bf38843c3c96be69d66b48490ace40655c3e31721169ce4d4
3
+ metadata.gz: 6c66cdf4f10a5d8d65b70c4d934cd4ab98b96d89fd5af283cdd1d0cd21cbb4b8
4
+ data.tar.gz: d3beeb71e1da7049735864c44e76abdd512fe22fbec0df056d10f2f0ad9dc409
5
5
  SHA512:
6
- metadata.gz: 2231a352ccd0e78268b164aa70613fa369462bc9bcaf2bc0fef51d088107c38c78bd43bf26fa01815afadb9ebc9af3c8cd7deae057c80b0b92ad15d75ca8e423
7
- data.tar.gz: f736a80afa224ae0c0d687472ad2754660f877a26a3c02b111101d3004c1875c7c3d6927682ee582aef587f98f269a976b33920c738868a516e264b3a66fa4a3
6
+ metadata.gz: a139c2b9bfc85f476a77c8e113d8e9d769dc505261028d807a4804dc108e1dee07dfa65f54220988b28bc78d4893fde0cbad37fee9e0eae01d697a3c58719b88
7
+ data.tar.gz: 18525da72a705a5bd8f955b5597f87035bde722fe3520abd2db09e6fac9066cb01eafffb39dbc1f480504568b60852388144e4245861a3d2d2590ba69f7eb790
data/haveapi.gemspec CHANGED
@@ -16,7 +16,7 @@ Gem::Specification.new do |s|
16
16
 
17
17
  s.add_runtime_dependency 'activesupport', '>= 7.1'
18
18
  s.add_runtime_dependency 'github-markdown'
19
- s.add_runtime_dependency 'haveapi-client', '~> 0.22.0'
19
+ s.add_runtime_dependency 'haveapi-client', '~> 0.23.0'
20
20
  s.add_runtime_dependency 'json'
21
21
  s.add_runtime_dependency 'mail'
22
22
  s.add_runtime_dependency 'nesty', '~> 1.0'
@@ -147,15 +147,12 @@ module HaveAPI::ClientExamples
147
147
  end
148
148
 
149
149
  def format_parameters(dir, params, prefix = '')
150
- ret = []
151
-
152
- params.each do |k, v|
153
- ret << if action[dir][:parameters][k][:type] == 'Custom'
154
- "#{prefix} \"#{k}\" => custom type}"
155
-
156
- else
157
- "#{prefix} \"#{k}\" => #{value(v)}"
158
- end
150
+ ret = params.map do |k, v|
151
+ if action[dir][:parameters][k][:type] == 'Custom'
152
+ "#{prefix} \"#{k}\" => custom type}"
153
+ else
154
+ "#{prefix} \"#{k}\" => #{value(v)}"
155
+ end
159
156
  end
160
157
 
161
158
  "#{prefix}[\n#{ret.join(",\n")}\n#{prefix}]"
@@ -80,7 +80,7 @@ module HaveAPI::ClientExamples
80
80
  out << "# reply is an instance of HaveAPI::Client::ResourceInstance\n"
81
81
 
82
82
  (sample[:response] || {}).each do |pn, pv|
83
- param = action[:output][:parameters][k]
83
+ param = action[:output][:parameters][pn]
84
84
 
85
85
  if param[:type] == 'Resource'
86
86
  out << "# reply.#{pn} = HaveAPI::Client::ResourceInstance("
@@ -116,7 +116,7 @@ module HaveAPI
116
116
  cls
117
117
  end
118
118
 
119
- def self.define_action(name, superclass: Action, &block)
119
+ def self.define_action(name, superclass: Action, &)
120
120
  return false if const_defined?(name)
121
121
 
122
122
  cls = Class.new(superclass)
@@ -124,7 +124,7 @@ module HaveAPI
124
124
  cls.resource = self
125
125
  cls.action_name = name
126
126
  superclass.delayed_inherited(cls)
127
- cls.class_exec(&block)
127
+ cls.class_exec(&)
128
128
  end
129
129
  end
130
130
  end
@@ -61,7 +61,6 @@ module HaveAPI::Resources
61
61
  authorize { allow }
62
62
 
63
63
  def exec
64
- ret = []
65
64
  actions = @context.server.action_state.list_pending(
66
65
  current_user,
67
66
  input[:offset],
@@ -69,11 +68,9 @@ module HaveAPI::Resources
69
68
  input[:order].to_sym
70
69
  )
71
70
 
72
- actions.each do |state|
73
- ret << state_to_hash(state)
71
+ actions.map do |state|
72
+ state_to_hash(state)
74
73
  end
75
-
76
- ret
77
74
  end
78
75
  end
79
76
 
@@ -11,6 +11,20 @@ module HaveAPI
11
11
 
12
12
  include Hookable
13
13
 
14
+ has_hook :pre_mount,
15
+ desc: 'Called before API actions are mounted in sinatra',
16
+ args: {
17
+ server: 'HaveAPI::Server',
18
+ sinatra: 'Sinatra::Base'
19
+ }
20
+
21
+ has_hook :post_mount,
22
+ desc: 'Called after API actions are mounted in sinatra',
23
+ args: {
24
+ server: 'HaveAPI::Server',
25
+ sinatra: 'Sinatra::Base'
26
+ }
27
+
14
28
  # Called after the user was authenticated (or not). The block is passed
15
29
  # current user object or nil as an argument.
16
30
  has_hook :post_authenticated,
@@ -339,12 +353,16 @@ module HaveAPI
339
353
 
340
354
  @extensions.each { |e| e.enabled(self) }
341
355
 
356
+ call_hooks_for(:pre_mount, args: [self, @sinatra])
357
+
342
358
  # Mount default version first
343
359
  mount_version(@root, @default_version)
344
360
 
345
361
  @versions.each do |v|
346
362
  mount_version(version_prefix(v), v)
347
363
  end
364
+
365
+ call_hooks_for(:post_mount, args: [self, @sinatra])
348
366
  end
349
367
 
350
368
  def mount_version(prefix, v)
@@ -8,7 +8,7 @@ module HaveAPI::Spec
8
8
  @v = v
9
9
  end
10
10
 
11
- def call(input, user: nil, &block)
11
+ def call(input, user: nil, &)
12
12
  action = @action.new(nil, @v, input, nil, HaveAPI::Context.new(
13
13
  @server,
14
14
  version: @v,
@@ -26,7 +26,7 @@ module HaveAPI::Spec
26
26
  status, data, errors = action.safe_exec
27
27
  raise(data || 'action failed') unless status
28
28
 
29
- action.instance_exec(@test, &block)
29
+ action.instance_exec(@test, &)
30
30
  data
31
31
  end
32
32
  end
@@ -74,12 +74,12 @@ module HaveAPI::Spec
74
74
  # @param version [any] API version, if not specified, the default version is used
75
75
  # @param user [any] object representing authenticated user
76
76
  # @yield [self] the block is executed in the action instance
77
- def mock_action(r_name, a_name, params, version: nil, user: nil, &block)
77
+ def mock_action(r_name, a_name, params, version: nil, user: nil, &)
78
78
  app
79
79
  v = version || @api.default_version
80
80
  action, path = find_action(v, r_name, a_name)
81
81
  m = MockAction.new(self, @api, action, path, v)
82
- m.call(params, user:, &block)
82
+ m.call(params, user:, &)
83
83
  end
84
84
 
85
85
  # Return parsed API response.
@@ -1,4 +1,4 @@
1
1
  module HaveAPI
2
2
  PROTOCOL_VERSION = '2.0'.freeze
3
- VERSION = '0.22.0'.freeze
3
+ VERSION = '0.23.0'.freeze
4
4
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: haveapi
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.22.0
4
+ version: 0.23.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jakub Skokan
@@ -44,14 +44,14 @@ dependencies:
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: 0.22.0
47
+ version: 0.23.0
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: 0.22.0
54
+ version: 0.23.0
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: json
57
57
  requirement: !ruby/object:Gem::Requirement
@@ -204,13 +204,8 @@ files:
204
204
  - LICENSE.txt
205
205
  - README.md
206
206
  - Rakefile
207
- - doc/Hooks.md
208
- - doc/create-client.md
209
207
  - doc/hooks.erb
210
208
  - doc/index.md
211
- - doc/json-schema.html
212
- - doc/protocol.md
213
- - doc/protocol.png
214
209
  - haveapi.gemspec
215
210
  - lib/haveapi.rb
216
211
  - lib/haveapi/action.rb
data/doc/Hooks.md DELETED
@@ -1,81 +0,0 @@
1
-
2
- # Hooks
3
-
4
- ##HaveAPI::Server
5
-
6
- ### post_authenticated
7
- <table>
8
- <tr>
9
- <td style="vertical-align: top;">Description:</td>
10
- <td>Called after the user was authenticated</td>
11
- </tr>
12
- <tr>
13
- <td style="vertical-align: top;">Context:</td>
14
- <td>current</td>
15
- </tr>
16
- <tr>
17
- <td style="vertical-align: top;">Arguments:</td>
18
- <td><dl><dt>current_user</dt><dd>object returned by the authentication backend</dd></dl></td>
19
- </tr>
20
- <tr>
21
- <td style="vertical-align: top;">Initial value:</td>
22
- <td>none</td>
23
- </tr>
24
- <tr>
25
- <td style="vertical-align: top;">Return value:</td>
26
- <td>none</td>
27
- </tr>
28
- </table>
29
-
30
- ### description_exception
31
- <table>
32
- <tr>
33
- <td style="vertical-align: top;">Description:</td>
34
- <td>Called when an exception occurs when building self-description</td>
35
- </tr>
36
- <tr>
37
- <td style="vertical-align: top;">Context:</td>
38
- <td>current</td>
39
- </tr>
40
- <tr>
41
- <td style="vertical-align: top;">Arguments:</td>
42
- <td><dl><dt>context</dt><dd>HaveAPI::Context</dd><dt>exception</dt><dd>exception instance</dd></dl></td>
43
- </tr>
44
- <tr>
45
- <td style="vertical-align: top;">Initial value:</td>
46
- <td>none</td>
47
- </tr>
48
- <tr>
49
- <td style="vertical-align: top;">Return value:</td>
50
- <td><dl><dt>http_status</dt><dd>HTTP status code to send to client</dd><dt>message</dt><dd>error message sent to the client</dd></dl></td>
51
- </tr>
52
- </table>
53
-
54
-
55
- ##HaveAPI::Action
56
-
57
- ### exec_exception
58
- <table>
59
- <tr>
60
- <td style="vertical-align: top;">Description:</td>
61
- <td>Called when unhandled exceptions occurs during Action.exec</td>
62
- </tr>
63
- <tr>
64
- <td style="vertical-align: top;">Context:</td>
65
- <td>current</td>
66
- </tr>
67
- <tr>
68
- <td style="vertical-align: top;">Arguments:</td>
69
- <td><dl><dt>action</dt><dd>HaveAPI::Action instance</dd><dt>exception</dt><dd>exception instance</dd></dl></td>
70
- </tr>
71
- <tr>
72
- <td style="vertical-align: top;">Initial value:</td>
73
- <td>none</td>
74
- </tr>
75
- <tr>
76
- <td style="vertical-align: top;">Return value:</td>
77
- <td><dl><dt>status</dt><dd>true or false, indicating whether error should be reported</dd><dt>message</dt><dd>error message sent to the user</dd></dl></td>
78
- </tr>
79
- </table>
80
-
81
-
data/doc/create-client.md DELETED
@@ -1,107 +0,0 @@
1
- # Client definition
2
- It is necessary to differentiate between clients for HaveAPI based APIs
3
- and clients to work with your API instance. This document describes
4
- the former. If you only want to use your API, you should check a list
5
- of available clients and pick the one in the right language. Only when
6
- there isn't a client already available in the language you want, then
7
- continue reading.
8
-
9
- # Design rules
10
- The client must completely depend on the API description:
11
-
12
- - it has no assumptions and API-specific code,
13
- - it does not know any resources, actions and parameters,
14
- - everything the client knows must be found out from the API description.
15
-
16
- All clients should use a similar paradigm, so that it is possible to use
17
- clients in different languages in the same way, as far as the language syntax
18
- allows. Clients bundled with HaveAPI may serve as a model. A client should
19
- use all the advantages and coding styles of the language it is written
20
- in (e.g. use objects in object oriented languages).
21
-
22
- A model paradigm (in no particular language):
23
-
24
- // Create client instance
25
- api = new HaveAPI.Client("https://your.api.tld")
26
-
27
- // Authenticate
28
- api.authenticate("basic", {"user": "yourname", "password": "yourpassword"})
29
-
30
- // Access resources and actions
31
- api.<resource>.<action>( { <parameters> } )
32
- api.user.new({"name": "Very Name", "password": "donottellanyone"})
33
- api.user.list()
34
- api.nested.resource.deep.list()
35
-
36
- // Pass IDs to resources
37
- api.nested(1).resource(2).deep.list()
38
-
39
- // Object-like access
40
- user = api.user.show(1)
41
- user.id
42
- user.name
43
- user.destroy()
44
-
45
- // Logout
46
- api.logout()
47
-
48
- # Necessary features to implement
49
- A client should implement all of the listed features in order to be useful.
50
-
51
- ## Resource tree
52
- The client gives access to all listed resources and their actions.
53
-
54
- In scripting languages, resources and actions are usually defined as dynamic
55
- properties/objects/methods, depending on the language.
56
-
57
- ## Input/output parameters
58
- Allow sending input parameters and accessing the response.
59
-
60
- ## Input/output formats
61
- A client must send appropriate HTTP header `Accept`. As only JSON is by now built-in
62
- in HaveAPI, it should send `application/json`.
63
-
64
- ## Authentication
65
- All authentication methods that are built-in the HaveAPI should be supported
66
- if possible. The client should choose suitable authentication method
67
- for its purpose and allow the developer to select the authentication method
68
- if it makes sense to do so.
69
-
70
- It is a good practise to implement authentication methods as plugins,
71
- so that developers may add custom authentication providers easily.
72
-
73
- ## Object-like access
74
- A client must interpret the API response according to action output layout.
75
- Layouts `object` and `object_list` should be handled as object instances,
76
- if the language allows it.
77
-
78
- Object instances represent the object fetched from the database. Received
79
- parameters are accessed via object attributes/properties. Actions are defined
80
- as instance methods. Objects may have associations to other resources which
81
- must be made available and be easy to access.
82
-
83
- # Supplemental features
84
- Following features are supplemental. It is good to support them,
85
- but is not necessary.
86
-
87
- ## Client-side validations
88
- Client may make use of described validators and validate the input before
89
- sending it to the API, to lessen the API load and make it more user-friendly.
90
-
91
- However, as the input is validated on the server anyway, it does not have
92
- to be implemented.
93
-
94
- ## Metadata channel
95
- Metadata channel is currently used to specify what associated resources should
96
- be prefetched and whether an object list should contain total number of items.
97
-
98
- Metadata is nothing more than a hash in input parameters under key `_meta`.
99
-
100
- ## Blocking actions
101
- Useful for APIs with long-running actions. Clients can check state of such actions
102
- using resource `ActionState`. Because this resource is automatically present in all
103
- APIs that use blocking actions, client libraries expose this resource to the developer
104
- just as any other resource in the API.
105
-
106
- However, you may wish to integrate it in your client and provide ways for the action
107
- call to block/accept callbacks.