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
@@ -0,0 +1,100 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'yaml'
4
+ require 'http_router'
5
+ require 'tzispa/utils/string'
6
+ require 'tzispa/controller/http_error'
7
+
8
+ module Tzispa
9
+
10
+ class RouteSet
11
+ using Tzispa::Utils::TzString
12
+
13
+ CONTROLLERS_BASE = 'Tzispa::Controller'
14
+
15
+ attr_reader :router, :map_path, :app
16
+
17
+ def initialize(app, root = nil)
18
+ @router = HttpRouter.new
19
+ @app = app
20
+ @router.default Controller::HttpError.new(app, :error_404)
21
+ @map_path = root unless root == '/'
22
+ end
23
+
24
+ def setup
25
+ draw do
26
+ contents = File.read(routes_definitions)
27
+ instance_eval(contents, File.basename(routes_definitions), 0)
28
+ end
29
+ end
30
+
31
+ def routes_definitions
32
+ @routes_definitions ||= "config/routes/#{app.name}.rb"
33
+ end
34
+
35
+ def path(path_id, params = {})
36
+ "#{@map_path}#{@router.path path_id, params}"
37
+ end
38
+
39
+ def call(env)
40
+ @router.call env
41
+ end
42
+
43
+ def add(route_id, path, controller, methods: nil, matching: nil)
44
+ add_route(route_id, path, to: build_controller(controller),
45
+ methods: methods,
46
+ matching: matching)
47
+ end
48
+
49
+ def draw
50
+ yield if block_given?
51
+ end
52
+
53
+ def index(path, controller: nil, methods: nil)
54
+ add :index, path, controller || 'layout:render!', methods: methods
55
+ end
56
+
57
+ def api(path, controller: nil, methods: nil)
58
+ add :api, path, controller || 'api:dispatch!', methods: methods
59
+ end
60
+
61
+ def signed_api(path, controller: nil, methods: nil)
62
+ add :sapi, path, controller || 'api:dispatch!', methods: methods
63
+ end
64
+
65
+ def layout(layout, path, controller: nil, methods: nil)
66
+ add layout, path, controller || 'layout:render!', methods: methods,
67
+ matching: { layout: layout.to_s }
68
+ end
69
+
70
+ private
71
+
72
+ def add_route(route_id, path, to:, methods: nil, matching: nil)
73
+ @router.add(path).tap do |rule|
74
+ rule.name = route_id
75
+ rule.to to
76
+ rule.add_request_method(methods) if methods
77
+ rule.add_match_with(matching) if matching
78
+ end
79
+ end
80
+
81
+ def build_controller(controller)
82
+ spec_control, callmethod = controller.to_s.split(':')
83
+ mpath = spec_control.split('#')
84
+ controller_class(mpath).new(app, callmethod)
85
+ end
86
+
87
+ def controller_class(mpath)
88
+ req_controller = mpath.pop
89
+ cmodule = if mpath.count > 1
90
+ require "#{app.path}/controller/#{req_controller}"
91
+ mpath.collect!(&:capitalize).join('::')
92
+ else
93
+ require "tzispa/controller/#{req_controller}"
94
+ CONTROLLERS_BASE
95
+ end
96
+ "#{cmodule}::#{req_controller.camelize}".constantize
97
+ end
98
+ end
99
+
100
+ end
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rack'
4
+ require 'tzispa/environment'
5
+
6
+ module Tzispa
7
+ # provides rack-based web server interface
8
+ class Server < ::Rack::Server
9
+ attr_reader :options
10
+
11
+ def initialize
12
+ @options = _extract_options
13
+ setup
14
+ end
15
+
16
+ def start
17
+ preload
18
+ super
19
+ end
20
+
21
+ private
22
+
23
+ def setup
24
+ instance_eval 'load "./config/boot.rb"'
25
+ @app = if code_reloading?
26
+ Shotgun::Loader.new(rackup_file)
27
+ else
28
+ config = "Rack::Builder.new {( #{::File.read(rackup_file)}\n )}.to_app"
29
+ instance_eval config, rackup_file
30
+ end
31
+ end
32
+
33
+ def env
34
+ @env ||= Tzispa::Environment.instance
35
+ end
36
+
37
+ def code_reloading?
38
+ env.code_reloading?
39
+ end
40
+
41
+ def preload
42
+ return unless code_reloading?
43
+ Shotgun.enable_copy_on_write
44
+ Shotgun.preload
45
+ end
46
+
47
+ def rackup_file
48
+ env.rackup.to_s
49
+ end
50
+
51
+ def _extract_options
52
+ {
53
+ environment: env.environment,
54
+ config: rackup_file,
55
+ Host: env.server_host,
56
+ Port: env.server_port,
57
+ AccessLog: []
58
+ }
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,80 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'pathname'
4
+ require 'tzispa/utils/hash'
5
+
6
+ module Tzispa
7
+
8
+ class Tzisparc
9
+ using Tzispa::Utils::TzHash
10
+
11
+ FILE_NAME = '.tzisparc'
12
+
13
+ DEFAULT_ARCHITECTURE = 'domains'
14
+
15
+ APP_ARCHITECTURE = 'app'
16
+
17
+ ARCHITECTURE_KEY = 'architecture'
18
+
19
+ PROJECT_NAME = 'project'
20
+
21
+ DEFAULT_TEST_SUITE = 'minitest'
22
+
23
+ TEST_KEY = 'test'
24
+
25
+ DEFAULT_TEMPLATE = 'rig'
26
+
27
+ TEMPLATE_KEY = 'template'
28
+
29
+ SEPARATOR = '='
30
+
31
+ def initialize(root)
32
+ @root = root
33
+ end
34
+
35
+ def options
36
+ @options ||= default_options.merge(file_options).symbolize!
37
+ end
38
+
39
+ def default_options
40
+ @default_options ||= { ARCHITECTURE_KEY => DEFAULT_ARCHITECTURE,
41
+ PROJECT_NAME => project_name,
42
+ TEST_KEY => DEFAULT_TEST_SUITE,
43
+ TEMPLATE_KEY => DEFAULT_TEMPLATE }
44
+ end
45
+
46
+ def exists?
47
+ path_file.exist?
48
+ end
49
+
50
+ def generate
51
+ File.open(path_file, 'w') do |file|
52
+ default_options.each { |k, v| file.puts("#{k}#{SEPARATOR}#{v}") }
53
+ end
54
+ end
55
+
56
+ private
57
+
58
+ def file_options
59
+ exists? ? parse_file(path_file) : {}
60
+ end
61
+
62
+ def parse_file(path)
63
+ {}.tap do |hash|
64
+ File.readlines(path).each do |line|
65
+ key, value = line.split(SEPARATOR)
66
+ hash[key] = value.strip
67
+ end
68
+ end
69
+ end
70
+
71
+ def path_file
72
+ @root.join FILE_NAME
73
+ end
74
+
75
+ def project_name
76
+ ::File.basename(@root)
77
+ end
78
+ end
79
+
80
+ end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Tzispa
4
- VERSION = '0.6.1'
4
+ VERSION = '0.7.0'
5
5
  FRAMEWORK_NAME = 'Tzispa'
