hanami-cli 2.2.0 → 2.3.0.beta1
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.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yml +9 -0
- data/CHANGELOG.md +43 -0
- data/Gemfile +3 -1
- data/hanami-cli.gemspec +2 -0
- data/lib/hanami/cli/command.rb +5 -11
- data/lib/hanami/cli/commands/app/command.rb +5 -5
- data/lib/hanami/cli/commands/app/console.rb +1 -0
- data/lib/hanami/cli/commands/app/db/command.rb +0 -1
- data/lib/hanami/cli/commands/app/db/drop.rb +2 -2
- data/lib/hanami/cli/commands/app/db/rollback.rb +204 -0
- data/lib/hanami/cli/commands/app/db/utils/mysql.rb +3 -2
- data/lib/hanami/cli/commands/app/db/utils/postgres.rb +3 -1
- data/lib/hanami/cli/commands/app/generate/action.rb +32 -40
- data/lib/hanami/cli/commands/app/generate/command.rb +54 -17
- data/lib/hanami/cli/commands/app/generate/component.rb +4 -19
- data/lib/hanami/cli/commands/app/generate/part.rb +4 -21
- data/lib/hanami/cli/commands/app/generate/slice.rb +2 -2
- data/lib/hanami/cli/commands/app/generate/view.rb +5 -24
- data/lib/hanami/cli/commands/app/install.rb +12 -0
- data/lib/hanami/cli/commands/app/server.rb +0 -1
- data/lib/hanami/cli/commands/app.rb +1 -0
- data/lib/hanami/cli/commands/gem/new.rb +37 -7
- data/lib/hanami/cli/errors.rb +26 -0
- data/lib/hanami/cli/files.rb +20 -6
- data/lib/hanami/cli/generators/app/action.rb +78 -101
- data/lib/hanami/cli/generators/app/component.rb +11 -33
- data/lib/hanami/cli/generators/app/migration.rb +1 -1
- data/lib/hanami/cli/generators/app/operation.rb +4 -5
- data/lib/hanami/cli/generators/app/part.rb +42 -65
- data/lib/hanami/cli/generators/app/relation.rb +4 -5
- data/lib/hanami/cli/generators/app/repo.rb +3 -5
- data/lib/hanami/cli/generators/app/ruby_class_file.rb +32 -0
- data/lib/hanami/cli/generators/app/ruby_file.rb +128 -0
- data/lib/hanami/cli/generators/app/ruby_module_file.rb +28 -0
- data/lib/hanami/cli/generators/app/slice.rb +130 -37
- data/lib/hanami/cli/generators/app/struct.rb +3 -4
- data/lib/hanami/cli/generators/app/view.rb +40 -45
- data/lib/hanami/cli/generators/context.rb +6 -0
- data/lib/hanami/cli/generators/gem/app/assets.js +14 -13
- data/lib/hanami/cli/generators/gem/app/dev +1 -1
- data/lib/hanami/cli/generators/gem/app/gemfile.erb +5 -0
- data/lib/hanami/cli/generators/gem/app/gitignore.erb +3 -1
- data/lib/hanami/cli/generators/gem/app/rakefile.erb +3 -0
- data/lib/hanami/cli/generators/gem/app/readme.erb +14 -0
- data/lib/hanami/cli/generators/gem/app.rb +40 -37
- data/lib/hanami/cli/ruby_file_generator.rb +17 -8
- data/lib/hanami/cli/server.rb +15 -1
- data/lib/hanami/cli/version.rb +1 -1
- data/lib/hanami/console/context.rb +5 -0
- metadata +35 -41
- data/lib/hanami/cli/generators/app/action/action.erb +0 -17
- data/lib/hanami/cli/generators/app/action/slice_action.erb +0 -17
- data/lib/hanami/cli/generators/app/action/slice_template.html.erb +0 -1
- data/lib/hanami/cli/generators/app/action/slice_view.erb +0 -10
- data/lib/hanami/cli/generators/app/action/template.erb +0 -0
- data/lib/hanami/cli/generators/app/action/template.html.erb +0 -1
- data/lib/hanami/cli/generators/app/action/view.erb +0 -10
- data/lib/hanami/cli/generators/app/action_context.rb +0 -90
- data/lib/hanami/cli/generators/app/component/component.erb +0 -8
- data/lib/hanami/cli/generators/app/component/slice_component.erb +0 -8
- data/lib/hanami/cli/generators/app/component_context.rb +0 -82
- data/lib/hanami/cli/generators/app/part/app_base_part.erb +0 -9
- data/lib/hanami/cli/generators/app/part/app_part.erb +0 -13
- data/lib/hanami/cli/generators/app/part/slice_base_part.erb +0 -9
- data/lib/hanami/cli/generators/app/part/slice_part.erb +0 -13
- data/lib/hanami/cli/generators/app/part_context.rb +0 -82
- data/lib/hanami/cli/generators/app/ruby_file_writer.rb +0 -151
- data/lib/hanami/cli/generators/app/slice/action.erb +0 -7
- data/lib/hanami/cli/generators/app/slice/app_css.erb +0 -5
- data/lib/hanami/cli/generators/app/slice/app_js.erb +0 -1
- data/lib/hanami/cli/generators/app/slice/app_layout.erb +0 -18
- data/lib/hanami/cli/generators/app/slice/helpers.erb +0 -10
- data/lib/hanami/cli/generators/app/slice/keep.erb +0 -0
- data/lib/hanami/cli/generators/app/slice/operation.erb +0 -7
- data/lib/hanami/cli/generators/app/slice/relation.erb +0 -8
- data/lib/hanami/cli/generators/app/slice/repo.erb +0 -8
- data/lib/hanami/cli/generators/app/slice/routes.erb +0 -3
- data/lib/hanami/cli/generators/app/slice/struct.erb +0 -8
- data/lib/hanami/cli/generators/app/slice/view.erb +0 -7
- data/lib/hanami/cli/generators/app/slice_context.rb +0 -72
- data/lib/hanami/cli/generators/app/view/app_template.html.erb +0 -1
- data/lib/hanami/cli/generators/app/view/app_view.erb +0 -10
- data/lib/hanami/cli/generators/app/view/slice_template.html.erb +0 -1
- data/lib/hanami/cli/generators/app/view/slice_view.erb +0 -10
- data/lib/hanami/cli/generators/app/view_context.rb +0 -88
@@ -21,36 +21,73 @@ module Hanami
|
|
21
21
|
|
22
22
|
# @since 2.2.0
|
23
23
|
# @api private
|
24
|
-
def initialize(
|
25
|
-
fs:,
|
26
|
-
inflector:,
|
27
|
-
**opts
|
28
|
-
)
|
24
|
+
def initialize(fs:, out:, **)
|
29
25
|
super
|
30
|
-
@generator = generator_class.new(fs
|
26
|
+
@generator = generator_class.new(fs:, inflector:, out:)
|
31
27
|
end
|
32
28
|
|
29
|
+
# @since 2.2.0
|
30
|
+
# @api private
|
33
31
|
def generator_class
|
34
|
-
# Must be implemented by subclasses, with
|
35
|
-
# fs:,
|
32
|
+
# Must be implemented by subclasses, with initialize method that takes:
|
33
|
+
# fs:, out:
|
36
34
|
end
|
37
35
|
|
38
36
|
# @since 2.2.0
|
39
37
|
# @api private
|
40
|
-
def call(name:, slice: nil, **)
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
namespace: slice,
|
45
|
-
base_path: fs.join("slices", inflector.underscore(slice))
|
46
|
-
)
|
47
|
-
else
|
38
|
+
def call(name:, slice: nil, **opts)
|
39
|
+
slice ||= detect_slice_from_cwd
|
40
|
+
|
41
|
+
if slice.nil?
|
48
42
|
generator.call(
|
49
43
|
key: name,
|
50
44
|
namespace: app.namespace,
|
51
|
-
base_path: "app"
|
45
|
+
base_path: "app",
|
46
|
+
**opts,
|
52
47
|
)
|
48
|
+
return
|
53
49
|
end
|
50
|
+
|
51
|
+
slice_root = slice.respond_to?(:root) ? slice.root : detect_slice_root(slice)
|
52
|
+
raise MissingSliceError.new(slice) unless fs.exist?(slice_root)
|
53
|
+
|
54
|
+
generator.call(
|
55
|
+
key: name,
|
56
|
+
namespace: slice,
|
57
|
+
base_path: slice_root,
|
58
|
+
**opts,
|
59
|
+
)
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
def detect_slice_from_cwd
|
65
|
+
slices_by_root = app.slices.with_nested.each.to_h { |slice| [slice.root.to_s, slice] }
|
66
|
+
slices_by_root[fs.pwd]
|
67
|
+
end
|
68
|
+
|
69
|
+
# Returns the root for the given slice name.
|
70
|
+
#
|
71
|
+
# This currently works with top-level slices only, and it simply appends the slice's
|
72
|
+
# name onto the "slices/" dir, returning e.g. "slices/main" when given "main".
|
73
|
+
#
|
74
|
+
# TODO: Make this work with nested slices when given slash-delimited slice names like
|
75
|
+
# "parent/child", which should look for "slices/parent/slices/child".
|
76
|
+
#
|
77
|
+
# This method makes two checks for the slice root (building off both `app.root` as well
|
78
|
+
# as `fs`). This is entirely to account for how we test commands, with most tests using
|
79
|
+
# an in-memory `fs` adapter, any files created via which will be invisible to the `app`,
|
80
|
+
# which doesn't know about the `fs`.
|
81
|
+
#
|
82
|
+
# FIXME: It would be better to find a way for this to make one check only. An ideal
|
83
|
+
# approach would be to use the slice_name to find actual slice registered within
|
84
|
+
# `app.slices`. To do this, we'd probably need to stop testing with an in-memory `fs`
|
85
|
+
# here.
|
86
|
+
def detect_slice_root(slice_name)
|
87
|
+
slice_root_in_fs = fs.join("slices", inflector.underscore(slice_name))
|
88
|
+
return slice_root_in_fs if fs.exist?(slice_root_in_fs)
|
89
|
+
|
90
|
+
app.root.join("slices", inflector.underscore(slice_name))
|
54
91
|
end
|
55
92
|
end
|
56
93
|
end
|
@@ -3,6 +3,7 @@
|
|
3
3
|
require "dry/inflector"
|
4
4
|
require "dry/files"
|
5
5
|
require "shellwords"
|
6
|
+
|
6
7
|
module Hanami
|
7
8
|
module CLI
|
8
9
|
module Commands
|
@@ -10,9 +11,8 @@ module Hanami
|
|
10
11
|
module Generate
|
11
12
|
# @api private
|
12
13
|
# @since 2.2.0
|
13
|
-
class Component <
|
14
|
+
class Component < Command
|
14
15
|
argument :name, required: true, desc: "Component name"
|
15
|
-
option :slice, required: false, desc: "Slice name"
|
16
16
|
|
17
17
|
example [
|
18
18
|
%(isbn_decoder (MyApp::IsbnDecoder)),
|
@@ -20,26 +20,11 @@ module Hanami
|
|
20
20
|
%(isbn_decoder --slice=admin (Admin::IsbnDecoder)),
|
21
21
|
%(Exporters::Complete::CSV (MyApp::Exporters::Complete::CSV)),
|
22
22
|
]
|
23
|
-
attr_reader :generator
|
24
|
-
private :generator
|
25
23
|
|
26
|
-
# @api private
|
27
24
|
# @since 2.2.0
|
28
|
-
def initialize(
|
29
|
-
fs:, inflector:,
|
30
|
-
generator: Generators::App::Component.new(fs: fs, inflector: inflector),
|
31
|
-
**opts
|
32
|
-
)
|
33
|
-
@generator = generator
|
34
|
-
super(fs: fs, inflector: inflector, **opts)
|
35
|
-
end
|
36
|
-
|
37
25
|
# @api private
|
38
|
-
|
39
|
-
|
40
|
-
slice = inflector.underscore(Shellwords.shellescape(slice)) if slice
|
41
|
-
|
42
|
-
generator.call(app.namespace, name, slice)
|
26
|
+
def generator_class
|
27
|
+
Generators::App::Component
|
43
28
|
end
|
44
29
|
end
|
45
30
|
end
|
@@ -11,12 +11,12 @@ module Hanami
|
|
11
11
|
module Generate
|
12
12
|
# @since 2.1.0
|
13
13
|
# @api private
|
14
|
-
class Part <
|
14
|
+
class Part < Command
|
15
15
|
DEFAULT_SKIP_TESTS = false
|
16
16
|
private_constant :DEFAULT_SKIP_TESTS
|
17
17
|
|
18
18
|
argument :name, required: true, desc: "Part name"
|
19
|
-
|
19
|
+
|
20
20
|
option \
|
21
21
|
:skip_tests,
|
22
22
|
required: false,
|
@@ -28,26 +28,9 @@ module Hanami
|
|
28
28
|
%(book (MyApp::Views::Parts::Book)),
|
29
29
|
%(book --slice=admin (Admin::Views::Parts::Book)),
|
30
30
|
]
|
31
|
-
attr_reader :generator
|
32
|
-
private :generator
|
33
|
-
|
34
|
-
# @since 2.0.0
|
35
|
-
# @api private
|
36
|
-
def initialize(
|
37
|
-
fs:, inflector:,
|
38
|
-
generator: Generators::App::Part.new(fs: fs, inflector: inflector),
|
39
|
-
**opts
|
40
|
-
)
|
41
|
-
super(fs: fs, inflector: inflector, **opts)
|
42
|
-
@generator = generator
|
43
|
-
end
|
44
|
-
|
45
|
-
# @since 2.0.0
|
46
|
-
# @api private
|
47
|
-
def call(name:, slice: nil, skip_tests: DEFAULT_SKIP_TESTS, **) # rubocop:disable Lint/UnusedMethodArgument
|
48
|
-
slice = inflector.underscore(Shellwords.shellescape(slice)) if slice
|
49
31
|
|
50
|
-
|
32
|
+
def generator_class
|
33
|
+
Generators::App::Part
|
51
34
|
end
|
52
35
|
end
|
53
36
|
end
|
@@ -49,11 +49,11 @@ module Hanami
|
|
49
49
|
# @since 2.0.0
|
50
50
|
# @api private
|
51
51
|
def initialize(
|
52
|
-
fs:,
|
52
|
+
fs:,
|
53
53
|
generator: Generators::App::Slice.new(fs: fs, inflector: inflector),
|
54
54
|
**opts
|
55
55
|
)
|
56
|
-
super(fs: fs,
|
56
|
+
super(fs: fs, **opts)
|
57
57
|
@generator = generator
|
58
58
|
end
|
59
59
|
|
@@ -13,40 +13,21 @@ module Hanami
|
|
13
13
|
module Generate
|
14
14
|
# @since 2.0.0
|
15
15
|
# @api private
|
16
|
-
class View <
|
17
|
-
# TODO: make
|
18
|
-
DEFAULT_FORMAT = "html"
|
19
|
-
private_constant :DEFAULT_FORMAT
|
20
|
-
|
16
|
+
class View < Command
|
17
|
+
# TODO: make format configurable
|
21
18
|
# TODO: make engine configurable
|
22
19
|
|
23
20
|
argument :name, required: true, desc: "View name"
|
24
|
-
option :slice, required: false, desc: "Slice name"
|
25
21
|
|
26
22
|
example [
|
27
23
|
%(books.index (MyApp::Actions::Books::Index)),
|
28
24
|
%(books.index --slice=admin (Admin::Actions::Books::Index)),
|
29
25
|
]
|
30
|
-
attr_reader :generator
|
31
|
-
private :generator
|
32
26
|
|
33
|
-
# @since 2.
|
27
|
+
# @since 2.2.0
|
34
28
|
# @api private
|
35
|
-
def
|
36
|
-
|
37
|
-
generator: Generators::App::View.new(fs: fs, inflector: inflector),
|
38
|
-
**opts
|
39
|
-
)
|
40
|
-
super(fs: fs, inflector: inflector, **opts)
|
41
|
-
@generator = generator
|
42
|
-
end
|
43
|
-
|
44
|
-
# @since 2.0.0
|
45
|
-
# @api private
|
46
|
-
def call(name:, format: DEFAULT_FORMAT, slice: nil, **)
|
47
|
-
slice = inflector.underscore(Shellwords.shellescape(slice)) if slice
|
48
|
-
|
49
|
-
generator.call(app.namespace, name, format, slice)
|
29
|
+
def generator_class
|
30
|
+
Generators::App::View
|
50
31
|
end
|
51
32
|
end
|
52
33
|
end
|
@@ -33,9 +33,21 @@ module Hanami
|
|
33
33
|
# @api private
|
34
34
|
option :head, type: :flag, desc: "Install head deps", default: DEFAULT_HEAD
|
35
35
|
|
36
|
+
# @api private
|
37
|
+
private attr_reader :bundler
|
38
|
+
|
39
|
+
def initialize(
|
40
|
+
fs:,
|
41
|
+
bundler: CLI::Bundler.new(fs: fs),
|
42
|
+
**opts
|
43
|
+
)
|
44
|
+
@bundler = bundler
|
45
|
+
end
|
46
|
+
|
36
47
|
# @since 2.0.0
|
37
48
|
# @api private
|
38
49
|
def call(head: DEFAULT_HEAD, **)
|
50
|
+
bundler.install!
|
39
51
|
end
|
40
52
|
end
|
41
53
|
end
|
@@ -32,6 +32,7 @@ module Hanami
|
|
32
32
|
db.register "create", DB::Create
|
33
33
|
db.register "drop", DB::Drop
|
34
34
|
db.register "migrate", DB::Migrate
|
35
|
+
db.register "rollback", DB::Rollback
|
35
36
|
db.register "structure dump", DB::Structure::Dump
|
36
37
|
db.register "structure load", DB::Structure::Load
|
37
38
|
db.register "seed", DB::Seed
|
@@ -30,6 +30,11 @@ module Hanami
|
|
30
30
|
SKIP_DB_DEFAULT = false
|
31
31
|
private_constant :SKIP_DB_DEFAULT
|
32
32
|
|
33
|
+
# @since 2.2.0
|
34
|
+
# @api private
|
35
|
+
SKIP_VIEW_DEFAULT = false
|
36
|
+
private_constant :SKIP_VIEW_DEFAULT
|
37
|
+
|
33
38
|
# @since 2.2.0
|
34
39
|
# @api private
|
35
40
|
DATABASE_SQLITE = "sqlite"
|
@@ -46,6 +51,9 @@ module Hanami
|
|
46
51
|
# @api private
|
47
52
|
SUPPORTED_DATABASES = [DATABASE_SQLITE, DATABASE_POSTGRES, DATABASE_MYSQL].freeze
|
48
53
|
|
54
|
+
# @api private
|
55
|
+
FORBIDDEN_APP_NAMES = %w[app slice].freeze
|
56
|
+
|
49
57
|
desc "Generate a new Hanami app"
|
50
58
|
|
51
59
|
# @since 2.0.0
|
@@ -76,6 +84,12 @@ module Hanami
|
|
76
84
|
default: SKIP_DB_DEFAULT,
|
77
85
|
desc: "Skip including hanami-db"
|
78
86
|
|
87
|
+
# @since 2.2.0
|
88
|
+
# @api private
|
89
|
+
option :skip_view, type: :flag, required: false,
|
90
|
+
default: SKIP_VIEW_DEFAULT,
|
91
|
+
desc: "Skip including hanami-view"
|
92
|
+
|
79
93
|
# @since 2.2.0
|
80
94
|
# @api private
|
81
95
|
option :database, type: :string, required: false,
|
@@ -87,8 +101,9 @@ module Hanami
|
|
87
101
|
"bookshelf # Generate a new Hanami app in `bookshelf/' directory, using `Bookshelf' namespace",
|
88
102
|
"bookshelf --head # Generate a new Hanami app, using Hanami HEAD version from GitHub `main' branches",
|
89
103
|
"bookshelf --skip-install # Generate a new Hanami app, but it skips Hanami installation",
|
90
|
-
"bookshelf --skip-assets # Generate a new Hanami app without
|
104
|
+
"bookshelf --skip-assets # Generate a new Hanami app without hanami-assets",
|
91
105
|
"bookshelf --skip-db # Generate a new Hanami app without hanami-db",
|
106
|
+
"bookshelf --skip-view # Generate a new Hanami app without hanami-view",
|
92
107
|
"bookshelf --database={sqlite|postgres|mysql} # Generate a new Hanami app with a specified database (default: sqlite)",
|
93
108
|
]
|
94
109
|
# rubocop:enable Layout/LineLength
|
@@ -98,13 +113,13 @@ module Hanami
|
|
98
113
|
# @since 2.0.0
|
99
114
|
# @api private
|
100
115
|
def initialize(
|
101
|
-
fs:,
|
116
|
+
fs:,
|
102
117
|
bundler: CLI::Bundler.new(fs: fs),
|
103
118
|
generator: Generators::Gem::App.new(fs: fs, inflector: inflector),
|
104
119
|
system_call: SystemCall.new,
|
105
120
|
**opts
|
106
121
|
)
|
107
|
-
super(fs: fs,
|
122
|
+
super(fs: fs, **opts)
|
108
123
|
@bundler = bundler
|
109
124
|
@generator = generator
|
110
125
|
@system_call = system_call
|
@@ -120,13 +135,14 @@ module Hanami
|
|
120
135
|
skip_install: SKIP_INSTALL_DEFAULT,
|
121
136
|
skip_assets: SKIP_ASSETS_DEFAULT,
|
122
137
|
skip_db: SKIP_DB_DEFAULT,
|
138
|
+
skip_view: SKIP_VIEW_DEFAULT,
|
123
139
|
database: nil
|
124
140
|
)
|
125
141
|
# rubocop:enable Metrics/ParameterLists
|
126
142
|
app = inflector.underscore(app)
|
127
143
|
|
128
144
|
raise PathAlreadyExistsError.new(app) if fs.exist?(app)
|
129
|
-
raise
|
145
|
+
raise ForbiddenAppNameError.new(app) if FORBIDDEN_APP_NAMES.include?(app)
|
130
146
|
|
131
147
|
normalized_database ||= normalize_database(database)
|
132
148
|
|
@@ -138,17 +154,18 @@ module Hanami
|
|
138
154
|
head: head,
|
139
155
|
skip_assets: skip_assets,
|
140
156
|
skip_db: skip_db,
|
157
|
+
skip_view: skip_view,
|
141
158
|
database: normalized_database
|
142
159
|
)
|
143
160
|
generator.call(app, context: context) do
|
144
161
|
if skip_install
|
145
162
|
out.puts "Skipping installation, please enter `#{app}' directory and run `bundle exec hanami install'"
|
146
163
|
else
|
147
|
-
out.puts "Running
|
164
|
+
out.puts "Running bundle install..."
|
148
165
|
bundler.install!
|
149
166
|
|
150
167
|
unless skip_assets
|
151
|
-
out.puts "Running
|
168
|
+
out.puts "Running npm install..."
|
152
169
|
system_call.call("npm", ["install"]).tap do |result|
|
153
170
|
unless result.successful?
|
154
171
|
puts "NPM ERROR:"
|
@@ -157,8 +174,11 @@ module Hanami
|
|
157
174
|
end
|
158
175
|
end
|
159
176
|
|
160
|
-
out.puts "Running
|
177
|
+
out.puts "Running hanami install..."
|
161
178
|
run_install_command!(head: head)
|
179
|
+
|
180
|
+
out.puts "Initializing git repository..."
|
181
|
+
init_git_repository
|
162
182
|
end
|
163
183
|
end
|
164
184
|
end
|
@@ -194,6 +214,16 @@ module Hanami
|
|
194
214
|
end
|
195
215
|
end
|
196
216
|
end
|
217
|
+
|
218
|
+
# @api private
|
219
|
+
def init_git_repository
|
220
|
+
system_call.call("git", ["init"]).tap do |result|
|
221
|
+
unless result.successful?
|
222
|
+
out.puts "WARNING: Failed to initialize git repository"
|
223
|
+
out.puts(result.err.lines.map { |line| line.prepend(" ") })
|
224
|
+
end
|
225
|
+
end
|
226
|
+
end
|
197
227
|
end
|
198
228
|
end
|
199
229
|
end
|
data/lib/hanami/cli/errors.rb
CHANGED
@@ -44,6 +44,24 @@ module Hanami
|
|
44
44
|
end
|
45
45
|
end
|
46
46
|
|
47
|
+
# @api public
|
48
|
+
class FileAlreadyExistsError < Error
|
49
|
+
ERROR_MESSAGE = <<~ERROR.chomp
|
50
|
+
The file `%{file_path}` could not be generated because it already exists.
|
51
|
+
ERROR
|
52
|
+
|
53
|
+
def initialize(file_path)
|
54
|
+
super(ERROR_MESSAGE % {file_path:})
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# @api public
|
59
|
+
class ForbiddenAppNameError < Error
|
60
|
+
def initialize(name)
|
61
|
+
super("Cannot create new Hanami app with the name: `#{name}'")
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
47
65
|
# @since 2.0.0
|
48
66
|
# @api public
|
49
67
|
class MissingSliceError < Error
|
@@ -100,6 +118,14 @@ module Hanami
|
|
100
118
|
end
|
101
119
|
end
|
102
120
|
|
121
|
+
# @since 2.2.0
|
122
|
+
# @api public
|
123
|
+
class DatabaseExistenceCheckError < Error
|
124
|
+
def initialize(original_message)
|
125
|
+
super("Could not check if the database exists. Error message:\n#{original_message}")
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
103
129
|
# @since 2.2.0
|
104
130
|
# @api public
|
105
131
|
class ConflictingOptionsError < Error
|
data/lib/hanami/cli/files.rb
CHANGED
@@ -14,6 +14,13 @@ module Hanami
|
|
14
14
|
@out = out
|
15
15
|
end
|
16
16
|
|
17
|
+
# @api private
|
18
|
+
def create(path, *content)
|
19
|
+
raise FileAlreadyExistsError.new(path) if exist?(path)
|
20
|
+
|
21
|
+
write(path, *content)
|
22
|
+
end
|
23
|
+
|
17
24
|
# @since 2.0.0
|
18
25
|
# @api private
|
19
26
|
def write(path, *content)
|
@@ -33,10 +40,10 @@ module Hanami
|
|
33
40
|
# @since 2.0.0
|
34
41
|
# @api private
|
35
42
|
def mkdir(path)
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
43
|
+
return if exist?(path)
|
44
|
+
|
45
|
+
super
|
46
|
+
created(dir_path(path))
|
40
47
|
end
|
41
48
|
|
42
49
|
# @since 2.0.0
|
@@ -46,6 +53,13 @@ module Hanami
|
|
46
53
|
super
|
47
54
|
end
|
48
55
|
|
56
|
+
def touch(path)
|
57
|
+
return if exist?(path)
|
58
|
+
|
59
|
+
super
|
60
|
+
created(path)
|
61
|
+
end
|
62
|
+
|
49
63
|
private
|
50
64
|
|
51
65
|
attr_reader :out
|
@@ -77,10 +91,10 @@ module Hanami
|
|
77
91
|
end
|
78
92
|
|
79
93
|
def within_folder(path)
|
80
|
-
out.puts "-> Within #{
|
94
|
+
out.puts "-> Within #{dir_path(path)}"
|
81
95
|
end
|
82
96
|
|
83
|
-
def
|
97
|
+
def dir_path(path)
|
84
98
|
path + ::File::SEPARATOR
|
85
99
|
end
|
86
100
|
end
|