hanami-cli 2.2.0.beta1 → 2.2.0.beta2
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 +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
|