6
6
  GEM_NAME = 'tzispa'
7
7
  end
data/lib/tzispa.rb CHANGED
@@ -1,6 +1,8 @@
1
1
  module Tzispa
2
2
 
3
3
  require 'tzispa/version'
4
+ require 'tzispa/environment'
5
+ require 'tzispa/server'
4
6
  require 'tzispa/app'
5
-
7
+
6
8
  end
data/tzispa.gemspec CHANGED
@@ -1,4 +1,6 @@
1
- # -*- encoding: utf-8 -*-
1
+ # coding: utf-8
2
+ # frozen_string_literal: true
3
+
2
4
  require File.expand_path('../lib/tzispa/version', __FILE__)
3
5
 
4
6
  Gem::Specification.new do |s|
@@ -10,21 +12,25 @@ Gem::Specification.new do |s|
10
12
  s.email = ['japinero@area-integral.com']
11
13
  s.homepage = 'https://github.com/japiber/tzispa'
12
14
  s.summary = 'A sparkling web framework'
13
- s.description = 'A sparkling web framework based on Rack and inspired by Sinatra and Lotus'
15
+ s.description = 'A sparkling web framework Rack based'
14
16
  s.licenses = ['MIT']
15
17
 
16
- s.required_ruby_version = '~> 2.3'
18
+ s.required_ruby_version = '~> 2.3'
17
19
 
