strata-cli 0.1.7 → 0.1.9

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 (43) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +25 -0
  3. data/README.md +24 -1
  4. data/lib/strata/cli/ai/services/table_generator.rb +35 -20
  5. data/lib/strata/cli/api/client.rb +23 -63
  6. data/lib/strata/cli/api/response_error_handler.rb +115 -0
  7. data/lib/strata/cli/credentials.rb +5 -9
  8. data/lib/strata/cli/error_reporter.rb +4 -1
  9. data/lib/strata/cli/generators/datasource.rb +4 -3
  10. data/lib/strata/cli/generators/group.rb +37 -0
  11. data/lib/strata/cli/generators/migration.rb +2 -1
  12. data/lib/strata/cli/generators/project.rb +18 -11
  13. data/lib/strata/cli/generators/relation.rb +2 -1
  14. data/lib/strata/cli/generators/table.rb +5 -8
  15. data/lib/strata/cli/generators/templates/adapters/databricks.yml +4 -3
  16. data/lib/strata/cli/generators/templates/adapters/snowflake.yml +1 -21
  17. data/lib/strata/cli/generators/templates/table.table_name.yml +1 -1
  18. data/lib/strata/cli/generators/test.rb +2 -1
  19. data/lib/strata/cli/guard.rb +4 -1
  20. data/lib/strata/cli/helpers/command_context.rb +8 -9
  21. data/lib/strata/cli/helpers/datasource_helper.rb +1 -1
  22. data/lib/strata/cli/helpers/description_helper.rb +2 -1
  23. data/lib/strata/cli/main.rb +15 -3
  24. data/lib/strata/cli/output.rb +103 -0
  25. data/lib/strata/cli/sub_commands/audit.rb +4 -3
  26. data/lib/strata/cli/sub_commands/branch.rb +163 -0
  27. data/lib/strata/cli/sub_commands/create.rb +1 -2
  28. data/lib/strata/cli/sub_commands/datasource.rb +13 -4
  29. data/lib/strata/cli/sub_commands/deploy.rb +14 -13
  30. data/lib/strata/cli/sub_commands/project.rb +4 -3
  31. data/lib/strata/cli/sub_commands/table.rb +9 -8
  32. data/lib/strata/cli/terminal.rb +7 -4
  33. data/lib/strata/cli/ui/field_editor.rb +21 -27
  34. data/lib/strata/cli/utils/deployment_monitor.rb +15 -34
  35. data/lib/strata/cli/utils/git.rb +78 -0
  36. data/lib/strata/cli/utils/import_manager.rb +4 -1
  37. data/lib/strata/cli/utils/test_reporter.rb +4 -32
  38. data/lib/strata/cli/utils/version_checker.rb +4 -8
  39. data/lib/strata/cli/utils.rb +3 -1
  40. data/lib/strata/cli/version.rb +1 -1
  41. data/lib/strata/cli.rb +4 -3
  42. metadata +4 -2
  43. data/lib/strata/cli/helpers/color_helper.rb +0 -103
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "../helpers/color_helper"
4
3
  require_relative "../terminal"
4
+ require_relative "../output"
5
5
  require "tty-spinner"
6
6
  require "pastel"
7
7
 
@@ -117,8 +117,8 @@ module Strata
117
117
 
118
118
  if Time.now - start_time > timeout
119
119
  complete_stage(TESTING_STAGE) if @tests_running
120
- say "\n Monitoring timeout reached (#{timeout}s)", ColorHelper.warning
121
- say " Deployment may still be in progress. Check server for status.\n", ColorHelper.info
120
+ say "\n Monitoring timeout reached (#{timeout}s)", :warning
121
+ say " Deployment may still be in progress. Check server for status.\n", :info
122
122
  return deployment
123
123
  end
124
124
 
@@ -126,13 +126,13 @@ module Strata
126
126
  end
127
127
  rescue Interrupt
128
128
  stop_all_spinners
129
- say "\n\n Monitoring interrupted. Deployment continues in background.", ColorHelper.warning
130
- say " Check server for deployment status with command `strata deploy status`.\n", ColorHelper.info
129
+ say "\n\n Monitoring interrupted. Deployment continues in background.", :warning
130
+ say " Check server for deployment status with command `strata deploy status`.\n", :info
131
131
  nil
