apiway 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/Gemfile +3 -0
- data/LICENSE.txt +22 -0
- data/README.md +1 -0
- data/Rakefile +0 -0
- data/bin/apiway +13 -0
- data/lib/apiway/application.rb +53 -0
- data/lib/apiway/client.rb +171 -0
- data/lib/apiway/commands.rb +62 -0
- data/lib/apiway/controller.rb +124 -0
- data/lib/apiway/diff.rb +84 -0
- data/lib/apiway/errors.rb +62 -0
- data/lib/apiway/events.rb +23 -0
- data/lib/apiway/extensions.rb +29 -0
- data/lib/apiway/generator.rb +111 -0
- data/lib/apiway/logger.rb +41 -0
- data/lib/apiway/model.rb +58 -0
- data/lib/apiway/path.rb +7 -0
- data/lib/apiway/resource.rb +110 -0
- data/lib/apiway/version.rb +5 -0
- data/lib/apiway.rb +17 -0
- data/lib/generator/application/.gitignore +1 -0
- data/lib/generator/application/Gemfile +9 -0
- data/lib/generator/application/Procfile +1 -0
- data/lib/generator/application/README.md +0 -0
- data/lib/generator/application/Rakefile +3 -0
- data/lib/generator/application/app/base/.keep +0 -0
- data/lib/generator/application/app/base/base.rb +5 -0
- data/lib/generator/application/app/base/client.rb +21 -0
- data/lib/generator/application/app/base/routes.rb +11 -0
- data/lib/generator/application/app/controllers/.keep +0 -0
- data/lib/generator/application/app/controllers/application.rb +5 -0
- data/lib/generator/application/app/models/.keep +0 -0
- data/lib/generator/application/app/resources/.keep +0 -0
- data/lib/generator/application/app/resources/application.rb +5 -0
- data/lib/generator/application/config/application.rb +13 -0
- data/lib/generator/application/config/database.yml +17 -0
- data/lib/generator/application/config/environments/development.rb +9 -0
- data/lib/generator/application/config/environments/production.rb +9 -0
- data/lib/generator/application/config/environments/test.rb +10 -0
- data/lib/generator/application/config.ru +3 -0
- data/lib/generator/application/db/migrate/.keep +0 -0
- data/lib/generator/application/lib/.keep +0 -0
- data/lib/generator/application/public/.keep +0 -0
- data/lib/generator/templates/controller.tpl +22 -0
- data/lib/generator/templates/model.tpl +5 -0
- data/lib/generator/templates/resource.tpl +29 -0
- metadata +174 -0
@@ -0,0 +1,111 @@
|
|
1
|
+
module Apiway
|
2
|
+
|
3
|
+
module Generator
|
4
|
+
|
5
|
+
|
6
|
+
class << self
|
7
|
+
|
8
|
+
HANDLERS = {
|
9
|
+
create_application: [ '-a', 'a', 'app' ],
|
10
|
+
create_controller: [ '-c', 'c', 'controller' ],
|
11
|
+
create_resource: [ '-r', 'r', 'resource' ],
|
12
|
+
create_model: [ '-m', 'm', 'model' ],
|
13
|
+
help: [ '-h', 'h', 'help' ]
|
14
|
+
}
|
15
|
+
|
16
|
+
DESC = {
|
17
|
+
create_application: 'Creating a new application (`apiway generate app Chat`)',
|
18
|
+
create_controller: 'Creating a new controller (`apiway generate controller Messages`)',
|
19
|
+
create_resource: 'Creating a new resource (`apiway generate resource Messages`)',
|
20
|
+
create_model: 'Creating a new model (`apiway generate model Message`)',
|
21
|
+
help: 'Show list of generator commands'
|
22
|
+
}
|
23
|
+
|
24
|
+
def run( command = nil, *args )
|
25
|
+
return help unless command
|
26
|
+
HANDLERS.each { |handler, commands| return send( handler, *args ) if commands.include? command }
|
27
|
+
puts "Apiway: Unknown generate command `#{ args.unshift( command ).join " " }`"
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def create_application( name = nil )
|
34
|
+
check_name( 'application', name ) do
|
35
|
+
source = File.join Apiway.path, 'generator/application'
|
36
|
+
target = File.join Dir.pwd, name
|
37
|
+
FileUtils.cp_r source, target
|
38
|
+
puts "Apiway: Application `#{ name }` created"
|
39
|
+
puts "Installing gems"
|
40
|
+
exec "cd #{ name } && bundle install"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def create_controller( name = nil )
|
45
|
+
check_name( 'controller', name ) do
|
46
|
+
in_root_folder do
|
47
|
+
filename = name.underscore
|
48
|
+
classname = filename.camelize
|
49
|
+
write "app/controllers/#{ filename }.rb", render( 'controller', classname )
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def create_resource( name = nil )
|
55
|
+
check_name( 'resource', name ) do
|
56
|
+
in_root_folder do
|
57
|
+
filename = name.underscore
|
58
|
+
classname = filename.camelize
|
59
|
+
write "app/resources/#{ filename }.rb", render( 'resource', classname )
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def create_model( name = nil )
|
65
|
+
check_name( 'model', name ) do
|
66
|
+
in_root_folder do
|
67
|
+
if name.scan( '_' ).size > 0
|
68
|
+
puts 'Apiway: Please do not use an underscore'
|
69
|
+
else
|
70
|
+
filename = name.downcase
|
71
|
+
classname = name.camelize
|
72
|
+
write "app/models/#{ filename }.rb", render( 'model', classname )
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def help( *args )
|
79
|
+
puts "\n Apiway generator commands: \n\n"
|
80
|
+
HANDLERS.each do |handler, commands|
|
81
|
+
puts " [#{ commands.join( "], [" ) }]".ljust(30) << "# #{ DESC[ handler ] } "
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def check_name( type, name )
|
86
|
+
if name then yield
|
87
|
+
else puts "Apiway: Enter a name of #{ type }" end
|
88
|
+
end
|
89
|
+
|
90
|
+
def in_root_folder
|
91
|
+
if Dir.exists?( File.join( Dir.pwd, 'app' ) ) then yield
|
92
|
+
else puts 'Apiway: Please go to application root folder' end
|
93
|
+
end
|
94
|
+
|
95
|
+
def render( name, classname )
|
96
|
+
modelname = classname.chomp 's'
|
97
|
+
varname = modelname.downcase
|
98
|
+
ERB.new( File.read( File.join( Apiway.path, 'generator/templates', "#{ name }.tpl" ) ) ).result binding
|
99
|
+
end
|
100
|
+
|
101
|
+
def write( path, content )
|
102
|
+
File.open( File.join( Dir.pwd, path ), 'w' ) { |file| file.write( content ) }
|
103
|
+
puts "Apiway: Created: #{ path }"
|
104
|
+
end
|
105
|
+
|
106
|
+
end
|
107
|
+
|
108
|
+
|
109
|
+
end
|
110
|
+
|
111
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Apiway
|
2
|
+
|
3
|
+
module LoggerBase
|
4
|
+
|
5
|
+
|
6
|
+
class << self
|
7
|
+
|
8
|
+
def apiway_log_level( level )
|
9
|
+
set_log_level( Log, level || :unknown )
|
10
|
+
end
|
11
|
+
|
12
|
+
def activerecord_log_level( level )
|
13
|
+
ActiveRecord::Base.logger = level ? set_log_level( new_logger, level ) : false
|
14
|
+
end
|
15
|
+
|
16
|
+
def new_logger
|
17
|
+
logger = Logger.new STDOUT
|
18
|
+
logger.formatter = proc do |severity, datetime, progname, msg|
|
19
|
+
"#{ datetime.strftime( "%H:%M:%S" ) } - #{ severity }> #{ msg }\n"
|
20
|
+
end
|
21
|
+
logger
|
22
|
+
end
|
23
|
+
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def set_log_level( logger, level )
|
28
|
+
logger.level = Logger.const_get level.to_s.upcase
|
29
|
+
logger
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
|
38
|
+
Log = LoggerBase::new_logger
|
39
|
+
|
40
|
+
|
41
|
+
end
|
data/lib/apiway/model.rb
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
module Apiway
|
2
|
+
|
3
|
+
module Model
|
4
|
+
|
5
|
+
|
6
|
+
|
7
|
+
class << self
|
8
|
+
|
9
|
+
def included( base )
|
10
|
+
all << base
|
11
|
+
base.class_eval do
|
12
|
+
extend ClassMethods
|
13
|
+
include InstanceMethods
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def all
|
18
|
+
@all ||= []
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
|
24
|
+
|
25
|
+
module ClassMethods
|
26
|
+
|
27
|
+
def self.extended( base )
|
28
|
+
base.class_eval do
|
29
|
+
|
30
|
+
if self.ancestors.include? ActiveRecord::Base
|
31
|
+
after_save :sync
|
32
|
+
after_destroy :sync
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def sync
|
39
|
+
Thread.current[ :changed_models ] << self
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
|
45
|
+
|
46
|
+
module InstanceMethods
|
47
|
+
|
48
|
+
def sync
|
49
|
+
self.class.sync
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
|
55
|
+
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
data/lib/apiway/path.rb
ADDED
@@ -0,0 +1,110 @@
|
|
1
|
+
module Apiway
|
2
|
+
|
3
|
+
module Resource
|
4
|
+
|
5
|
+
|
6
|
+
|
7
|
+
class << self
|
8
|
+
|
9
|
+
def included( base )
|
10
|
+
base.class_eval do
|
11
|
+
extend ClassMethods
|
12
|
+
include InstanceMethods
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
|
19
|
+
|
20
|
+
module ClassMethods
|
21
|
+
|
22
|
+
def depend_on( *models )
|
23
|
+
models.empty? ? @depend_on ||= [] : @depend_on = models
|
24
|
+
end
|
25
|
+
|
26
|
+
def access( &block )
|
27
|
+
block_given? ? @access = block : @access ||= Proc.new {}
|
28
|
+
end
|
29
|
+
|
30
|
+
def data( &block )
|
31
|
+
block_given? ? @data = block : @data
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
|
37
|
+
|
38
|
+
module InstanceMethods
|
39
|
+
|
40
|
+
def initialize( id, client )
|
41
|
+
@id = id
|
42
|
+
@client = client
|
43
|
+
end
|
44
|
+
|
45
|
+
def set_params( params = {} )
|
46
|
+
@params = params
|
47
|
+
@current_error = nil
|
48
|
+
self
|
49
|
+
end
|
50
|
+
|
51
|
+
def sync_changes( changed_models )
|
52
|
+
sync if self.class.depend_on.any? { |dependency| changed_models.include? dependency }
|
53
|
+
end
|
54
|
+
|
55
|
+
def sync
|
56
|
+
begin
|
57
|
+
instance_eval &self.class.access
|
58
|
+
rescue ResourceError => e
|
59
|
+
sync_error e.params
|
60
|
+
else
|
61
|
+
sync_data instance_eval &self.class.data
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
|
66
|
+
protected
|
67
|
+
|
68
|
+
attr_reader :client, :params
|
69
|
+
|
70
|
+
def error( params )
|
71
|
+
raise ResourceError, params
|
72
|
+
end
|
73
|
+
|
74
|
+
|
75
|
+
private
|
76
|
+
|
77
|
+
def sync_params( error: nil, full: nil, patch: nil )
|
78
|
+
params = { id: @id }
|
79
|
+
params[ :error ] = error if error
|
80
|
+
params[ :full ] = full if full
|
81
|
+
params[ :patch ] = patch if patch
|
82
|
+
params
|
83
|
+
end
|
84
|
+
|
85
|
+
def sync_error( error )
|
86
|
+
new_error_json = JSON.generate error, quirks_mode: true
|
87
|
+
if !@current_error || @current_error != new_error_json
|
88
|
+
@current_error = new_error_json
|
89
|
+
@client.trigger RESOURCE::SYNC, sync_params( error: error )
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def sync_data( data )
|
94
|
+
@current_error = nil
|
95
|
+
new_data_json = JSON.generate data, quirks_mode: true
|
96
|
+
if !@current_data || @current_data != new_data_json
|
97
|
+
patch = Diff.new( @current_data, new_data_json ).patch
|
98
|
+
patch_json = JSON.generate patch, quirks_mode: true
|
99
|
+
params_sync = @current_data && patch_json.size < new_data_json.size ? sync_params( patch: patch ) : sync_params( full: data )
|
100
|
+
@current_data = new_data_json
|
101
|
+
@client.trigger RESOURCE::SYNC, params_sync
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
|
106
|
+
end
|
107
|
+
|
108
|
+
end
|
109
|
+
|
110
|
+
end
|
data/lib/apiway.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'logger'
|
2
|
+
require 'sinatra/base'
|
3
|
+
require 'sinatra/activerecord'
|
4
|
+
require 'sinatra/contrib'
|
5
|
+
require 'sinatra-websocket'
|
6
|
+
|
7
|
+
require 'apiway/logger'
|
8
|
+
require 'apiway/errors'
|
9
|
+
require 'apiway/diff'
|
10
|
+
require 'apiway/events'
|
11
|
+
require 'apiway/extensions'
|
12
|
+
require 'apiway/path'
|
13
|
+
require 'apiway/client'
|
14
|
+
require 'apiway/controller'
|
15
|
+
require 'apiway/resource'
|
16
|
+
require 'apiway/model'
|
17
|
+
require 'apiway/application'
|
@@ -0,0 +1 @@
|
|
1
|
+
*.sqlite3
|
@@ -0,0 +1 @@
|
|
1
|
+
web: bundle exec thin --max-conns 3000 --max-persistent-conns 1500 start -p $PORT
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
@@ -0,0 +1,17 @@
|
|
1
|
+
development:
|
2
|
+
adapter: sqlite3
|
3
|
+
database: db/development.sqlite3
|
4
|
+
pool: 5
|
5
|
+
timeout: 5000
|
6
|
+
|
7
|
+
test:
|
8
|
+
adapter: sqlite3
|
9
|
+
database: db/test.sqlite3
|
10
|
+
pool: 5
|
11
|
+
timeout: 5000
|
12
|
+
|
13
|
+
production:
|
14
|
+
adapter: postgresql
|
15
|
+
database: pg_production
|
16
|
+
pool: 5
|
17
|
+
timeout: 5000
|
File without changes
|
File without changes
|
File without changes
|
@@ -0,0 +1,22 @@
|
|
1
|
+
class <%= classname %>Controller < ApplicationController
|
2
|
+
|
3
|
+
include Apiway::Controller
|
4
|
+
|
5
|
+
|
6
|
+
# before_action :auth?
|
7
|
+
|
8
|
+
# action :new do
|
9
|
+
#
|
10
|
+
# begin
|
11
|
+
# <%= modelname %>.create! params
|
12
|
+
# rescue Exception => e
|
13
|
+
# error e.message
|
14
|
+
# end
|
15
|
+
#
|
16
|
+
# end
|
17
|
+
|
18
|
+
# def auth?
|
19
|
+
# error :auth_error unless client[ :user_id ]
|
20
|
+
# end
|
21
|
+
|
22
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
class <%= classname %>Resource < ApplicationResource
|
2
|
+
|
3
|
+
include Apiway::Resource
|
4
|
+
|
5
|
+
depend_on <%= modelname %>
|
6
|
+
|
7
|
+
|
8
|
+
access do
|
9
|
+
# auth?
|
10
|
+
end
|
11
|
+
|
12
|
+
|
13
|
+
data do
|
14
|
+
|
15
|
+
# <%= modelname %>.limit( params[ :limit ] ).map do |<%= varname %>|
|
16
|
+
# {
|
17
|
+
# id: <%= varname %>.id,
|
18
|
+
# name: <%= varname %>.name
|
19
|
+
# }
|
20
|
+
# end
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
|
25
|
+
# def auth?
|
26
|
+
# error :auth_error unless client[ :user_id ]
|
27
|
+
# end
|
28
|
+
|
29
|
+
end
|