20
+ s.add_dependency 'bundler', '~> 1.14'
18
21
  s.add_dependency 'rack', '~> 2.0', '>= 2.0.1'
19
22
  s.add_dependency 'i18n', '~> 0.8.0'
20
23
  s.add_dependency 'thor', '~> 0.19.0'
21
24
  s.add_dependency 'http_router', '~> 0.11.2'
22
- s.add_dependency 'tzispa_helpers', '~> 0.2.2'
25
+ s.add_dependency 'tzispa_helpers', '~> 0.3'
23
26
  s.add_dependency 'tzispa_utils', '~> 0.3'
24
27
  s.add_dependency 'tzispa_rig', '~> 0.5'
25
- s.add_dependency 'tzispa_data', '~> 0.3'
28
+ s.add_dependency 'tzispa_data', '~> 0.4'
29
+ s.add_dependency 'dotenv', '~> 2.2'
30
+
31
+ s.add_development_dependency 'shotgun'
26
32
 
27
- s.files = Dir.glob("{lib,bin}/**/*") + %w(README.md CHANGELOG.md LICENSE tzispa.gemspec)
33
+ s.files = Dir.glob('{lib,bin}/**/*') + %w(README.md CHANGELOG.md LICENSE tzispa.gemspec)
28
34
  s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) }
29
35
  s.require_paths = ['lib']
30
36
  end
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tzispa
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.1
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Juan Antonio Piñero
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-02-16 00:00:00.000000000 Z
11
+ date: 2017-03-13 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.14'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.14'
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: rack
15
29
  requirement: !ruby/object:Gem::Requirement
@@ -78,14 +92,14 @@ dependencies:
78
92
  requirements:
79
93
  - - "~>"
80
94
  - !ruby/object:Gem::Version
81
- version: 0.2.2
95
+ version: '0.3'
82
96
  type: :runtime
83
97
  prerelease: false
84
98
  version_requirements: !ruby/object:Gem::Requirement
85
99
  requirements:
86
100
  - - "~>"
87
101
  - !ruby/object:Gem::Version
88
- version: 0.2.2
102
+ version: '0.3'
89
103
  - !ruby/object:Gem::Dependency
90
104
  name: tzispa_utils
91
105
  requirement: !ruby/object:Gem::Requirement
@@ -120,15 +134,43 @@ dependencies:
120
134
  requirements:
121
135
  - - "~>"
122
136
  - !ruby/object:Gem::Version
123
- version: '0.3'
137
+ version: '0.4'
124
138
  type: :runtime
125
139
  prerelease: false
126
140
  version_requirements: !ruby/object:Gem::Requirement
127
141
  requirements:
128
142
  - - "~>"
129
143
  - !ruby/object:Gem::Version
130
- version: '0.3'
131
- description: A sparkling web framework based on Rack and inspired by Sinatra and Lotus
144
+ version: '0.4'
145
+ - !ruby/object:Gem::Dependency
146
+ name: dotenv
147
+ requirement: !ruby/object:Gem::Requirement
148
+ requirements:
149
+ - - "~>"
150
+ - !ruby/object:Gem::Version
151
+ version: '2.2'
152
+ type: :runtime
153
+ prerelease: false
154
+ version_requirements: !ruby/object:Gem::Requirement
155
+ requirements:
156
+ - - "~>"
157
+ - !ruby/object:Gem::Version
158
+ version: '2.2'
159
+ - !ruby/object:Gem::Dependency
160
+ name: shotgun
161
+ requirement: !ruby/object:Gem::Requirement
162
+ requirements:
163
+ - - ">="
164
+ - !ruby/object:Gem::Version
165
+ version: '0'
166
+ type: :development
167
+ prerelease: false
168
+ version_requirements: !ruby/object:Gem::Requirement
169
+ requirements:
170
+ - - ">="
171
+ - !ruby/object:Gem::Version
172
+ version: '0'
173
+ description: A sparkling web framework Rack based
132
174
  email:
133
175
  - japinero@area-integral.com
134
176
  executables:
