hanami-cli 2.2.0.beta1 → 2.2.0.beta2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yml +13 -2
- data/.rubocop.yml +2 -0
- data/CHANGELOG.md +15 -2
- data/Gemfile +3 -0
- data/README.md +2 -0
- data/docker-compose.yml +6 -1
- data/lib/hanami/cli/command.rb +1 -1
- data/lib/hanami/cli/commands/app/db/command.rb +62 -30
- data/lib/hanami/cli/commands/app/db/create.rb +4 -2
- data/lib/hanami/cli/commands/app/db/drop.rb +4 -2
- data/lib/hanami/cli/commands/app/db/migrate.rb +40 -8
- data/lib/hanami/cli/commands/app/db/prepare.rb +34 -8
- data/lib/hanami/cli/commands/app/db/seed.rb +12 -0
- data/lib/hanami/cli/commands/app/db/structure/dump.rb +7 -5
- data/lib/hanami/cli/commands/app/db/structure/load.rb +7 -5
- data/lib/hanami/cli/commands/app/db/utils/database.rb +44 -14
- data/lib/hanami/cli/commands/app/db/utils/mysql.rb +57 -4
- data/lib/hanami/cli/commands/app/db/utils/postgres.rb +10 -8
- data/lib/hanami/cli/commands/app/db/version.rb +6 -3
- data/lib/hanami/cli/commands/app/generate/command.rb +13 -2
- data/lib/hanami/cli/commands/app/generate/migration.rb +20 -0
- data/lib/hanami/cli/commands/app/generate/relation.rb +0 -6
- data/lib/hanami/cli/commands/app/generate/repo.rb +3 -7
- data/lib/hanami/cli/files.rb +22 -0
- data/lib/hanami/cli/generators/app/migration.rb +6 -9
- data/lib/hanami/cli/generators/app/operation.rb +5 -4
- data/lib/hanami/cli/generators/app/relation.rb +5 -4
- data/lib/hanami/cli/generators/app/repo.rb +5 -4
- data/lib/hanami/cli/generators/app/ruby_file_writer.rb +39 -37
- data/lib/hanami/cli/generators/app/struct.rb +5 -4
- data/lib/hanami/cli/generators/context.rb +4 -4
- data/lib/hanami/cli/generators/gem/app/gitignore.erb +3 -0
- data/lib/hanami/cli/version.rb +1 -1
- metadata +3 -4
- data/lib/hanami/cli/generators/app/slice/entities.erb +0 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d62ed9aeff86f86693ffdf5acafb274e6e97a535a177bf46131c8c33141fc0e9
|
4
|
+
data.tar.gz: 86da7248a20712451a83b8e5167870e34fd508f2e5f41a107d9bf3a4dea1d376
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: affe042dfe0daf2dc93e1252b06d2d51dd5ea605c1287ad2500371bed6ee98e902cf9d19667458f86edadabb671f923b986bcd2a76a0e7d8821f4e0b9af6ecf6
|
7
|
+
data.tar.gz: b1a097c66c10495ef31fd0783083d542ac6e7a5be7ab94f11b9e1a0d68dc865e04d6f970e08b88d33dd3939b47736cc8893989cb037d070d3c5d2ff86d35ccad
|
data/.github/workflows/ci.yml
CHANGED
@@ -41,6 +41,17 @@ jobs:
|
|
41
41
|
- name: Run all tests
|
42
42
|
run: bundle exec rake spec
|
43
43
|
services:
|
44
|
+
mysql:
|
45
|
+
image: mysql:latest
|
46
|
+
env:
|
47
|
+
MYSQL_ROOT_PASSWORD: password
|
48
|
+
ports:
|
49
|
+
- 3307:3306
|
50
|
+
options: >-
|
51
|
+
--health-cmd "mysqladmin ping"
|
52
|
+
--health-interval 10s
|
53
|
+
--health-timeout 5s
|
54
|
+
--health-retries 3
|
44
55
|
postgres:
|
45
56
|
# Use postgres:14 for CLI compatibility with ubuntu-latest, currently ubuntu-22.04
|
46
57
|
# See https://github.com/actions/runner-images/blob/main/images/ubuntu/Ubuntu2204-Readme.md
|
@@ -48,10 +59,10 @@ jobs:
|
|
48
59
|
env:
|
49
60
|
POSTGRES_USER: postgres
|
50
61
|
POSTGRES_PASSWORD: password
|
62
|
+
ports:
|
63
|
+
- 5432:5432
|
51
64
|
options: >-
|
52
65
|
--health-cmd pg_isready
|
53
66
|
--health-interval 10s
|
54
67
|
--health-timeout 5s
|
55
68
|
--health-retries 5
|
56
|
-
ports:
|
57
|
-
- 5432:5432
|
data/.rubocop.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -2,9 +2,22 @@
|
|
2
2
|
|
3
3
|
Hanami Command Line Interface
|
4
4
|
|
5
|
+
## v2.2.0.beta2 - 2024-09-25
|
6
|
+
|
7
|
+
### Added
|
8
|
+
|
9
|
+
- [Tim Riley] MySQL support for `db` commands (#226)
|
10
|
+
- [Tim Riley] Support for multiple gateways in `db` commands (#232, #234, #237, #238)
|
11
|
+
|
12
|
+
### Changed
|
13
|
+
|
14
|
+
- [Kyle Plump, Tim Riley] Delete `.keep` files when generating new files into previously empty directory (#224)
|
15
|
+
- [Sean Collins] Add `db/*.sqlite` to the `.gitignore` in new apps (#210)
|
16
|
+
- [Sean Collins] Print warnings for misconfigured databases when running `db` commands (#211)
|
17
|
+
|
5
18
|
## v2.2.0.beta1 - 2024-07-16
|
6
19
|
|
7
|
-
|
20
|
+
### Added
|
8
21
|
|
9
22
|
- [Sean Collins] Generate db files in `hanami new` and `generate slice`
|
10
23
|
- [Tim Riley] Add `db` commands: `create`, `drop`, `migrate`, `structure dump` `structure load`, `seed` `prepare`, `version`
|
@@ -13,7 +26,7 @@ Hanami Command Line Interface
|
|
13
26
|
- [Krzysztof] Add `generate component` command
|
14
27
|
- [Sean Collins] Add `generate operation` command
|
15
28
|
|
16
|
-
|
29
|
+
### Changed
|
17
30
|
|
18
31
|
- Drop support for Ruby 3.0
|
19
32
|
|
data/Gemfile
CHANGED
@@ -16,8 +16,11 @@ gem "hanami-db", github: "hanami/db", branch: "main"
|
|
16
16
|
gem "hanami-router", github: "hanami/router", branch: "main"
|
17
17
|
gem "hanami-utils", github: "hanami/utils", branch: "main"
|
18
18
|
|
19
|
+
gem "dry-system", github: "dry-rb/dry-system", branch: "main"
|
20
|
+
|
19
21
|
gem "rack"
|
20
22
|
|
23
|
+
gem "mysql2"
|
21
24
|
gem "pg"
|
22
25
|
gem "sqlite3"
|
23
26
|
|
data/README.md
CHANGED
@@ -34,6 +34,8 @@ After checking out the repo, run `bin/setup` to install dependencies. Then, run
|
|
34
34
|
|
35
35
|
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
36
36
|
|
37
|
+
In order to run all of the tests, you should run `docker compose up` separately, to run a `postgres` server.
|
38
|
+
|
37
39
|
## Contributing
|
38
40
|
|
39
41
|
Bug reports and pull requests are welcome on GitHub at https://github.com/hanami/cli. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/hanami/cli/blob/main/CODE_OF_CONDUCT.md).
|
data/docker-compose.yml
CHANGED
data/lib/hanami/cli/command.rb
CHANGED
@@ -31,7 +31,7 @@ module Hanami
|
|
31
31
|
def run_command(klass, ...)
|
32
32
|
klass.new(
|
33
33
|
out: out,
|
34
|
-
inflector:
|
34
|
+
inflector: inflector,
|
35
35
|
fs: fs,
|
36
36
|
system_call: system_call,
|
37
37
|
).call(...)
|
@@ -39,59 +39,87 @@ module Hanami
|
|
39
39
|
|
40
40
|
private
|
41
41
|
|
42
|
-
def databases(app: false, slice: nil)
|
43
|
-
if app
|
44
|
-
|
45
|
-
|
46
|
-
[database_for_slice(slice)]
|
47
|
-
else
|
48
|
-
all_databases
|
42
|
+
def databases(app: false, slice: nil, gateway: nil)
|
43
|
+
if gateway && !app && !slice
|
44
|
+
err.puts "When specifying --gateway, an --app or --slice must also be given"
|
45
|
+
exit 1
|
49
46
|
end
|
50
|
-
end
|
51
47
|
|
52
|
-
|
53
|
-
|
48
|
+
databases =
|
49
|
+
if slice
|
50
|
+
[database_for_slice(slice, gateway: gateway)]
|
51
|
+
elsif app
|
52
|
+
[database_for_slice(self.app, gateway: gateway)]
|
53
|
+
else
|
54
|
+
all_databases
|
55
|
+
end
|
56
|
+
|
57
|
+
databases.flatten
|
54
58
|
end
|
55
59
|
|
56
|
-
def database_for_slice(slice)
|
60
|
+
def database_for_slice(slice, gateway: nil)
|
57
61
|
unless slice.is_a?(Class) && slice < Hanami::Slice
|
58
62
|
slice_name = inflector.underscore(Shellwords.shellescape(slice)).to_sym
|
59
63
|
slice = app.slices[slice_name]
|
60
64
|
end
|
61
65
|
|
62
|
-
|
66
|
+
ensure_database_slice slice
|
67
|
+
|
68
|
+
databases = build_databases(slice)
|
69
|
+
|
70
|
+
if gateway
|
71
|
+
databases.fetch(gateway.to_sym) do
|
72
|
+
err.puts %(No gateway "#{gateway}" in #{slice})
|
73
|
+
exit 1
|
74
|
+
end
|
75
|
+
else
|
76
|
+
databases.values
|
77
|
+
end
|
63
78
|
end
|
64
79
|
|
65
|
-
def all_databases
|
80
|
+
def all_databases # rubocop:disable Metrics/AbcSize, Metrics/PerceivedComplexity
|
66
81
|
slices = [app] + app.slices.with_nested
|
67
82
|
|
68
|
-
|
69
|
-
|
70
|
-
next unless
|
83
|
+
slice_gateways_by_database_url = slices.each_with_object({}) { |slice, hsh|
|
84
|
+
db_provider_source = slice.container.providers[:db]&.source
|
85
|
+
next unless db_provider_source
|
71
86
|
|
72
|
-
|
73
|
-
|
74
|
-
|
87
|
+
db_provider_source.database_urls.each do |gateway, url|
|
88
|
+
hsh[url] ||= []
|
89
|
+
hsh[url] << {slice: slice, gateway: gateway}
|
90
|
+
end
|
75
91
|
}
|
76
92
|
|
77
|
-
|
78
|
-
|
93
|
+
slice_gateways_by_database_url.each_with_object([]) { |(url, slice_gateways), arr|
|
94
|
+
slice_gateways_with_config = slice_gateways.select {
|
95
|
+
_1[:slice].root.join("config", "db").directory?
|
96
|
+
}
|
79
97
|
|
80
|
-
|
98
|
+
db_slice_gateway = slice_gateways_with_config.first || slice_gateways.first
|
99
|
+
database = Utils::Database.database_class(url).new(
|
100
|
+
slice: db_slice_gateway.fetch(:slice),
|
101
|
+
gateway_name: db_slice_gateway.fetch(:gateway),
|
102
|
+
system_call: system_call
|
103
|
+
)
|
81
104
|
|
82
|
-
warn_on_misconfigured_database database,
|
105
|
+
warn_on_misconfigured_database database, slice_gateways.map { _1.fetch(:slice) }
|
83
106
|
|
84
107
|
arr << database
|
85
108
|
}
|
109
|
+
end
|
86
110
|
|
87
|
-
|
111
|
+
def build_databases(slice)
|
112
|
+
Utils::Database.from_slice(slice: slice, system_call: system_call)
|
88
113
|
end
|
89
114
|
|
90
|
-
def
|
91
|
-
|
115
|
+
def ensure_database_slice(slice)
|
116
|
+
return if slice.container.providers[:db]
|
117
|
+
|
118
|
+
out.puts "#{slice} does not have a :db provider."
|
119
|
+
exit 1
|
92
120
|
end
|
93
121
|
|
94
|
-
def warn_on_misconfigured_database(database, slices)
|
122
|
+
def warn_on_misconfigured_database(database, slices) # rubocop:disable Metrics/AbcSize
|
95
123
|
if slices.length > 1
|
96
124
|
out.puts <<~STR
|
97
125
|
WARNING: Database #{database.name} is configured for multiple config/db/ directories:
|
@@ -101,9 +129,13 @@ module Hanami
|
|
101
129
|
Migrating database using #{database.slice.slice_name.to_s.inspect} slice only.
|
102
130
|
|
103
131
|
STR
|
104
|
-
elsif
|
132
|
+
elsif !database.db_config_dir?
|
133
|
+
relative_path = database.slice.root
|
134
|
+
.relative_path_from(database.slice.app.root)
|
135
|
+
.join("config", "db").to_s
|
136
|
+
|
105
137
|
out.puts <<~STR
|
106
|
-
WARNING: Database #{database.name}
|
138
|
+
WARNING: Database #{database.name} expects the folder #{relative_path}/ to exist but it does not.
|
107
139
|
|
108
140
|
STR
|
109
141
|
end
|
@@ -9,10 +9,12 @@ module Hanami
|
|
9
9
|
class Create < DB::Command
|
10
10
|
desc "Create databases"
|
11
11
|
|
12
|
-
|
12
|
+
option :gateway, required: false, desc: "Use database for gateway"
|
13
|
+
|
14
|
+
def call(app: false, slice: nil, gateway: nil, command_exit: method(:exit), **)
|
13
15
|
exit_codes = []
|
14
16
|
|
15
|
-
databases(app: app, slice: slice).each do |database|
|
17
|
+
databases(app: app, slice: slice, gateway: gateway).each do |database|
|
16
18
|
result = database.exec_create_command
|
17
19
|
exit_codes << result.exit_code if result.respond_to?(:exit_code)
|
18
20
|
|
@@ -9,10 +9,12 @@ module Hanami
|
|
9
9
|
class Drop < DB::Command
|
10
10
|
desc "Delete databases"
|
11
11
|
|
12
|
-
|
12
|
+
option :gateway, required: false, desc: "Use database for gateway"
|
13
|
+
|
14
|
+
def call(app: false, slice: nil, gateway: nil, **)
|
13
15
|
exit_codes = []
|
14
16
|
|
15
|
-
databases(app: app, slice: slice).each do |database|
|
17
|
+
databases(app: app, slice: slice, gateway: gateway).each do |database|
|
16
18
|
result = database.exec_drop_command
|
17
19
|
exit_codes << result.exit_code if result.respond_to?(:exit_code)
|
18
20
|
|
@@ -9,22 +9,29 @@ module Hanami
|
|
9
9
|
class Migrate < DB::Command
|
10
10
|
desc "Migrates database"
|
11
11
|
|
12
|
+
option :gateway, required: false, desc: "Use database for gateway"
|
12
13
|
option :target, desc: "Target migration number", aliases: ["-t"]
|
13
14
|
option :dump, required: false, type: :boolean, default: true,
|
14
|
-
|
15
|
+
desc: "Dump the database structure after migrating"
|
15
16
|
|
16
|
-
def call(target: nil, app: false, slice: nil, dump: true, command_exit: method(:exit), **)
|
17
|
-
databases(app: app, slice: slice).each do |database|
|
18
|
-
|
17
|
+
def call(target: nil, app: false, slice: nil, gateway: nil, dump: true, command_exit: method(:exit), **)
|
18
|
+
databases(app: app, slice: slice, gateway: gateway).each do |database|
|
19
|
+
if migrations_dir_missing?(database)
|
20
|
+
warn_on_missing_migrations_dir(database)
|
21
|
+
elsif no_migrations?(database)
|
22
|
+
warn_on_empty_migrations_dir(database)
|
23
|
+
else
|
24
|
+
migrate_database(database, target: target)
|
25
|
+
end
|
19
26
|
end
|
20
27
|
|
21
|
-
run_command(Structure::Dump, app: app, slice: slice, command_exit: command_exit) if dump
|
28
|
+
run_command(Structure::Dump, app: app, slice: slice, gateway: gateway, command_exit: command_exit) if dump
|
22
29
|
end
|
23
30
|
|
24
31
|
private
|
25
32
|
|
26
33
|
def migrate_database(database, target:)
|
27
|
-
return true unless
|
34
|
+
return true unless database.migrations_dir?
|
28
35
|
|
29
36
|
measure "database #{database.name} migrated" do
|
30
37
|
if target
|
@@ -37,8 +44,33 @@ module Hanami
|
|
37
44
|
end
|
38
45
|
end
|
39
46
|
|
40
|
-
def
|
41
|
-
database.migrations_dir?
|
47
|
+
def migrations_dir_missing?(database)
|
48
|
+
!database.migrations_dir?
|
49
|
+
end
|
50
|
+
|
51
|
+
def no_migrations?(database)
|
52
|
+
database.sequel_migrator.files.empty?
|
53
|
+
end
|
54
|
+
|
55
|
+
def warn_on_missing_migrations_dir(database)
|
56
|
+
out.puts <<~STR
|
57
|
+
WARNING: Database #{database.name} expects migrations to be located within #{relative_migrations_path(database)} but that folder does not exist.
|
58
|
+
|
59
|
+
No database migrations can be run for this database.
|
60
|
+
STR
|
61
|
+
end
|
62
|
+
|
63
|
+
def warn_on_empty_migrations_dir(database)
|
64
|
+
out.puts <<~STR
|
65
|
+
NOTE: Empty database migrations folder (#{relative_migrations_path(database)}) for #{database.name}
|
66
|
+
STR
|
67
|
+
end
|
68
|
+
|
69
|
+
def relative_migrations_path(database)
|
70
|
+
database
|
71
|
+
.migrations_path
|
72
|
+
.relative_path_from(database.slice.app.root)
|
73
|
+
.to_s + "/"
|
42
74
|
end
|
43
75
|
end
|
44
76
|
end
|
@@ -10,11 +10,21 @@ module Hanami
|
|
10
10
|
desc "Prepare databases"
|
11
11
|
|
12
12
|
def call(app: false, slice: nil, **)
|
13
|
-
|
13
|
+
command_exit = -> code { throw :command_exited, code }
|
14
|
+
command_exit_arg = {command_exit: command_exit}
|
14
15
|
|
16
|
+
# Since any slice may have multiple databases, we need to run the steps below in a
|
17
|
+
# particular order to satisfy our ROM/Sequel's migrator, which requires _all_ the
|
18
|
+
# databases in a slice to be created before we can use it.
|
19
|
+
#
|
20
|
+
# So before we do anything else, make sure to create/load every database first.
|
15
21
|
databases(app: app, slice: slice).each do |database|
|
16
|
-
|
17
|
-
|
22
|
+
command_args = {
|
23
|
+
**command_exit_arg,
|
24
|
+
app: database.slice.app?,
|
25
|
+
slice: database.slice,
|
26
|
+
gateway: database.gateway_name.to_s
|
27
|
+
}
|
18
28
|
|
19
29
|
exit_code = catch :command_exited do
|
20
30
|
unless database.exists?
|
@@ -22,17 +32,33 @@ module Hanami
|
|
22
32
|
run_command(DB::Structure::Load, **command_args)
|
23
33
|
end
|
24
34
|
|
25
|
-
run_command(DB::Migrate, **command_args)
|
26
|
-
run_command(DB::Seed, **command_args)
|
27
35
|
nil
|
28
36
|
end
|
29
37
|
|
30
|
-
|
38
|
+
return exit exit_code if exit_code.to_i > 1
|
31
39
|
end
|
32
40
|
|
33
|
-
|
34
|
-
|
41
|
+
# Once all databases are created, the migrator will properly load for each slice, and
|
42
|
+
# we can migrate each database.
|
43
|
+
databases(app: app, slice: slice).each do |database|
|
44
|
+
command_args = {
|
45
|
+
**command_exit_arg,
|
46
|
+
app: database.slice.app?,
|
47
|
+
slice: database.slice,
|
48
|
+
gateway: database.gateway_name.to_s
|
49
|
+
}
|
50
|
+
|
51
|
+
exit_code = catch :command_exited do
|
52
|
+
run_command(DB::Migrate, **command_args)
|
53
|
+
|
54
|
+
nil
|
55
|
+
end
|
56
|
+
|
57
|
+
return exit exit_code if exit_code.to_i > 1
|
35
58
|
end
|
59
|
+
|
60
|
+
# Finally, load the seeds for the slice overall, which is a once-per-slice operation.
|
61
|
+
run_command(DB::Seed, app: app, slice: slice)
|
36
62
|
end
|
37
63
|
end
|
38
64
|
end
|
@@ -13,7 +13,17 @@ module Hanami
|
|
13
13
|
desc "Load seed data"
|
14
14
|
|
15
15
|
def call(app: false, slice: nil, **)
|
16
|
+
# We use `databases` below to discover the databases throughout the app and slices. It
|
17
|
+
# yields every database, so in a slice with multiple gateways, we'll see multiple
|
18
|
+
# databases for the slice.
|
19
|
+
#
|
20
|
+
# Since `db seed` is intended to run over whole slices only (not per-gateway), keep
|
21
|
+
# track of the seeded slices here, so we can avoid seeding a slice multiple times.
|
22
|
+
seeded_slices = []
|
23
|
+
|
16
24
|
databases(app: app, slice: slice).each do |database|
|
25
|
+
next if seeded_slices.include?(database.slice)
|
26
|
+
|
17
27
|
seeds_path = database.slice.root.join(SEEDS_PATH)
|
18
28
|
next unless seeds_path.file?
|
19
29
|
|
@@ -21,6 +31,8 @@ module Hanami
|
|
21
31
|
measure "seed data loaded from #{relative_seeds_path}" do
|
22
32
|
load seeds_path.to_s
|
23
33
|
end
|
34
|
+
|
35
|
+
seeded_slices << database.slice
|
24
36
|
end
|
25
37
|
end
|
26
38
|
end
|
@@ -11,13 +11,15 @@ module Hanami
|
|
11
11
|
class Dump < DB::Command
|
12
12
|
desc "Dumps database structure to config/db/structure.sql file"
|
13
13
|
|
14
|
+
option :gateway, required: false, desc: "Use database for gateway"
|
15
|
+
|
14
16
|
# @api private
|
15
|
-
def call(app: false, slice: nil, command_exit: method(:exit), **)
|
17
|
+
def call(app: false, slice: nil, gateway: nil, command_exit: method(:exit), **)
|
16
18
|
exit_codes = []
|
17
19
|
|
18
|
-
databases(app: app, slice: slice).each do |database|
|
19
|
-
|
20
|
-
|
20
|
+
databases(app: app, slice: slice, gateway: gateway).each do |database|
|
21
|
+
relative_structure_path = database.structure_file
|
22
|
+
.relative_path_from(database.slice.app.root)
|
21
23
|
|
22
24
|
measure("#{database.name} structure dumped to #{relative_structure_path}") do
|
23
25
|
catch :dump_failed do
|
@@ -29,7 +31,7 @@ module Hanami
|
|
29
31
|
throw :dump_failed, false
|
30
32
|
end
|
31
33
|
|
32
|
-
File.open(
|
34
|
+
File.open(database.structure_file, "a") do |f|
|
33
35
|
f.puts "#{database.schema_migrations_sql_dump}\n"
|
34
36
|
end
|
35
37
|
|
@@ -14,15 +14,17 @@ module Hanami
|
|
14
14
|
|
15
15
|
desc "Loads database from config/db/structure.sql file"
|
16
16
|
|
17
|
+
option :gateway, required: false, desc: "Use database for gateway"
|
18
|
+
|
17
19
|
# @api private
|
18
|
-
def call(app: false, slice: nil, command_exit: method(:exit), **)
|
20
|
+
def call(app: false, slice: nil, gateway: nil, command_exit: method(:exit), **)
|
19
21
|
exit_codes = []
|
20
22
|
|
21
|
-
databases(app: app, slice: slice).each do |database|
|
22
|
-
|
23
|
-
next unless structure_path.exist?
|
23
|
+
databases(app: app, slice: slice, gateway: gateway).each do |database|
|
24
|
+
next unless database.structure_file.exist?
|
24
25
|
|
25
|
-
relative_structure_path =
|
26
|
+
relative_structure_path = database.structure_file
|
27
|
+
.relative_path_from(database.slice.app.root)
|
26
28
|
|
27
29
|
measure("#{database.name} structure loaded from #{relative_structure_path}") do
|
28
30
|
catch :load_failed do
|
@@ -11,9 +11,6 @@ module Hanami
|
|
11
11
|
# @api private
|
12
12
|
# @since 2.2.0
|
13
13
|
class Database
|
14
|
-
MIGRATIONS_DIR = "config/db/migrate"
|
15
|
-
private_constant :MIGRATIONS_DIR
|
16
|
-
|
17
14
|
DATABASE_CLASS_RESOLVER = Hash.new { |_, key|
|
18
15
|
raise "#{key} is not a supported db scheme"
|
19
16
|
}.update(
|
@@ -29,27 +26,40 @@ module Hanami
|
|
29
26
|
require_relative("postgres")
|
30
27
|
Postgres
|
31
28
|
},
|
32
|
-
"
|
29
|
+
"mysql2" => -> {
|
33
30
|
require_relative("mysql")
|
34
31
|
Mysql
|
35
32
|
}
|
36
33
|
).freeze
|
37
34
|
|
38
|
-
def self.
|
35
|
+
def self.database_class(database_url)
|
36
|
+
database_scheme = URI(database_url).scheme
|
37
|
+
DATABASE_CLASS_RESOLVER[database_scheme].call
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.from_slice(slice:, system_call:)
|
39
41
|
provider = slice.container.providers[:db]
|
40
|
-
raise "
|
42
|
+
raise "No :db provider for #{slice}" unless provider
|
41
43
|
|
42
|
-
|
43
|
-
|
44
|
-
|
44
|
+
provider.source.database_urls.map { |(gateway_name, database_url)|
|
45
|
+
database = database_class(database_url).new(
|
46
|
+
slice: slice,
|
47
|
+
gateway_name: gateway_name,
|
48
|
+
system_call: system_call
|
49
|
+
)
|
50
|
+
|
51
|
+
[gateway_name, database]
|
52
|
+
}.to_h
|
45
53
|
end
|
46
54
|
|
47
55
|
attr_reader :slice
|
56
|
+
attr_reader :gateway_name
|
48
57
|
|
49
58
|
attr_reader :system_call
|
50
59
|
|
51
|
-
def initialize(slice:, system_call:)
|
60
|
+
def initialize(slice:, gateway_name:, system_call:)
|
52
61
|
@slice = slice
|
62
|
+
@gateway_name = gateway_name
|
53
63
|
@system_call = system_call
|
54
64
|
end
|
55
65
|
|
@@ -58,7 +68,7 @@ module Hanami
|
|
58
68
|
end
|
59
69
|
|
60
70
|
def database_url
|
61
|
-
slice.container.providers[:db].source.
|
71
|
+
slice.container.providers[:db].source.database_urls.fetch(gateway_name)
|
62
72
|
end
|
63
73
|
|
64
74
|
def database_uri
|
@@ -66,7 +76,7 @@ module Hanami
|
|
66
76
|
end
|
67
77
|
|
68
78
|
def gateway
|
69
|
-
slice["db.config"].gateways[
|
79
|
+
slice["db.config"].gateways[gateway_name]
|
70
80
|
end
|
71
81
|
|
72
82
|
def connection
|
@@ -127,8 +137,20 @@ module Hanami
|
|
127
137
|
sequel_migrator.applied_migrations
|
128
138
|
end
|
129
139
|
|
140
|
+
def db_config_path
|
141
|
+
slice.root.join("config", "db")
|
142
|
+
end
|
143
|
+
|
144
|
+
def db_config_dir?
|
145
|
+
db_config_path.directory?
|
146
|
+
end
|
147
|
+
|
130
148
|
def migrations_path
|
131
|
-
|
149
|
+
if gateway_name == :default
|
150
|
+
db_config_path.join("migrate")
|
151
|
+
else
|
152
|
+
db_config_path.join("#{gateway_name}_migrate")
|
153
|
+
end
|
132
154
|
end
|
133
155
|
|
134
156
|
def migrations_dir?
|
@@ -136,10 +158,18 @@ module Hanami
|
|
136
158
|
end
|
137
159
|
|
138
160
|
def structure_file
|
139
|
-
slice.root.join("config
|
161
|
+
path = slice.root.join("config", "db")
|
162
|
+
|
163
|
+
if gateway_name == :default
|
164
|
+
path.join("structure.sql")
|
165
|
+
else
|
166
|
+
path.join("#{gateway_name}_structure.sql")
|
167
|
+
end
|
140
168
|
end
|
141
169
|
|
142
170
|
def schema_migrations_sql_dump
|
171
|
+
return unless migrations_dir?
|
172
|
+
|
143
173
|
sql = +"INSERT INTO schema_migrations (filename) VALUES\n"
|
144
174
|
sql << applied_migrations.map { |v| "('#{v}')" }.join(",\n")
|
145
175
|
sql << ";"
|
@@ -11,18 +11,71 @@ module Hanami
|
|
11
11
|
# @api private
|
12
12
|
class Mysql < Database
|
13
13
|
# @api private
|
14
|
-
def
|
15
|
-
|
14
|
+
def exec_create_command
|
15
|
+
return true if exists?
|
16
|
+
|
17
|
+
exec_cli("mysql", %(-e "CREATE DATABASE #{escaped_name}"))
|
18
|
+
end
|
19
|
+
|
20
|
+
# @api private
|
21
|
+
# @since 2.2.0
|
22
|
+
def exec_drop_command
|
23
|
+
return true unless exists?
|
24
|
+
|
25
|
+
exec_cli("mysql", %(-e "DROP DATABASE #{escaped_name}"))
|
26
|
+
end
|
27
|
+
|
28
|
+
# @api private
|
29
|
+
# @since 2.2.0
|
30
|
+
def exists?
|
31
|
+
result = exec_cli("mysql", %(-e "SHOW DATABASES LIKE '#{name}'" --batch))
|
32
|
+
|
33
|
+
result.successful? && result.out != ""
|
16
34
|
end
|
17
35
|
|
18
36
|
# @api private
|
37
|
+
# @since 2.2.0
|
19
38
|
def exec_dump_command
|
20
|
-
|
39
|
+
exec_cli(
|
40
|
+
"mysqldump",
|
41
|
+
"--no-data --routines --skip-comments --result-file=#{structure_file} #{escaped_name}"
|
42
|
+
)
|
21
43
|
end
|
22
44
|
|
23
45
|
# @api private
|
46
|
+
# @since 2.2.0
|
24
47
|
def exec_load_command
|
25
|
-
|
48
|
+
exec_cli(
|
49
|
+
"mysql",
|
50
|
+
%(--execute "SET FOREIGN_KEY_CHECKS = 0; SOURCE #{structure_file}; SET FOREIGN_KEY_CHECKS = 1" --database #{escaped_name})
|
51
|
+
)
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
def escaped_name
|
57
|
+
Shellwords.escape(name)
|
58
|
+
end
|
59
|
+
|
60
|
+
def exec_cli(cli_name, cli_args)
|
61
|
+
system_call.call(
|
62
|
+
"#{cli_name} #{cli_options} #{cli_args}",
|
63
|
+
env: cli_env_vars
|
64
|
+
)
|
65
|
+
end
|
66
|
+
|
67
|
+
def cli_options
|
68
|
+
[].tap { |opts|
|
69
|
+
opts << "--host=#{Shellwords.escape(database_uri.host)}" if database_uri.host
|
70
|
+
opts << "--port=#{Shellwords.escape(database_uri.port)}" if database_uri.port
|
71
|
+
opts << "--user=#{Shellwords.escape(database_uri.user)}" if database_uri.user
|
72
|
+
}.join(" ")
|
73
|
+
end
|
74
|
+
|
75
|
+
def cli_env_vars
|
76
|
+
@cli_env_vars ||= {}.tap do |vars|
|
77
|
+
vars["MYSQL_PWD"] = database_uri.password.to_s if database_uri.password
|
78
|
+
end
|
26
79
|
end
|
27
80
|
end
|
28
81
|
end
|
@@ -54,6 +54,16 @@ module Hanami
|
|
54
54
|
)
|
55
55
|
end
|
56
56
|
|
57
|
+
def schema_migrations_sql_dump
|
58
|
+
search_path = slice["db.gateway"].connection
|
59
|
+
.fetch("SHOW search_path").to_a.first
|
60
|
+
.fetch(:search_path)
|
61
|
+
|
62
|
+
+"SET search_path TO #{search_path};\n\n" << super
|
63
|
+
end
|
64
|
+
|
65
|
+
private
|
66
|
+
|
57
67
|
def escaped_name
|
58
68
|
Shellwords.escape(name)
|
59
69
|
end
|
@@ -66,14 +76,6 @@ module Hanami
|
|
66
76
|
vars["PGPASSWORD"] = database_uri.password.to_s if database_uri.password
|
67
77
|
end
|
68
78
|
end
|
69
|
-
|
70
|
-
def schema_migrations_sql_dump
|
71
|
-
search_path = slice["db.gateway"].connection
|
72
|
-
.fetch("SHOW search_path").to_a.first
|
73
|
-
.fetch(:search_path)
|
74
|
-
|
75
|
-
+"SET search_path TO #{search_path};\n\n" << super
|
76
|
-
end
|
77
79
|
end
|
78
80
|
end
|
79
81
|
end
|
@@ -9,11 +9,14 @@ module Hanami
|
|
9
9
|
class Version < DB::Command
|
10
10
|
desc "Print schema version"
|
11
11
|
|
12
|
+
option :gateway, required: false, desc: "Use database for gateway"
|
13
|
+
|
12
14
|
# @api private
|
13
|
-
def call(app: false, slice: nil, **)
|
14
|
-
databases(app: app, slice: slice).each do |database|
|
15
|
+
def call(app: false, slice: nil, gateway: nil, **)
|
16
|
+
databases(app: app, slice: slice, gateway: gateway).each do |database|
|
15
17
|
unless database.migrations_dir?
|
16
|
-
|
18
|
+
relative_migrations_path = database.migrations_path.relative_path_from(database.slice.app.root)
|
19
|
+
out.puts "=> Cannot find version for database #{database.name}: no migrations directory at #{relative_migrations_path}/"
|
17
20
|
return
|
18
21
|
end
|
19
22
|
|
@@ -38,8 +38,19 @@ module Hanami
|
|
38
38
|
# @since 2.2.0
|
39
39
|
# @api private
|
40
40
|
def call(name:, slice: nil, **)
|
41
|
-
|
42
|
-
|
41
|
+
if slice
|
42
|
+
generator.call(
|
43
|
+
key: name,
|
44
|
+
namespace: slice,
|
45
|
+
base_path: fs.join("slices", inflector.underscore(slice))
|
46
|
+
)
|
47
|
+
else
|
48
|
+
generator.call(
|
49
|
+
key: name,
|
50
|
+
namespace: app.namespace,
|
51
|
+
base_path: "app"
|
52
|
+
)
|
53
|
+
end
|
43
54
|
end
|
44
55
|
end
|
45
56
|
end
|
@@ -9,16 +9,36 @@ module Hanami
|
|
9
9
|
# @api private
|
10
10
|
class Migration < Command
|
11
11
|
argument :name, required: true, desc: "Migration name"
|
12
|
+
option :gateway, desc: "Generate migration for gateway"
|
12
13
|
|
13
14
|
example [
|
14
15
|
%(create_posts),
|
15
16
|
%(add_published_at_to_posts),
|
16
17
|
%(create_users --slice=admin),
|
18
|
+
%(create_comments --slice=admin --gateway=extra),
|
17
19
|
]
|
18
20
|
|
19
21
|
def generator_class
|
20
22
|
Generators::App::Migration
|
21
23
|
end
|
24
|
+
|
25
|
+
def call(name:, slice: nil, gateway: nil)
|
26
|
+
if slice
|
27
|
+
generator.call(
|
28
|
+
key: name,
|
29
|
+
namespace: slice,
|
30
|
+
base_path: fs.join("slices", inflector.underscore(slice)),
|
31
|
+
gateway: gateway
|
32
|
+
)
|
33
|
+
else
|
34
|
+
generator.call(
|
35
|
+
key: name,
|
36
|
+
namespace: app.namespace,
|
37
|
+
base_path: "app",
|
38
|
+
gateway: gateway
|
39
|
+
)
|
40
|
+
end
|
41
|
+
end
|
22
42
|
end
|
23
43
|
end
|
24
44
|
end
|
@@ -30,13 +30,9 @@ module Hanami
|
|
30
30
|
|
31
31
|
# @since 2.2.0
|
32
32
|
# @api private
|
33
|
-
def call(name:,
|
34
|
-
|
35
|
-
|
36
|
-
else
|
37
|
-
"#{inflector.singularize(name)}_repo"
|
38
|
-
end
|
39
|
-
super(name: normalized_name, slice: slice, **opts)
|
33
|
+
def call(name:, **opts)
|
34
|
+
name = "#{inflector.singularize(name)}_repo" unless name.end_with?("_repo")
|
35
|
+
super
|
40
36
|
end
|
41
37
|
end
|
42
38
|
end
|
data/lib/hanami/cli/files.rb
CHANGED
@@ -18,7 +18,11 @@ module Hanami
|
|
18
18
|
# @api private
|
19
19
|
def write(path, *content)
|
20
20
|
already_exists = exist?(path)
|
21
|
+
|
21
22
|
super
|
23
|
+
|
24
|
+
delete_keepfiles(path) unless already_exists
|
25
|
+
|
22
26
|
if already_exists
|
23
27
|
updated(path)
|
24
28
|
else
|
@@ -46,6 +50,24 @@ module Hanami
|
|
46
50
|
|
47
51
|
attr_reader :out
|
48
52
|
|
53
|
+
# Removes .keep files in any directories leading up to the given path.
|
54
|
+
#
|
55
|
+
# Does not attempt to remove `.keep` files in the following scenarios:
|
56
|
+
# - When the given path is a `.keep` file itself.
|
57
|
+
# - When the given path is absolute, since ascending up this path may lead to removal of
|
58
|
+
# files outside the Hanami project directory.
|
59
|
+
def delete_keepfiles(path)
|
60
|
+
path = Pathname(path)
|
61
|
+
|
62
|
+
return if path.absolute?
|
63
|
+
return if path.relative_path_from(path.dirname).to_s == ".keep"
|
64
|
+
|
65
|
+
path.dirname.ascend do |part|
|
66
|
+
keepfile = (part + ".keep").to_path
|
67
|
+
delete(keepfile) if exist?(keepfile)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
49
71
|
def updated(path)
|
50
72
|
out.puts "Updated #{path}"
|
51
73
|
end
|
@@ -17,17 +17,14 @@ module Hanami
|
|
17
17
|
|
18
18
|
# @since 2.2.0
|
19
19
|
# @api private
|
20
|
-
def call(
|
21
|
-
|
22
|
-
ensure_valid_name(
|
20
|
+
def call(key:, base_path:, gateway: nil, **_opts)
|
21
|
+
name = inflector.underscore(key)
|
22
|
+
ensure_valid_name(name)
|
23
23
|
|
24
|
-
|
25
|
-
|
26
|
-
else
|
27
|
-
fs.join("config", "db", "migrate")
|
28
|
-
end
|
24
|
+
base_path = nil if base_path == "app" # Migrations are in the root dir, not app/
|
25
|
+
migrate_dir = gateway ? "#{gateway}_migrate" : "migrate"
|
29
26
|
|
30
|
-
path = fs.join(
|
27
|
+
path = fs.join(*[base_path, "config", "db", migrate_dir, file_name(name)].compact)
|
31
28
|
|
32
29
|
fs.write(path, FILE_CONTENTS)
|
33
30
|
end
|
@@ -19,16 +19,17 @@ module Hanami
|
|
19
19
|
|
20
20
|
# @since 2.2.0
|
21
21
|
# @api private
|
22
|
-
def call(
|
22
|
+
def call(key:, namespace:, base_path:)
|
23
23
|
RubyFileWriter.new(
|
24
24
|
fs: fs,
|
25
25
|
inflector: inflector,
|
26
|
-
|
26
|
+
).call(
|
27
|
+
namespace: namespace,
|
28
|
+
base_path: base_path,
|
27
29
|
key: key,
|
28
|
-
slice: slice,
|
29
30
|
relative_parent_class: "Operation",
|
30
31
|
body: ["def call", "end"],
|
31
|
-
)
|
32
|
+
)
|
32
33
|
|
33
34
|
unless key.match?(KEY_SEPARATOR)
|
34
35
|
out.puts(
|
@@ -19,19 +19,20 @@ module Hanami
|
|
19
19
|
|
20
20
|
# @since 2.2.0
|
21
21
|
# @api private
|
22
|
-
def call(
|
22
|
+
def call(key:, namespace:, base_path:)
|
23
23
|
schema_name = key.split(KEY_SEPARATOR).last
|
24
24
|
|
25
25
|
RubyFileWriter.new(
|
26
26
|
fs: fs,
|
27
27
|
inflector: inflector,
|
28
|
-
|
28
|
+
).call(
|
29
|
+
namespace: namespace,
|
29
30
|
key: key,
|
30
|
-
|
31
|
+
base_path: base_path,
|
31
32
|
extra_namespace: "Relations",
|
32
33
|
relative_parent_class: "DB::Relation",
|
33
34
|
body: ["schema :#{schema_name}, infer: true"],
|
34
|
-
)
|
35
|
+
)
|
35
36
|
end
|
36
37
|
|
37
38
|
private
|
@@ -17,17 +17,18 @@ module Hanami
|
|
17
17
|
|
18
18
|
# @since 2.2.0
|
19
19
|
# @api private
|
20
|
-
def call(
|
20
|
+
def call(key:, namespace:, base_path:)
|
21
21
|
RubyFileWriter.new(
|
22
22
|
fs: fs,
|
23
23
|
inflector: inflector,
|
24
|
-
|
24
|
+
).call(
|
25
25
|
key: key,
|
26
|
-
|
26
|
+
namespace: namespace,
|
27
|
+
base_path: base_path,
|
27
28
|
extra_namespace: "Repos",
|
28
29
|
relative_parent_class: "DB::Repo",
|
29
30
|
body: [],
|
30
|
-
)
|
31
|
+
)
|
31
32
|
end
|
32
33
|
|
33
34
|
private
|
@@ -14,31 +14,55 @@ module Hanami
|
|
14
14
|
class RubyFileWriter
|
15
15
|
# @since 2.2.0
|
16
16
|
# @api private
|
17
|
+
def initialize(fs:, inflector:)
|
18
|
+
@fs = fs
|
19
|
+
@inflector = inflector
|
20
|
+
end
|
21
|
+
|
22
|
+
# @since 2.2.0
|
23
|
+
# @api private
|
24
|
+
def call(key:, namespace:, base_path:, relative_parent_class:, extra_namespace: nil, body: [])
|
25
|
+
ClassFile.new(
|
26
|
+
fs: fs,
|
27
|
+
inflector: inflector,
|
28
|
+
key: key,
|
29
|
+
namespace: namespace,
|
30
|
+
base_path: base_path,
|
31
|
+
relative_parent_class: relative_parent_class,
|
32
|
+
extra_namespace: extra_namespace,
|
33
|
+
body: body,
|
34
|
+
).write
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
# @since 2.2.0
|
40
|
+
# @api private
|
41
|
+
attr_reader :fs, :inflector
|
42
|
+
end
|
43
|
+
|
44
|
+
class ClassFile
|
17
45
|
def initialize(
|
18
46
|
fs:,
|
19
47
|
inflector:,
|
20
|
-
app_namespace:,
|
21
48
|
key:,
|
22
|
-
|
49
|
+
namespace:,
|
50
|
+
base_path:,
|
23
51
|
relative_parent_class:,
|
24
52
|
extra_namespace: nil,
|
25
53
|
body: []
|
26
54
|
)
|
27
55
|
@fs = fs
|
28
56
|
@inflector = inflector
|
29
|
-
@app_namespace = app_namespace
|
30
57
|
@key = key
|
31
|
-
@
|
58
|
+
@namespace = namespace
|
59
|
+
@base_path = base_path
|
32
60
|
@extra_namespace = extra_namespace&.downcase
|
33
61
|
@relative_parent_class = relative_parent_class
|
34
62
|
@body = body
|
35
|
-
raise_missing_slice_error_if_missing(slice) if slice
|
36
63
|
end
|
37
64
|
|
38
|
-
|
39
|
-
# @api private
|
40
|
-
def call
|
41
|
-
fs.mkdir(directory)
|
65
|
+
def write
|
42
66
|
fs.write(path, file_contents)
|
43
67
|
end
|
44
68
|
|
@@ -49,9 +73,9 @@ module Hanami
|
|
49
73
|
attr_reader(
|
50
74
|
:fs,
|
51
75
|
:inflector,
|
52
|
-
:app_namespace,
|
53
76
|
:key,
|
54
|
-
:
|
77
|
+
:namespace,
|
78
|
+
:base_path,
|
55
79
|
:extra_namespace,
|
56
80
|
:relative_parent_class,
|
57
81
|
:body,
|
@@ -62,7 +86,6 @@ module Hanami
|
|
62
86
|
def file_contents
|
63
87
|
class_definition(
|
64
88
|
class_name: class_name,
|
65
|
-
container_namespace: container_namespace,
|
66
89
|
local_namespaces: local_namespaces,
|
67
90
|
)
|
68
91
|
end
|
@@ -73,12 +96,6 @@ module Hanami
|
|
73
96
|
key.split(KEY_SEPARATOR)[-1]
|
74
97
|
end
|
75
98
|
|
76
|
-
# @since 2.2.0
|
77
|
-
# @api private
|
78
|
-
def container_namespace
|
79
|
-
slice || app_namespace
|
80
|
-
end
|
81
|
-
|
82
99
|
# @since 2.2.0
|
83
100
|
# @api private
|
84
101
|
def local_namespaces
|
@@ -88,16 +105,10 @@ module Hanami
|
|
88
105
|
# @since 2.2.0
|
89
106
|
# @api private
|
90
107
|
def directory
|
91
|
-
base = if slice
|
92
|
-
fs.join("slices", slice)
|
93
|
-
else
|
94
|
-
fs.join("app")
|
95
|
-
end
|
96
|
-
|
97
108
|
@directory ||= if local_namespaces.any?
|
98
|
-
fs.join(
|
109
|
+
fs.join(base_path, local_namespaces)
|
99
110
|
else
|
100
|
-
|
111
|
+
base_path
|
101
112
|
end
|
102
113
|
end
|
103
114
|
|
@@ -109,8 +120,8 @@ module Hanami
|
|
109
120
|
|
110
121
|
# @since 2.2.0
|
111
122
|
# @api private
|
112
|
-
def class_definition(class_name:,
|
113
|
-
container_module = normalize(
|
123
|
+
def class_definition(class_name:, local_namespaces:)
|
124
|
+
container_module = normalize(namespace)
|
114
125
|
|
115
126
|
modules = local_namespaces
|
116
127
|
.map { normalize(_1) }
|
@@ -133,15 +144,6 @@ module Hanami
|
|
133
144
|
def normalize(name)
|
134
145
|
inflector.camelize(name).gsub(/[^\p{Alnum}]/, "")
|
135
146
|
end
|
136
|
-
|
137
|
-
# @since 2.2.0
|
138
|
-
# @api private
|
139
|
-
def raise_missing_slice_error_if_missing(slice)
|
140
|
-
if slice
|
141
|
-
slice_directory = fs.join("slices", slice)
|
142
|
-
raise MissingSliceError.new(slice) unless fs.directory?(slice_directory)
|
143
|
-
end
|
144
|
-
end
|
145
147
|
end
|
146
148
|
end
|
147
149
|
end
|
@@ -17,16 +17,17 @@ module Hanami
|
|
17
17
|
|
18
18
|
# @since 2.2.0
|
19
19
|
# @api private
|
20
|
-
def call(
|
20
|
+
def call(key:, namespace:, base_path:)
|
21
21
|
RubyFileWriter.new(
|
22
22
|
fs: fs,
|
23
23
|
inflector: inflector,
|
24
|
-
|
24
|
+
).call(
|
25
25
|
key: key,
|
26
|
-
|
26
|
+
namespace: namespace,
|
27
|
+
base_path: base_path,
|
27
28
|
extra_namespace: "Structs",
|
28
29
|
relative_parent_class: "DB::Struct",
|
29
|
-
)
|
30
|
+
)
|
30
31
|
end
|
31
32
|
|
32
33
|
private
|
@@ -89,19 +89,19 @@ module Hanami
|
|
89
89
|
# @since 2.2.0
|
90
90
|
# @api private
|
91
91
|
def generate_sqlite?
|
92
|
-
database_option == Commands::Gem::New::DATABASE_SQLITE
|
92
|
+
generate_db? && database_option == Commands::Gem::New::DATABASE_SQLITE
|
93
93
|
end
|
94
94
|
|
95
95
|
# @since 2.2.0
|
96
96
|
# @api private
|
97
97
|
def generate_postgres?
|
98
|
-
database_option == Commands::Gem::New::DATABASE_POSTGRES
|
98
|
+
generate_db? && database_option == Commands::Gem::New::DATABASE_POSTGRES
|
99
99
|
end
|
100
100
|
|
101
101
|
# @since 2.2.0
|
102
102
|
# @api private
|
103
103
|
def generate_mysql?
|
104
|
-
database_option == Commands::Gem::New::DATABASE_MYSQL
|
104
|
+
generate_db? && database_option == Commands::Gem::New::DATABASE_MYSQL
|
105
105
|
end
|
106
106
|
|
107
107
|
# @since 2.2.0
|
@@ -112,7 +112,7 @@ module Hanami
|
|
112
112
|
elsif generate_postgres?
|
113
113
|
"postgres://localhost/#{app}"
|
114
114
|
elsif generate_mysql?
|
115
|
-
"
|
115
|
+
"mysql2://localhost/#{app}"
|
116
116
|
else
|
117
117
|
raise "Unknown database option: #{database_option}"
|
118
118
|
end
|
data/lib/hanami/cli/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hanami-cli
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.2.0.
|
4
|
+
version: 2.2.0.beta2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Luca Guidi
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-09-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -263,7 +263,6 @@ files:
|
|
263
263
|
- lib/hanami/cli/generators/app/slice/app_css.erb
|
264
264
|
- lib/hanami/cli/generators/app/slice/app_js.erb
|
265
265
|
- lib/hanami/cli/generators/app/slice/app_layout.erb
|
266
|
-
- lib/hanami/cli/generators/app/slice/entities.erb
|
267
266
|
- lib/hanami/cli/generators/app/slice/favicon.ico
|
268
267
|
- lib/hanami/cli/generators/app/slice/helpers.erb
|
269
268
|
- lib/hanami/cli/generators/app/slice/keep.erb
|
@@ -354,7 +353,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
354
353
|
- !ruby/object:Gem::Version
|
355
354
|
version: '0'
|
356
355
|
requirements: []
|
357
|
-
rubygems_version: 3.5.
|
356
|
+
rubygems_version: 3.5.16
|
358
357
|
signing_key:
|
359
358
|
specification_version: 4
|
360
359
|
summary: Hanami CLI
|