tzispa 0.6.1 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +12 -0
  3. data/lib/tzispa/api/handler.rb +54 -23
  4. data/lib/tzispa/app.rb +60 -68
  5. data/lib/tzispa/cli.rb +42 -3
  6. data/lib/tzispa/commands/api.rb +55 -0
  7. data/lib/tzispa/commands/app.rb +83 -0
  8. data/lib/tzispa/commands/cli/generate.rb +60 -0
  9. data/lib/tzispa/commands/command.rb +28 -0
  10. data/lib/tzispa/commands/console.rb +62 -0
  11. data/lib/tzispa/commands/helpers/i18n.rb +67 -0
  12. data/lib/tzispa/commands/helpers/project.rb +69 -0
  13. data/lib/tzispa/commands/helpers/repository.rb +46 -0
  14. data/lib/tzispa/commands/project.rb +104 -0
  15. data/lib/tzispa/commands/repository.rb +66 -0
  16. data/lib/tzispa/commands/rig.rb +28 -0
  17. data/lib/tzispa/commands/server.rb +26 -0
  18. data/lib/tzispa/config/{appconfig.rb → app_config.rb} +12 -32
  19. data/lib/tzispa/config/base.rb +7 -5
  20. data/lib/tzispa/config/db_config.rb +67 -0
  21. data/lib/tzispa/config/yaml.rb +9 -10
  22. data/lib/tzispa/context.rb +3 -2
  23. data/lib/tzispa/controller/api.rb +66 -60
  24. data/lib/tzispa/controller/auth_layout.rb +4 -28
  25. data/lib/tzispa/controller/base.rb +61 -24
  26. data/lib/tzispa/controller/exceptions.rb +3 -4
  27. data/lib/tzispa/controller/http_error.rb +0 -3
  28. data/lib/tzispa/controller/layout.rb +4 -4
  29. data/lib/tzispa/domain.rb +27 -23
  30. data/lib/tzispa/env.rb +34 -0
  31. data/lib/tzispa/environment.rb +231 -0
  32. data/lib/tzispa/http/context.rb +65 -80
  33. data/lib/tzispa/http/request.rb +29 -17
  34. data/lib/tzispa/http/response.rb +45 -12
  35. data/lib/tzispa/route_set.rb +100 -0
  36. data/lib/tzispa/server.rb +61 -0
  37. data/lib/tzispa/tzisparc.rb +80 -0
  38. data/lib/tzispa/version.rb +1 -1
  39. data/lib/tzispa.rb +3 -1
  40. data/tzispa.gemspec +12 -6
  41. metadata +68 -17
  42. data/lib/tzispa/command/api.rb +0 -24
  43. data/lib/tzispa/command/app.rb +0 -95
  44. data/lib/tzispa/command/cli/generate.rb +0 -51
  45. data/lib/tzispa/command/project.rb +0 -258
  46. data/lib/tzispa/command/rig.rb +0 -26
  47. data/lib/tzispa/controller/signed_api.rb +0 -13
  48. data/lib/tzispa/http/session_flash_bag.rb +0 -62
  49. data/lib/tzispa/middleware.rb +0 -48
  50. data/lib/tzispa/routes.rb +0 -69
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1e7d9bdf85429d1bbe0fd303daff3853049aa4f6
4
- data.tar.gz: 61aecb036fb1501b56572e8f5504ed9911e51242
3
+ metadata.gz: 494da0d1c9e0718fe00cf30c6ca12ff79656a152
4
+ data.tar.gz: b076698a91484ffee3f0561f4293034f5eea6115
5
5
  SHA512:
6
- metadata.gz: 79493c3072124348bc1e9458615da7a75665c4a9ee6f29ef138ede3df6bdae48648402c7ecfb3058fc93357905717ed034f6e17b4f0929d18993603927981560
7
- data.tar.gz: f38fabe97d6d006bfde4e0e2d9f2349d96a428c68f7fa818e38e33cb836b8f8a04257b7cd4137d06f69206e48c03f1d20610eba913411a61f2d45edf6081a435
6
+ metadata.gz: 98dd03475d556c2a0990b4f7979a4eba9ecc1ba94c8943874abf67a568c136f07fceb4c89de9672399bff13f7322d2f1a069a2d6693942be520b5d6816d00d4b
7
+ data.tar.gz: df7eb2126ea1cf8fc7bd2ddeefc8f975cf99c03d97ab90f31dd4cf5a3ba4d8e843e88ef56beac5bb66ed1d10252074b51ffff0e25a9ea4036e77d0d95a75aedb
data/CHANGELOG.md CHANGED
@@ -2,6 +2,18 @@ Tzispa
2
2
 
3
3
  General purpose web framework
4
4
 
5
+ ## v0.7.0
6
+ - distinct error and http status in api handlers
7
+ - better api responses by content type
8
+ - controller base: better error handling in invoke
9
+ - api handlers: added support for api http verbs using request_method
10
+ - independent db/repository configuration file
11
+ - app environment implementation
12
+ - automatic code reloading in development env (Shotgun)
13
+ - added before hook in controllers and api-handlers
14
+ - new routes specification file per app
15
+ - code refactoring and bug fixes
16
+
5
17
  ## v0.6.1
6
18
  - sessions security improvements
7
19
  - added "x-frame-option: sameorigin" header to security improvement
@@ -19,69 +19,100 @@ module Tzispa
19
19
  class InvalidSign < ApiException; end
20
20
 
21
21
  class Handler
22
+ extend Forwardable
23
+
22
24
  include Tzispa::Helpers::Provider
23
25
  include Tzispa::Helpers::SignRequirer
24
- extend Forwardable
25
26
 
26
- using Tzispa::Utils
27
+ using Tzispa::Utils::TzString
27
28
 
28
- attr_reader :context, :response_verb, :data, :status
29
- def_delegators :@context, :request, :response, :app, :repository, :config, :logger
29
+ attr_reader :context, :type, :data, :error, :status
30
+ def_delegators :@context, :request, :response, :app, :repository,
31
+ :config, :logger, :unauthorized_but_logged, :login_redirect
30
32
 
31
- HANDLER_STATUS_UNDEFINED = nil
32
- HANDLER_STATUS_OK = :ok
33
- HANDLER_MISSING_PARAMETER = :missing_parameter
33
+ attr_writer :error
34
34
 
35
+ HANDLER_OK = :ok
36
+ HANDLER_MISSING_PARAMETER = :missing_parameter
35
37
 
36
38
  def initialize(context)
37
39
  @context = context
40
+ @error = nil
41
+ @status = nil
38
42
  end
39
43
 
40
- def result(response_verb:, data: nil, status: HANDLER_STATUS_UNDEFINED)
41
- @response_verb = response_verb
42
- @status = status if status
44
+ def result(type:, data: nil, error: nil)
45
+ @type = type
43
46
  @data = data
47
+ @error = error
48
+ end
49
+
50
+ class << self
51
+ def before(*args)
52
+ (@before_chain ||= []).tap do |bef|
53
+ args.each do |s|
54
+ s = s.to_sym
55
+ bef << s unless bef.include?(s)
56
+ end
57
+ end
58
+ end
44
59
  end
45
60
 
46
61
  def error?
47
- status && status != HANDLER_STATUS_OK
62
+ error && error != HANDLER_OK
63
+ end
64
+
65
+ def error_status(error, status = nil)
66
+ @error = error
67
+ @status = status
48
68
  end
49
69
 
50
- def result_json(data, status: nil)
51
- result response_verb: :json, data: data, status: status
70
+ def result_json(data, error: nil)
71
+ result type: :json, data: data, error: error
52
72
  end
53
73
 