@@ -145,13 +187,21 @@ files:
145
187
  - lib/tzispa/app.rb
146
188
  - lib/tzispa/bin/tzispa
147
189
  - lib/tzispa/cli.rb
148
- - lib/tzispa/command/api.rb
149
- - lib/tzispa/command/app.rb
150
- - lib/tzispa/command/cli/generate.rb
151
- - lib/tzispa/command/project.rb
152
- - lib/tzispa/command/rig.rb
153
- - lib/tzispa/config/appconfig.rb
190
+ - lib/tzispa/commands/api.rb
191
+ - lib/tzispa/commands/app.rb
192
+ - lib/tzispa/commands/cli/generate.rb
193
+ - lib/tzispa/commands/command.rb
194
+ - lib/tzispa/commands/console.rb
195
+ - lib/tzispa/commands/helpers/i18n.rb
196
+ - lib/tzispa/commands/helpers/project.rb
197
+ - lib/tzispa/commands/helpers/repository.rb
198
+ - lib/tzispa/commands/project.rb
199
+ - lib/tzispa/commands/repository.rb
200
+ - lib/tzispa/commands/rig.rb
201
+ - lib/tzispa/commands/server.rb
202
+ - lib/tzispa/config/app_config.rb
154
203
  - lib/tzispa/config/base.rb
204
+ - lib/tzispa/config/db_config.rb
155
205
  - lib/tzispa/config/yaml.rb
156
206
  - lib/tzispa/context.rb
157
207
  - lib/tzispa/controller/api.rb
@@ -160,14 +210,15 @@ files:
160
210
  - lib/tzispa/controller/exceptions.rb
161
211
  - lib/tzispa/controller/http_error.rb
162
212
  - lib/tzispa/controller/layout.rb
163
- - lib/tzispa/controller/signed_api.rb
164
213
  - lib/tzispa/domain.rb
214
+ - lib/tzispa/env.rb
215
+ - lib/tzispa/environment.rb
165
216
  - lib/tzispa/http/context.rb
166
217
  - lib/tzispa/http/request.rb
167
218
  - lib/tzispa/http/response.rb
168
- - lib/tzispa/http/session_flash_bag.rb
169
- - lib/tzispa/middleware.rb
170
- - lib/tzispa/routes.rb
219
+ - lib/tzispa/route_set.rb
220
+ - lib/tzispa/server.rb
221
+ - lib/tzispa/tzisparc.rb
171
222
  - lib/tzispa/version.rb
172
223
  - tzispa.gemspec
173
224
  homepage: https://github.com/japiber/tzispa
