joshua 0.2.2 → 0.2.4

Sign up to get free protection for your applications and to get access to all the features.
data/lib/joshua/error.rb DELETED
@@ -1,61 +0,0 @@
1
- class Joshua
2
- class Error < StandardError
3
- end
4
-
5
- RESCUE_FROM = {}
6
-
7
- class << self
8
- # rescue_from CustomError do ...
9
- # for unhandled
10
- # rescue_from :all do
11
- # api.error 500, 'Error happens'
12
- # end
13
- # define handled error code and description
14
- # error :not_found, 'Document not found'
15
- # error 404, 'Document not found'
16
- # in api methods
17
- # error 404
18
- # error :not_found
19
- def rescue_from klass, desc=nil, &block
20
- RESCUE_FROM[klass] = desc || block
21
- end
22
-
23
- # show and render single error in class error format
24
- # usually when API class not found
25
- def error text
26
- out = Response.new nil
27
- out.error text
28
- out.render
29
- end
30
-
31
- def error_print error
32
- return if ENV['RACK_ENV'] == 'test'
33
-
34
- puts
35
- puts 'Joshua error dump'.red
36
- puts '---'
37
- puts '%s: %s' % [error.class, error.message]
38
- puts '---'
39
- puts error.backtrace
40
- puts '---'
41
- end
42
- end
43
-
44
- ###
45
-
46
- def error desc
47
- if err = RESCUE_FROM[desc]
48
- if err.is_a?(Proc)
49
- err.call
50
- else
51
- response.error desc, err
52
- desc = err
53
- end
54
-
55
- return
56
- end
57
-
58
- raise Joshua::Error, desc
59
- end
60
-
61
- end
data/lib/joshua/opts.rb DELETED
@@ -1,216 +0,0 @@
1
- class Joshua
2
- ANNOTATIONS ||= {}
3
- OPTS = {}
4
- PLUGINS = {}
5
- DOCUMENTED = []
6
-
7
- class << self
8
- @@params = Params::Define.new
9
-
10
- def base what
11
- set :opts, :base, what
12
- end
13
-
14
- # if you want to make API DOC public use "documented"
15
- def documented
16
- if self == Joshua
17
- DOCUMENTED.map(&:to_s).sort.map(&:constantize)
18
- else
19
- DOCUMENTED.push self unless DOCUMENTED.include?(self)
20
- end
21
- end
22
-
23
- def api_path
24
- to_s.underscore.sub(/_api$/, '')
25
- end
26
-
27
- # define method annotations
28
- # annotation :unsecure! do
29
- # @is_unsecure = true
30
- # end
31
- # unsecure!
32
- # def login
33
- # ...
34
- def annotation name, &block
35
- ANNOTATIONS[name] = block
36
- self.define_singleton_method name do |*args|
37
- @@params.add_annotation name, args
38
- end
39
- end
40
-
41
- # /api/companies/1/show
42
- def member &block
43
- @method_type = :member
44
- class_exec &block
45
- @method_type = nil
46
- end
47
-
48
- # /api/companies/list?countrty_id=1
49
- def collection &block
50
- @method_type = :collection
51
- class_exec &block
52
- @method_type = nil
53
- end
54
-
55
- # There are multiple ways to create params
56
- # params :name, String, req: true
57
- # params.name!, String
58
- # params do
59
- # name String, required: true
60
- # name! String
61
- # end
62
- # params :label do |value, opts|
63
- # # validate is value a label, return coarced label
64
- # # or raise error with error
65
- # end
66
- def params *args, &block
67
- if name = args.first
68
- if block
69
- # if argument is provided we create a validator
70
- Params::Parse.define name, &block
71
- else
72
- only_in_api_methods!
73
- @@params.send *args
74
- end
75
- elsif block
76
- @@params.instance_eval &block
77
- else
78
- only_in_api_methods!
79
- @@params
80
- end
81
- end
82
-
83
- # api method icon
84
- # you can find great icons at https://boxicons.com/ - export to svg
85
- def icon data
86
- if @method_type
87
- raise ArgumentError.new('Icons cant be added on methods')
88
- else
89
- set :opts, :icon, data
90
- end
91
- end
92
-
93
- # api method description
94
- def desc data
95
- if @method_type
96
- @@params.add_generic :desc, data
97
- else
98
- set :opts, :desc, data
99
- end
100
- end
101
-
102
- # api method detailed description
103
- def detail data
104
- return if data.to_s == ''
105
-
106
- if @method_type
107
- @@params.add_generic :detail, data
108
- else
109
- set :opts, :detail, data
110
- end
111
- end
112
-
113
- # method in available for GET requests as well
114
- def gettable
115
- if @method_type
116
- @@params.add_generic :gettable
117
- else
118
- raise ArgumentError.new('gettable can only be set on methods')
119
- end
120
- end
121
-
122
- # allow methods without @api.bearer token set
123
- def unsafe
124
- if @method_type
125
- @@params.add_generic :unsafe
126
- else
127
- raise ArgumentError.new('Only api methods can be unsafe')
128
- end
129
- end
130
-
131
- # all api methods are secure (require bearer token)
132
- def unsecure
133
-
134
- end
135
-
136
- # block execute before any public method or just some member or collection methods
137
- def before &block
138
- set_callback :before, block
139
- end
140
-
141
- # block execute after any public method or just some member or collection methods
142
- # used to add meta tags to response
143
- def after &block
144
- set_callback :after, block
145
- end
146
-
147
- # simplified module include, masked as plugin
148
- # Joshua.plugin :foo do ...
149
- # Joshua.plugin :foo
150
- def plugin name, &block
151
- if block_given?
152
- # if block given, define a plugin
153
- PLUGINS[name] = block
154
- else
155
- # without a block execute it
156
- blk = PLUGINS[name]
157
- raise ArgumentError.new('Plugin :%s not defined' % name) unless blk
158
- instance_exec &blk
159
- end
160
- end
161
-
162
- def get *args
163
- opts.dig *args
164
- end
165
-
166
- # dig all options for a current class
167
- def opts
168
- out = {}
169
-
170
- # dig down the ancestors tree till Object class
171
- ancestors.each do |klass|
172
- break if klass == Object
173
-
174
- # copy all member and collection method options
175
- keys = (OPTS[klass.to_s] || {}).keys
176
- keys.each do |type|
177
- for k, v in (OPTS.dig(klass.to_s, type) || {})
178
- out[type] ||= {}
179
- out[type][k] ||= v
180
- end
181
- end
182
- end
183
-
184
- out
185
- end
186
-
187
- # here we capture member & collection metods
188
- def method_added name
189
- return if name.to_s.start_with?('_api_')
190
- return unless @method_type
191
-
192
- set @method_type, name, @@params.fetch_and_clear_opts
193
-
194
- alias_method "_api_#{@method_type}_#{name}", name
195
- remove_method name
196
- end
197
-
198
- private
199
-
200
- # generic opts set
201
- # set :foo, :bar, :baz
202
- def set *args
203
- name, value = args.pop(2)
204
- args.unshift to_s
205
- pointer = OPTS
206
-
207
- for el in args
208
- pointer[el] ||= {}
209
- pointer = pointer[el]
210
- end
211
-
212
- pointer[name] = value
213
- end
214
- end
215
- end
216
-
@@ -1,53 +0,0 @@
1
- class Joshua
2
- module Params
3
- class Define
4
- def initialize
5
- @opts = { }
6
- end
7
-
8
- def method_missing name, *args
9
- name = name.to_s
10
-
11
- raise ArgumentError.new('! is not allowed in params') if name.include?('!')
12
-
13
- type, opts = args
14
-
15
- if type.is_a?(Hash)
16
- opts = args.first
17
- type = :string
18
- end
19
-
20
- type = :string if type.nil?
21
-
22
- opts ||= {}
23
- opts[:type] = type.to_s.dasherize.downcase.to_sym
24
-
25
- opts[:required] = true if opts[:required].nil?
26
- opts[:required] = false if name.sub! /\?$/, ''
27
- opts[:required] = false if opts.delete(:optional)
28
-
29
- opts.merge!(type: :boolean, default: false) if opts[:type] == :false
30
- opts.merge!(type: :boolean, default: true) if opts[:type] == :true
31
- opts[:required] = false if opts[:type] == :boolean
32
-
33
- @opts[:params] ||= {}
34
- @opts[:params][name.to_sym] = opts
35
- end
36
-
37
- def fetch_and_clear_opts
38
- @opts
39
- .dup
40
- .tap { @opts = {} }
41
- end
42
-
43
- def add_generic name, value=true
44
- @opts[name] = value
45
- end
46
-
47
- def add_annotation name, data
48
- @opts[:annotations] ||= {}
49
- @opts[:annotations][name] = data
50
- end
51
- end
52
- end
53
- end
@@ -1,56 +0,0 @@
1
- class Joshua
2
- module Params
3
- class Parse
4
- class << self
5
- def define name, &block
6
- define_method 'check_%s' % name do |value, opts|
7
- block.call value, opts || {}
8
- end
9
- end
10
- end
11
-
12
- ###
13
-
14
- # check :boolean, 'on'
15
- def check type, value, opts={}
16
- opts[:required] = true if opts.delete(:req)
17
-
18
- if value.to_s == ''
19
- if !opts[:default].nil?
20
- opts[:default]
21
- elsif opts[:required]
22
- error 'Argument missing'
23
- end
24
- else
25
- m = 'check_%s' % type
26
- hard_error 'Unsupported paramter type: %s' % type unless respond_to?(m)
27
-
28
- if opts[:array]
29
- delimiter = opts[:array].is_a?(TrueClass) ? /\s*[,:;]\s*/ : opts[:array]
30
-
31
- value = value.split(delimiter) unless value.is_a?(Array)
32
- value.map { |_| check_send m, _, opts }
33
- else
34
- check_send m, value, opts
35
- end
36
- end
37
- end
38
-
39
- private
40
-
41
- def check_send m, value, opts
42
- send(m, value, opts).tap do |_|
43
- error 'Value not in range of values' if opts[:values] && !opts[:values].include?(_)
44
- end
45
- end
46
-
47
- def error desc
48
- raise Joshua::Error, desc
49
- end
50
-
51
- def hard_error desc
52
- raise StandardError, desc
53
- end
54
- end
55
- end
56
- end
@@ -1,152 +0,0 @@
1
- require 'date'
2
-
3
- class Joshua
4
- module Params
5
- class Parse
6
- # params.is_active :boolean, default: false
7
- def check_boolean value, opts={}
8
- return false unless value
9
-
10
- if %w(true 1 on).include?(value.to_s)
11
- true
12
- elsif %w(false 0 off).include?(value.to_s)
13
- false
14
- else
15
- error 'Unsupported boolean param value: %s' % value
16
- end
17
- end
18
-
19
- def check_integer value, opts={}
20
- value.to_i.tap do |test|
21
- error localized(:not_integer) if test.to_s != value.to_s
22
- error localized(:min_value) % opts[:min] if opts[:min] && test < opts[:min]
23
- error localized(:max_value) % opts[:max] if opts[:max] && test > opts[:max]
24
- end
25
- end
26
-
27
- def check_string value, opts={}
28
- value
29
- .to_s
30
- .sub(/^\s+/, '')
31
- .sub(/\s+$/, '')
32
- end
33
-
34
- def check_float value, opts={}
35
- value =
36
- if opts[:round]
37
- value.to_f.round(opts[:round])
38
- else
39
- value.to_f
40
- end
41
-
42
- error localized(:min_value) % opts[:min] if opts[:min] && value < opts[:min]
43
- error localized(:max_value) % opts[:max] if opts[:max] && value > opts[:max]
44
-
45
- value
46
- end
47
-
48
- def check_date value, opts={}
49
- date = DateTime.parse(value)
50
- date = DateTime.new(date.year, date.month, date.day)
51
-
52
- check_date_min_max date, opts
53
- end
54
-
55
- def check_date_time value, opts={}
56
- date = DateTime.parse(value)
57
- check_date_min_max date, opts
58
- end
59
-
60
- def check_hash value, opts={}
61
- value = {} unless value.is_a?(Hash)
62
-
63
- if opts[:allow]
64
- for key in value.keys
65
- value.delete(key) unless opts[:allow].include?(key)
66
- end
67
- end
68
-
69
- value
70
- end
71
-
72
- def check_email email, opts={}
73
- error localized(:email_min) unless email.to_s.length > 7
74
- error localized(:email_missing) unless email.include?('@')
75
- email.downcase
76
- end
77
-
78
- def check_url url
79
- error localized(:url_start) unless url =~ /^https?:\/\/./
80
- url
81
- end
82
-
83
- # geolocation point. google maps url will be automaticly converted
84
- # https://www.google.com/maps/@51.5254742,-0.1057319,13z
85
- def check_point value, opts={}
86
- parts = value.split(/\s*,\s*/) unless parts.is_a?(Array)
87
-
88
- error localized(:point_format) unless parts[1]
89
-
90
- for part in parts
91
- error localized(:point_format) unless part.include?('.')
92
- error localized(:point_format) unless part.length > 5
93
- end
94
-
95
- parts.join(',')
96
- end
97
-
98
- def check_oib oib, opts={}
99
- oib = oib.to_s
100
-
101
- return false unless oib.match(/^[0-9]{11}$/)
102
-
103
- control_sum = (0..9).inject(10) do |middle, position|
104
- middle += oib.at(position).to_i
105
- middle %= 10
106
- middle = 10 if middle == 0
107
- middle *= 2
108
- middle %= 11
109
- end
110
-
111
- control_sum = 11 - control_sum
112
- control_sum = 0 if control_sum == 10
113
-
114
- if control_sum == oib.at(10).to_i
115
- oib.to_i
116
- else
117
- error 'Wrong OIB'
118
- end
119
- end
120
-
121
- private
122
-
123
- def check_date_min_max value, opts={}
124
- if min = opts[:min]
125
- min = DateTime.parse(min)
126
- error localized(:min_date) % min if min > value
127
- end
128
-
129
- if max = opts[:max]
130
- max = DateTime.parse(max)
131
- error localized(:max_date) % max if value > max
132
- end
133
-
134
- value
135
- end
136
-
137
- def localized error
138
- locale =
139
- if defined?(Lux)
140
- Lux.current.locale.to_s
141
- elsif defined?(I18n)
142
- I18n.with_locale || I18n.locale
143
- else
144
- :en
145
- end
146
-
147
- pointer = ERRORS[locale.to_sym] || ERRORS[:en]
148
- pointer[error]
149
- end
150
- end
151
- end
152
- end