54
- def result_download(data, status: nil)
55
- result response_verb: :download, data: data, status: status
74
+ def result_download(data, error: nil)
75
+ result type: :download, data: data, error: error
56
76
  end
57
77
 
58
78
  def not_found
59
- result response_verb: :not_found
79
+ result type: :not_found
60
80
  end
61
81
 
62
82
  def message
63
- I18n.t("#{self.class.name.dottize}.#{status}", default: "#{status}") if status
83
+ I18n.t("#{self.class.name.dottize}.#{error}", default: error.to_s) if error
64
84
  end
65
85
 
66
- def run!(verb, predicate=nil)
86
+ def run!(verb, predicate = nil)
67
87
  raise UnknownHandlerVerb.new(verb, self.class.name) unless provides? verb
68
- raise InvalidSign.new if sign_required? && !sign_valid?
88
+ raise InvalidSign if sign_required? && !sign_valid?
89
+ do_before
69
90
  # process compound predicates
70
91
  args = predicate ? predicate.split(',') : nil
71
92
  send verb, *args
72
93
  end
73
94
 
74
- def set_status(value)
75
- @status = value
95
+ def redirect_url(url)
96
+ if url && !url.strip.empty?
97
+ url.start_with?('#') ? "#{request.referer}#{url}" : url
98
+ else
99
+ request.referer
100
+ end
76
101
  end
77
102
 
78
103
  protected
79
104
 
80
105
  def static_path_sign?
81
- context.path_sign? context.router_params[:sign], context.router_params[:handler], context.router_params[:verb], context.router_params[:predicate]
106
+ context.path_sign? context.router_params[:sign],
107
+ context.router_params[:handler],
108
+ context.router_params[:verb],
109
+ context.router_params[:predicate]
82
110
  end
83
111
 
84
-
112
+ def do_before
113
+ self.class.before.each { |hbef| send hbef }
114
+ end
85
115
  end
116
+
86
117
  end
87
118
  end
data/lib/tzispa/app.rb CHANGED
@@ -4,49 +4,37 @@ require 'forwardable'
4
4
  require 'logger'
5
5
  require 'i18n'
6
6
  require 'tzispa/domain'
7
- require 'tzispa/routes'
8
- require 'tzispa/config/appconfig'
9
- require 'tzispa/middleware'
7
+ require 'tzispa/route_set'
8
+ require 'tzispa/config/app_config'
9
+ require 'tzispa/config/db_config'
10
10
  require 'tzispa_data'
11
11
 
12
-
13
12
  module Tzispa
14
13
 
15
- ENV_TZISPA_APP = :tzispa__app
16
- ENV_TZISPA_CONTEXT = :tzispa__context
17
-
18
-
19
14
  class Application
20
15
  extend Forwardable
21
16
 
22
- attr_reader :domain, :config, :middleware, :repository, :engine,
23
- :logger, :mount_path, :routes
24
-
25
- def_delegator :@middleware, :use
26
- def_delegator :@domain, :name
27
- def_delegators :@routes, :routing, :route_rig_index, :route_rig_api, :route_rig_signed_api, :route_rig_layout
17
+ attr_reader :domain, :logger, :map_path
28
18
 
19
+ def_delegators :@domain, :name, :path
20
+ def_delegators :@routes, :routing, :index, :api, :signed_api, :layout
29
21
 
30
22
  class << self
31
-
32
- alias :__new__ :new
23
+ alias __new__ :new
33
24
 
34
25
  def new(*args, &block)
35
- __new__(*args, &block).tap { |app|
36
- add app
37
- }
26
+ __new__(*args, &block).tap { |app| add app }
38
27
  end
39
28
 
29
+ # rubocop:disable Style/ClassVars
40
30
  def applications
41
31
  synchronize do
42
- @@applications ||= Hash.new{ |hash, key| raise UnknownApplication.new("#{key}") }
32
+ @@applications ||= Hash.new { |_, key| raise UnknownApplication(key.to_s) }
43
33
  end
44
34
  end
45
35
 
46
36
  def synchronize
47
- Mutex.new.synchronize {
48
- yield
49
- }
37
+ Mutex.new.synchronize { yield }
50
38
  end
51
39
 
52
40
  def [](name)
@@ -55,78 +43,82 @@ module Tzispa
55
43
 
56
44
  def add(app)
57
45
  synchronize do
58
- raise DuplicateDomain.new("You have try to add an app with a duplicate domain name #{app.name}") if applications.has_key? app.name
46
+ raise DuplicateDomain.new(app.name) if applications.key?(app.name)
59
47
  applications[app.name] = app
60
48
  end
61
49
  end
62
-
63
- def run(appid, builder: nil, on: nil, &block)
64
- theapp = self.new appid, on: on, &block
65
- theapp.run builder
66
- end
67
-
68
50
  end
69
51
 
70
52
  def initialize(appid, on: nil, &block)
71
53
  @domain = Domain.new(appid)
72
- @config = Config::AppConfig.new(@domain).load!
73
- @middleware = Middleware.new self
74
- @routes ||= Routes.new(self, on)
54
+ @map_path = on
75
55
  instance_eval(&block) if block
76
56
  end
77
57
 
78
- def run(builder=nil)
79
- builder ||= ::Rack::Builder.new
80
- if routes.map_path
81
- this_app = self
82
- builder.map routes.map_path do
83
- run this_app.middleware.builder
84
- end
85
- else
86
- builder.run middleware.builder
87
- end
58
+ def call(env)
59
+ routes.call env
88
60
  end
89
61
 
90
62
  def load!
91
- self.class.synchronize {
92
- load_locales
93
- @logger = Logger.new("logs/#{domain.name}.log", config.logging.shift_age).tap { |log|
94
- log.level = config.developing ? Logger::DEBUG : Logger::INFO
95
- } if config.logging&.enabled
96
- domain_setup
97
- @repository = Data::Repository.new(config.repository.to_h).load!(domain) if config.respond_to? :repository
98
- @loaded = true
99
- }
100
- self
63
+ tap do |app|
64
+ app.class.synchronize do
65
+ logging
66
+ load_locales
67
+ domain.setup
68
+ routes.setup
69
+ repository&.load!(domain)
70
+ end
71
+ end
101
72
  end
102
73
 
103
74
  def [](domain)
104
75
  self.class[domain]
105
76
  end
106
77
 
107
- private
78
+ def default_layout?(layout)
79
+ config.default_layout.to_sym == layout
80
+ end
108
81
 
109
- def domain_setup
110
- domain.require_dir
111
- domain.require_dir 'helpers'
112
- domain.require_dir 'services'
113
- domain.require_dir 'api'
114
- domain.require_dir 'middleware'
82
+ def env
83
+ Tzispa::Environment.instance
115
84
  end
116
85
 
117
- def load_locales
118
- if config.respond_to?(:locales)
119
- I18n.enforce_available_locales = false
120
- I18n.load_path += Dir["config/locales/*.yml", "#{domain.path}/locales/*.yml"]
86
+ def routes
87
+ @routes ||= RouteSet.new(self, map_path)
88
+ end
89
+
90
+ def config
91
+ @config ||= Config::AppConfig.new(@domain).load!
92
+ end
93
+
94
+ def repository
95
+ @repository ||= begin
96
+ dbcfg = Config::DbConfig.new(env.environment)&.to_h
97
+ Data::Repository.new(dbcfg) if dbcfg&.count&.positive?
121
98
  end
122
99
  end
123
100
 
124
- public
101
+ private
125
102
 
126
- class ApplicationError < StandardError; end
127
- class UnknownApplication < ApplicationError; end
128
- class DuplicateDomain < ApplicationError; end
103
+ def logging
104
+ return unless config&.logging&.enabled
105
+ @logger = Logger.new("logs/#{domain.name}.log", config.logging&.shift_age)
106
+ @logger.level = Tzispa::Environment.development? ? Logger::DEBUG : Logger::INFO
107
+ end
129
108
 