@@ -1,24 +0,0 @@
1
- require 'tzispa/controller/api'
2
-
3
- module Tzispa
4
- module Command
5
-
6
- class Api
7
-
8
- attr_reader :name, :domain
9
-
10
- def initialize(name, app)
11
- @prj = Project.open
12
- raise "Application '#{app}' does not exists in project file" unless @prj.apps.include?(app)
13
- @domain = Tzispa::Domain.new app
14
- @name = name
15
- end
16
-
17
- def generate
18
- Tzispa::Controller::Api.new.generate_handler(domain, name)
19
- end
20
-
21
- end
22
-
23
- end
24
- end
@@ -1,95 +0,0 @@
1
- require 'json'
2
- require 'tzispa/domain'
3
- require 'tzispa/utils/string'
4
- require 'tzispa/utils/indenter'
5
- require 'tzispa/config/appconfig'
6
- require_relative 'project'
7
-
8
- module Tzispa
9
- module Command
10
-
11
- class App
12
-
13
- using Tzispa::Utils
14
-
15
- APP_STRUCTURE = [
16
- 'api',
17
- 'locales',
18
- 'error',
19
- 'helpers',
20
- 'middleware',
21
- 'rig',
22
- 'rig/block',
23
- 'rig/layout',
24
- 'rig/static',
25
- 'services'
26
- ]
27
-
28
- attr_reader :domain, :config
29
-
30
- def initialize(name)
31
- @domain = Tzispa::Domain.new(name)
32
- end
33
-
34
- def generate(host, mount_path=nil)
35
- update_project
36
- create_structure
37
- create_class mount_path
38
- create_appconfig(host)
39
- create_home_layout
40
- end
41
-
42
- private
43
-
44
- def app_class_name
45
- @app_class_name ||= "#{domain.name.camelize}App"
46
- end
47
-
48
- def update_project
49
- prj = Project.open
50
- raise "Application '#{domain.name}' already exist in this project" if prj.apps.include?(domain.name)
51
- prj.apps << domain.name
52
- prj.close
53
- end
54
-
55
- def create_class(mount_path=nil)
56
- mount_path ||= DEFAULT_MOUNT_PATH
57
- File.open("#{Project::START_FILE}","a") do |f|
58
- f.puts write_app_code(mount_path)
59
- end
60
- end
61
-
62
- def write_app_code(mount_path)
63
- mount_path = "/#{mount_path}" unless mount_path.start_with? '/'
64
- Tzispa::Utils::Indenter.new(2).tap { |code|
65
- code << "(Class.new Tzispa::Application).run :#{domain.name}, builder: self#{", on: \'"+mount_path+"\'" if mount_path && mount_path.length > 0} do\n\n"
66
- code.indent << "route_rig_signed_api '/api_:sign/:handler/:verb(~:predicate)(/:sufix)'\n"
67
- code << "route_rig_api '/api/:handler/:verb(~:predicate)(/:sufix)'\n"
68
- code << "route_rig_index '/'\n\n"
69
- code.unindent << "end\n\n"
70
- }.to_s
71
- end
72
-
73
- def create_structure
74
- unless File.exist? domain.path
75
- Dir.mkdir "#{domain.path}"
76
- APP_STRUCTURE.each { |appdir|
77
- Dir.mkdir "#{domain.path}/#{appdir}"
78
- }
79
- end
80
- end
81
-
82
- def create_appconfig(host)
83
- appconfig = Tzispa::Config::AppConfig.new(domain)
84
- @config = appconfig.create_default host: host
85
- end
86
-
87
- def create_home_layout
88
- tpl = Tzispa::Rig::Template.new(name: config&.default_layout || 'index', type: :layout, domain: domain, format: :htm)
89
- tpl.create("<html><body><h1>Welcome: Tzispa #{domain.name} application is working!</h1></body></html>")
90
- end
91
-
92
- end
93
-
94
- end
95
- end
@@ -1,51 +0,0 @@
1
- require 'thor'
2
-
3
-
4
- module Tzispa
5
- module Command
6
- module Cli
7
-
8
- class Generate < Thor
9
-
10
- require 'tzispa/command/project'
11
- desc 'project', 'Generate Tzispa project components'
12
- def project(name)
13
- Tzispa::Command::Project.new(name).generate
14
- puts "Project '#{name}' has been created"
15
- end
16
-
17
- require 'tzispa/command/app'
18
- desc 'app', 'Generate new application into a project'
19
- method_option :mount, :aliases => "-m", :desc => "The mount point for this app", :default => ""
20
- method_option :host, :aliases => "-h", :desc => "The hostname used for this app ", :required => true
21
- def app(name)
22
- tzapp = Tzispa::Command::App.new(name)
23
- tzapp.generate(options[:host], options[:mount])
24
- puts "App '#{name}' has been created"
25
- end
26
-
27
- require 'tzispa/command/rig'
28
- desc 'rig', 'Generate new rig template'
29
- method_option :app, :aliases => "-a", :desc => "The app where the new template will be created", :required => true
30
- method_option :type, :aliases => "-t", :desc => "The template type: block, static or layout ", :required => true
31
- def rig(name)
32
- tpl = Tzispa::Command::Rig.new(name, options[:app], options[:type])
33
- tpl.generate
34
- puts "Rig #{options[:type]} template '#{name}' has been created in #{options[:app]}"
35
- end
36
-
37
- require 'tzispa/command/api'
38
- desc 'api', 'Generate new api handler'
39
- method_option :app, :aliases => "-a", :desc => "The app where the api handler will be created", :required => true
40
- def api(name)
41
- hnd = Tzispa::Command::Api.new(name, options[:app])
42
- hnd.generate
43
- puts "Api handler '#{name}' has been created in #{options[:app]}"
44
- end
45
-
46
-
47
- end
48
-
49
- end
50
- end
51
- end