saasr 0.1.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 (44) hide show
  1. checksums.yaml +7 -0
  2. checksums.yaml.gz.sig +0 -0
  3. data/README.md +10 -0
  4. data/Rakefile +8 -0
  5. data/app/assets/config/saasr_manifest.js +5 -0
  6. data/app/assets/stylesheets/saasr/application.css +10 -0
  7. data/app/controllers/concerns/saasr/base_api_controller_mixin.rb +3 -0
  8. data/app/controllers/concerns/saasr/base_controller_mixin.rb +7 -0
  9. data/app/controllers/concerns/saasr/base_metal_controller_mixin.rb +3 -0
  10. data/app/controllers/saasr/base_api_controller.rb +5 -0
  11. data/app/controllers/saasr/base_controller.rb +5 -0
  12. data/app/controllers/saasr/base_metal_controller.rb +5 -0
  13. data/app/controllers/saasr/test_controller.rb +2 -0
  14. data/app/helpers/saasr/application_helper.rb +2 -0
  15. data/app/javascript/controllers/saasr/test_controller.js +7 -0
  16. data/app/javascript/helpers/saasr/index.js +0 -0
  17. data/app/javascript/lib/saasr/index.js +4 -0
  18. data/app/javascript/lib/saasr/utils.js +0 -0
  19. data/app/jobs/concerns/saasr/base_job_mixin.rb +13 -0
  20. data/app/jobs/saasr/base_job.rb +5 -0
  21. data/app/mailers/concerns/saasr/base_mailer_mixin.rb +8 -0
  22. data/app/mailers/saasr/base_mailer.rb +5 -0
  23. data/app/models/concerns/saasr/base_record_mixin.rb +5 -0
  24. data/app/models/concerns/saasr/current_attributes.rb +2 -0
  25. data/app/models/saasr/base_record.rb +7 -0
  26. data/app/views/layouts/saasr/application.html.erb +29 -0
  27. data/app/views/layouts/saasr/mailer.html.erb +13 -0
  28. data/app/views/layouts/saasr/mailer.text.erb +1 -0
  29. data/app/views/saasr/test/index.html.erb +0 -0
  30. data/config/better-html.yml +1 -0
  31. data/config/i18n-tasks.yml +179 -0
  32. data/config/importmap.rb +7 -0
  33. data/config/locales/saasr.en.yml +6 -0
  34. data/config/routes.rb +3 -0
  35. data/lib/saasr/configuration/attributes.rb +15 -0
  36. data/lib/saasr/configuration.rb +16 -0
  37. data/lib/saasr/engine.rb +59 -0
  38. data/lib/saasr/error.rb +2 -0
  39. data/lib/saasr/log_subscriber.rb +2 -0
  40. data/lib/saasr/version.rb +3 -0
  41. data/lib/saasr.rb +58 -0
  42. data.tar.gz.sig +0 -0
  43. metadata +366 -0
  44. metadata.gz.sig +0 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 7081026e17b82112a41904ee131017661711c003abf53b2b9a578b002edc6d82
