apiway 0.0.1

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.
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