109
+ def load_locales
110
+ return unless config.respond_to?(:locales)
111
+ I18n.enforce_available_locales = false
112
+ I18n.load_path += Dir['config/locales/*.yml', "#{domain.path}/locales/*.yml"]
113
+ end
114
+ end
130
115
 
116
+ class ApplicationError < StandardError; end
117
+ class UnknownApplication < ApplicationError; end
118
+ class DuplicateDomain < ApplicationError
119
+ def initialize(app_name)
120
+ super "You have tried to add an app with a duplicate domain name #{app_name}"
121
+ end
131
122
  end
123
+
132
124
  end
data/lib/tzispa/cli.rb CHANGED
@@ -1,18 +1,57 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'thor'
4
+ require 'tzispa'
2
5
 
3
6
  module Tzispa
4
7
 
5
8
  class Cli < Thor
6
-
7
9
  desc 'version', 'Prints Tzispa version'
8
10
  def version
9
11
  require 'tzispa/version'
10
12
  puts "v#{VERSION}"
11
13
  end
12
14
 
13
- require 'tzispa/command/cli/generate'
14
- register Tzispa::Command::Cli::Generate, 'generate', 'generate [SUBCOMMAND]', 'Generate Tzispa components'
15
+ desc 'new', 'Generate a new Tzispa project'
16
+ def new(name)
17
+ require 'tzispa/commands/project'
18
+ Tzispa::Commands::Project.new(name).generate
19
+ puts "Project '#{name}' has been created"
20
+ end
21
+
22
+ require 'tzispa/commands/server'
23
+ desc 'server', 'Start Tzispa app server'
24
+ method_option :port, aliases: '-p', desc: 'The port to run the server on'
25
+ method_option :server, desc: 'Choose a specific Rack::Handler (webrick, thin, etc)'
26
+ method_option :rackup, desc: 'A rackup configuration file path to load (config.ru)'
27
+ method_option :host, desc: 'The host address to bind to'
28
+ method_option :debug, desc: 'Turn on debug output'
29
+ method_option :warn, desc: 'Turn on warnings'
30
+ method_option :daemonize, desc: 'If true, the server will daemonize itself'
31
+ method_option :help, desc: 'Displays the help usage'
32
+ def server
33
+ if options[:help]
34
+ invoke :help, ['server']
35
+ else
36
+ Tzispa::Commands::Server.new(options).start
37
+ end
38
+ end
39
+
40
+ require 'tzispa/commands/console'
41
+ desc 'console', 'Starts a Tzispa console'
42
+ method_option :engine, desc: "Choose: (#{Tzispa::Commands::Console::ENGINES.keys.join('/')})"
43
+ method_option :help, desc: 'Displays the usage help'
44
+ def console
45
+ if options[:help]
46
+ invoke :help, ['console']
47
+ else
48
+ Tzispa::Commands::Console.new(options).start
49
+ end
50
+ end
15
51
 
52
+ require 'tzispa/commands/cli/generate'
53
+ register Tzispa::Commands::Cli::Generate, 'generate', 'generate [SUBCOMMAND]',
54
+ 'Generate Tzispa components'
16
55
  end
17
56
 
18
57
  end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'fileutils'