4
+ data.tar.gz: 5066ab805f70dd88c1d7ea444befa41b77b2353bbf85e83ea30898c74b61f8a9
5
+ SHA512:
6
+ metadata.gz: 6b08389ce6c5552dd8a3de9d58d5706a305467b4c292beb4a8371f09bae0945578d323696bcc7d04fb23ce8d3df5fffcb6157487874c6c93733cdde50b582cfb
7
+ data.tar.gz: 01fc45448e7c3432746d71d3fc6b55c8c45b2783f57ce0e3b455f609379c1988aa89934e1f5633aa951d05a4a3a3e86a91b4854917db060e80aa9e400ad23058
checksums.yaml.gz.sig ADDED
Binary file
data/README.md ADDED
@@ -0,0 +1,10 @@
1
+ # Saasr
2
+
3
+ > [!NOTE]
4
+ > Saasr is currently under active development. Star the repository to follow its progress!
5
+
6
+ A batteries-included SaaS framework for Ruby on Rails 8, embracing convention over configuration and the Rails way. Build enterprise-ready SaaS applications without sacrificing the joy of Rails development.
7
+
8
+ ## License
9
+
10
+ Saasr will be released under an open source license prior to the first stable release.
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ require 'bundler/setup'
2
+
3
+ APP_RAKEFILE = File.expand_path('test/dummy/Rakefile', __dir__)
4
+ load 'rails/tasks/engine.rake'
5
+
6
+ load 'rails/tasks/statistics.rake'
7
+
8
+ require 'bundler/gem_tasks'
@@ -0,0 +1,5 @@
1
+ //= link_directory ../stylesheets/saasr .css
2
+ //= link_directory ../../../vendor/javascript .js
3
+ //= link_directory ../../javascript/controllers .js
4
+ //= link_directory ../../javascript/helpers .js
5
+ //= link_directory ../../javascript/lib .js
@@ -0,0 +1,10 @@
1
+ /*
2
+ * This is a manifest file that'll be compiled into application.css.
3
+ *
4
+ * With Propshaft, assets are served efficiently without preprocessing steps. You can still include
5
+ * application-wide styles in this file, but keep in mind that CSS precedence will follow the standard
6
+ * cascading order, meaning styles declared later in the document or manifest will override earlier ones,
7
+ * depending on specificity.
8
+ *
9
+ * Consider organizing styles into separate files for maintainability.
10
+ */
@@ -0,0 +1,3 @@
1
+ module Saasr::BaseAPIControllerMixin
2
+ extend ActiveSupport::Concern
3
+ end
@@ -0,0 +1,7 @@
1
+ module Saasr::BaseControllerMixin
2
+ extend ActiveSupport::Concern
3
+
4
+ included do
5
+ layout 'saasr/application'
6
+ end
7
+ end
@@ -0,0 +1,3 @@
1
+ module Saasr::BaseMetalControllerMixin
2
+ extend ActiveSupport::Concern
3
+ end
@@ -0,0 +1,5 @@
1
+ class Saasr::BaseAPIController < Saasr.config.base_api_controller_class.constantize
2
+ include Saasr::BaseAPIControllerMixin
3
+
4
+ ActiveSupport.run_load_hooks(:saasr_api_controller, self)
5
+ end
@@ -0,0 +1,5 @@
1
+ class Saasr::BaseController < Saasr.config.base_controller_class.constantize
2
+ include Saasr::BaseControllerMixin
3
+
4
+ ActiveSupport.run_load_hooks(:saasr_controller, self)
5
+ end
@@ -0,0 +1,5 @@
1
+ class Saasr::BaseMetalController < Saasr.config.base_metal_controller_class.constantize
2
+ include Saasr::BaseMetalControllerMixin
3
+
4
+ ActiveSupport.run_load_hooks(:saasr_metal_controller, self)
5
+ end
@@ -0,0 +1,2 @@
1
+ class Saasr::TestController < Saasr::BaseController
2
+ end
@@ -0,0 +1,2 @@
1
+ module Saasr::ApplicationHelper
2
+ end
@@ -0,0 +1,7 @@
1
+ import { Controller } from "@hotwired/stimulus";
2
+
3
+ export default class extends Controller {
4
+ connect() {
5
+ console.log("Hello, Saasr!");
6
+ }
7
+ }
File without changes
@@ -0,0 +1,4 @@
1
+ import LocalTime from "local-time";
2
+ LocalTime.start();
3
+
4
+ import "saasr/utils";
File without changes
@@ -0,0 +1,13 @@
1
+ module Saasr::BaseJobMixin
2
+ extend ActiveSupport::Concern
3
+
4
+ include ActiveSupport::Configurable
5
+
6
+ included do
7
+ # Automatically retry jobs that encountered a deadlock
8
+ retry_on ActiveRecord::Deadlocked
9
+
10
+ # Most jobs are safe to ignore if the underlying records are no longer available
11
+ discard_on ActiveJob::DeserializationError
12
+ end
13
+ end
@@ -0,0 +1,5 @@
1
+ class Saasr::BaseJob < Saasr.config.base_job_class.constantize
2
+ include Saasr::BaseJobMixin
3
+
4
+ ActiveSupport.run_load_hooks(:saasr_job, self)
5
+ end
@@ -0,0 +1,8 @@
1
+ module Saasr::BaseMailerMixin
2
+ extend ActiveSupport::Concern
3
+
4
+ included do
5
+ prepend_view_path Saasr::Engine.root.join('app/views/mailers')
6
+ layout 'saasr/mailer'
7
+ end
8
+ end
@@ -0,0 +1,5 @@
1
+ class Saasr::BaseMailer < Saasr.config.base_mailer_class.constantize
2
+ include Saasr::BaseMailerMixin
3
+
4
+ ActiveSupport.run_load_hooks(:saasr_mailer, self)
5
+ end
@@ -0,0 +1,5 @@
1
+ module Saasr::BaseRecordMixin
2
+ extend ActiveSupport::Concern
3
+
4
+ include ActiveSupport::Configurable
5
+ end
@@ -0,0 +1,2 @@
1
+ module Saasr::CurrentAttributes
2
+ end
@@ -0,0 +1,7 @@
1
+ class Saasr::BaseRecord < Saasr.config.base_record_class.constantize
2
+ include Saasr::BaseRecordMixin
3
+
4
+ self.abstract_class = true
5
+
6
+ ActiveSupport.run_load_hooks(:saasr_record, self)
7
+ end
@@ -0,0 +1,29 @@
1
+ <!DOCTYPE html>
2
+ <html lang="" class="<%= content_for(:html_class) %>">
3
+ <head>
4
+ <title><%= content_for(:title) || 'Saasr' %></title>
5
+ <meta name="viewport" content="width=device-width,initial-scale=1">
6
+ <meta name="apple-mobile-web-app-capable" content="yes">
7
+ <meta name="mobile-web-app-capable" content="yes">
8
+ <%= csrf_meta_tags %>
9
+ <%= csp_meta_tag %>
10
+
11
+ <%= yield :head %>
12
+
13
+ <%#= tag.link rel: "manifest", href: pwa_manifest_path(format: :json) %>
14
+
15
+ <link rel="icon" href="/icon.png" type="image/png">
16
+ <link rel="icon" href="/icon.svg" type="image/svg+xml">
17
+ <link rel="apple-touch-icon" href="/icon.png">
18
+
19
+ <%= stylesheet_link_tag 'tailwind', 'inter-font', 'data-turbo-track': 'reload' %>
20
+ <%= stylesheet_link_tag :app, 'data-turbo-track': 'reload' %>
21
+ <%= javascript_importmap_tags 'application-saasr' %>
22
+ </head>
23
+ <body class="<%= content_for(:body_class) %>">
24
+ <a href="#main" class="sr-only"><%= t('.skip_link') %></a>
25
+ <main id="main" class="container mx-auto mt-28 px-5 flex">
26
+ <%= yield %>
27
+ </main>
28
+ </body>
29
+ </html>
@@ -0,0 +1,13 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
5
+ <style>
6
+ /* Email styles need to be inline */
7
+ </style>
8
+ </head>
9
+
10
+ <body>
11
+ <%= yield %>
12
+ </body>
13
+ </html>
@@ -0,0 +1 @@
1
+ <%= yield %>
File without changes
@@ -0,0 +1 @@
1
+ allow_single_quoted_attributes: false
@@ -0,0 +1,179 @@
1
+ # i18n-tasks finds and manages missing and unused translations: https://github.com/glebm/i18n-tasks
2
+
3
+ # The "main" locale.
4
+ base_locale: en
5
+ ## All available locales are inferred from the data by default. Alternatively, specify them explicitly:
6
+ # locales: [es, fr]
7
+ ## Reporting locale, default: en. Available: en, ru.
8
+ # internal_locale: en
9
+
10
+ # Read and write translations.
11
+ data:
12
+ ## Translations are read from the file system. Supported format: YAML, JSON.
13
+ ## Provide a custom adapter:
14
+ # adapter: I18n::Tasks::Data::FileSystem
15
+
16
+ # Locale files or `Dir.glob` patterns where translations are read from:
17
+ read:
18
+ ## Default:
19
+ # - config/locales/%{locale}.yml
20
+ ## More files:
21
+ - config/locales/*.%{locale}.yml
22
+
23
+ # Locale files to write new keys to, based on a list of key pattern => file rules. Matched from top to bottom:
24
+ # `i18n-tasks normalize -p` will force move the keys according to these rules
25
+ write:
26
+ ## For example, write devise and simple form keys to their respective files:
27
+ # - ['{devise, simple_form}.*', 'config/locales/\1.%{locale}.yml']
28
+ ## Catch-all default:
29
+ # - config/locales/%{locale}.yml
30
+ - config/locales/saasr.%{locale}.yml
31
+
32
+ # External locale data (e.g. gems).
33
+ # This data is not considered unused and is never written to.
34
+ external:
35
+ ## Example (replace %#= with %=):
36
+ # - "<%#= %x[bundle info vagrant --path].chomp %>/templates/locales/%{locale}.yml"
37
+
38
+ ## Specify the router (see Readme for details). Valid values: conservative_router, pattern_router, or a custom class.
39
+ # router: conservative_router
40
+
41
+ yaml:
42
+ write:
43
+ # do not wrap lines at 80 characters
44
+ line_width: -1
45
+
46
+ ## Pretty-print JSON:
47
+ # json:
48
+ # write:
49
+ # indent: ' '
50
+ # space: ' '
51
+ # object_nl: "\n"
52
+ # array_nl: "\n"
53
+
54
+ # Find translate calls
55
+ search:
56
+ ## Paths or `Find.find` patterns to search in:
57
+ # paths:
58
+ # - app/
59
+
60
+ ## Root directories for relative keys resolution.
61
+ # relative_roots:
62
+ # - app/controllers
63
+ # - app/helpers
64
+ # - app/mailers
65
+ # - app/presenters
66
+ # - app/views
67
+
68
+ ## Directories where method names which should not be part of a relative key resolution.
69
+ # By default, if a relative translation is used inside a method, the name of the method will be considered part of the resolved key.
70
+ # Directories listed here will not consider the name of the method part of the resolved key
71
+ #
72
+ # relative_exclude_method_name_paths:
73
+ # -
74
+
75
+ ## Files or `File.fnmatch` patterns to exclude from search. Some files are always excluded regardless of this setting:
76
+ ## *.jpg *.jpeg *.png *.gif *.svg *.ico *.eot *.otf *.ttf *.woff *.woff2 *.pdf *.css *.sass *.scss *.less
77
+ ## *.yml *.json *.zip *.tar.gz *.swf *.flv *.mp3 *.wav *.flac *.webm *.mp4 *.ogg *.opus *.webp *.map *.xlsx
78
+ exclude:
79
+ - app/assets/images
80
+ - app/assets/fonts
81
+ - app/assets/videos
82
+ - app/assets/builds
83
+
84
+ ## Alternatively, the only files or `File.fnmatch patterns` to search in `paths`:
85
+ ## If specified, this settings takes priority over `exclude`, but `exclude` still applies.
86
+ # only: ["*.rb", "*.html.slim"]
87
+
88
+ ## If `strict` is `false`, guess usages such as t("categories.#{category}.title"). The default is `true`.
89
+ # strict: true
90
+
91
+ ## Allows adding ast_matchers for finding translations using the AST-scanners
92
+ ## The available matchers are:
93
+ ## - RailsModelMatcher
94
+ ## Matches ActiveRecord translations like
95
+ ## User.human_attribute_name(:email) and User.model_name.human
96
+ ## - DefaultI18nSubjectMatcher
97
+ ## Matches ActionMailer's default_i18n_subject method
98
+ ##
99
+ ## To implement your own, please see `I18n::Tasks::Scanners::AstMatchers::BaseMatcher`.
100
+ # ast_matchers:
101
+ # - 'I18n::Tasks::Scanners::AstMatchers::RailsModelMatcher'
102
+ # - 'I18n::Tasks::Scanners::AstMatchers::DefaultI18nSubjectMatcher'
103
+
104
+ ## Multiple scanners can be used. Their results are merged.
105
+ ## The options specified above are passed down to each scanner. Per-scanner options can be specified as well.
106
+ ## See this example of a custom scanner: https://github.com/glebm/i18n-tasks/wiki/A-custom-scanner-example
107
+ ## Translation Services
108
+ # translation:
109
+ # # Google Translate
110
+ # # Get an API key and set billing info at https://code.google.com/apis/console to use Google Translate
111
+ # google_translate_api_key: "AbC-dEf5"
112
+ # # DeepL Pro Translate
113
+ # # Get an API key and subscription at https://www.deepl.com/pro to use DeepL Pro
114
+ # deepl_api_key: "48E92789-57A3-466A-9959-1A1A1A1A1A1A"
115
+ # # deepl_host: "https://api.deepl.com"
116
+ # # deepl_version: "v2"
117
+ # # deepl_glossary_ids:
118
+ # # - f28106eb-0e06-489e-82c6-8215d6f95089
119
+ # # - 2c6415be-1852-4f54-9e1b-d800463496b4
120
+ # # add additional options to the DeepL.translate call: https://www.deepl.com/docs-api/translate-text/translate-text/
121
+ # deepl_options:
122
+ # formality: prefer_less
123
+ # # OpenAI
124
+ # openai_api_key: "sk-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
125
+ # # openai_model: "gpt-3.5-turbo" # see https://platform.openai.com/docs/models
126
+ # # may contain `%{from}` and `%{to}`, which will be replaced by source and target locale codes, respectively (using `Kernel.format`)
127
+ # # openai_admin_prompt: >-
128
+ # # You are a professional translator that translates content from the %{from} locale
129
+ # # to the %{to} locale in an i18n locale array.
130
+ # #
131
+ # # The array has a structured format and contains multiple strings. Your task is to translate
132
+ # # each of these strings and create a new array with the translated strings.
133
+ # #
134
+ # # HTML markups (enclosed in < and > characters) must not be changed under any circumstance.
135
+ # # Variables (starting with %%{ and ending with }) must not be changed under any circumstance.
136
+ # #
137
+ # # Keep in mind the context of all the strings for a more accurate translation.
138
+
139
+ ## Do not consider these keys missing:
140
+ # ignore_missing:
141
+ # - 'errors.messages.{accepted,blank,invalid,too_short,too_long}'
142
+ # - '{devise,simple_form}.*'
143
+
144
+ ## Consider these keys used:
145
+ ignore_unused:
146
+ - "activerecord.attributes.*"
147
+ - "activerecord.errors.*"
148
+ # - '{devise,kaminari,will_paginate}.*'
149
+ # - 'simple_form.{yes,no}'
150
+ # - 'simple_form.{placeholders,hints,labels}.*'
151
+ # - 'simple_form.{error_notification,required}.:'
152
+
153
+ ## Exclude these keys from the `i18n-tasks eq-base' report:
154
+ # ignore_eq_base:
155
+ # all:
156
+ # - common.ok
157
+ # fr,es:
158
+ # - common.brand
159
+
160
+ ## Exclude these keys from the `i18n-tasks check-consistent-interpolations` report:
161
+ # ignore_inconsistent_interpolations:
162
+ # - 'activerecord.attributes.*'
163
+
164
+ ## Ignore these keys completely:
165
+ # ignore:
166
+ # - kaminari.*
167
+
168
+ ## Sometimes, it isn't possible for i18n-tasks to match the key correctly,
169
+ ## e.g. in case of a relative key defined in a helper method.
170
+ ## In these cases you can use the built-in PatternMapper to map patterns to keys, e.g.:
171
+ #
172
+ # <%# I18n::Tasks.add_scanner 'I18n::Tasks::Scanners::PatternMapper',
173
+ # only: %w(*.html.haml *.html.slim),
174
+ # patterns: [['= title\b', '.page_title']] %>
175
+ #
176
+ # The PatternMapper can also match key literals via a special %{key} interpolation, e.g.:
177
+ #
178
+ # <%# I18n::Tasks.add_scanner 'I18n::Tasks::Scanners::PatternMapper',
179
+ # patterns: [['\bSpree\.t[( ]\s*%{key}', 'spree.%{key}']] %>
@@ -0,0 +1,7 @@
1
+ pin '@hotwired/turbo-rails', to: 'turbo.min.js', preload: true
2
+ pin '@hotwired/stimulus', to: 'stimulus.min.js', preload: true
3
+ pin '@hotwired/stimulus-loading', to: 'stimulus-loading.js', preload: true
4
+ pin 'local-time' # @3.0.2
5
+ pin_all_from Saasr::Engine.root.join('app/javascript/lib/saasr'), under: 'saasr', to: 'lib/saasr'
6
+ pin_all_from Saasr::Engine.root.join('app/javascript/controllers'), under: 'controllers'
7
+ pin_all_from Saasr::Engine.root.join('app/javascript/helpers'), under: 'helpers'
@@ -0,0 +1,6 @@
1
+ ---
2
+ en:
3
+ layouts:
4
+ saasr:
5
+ application:
6
+ skip_link: Skip to main content
data/config/routes.rb ADDED
@@ -0,0 +1,3 @@
1
+ Rails.application.routes.draw do
2
+ get '-/saasr/test', to: 'saasr/test#index' if Rails.env.development?
3
+ end if Saasr.config.draw_routes
@@ -0,0 +1,15 @@
1
+ module Saasr::Configuration::Attributes
2
+ extend ActiveSupport::Concern
3
+
4
+ include ActiveModel::Attributes
5
+ include ActiveModel::Dirty
6
+
7
+ module ClassMethods
8
+ def required_attribute(name, type = nil, **)
9
+ attribute(name, type, **)
10
+
11
+ validates! name, presence: true
12
+ end
13
+ alias required required_attribute
14
+ end
15
+ end
@@ -0,0 +1,16 @@
1
+ class Saasr::Configuration
2
+ include ActiveModel::Model
3
+ include ActiveModel::Serialization
4
+ include Saasr::Configuration::Attributes
5
+
6
+ required :base_controller_class, :string, default: '::ApplicationController'
7
+ required :base_api_controller_class, :string, default: '::ActionController::API'
8
+ required :base_metal_controller_class, :string, default: '::ActionController::Metal'
9
+ required :base_mailer_class, :string, default: '::ApplicationMailer'
10
+ required :base_job_class, :string, default: '::ApplicationJob'
11
+ required :base_record_class, presence: true, default: '::ApplicationRecord'
12
+
13
+ required :draw_routes, :boolean, default: true
14
+
15
+ ActiveSupport.run_load_hooks(:saasr_configuration, self)
16
+ end
@@ -0,0 +1,59 @@
1
+ require 'rails'
2
+
3
+ require 'better_html'
4
+ require 'importmap-rails'
5
+ require 'turbo-rails'
6
+ require 'stimulus-rails'
7
+ require 'tailwindcss-rails'
8
+
9
+ module Saasr
10
+ class Engine < Rails::Engine
11
+ config.saasr = ActiveSupport::OrderedOptions.new
12
+
13
+ config.after_initialize do |app|
14
+ # :nocov:
15
+ unless app.config.eager_load
16
+ Saasr.config.base_controller_class.constantize
17
+ Saasr.config.base_api_controller_class.constantize
18
+ Saasr.config.base_metal_controller_class.constantize
19
+ Saasr.config.base_job_class.constantize
20
+ Saasr.config.base_mailer_class.constantize
21
+ Saasr.config.base_record_class.constantize
22
+ end
23
+ # :nocov:
24
+ end
25
+
26
+ initializer 'saasr.config' do
27
+ config.saasr.each { |key, value| Saasr.config.send(:"#{key}=", value) }
28
+ Saasr.config.validate!
29
+ end
30
+
31
+ initializer 'saasr.inflections' do
32
+ ActiveSupport::Inflector.inflections(:en) do |inflect|
33
+ inflect.acronym 'API'
34
+ end
35
+ end
36
+
37
+ initializer 'saasr.logger' do
38
+ # :nocov:
39
+ ActiveSupport.on_load(:saasr) do
40
+ self.logger = ::Rails.logger if logger == Saasr::DEFAULT_LOGGER
41
+ end
42
+ # :nocov:
43
+
44
+ Saasr::LogSubscriber.attach_to :saasr
45
+ end
46
+
47
+ initializer 'saasr.assets' do |app|
48
+ app.config.assets.paths << root.join('app/javascript')
49
+ app.config.assets.paths << root.join('vendor/javascript')
50
+ app.config.assets.precompile += %w[saasr_manifest]
51
+ end
52
+
53
+ initializer 'saasr.importmap', before: 'importmap' do |app|
54
+ app.config.importmap.cache_sweepers << root.join('app/javascript')
55
+ app.config.importmap.cache_sweepers << root.join('vendor/javascript')
56
+ app.config.importmap.paths << root.join('config/importmap.rb')
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,2 @@
1
+ class Saasr::Error < StandardError
2
+ end
@@ -0,0 +1,2 @@
1
+ class Saasr::LogSubscriber < ActiveSupport::LogSubscriber
2
+ end
@@ -0,0 +1,3 @@
1
+ module Saasr
2
+ VERSION = '0.1.0'.freeze
3
+ end
data/lib/saasr.rb ADDED
@@ -0,0 +1,58 @@
1
+ if ENV['RAILS_ENV'] == 'test'
2
+ require 'simplecov'
3
+
4
+ SimpleCov.start do
5
+ load_profile 'test_frameworks'
6
+
7
+ add_filter %r{^/config/}
8
+ add_filter %r{^/db/}
9
+
10
+ add_group 'Channels', 'app/channels'
11
+ add_group 'Controllers', 'app/controllers'
12
+ add_group 'Generators', 'lib/generators'
13
+ add_group 'Helpers', 'app/helpers'
14
+ add_group 'Jobs', 'app/jobs'
15
+ add_group 'Libraries', %w[app/lib lib]
16
+ add_group 'Mailers', 'app/mailers'
17
+ add_group 'Models', 'app/models'
18
+ add_group 'Tasks', 'lib/tasks'
19
+
20
+ enable_coverage :branch
21
+ primary_coverage :branch
22
+ end
23
+ end
24
+
25
+ require 'saasr/version'
26
+ require 'saasr/engine'
27
+
28
+ require 'zeitwerk'
29
+
30
+ Zeitwerk::Loader.for_gem.tap do |loader|
31
+ loader.inflector.inflect(
32
+ 'api' => 'API'
33
+ )
34
+
35
+ loader.ignore(
36
+ "#{__dir__}/generators",
37
+ "#{__dir__}/saasr/version.rb",
38
+ "#{__dir__}/tasks"
39
+ )
40
+ end.setup
41
+
42
+ module Saasr
43
+ DEFAULT_LOGGER = ActiveSupport::Logger.new(nil)
44
+
45
+ mattr_accessor :config, default: Configuration.new
46
+
47
+ mattr_accessor :logger, default: DEFAULT_LOGGER
48
+
49
+ def self.configure
50
+ yield config
51
+ end
52
+
53
+ def instrument(channel, **, &)
54
+ ActiveSupport::Notifications.instrument("#{channel}.saasr", **, &)
55
+ end
56
+
57
+ ActiveSupport.run_load_hooks(:saasr, self)
58
+ end
data.tar.gz.sig ADDED
Binary file
metadata ADDED
@@ -0,0 +1,366 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: saasr
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Tony Burns
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain:
11
+ - |
12
+ -----BEGIN CERTIFICATE-----
13
+ MIIEcDCCAtigAwIBAgIBATANBgkqhkiG9w0BAQsFADA/MQ0wCwYDVQQDDAR0b255
14
+ MRkwFwYKCZImiZPyLGQBGRYJdG9ueWJ1cm5zMRMwEQYKCZImiZPyLGQBGRYDbmV0
15
+ MB4XDTI0MDcxNDAxMDg0OVoXDTI1MDcxNDAxMDg0OVowPzENMAsGA1UEAwwEdG9u
16
+ eTEZMBcGCgmSJomT8ixkARkWCXRvbnlidXJuczETMBEGCgmSJomT8ixkARkWA25l
17
+ dDCCAaIwDQYJKoZIhvcNAQEBBQADggGPADCCAYoCggGBAKggfvyjaYMtMwan119S
18
+ oOKyXi6ES6fn92c4jsiNowr15QR5VUlqI53RBowrLZzVTAYs7duxLT1jd6H58vpC
19
+ bJEkTtFWmJj8tL4+XozzESDnytcdLiT51fb7fmq9LUUwF+iJbotP7EOuzdp58p4O
20
+ qAIhL9HTPSgV02xqgoLV/9qBfMGMp2OIg8LxeY4j6tsu/NWxf19vBYI++ETr8vce
21
+ NjafoEa3zuVhB7aasnURf5nuhl+Rlp/CZ3DunXLsfCRil1Lu5FD53YDmozEVlWb0
22
+ wBbcbg/v73x2TV5jyIzxW6HOde2LhC/eI1sNitCflLZ0Q7kWAKMbx82RMTuNHNVa
23
+ JJRB2D6A64V+IJ9GAsYgyrkZ63sTlABylI2IXasif5Y4gsHLzr8m8f+6bKoKmKxo
24
+ qPs+sLlD3PbeWeNuxYnd2VP55NqTHSpFyytYjuFP0PErdChini435Zrxedq4UuRx
25
+ 0Bhq4cVlspDqbVhJoFqL27ZVyJWVpwMPXbN8sWZCJgWaAQIDAQABo3cwdTAJBgNV
26
+ HRMEAjAAMAsGA1UdDwQEAwIEsDAdBgNVHQ4EFgQUJWq36v7uqFV7BcGsCCpzg+r7
27
+ OVQwHQYDVR0RBBYwFIESdG9ueUB0b255YnVybnMubmV0MB0GA1UdEgQWMBSBEnRv
28
+ bnlAdG9ueWJ1cm5zLm5ldDANBgkqhkiG9w0BAQsFAAOCAYEAhCrMM1e7kL5MtTRy
29
+ 9kOU48uTLtLuyvUxFkdN/b/iMh+MKYRButfY35SxqRzs76Lta58V6cgRpRNb/WZv
30
+ Y5613dW/XF3oPOjaSyjYTGT/RyVobT5BydDIZ5uN/l38cd4fM++PEyIyP0D/CyNY
31
+ EVs+WvSSCAWzjO5PRgQDBU0+VrQaA2sp/qohi9kjxEFllkqi9eC2Py1rSndlXv0s
32
+ UW1jECxYZ56EHfypdqGjb9FRheRcEB6FtUzgjN8+IFsq1KyKDTproT3qVYFPT7IU
33
+ VSYwGC6ZO8B+/FxtebityYd+WuwSIcGoZVdbnl/GUPzT/O+5VdEmOFfn9lG3RbL2
34
+ xZax49uLQDvhfCrzISFszjYMMzfBhgpR+j9kq0HvZhrhZJRvlu8r7KP9EDvWrkXG
35
+ Gso2iuR/JK+nlYYHnXZSMQgPTNEv7urC3s3YBLkEeZAyKSzTub/yFiZ0f1rZECNq
36
+ RdwSWsf01XE0bKBtz4/dixrX45mIFrPmGp1gobRN/q4Tq3lU
37
+ -----END CERTIFICATE-----
38
+ date: 2024-10-26 00:00:00.000000000 Z
39
+ dependencies:
40
+ - !ruby/object:Gem::Dependency
41
+ name: actioncable
42
+ requirement: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: 8.0.0.rc1
47
+ type: :runtime
48
+ prerelease: false
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: 8.0.0.rc1
54
+ - !ruby/object:Gem::Dependency
55
+ name: actionmailer
56
+ requirement: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: 8.0.0.rc1
61
+ type: :runtime
62
+ prerelease: false
63
+ version_requirements: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: 8.0.0.rc1
68
+ - !ruby/object:Gem::Dependency
69
+ name: actionpack
70
+ requirement: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: 8.0.0.rc1
75
+ type: :runtime
76
+ prerelease: false
77
+ version_requirements: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: 8.0.0.rc1
82
+ - !ruby/object:Gem::Dependency
83
+ name: activejob
84
+ requirement: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: 8.0.0.rc1
89
+ type: :runtime
90
+ prerelease: false
91
+ version_requirements: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - ">="
94
+ - !ruby/object:Gem::Version
95
+ version: 8.0.0.rc1
96
+ - !ruby/object:Gem::Dependency
97
+ name: activemodel
98
+ requirement: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ version: 8.0.0.rc1
103
+ type: :runtime
104
+ prerelease: false
105
+ version_requirements: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ version: 8.0.0.rc1
110
+ - !ruby/object:Gem::Dependency
111
+ name: activerecord
112
+ requirement: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - ">="
115
+ - !ruby/object:Gem::Version
116
+ version: 8.0.0.rc1
117
+ type: :runtime
118
+ prerelease: false
119
+ version_requirements: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - ">="
122
+ - !ruby/object:Gem::Version
123
+ version: 8.0.0.rc1
124
+ - !ruby/object:Gem::Dependency
125
+ name: activestorage
126
+ requirement: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - ">="
129
+ - !ruby/object:Gem::Version
130
+ version: 8.0.0.rc1
131
+ type: :runtime
132
+ prerelease: false
133
+ version_requirements: !ruby/object:Gem::Requirement
134
+ requirements:
135
+ - - ">="
136
+ - !ruby/object:Gem::Version
137
+ version: 8.0.0.rc1
138
+ - !ruby/object:Gem::Dependency
139
+ name: activesupport
140
+ requirement: !ruby/object:Gem::Requirement
141
+ requirements:
142
+ - - ">="
143
+ - !ruby/object:Gem::Version
144
+ version: 8.0.0.rc1
145
+ type: :runtime
146
+ prerelease: false
147
+ version_requirements: !ruby/object:Gem::Requirement
148
+ requirements:
149
+ - - ">="
150
+ - !ruby/object:Gem::Version
151
+ version: 8.0.0.rc1
152
+ - !ruby/object:Gem::Dependency
153
+ name: bundler
154
+ requirement: !ruby/object:Gem::Requirement
155
+ requirements:
156
+ - - ">="
157
+ - !ruby/object:Gem::Version
158
+ version: 1.15.0
159
+ type: :runtime
160
+ prerelease: false
161
+ version_requirements: !ruby/object:Gem::Requirement
162
+ requirements:
163
+ - - ">="
164
+ - !ruby/object:Gem::Version
165
+ version: 1.15.0
166
+ - !ruby/object:Gem::Dependency
167
+ name: railties
168
+ requirement: !ruby/object:Gem::Requirement
169
+ requirements:
170
+ - - ">="
171
+ - !ruby/object:Gem::Version
172
+ version: 8.0.0.rc1
173
+ type: :runtime
174
+ prerelease: false
175
+ version_requirements: !ruby/object:Gem::Requirement
176
+ requirements:
177
+ - - ">="
178
+ - !ruby/object:Gem::Version
179
+ version: 8.0.0.rc1
180
+ - !ruby/object:Gem::Dependency
181
+ name: zeitwerk
182
+ requirement: !ruby/object:Gem::Requirement
183
+ requirements:
184
+ - - "~>"
185
+ - !ruby/object:Gem::Version
186
+ version: '2.6'
187
+ type: :runtime
188
+ prerelease: false
189
+ version_requirements: !ruby/object:Gem::Requirement
190
+ requirements:
191
+ - - "~>"
192
+ - !ruby/object:Gem::Version
193
+ version: '2.6'
194
+ - !ruby/object:Gem::Dependency
195
+ name: better_html
196
+ requirement: !ruby/object:Gem::Requirement
197
+ requirements:
198
+ - - "~>"
199
+ - !ruby/object:Gem::Version
200
+ version: '2.1'
201
+ type: :runtime
202
+ prerelease: false
203
+ version_requirements: !ruby/object:Gem::Requirement
204
+ requirements:
205
+ - - "~>"
206
+ - !ruby/object:Gem::Version
207
+ version: '2.1'
208
+ - !ruby/object:Gem::Dependency
209
+ name: importmap-rails
210
+ requirement: !ruby/object:Gem::Requirement
211
+ requirements:
212
+ - - "~>"
213
+ - !ruby/object:Gem::Version
214
+ version: '2.0'
215
+ type: :runtime
216
+ prerelease: false
217
+ version_requirements: !ruby/object:Gem::Requirement
218
+ requirements:
219
+ - - "~>"
220
+ - !ruby/object:Gem::Version
221
+ version: '2.0'
222
+ - !ruby/object:Gem::Dependency
223
+ name: local_time
224
+ requirement: !ruby/object:Gem::Requirement
225
+ requirements:
226
+ - - "~>"
227
+ - !ruby/object:Gem::Version
228
+ version: '3.0'
229
+ type: :runtime
230
+ prerelease: false
231
+ version_requirements: !ruby/object:Gem::Requirement
232
+ requirements:
233
+ - - "~>"
234
+ - !ruby/object:Gem::Version
235
+ version: '3.0'
236
+ - !ruby/object:Gem::Dependency
237
+ name: pg
238
+ requirement: !ruby/object:Gem::Requirement
239
+ requirements:
240
+ - - "~>"
241
+ - !ruby/object:Gem::Version
242
+ version: '1.1'
243
+ type: :runtime
244
+ prerelease: false
245
+ version_requirements: !ruby/object:Gem::Requirement
246
+ requirements:
247
+ - - "~>"
248
+ - !ruby/object:Gem::Version
249
+ version: '1.1'
250
+ - !ruby/object:Gem::Dependency
251
+ name: stimulus-rails
252
+ requirement: !ruby/object:Gem::Requirement
253
+ requirements:
254
+ - - "~>"
255
+ - !ruby/object:Gem::Version
256
+ version: '1.3'
257
+ type: :runtime
258
+ prerelease: false
259
+ version_requirements: !ruby/object:Gem::Requirement
260
+ requirements:
261
+ - - "~>"
262
+ - !ruby/object:Gem::Version
263
+ version: '1.3'
264
+ - !ruby/object:Gem::Dependency
265
+ name: tailwindcss-rails
266
+ requirement: !ruby/object:Gem::Requirement
267
+ requirements:
268
+ - - "~>"
269
+ - !ruby/object:Gem::Version
270
+ version: '3.0'
271
+ type: :runtime
272
+ prerelease: false
273
+ version_requirements: !ruby/object:Gem::Requirement
274
+ requirements:
275
+ - - "~>"
276
+ - !ruby/object:Gem::Version
277
+ version: '3.0'
278
+ - !ruby/object:Gem::Dependency
279
+ name: turbo-rails
280
+ requirement: !ruby/object:Gem::Requirement
281
+ requirements:
282
+ - - "~>"
283
+ - !ruby/object:Gem::Version
284
+ version: '2.0'
285
+ type: :runtime
286
+ prerelease: false
287
+ version_requirements: !ruby/object:Gem::Requirement
288
+ requirements:
289
+ - - "~>"
290
+ - !ruby/object:Gem::Version
291
+ version: '2.0'
292
+ description: Build enterprise-ready SaaS applications without sacrificing the joy
293
+ of Rails development.
294
+ email: tony@tonyburns.net
295
+ executables: []
296
+ extensions: []
297
+ extra_rdoc_files: []
298
+ files:
299
+ - README.md
300
+ - Rakefile
301
+ - app/assets/config/saasr_manifest.js
302
+ - app/assets/stylesheets/saasr/application.css
303
+ - app/controllers/concerns/saasr/base_api_controller_mixin.rb
304
+ - app/controllers/concerns/saasr/base_controller_mixin.rb
305
+ - app/controllers/concerns/saasr/base_metal_controller_mixin.rb
306
+ - app/controllers/saasr/base_api_controller.rb
307
+ - app/controllers/saasr/base_controller.rb
308
+ - app/controllers/saasr/base_metal_controller.rb
309
+ - app/controllers/saasr/test_controller.rb
310
+ - app/helpers/saasr/application_helper.rb
311
+ - app/javascript/controllers/saasr/test_controller.js
312
+ - app/javascript/helpers/saasr/index.js
313
+ - app/javascript/lib/saasr/index.js
314
+ - app/javascript/lib/saasr/utils.js
315
+ - app/jobs/concerns/saasr/base_job_mixin.rb
316
+ - app/jobs/saasr/base_job.rb
317
+ - app/mailers/concerns/saasr/base_mailer_mixin.rb
318
+ - app/mailers/saasr/base_mailer.rb
319
+ - app/models/concerns/saasr/base_record_mixin.rb
320
+ - app/models/concerns/saasr/current_attributes.rb
321
+ - app/models/saasr/base_record.rb
322
+ - app/views/layouts/saasr/application.html.erb
323
+ - app/views/layouts/saasr/mailer.html.erb
324
+ - app/views/layouts/saasr/mailer.text.erb
325
+ - app/views/saasr/test/index.html.erb
326
+ - config/better-html.yml
327
+ - config/i18n-tasks.yml
328
+ - config/importmap.rb
329
+ - config/locales/saasr.en.yml
330
+ - config/routes.rb
331
+ - lib/saasr.rb
332
+ - lib/saasr/configuration.rb
333
+ - lib/saasr/configuration/attributes.rb
334
+ - lib/saasr/engine.rb
335
+ - lib/saasr/error.rb
336
+ - lib/saasr/log_subscriber.rb
337
+ - lib/saasr/version.rb
338
+ homepage: https://saasr.build
339
+ licenses: []
340
+ metadata:
341
+ bug_tracker_uri: https://github.com/saasr/saasr/issues
342
+ changelog_uri: https://github.com/saasr/saasr/v0.1.0/CHANGELOG.md
343
+ documentation_uri: https://api.saasr.build/v0.1.0/
344
+ mailing_list_uri: https://github.com/saasr/saasr/discussions
345
+ source_code_uri: https://github.com/saasr/saasr/tree/v0.1.0
346
+ rubygems_mfa_required: 'true'
347
+ post_install_message:
348
+ rdoc_options: []
349
+ require_paths:
350
+ - lib
351
+ required_ruby_version: !ruby/object:Gem::Requirement
352
+ requirements:
353
+ - - ">="
354
+ - !ruby/object:Gem::Version
355
+ version: 3.2.0
356
+ required_rubygems_version: !ruby/object:Gem::Requirement
357
+ requirements:
358
+ - - ">="
359
+ - !ruby/object:Gem::Version
360
+ version: 1.8.11
361
+ requirements: []
362
+ rubygems_version: 3.5.16
363
+ signing_key:
364
+ specification_version: 4
365
+ summary: Batteries-included SaaS framework for Rails.
366
+ test_files: []
metadata.gz.sig ADDED
Binary file