132
132
  rescue => e
133
133
  stop_all_spinners
134
- say "\n Error monitoring deployment: #{e.message}", ColorHelper.error
135
- say " Check server for deployment status.\n", ColorHelper.info
134
+ say "\n Error monitoring deployment: #{e.message}", :error
135
+ say " Check server for deployment status.\n", :info
136
136
  nil
137
137
  end
138
138
 
@@ -150,11 +150,11 @@ module Strata
150
150
  deployment
151
151
  rescue Interrupt
152
152
  stop_all_spinners
153
- say "\n\n Exiting status view.\n", ColorHelper.info
153
+ say "\n\n Exiting status view.\n", :info
154
154
  nil
155
155
  rescue => e
156
156
  stop_all_spinners
157
- say "\n Error fetching deployment status: #{e.message}", ColorHelper.error
157
+ say "\n Error fetching deployment status: #{e.message}", :error
158
158
  nil
159
159
  end
160
160
 
@@ -169,42 +169,23 @@ module Strata
169
169
 
170
170
  private
171
171
 
172
- def say(message, color_helper_result = nil)
173
- return $stdout.puts(message) unless color_helper_result
174
-
175
- colored_message = case color_helper_result
176
- when Array
177
- ColorHelper.pastel.decorate(message, *color_helper_result)
178
- when Symbol
179
- theme = ColorHelper::THEME[color_helper_result]
180
- if theme
181
- ColorHelper.pastel.decorate(message, *Array(theme))
182
- else
183
- begin
184
- ColorHelper.pastel.send(color_helper_result, message)
185
- rescue NoMethodError
186
- message
187
- end
188
- end
189
- else
190
- message
191
- end
192
-
193
- $stdout.puts(colored_message)
172
+ def say(message, type = nil)
173
+ shell = Output.shell_for(nil)
174
+ shell.say(type ? Output.format(type, message) : message)
194
175
  end
195
176
 
196
177
  def display_initial_status
197
- say "\n Monitoring deployment progress...\n", ColorHelper.title
178
+ say "\n Monitoring deployment progress...\n", :title
198
179
  end
199
180
 
200
181
  def display_exit_instruction
201
- say " Press Ctrl+C to exit monitoring.\n", ColorHelper.dim
182
+ say " Press Ctrl+C to exit monitoring.\n", :dim
202
183
  end
203
184
 
204
185
  def fetch_deployment_status
205
186
  @client.get_deployment(@project_id, @branch_id, @deployment_id)
206
187
  rescue Strata::CommandError => e
207
- say "\n Could not fetch deployment status: #{e.message}", ColorHelper.warning
188
+ say "\n Could not fetch deployment status: #{e.message}", :warning
208
189
  nil
209
190
  end
210
191
 
@@ -21,6 +21,53 @@ module Strata
21
21
  run_git_command("rev-parse", "--abbrev-ref", "HEAD")
22
22
  end
23
23
 
24
+ def local_branches
25
+ return [] unless git_repo?
26
+
27
+ output = run_git_command("branch", "--format", "%(refname:short)")
28
+ return [] unless output
29
+
30
+ output.lines.map(&:strip).reject(&:empty?)
31
+ end
32
+
33
+ def create_and_checkout_branch(branch_name)
34
+ ensure_git_repo!
35
+ branch_name = validate_branch_name!(branch_name)
36
+
37
+ _, stderr, status = Open3.capture3("git", "switch", "-c", branch_name)
38
+ raise Strata::CommandError, "Failed to create branch '#{branch_name}': #{stderr.strip}" unless status.success?
39
+
40
+ branch_name
41
+ end
42
+
43
+ def checkout_branch(branch_name)
44
+ ensure_git_repo!
45
+ branch_name = validate_branch_name!(branch_name)
46
+
47
+ _, stderr, status = Open3.capture3("git", "switch", branch_name)
48
+ raise Strata::CommandError, "Failed to checkout branch '#{branch_name}': #{stderr.strip}" unless status.success?
49
+
50
+ branch_name
51
+ end
52
+
53
+ def delete_local_branch(branch_name, fallback_branches: %w[main master])
54
+ return :not_git_repo unless git_repo?
55
+
56
+ branch_name = branch_name.to_s.strip
57
+ raise Strata::CommandError, "Branch name is required." if branch_name.empty?
58
+
59
+ return :not_found unless local_branch_exists?(branch_name)
60
+
61
+ if current_branch == branch_name
62
+ switch_to_fallback_branch(branch_name, fallback_branches)
63
+ end
64
+
65
+ _, stderr, status = Open3.capture3("git", "branch", "-D", branch_name)
66
+ raise Strata::CommandError, "Failed to delete local branch '#{branch_name}': #{stderr.strip}" unless status.success?
67
+
68
+ :deleted
69
+ end
70
+
24
71
  def commit_info