4
+ require 'tzispa/controller/api'
5
+ require 'tzispa/commands/command'
6
+ require 'tzispa/utils/indenter'
7
+
8
+ module Tzispa
9
+ module Commands
10
+
11
+ class Api < Command
12
+ attr_reader :name, :domain, :verb
13
+
14
+ def initialize(name, app, verb, options = nil)
15
+ super(options)
16
+ @domain = Tzispa::Domain.new app
17
+ @name = name
18
+ @verb = verb
19
+ end
20
+
21
+ def generate
22
+ file_name = Tzispa::Controller::Api.handler_class_file(domain, name, verb)
23
+ raise "The handler '#{name}' already exist" if File.exist?(file_name)
24
+ namespace = Tzispa::Controller::Api.handler_namespace(domain, verb)
25
+ class_name = Tzispa::Controller::Api.handler_class_name(name)
26
+ create_file file_name, namespace, class_name
27
+ end
28
+
29
+ private
30
+
31
+ def create_file(file_name, ns, class_name)
32
+ dir, = Pathname.new(file_name).split
33
+ FileUtils.mkpath dir
34
+ File.open(file_name, 'w') do |f|
35
+ f.puts handler_code(ns, class_name)
36
+ end
37
+ end
38
+
39
+ def handler_code(namespace, class_name)
40
+ Tzispa::Utils::Indenter.new.tap do |code|
41
+ code << "require 'tzispa/api/handler'\n\n"
42
+ level = 0
43
+ namespace.split('::').each do |ns|
44
+ level.positive? ? code.indent << "module #{ns}\n" : code << "module #{ns}\n"
45
+ level += 1
46
+ end
47
+ code.indent << "\nclass #{class_name} < Tzispa::Api::Handler\n\n"
48
+ code << "end\n\n"
49
+ namespace.split('::').each { code.unindent << "end\n" }
50
+ end.to_s
51
+ end
52
+ end
53
+
54
+ end
55
+ end
@@ -0,0 +1,83 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+ require 'tzispa/domain'
5
+ require 'tzispa/utils/string'
6
+ require 'tzispa/utils/indenter'
7
+ require 'tzispa/config/app_config'
8
+ require 'tzispa/commands/command'
9
+
10
+ module Tzispa
11
+ module Commands
12
+ class App < Command
13
+ using Tzispa::Utils::TzString
14
+
15
+ APP_STRUCTURE = [
16
+ 'api', 'locales', 'error', 'controller', 'helpers', 'view', 'view/_',
17
+ 'view/_/block', 'view/_/layout', 'view/_/static', 'services'
18
+ ].freeze
19
+
20
+ attr_reader :domain
21
+
22
+ def initialize(name, options = nil)
23
+ super(options)
24
+ @domain = Tzispa::Domain.new(name)
25
+ end
26
+
27
+ def generate(mount_path, index_layout, locale)
28
+ update_rackup mount_path
29
+ create_structure
30
+ create_appconfig index_layout, locale
31
+ create_home_layout
32
+ create_routes
33
+ end
34
+
35
+ private
36
+
37
+ def update_rackup(mount_path = nil)
38
+ mount_path ||= DEFAULT_MOUNT_PATH
39
+ File.open(Tzispa::Environment::DEFAULT_RACKUP, 'a') do |f|
40
+ f.puts write_app_code(mount_path)
41
+ end
42
+ end
43
+
44
+ def write_app_code(mount_path)
45
+ map_path = mount_path.start_with?('/') ? mount_path : "/#{mount_path}"
46
+ Tzispa::Utils::Indenter.new(2).tap do |code|
47
+ code << "\nmap '#{map_path}' do\n"
48
+ code.indent << "run Tzispa::Application.new(:#{domain.name},on: '#{map_path}').load!\n"
49
+ code.unindent << "end\n"
50
+ end.to_s
51
+ end
52
+
53
+ def create_structure
54
+ return unless File.exist? domain.path
55
+ Dir.mkdir domain.path.to_s
56
+ APP_STRUCTURE.each { |appdir| Dir.mkdir "#{domain.path}/#{appdir}" }
57
+ end
58
+
59
+ def create_appconfig(default_layout, locale)
60
+ appconfig = Tzispa::Config::AppConfig.new(domain)
61
+ @config = appconfig.create_default(default_layout, locale)
62
+ end
63
+
64
+ def create_home_layout
65
+ tpl = Tzispa::Rig::Template.new(name: @config.default_layout || 'index',
66
+ type: :layout,
67
+ domain: domain,
68
+ content_type: :htm)
69
+ tpl.create("<html><body><h1>Welcome: #{domain.name} is working!</h1></body></html>")
70
+ end
71
+
72
+ def create_routes
73
+ File.open("config/routes/#{domain.name}.rb", 'w') do |file|
74
+ file.puts '# app routes definitions \n'
75
+ file.puts "index '/', controller: 'layout:render!'"
76
+ file.puts "signed_api '/api_:sign/:handler/:verb(~:predicate)(/:sufix)'"
77
+ file.puts "api '/api/:handler/:verb(~:predicate)(/:sufix)'"
78
+ end
79
+ end
80
+ end
81
+
82
+ end
83
+ end
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'thor'
4
+
5
+ module Tzispa
6
+ module Commands
7
+ module Cli
8
+
9
+ class Generate < Thor
10
+ require 'tzispa/commands/app'
11
+ desc 'app', 'Generate new application into a project'
12
+ method_option :mount, aliases: '-m', desc: 'The mount point for this app', default: '/'
13
+ method_option :index, aliases: '-i', desc: 'Default index layout', default: 'index'
14
+ method_option :locale, aliases: '-l', desc: 'Default app locale', default: 'en'
15
+ def app(name)
16
+ tzapp = Tzispa::Commands::App.new(name)
17
+ tzapp.generate(options[:mount], options[:index], options[:locale])
18
+ puts "App '#{name}' has been created"
19
+ end
20
+
21
+ require 'tzispa/commands/rig'
22
+ desc 'rig', 'Generate new rig template'
23
+ method_option :app, aliases: '-a',
24
+ desc: 'The app where create the new template', required: true
25
+ method_option :type, aliases: '-t',
26
+ desc: 'Template type: block, static or layout', required: true
27
+ def rig(name)
28
+ tpl = Tzispa::Commands::Rig.new(name, options[:app], options[:type])
29
+ tpl.generate
30
+ puts "Rig #{options[:type]} template '#{name}' has been created in #{options[:app]}"
31
+ end
32
+
33
+ require 'tzispa/commands/repository'
34
+ desc 'repository', 'Generate new repsitory'
35
+ method_option :adapter, aliases: '-a',
36
+ desc: 'Database adapter to use in the repository', required: true
37
+ method_option :database, aliases: '-d',
38
+ desc: 'Database connection string or path', required: true
39
+ def repository(name)
40
+ repo = Tzispa::Commands::Repository.new name, options[:adapter], options[:database]
41
+ repo.generate
42
+ puts "Repository #{name} has been created into local project"
43
+ end
44
+
45
+ require 'tzispa/commands/api'
46
+ desc 'api', 'Generate new api handler'
47
+ method_option :app, aliases: '-a',
48
+ desc: 'The app where the api handler will be created', required: true
49
+ method_option :verb, aliases: '-v',
50
+ desc: 'The http verb that this api will respond to', required: true
51
+ def api(name)
52
+ hnd = Tzispa::Commands::Api.new(name, options[:app], options[:verb])
53
+ hnd.generate
54
+ puts "Api handler '#{name}' has been created in #{options[:app]}"
55
+ end
56
+ end
57
+
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'tzispa/environment'
4
+
5
+ module Tzispa
6
+ module Commands
7
+
8
+ class Command
9
+
10
+ NO_PROJECT_FOLDER = 'You must be located in a Tzispa project folder to run this command'
11
+
12
+ def initialize(options)
13
+ raise NO_PROJECT_FOLDER unless project_folder?
14
+ Tzispa::Environment.opts = options
15
+ @environment = Tzispa::Environment.instance
16
+ end
17
+
18
+ protected
19
+
20
+ attr_reader :environment
21
+
22
+ def project_folder?
23
+ File.exist?(Tzispa::Environment::DEFAULT_RACKUP)
24
+ end
25
+ end
26
+
27
+ end
28
+ end