kern 0.5.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 (84) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +22 -0
  3. data/Gemfile.lock +423 -0
  4. data/README.md +178 -0
  5. data/Rakefile +31 -0
  6. data/app/assets/builds/tailwind.css +2 -0
  7. data/app/controllers/concerns/authentication.rb +55 -0
  8. data/app/controllers/concerns/authentication.rb.tt +55 -0
  9. data/app/controllers/kern/application_controller.rb +7 -0
  10. data/app/controllers/kern/pages_controller.rb +6 -0
  11. data/app/controllers/kern/passwords_controller.rb +40 -0
  12. data/app/controllers/kern/sessions_controller.rb +30 -0
  13. data/app/controllers/kern/settings/users_controller.rb +26 -0
  14. data/app/controllers/kern/settings_controller.rb +6 -0
  15. data/app/controllers/kern/signups_controller.rb +31 -0
  16. data/app/controllers/kern/signups_controller.rb.tt +31 -0
  17. data/app/helpers/kern/component_helper.rb +15 -0
  18. data/app/helpers/kern/turbo_stream_actions_helper.rb +10 -0
  19. data/app/mailers/kern/application_mailer.rb +6 -0
  20. data/app/mailers/kern/passwords_mailer.rb +9 -0
  21. data/app/models/actor.rb +4 -0
  22. data/app/models/application_form.rb +12 -0
  23. data/app/models/current.rb +8 -0
  24. data/app/models/member/acting.rb +28 -0
  25. data/app/models/member/setup.rb +37 -0
  26. data/app/models/member.rb +10 -0
  27. data/app/models/role.rb +5 -0
  28. data/app/models/session.rb +5 -0
  29. data/app/models/signup.rb +38 -0
  30. data/app/models/user/workspace_member.rb +12 -0
  31. data/app/models/user.rb +14 -0
  32. data/app/models/workspace/members.rb +10 -0
  33. data/app/models/workspace/setup.rb +21 -0
  34. data/app/models/workspace.rb +7 -0
  35. data/app/views/components/_container.html.erb +2 -0
  36. data/app/views/components/_flash.html.erb +7 -0
  37. data/app/views/components/_heading.html.erb +12 -0
  38. data/app/views/components/flash/_message.html.erb +4 -0
  39. data/app/views/kern/pages/welcome.html.erb +42 -0
  40. data/app/views/kern/passwords/edit.html.erb +12 -0
  41. data/app/views/kern/passwords/new.html.erb +10 -0
  42. data/app/views/kern/passwords_mailer/reset.html.erb +6 -0
  43. data/app/views/kern/passwords_mailer/reset.html.erb.tt +6 -0
  44. data/app/views/kern/passwords_mailer/reset.text.erb +4 -0
  45. data/app/views/kern/passwords_mailer/reset.text.erb.tt +4 -0
  46. data/app/views/kern/sessions/new.html.erb +16 -0
  47. data/app/views/kern/settings/_cards.html.erb +10 -0
  48. data/app/views/kern/settings/show.html.erb +5 -0
  49. data/app/views/kern/settings/users/show.html.erb +15 -0
  50. data/app/views/kern/signups/new.html.erb +16 -0
  51. data/app/views/layouts/kern/application/_navigation.html.erb +30 -0
  52. data/app/views/layouts/kern/application.html.erb +31 -0
  53. data/app/views/layouts/kern/application.html.erb.tt +31 -0
  54. data/app/views/layouts/kern/auth.html.erb +42 -0
  55. data/bin/dev +4 -0
  56. data/bin/rails +14 -0
  57. data/bin/release +35 -0
  58. data/config/routes.rb +13 -0
  59. data/db/migrate/20250101000001_create_users.rb +13 -0
  60. data/db/migrate/20250101000002_create_sessions.rb +11 -0
  61. data/db/migrate/20250101000003_create_workspaces.rb +12 -0
  62. data/db/migrate/20250101000004_create_members.rb +15 -0
  63. data/db/migrate/20250101000005_create_roles.rb +11 -0
  64. data/db/migrate/20250101000006_create_actors.rb +10 -0
  65. data/kern.gemspec +22 -0
  66. data/lib/generators/kern/feature/USAGE +17 -0
  67. data/lib/generators/kern/feature/feature_generator.rb +77 -0
  68. data/lib/generators/kern/helpers.rb +28 -0
  69. data/lib/generators/kern/install/USAGE +13 -0
  70. data/lib/generators/kern/install/install_generator.rb +48 -0
  71. data/lib/generators/kern/install/templates/configurations/README.md +33 -0
  72. data/lib/generators/kern/install/templates/configurations/urls.yml +9 -0
  73. data/lib/generators/kern/views/USAGE +22 -0
  74. data/lib/generators/kern/views/views_generator.rb +42 -0
  75. data/lib/kern/config.rb +25 -0
  76. data/lib/kern/engine.rb +17 -0
  77. data/lib/kern/form_builder/input.rb +100 -0
  78. data/lib/kern/form_builder/styles.rb +53 -0
  79. data/lib/kern/form_builder.rb +101 -0
  80. data/lib/kern/version.rb +3 -0
  81. data/lib/kern.rb +7 -0
  82. data/lib/sluggable.rb +66 -0
  83. data/lib/tasks/kern_tasks.rake +4 -0
  84. metadata +139 -0