25
72
  sha = run_git_command("rev-parse", "HEAD")
26
73
  message = run_git_command("log", "-1", "--pretty=%B")
@@ -121,6 +168,21 @@ module Strata
121
168
  false
122
169
  end
123
170
 
171
+ def local_branch_exists?(branch_name)
172
+ _, _, status = Open3.capture3("git", "show-ref", "--verify", "--quiet", "refs/heads/#{branch_name}")
173
+ status.success?
174
+ end
175
+
176
+ def validate_branch_name!(branch_name)
177
+ branch_name = branch_name.to_s.strip
178
+ raise Strata::CommandError, "Branch name is required." if branch_name.empty?
179
+
180
+ _, stderr, status = Open3.capture3("git", "check-ref-format", "--branch", branch_name)
181
+ raise Strata::CommandError, "Invalid branch name '#{branch_name}': #{stderr.strip}" unless status.success?
182
+
183
+ branch_name
184
+ end
185
+
124
186
  def check_requirement_and_exit_if_unavailable(args)
125
187
  # Allow help and version commands to work without Git
126
188
  command = args.first
@@ -149,6 +211,22 @@ module Strata
149
211
  stdout&.strip
150
212
  end
151
213
 
214
+ def ensure_git_repo!
215
+ raise Strata::CommandError, "Not a git repository." unless git_repo?
216
+ end
217
+
218
+ def switch_to_fallback_branch(branch_name, fallback_branches)
219
+ fallback_branch = fallback_branches.find { |candidate| candidate != branch_name && local_branch_exists?(candidate) }
220
+
221
+ unless fallback_branch
222
+ raise Strata::CommandError,
223
+ "Cannot delete the currently checked out branch '#{branch_name}'. Check out another branch and try again."
224
+ end
225
+
226
+ _, stderr, status = Open3.capture3("git", "switch", fallback_branch)
227
+ raise Strata::CommandError, "Failed to switch to '#{fallback_branch}': #{stderr.strip}" unless status.success?
228
+ end
229
+
152
230
  def parse_diff_output(output)
153
231
  output.lines.map do |line|
154
232
  parse_diff_status(line.strip)
@@ -135,7 +135,10 @@ module Strata
135
135
 
136
136
  YAML.safe_load_file(lock_path, permitted_classes: [Date, Time], aliases: true) || default_lock_data
137
137
  rescue => e
138
- warn "Failed to load lock file: #{e.message}" if ENV["DEBUG"]
138
+ if ENV["DEBUG"]
139
+ require_relative "../output"
140
+ Output.print_warning("Failed to load lock file: #{e.message}")
141
+ end
139
142
  default_lock_data
140
143
  end
141
144
 
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "../helpers/color_helper"
4
3
  require_relative "../terminal"
4
+ require_relative "../output"
5
5
 
6
6
  module Strata
7
7
  module CLI
@@ -9,10 +9,6 @@ module Strata
9
9
  class TestReporter
10
10
  include Terminal
11
11
 
12
- def initialize(color_helper: ColorHelper)
13
- @color_helper = color_helper
14
- end
15
-
16
12
  def display(test_results, skip_opening_divider: false)
17
13
  return unless test_results.is_a?(Hash) && test_results["tests"].is_a?(Array)
18
14
 
@@ -22,33 +18,9 @@ module Strata
22
18
 
23
19
  private
24
20
 
