apiway 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +3 -0
  3. data/LICENSE.txt +22 -0
  4. data/README.md +1 -0
  5. data/Rakefile +0 -0
  6. data/bin/apiway +13 -0
  7. data/lib/apiway/application.rb +53 -0
  8. data/lib/apiway/client.rb +171 -0
  9. data/lib/apiway/commands.rb +62 -0
  10. data/lib/apiway/controller.rb +124 -0
  11. data/lib/apiway/diff.rb +84 -0
  12. data/lib/apiway/errors.rb +62 -0
  13. data/lib/apiway/events.rb +23 -0
  14. data/lib/apiway/extensions.rb +29 -0
  15. data/lib/apiway/generator.rb +111 -0
  16. data/lib/apiway/logger.rb +41 -0
  17. data/lib/apiway/model.rb +58 -0
  18. data/lib/apiway/path.rb +7 -0
  19. data/lib/apiway/resource.rb +110 -0
  20. data/lib/apiway/version.rb +5 -0
  21. data/lib/apiway.rb +17 -0
  22. data/lib/generator/application/.gitignore +1 -0
  23. data/lib/generator/application/Gemfile +9 -0
  24. data/lib/generator/application/Procfile +1 -0
  25. data/lib/generator/application/README.md +0 -0
  26. data/lib/generator/application/Rakefile +3 -0
  27. data/lib/generator/application/app/base/.keep +0 -0
  28. data/lib/generator/application/app/base/base.rb +5 -0
  29. data/lib/generator/application/app/base/client.rb +21 -0
  30. data/lib/generator/application/app/base/routes.rb +11 -0
  31. data/lib/generator/application/app/controllers/.keep +0 -0
  32. data/lib/generator/application/app/controllers/application.rb +5 -0
  33. data/lib/generator/application/app/models/.keep +0 -0
  34. data/lib/generator/application/app/resources/.keep +0 -0
  35. data/lib/generator/application/app/resources/application.rb +5 -0
  36. data/lib/generator/application/config/application.rb +13 -0
  37. data/lib/generator/application/config/database.yml +17 -0
  38. data/lib/generator/application/config/environments/development.rb +9 -0
  39. data/lib/generator/application/config/environments/production.rb +9 -0
  40. data/lib/generator/application/config/environments/test.rb +10 -0
  41. data/lib/generator/application/config.ru +3 -0
  42. data/lib/generator/application/db/migrate/.keep +0 -0
  43. data/lib/generator/application/lib/.keep +0 -0
  44. data/lib/generator/application/public/.keep +0 -0
  45. data/lib/generator/templates/controller.tpl +22 -0
  46. data/lib/generator/templates/model.tpl +5 -0
  47. data/lib/generator/templates/resource.tpl +29 -0
  48. 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
@@ -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
@@ -0,0 +1,7 @@
1
+ module Apiway
2
+
3
+ def self.path
4
+ @gem_path ||= File.expand_path '..', File.dirname( __FILE__ )
5
+ end
6
+
7
+ end
@@ -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
@@ -0,0 +1,5 @@
1
+ module Apiway
2
+
3
+ VERSION = '0.0.1'
4
+
5
+ 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,9 @@
1
+ source 'https://rubygems.org'
2
+
3
+
4
+ gem 'apiway'
5
+
6
+ # Use sqlite3 as the database for Active Record
7
+ group :development, :test do
8
+ gem 'sqlite3'
9
+ end
@@ -0,0 +1 @@
1
+ web: bundle exec thin --max-conns 3000 --max-persistent-conns 1500 start -p $PORT
File without changes
@@ -0,0 +1,3 @@
1
+ require './config/application'
2
+
3
+ Apiway::Application.tasks
File without changes
@@ -0,0 +1,5 @@
1
+ class Base
2
+
3
+ protected
4
+
5
+ end
@@ -0,0 +1,21 @@
1
+ module Apiway
2
+
3
+ class Client
4
+
5
+
6
+ on_connected do
7
+
8
+ end
9
+
10
+ on_message do |message|
11
+
12
+ end
13
+
14
+ on_disconnected do
15
+
16
+ end
17
+
18
+
19
+ end
20
+
21
+ end
@@ -0,0 +1,11 @@
1
+ Apiway::Application.configure do |routes|
2
+
3
+ #
4
+ # Sinatra routes
5
+ #
6
+ # routes.get '/test' do
7
+ # Your code
8
+ # end
9
+ #
10
+
11
+ end
File without changes
@@ -0,0 +1,5 @@
1
+ class ApplicationController < Base
2
+
3
+ protected
4
+
5
+ end
File without changes
File without changes
@@ -0,0 +1,5 @@
1
+ class ApplicationResource < Base
2
+
3
+ protected
4
+
5
+ end
@@ -0,0 +1,13 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+ Bundler.require
4
+
5
+
6
+ module Apiway
7
+
8
+ class Application
9
+
10
+
11
+ end
12
+
13
+ end
@@ -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
@@ -0,0 +1,9 @@
1
+ Apiway::Application.configure :development do |config|
2
+
3
+
4
+ config.set apiway_log: :info
5
+
6
+ config.set activerecord_log: :info
7
+
8
+
9
+ end
@@ -0,0 +1,9 @@
1
+ Apiway::Application.configure :production do |config|
2
+
3
+
4
+ config.set apiway_log: false
5
+
6
+ config.set activerecord_log: false
7
+
8
+
9
+ end
@@ -0,0 +1,10 @@
1
+ Apiway::Application.configure :test do |config|
2
+
3
+
4
+ config.set apiway_log: :error
5
+
6
+ config.set activerecord_log: :error
7
+
8
+
9
+ end
10
+
@@ -0,0 +1,3 @@
1
+ require './config/application'
2
+
3
+ run Apiway::Application
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,5 @@
1
+ class <%= classname %> < ActiveRecord::Base
2
+
3
+ include Apiway::Model
4
+
5
+ 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