hanami-cli 2.2.0.beta2 → 2.2.0

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.
Files changed (32) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +32 -0
  3. data/lib/hanami/cli/commands/app/command.rb +9 -3
  4. data/lib/hanami/cli/commands/app/console.rb +1 -5
  5. data/lib/hanami/cli/commands/app/db/command.rb +80 -4
  6. data/lib/hanami/cli/commands/app/db/create.rb +2 -0
  7. data/lib/hanami/cli/commands/app/db/drop.rb +2 -0
  8. data/lib/hanami/cli/commands/app/db/migrate.rb +10 -1
  9. data/lib/hanami/cli/commands/app/db/prepare.rb +3 -1
  10. data/lib/hanami/cli/commands/app/db/seed.rb +5 -1
  11. data/lib/hanami/cli/commands/app/db/structure/dump.rb +5 -2
  12. data/lib/hanami/cli/commands/app/db/structure/load.rb +2 -0
  13. data/lib/hanami/cli/commands/app/db/utils/postgres.rb +5 -2
  14. data/lib/hanami/cli/commands/app/generate/action.rb +12 -2
  15. data/lib/hanami/cli/commands/app/generate/component.rb +4 -4
  16. data/lib/hanami/cli/commands/app/generate/relation.rb +20 -0
  17. data/lib/hanami/cli/commands/app/generate/slice.rb +16 -3
  18. data/lib/hanami/cli/commands/app.rb +21 -9
  19. data/lib/hanami/cli/generators/app/action.rb +27 -15
  20. data/lib/hanami/cli/generators/app/component.rb +1 -0
  21. data/lib/hanami/cli/generators/app/migration.rb +3 -1
  22. data/lib/hanami/cli/generators/app/relation.rb +5 -2
  23. data/lib/hanami/cli/generators/app/slice.rb +5 -3
  24. data/lib/hanami/cli/generators/app/slice_context.rb +6 -0
  25. data/lib/hanami/cli/generators/context.rb +1 -1
  26. data/lib/hanami/cli/generators/gem/app/gemfile.erb +2 -2
  27. data/lib/hanami/cli/generators/gem/app/operation.erb +0 -4
  28. data/lib/hanami/cli/generators/gem/app/seeds.erb +15 -0
  29. data/lib/hanami/cli/generators/gem/app.rb +3 -2
  30. data/lib/hanami/cli/repl/irb.rb +2 -2
  31. data/lib/hanami/cli/version.rb +1 -1
  32. metadata +4 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d62ed9aeff86f86693ffdf5acafb274e6e97a535a177bf46131c8c33141fc0e9
4
- data.tar.gz: 86da7248a20712451a83b8e5167870e34fd508f2e5f41a107d9bf3a4dea1d376
3
+ metadata.gz: af8c95d39ccda17c32851a787f8ef309b6af8936d1bb1eca4780a8f57969af66
4
+ data.tar.gz: a4aff54793a12526acf3919a16657fea36d496645fad596f2d214f3baf00e974
5
5
  SHA512:
6
- metadata.gz: affe042dfe0daf2dc93e1252b06d2d51dd5ea605c1287ad2500371bed6ee98e902cf9d19667458f86edadabb671f923b986bcd2a76a0e7d8821f4e0b9af6ecf6
7
- data.tar.gz: b1a097c66c10495ef31fd0783083d542ac6e7a5be7ab94f11b9e1a0d68dc865e04d6f970e08b88d33dd3939b47736cc8893989cb037d070d3c5d2ff86d35ccad
6
+ metadata.gz: 4a82b7839e9890b5dc3ed61b6e95ba3cc42dc1ba217d8d2f60b77fe2dd09a566331a1164f3ea8236ecb25f303bc64203388c5d1803ae38f0f5bffc18a9d9c60d
7
+ data.tar.gz: a3b6a3321bab8c5089c601849e47f159efe839413ac40292042c75f78b1ffd43d976ffc8615ed1ade575aba1e8b8a01fb299ac0cf2265e122cbb509c2dd497f3
data/CHANGELOG.md CHANGED
@@ -2,6 +2,38 @@
2
2
 
3
3
  Hanami Command Line Interface
4
4
 