25
- attr_reader :color_helper
26
-
27
- def say(message, color_helper_result = nil)
28
- if color_helper_result
29
- if color_helper_result.is_a?(Array)
30
- colored_message = ColorHelper.pastel.decorate(message, *color_helper_result)
31
- $stdout.puts(colored_message)
32
- elsif color_helper_result.is_a?(Symbol)
33
- theme = ColorHelper::THEME[color_helper_result]
34
- if theme
35
- styles = Array(theme)
36
- colored_message = ColorHelper.pastel.decorate(message, *styles)
37
- $stdout.puts(colored_message)
38
- else
39
- begin
40
- colored_message = ColorHelper.pastel.send(color_helper_result, message)
41
- $stdout.puts(colored_message)
42
- rescue NoMethodError
43
- $stdout.puts(message)
44
- end
45
- end
46
- else
47
- $stdout.puts(message)
48
- end
49
- else
50
- $stdout.puts(message)
51
- end
21
+ def say(message, type = nil)
22
+ shell = Output.shell_for(nil)
23
+ shell.say(type ? Output.format(type, message) : message)
52
24
  end
53
25
 
54
26
  def display_summary(test_results, skip_opening_divider: false)
@@ -29,7 +29,7 @@ module Strata
29
29
  update_cache
30
30
  rescue
31
31
  # Silently fail - version checking should never break the CLI
32
- # In development, you might want to log this: warn "Version check failed: #{e.message}"
32
+ # In development, you might want to log this failure.
33
33
  nil
34
34
  end
35
35
 
@@ -81,15 +81,11 @@ module Strata
81
81
  end
82
82
 
83
83
  def display_update_message(version)
84
- require_relative "../helpers/color_helper"
85
- colors = ColorHelper
86
-
87
84
  message = "💡 Tip: A new version of #{GEM_NAME} (#{version}) is available. " \
88
- "Update with: #{colors.info("gem update strata-cli")}"
85
+ "Update with: #{Output.format(:info, "gem update strata-cli")}"
89
86
 
90
- # Use Thor's say method for consistent output
91
- shell = Thor::Shell::Color.new
92
- shell.say "\n#{colors.warning(message)}\n"
87
+ require_relative "../output"
88
+ Output.print_warning("\n#{message}\n")
93
89
  end
94
90
 
95
91
  def skip_check?
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative "output"
4
+
3
5
  module Strata
4
6
  module CLI
5
7
  module Utils
@@ -16,7 +18,7 @@ module Strata
16
18
  def exit_error_if_not_strata!
17
19
  return if CLI.config.strata_project?
18
20
 
19
- Thor::Shell::Color.new.say_error "ERROR: This is not a valid strata project", :red
21
+ Output.print_error("ERROR: This is not a valid strata project")
20
22
  exit 1
21
23
  end
22
24
 
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Strata
4
4
  module CLI
5
- VERSION = "0.1.7"
5
+ VERSION = "0.1.9"
6
6
  end
7
7
  end
data/lib/strata/cli.rb CHANGED
@@ -9,6 +9,7 @@ require_relative "cli/utils"
9
9
  require_relative "cli/utils/git"
10
10
  require_relative "cli/utils/version_checker"
11
11
  require_relative "cli/error_reporter"
12
+ require_relative "cli/output"
12
13
 
13
14
  module Strata
14
15
  class StrataError < StandardError; end
@@ -37,12 +38,12 @@ module Strata
37
38
  begin
38
39
  Main.start(args)
39
40
  rescue TTY::Reader::InputInterrupt
40
- warn "\nCancelled."
41
+ Output.print_warning("\nCancelled.")
41
42
  exit(1)
42
43
  rescue => e
43
44
  ErrorReporter.log_error(e, context: "strata #{args.join(" ")}")
44
- warn "ERROR: #{ErrorReporter.user_message_for(e)}"
45
- warn "Hint: See #{ErrorReporter.log_relative_path} for details."
45
+ Output.print_error("ERROR: #{ErrorReporter.user_message_for(e)}")
46
+ Output.print_hint("Hint: See #{ErrorReporter.log_relative_path} for details.", stderr: true)
46
47
  exit(1)
47
48
  end
