console_kit 0.1.0 → 0.1.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f2d0c26442743fd36188fcb719990675c771eb719974a847a90f404a7b3219d5
4
- data.tar.gz: 1be941647df505e1972fbf80aaa2bb49c1e74b6f029938c19e0f28f02c390c4d
3
+ metadata.gz: 8c68e98f9ea76d56039a31aee01f4642c23bc89e9b41868f988efff84f891647
4
+ data.tar.gz: 87be1db75fcb8d80851409a1903fe136d09e6275e5db9797b74f18df28603c63
5
5
  SHA512:
6
- metadata.gz: e691e2c0ea5658d03799fc037f9db6fddda50293224ccf5461295a81f7096bc44a2115ec9df3de697619b5532b3d92ddeec2c07204ac80c46c1a52cd35dd1ae2
7
- data.tar.gz: b6bc30dc509a8ce4bb98b7adb903e7b6dffbf96973d3afc11b8d4777feb73b69d96f3ceb5ef43205bac175247383ebc3b02d08c3ecaf87df96d3136d18161ef1
6
+ metadata.gz: f339cda7362c7a913918b992395ebd84ab4db2601a8c4d778302ae2579a1adfffab19d8eb63ca669b1d669ed9c58b589bfbe18c0d4ce758b83667b5935ebf304
7
+ data.tar.gz: c171cf918f2ea0ebe30c292f7b09847f3974c2fc39c55e21e36845c0399e04d7bc1b6558a8022bf860a57ae25403148ce62ef58748a7aad527ef55a870e6c5dd
data/.rubocop.yml CHANGED
@@ -1,8 +1,6 @@
1
1
  AllCops:
2
2
  TargetRubyVersion: 3.1
3
3
 