@@ -0,0 +1,48 @@
1
+ require "generators/kern/helpers"
2
+
3
+ module Kern
4
+ class InstallGenerator < Rails::Generators::Base
5
+ include Helpers
6
+
7
+ source_root File.expand_path("templates", __dir__)
8
+
9
+ class_option :skip_migrations, type: :boolean, default: false
10
+
11
+ def copy_migrations
12
+ return if options[:skip_migrations]
13
+
14
+ rails_command "railties:install:migrations FROM=kern", inline: true
15
+ end
16
+
17
+ def inject_authentication
18
+ inject_into_class "app/controllers/application_controller.rb", "ApplicationController" do
19
+ " include Authentication\n"
20
+ end
21
+ end
22
+
23
+ def inject_kern_layout
24
+ inject_into_class "app/controllers/application_controller.rb", "ApplicationController" do
25
+ " layout \"kern/application\"\n"
26
+ end
27
+ end
28
+
29
+ def copy_urls_configuration
30
+ template "configurations/urls.yml", "config/configurations/urls.yml"
31
+ template "configurations/README.md", "config/configurations/README.md"
32
+ end
33
+
34
+ def enable_bcrypt
35
+ if File.read(File.expand_path("Gemfile", destination_root)).include?('gem "bcrypt"')
36
+ uncomment_lines "Gemfile", /gem "bcrypt"/
37
+
38
+ bundle_command("install --quiet")
39
+ else
40
+ bundle_command("add bcrypt", {}, quiet: true)
41
+ end
42
+ end
43
+
44
+ def mount_engine
45
+ route 'mount Kern::Engine => "/"'
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,33 @@
1
+ # Configuration
2
+
3
+ Load all YAML files from `config/configurations/` into `Config` constants.
4
+
5
+
6
+ ## Usage
7
+
8
+ Each YAML file in this directory becomes a `Config` constant. For example:
9
+ - `config/configurations/urls.yml` becomes `Config::Urls`
10
+ - `config/configurations/features.yml` becomes `Config::Features`
11
+
12
+ Access values using dot notation:
13
+ ```ruby
14
+ Config::Urls.app
15
+ Config::Urls.site
16
+ ```
17
+
18
+
19
+ ## Environment variables
20
+
21
+ You can override any configuration value using environment variables. For example, in `urls.yml`:
22
+ ```yaml
23
+ shared:
24
+ app: <%= ENV.fetch("URLS_APP", "http://localhost:3000") %>
25
+ site: <%= ENV.fetch("URLS_SITE", "https://example.com") %>
26
+ ```
27
+
28
+ The `URLS_` prefix is a recommended convention but not required. Use any naming convention that works for your application.
29
+
30
+
31
+ ## How it works
32
+
33
+ Under the hood, this uses `Rails.application.config_for` which automatically handles environment-specific configurations and ERB processing.
@@ -0,0 +1,9 @@
1
+ shared:
2
+ app: <%= ENV.fetch("URLS_APP", "http://localhost:3000") %>
3
+ site: <%= ENV.fetch("URLS_SITE", "https://saas.railsdesigner.com") %>
4
+ docs: <%= ENV.fetch("URLS_DOCS", "https://example.com/docs/") %>
5
+ terms: <%= ENV.fetch("URLS_TERMS", "https://example.com/legal/terms/") %>
6
+ privacy: <%= ENV.fetch("URLS_PRIVACY", "https://example.com/legal/privacy/") %>
7
+
8
+ production:
9
+ app: <%= ENV.fetch("URLS_APP", "https://app.example.com") %>
@@ -0,0 +1,22 @@
1
+ Description:
2
+ Generates Kern view templates in your application.
3
+
4
+ Example:
5
+ rails generate kern:views
6
+
7
+ This will generate all available Kern views.
8
+
9
+ rails generate kern:views sessions
10
+
11
+ This will generate only the sessions views.
12
+
13
+ rails generate kern:views sessions passwords
14
+
15
+ This will generate sessions and passwords views.
16
+
17
+ Available views:
18
+ passwords Password reset views
19
+ sessions Sign in views
20
+ settings User settings views
21
+ signups Sign up views
22
+ layouts Kern layout files
@@ -0,0 +1,42 @@
1
+ module Kern
2
+ class ViewsGenerator < Rails::Generators::Base
3
+ source_root File.expand_path("../../../../../app/views", __FILE__)
4
+
5
+ AVAILABLE_VIEWS = %w[passwords sessions settings signups layouts]
6
+
7
+ argument :views, type: :array, default: [], banner: "view view", desc: "Select specific view directories to generate (#{AVAILABLE_VIEWS.join(", ")}). Leave empty for all."
8
+
9
+ def copy_views
10
+ views_to_generate.map(&:inquiry).each do |view|
11
+ verify_view_exists!(view)
12
+
13
+ if view.layouts?
14
+ generate_layouts
15
+ else
16
+ directory "kern/#{view}", "app/views/#{view}", recursive: true
17
+ end
18
+ end
19
+ end
20
+
21
+ private
22
+
23
+ def views_to_generate
24
+ views.any? ? views : AVAILABLE_VIEWS
25
+ end
26
+
27
+ def verify_view_exists!(view)
28
+ return if AVAILABLE_VIEWS.include?(view)
29
+
30
+ say "View `#{view}` not found. Available views: #{AVAILABLE_VIEWS.join(", ")}", :red
31
+
32
+ exit(1)
33
+ end
34
+
35
+ def generate_layouts
36
+ template "layouts/kern/application.html.erb.tt", "app/views/layouts/application.html.erb"
37
+ copy_file "layouts/kern/application/_navigation.html.erb", "app/views/layouts/application/_navigation.html.erb"
38
+
39
+ copy_file "layouts/kern/auth.html.erb", "app/views/layouts/auth.html.erb"
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kern
4
+ module Config
5
+ module_function
6
+
7
+ def load!
8
+ configurations_path = Rails.root.join("config", "configurations")
9
+
10
+ return unless File.directory?(configurations_path)
11
+
12
+ Dir.glob(configurations_path.join("*.yml")).each do |path|
13
+ file_name = File.basename(path, ".yml")
14
+
15
+ ::Config.const_set(
16
+ file_name.camelize,
17
+ Rails.application.config_for("configurations/#{file_name}")
18
+ )
19
+ end
20
+ end
21
+ end
22
+ end
23
+
24
+ module Config
25
+ end
@@ -0,0 +1,17 @@
1
+ module Kern
2
+ class Engine < ::Rails::Engine
3
+ isolate_namespace Kern
4
+
5
+ initializer "kern.load_config", before: :load_config_initializers do
6
+ require "kern/config"
7
+
8
+ Kern::Config.load!
9
+ end
10
+
11
+ initializer "kern.helpers" do
12
+ ActiveSupport.on_load(:action_controller_base) do
13
+ helper Kern::Engine.helpers
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,100 @@
1
+ module Kern
2
+ class FormBuilder < ActionView::Helpers::FormBuilder
3
+ module Input
4
+ if Gem.loaded_specs.key?("rails_icons")
5
+ require "rails_icons"
6
+
7
+ include RailsIcons::Helpers::IconHelper
8
+ end
9
+
10
+ FIELD_TYPES = {
11
+ string: :text_field,
12
+ email: :email_field,
13
+ password: :password_field,
14
+ url: :url_field,
15
+ text: :text_area,
16
+ integer: :number_field,
17
+ float: :number_field,
18
+ decimal: :number_field,
19
+ datetime: :datetime_local_field,
20
+ date: :date_field
21
+ }.freeze
22
+
23
+ def input(attribute, options = {})
24
+ label_suffix = options.delete(:label_suffix)
25
+ hint = options.delete(:hint)
26
+
27
+ @template.content_tag(:div, data: {slot: "field"}, class: options[:field_css] || field_css) do
28
+ label_html = label(attribute, options)
29
+
30
+ @template.safe_join([
31
+ (if label_suffix
32
+ @template.content_tag(:div, class: "flex items-center justify-between") do
33
+ @template.safe_join([label_html, @template.content_tag(:span, label_suffix.html_safe, class: "text-xs font-medium text-gray-500")].compact)
34
+ end
35
+ end),
36
+
37
+ (label_html unless label_suffix),
38
+
39
+ input_field(attribute, options),
40
+
41
+ (@template.content_tag(:p, hint.html_safe, class: "flex items-center gap-x-1 mt-0.5 px-0.5 text-xs font-light text-gray-500") if hint)
42
+ ].compact)
43
+ end
44
+ end
45
+
46
+ def label(attribute, text = nil, options = {}, &block)
47
+ text, options = nil, text if text.is_a?(Hash)
48
+ label_options = options[:label] || {}
49
+ field_errors = @object&.errors&.where(attribute)
50
+
51
+ label_options[:class] = class_names("flex items-center gap-1 text-sm font-medium", {"text-gray-700": field_errors&.none?, "text-red-600": field_errors&.any?})
52
+ label_text = text || I18n.t("labels.#{attribute}", default: attribute.to_s.humanize)
53
+
54
+ super(attribute, label_options) do
55
+ safe_join([
56
+ begin
57
+ icon("warning-circle", class: "size-3.5 scale-100 transition ml-0 ease-in-out duration-300 starting:ml-3.5 starting:scale-0") if field_errors&.any?
58
+ rescue
59
+ nil
60
+ end,
61
+ label_text.html_safe? ? label_text : label_text.to_s
62
+ ].compact)
63
+ end
64
+ end
65
+
66
+ def toggle_wrapper(&block)
67
+ content_tag(:div, yield, data: {slot: "toggle-field"}, class: "flex items-start gap-x-2 [&>input]:mt-[0.15em]")
68
+ end
69
+
70
+ def toggle_label(method, text)
71
+ label(method, text.html_safe, class: toggle_label_css)
72
+ end
73
+
74
+ private
75
+
76
+ def input_field(attribute, options)
77
+ return select(attribute, options[:collection], {}, options.except(:as, :label, :collection)) if options[:collection]
78
+
79
+ send(FIELD_TYPES.fetch(options[:as] || type_for(attribute), :text_field), attribute, options.except(:as, :label, :collection))
80
+ end
81
+
82
+ def type_for(attribute)
83
+ return :email if attribute.to_s.end_with?("email")
84
+ return :password if attribute.to_s.include?("password")
85
+ return :url if attribute.match?(/url|website|site/)
86
+ return :string unless valid?(attribute)
87
+
88
+ @object.type_for_attribute(attribute.to_s).type
89
+ rescue NoMethodError
90
+ :string
91
+ end
92
+
93
+ def valid?(attribute)
94
+ @object.respond_to?(attribute) &&
95
+ @object.respond_to?(:has_attribute?) &&
96
+ @object.has_attribute?(attribute)
97
+ end
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,53 @@
1
+ module Kern
2
+ class FormBuilder < ActionView::Helpers::FormBuilder
3
+ module Styles
4
+ def field_css
5
+ "w-full [&[data-slot='field']+[data-slot='field']]:mt-4"
6
+ end
7
+
8
+ def input_css
9
+ <<~CSS
10
+ w-full px-2.5 py-1.5
11
+ text-sm font-normal text-gray-900
12
+ bg-white
13
+ border-0 ring ring-gray-200/80 rounded-sm
14
+ hover:ring-gray-300
15
+ disabled:opacity-50 disabled:hover:ring-gray-200/80
16
+ outline-none
17
+ focus:bg-white focus:ring focus:ring-brand-300
18
+ CSS
19
+ end
20
+
21
+ def file_field_css
22
+ <<~CSS
23
+ w-full py-1.5
24
+ text-sm font-normal text-gray-600
25
+ disabled:opacity-50
26
+ file:mr-2 file:py-1 file:px-4
27
+ file:text-xs file:font-medium
28
+ file:bg-gray-100 file:text-gray-700
29
+ file:rounded-full file:border-0
30
+ hover:file:bg-gray-200
31
+ focus:outline-hidden focus:ring-0
32
+ CSS
33
+ end
34
+
35
+ def toggle_input_css
36
+ <<~CSS
37
+ peer
38
+ accent-brand-500
39
+ border border-gray-100
40
+ rounded-md
41
+ focus:outline-hidden focus:ring focus:ring-offset-1 focus:ring-gray-300
42
+ disabled:opacity-25 disabled:cursor-not-allowed
43
+ CSS
44
+ end
45
+
46
+ def toggle_label_css
47
+ <<~CSS
48
+ block text-sm font-normal text-gray-800 peer-disabled:opacity-50 peer-disabled:cursor-not-allowed
49
+ CSS
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,101 @@
1
+ require "kern/form_builder/styles"
2
+ require "kern/form_builder/input"
3
+
4
+ module Kern
5
+ class FormBuilder < ActionView::Helpers::FormBuilder
6
+ include ActionView::Helpers::TagHelper
7
+
8
+ include Input
9
+ include Styles
10
+
11
+ %w[
12
+ text_field email_field password_field
13
+ search_field telephone_field url_field number_field
14
+ date_field time_field datetime_field datetime_local_field month_field week_field
15
+ ].each do |field_type|
16
+ define_method(field_type) do |method, options = {}|
17
+ field_classes(options, input_css)
18
+
19
+ super(method, options)
20
+ end
21
+ end
22
+ alias_method :phone_field, :telephone_field
23
+
24
+ def text_area(method, options = {})
25
+ field_classes(options, input_css)
26
+
27
+ super
28
+ end
29
+ alias_method :textarea, :text_area
30
+
31
+ def check_box(method, options = {}, checked_value = "1", unchecked_value = "0", &block)
32
+ field_classes(options, toggle_input_css)
33
+ label_text = block ? @template.capture(&block) : method.to_s.humanize
34
+
35
+ toggle_wrapper do
36
+ super(method, options, checked_value, unchecked_value) + label(method, label_text)
37
+ end
38
+ end
39
+ alias_method :checkbox, :check_box
40
+
41
+ def radio_button(method, tag_value, options = {}, &block)
42
+ field_classes(options, toggle_input_css)
43
+ label_text = block ? @template.capture(&block) : tag_value.to_s.humanize
44
+
45
+ toggle_wrapper do
46
+ super(method, tag_value, options) + toggle_label("#{method}_#{tag_value}", label_text)
47
+ end
48
+ end
49
+
50
+ def select(method, choices = nil, options = {}, html_options = {})
51
+ field_classes(html_options, input_css)
52
+
53
+ super
54
+ end
55
+
56
+ def file_field(method, options = {})
57
+ field_classes(options, file_field_css)
58
+
59
+ super
60
+ end
61
+
62
+ def collection_select(method, collection, value_method, text_method, options = {}, html_options = {})
63
+ field_classes(html_options, input_css)
64
+ super
65
+ end
66
+
67
+ def grouped_collection_select(method, collection, group_method, group_label_method, option_key_method, option_value_method, options = {}, html_options = {})
68
+ field_classes(html_options, input_css)
69
+
70
+ super
71
+ end
72
+
73
+ def collection_check_boxes(method, collection, value_method, text_method, options = {}, html_options = {})
74
+ field_classes(html_options, toggle_input_css, "rounded-sm")
75
+
76
+ toggle_wrapper do
77
+ @template.collection_check_boxes(object_name, method, collection, value_method, text_method, options, html_options) do |template|
78
+ template.check_box(class: html_options[:class]) + toggle_label("#{method}_#{template.value.to_s.underscore}", template.text)
79
+ end
80
+ end
81
+ end
82
+ alias_method :collection_checkboxes, :collection_check_boxes
83
+
84
+ def collection_radio_buttons(method, collection, value_method, text_method, options = {}, html_options = {})
85
+ field_classes(html_options, toggle_input_css)
86
+
87
+ toggle_wrapper do
88
+ @template.collection_radio_buttons(object_name, method, collection, value_method, text_method, options, html_options) do |template|
89
+ template.radio_button(class: html_options[:class]) + toggle_label("#{method}_#{template.value.to_s.underscore}", template.text)
90
+ end
91
+ end
92
+ end
93
+
94
+ private
95
+
96
+ def field_classes(options, base_css, *additional_classes)
97
+ options[:class] = options[:class].presence || class_names(base_css, *additional_classes, options[:additional_class])
98
+ options.delete(:additional_class)
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,3 @@
1
+ module Kern
2
+ VERSION = "0.5.0"
3
+ end
data/lib/kern.rb ADDED
@@ -0,0 +1,7 @@
1
+ require "kern/version"
2
+ require "kern/engine"
3
+ require "kern/form_builder"
4
+ require "sluggable"
5
+
6
+ module Kern
7
+ end
data/lib/sluggable.rb ADDED
@@ -0,0 +1,66 @@
1
+ # Usage
2
+ #
3
+ # Migration:
4
+ # add_column :<table_name>, :slug, null: false
5
+ # add_index :<table_name>, :slug, unique: true, # or:
6
+ # add_index :<table_name>, [:slug, :workspace_id], unique: true
7
+ #
8
+ # In app/models/<name>.rb
9
+ # include Sluggable
10
+ #
11
+ # In app/controller/model_name_plural_controller.rb
12
+ # `<model_name>.sluggble.find(params[:id])`
13
+ #
14
+ module Sluggable
15
+ extend ActiveSupport::Concern
16
+
17
+ class_methods do
18
+ def create_slug(from:)
19
+ @slug_source = from
20
+ end
21
+ end
22
+
23
+ included do
24
+ before_create :set_slug
25
+
26
+ scope :sluggable, -> { Sluggable::Finder.new(self) }
27
+ end
28
+
29
+ def to_key = [slug]
30
+
31
+ def to_param = slug
32
+
33
+ private
34
+
35
+ def set_slug
36
+ return if slug
37
+
38
+ slug = if slug_source && send(slug_source).present?
39
+ send(slug_source).parameterize
40
+ else
41
+ random_slug
42
+ end
43
+
44
+ self.slug = slug
45
+ end
46
+
47
+ def random_slug
48
+ loop do
49
+ slug = SecureRandom.hex(4)
50
+
51
+ return slug unless self.class.name.constantize.where(slug: slug).exists?
52
+ end
53
+ end
54
+
55
+ def slug_source = self.class.instance_variable_get(:@slug_source)
56
+ end
57
+
58
+ class Sluggable::Finder
59
+ def initialize(scope)
60
+ @scope = scope
61
+ end
62
+
63
+ def find(slug) = @scope.find_by(slug: slug)
64
+
65
+ def find!(slug) = @scope.find_by!(slug: slug)
66
+ end
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :kern do
3
+ # # Task goes here
4
+ # end
metadata ADDED
@@ -0,0 +1,139 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: kern
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.5.0
5
+ platform: ruby
6
+ authors:
7
+ - Rails Designer
8
+ bindir: bin
9
+ cert_chain: []
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: rails
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - ">="
17
+ - !ruby/object:Gem::Version
18
+ version: 8.0.0
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - ">="
24
+ - !ruby/object:Gem::Version
25
+ version: 8.0.0
26
+ description: 'A Rails engine that handles the SaaS essentials: authentication, team
27
+ invitations, subscription/billing, and common partials. Skip the boilerplate and
28
+ start shipping the actual product. Launch faster.'
29
+ email: devs@railsdeigner.com
30
+ executables: []
31
+ extensions: []
32
+ extra_rdoc_files: []
33
+ files:
34
+ - Gemfile
35
+ - Gemfile.lock
36
+ - README.md
37
+ - Rakefile
38
+ - app/assets/builds/tailwind.css
39
+ - app/controllers/concerns/authentication.rb
40
+ - app/controllers/concerns/authentication.rb.tt
41
+ - app/controllers/kern/application_controller.rb
42
+ - app/controllers/kern/pages_controller.rb
43
+ - app/controllers/kern/passwords_controller.rb
44
+ - app/controllers/kern/sessions_controller.rb
45
+ - app/controllers/kern/settings/users_controller.rb
46
+ - app/controllers/kern/settings_controller.rb
47
+ - app/controllers/kern/signups_controller.rb
48
+ - app/controllers/kern/signups_controller.rb.tt
49
+ - app/helpers/kern/component_helper.rb
50
+ - app/helpers/kern/turbo_stream_actions_helper.rb
51
+ - app/mailers/kern/application_mailer.rb
52
+ - app/mailers/kern/passwords_mailer.rb
53
+ - app/models/actor.rb
54
+ - app/models/application_form.rb
55
+ - app/models/current.rb
56
+ - app/models/member.rb
57
+ - app/models/member/acting.rb
58
+ - app/models/member/setup.rb
59
+ - app/models/role.rb
60
+ - app/models/session.rb
61
+ - app/models/signup.rb
62
+ - app/models/user.rb
63
+ - app/models/user/workspace_member.rb
64
+ - app/models/workspace.rb
65
+ - app/models/workspace/members.rb
66
+ - app/models/workspace/setup.rb
67
+ - app/views/components/_container.html.erb
68
+ - app/views/components/_flash.html.erb
69
+ - app/views/components/_heading.html.erb
70
+ - app/views/components/flash/_message.html.erb
71
+ - app/views/kern/pages/welcome.html.erb
72
+ - app/views/kern/passwords/edit.html.erb
73
+ - app/views/kern/passwords/new.html.erb
74
+ - app/views/kern/passwords_mailer/reset.html.erb
75
+ - app/views/kern/passwords_mailer/reset.html.erb.tt
76
+ - app/views/kern/passwords_mailer/reset.text.erb
77
+ - app/views/kern/passwords_mailer/reset.text.erb.tt
78
+ - app/views/kern/sessions/new.html.erb
79
+ - app/views/kern/settings/_cards.html.erb
80
+ - app/views/kern/settings/show.html.erb
81
+ - app/views/kern/settings/users/show.html.erb
82
+ - app/views/kern/signups/new.html.erb
83
+ - app/views/layouts/kern/application.html.erb
84
+ - app/views/layouts/kern/application.html.erb.tt
85
+ - app/views/layouts/kern/application/_navigation.html.erb
86
+ - app/views/layouts/kern/auth.html.erb
87
+ - bin/dev
88
+ - bin/rails
89
+ - bin/release
90
+ - config/routes.rb
91
+ - db/migrate/20250101000001_create_users.rb
92
+ - db/migrate/20250101000002_create_sessions.rb
93
+ - db/migrate/20250101000003_create_workspaces.rb
94
+ - db/migrate/20250101000004_create_members.rb
95
+ - db/migrate/20250101000005_create_roles.rb
96
+ - db/migrate/20250101000006_create_actors.rb
97
+ - kern.gemspec
98
+ - lib/generators/kern/feature/USAGE
99
+ - lib/generators/kern/feature/feature_generator.rb
100
+ - lib/generators/kern/helpers.rb
101
+ - lib/generators/kern/install/USAGE
102
+ - lib/generators/kern/install/install_generator.rb
103
+ - lib/generators/kern/install/templates/configurations/README.md
104
+ - lib/generators/kern/install/templates/configurations/urls.yml
105
+ - lib/generators/kern/views/USAGE
106
+ - lib/generators/kern/views/views_generator.rb
107
+ - lib/kern.rb
108
+ - lib/kern/config.rb
109
+ - lib/kern/engine.rb
110
+ - lib/kern/form_builder.rb
111
+ - lib/kern/form_builder/input.rb
112
+ - lib/kern/form_builder/styles.rb
113
+ - lib/kern/version.rb
114
+ - lib/sluggable.rb
115
+ - lib/tasks/kern_tasks.rake
116
+ homepage: https://saas.railsdesigner.com/
117
+ licenses:
118
+ - MIT
119
+ metadata:
120
+ homepage_uri: https://saas.railsdesigner.com/
121
+ source_code_uri: https://github.com/Rails-Designer/kern/
122
+ rdoc_options: []
123
+ require_paths:
124
+ - lib
125
+ required_ruby_version: !ruby/object:Gem::Requirement
126
+ requirements:
127
+ - - ">="
128
+ - !ruby/object:Gem::Version
129
+ version: 3.4.0
130
+ required_rubygems_version: !ruby/object:Gem::Requirement
131
+ requirements:
132
+ - - ">="
133
+ - !ruby/object:Gem::Version
134
+ version: '0'
135
+ requirements: []
136
+ rubygems_version: 4.0.1
137
+ specification_version: 4
138
+ summary: Rails engine with auth, billing, and common components for SaaS apps
139
+ test_files: []