5
+ ## v2.2.0 - 2024-11-05
6
+
7
+ ### Changed
8
+
9
+ - [Kyle Plump] Add `--gateway` optiopn to `generate relation` (#261)
10
+ - [Tim Riley] Depend on stable release of dry-operation in new app `Gemfile` (#262)
11
+ - [Tim Riley] Depend on newser dry-types with a simpler version constraint in new app `Gemfile` (#263)
12
+ - [Adam Lassek] Point to Hanami's own migrations guide from generated migration files (#264)
13
+
14
+ ## v2.2.0.rc1 - 2024-10-29
15
+
16
+ ### Added
17
+
18
+ - [Tim Riley, François Beausoleil] Generate a `config/db/seeds.rb` file in new apps (#255, #256)
19
+
20
+ ### Changed
21
+
22
+ - [Tim Riley] Add `--env` and `-e` options to all app commands, for setting the Hanami env (#246)
23
+ - [Tim Riley] Keep test database in sync by applying `hanami db` commands to both development and test databases when invoked in development environment (#247)
24
+ - [Kyle Plump] Add `--skip-route` flag to `generate action` and `generate slice` commands (#227)
25
+ - [Tim Riley] Include a `change do` block in generated migrations (#254)
26
+ - [Tim Riley] Generate MySQL database URL in `.env` that works with standard Homebrew MySQL installation (#249)
27
+ - [Tim Riley, Adam Lassek] Remove ROM extension boilerplate in operations generated by `hanami new` and `generate operation` (this is now applied automatically) (#240, #252)
28
+ - [François Beausoleil] Print a warning when running `db seed` but expected seeds files could not be found (#256)
29
+ - [Seb Wilgosz] Only register `generate` subcommands if the relevant gems are bundled (#242)
30
+ - [Anderson Saunders] When both IRB and pry are loaded, use IRB as the default engine for `hanami console` (#182)
31
+
32
+ ### Fixed
33
+
34
+ - [Tim Riley] Fix error dumping structure when there are no migrations (#244)
35
+ - [Tim Riley] Stop erroneous misconfigured DB warnings from `hanami db` commands when a database is configured once but shared across sliaces (#253)
36
+
5
37
  ## v2.2.0.beta2 - 2024-09-25
6
38
 
7
39
  ### Added
@@ -18,8 +18,8 @@ module Hanami
18
18
  # @api private
19
19
  ACTION_SEPARATOR = "." # TODO: rename to container key separator
20
20
 
21
- # Overloads {Hanami::CLI::Commands::App::Command#call} to ensure an appropriate `HANAMI_ENV`
22
- # environment variable is set.
21
+ # Overloads {Hanami::CLI::Commands::App::Command#call} to ensure an appropriate
22
+ # `HANAMI_ENV` environment variable is set.
23
23
  #
24
24
  # Uses an `--env` option if provided, then falls back to an already-set `HANAMI_ENV`
25
25
  # environment variable, and defaults to "development" in the absence of both.
@@ -27,6 +27,12 @@ module Hanami
27
27
  # @since 2.0.0
28
28
  # @api private
29
29
  module Environment
30
+ # @since 2.2.0
31
+ # @api private
32
+ def self.prepended(klass)
33
+ klass.option :env, desc: "App environment (development, test, production)", aliases: ["e"]
34
+ end
35
+
30
36
  # @since 2.0.0
31
37
  # @api private
32
38
  def call(*args, **opts)
@@ -37,7 +43,7 @@ module Hanami
37
43
  ENV["HANAMI_ENV"] = hanami_env
38
44
  Hanami::Env.load
39
45
 
40
- super(*args, **opts)
46
+ super
41
47
  end
42
48
  end
43
49
 
@@ -51,11 +51,7 @@ module Hanami
51
51
  private
52
52
 
53
53
  def resolve_engine(engine, opts)
54
- if engine
55
- ENGINES.fetch(engine).(app, opts)
56
- else
57
- ENGINES.map { |(_, loader)| loader.(app, opts) }.compact.first
58
- end
54
+ ENGINES.fetch(engine, ENGINES[DEFAULT_ENGINE]).call(app, opts)
59
55
  end
60
56
  end
61
57
  end
@@ -17,15 +17,23 @@ module Hanami
17
17
  option :app, required: false, type: :flag, default: false, desc: "Use app database"
18
18
  option :slice, required: false, desc: "Use database for slice"
19
19
 
20
+ # @api private
20
21
  attr_reader :system_call
21
22
 
23
+ # @api private
24
+ attr_reader :test_env_executor
25
+
22
26
  def initialize(
23
27
  out:, err:,
24
28
  system_call: SystemCall.new,
29
+ test_env_executor: InteractiveSystemCall.new(out: out, err: err),
30
+ nested_command: false,
25
31
  **opts
26
32
  )
27
33
  super(out: out, err: err, **opts)
28
34
  @system_call = system_call
35
+ @test_env_executor = test_env_executor
36
+ @nested_command = nested_command
29
37
  end
30
38
 
31
39
  def run_command(klass, ...)
@@ -34,9 +42,15 @@ module Hanami
34
42
  inflector: inflector,
35
43
  fs: fs,
36
44
  system_call: system_call,
45
+ test_env_executor: test_env_executor,
46
+ nested_command: true,
37
47
  ).call(...)
38
48
  end
39
49
 
50
+ def nested_command?
51
+ @nested_command
52
+ end
53
+
40
54
  private
41
55
 
42
56
  def databases(app: false, slice: nil, gateway: nil)
@@ -77,7 +91,7 @@ module Hanami
77
91
  end
78
92
  end
79
93
 
80
- def all_databases # rubocop:disable Metrics/AbcSize, Metrics/PerceivedComplexity
94
+ def all_databases # rubocop:disable Metrics/AbcSize
81
95
  slices = [app] + app.slices.with_nested
82
96
 
83
97
  slice_gateways_by_database_url = slices.each_with_object({}) { |slice, hsh|
@@ -92,7 +106,9 @@ module Hanami
92
106
 
93
107
  slice_gateways_by_database_url.each_with_object([]) { |(url, slice_gateways), arr|
94
108
  slice_gateways_with_config = slice_gateways.select {
95
- _1[:slice].root.join("config", "db").directory?
109
+ migrate_dir = _1[:gateway] == :default ? "migrate" : "#{_1[:gateway]}_migrate"
110
+
111
+ _1[:slice].root.join("config", "db", migrate_dir).directory?
96
112
  }
97
113
 
98
114
  db_slice_gateway = slice_gateways_with_config.first || slice_gateways.first
@@ -102,7 +118,7 @@ module Hanami
102
118
  system_call: system_call
103
119
  )
104
120
 
105
- warn_on_misconfigured_database database, slice_gateways.map { _1.fetch(:slice) }
121
+ warn_on_misconfigured_database database, slice_gateways_with_config.map { _1.fetch(:slice) }
106
122
 
107
123
  arr << database
108
124
  }
@@ -126,7 +142,7 @@ module Hanami
126
142
 
127
143
  #{slices.map { "- " + _1.root.relative_path_from(_1.app.root).join("config", "db").to_s }.join("\n")}
128
144
 
129
- Migrating database using #{database.slice.slice_name.to_s.inspect} slice only.
145
+ Using config in #{database.slice.slice_name.to_s.inspect} slice only.
130
146
 
131
147
  STR
132
148
  elsif !database.db_config_dir?
@@ -140,6 +156,66 @@ module Hanami
140
156
  STR
141
157
  end
142
158
  end
159
+
160
+ # Invokes the currently executing `hanami` CLI command again, but with any `--env` args
161
+ # removed and the `HANAMI_ENV=test` env var set.
162
+ #
163
+ # This is called by certain `db` commands only, and runs only if the Hanami env is
164
+ # `:development`. This behavior important to streamline the local development
165
+ # experience, making sure that the test databases are kept in sync with operations run
166
+ # on the development databases.
167
+ #
168
+ # Spawning an entirely new process to change the env is a compromise approach until we
169
+ # can have an API for reinitializing the DB subsystem in-process with a different env.
170
+ def re_run_development_command_in_test
171
+ # Only invoke a new process if we've been called as `hanami`. This avoids awkward
172
+ # failures when testing commands via RSpec, for which the $0 is "/full/path/to/rspec".
173
+ return unless $0.end_with?("hanami")
174
+
175
+ # If this special env key is set, then a re-run has already been invoked. This would
176
+ # mean the current command is actually a nested command run by another db command. In
177
+ # this case, don't trigger a re-runs, because one is already in process.
178
+ return if nested_command?
179
+
180
+ # Re-runs in test are for development-env commands only.
181
+ return unless Hanami.env == :development
182
+
183
+ cmd = $0
184
+ cmd = "bundle exec #{cmd}" if ENV.key?("BUNDLE_BIN_PATH")
185
+
186
+ test_env_executor.call(
187
+ cmd, *argv_without_env_args,
188
+ env: {
189
+ "HANAMI_ENV" => "test",
190
+ "HANAMI_CLI_DB_COMMAND_RE_RUN_IN_TEST" => "true"
191
+ }
192
+ )
193
+ end
194
+
195
+ def re_running_in_test?
196
+ ENV.key?("HANAMI_CLI_DB_COMMAND_RE_RUN_IN_TEST")
197
+ end
198
+
199
+ # Returns the `ARGV` with every option argument included, but the `-e` or `--env` args
200
+ # removed.
201
+ def argv_without_env_args
202
+ new_argv = ARGV.dup
203
+
204
+ env_arg_index = new_argv.index {
205
+ _1 == "-e" || _1 == "--env" || _1.start_with?("-e=") || _1.start_with?("--env=")
206
+ }
207
+
208
+ if env_arg_index
209
+ # Remove the env argument
210
+ env_arg = new_argv.delete_at(env_arg_index)
211
+
212
+ # If the env argument is not in combined form ("--env foo" rather than "--env=foo"),
213
+ # then remove the following argument too
214
+ new_argv.delete_at(env_arg_index) if ["-e", "--env"].include?(env_arg)
215
+ end
216
+
217
+ new_argv
218
+ end
143
219
  end
144
220
  end
145
221
  end
@@ -29,6 +29,8 @@ module Hanami
29
29
  exit_codes.each do |code|
30
30
  break command_exit.(code) if code > 0
31
31
  end
32
+
33
+ re_run_development_command_in_test
32
34
  end
33
35
  end
34
36
  end
@@ -29,6 +29,8 @@ module Hanami
29
29
  exit_codes.each do |code|
30
30
  break exit code if code > 0
31
31
  end
32
+
33
+ re_run_development_command_in_test
32
34
  end
33
35
  end
34
36
  end
@@ -25,7 +25,16 @@ module Hanami
25
25
  end
26
26
  end
27
27
 
28
- run_command(Structure::Dump, app: app, slice: slice, gateway: gateway, command_exit: command_exit) if dump
28
+ # Only dump for the initial command, not a re-run of the command in test env
29
+ if dump && !re_running_in_test?
30
+ run_command(
31
+ Structure::Dump,
32
+ app: app, slice: slice, gateway: gateway,
33
+ command_exit: command_exit
34
+ )
35
+ end
36
+
37
+ re_run_development_command_in_test
29
38
  end
30
39
 
31
40
  private
@@ -58,7 +58,9 @@ module Hanami
58
58
  end
59
59
 
60
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)
61
+ run_command(DB::Seed, app: app, slice: slice) unless re_running_in_test?
62
+
63
+ re_run_development_command_in_test
62
64
  end
63
65
  end
64
66
  end
@@ -25,7 +25,11 @@ module Hanami
25
25
  next if seeded_slices.include?(database.slice)
26
26
 
27
27
  seeds_path = database.slice.root.join(SEEDS_PATH)
28
- next unless seeds_path.file?
28
+
29
+ unless seeds_path.file?
30
+ out.puts "no seeds found at #{seeds_path.relative_path_from(database.slice.app.root)}"
31
+ next
32
+ end
29
33
 
30
34
  relative_seeds_path = seeds_path.relative_path_from(database.slice.app.root)
31
35
  measure "seed data loaded from #{relative_seeds_path}" do
@@ -31,8 +31,11 @@ module Hanami
31
31
  throw :dump_failed, false
32
32
  end
33
33
 
34
- File.open(database.structure_file, "a") do |f|
35
- f.puts "#{database.schema_migrations_sql_dump}\n"
34
+ migrations_sql = database.schema_migrations_sql_dump
35
+ if migrations_sql
36
+ File.open(database.structure_file, "a") do |f|
37
+ f.puts "#{migrations_sql}\n"
38
+ end
36
39
  end
37
40
 
38
41
  true
@@ -44,6 +44,8 @@ module Hanami
44
44
  exit_codes.each do |code|
45
45
  break command_exit.(code) if code > 0
46
46
  end
47
+
48
+ re_run_development_command_in_test
47
49
  end
48
50
  end
49
51
  end
@@ -55,11 +55,14 @@ module Hanami
55
55
  end
56
56
 
57
57
  def schema_migrations_sql_dump
58
- search_path = slice["db.gateway"].connection
58
+ migrations_sql = super
59
+ return unless migrations_sql
60
+
61
+ search_path = gateway.connection
59
62
  .fetch("SHOW search_path").to_a.first
60
63
  .fetch(:search_path)
61
64
 
62
- +"SET search_path TO #{search_path};\n\n" << super
65
+ +"SET search_path TO #{search_path};\n\n" << migrations_sql
63
66
  end
64
67
 
65
68
  private
@@ -25,6 +25,9 @@ module Hanami
25
25
  DEFAULT_SKIP_TESTS = false
26
26
  private_constant :DEFAULT_SKIP_TESTS
27
27
 
28
+ DEFAULT_SKIP_ROUTE = false
29
+ private_constant :DEFAULT_SKIP_ROUTE
30
+
28
31
  argument :name, required: true, desc: "Action name"
29
32
  option :url, required: false, type: :string, desc: "Action URL"
30
33
  option :http, required: false, type: :string, desc: "Action HTTP method"
@@ -41,6 +44,12 @@ module Hanami
41
44
  type: :flag,
42
45
  default: DEFAULT_SKIP_TESTS,
43
46
  desc: "Skip test generation"
47
+ option \
48
+ :skip_route,
49
+ required: false,
50
+ type: :flag,
51
+ default: DEFAULT_SKIP_ROUTE,
52
+ desc: "Skip route generation"
44
53
  option :slice, required: false, desc: "Slice name"
45
54
 
46
55
  # rubocop:disable Layout/LineLength
@@ -83,7 +92,8 @@ module Hanami
83
92
  http: nil,
84
93
  format: DEFAULT_FORMAT,
85
94
  skip_view: DEFAULT_SKIP_VIEW,
86
- skip_tests: DEFAULT_SKIP_TESTS, # rubocop:disable Lint/UnusedMethodArgument
95
+ skip_tests: DEFAULT_SKIP_TESTS, # rubocop:disable Lint/UnusedMethodArgument,
96
+ skip_route: DEFAULT_SKIP_ROUTE,
87
97
  slice: nil,
88
98
  context: nil,
89
99
  **
@@ -96,7 +106,7 @@ module Hanami
96
106
  raise InvalidActionNameError.new(name)
97
107
  end
98
108
 
99
- generator.call(app.namespace, controller, action, url, http, format, skip_view, slice, context: context)
109
+ generator.call(app.namespace, controller, action, url, http, format, skip_view, skip_route, slice, context: context)
100
110
  end
101
111
 
102
112
  # rubocop:enable Metrics/ParameterLists
@@ -15,10 +15,10 @@ module Hanami
15
15
  option :slice, required: false, desc: "Slice name"
16
16
 
17
17
  example [
18
- %(operations.create_user (MyApp::Operations::CreateUser)),
19
- %(operations.user.create (MyApp::Operations::Create::User)),
20
- %(operations.create_user --slice=admin (Admin::Operations::CreateUser)),
21
- %(Operations::CreateUser (MyApp::Operations::CreateUser)),
18
+ %(isbn_decoder (MyApp::IsbnDecoder)),
19
+ %(recommenders.fiction (MyApp::Recommenders::Fiction)),
20
+ %(isbn_decoder --slice=admin (Admin::IsbnDecoder)),
21
+ %(Exporters::Complete::CSV (MyApp::Exporters::Complete::CSV)),
22
22
  ]
23
23
  attr_reader :generator
24
24
  private :generator
@@ -9,11 +9,13 @@ module Hanami
9
9
  # @api private
10
10
  class Relation < Command
11
11
  argument :name, required: true, desc: "Relation name"
12
+ option :gateway, desc: "Generate relation for gateway"
12
13
 
13
14
  example [
14
15
  %(books (MyApp::Relation::Book)),
15
16
  %(books/drafts (MyApp::Relations::Books::Drafts)),
16
17
  %(books --slice=admin (Admin::Relations::Books)),
18
+ %(books --slice=admin --gateway=extra (Admin::Relations::Books)),
17
19
  ]
18
20
 
19
21
  # @since 2.2.0
@@ -21,6 +23,24 @@ module Hanami
21
23
  def generator_class
22
24
  Generators::App::Relation
23
25
  end
26
+
27
+ def call(name:, slice: nil, gateway: nil)
28
+ if slice
29
+ generator.call(
30
+ key: name,
31
+ namespace: slice,
32
+ base_path: fs.join("slices", inflector.underscore(slice)),
33
+ gateway: gateway
34
+ )
35
+ else
36
+ generator.call(
37
+ key: name,
38
+ namespace: app.namespace,
39
+ base_path: "app",
40
+ gateway: gateway
41
+ )
42
+ end
43
+ end
24
44
  end
25
45
  end
26
46
  end
@@ -21,13 +21,25 @@ module Hanami
21
21
  SKIP_DB_DEFAULT = false
22
22
  private_constant :SKIP_DB_DEFAULT
23
23
 
24
+ # @since 2.2.0
25
+ # @api private
26
+ DEFAULT_SKIP_ROUTE = false
27
+ private_constant :DEFAULT_SKIP_ROUTE
28
+
24
29
  # @since 2.2.0
25
30
  # @api private
26
31
  option :skip_db,
27
- type: :boolean,
32
+ type: :flag,
28
33
  required: false,
29
34
  default: SKIP_DB_DEFAULT,
30
35
  desc: "Skip database"
36
+ # @since 2.2.0
37
+ # @api private
38
+ option :skip_route,
39
+ type: :flag,
40
+ required: false,
41
+ default: DEFAULT_SKIP_ROUTE,
42
+ desc: "Skip route generation"
31
43
 
32
44
  example [
33
45
  "admin # Admin slice (/admin URL prefix)",
@@ -50,7 +62,8 @@ module Hanami
50
62
  def call(
51
63
  name:,
52
64
  url: nil,
53
- skip_db: SKIP_DB_DEFAULT
65
+ skip_db: SKIP_DB_DEFAULT,
66
+ skip_route: DEFAULT_SKIP_ROUTE
54
67
  )
55
68
  require "hanami/setup"
56
69
 
@@ -58,7 +71,7 @@ module Hanami
58
71
  name = inflector.underscore(Shellwords.shellescape(name))
59
72
  url = sanitize_url_prefix(name, url)
60
73
 
61
- generator.call(app, name, url, skip_db: skip_db)
74
+ generator.call(app, name, url, skip_db: skip_db, skip_route: skip_route)
62
75
  end
63
76
 
64
77
  private
@@ -41,16 +41,28 @@ module Hanami
41
41
  end
42
42
 
43
43
  register "generate", aliases: ["g"] do |prefix|
44
- prefix.register "action", Generate::Action
45
- prefix.register "component", Generate::Component
46
- prefix.register "migration", Generate::Migration
47
- prefix.register "operation", Generate::Operation
48
- prefix.register "part", Generate::Part
49
- prefix.register "relation", Generate::Relation
50
- prefix.register "repo", Generate::Repo
51
44
  prefix.register "slice", Generate::Slice
52
- prefix.register "struct", Generate::Struct
53
- prefix.register "view", Generate::View
45
+ prefix.register "component", Generate::Component
46
+
47
+ if Hanami.bundled?("hanami-controller")
48
+ prefix.register "action", Generate::Action
49
+ end
50
+
51
+ if Hanami.bundled?("dry-operation")
52
+ prefix.register "operation", Generate::Operation
53
+ end
54
+
55
+ if Hanami.bundled?("hanami-view")
56
+ prefix.register "view", Generate::View
57
+ prefix.register "part", Generate::Part
58
+ end
59
+
60
+ if Hanami.bundled?("hanami-db")
61
+ prefix.register "migration", Generate::Migration
62
+ prefix.register "relation", Generate::Relation
63
+ prefix.register "repo", Generate::Repo
64
+ prefix.register "struct", Generate::Struct
65
+ end
54
66
  end
55
67
  end
56
68
  end
@@ -21,12 +21,12 @@ module Hanami
21
21
 
22
22
  # @since 2.0.0
23
23
  # @api private
24
- def call(app, controller, action, url, http, format, skip_view, slice, context: nil)
24
+ def call(app, controller, action, url, http, format, skip_view, skip_route, slice, context: nil)
25
25
  context ||= ActionContext.new(inflector, app, slice, controller, action)
26
26
  if slice
27
- generate_for_slice(controller, action, url, http, format, skip_view, slice, context)
27
+ generate_for_slice(controller, action, url, http, format, skip_view, skip_route, slice, context)
28
28
  else
29
- generate_for_app(controller, action, url, http, format, skip_view, context)
29
+ generate_for_app(controller, action, url, http, format, skip_view, skip_route, context)
30
30
  end
31
31
  end
32
32
 
@@ -72,15 +72,17 @@ module Hanami
72
72
  attr_reader :inflector
73
73
 
74
74
  # rubocop:disable Metrics/AbcSize
75
- def generate_for_slice(controller, action, url, http, format, skip_view, slice, context)
75
+ def generate_for_slice(controller, action, url, http, format, skip_view, skip_route, slice, context)
76
76
  slice_directory = fs.join("slices", slice)
77
77
  raise MissingSliceError.new(slice) unless fs.directory?(slice_directory)
78
78
 
79
- fs.inject_line_at_block_bottom(
80
- fs.join("config", "routes.rb"),
81
- slice_matcher(slice),
82
- route(controller, action, url, http)
83
- )
79
+ if generate_route?(skip_route)
80
+ fs.inject_line_at_block_bottom(
81
+ fs.join("config", "routes.rb"),
82
+ slice_matcher(slice),
83
+ route(controller, action, url, http)
84
+ )
85
+ end
84
86
 
85
87
  fs.mkdir(directory = fs.join(slice_directory, "actions", controller))
86
88
  fs.write(fs.join(directory, "#{action}.rb"), t("slice_action.erb", context))
@@ -95,12 +97,14 @@ module Hanami
95
97
  end
96
98
  end
97
99
 
98
- def generate_for_app(controller, action, url, http, format, skip_view, context)
99
- fs.inject_line_at_class_bottom(
100
- fs.join("config", "routes.rb"),
101
- "class Routes",
102
- route(controller, action, url, http)
103
- )
100
+ def generate_for_app(controller, action, url, http, format, skip_view, skip_route, context)
101
+ if generate_route?(skip_route)
102
+ fs.inject_line_at_class_bottom(
103
+ fs.join("config", "routes.rb"),
104
+ "class Routes",
105
+ route(controller, action, url, http)
106
+ )
107
+ end
104
108
 
105
109
  fs.mkdir(directory = fs.join("app", "actions", controller))
106
110
  fs.write(fs.join(directory, "#{action}.rb"), t("action.erb", context))
@@ -137,6 +141,14 @@ module Hanami
137
141
  true
138
142
  end
139
143
 
144
+ # @api private
145
+ # @since 2.2.0
146
+ def generate_route?(skip_route)
147
+ return false if skip_route
148
+
149
+ true
150
+ end
151
+
140
152
  # @api private
141
153
  # @since 2.1.0
142
154
  def generate_restful_view?(view, directory)
@@ -2,6 +2,7 @@
2
2
 
3
3
  require "erb"
4
4
  require "dry/files"
5
+
5
6
  module Hanami
6
7
  module CLI
7
8
  module Generators
@@ -55,7 +55,9 @@ module Hanami
55
55
  ROM::SQL.migration do
56
56
  # Add your migration here.
57
57
  #
58
- # See https://sequel.jeremyevans.net/rdoc/files/doc/migration_rdoc.html for details.
58
+ # See https://guides.hanamirb.org/v2.2/database/migrations/ for details.
59
+ change do
60
+ end
59
61
  end
60
62
  RUBY
61
63
  private_constant :FILE_CONTENTS
@@ -19,8 +19,11 @@ module Hanami
19
19
 
20
20
  # @since 2.2.0
21
21
  # @api private
22
- def call(key:, namespace:, base_path:)
22
+ def call(key:, namespace:, base_path:, gateway:)
23
23
  schema_name = key.split(KEY_SEPARATOR).last
24
+ body_content = ["schema :#{schema_name}, infer: true"]
25
+
26
+ body_content.prepend("gateway :#{gateway}") if gateway
24
27
 
25
28
  RubyFileWriter.new(
26
29
  fs: fs,
@@ -31,7 +34,7 @@ module Hanami
31
34
  base_path: base_path,
32
35
  extra_namespace: "Relations",
33
36
  relative_parent_class: "DB::Relation",
34
- body: ["schema :#{schema_name}, infer: true"],
37
+ body: body_content,
35
38
  )
36
39
  end
37
40
 
@@ -22,9 +22,11 @@ module Hanami
22
22
  def call(app, slice, url, context: nil, **opts)
23
23
  context ||= SliceContext.new(inflector, app, slice, url, **opts)
24
24
 
25
- fs.inject_line_at_class_bottom(
26
- fs.join("config", "routes.rb"), "class Routes", t("routes.erb", context).chomp
27
- )
25
+ if context.generate_route?
26
+ fs.inject_line_at_class_bottom(
27
+ fs.join("config", "routes.rb"), "class Routes", t("routes.erb", context).chomp
28
+ )
29
+ end
28
30
 
29
31
  fs.mkdir(directory = "slices/#{slice}")
30
32
 
@@ -54,6 +54,12 @@ module Hanami
54
54
  !options.fetch(:skip_db, false)
55
55
  end
56
56
 
57
+ # @since 2.2.0
58
+ # @api private
59
+ def generate_route?
60
+ !options.fetch(:skip_route, false)
61
+ end
62
+
57
63
  private
58
64
 
59
65
  attr_reader :slice
@@ -112,7 +112,7 @@ module Hanami
112
112
  elsif generate_postgres?
113
113
  "postgres://localhost/#{app}"
114
114
  elsif generate_mysql?
115
- "mysql2://localhost/#{app}"
115
+ "mysql2://root@localhost/#{app}"
116
116
  else
117
117
  raise "Unknown database option: #{database_option}"
118
118
  end
@@ -14,8 +14,8 @@ source "https://rubygems.org"
14
14
  <%= hanami_gem("validations") %>
15
15
  <%= hanami_gem("view") %>
16
16
 
17
- gem "dry-types", "~> 1.0", ">= 1.6.1"
18
- gem "dry-operation", github: "dry-rb/dry-operation"
17
+ gem "dry-types", "~> 1.7"
18
+ gem "dry-operation"
19
19
  gem "puma"
20
20
  gem "rake"
21
21
  <%- if generate_sqlite? -%>
@@ -5,9 +5,5 @@ require "dry/operation"
5
5
 
6
6
  module <%= camelized_app_name %>
7
7
  class Operation < Dry::Operation
8
- <%- if generate_db? -%>
9
- # Provide `transaction do ... end` method for database transactions
10
- include Dry::Operation::Extensions::ROM
11
- <%- end -%>
12
8
  end
13
9
  end
@@ -0,0 +1,15 @@
1
+ # This seeds file should create the database records required to run the app.
2
+ #
3
+ # The code should be idempotent so that it can be executed at any time.
4
+ #
5
+ # To load the seeds, run `hanami db seed`. Seeds are also loaded as part of `hanami db prepare`.
6
+
7
+ # For example, if you have appropriate repos available:
8
+ #
9
+ # category_repo = Hanami.app["repos.category_repo"]
10
+ # category_repo.create(title: "General")
11
+ #
12
+ # Alternatively, you can use relations directly:
13
+ #
14
+ # categories = Hanami.app["relations.categories"]
15
+ # categories.insert(title: "General")
@@ -78,10 +78,11 @@ module Hanami
78
78
  fs.write("app/db/struct.rb", t("struct.erb", context))
79
79
  fs.write("app/structs/.keep", t("keep.erb", context))
80
80
 
81
- fs.write("config/db/migrate/.keep" , t("keep.erb", context))
81
+ fs.write("config/db/seeds.rb", t("seeds.erb", context))
82
+ fs.write("config/db/migrate/.keep", t("keep.erb", context))
82
83
 
83
84
  if context.generate_sqlite?
84
- fs.write("db/.keep" , t("keep.erb", context))
85
+ fs.write("db/.keep", t("keep.erb", context))
85
86
  end
86
87
  end
87
88
 
@@ -24,8 +24,8 @@ module Hanami
24
24
  AUTO_INDENT: true,
25
25
  PROMPT_I: "#{prompt}> ",
26
26
  PROMPT_N: "#{prompt}> ",
27
- PROMPT_S: "#{prompt} %l> ",
28
- PROMPT_C: "#{prompt} ?> ",
27
+ PROMPT_S: "#{prompt}%l ",
28
+ PROMPT_C: "#{prompt}* ",
29
29
  RETURN: "=> %s\n"
30
30
  }
31
31
 
@@ -6,6 +6,6 @@ module Hanami
6
6
  #
7
7
  # @api public
8
8
  # @since 2.0.0
9
- VERSION = "2.2.0.beta2"
9
+ VERSION = "2.2.0"
10
10
  end
11
11
  end
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.beta2
4
+ version: 2.2.0
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-09-25 00:00:00.000000000 Z
11
+ date: 2024-11-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -308,6 +308,7 @@ files:
308
308
  - lib/hanami/cli/generators/gem/app/relation.erb
309
309
  - lib/hanami/cli/generators/gem/app/repo.erb
310
310
  - lib/hanami/cli/generators/gem/app/routes.erb
311
+ - lib/hanami/cli/generators/gem/app/seeds.erb
311
312
  - lib/hanami/cli/generators/gem/app/settings.erb
312
313
  - lib/hanami/cli/generators/gem/app/struct.erb
313
314
  - lib/hanami/cli/generators/gem/app/types.erb
@@ -353,7 +354,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
353
354
  - !ruby/object:Gem::Version
354
355
  version: '0'
355
356
  requirements: []
356
- rubygems_version: 3.5.16
357
+ rubygems_version: 3.5.22
357
358
  signing_key:
358
359
  specification_version: 4
359
360
  summary: Hanami CLI