4
- Style/StringLiterals:
5
- EnforcedStyle: double_quotes
6
-
7
- Style/StringLiteralsInInterpolation:
8
- EnforcedStyle: double_quotes
4
+ Metrics/BlockLength:
5
+ Exclude:
6
+ - 'spec/**/*_spec.rb'
data/CHANGELOG.md CHANGED
@@ -1,5 +1,43 @@
1
- ## [Unreleased]
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ This project adheres to [Semantic Versioning](https://semver.org/).
6
+
7
+ ---
8
+
9
+ ## [0.1.2] - 2025-07-23
10
+ ### Added
11
+ - Changelog added.
12
+ - Readme and installation instructions added.
13
+
14
+ ---
15
+
16
+ ## [0.1.1] - 2025-07-21
17
+ ### Added
18
+ - Initial generator: `console_kit:install` to scaffold configuration.
19
+ - RSpec test suite to support core features.
20
+
21
+ ### Changed
22
+ - Applied RuboCop fixes for code consistency and style.
23
+
24
+ ---
2
25
 
3
26
  ## [0.1.0] - 2025-07-09
4
27
 
5
28
  - Initial release
29
+
30
+ ### Added
31
+ - Core setup logic for ConsoleKit:
32
+ - `ConsoleKit.setup`
33
+ - Tenant selection via CLI.
34
+ - Tenant-specific database configuration.
35
+ - Colorized console output for improved UX.
36
+
37
+ ---
38
+
39
+ ## [Unreleased]
40
+
41
+ [0.1.2]: https://github.com/Soumyadeep-ai/console_kit/releases/tag/v0.1.2
42
+ [0.1.1]: https://github.com/Soumyadeep-ai/console_kit/releases/tag/v0.1.1
43
+ [0.1.0]: https://github.com/Soumyadeep-ai/console_kit/releases/tag/v0.1.0
data/CODE_OF_CONDUCT.md CHANGED
@@ -60,7 +60,7 @@ representative at an online or offline event.
60
60
 
61
61
  Instances of abusive, harassing, or otherwise unacceptable behavior may be
62
62
  reported to the community leaders responsible for enforcement at
63
- [INSERT CONTACT METHOD].
63
+ [report here](https://github.com/Soumyadeep-ai/console_kit/issues).
64
64
  All complaints will be reviewed and investigated promptly and fairly.
65
65
 
66
66
  All community leaders are obligated to respect the privacy and security of the
data/README.md CHANGED
@@ -1,28 +1,59 @@
1
1
  # ConsoleKit
2
2
 
3
- TODO: Delete this and the text below, and describe your gem
3
+ A simple and flexible multi-tenant console setup toolkit for Rails applications.
4
4
 
5
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/console_kit`. To experiment with that code, run `bin/console` for an interactive prompt.
5
+ ConsoleKit helps you manage tenant-specific database connections and context configuration via an easy CLI interface and Rails integration.
6
6
 
7
7
  ## Installation
8
8
 
9
- TODO: Replace `UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG` with your gem name right after releasing it to RubyGems.org. Please do not do it earlier due to security reasons. Alternatively, replace this section with instructions to install your gem from git if you don't plan to release to RubyGems.org.
10
-
11
9
  Install the gem and add to the application's Gemfile by executing:
12
10
 
13
- ```bash
14
- bundle add UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG
11
+ ```ruby
12
+ bundle add console_kit
13
+ ```
14
+
15
+ Additionally you can also add this line to your application's Gemfile:
16
+
17
+ ```ruby
18
+ gem 'console_kit'
19
+ ```
20
+
21
+ And then execute:
22
+
23
+ ```ruby
24
+ bundle install
15
25
  ```
16
26
 
17
27
  If bundler is not being used to manage dependencies, install the gem by executing:
18
28
 
19
- ```bash
20
- gem install UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG
29
+ ```ruby
30
+ gem install console_kit
21
31
  ```
22
32
 
23
33
  ## Usage
24
34
 
25
- TODO: Write usage instructions here
35
+ After installing, generate the initializer and configuration files by running:
36
+
37
+ ```ruby
38
+ rails generate console_kit:install
39
+ ```
40
+
41
+ Then, edit config/initializers/console_kit.rb to define your tenants and context class. Example format:
42
+
43
+ ```ruby
44
+ ConsoleKit.configure do |config|
45
+ config.tenants = {
46
+ tenant_one: {
47
+ constants: { shard: :tenant_one_db, mongo_db: :tenant_one_mongo, partner_code: 'partnerA' }
48
+ },
49
+ tenant_two: {
50
+ constants: { shard: :tenant_two_db, mongo_db: :tenant_two_mongo, partner_code: 'partnerB' }
51
+ }
52
+ }
53
+
54
+ config.context_class = CurrentContext
55
+ end
56
+ ```
26
57
 
27
58
  ## Development
28
59
 
@@ -32,7 +63,7 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
32
63
 
33
64
  ## Contributing
34
65
 
35
- Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/console_kit. 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/[USERNAME]/console_kit/blob/master/CODE_OF_CONDUCT.md).
66
+ Bug reports and pull requests are welcome on GitHub at https://github.com/Soumyadeep-ai/console_kit. 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/Soumyadeep-ai/console_kit/blob/main/CODE_OF_CONDUCT.md).
36
67
 
37
68
  ## License
38
69
 
@@ -40,4 +71,4 @@ The gem is available as open source under the terms of the [MIT License](https:/
40
71
 
41
72
  ## Code of Conduct
42
73
 
43
- Everyone interacting in the ConsoleKit project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/[USERNAME]/console_kit/blob/master/CODE_OF_CONDUCT.md).
74
+ Everyone interacting in the ConsoleKit project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/Soumyadeep-ai/console_kit/blob/main/CODE_OF_CONDUCT.md).
data/Rakefile CHANGED
@@ -1,11 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "bundler/gem_tasks"
4
- require "rspec/core/rake_task"
3
+ require 'bundler/gem_tasks'
4
+ require 'rspec/core/rake_task'
5
5
 
6
6
  RSpec::Core::RakeTask.new(:spec)
7
7
 
8
- require "rubocop/rake_task"
8
+ require 'rubocop/rake_task'
9
9
 
10
10
  RuboCop::RakeTask.new
11
11
 
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ConsoleKit
4
+ # Handles Console outputs
5
+ module Output
6
+ class << self
7
+ def print_error(text)
8
+ print_message("[āœ—] #{text}", '1;31') # Red
9
+ end
10
+
11
+ def print_success(text)
12
+ print_message("[āœ“] #{text}", '1;32') # Green
13
+ end
14
+
15
+ def print_backtrace(exception)
16
+ exception.backtrace.each { |line| print_message(" #{line}", '0;90') } # Dim gray
17
+ end
18
+
19
+ def print_header(text)
20
+ print_message("\n=== #{text} ===", '1;34') # Bold Blue
21
+ end
22
+
23
+ def print_info(text)
24
+ print_message(text)
25
+ end
26
+
27
+ def print_prompt(text)
28
+ print_message(text, '1;36') # Cyan
29
+ end
30
+
31
+ def print_warning(text)
32
+ print_message("[!] #{text}", '1;33') # Yellow
33
+ end
34
+
35
+ private
36
+
37
+ def print_message(text, color = nil)
38
+ msg = "[ConsoleKit] #{text}"
39
+ puts color ? "\e[#{color}m#{msg}\e[0m" : msg
40
+ end
41
+ end
42
+ end
43
+ end
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ConsoleKit
4
+ # Railtie
4
5
  class Railtie < Rails::Railtie
5
6
  console do
6
7
  ConsoleKit.setup
@@ -1,20 +1,23 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative 'tenant_selector'
4
+ require_relative 'tenant_configurator'
5
+ require_relative 'output'
6
+
7
+ # Core Logic for initial Setup
3
8
  module ConsoleKit
4
9
  class << self
5
10
  attr_accessor :tenants, :context_class
6
11
 
7
12
  def setup
8
- return print_error("No tenants configured.") if tenants.nil? || tenants.empty?
13
+ return Output.print_error('No tenants configured.') if tenants.nil? || tenants.empty?
9
14
 
10
- tenant_key = tenants.size == 1 || !$stdin.tty? ? tenants.keys.first : select_tenant(tenants.keys)
11
- return print_error("No tenant selected. Loading without tenant configuration.") unless tenant_key
15
+ tenant_key = resolve_tenant_key
16
+ return Output.print_error('No tenant selected. Loading without tenant configuration.') unless tenant_key
12
17
 
13
- configure_tenant(tenant_key)
14
- print_success("Tenant initialized: #{tenant_key}")
18
+ initialize_tenant(tenant_key)
15
19
  rescue StandardError => e
16
- print_error("Error setting up tenant: #{e.message}")
17
- print_backtrace(e)
20
+ handle_setup_error(e)
18
21
  end
19
22
 
20
23
  def configure
@@ -23,88 +26,26 @@ module ConsoleKit
23
26
 
24
27
  private
25
28
 
26
- def select_tenant(keys)
27
- print_header("Multiple tenants detected. Please choose one:")
28
- print_info(" 0. Load without tenant (no tenant configuration)")
29
- keys.each_with_index do |key, index|
30
- partner = tenants.dig(key, :constants, :partner_code) || 'N/A'
31
- print_info(" #{index + 1}. #{key} (partner: #{partner})")
32
- end
33
-
34
- max_attempts = 3
35
- selected_key = nil
36
-
37
- max_attempts.times do
38
- print_prompt("\nEnter the number of the tenant you want (or press Enter for default '1'): ")
39
- input = $stdin.gets&.chomp&.strip
40
-
41
- input = '1' if input.to_s.empty?
42
-
43
- unless (index = input.to_i) && index.between?(0, keys.size)
44
- print_warning("Invalid selection. Please try again.")
45
- next
46
- end
47
-
48
- return nil if index.zero?
49
-
50
- selected_key = keys[index - 1]
51
- break
52
- end
53
-
54
- selected_key
55
- end
56
-
57
- def configure_tenant(key)
58
- config = tenants[key]
59
- constants = config[:constants]
60
-
61
- tenant_shard = constants[:shard]
62
- tenant_mongo_db = constants[:mongo_db]
63
-
64
- context_class.tenant_shard = tenant_shard
65
- context_class.tenant_mongo_db = tenant_mongo_db
66
- context_class.partner_identifier = constants[:partner_code]
67
-
68
- ApplicationRecord.establish_connection(tenant_shard.to_sym)
69
- Mongoid.override_client(tenant_mongo_db.to_s)
70
-
71
- print_success("Tenant set to: #{key}")
72
- rescue StandardError => e
73
- print_error("Failed to configure tenant '#{key}': #{e.message}")
74
- print_backtrace(e)
75
- end
76
-
77
- def print_error(text)
78
- print_message("[āœ—] #{text}", '1;31') # Red
79
- end
80
-
81
- def print_success(text)
82
- print_message("[āœ“] #{text}", '1;32') # Green
83
- end
84
-
85
- def print_backtrace(exception)
86
- exception.backtrace.each { |line| print_message(" #{line}", '0;90') } # Dim gray
87
- end
88
-
89
- def print_header(text)
90
- print_message("\n=== #{text} ===", '1;34') # Bold Blue
29
+ def resolve_tenant_key
30
+ single_tenant? || non_interactive? ? tenants.keys.first : TenantSelector.select(tenants, tenants.keys)
91
31
  end
92
32
 
93
- def print_info(text)
94
- print_message(text)
33
+ def single_tenant?
34
+ tenants.size == 1
95
35
  end
96
36
 
97
- def print_prompt(text)
98
- print_message(text, '1;36') # Cyan
37
+ def non_interactive?
38
+ !$stdin.tty?
99
39
  end
100
40
 
101
- def print_warning(text)
102
- print_message("[!] #{text}", '1;33') # Yellow
41
+ def initialize_tenant(tenant_key)
42
+ TenantConfigurator.configure_tenant(tenant_key, tenants, context_class)
43
+ Output.print_success("Tenant initialized: #{tenant_key}")
103
44
  end
104
45
 
105
- def print_message(text, color = nil)
106
- msg = "[ConsoleKit] #{text}"
107
- puts color ? "\e[#{color}m#{msg}\e[0m" : msg
46
+ def handle_setup_error(error)
47
+ Output.print_error("Error setting up tenant: #{error.message}")
48
+ Output.print_backtrace(error)
108
49
  end
109
50
  end
110
51
  end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'output'
4
+
5
+ module ConsoleKit
6
+ # For tenant configuration
7
+ module TenantConfigurator
8
+ class << self
9
+ def configure_tenant(key, tenants, context_class)
10
+ config = tenants[key]
11
+ return Output.print_error("No configuration found for tenant: #{key}") unless config
12
+
13
+ constants = config[:constants]
14
+ apply_context(context_class, constants)
15
+ setup_database_connections(context_class)
16
+
17
+ Output.print_success("Tenant set to: #{key}")
18
+ rescue StandardError => e
19
+ Output.print_error("Failed to configure tenant '#{key}': #{e.message}")
20
+ Output.print_backtrace(e)
21
+ end
22
+
23
+ private
24
+
25
+ def apply_context(context_class, constants)
26
+ context_class.tenant_shard = constants[:shard]
27
+ context_class.tenant_mongo_db = constants[:mongo_db]
28
+ context_class.partner_identifier = constants[:partner_code]
29
+ end
30
+
31
+ def setup_database_connections(context_class)
32
+ ApplicationRecord.establish_connection(context_class.tenant_shard.to_sym)
33
+ Mongoid.override_client(context_class.tenant_mongo_db.to_s)
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'output'
4
+
5
+ module ConsoleKit
6
+ # For tenant selection
7
+ module TenantSelector
8
+ class << self
9
+ def select(tenants, keys)
10
+ print_tenant_selection_menu(tenants, keys)
11
+
12
+ max_attempts = 3
13
+ max_attempts.times do
14
+ index = prompt_user_for_selection(keys.size)
15
+ return nil if index.zero?
16
+ return keys[index - 1] if index.positive?
17
+ end
18
+
19
+ nil
20
+ end
21
+
22
+ private
23
+
24
+ def print_tenant_selection_menu(tenants, keys)
25
+ Output.print_header('Multiple tenants detected. Please choose one:')
26
+ Output.print_info(' 0. Load without tenant (no tenant configuration)')
27
+
28
+ keys.each_with_index do |key, index|
29
+ partner = tenants.dig(key, :constants, :partner_code) || 'N/A'
30
+ Output.print_info(" #{index + 1}. #{key} (partner: #{partner})")
31
+ end
32
+ end
33
+
34
+ def prompt_user_for_selection(max_index)
35
+ Output.print_prompt("\nEnter the number of the tenant you want (or press Enter for default '1'): ")
36
+ input = $stdin.gets&.chomp&.strip
37
+ input = '1' if input.to_s.empty?
38
+
39
+ return invalid_input_response unless valid_integer?(input)
40
+
41
+ parsed_index = input.to_i
42
+ return invalid_range_response(max_index) unless parsed_index.between?(0, max_index)
43
+
44
+ parsed_index
45
+ end
46
+
47
+ def valid_integer?(input)
48
+ input.match?(/\A\d+\z/)
49
+ end
50
+
51
+ def invalid_input_response
52
+ Output.print_warning('Invalid input. Please enter a number.')
53
+ -1
54
+ end
55
+
56
+ def invalid_range_response(max_index)
57
+ Output.print_warning("Selection must be between 0 and #{max_index}.")
58
+ -1
59
+ end
60
+ end
61
+ end
62
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ConsoleKit
4
- VERSION = "0.1.0"
4
+ VERSION = '0.1.2'
5
5
  end
data/lib/console_kit.rb CHANGED
@@ -1,8 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "console_kit/version"
4
- require_relative "console_kit/setup"
5
- require_relative "console_kit/railtie" if defined?(Rails::Railtie)
3
+ require_relative 'console_kit/version'
4
+ require_relative 'console_kit/setup'
5
+ require_relative 'console_kit/railtie' if defined?(Rails::Railtie)
6
6
 
7
7
  module ConsoleKit
8
8
  class Error < StandardError; end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails/generators'
4
+ require 'rails/generators/base'
5
+
6
+ module ConsoleKit
7
+ module Generators
8
+ # Generates the required files
9
+ class InstallGenerator < Rails::Generators::Base
10
+ source_root File.expand_path('templates', __dir__)
11
+
12
+ def copy_initializer
13
+ initializer_path = Rails.root.join('config', 'initializers', 'console_kit.rb')
14
+
15
+ if File.exist?(initializer_path)
16
+ say_status('skipped', "Initializer already exists: #{initializer_path}", :yellow)
17
+ else
18
+ template 'console_kit.rb', 'config/initializers/console_kit.rb'
19
+ say_status('created', "Initializer generated at #{initializer_path}", :green)
20
+ end
21
+ end
22
+
23
+ def remind_about_customization
24
+ say "\nāœ… Setup complete!", :green
25
+ say 'šŸ‘‰ Please update `config/initializers/console_kit.rb` to set your `tenants` and `context_class`.', :green
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Auto-generated by ConsoleKit
4
+ # šŸ‘‰ Customize the following configuration to fit your application
5
+
6
+ Rails.application.config.after_initialize do
7
+ ConsoleKit.configure do |config|
8
+ # TODO: Set your tenants source in the following format
9
+ # {
10
+ # key:
11
+ # {
12
+ # constants:
13
+ # {
14
+ # shard: # Active Record Shard
15
+ # mongo_db: # Mongo Shard (If Mongo Is being used)
16
+ # partner_code: # If partners are needed
17
+ # }
18
+ # }
19
+ # }
20
+ config.tenants = nil
21
+
22
+ # TODO: Set your context class (e.g., CurrentContext)
23
+ config.context_class = nil
24
+ end
25
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: console_kit
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Soumyadeep Pal
@@ -10,33 +10,33 @@ cert_chain: []
10
10
  date: 1980-01-02 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
- name: rails
13
+ name: mongoid
14
14
  requirement: !ruby/object:Gem::Requirement
15
15
  requirements:
16
16
  - - ">="
17
17
  - !ruby/object:Gem::Version
18
- version: 7.2.1
18
+ version: '0'
19
19
  type: :runtime
20
20
  prerelease: false
21
21
  version_requirements: !ruby/object:Gem::Requirement
22
22
  requirements:
23
23
  - - ">="
24
24
  - !ruby/object:Gem::Version
25
- version: 7.2.1
25
+ version: '0'
26
26
  - !ruby/object:Gem::Dependency
27
- name: mongoid
27
+ name: rails
28
28
  requirement: !ruby/object:Gem::Requirement
29
29
  requirements:
30
30
  - - ">="
31
31
  - !ruby/object:Gem::Version
32
- version: '0'
32
+ version: 7.2.1
33
33
  type: :runtime
34
34
  prerelease: false
35
35
  version_requirements: !ruby/object:Gem::Requirement
36
36
  requirements:
37
37
  - - ">="
38
38
  - !ruby/object:Gem::Version
39
- version: '0'
39
+ version: 7.2.1
40
40
  description: Adds tenant selection to Rails consoles
41
41
  email:
42
42
  - soumyadeeppal2001@gmail.com
@@ -52,9 +52,14 @@ files:
52
52
  - README.md
53
53
  - Rakefile
54
54
  - lib/console_kit.rb
55
+ - lib/console_kit/output.rb
55
56
  - lib/console_kit/railtie.rb
56
57
  - lib/console_kit/setup.rb
58
+ - lib/console_kit/tenant_configurator.rb
59
+ - lib/console_kit/tenant_selector.rb
57
60
  - lib/console_kit/version.rb
61
+ - lib/generators/console_kit/install_generator.rb
62
+ - lib/generators/console_kit/templates/console_kit.rb
58
63
  - sig/console_kit.rbs
59
64
  homepage: https://github.com/Soumyadeep-ai/console_kit
60
65
  licenses: