smriti 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.
- checksums.yaml +7 -0
- data/LICENSE +21 -0
- data/README.md +168 -0
- data/Rakefile +15 -0
- data/app/assets/images/smriti/android-chrome-192x192.png +0 -0
- data/app/assets/images/smriti/android-chrome-512x512.png +0 -0
- data/app/assets/images/smriti/apple-touch-icon.png +0 -0
- data/app/assets/images/smriti/favicon-16x16.png +0 -0
- data/app/assets/images/smriti/favicon-32x32.png +0 -0
- data/app/assets/images/smriti/favicon-48x48.png +0 -0
- data/app/assets/images/smriti/favicon.ico +0 -0
- data/app/assets/images/smriti/favicon.svg +18 -0
- data/app/assets/images/smriti/logo.svg +18 -0
- data/app/assets/images/smriti/mask-icon.svg +5 -0
- data/app/assets/stylesheets/smriti/application.css +1040 -0
- data/app/controllers/smriti/admin/application_controller.rb +135 -0
- data/app/controllers/smriti/admin/dashboard_controller.rb +32 -0
- data/app/controllers/smriti/admin/mat_view_definitions_controller.rb +372 -0
- data/app/controllers/smriti/admin/mat_view_runs_controller.rb +185 -0
- data/app/controllers/smriti/admin/preferences_controller.rb +91 -0
- data/app/helpers/smriti/admin/datatable_helper.rb +249 -0
- data/app/helpers/smriti/admin/localized_digit_helper.rb +70 -0
- data/app/helpers/smriti/admin/ui_helper.rb +539 -0
- data/app/javascript/smriti/application.js +8 -0
- data/app/javascript/smriti/controllers/application.js +10 -0
- data/app/javascript/smriti/controllers/body_setup_controller.js +120 -0
- data/app/javascript/smriti/controllers/datatable_controller.js +351 -0
- data/app/javascript/smriti/controllers/details_controller.js +200 -0
- data/app/javascript/smriti/controllers/drawer_controller.js +470 -0
- data/app/javascript/smriti/controllers/flash_controller.js +112 -0
- data/app/javascript/smriti/controllers/index.js +10 -0
- data/app/javascript/smriti/controllers/mv_confirm_controller.js +435 -0
- data/app/javascript/smriti/controllers/tabs_controller.js +184 -0
- data/app/javascript/smriti/controllers/tooltip_controller.js +525 -0
- data/app/javascript/smriti/controllers/turbo_frame_lifecycle_controller.js +342 -0
- data/app/jobs/smriti/application_job.rb +144 -0
- data/app/jobs/smriti/create_view_job.rb +87 -0
- data/app/jobs/smriti/delete_view_job.rb +89 -0
- data/app/jobs/smriti/refresh_view_job.rb +94 -0
- data/app/models/concerns/smriti_i18n.rb +139 -0
- data/app/models/concerns/smriti_paginate.rb +70 -0
- data/app/models/concerns/smriti_query_helper.rb +36 -0
- data/app/models/smriti/application_record.rb +39 -0
- data/app/models/smriti/mat_view_definition.rb +254 -0
- data/app/models/smriti/mat_view_run.rb +275 -0
- data/app/views/layouts/smriti/_footer.html.erb +47 -0
- data/app/views/layouts/smriti/_header.html.erb +25 -0
- data/app/views/layouts/smriti/admin.html.erb +47 -0
- data/app/views/layouts/smriti/turbo_frame.html.erb +3 -0
- data/app/views/smriti/admin/dashboard/index.html.erb +38 -0
- data/app/views/smriti/admin/mat_view_definitions/_definition_actions.html.erb +94 -0
- data/app/views/smriti/admin/mat_view_definitions/_dt-index-empty-row.html.erb +11 -0
- data/app/views/smriti/admin/mat_view_definitions/_dt-index-row.html.erb +27 -0
- data/app/views/smriti/admin/mat_view_definitions/empty.html.erb +1 -0
- data/app/views/smriti/admin/mat_view_definitions/form.html.erb +79 -0
- data/app/views/smriti/admin/mat_view_definitions/index.html.erb +10 -0
- data/app/views/smriti/admin/mat_view_definitions/show.html.erb +40 -0
- data/app/views/smriti/admin/mat_view_runs/_dt-index-empty-row.html.erb +11 -0
- data/app/views/smriti/admin/mat_view_runs/_dt-index-row.html.erb +41 -0
- data/app/views/smriti/admin/mat_view_runs/index.html.erb +1 -0
- data/app/views/smriti/admin/mat_view_runs/show.html.erb +64 -0
- data/app/views/smriti/admin/preferences/show.html.erb +49 -0
- data/app/views/smriti/admin/ui/_card.html.erb +15 -0
- data/app/views/smriti/admin/ui/_datatable.html.erb +34 -0
- data/app/views/smriti/admin/ui/_datatable_filters.html.erb +45 -0
- data/app/views/smriti/admin/ui/_datatable_tbody.html.erb +11 -0
- data/app/views/smriti/admin/ui/_datatable_tfoot.html.erb +70 -0
- data/app/views/smriti/admin/ui/_datatable_thead.html.erb +105 -0
- data/app/views/smriti/admin/ui/_details.html.erb +10 -0
- data/app/views/smriti/admin/ui/_flash.html.erb +6 -0
- data/app/views/smriti/admin/ui/_table.html.erb +8 -0
- data/config/importmap.rb +9 -0
- data/config/locales/ar.yml +223 -0
- data/config/locales/de.yml +230 -0
- data/config/locales/en-AU-ocker.yml +223 -0
- data/config/locales/en-AU.yml +202 -0
- data/config/locales/en-BORK.yml +225 -0
- data/config/locales/en-CA.yml +223 -0
- data/config/locales/en-GB.yml +223 -0
- data/config/locales/en-LOL.yml +219 -0
- data/config/locales/en-SCOT.yml +223 -0
- data/config/locales/en-SHAKESPEARE.yml +225 -0
- data/config/locales/en-US-pirate.yml +222 -0
- data/config/locales/en-US.yml +225 -0
- data/config/locales/en-YODA.yml +221 -0
- data/config/locales/en.yml +223 -0
- data/config/locales/es.yml +226 -0
- data/config/locales/fa.yml +223 -0
- data/config/locales/fr-CA.yml +227 -0
- data/config/locales/fr.yml +227 -0
- data/config/locales/he.yml +218 -0
- data/config/locales/hi.yml +223 -0
- data/config/locales/it.yml +225 -0
- data/config/locales/ja-JP.yml +215 -0
- data/config/locales/pt.yml +225 -0
- data/config/locales/ru.yml +228 -0
- data/config/locales/ur.yml +225 -0
- data/config/locales/zh-CN.yml +214 -0
- data/config/locales/zh-TW.yml +214 -0
- data/config/routes.rb +36 -0
- data/lib/ext/exception.rb +20 -0
- data/lib/generators/smriti/install/install_generator.rb +86 -0
- data/lib/generators/smriti/install/templates/create_mat_view_definitions.rb +29 -0
- data/lib/generators/smriti/install/templates/create_mat_view_runs.rb +32 -0
- data/lib/generators/smriti/install/templates/smriti_initializer.rb +23 -0
- data/lib/smriti/admin/auth_bridge.rb +93 -0
- data/lib/smriti/admin/default_auth.rb +62 -0
- data/lib/smriti/configuration.rb +58 -0
- data/lib/smriti/engine.rb +82 -0
- data/lib/smriti/helpers/ui_test_ids.rb +49 -0
- data/lib/smriti/jobs/adapter.rb +81 -0
- data/lib/smriti/service_response.rb +75 -0
- data/lib/smriti/services/base_service.rb +471 -0
- data/lib/smriti/services/check_matview_exists.rb +76 -0
- data/lib/smriti/services/concurrent_refresh.rb +94 -0
- data/lib/smriti/services/create_view.rb +173 -0
- data/lib/smriti/services/delete_view.rb +111 -0
- data/lib/smriti/services/regular_refresh.rb +90 -0
- data/lib/smriti/services/swap_refresh.rb +181 -0
- data/lib/smriti/version.rb +21 -0
- data/lib/smriti.rb +64 -0
- data/lib/tasks/helpers.rb +185 -0
- data/lib/tasks/smriti_tasks.rake +151 -0
- metadata +206 -0
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Copyright Codevedas Inc. 2025-present
|
|
4
|
+
#
|
|
5
|
+
# This source code is licensed under the MIT license found in the
|
|
6
|
+
# LICENSE file in the root directory of this source tree.
|
|
7
|
+
|
|
8
|
+
# Extend the Exception class to add a method for serializing error details.
|
|
9
|
+
class Exception
|
|
10
|
+
# Serialize the exception into a hash with message, class, and backtrace.
|
|
11
|
+
#
|
|
12
|
+
# @return [Hash] serialized error details
|
|
13
|
+
def mv_serialize_error
|
|
14
|
+
{
|
|
15
|
+
message: message,
|
|
16
|
+
class: self.class.name,
|
|
17
|
+
backtrace: Array(backtrace)
|
|
18
|
+
}
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Copyright Codevedas Inc. 2025-present
|
|
4
|
+
#
|
|
5
|
+
# This source code is licensed under the MIT license found in the
|
|
6
|
+
# LICENSE file in the root directory of this source tree.
|
|
7
|
+
|
|
8
|
+
require 'rails/generators'
|
|
9
|
+
require 'rails/generators/migration'
|
|
10
|
+
require 'rails/generators/active_record'
|
|
11
|
+
|
|
12
|
+
##
|
|
13
|
+
# Top-level namespace for the smriti engine.
|
|
14
|
+
module Smriti
|
|
15
|
+
##
|
|
16
|
+
# Namespace for Rails generators shipped with the smriti engine.
|
|
17
|
+
module Generators
|
|
18
|
+
##
|
|
19
|
+
# Rails generator that installs Smriti into a host application by:
|
|
20
|
+
#
|
|
21
|
+
# 1. Copying migrations for definitions and run-tracking tables.
|
|
22
|
+
# 2. Creating an initializer at `config/initializers/smriti.rb`.
|
|
23
|
+
# 3. Printing a success message with next steps.
|
|
24
|
+
#
|
|
25
|
+
# @example Run the installer
|
|
26
|
+
# bin/rails g smriti:install
|
|
27
|
+
#
|
|
28
|
+
# @see Smriti::MatViewDefinition
|
|
29
|
+
# @see Smriti::MatViewRun
|
|
30
|
+
#
|
|
31
|
+
class InstallGenerator < Rails::Generators::Base
|
|
32
|
+
include Rails::Generators::Migration
|
|
33
|
+
|
|
34
|
+
##
|
|
35
|
+
# Directory containing template files for the generator.
|
|
36
|
+
#
|
|
37
|
+
# @return [String] absolute path to templates dir
|
|
38
|
+
#
|
|
39
|
+
source_root File.expand_path('templates', __dir__)
|
|
40
|
+
|
|
41
|
+
##
|
|
42
|
+
# Short description shown in `rails g --help`.
|
|
43
|
+
desc 'Installs Smriti: copies migrations and initializer.'
|
|
44
|
+
|
|
45
|
+
##
|
|
46
|
+
# Copies all required migrations into the host app.
|
|
47
|
+
#
|
|
48
|
+
# @return [void]
|
|
49
|
+
#
|
|
50
|
+
def copy_migrations
|
|
51
|
+
migration_template 'create_mat_view_definitions.rb', 'db/migrate/create_mat_view_definitions.rb'
|
|
52
|
+
migration_template 'create_mat_view_runs.rb', 'db/migrate/create_mat_view_runs.rb'
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
##
|
|
56
|
+
# Creates the engine initializer in the host app.
|
|
57
|
+
#
|
|
58
|
+
# @return [void]
|
|
59
|
+
#
|
|
60
|
+
def create_initializer
|
|
61
|
+
copy_file 'smriti_initializer.rb', 'config/initializers/smriti.rb'
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
##
|
|
65
|
+
# Prints a success message after installation.
|
|
66
|
+
#
|
|
67
|
+
# @return [void]
|
|
68
|
+
#
|
|
69
|
+
def show_success_message
|
|
70
|
+
say "\n✅ Smriti installed! Don't forget to run: rails db:migrate\n", :green
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
##
|
|
74
|
+
# Computes the next migration number for copied migrations.
|
|
75
|
+
#
|
|
76
|
+
# Required by Rails to generate timestamped migration filenames.
|
|
77
|
+
#
|
|
78
|
+
# @param path [String] destination path for migrations
|
|
79
|
+
# @return [String] the next migration number (timestamp)
|
|
80
|
+
#
|
|
81
|
+
def self.next_migration_number(path)
|
|
82
|
+
ActiveRecord::Generators::Base.next_migration_number(path)
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Copyright Codevedas Inc. 2025-present
|
|
4
|
+
#
|
|
5
|
+
# This source code is licensed under the MIT license found in the
|
|
6
|
+
# LICENSE file in the root directory of this source tree.
|
|
7
|
+
|
|
8
|
+
# This migration creates the mat_view_definitions table, which stores definitions for materialised views.
|
|
9
|
+
# It includes fields for the view name, SQL definition, refresh strategy, schedule, unique index columns,
|
|
10
|
+
# dependencies, last refreshed timestamp, and timestamps for creation and updates.
|
|
11
|
+
class CreateMatViewDefinitions < ActiveRecord::Migration[7.1]
|
|
12
|
+
def change
|
|
13
|
+
create_table :mat_view_definitions do |t|
|
|
14
|
+
t.string :name, null: false, comment: 'The name of the materialised view'
|
|
15
|
+
t.text :sql, null: false, comment: 'The SQL query defining the materialised view'
|
|
16
|
+
# refresh_strategy can be
|
|
17
|
+
# regular: 0 - Default strategy, in-place refresh.
|
|
18
|
+
# concurrent: 1 - Concurrent refresh, requires at least one unique index.
|
|
19
|
+
# swap: 2 - Swap the materialised view with a new one, uses more memory.
|
|
20
|
+
t.integer :refresh_strategy, default: 0, null: false,
|
|
21
|
+
comment: 'Strategy for refreshing the materialised view. Options: regular, concurrent, swap'
|
|
22
|
+
t.string :schedule_cron, comment: 'Cron schedule for automatic refresh of the materialised view'
|
|
23
|
+
t.jsonb :unique_index_columns, default: [], comment: 'Columns used for unique indexing, if any'
|
|
24
|
+
t.jsonb :dependencies, default: [],
|
|
25
|
+
comment: 'Dependencies of the materialised view, such as other views or tables'
|
|
26
|
+
t.timestamps
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Copyright Codevedas Inc. 2025-present
|
|
4
|
+
#
|
|
5
|
+
# This source code is licensed under the MIT license found in the
|
|
6
|
+
# LICENSE file in the root directory of this source tree.
|
|
7
|
+
|
|
8
|
+
# This migration creates the mat_view_runs table, which tracks the mutation runs(create,refresh,drop) of materialised views.
|
|
9
|
+
# It includes references to the materialised view definition, status, operation type, timestamps,
|
|
10
|
+
# duration, error messages, and additional metadata.
|
|
11
|
+
class CreateMatViewRuns < ActiveRecord::Migration[7.1]
|
|
12
|
+
def change
|
|
13
|
+
create_table :mat_view_runs do |t|
|
|
14
|
+
t.references :mat_view_definition,
|
|
15
|
+
null: false,
|
|
16
|
+
foreign_key: true,
|
|
17
|
+
comment: 'Reference to the materialised view definition'
|
|
18
|
+
|
|
19
|
+
# 0=running, 1=success, 2=failed
|
|
20
|
+
t.integer :status, null: false, default: 0, comment: '0=running,1=success,2=failed'
|
|
21
|
+
# 0=create, 1=refresh, 2=drop
|
|
22
|
+
t.integer :operation, null: false, default: 0, comment: '0=create,1=refresh,2=drop'
|
|
23
|
+
t.datetime :started_at, comment: 'Timestamp when the operation started'
|
|
24
|
+
t.datetime :finished_at, comment: 'Timestamp when the operation finished'
|
|
25
|
+
t.integer :duration_ms, comment: 'Duration of the operation in milliseconds'
|
|
26
|
+
t.jsonb :error, comment: 'Error details if the operation failed. :message, :class, :backtrace'
|
|
27
|
+
t.jsonb :meta, null: false, default: {}, comment: 'Additional metadata about the run, such as job ID, row count or parameters'
|
|
28
|
+
|
|
29
|
+
t.timestamps
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Copyright Codevedas Inc. 2025-present
|
|
4
|
+
#
|
|
5
|
+
# This source code is licensed under the MIT license found in the
|
|
6
|
+
# LICENSE file in the root directory of this source tree.
|
|
7
|
+
|
|
8
|
+
Smriti.configure do |config|
|
|
9
|
+
### Job Adapter Configuration
|
|
10
|
+
# Set job adapter for Smriti
|
|
11
|
+
# This can be set to :active_job, :sidekiq, and :resque,
|
|
12
|
+
# defaults to :active_job.
|
|
13
|
+
#
|
|
14
|
+
# Depending on your application's job processing setup.
|
|
15
|
+
# Uncomment the line below to set the job adapter.
|
|
16
|
+
# config.job_adapter = :active_job
|
|
17
|
+
|
|
18
|
+
# job_queue is the queue name for the job adapter.
|
|
19
|
+
# Default is :default.
|
|
20
|
+
# This is used to specify the queue where Smriti jobs will be enqueued.
|
|
21
|
+
# Uncomment the line below to set the job queue.
|
|
22
|
+
# config.job_queue = :default
|
|
23
|
+
end
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Copyright Codevedas Inc. 2025-present
|
|
4
|
+
#
|
|
5
|
+
# This source code is licensed under the MIT license found in the
|
|
6
|
+
# LICENSE file in the root directory of this source tree.
|
|
7
|
+
|
|
8
|
+
module Smriti
|
|
9
|
+
module Admin
|
|
10
|
+
#
|
|
11
|
+
# Smriti::Admin::AuthBridge
|
|
12
|
+
# ---------------------------
|
|
13
|
+
# Bridge module that wires the Smriti admin engine to a **host-provided**
|
|
14
|
+
# authentication/authorization layer, while providing safe defaults.
|
|
15
|
+
#
|
|
16
|
+
# ### How it works
|
|
17
|
+
# - Includes {Smriti::Admin::DefaultAuth} first (fallback, no-op/hostable).
|
|
18
|
+
# - Then includes the **host auth module** returned by {.host_auth_module}.
|
|
19
|
+
# Because Ruby searches the most recently included module first, the host
|
|
20
|
+
# module cleanly **overrides** any defaults from `DefaultAuth`.
|
|
21
|
+
# - Registers a before_action `authenticate_smriti!`.
|
|
22
|
+
# - Exposes helpers: `smriti_current_user` and its alias {#user}.
|
|
23
|
+
#
|
|
24
|
+
# ### Host integration options (define one of these):
|
|
25
|
+
# 1) A top-level module:
|
|
26
|
+
# ```ruby
|
|
27
|
+
# # app/lib/smriti_admin.rb (or any autoloaded path)
|
|
28
|
+
# module SmritiAdmin
|
|
29
|
+
# def authenticate_smriti!; end
|
|
30
|
+
# def authorize_smriti!(*); end
|
|
31
|
+
# def smriti_current_user; end
|
|
32
|
+
# end
|
|
33
|
+
# ```
|
|
34
|
+
# 2) A namespaced module:
|
|
35
|
+
# ```ruby
|
|
36
|
+
# # app/lib/smriti/admin/host_auth.rb
|
|
37
|
+
# module Smriti
|
|
38
|
+
# module Admin
|
|
39
|
+
# module HostAuth
|
|
40
|
+
# def authenticate_smriti!; end
|
|
41
|
+
# def authorize_smriti!(*); end
|
|
42
|
+
# def smriti_current_user; end
|
|
43
|
+
# end
|
|
44
|
+
# end
|
|
45
|
+
# end
|
|
46
|
+
# ```
|
|
47
|
+
#
|
|
48
|
+
# If neither module is present, a blank `Module.new` is included and the
|
|
49
|
+
# defaults in {Smriti::Admin::DefaultAuth} remain in effect.
|
|
50
|
+
#
|
|
51
|
+
# @see Smriti::Admin::DefaultAuth
|
|
52
|
+
#
|
|
53
|
+
module AuthBridge
|
|
54
|
+
extend ActiveSupport::Concern
|
|
55
|
+
|
|
56
|
+
included do
|
|
57
|
+
# Include defaults first, so the host module (included below) can override.
|
|
58
|
+
include Smriti::Admin::DefaultAuth
|
|
59
|
+
include host_auth_module
|
|
60
|
+
|
|
61
|
+
before_action :authenticate_smriti!
|
|
62
|
+
helper_method :smriti_current_user, :user
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# Convenience alias for `smriti_current_user` exposed to views.
|
|
66
|
+
#
|
|
67
|
+
# @return [Object, nil] the current user object as defined by host auth
|
|
68
|
+
def user = smriti_current_user
|
|
69
|
+
|
|
70
|
+
class_methods do
|
|
71
|
+
# Resolves the host's auth module, if any.
|
|
72
|
+
#
|
|
73
|
+
# Lookup order:
|
|
74
|
+
# 1. `::SmritiAdmin`
|
|
75
|
+
# 2. `::Smriti::Admin::HostAuth`
|
|
76
|
+
# 3. Fallback: a blank Module (no overrides)
|
|
77
|
+
#
|
|
78
|
+
# @return [Module] the module to include for host auth overrides
|
|
79
|
+
def host_auth_module
|
|
80
|
+
if Object.const_defined?('SmritiAdmin')
|
|
81
|
+
::SmritiAdmin
|
|
82
|
+
elsif Object.const_defined?('Smriti') &&
|
|
83
|
+
Smriti.const_defined?('Admin') &&
|
|
84
|
+
Smriti::Admin.const_defined?('HostAuth')
|
|
85
|
+
::Smriti::Admin::HostAuth
|
|
86
|
+
else
|
|
87
|
+
Module.new
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Copyright Codevedas Inc. 2025-present
|
|
4
|
+
#
|
|
5
|
+
# This source code is licensed under the MIT license found in the
|
|
6
|
+
# LICENSE file in the root directory of this source tree.
|
|
7
|
+
|
|
8
|
+
module Smriti
|
|
9
|
+
module Admin
|
|
10
|
+
# Smriti::Admin::DefaultAuth
|
|
11
|
+
# ----------------------------
|
|
12
|
+
# Development-friendly **fallback** authentication/authorization for the Smriti
|
|
13
|
+
# admin UI. It is included first by {Smriti::Admin::AuthBridge}, and is meant
|
|
14
|
+
# to be overridden by a host-provided module (`SmritiAdmin` or
|
|
15
|
+
# `Smriti::Admin::HostAuth`).
|
|
16
|
+
#
|
|
17
|
+
# ❗ **Not for production**: this module allows all access and returns a dummy user.
|
|
18
|
+
#
|
|
19
|
+
# @see Smriti::Admin::AuthBridge
|
|
20
|
+
#
|
|
21
|
+
module DefaultAuth
|
|
22
|
+
# Minimal stand-in user object used by the default auth.
|
|
23
|
+
#
|
|
24
|
+
# @!attribute [rw] email
|
|
25
|
+
# @return [String] the email address of the sample user
|
|
26
|
+
class SampleUser
|
|
27
|
+
attr_accessor :email
|
|
28
|
+
|
|
29
|
+
# @param email [String]
|
|
30
|
+
def initialize(email) = @email = email
|
|
31
|
+
|
|
32
|
+
# @return [String] the user's email
|
|
33
|
+
def to_s = email
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Authenticates the current request.
|
|
37
|
+
# Always returns true in the default implementation.
|
|
38
|
+
#
|
|
39
|
+
# @return [Boolean] true
|
|
40
|
+
# rubocop:disable Naming/PredicateMethod
|
|
41
|
+
def authenticate_smriti! = true
|
|
42
|
+
# rubocop:enable Naming/PredicateMethod
|
|
43
|
+
|
|
44
|
+
# Returns the current user object.
|
|
45
|
+
# In the default implementation this is a {SampleUser}.
|
|
46
|
+
#
|
|
47
|
+
# @return [SampleUser]
|
|
48
|
+
def smriti_current_user = SampleUser.new('sample-user@example.com')
|
|
49
|
+
|
|
50
|
+
# Authorizes an action on a record.
|
|
51
|
+
# Always returns true in the default implementation.
|
|
52
|
+
#
|
|
53
|
+
# @param _action [Symbol, String] the attempted action (ignored)
|
|
54
|
+
# @param _type [Symbol, String] the type of resource (ignored)
|
|
55
|
+
# @param _record [Object] the target record or symbol (ignored)
|
|
56
|
+
# @return [Boolean] true
|
|
57
|
+
# rubocop:disable Naming/PredicateMethod
|
|
58
|
+
def authorize_smriti!(_action, _type, _record = nil) = true
|
|
59
|
+
# rubocop:enable Naming/PredicateMethod
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Copyright Codevedas Inc. 2025-present
|
|
4
|
+
#
|
|
5
|
+
# This source code is licensed under the MIT license found in the
|
|
6
|
+
# LICENSE file in the root directory of this source tree.
|
|
7
|
+
|
|
8
|
+
module Smriti
|
|
9
|
+
##
|
|
10
|
+
# Configuration for the Smriti engine.
|
|
11
|
+
#
|
|
12
|
+
# This class provides customization points for how Smriti integrates
|
|
13
|
+
# with background job systems and controls default behavior across
|
|
14
|
+
# the engine.
|
|
15
|
+
#
|
|
16
|
+
# @example Configure in an initializer
|
|
17
|
+
# Smriti.configure do |config|
|
|
18
|
+
# config.job_adapter = :sidekiq
|
|
19
|
+
# config.job_queue = :low_priority
|
|
20
|
+
# config.admin_ui = { row_count_strategy: :estimated }
|
|
21
|
+
# end
|
|
22
|
+
#
|
|
23
|
+
# Supported job adapters:
|
|
24
|
+
# - `:active_job` (default)
|
|
25
|
+
# - `:sidekiq`
|
|
26
|
+
# - `:resque`
|
|
27
|
+
#
|
|
28
|
+
class Configuration
|
|
29
|
+
##
|
|
30
|
+
# The job adapter to use for enqueuing jobs.
|
|
31
|
+
#
|
|
32
|
+
# @return [Symbol] :active_job, :sidekiq, or :resque
|
|
33
|
+
attr_accessor :job_adapter
|
|
34
|
+
|
|
35
|
+
##
|
|
36
|
+
# The default queue name to use for jobs.
|
|
37
|
+
#
|
|
38
|
+
# @return [Symbol, String]
|
|
39
|
+
attr_accessor :job_queue
|
|
40
|
+
|
|
41
|
+
##
|
|
42
|
+
# admin_ui configuration
|
|
43
|
+
# @return [Hash]
|
|
44
|
+
attr_accessor :admin_ui
|
|
45
|
+
|
|
46
|
+
##
|
|
47
|
+
# Initialize with defaults.
|
|
48
|
+
#
|
|
49
|
+
# @return [void]
|
|
50
|
+
def initialize
|
|
51
|
+
@job_adapter = :active_job
|
|
52
|
+
@job_queue = :default
|
|
53
|
+
@admin_ui = {
|
|
54
|
+
row_count_strategy: :none
|
|
55
|
+
}
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Copyright Codevedas Inc. 2025-present
|
|
4
|
+
#
|
|
5
|
+
# This source code is licensed under the MIT license found in the
|
|
6
|
+
# LICENSE file in the root directory of this source tree.
|
|
7
|
+
|
|
8
|
+
##
|
|
9
|
+
# Smriti is a Rails engine that provides first-class support for
|
|
10
|
+
# PostgreSQL materialised views in Rails applications.
|
|
11
|
+
module Smriti
|
|
12
|
+
class << self
|
|
13
|
+
attr_accessor :importmap
|
|
14
|
+
end
|
|
15
|
+
##
|
|
16
|
+
# Rails Engine for Smriti.
|
|
17
|
+
#
|
|
18
|
+
# This engine encapsulates all functionality related to
|
|
19
|
+
# materialised views, including:
|
|
20
|
+
# - Defining materialised view definitions
|
|
21
|
+
# - Creating and refreshing views
|
|
22
|
+
# - Managing background jobs for refresh/create/delete
|
|
23
|
+
#
|
|
24
|
+
# By isolating the namespace, it ensures that routes, models,
|
|
25
|
+
# and helpers do not conflict with the host application.
|
|
26
|
+
#
|
|
27
|
+
# @example Mounting the engine in a Rails application
|
|
28
|
+
# # config/routes.rb
|
|
29
|
+
# Rails.application.routes.draw do
|
|
30
|
+
# mount Smriti::Engine => "/smriti"
|
|
31
|
+
# end
|
|
32
|
+
#
|
|
33
|
+
class Engine < ::Rails::Engine
|
|
34
|
+
isolate_namespace Smriti
|
|
35
|
+
|
|
36
|
+
initializer 'smriti.load_config' do
|
|
37
|
+
Smriti.configuration ||= Smriti::Configuration.new
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
initializer 'smriti.javascript' do |app|
|
|
41
|
+
app.config.assets.paths << root.join('app/javascript')
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
initializer 'smriti.importmap', before: 'importmap' do |_app|
|
|
45
|
+
next unless defined?(Importmap)
|
|
46
|
+
|
|
47
|
+
Smriti.importmap = Importmap::Map.new
|
|
48
|
+
Smriti.importmap.draw(root.join('config/importmap.rb'))
|
|
49
|
+
Smriti.importmap.cache_sweeper(watches: root.join('app/javascript'))
|
|
50
|
+
|
|
51
|
+
ActiveSupport.on_load(:action_controller_base) do
|
|
52
|
+
before_action { Smriti.importmap.cache_sweeper.execute_if_updated }
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def self.locale_code_mapping
|
|
57
|
+
@locale_code_mapping ||= begin
|
|
58
|
+
mappings = Dir[root.join('config', 'locales', '*.yml')].map.to_h do |file|
|
|
59
|
+
code = File.basename(file, '.yml').to_sym
|
|
60
|
+
name = I18n.t('i18n.name', locale: code)
|
|
61
|
+
[code, name]
|
|
62
|
+
end
|
|
63
|
+
mappings.sort_by { |code, _name| code.to_s }.to_h
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def self.available_locales
|
|
68
|
+
@available_locales ||= locale_code_mapping.keys.freeze
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def self.default_locale = :en
|
|
72
|
+
def self.loaded_spec = Gem.loaded_specs['smriti']
|
|
73
|
+
def self.project_name = loaded_spec&.name
|
|
74
|
+
def self.project_version = Smriti::VERSION
|
|
75
|
+
def self.project_homepage = loaded_spec&.homepage
|
|
76
|
+
def self.company_name = 'Codevedas Inc.'
|
|
77
|
+
def self.documentation_uri = loaded_spec&.metadata&.[]('documentation_uri')
|
|
78
|
+
def self.bug_tracker_uri = loaded_spec&.metadata&.[]('bug_tracker_uri')
|
|
79
|
+
def self.support_uri = loaded_spec&.metadata&.[]('support_uri')
|
|
80
|
+
def self.rubygems_uri = loaded_spec&.metadata&.[]('rubygems_uri')
|
|
81
|
+
end
|
|
82
|
+
end
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Copyright Codevedas Inc. 2025-present
|
|
4
|
+
#
|
|
5
|
+
# This source code is licensed under the MIT license found in the
|
|
6
|
+
# LICENSE file in the root directory of this source tree.
|
|
7
|
+
|
|
8
|
+
module Smriti
|
|
9
|
+
module Helpers
|
|
10
|
+
module UiTestIds
|
|
11
|
+
GEM_LINK = 'gem_link'
|
|
12
|
+
PROJECT_HOMEPAGE_LINK = 'project_homepage_link'
|
|
13
|
+
OPEN_ISSUE_LINK = 'open_issue_link'
|
|
14
|
+
DOCUMENTATION_LINK = 'documentation_link'
|
|
15
|
+
SUPPORT_LINK = 'support_link'
|
|
16
|
+
|
|
17
|
+
DRAWER_REFRESH_LINK = 'drawer_refresh_link'
|
|
18
|
+
DRAWER_CLOSE_LINK = 'drawer_close_link'
|
|
19
|
+
|
|
20
|
+
HEADER_LINK = 'header_link'
|
|
21
|
+
PREFERENCES_LINK = 'preferences_link'
|
|
22
|
+
|
|
23
|
+
DEFINITIONS_TAB_LINK = 'definitions_tab_link'
|
|
24
|
+
RUNS_TAB_LINK = 'runs_tab_link'
|
|
25
|
+
|
|
26
|
+
NEW_DEFINITION_LINK = 'new_definition_link'
|
|
27
|
+
SUBMIT_BUTTON = 'submit_button'
|
|
28
|
+
CANCEL_BUTTON = 'cancel_button'
|
|
29
|
+
VIEW_HISTORY_LINK = 'view_history_link'
|
|
30
|
+
VIEW_LINK = 'view_link'
|
|
31
|
+
EDIT_LINK = 'edit_link'
|
|
32
|
+
DELETE_LINK = 'delete_link'
|
|
33
|
+
REFRESH_LINK = 'refresh_link'
|
|
34
|
+
DROP_LINK = 'drop_link'
|
|
35
|
+
DROP_CASCADE_LINK = 'drop_cascade_link'
|
|
36
|
+
CREATE_MV_LINK = 'create_mv_link'
|
|
37
|
+
RESET_FILTERS_LINK = 'reset_filters_link'
|
|
38
|
+
|
|
39
|
+
PREFERENCES_SAVE_BUTTON = 'preferences_save_button'
|
|
40
|
+
PREFERENCES_CANCEL_BUTTON = 'preferences_cancel_button'
|
|
41
|
+
|
|
42
|
+
TOGGLE_SORT_BUTTON = 'toggle_sort_button'
|
|
43
|
+
DT_SEARCH_INPUT = 'dt_search_input'
|
|
44
|
+
DT_FILTER_SELECT = 'dt_filter_select'
|
|
45
|
+
DT_CLEAR_SEARCH_BTN = 'dt_clear_search_btn'
|
|
46
|
+
DT_PAGINATION_BTN = 'dt_pagination_btn'
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Copyright Codevedas Inc. 2025-present
|
|
4
|
+
#
|
|
5
|
+
# This source code is licensed under the MIT license found in the
|
|
6
|
+
# LICENSE file in the root directory of this source tree.
|
|
7
|
+
|
|
8
|
+
##
|
|
9
|
+
# Top-level namespace for the smriti engine.
|
|
10
|
+
module Smriti
|
|
11
|
+
##
|
|
12
|
+
# Namespace for job-related utilities and integrations.
|
|
13
|
+
module Jobs
|
|
14
|
+
##
|
|
15
|
+
# Adapter class for handling job enqueuing across different backends.
|
|
16
|
+
#
|
|
17
|
+
# This class abstracts the job enqueueing process so Smriti can work
|
|
18
|
+
# with multiple background processing frameworks without changing core code.
|
|
19
|
+
#
|
|
20
|
+
# Supported adapters (configured via `Smriti.configuration.job_adapter`):
|
|
21
|
+
# - `:active_job` → {ActiveJob}
|
|
22
|
+
# - `:sidekiq` → {Sidekiq::Client}
|
|
23
|
+
# - `:resque` → {Resque}
|
|
24
|
+
#
|
|
25
|
+
# @example Enqueue via ActiveJob
|
|
26
|
+
# Smriti.configuration.job_adapter = :active_job
|
|
27
|
+
# Smriti::Jobs::Adapter.enqueue(MyJob, queue: :low, args: [1, "foo"])
|
|
28
|
+
#
|
|
29
|
+
# @example Enqueue via Sidekiq
|
|
30
|
+
# Smriti.configuration.job_adapter = :sidekiq
|
|
31
|
+
# Smriti::Jobs::Adapter.enqueue(MyWorker, queue: :critical, args: [42])
|
|
32
|
+
#
|
|
33
|
+
# @example Enqueue via Resque
|
|
34
|
+
# Smriti.configuration.job_adapter = :resque
|
|
35
|
+
# Smriti::Jobs::Adapter.enqueue(MyWorker, queue: :default, args: %w[a b c])
|
|
36
|
+
#
|
|
37
|
+
# @raise [ArgumentError] if the configured adapter is not recognized
|
|
38
|
+
#
|
|
39
|
+
class Adapter
|
|
40
|
+
##
|
|
41
|
+
# Enqueue a job across supported backends.
|
|
42
|
+
#
|
|
43
|
+
# @api public
|
|
44
|
+
#
|
|
45
|
+
# @param job_class [Class] The job or worker class to enqueue.
|
|
46
|
+
# - For `:active_job`, this should be a subclass of {ActiveJob::Base}.
|
|
47
|
+
# - For `:sidekiq`, this should be a Sidekiq worker class.
|
|
48
|
+
# - For `:resque`, this should be a Resque worker class.
|
|
49
|
+
#
|
|
50
|
+
# @param queue [String, Symbol] Target queue name.
|
|
51
|
+
# @param args [Array] Arguments to pass into the job/worker.
|
|
52
|
+
#
|
|
53
|
+
# @return [Object] Framework-dependent:
|
|
54
|
+
# - For ActiveJob → enqueued {ActiveJob::Base} instance
|
|
55
|
+
# - For Sidekiq → job ID hash
|
|
56
|
+
# - For Resque → `true` if enqueue succeeded
|
|
57
|
+
#
|
|
58
|
+
# @raise [ArgumentError] if the configured adapter is not recognized.
|
|
59
|
+
#
|
|
60
|
+
def self.enqueue(job_class, queue:, args: [])
|
|
61
|
+
queue_str = queue.to_s
|
|
62
|
+
job_adapter = Smriti.configuration.job_adapter
|
|
63
|
+
|
|
64
|
+
case job_adapter
|
|
65
|
+
when :active_job
|
|
66
|
+
job_class.set(queue: queue_str).perform_later(*args)
|
|
67
|
+
when :sidekiq
|
|
68
|
+
Sidekiq::Client.push(
|
|
69
|
+
'class' => job_class.name,
|
|
70
|
+
'queue' => queue_str,
|
|
71
|
+
'args' => args
|
|
72
|
+
)
|
|
73
|
+
when :resque
|
|
74
|
+
Resque.enqueue_to(queue_str, job_class, *args)
|
|
75
|
+
else
|
|
76
|
+
raise ArgumentError, "Unknown job adapter: #{job_adapter.inspect}"
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|