48
49
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: strata-cli
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.7
4
+ version: 0.1.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ajo Abraham
@@ -247,6 +247,7 @@ files:
247
247
  - lib/strata/cli/ai/services/table_generator.rb
248
248
  - lib/strata/cli/api/client.rb
249
249
  - lib/strata/cli/api/connection_error_handler.rb
250
+ - lib/strata/cli/api/response_error_handler.rb
250
251
  - lib/strata/cli/configuration.rb
251
252
  - lib/strata/cli/credentials.rb
252
253
  - lib/strata/cli/descriptions/create/migration.txt
@@ -288,7 +289,6 @@ files:
288
289
  - lib/strata/cli/generators/templates/test.yml
289
290
  - lib/strata/cli/generators/test.rb
290
291
  - lib/strata/cli/guard.rb
291
- - lib/strata/cli/helpers/color_helper.rb
292
292
  - lib/strata/cli/helpers/command_context.rb
293
293
  - lib/strata/cli/helpers/datasource_helper.rb
294
294
  - lib/strata/cli/helpers/description_helper.rb
@@ -296,7 +296,9 @@ files:
296
296
  - lib/strata/cli/helpers/prompts.rb
297
297
  - lib/strata/cli/helpers/table_filter.rb
298
298
  - lib/strata/cli/main.rb
299
+ - lib/strata/cli/output.rb
299
300
  - lib/strata/cli/sub_commands/audit.rb
301
+ - lib/strata/cli/sub_commands/branch.rb
300
302
  - lib/strata/cli/sub_commands/create.rb
301
303
  - lib/strata/cli/sub_commands/datasource.rb
302
304
  - lib/strata/cli/sub_commands/deploy.rb
@@ -1,103 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "pastel"
4
-
5
- module Strata
6
- module CLI
7
- module ColorHelper
8
- THEME = {
9
- success: :green,
10
- error: %i[red bold],
11
- warning: :yellow,
12
- info: :cyan,
13
- title: %i[cyan bold],
14
- highlight: %i[cyan bold],
15
- dim: :bright_black,
16
- primary: :blue,
17
- secondary: :magenta,
18
- border: %i[cyan dim],
19
- selected: %i[green bold],
20
- disabled: :dim
21
- }.freeze
22
-
23
- class << self
24
- def pastel
25
- @pastel ||= Pastel.new(enabled: $stdout.tty?)
26
- end
27
-
28
- def success(text = nil)
29
- apply_theme(:success, text)
30
- end
31
-
32
- def error(text = nil)
33
- apply_theme(:error, text)
34
- end
35
-
36
- def warning(text = nil)
37
- apply_theme(:warning, text)
38
- end
39
-
40
- def info(text = nil)
41
- apply_theme(:info, text)
42
- end
43
-
44
- def title(text = nil)
45
- apply_theme(:title, text)
46
- end
47
-
48
- def highlight(text = nil)
49
- apply_theme(:highlight, text)
50
- end
51
-
52
- def dim(text = nil)
53
- apply_theme(:dim, text)
54
- end
55
-
56
- def primary(text = nil)
57
- apply_theme(:primary, text)
58
- end
59
-
60
- def secondary(text = nil)
61
- apply_theme(:secondary, text)
62
- end
63
-
64
- def border(text = nil)
65
- apply_theme(:border, text)
66
- end
67
-
68
- def selected(text = nil)
69
- apply_theme(:selected, text)
70
- end
71
-
72
- def disabled(text = nil)
73
- apply_theme(:disabled, text)
74
- end
75
-
76
- def bright_cyan(text = nil)
77
- text ? pastel.bright_cyan(text) : :bright_cyan
78
- end
79
-
80
- def bright_green(text = nil)
81
- text ? pastel.bright_green(text) : :bright_green
82
- end
83
-
84
- def bright_yellow(text = nil)
85
- text ? pastel.bright_yellow(text) : :bright_yellow
86
- end
87
-
88
- private
89
-
90
- def apply_theme(key, text)
91
- styles = THEME[key]
92
- return styles unless text
93
-
94
- if styles.is_a?(Array)
95
- pastel.decorate(text, *styles)
96
- else
97
- pastel.send(styles, text)
98
- end
99
- end
100
- end
101
- end
102
- end
103
- end