databasium 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 (125) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +32 -0
  3. data/MIT-LICENSE +20 -0
  4. data/README.md +109 -0
  5. data/Rakefile +6 -0
  6. data/app/assets/builds/application.js +9045 -0
  7. data/app/assets/builds/application.js.map +7 -0
  8. data/app/assets/builds/databasium.css +2 -0
  9. data/app/assets/config/databasium_manifest.js +1 -0
  10. data/app/assets/javascript/databasium/application.js +2 -0
  11. data/app/assets/javascript/databasium/controllers/attribute_controller.js +27 -0
  12. data/app/assets/javascript/databasium/controllers/collapse_controller.js +18 -0
  13. data/app/assets/javascript/databasium/controllers/error_controller.js +15 -0
  14. data/app/assets/javascript/databasium/controllers/filter_controller.js +224 -0
  15. data/app/assets/javascript/databasium/controllers/flash_controller.js +18 -0
  16. data/app/assets/javascript/databasium/controllers/graph_controller.js +193 -0
  17. data/app/assets/javascript/databasium/controllers/index.js +7 -0
  18. data/app/assets/javascript/databasium/controllers/layout_controller.js +13 -0
  19. data/app/assets/javascript/databasium/controllers/model_controller.js +32 -0
  20. data/app/assets/javascript/databasium/controllers/new_migration_controller.js +107 -0
  21. data/app/assets/javascript/databasium/controllers/relation_controller.js +10 -0
  22. data/app/assets/javascript/databasium/controllers/search_controller.js +23 -0
  23. data/app/assets/javascript/databasium/controllers/table_controller.js +283 -0
  24. data/app/assets/javascript/databasium/controllers/table_select_controller.js +19 -0
  25. data/app/assets/javascript/databasium/controllers/toggle_controller.js +28 -0
  26. data/app/assets/javascript/databasium/controllers/validation_controller.js +78 -0
  27. data/app/assets/javascript/databasium/shapes/erd_table_shape.js +54 -0
  28. data/app/assets/stylesheets/databasium/application.css +15 -0
  29. data/app/assets/stylesheets/databasium/colors.css +55 -0
  30. data/app/assets/stylesheets/databasium/custom.css +36 -0
  31. data/app/assets/stylesheets/databasium/databasium_engine.css +6 -0
  32. data/app/assets/stylesheets/databasium/pagy-tailwind.css +66 -0
  33. data/app/components/base.rb +50 -0
  34. data/app/components/databasium/collapsable.rb +62 -0
  35. data/app/components/databasium/forms/model.rb +147 -0
  36. data/app/components/databasium/forms/search.rb +31 -0
  37. data/app/components/databasium/global/error.rb +60 -0
  38. data/app/components/databasium/global/flash.rb +73 -0
  39. data/app/components/databasium/global/header_actions.rb +36 -0
  40. data/app/components/databasium/global/sidebar.rb +45 -0
  41. data/app/components/databasium/global/suggestion.rb +25 -0
  42. data/app/components/databasium/migrations/action.rb +39 -0
  43. data/app/components/databasium/migrations/file.rb +58 -0
  44. data/app/components/databasium/migrations/form.rb +222 -0
  45. data/app/components/databasium/migrations/header_actions.rb +87 -0
  46. data/app/components/databasium/migrations/migration_status.rb +22 -0
  47. data/app/components/databasium/migrations/preview.rb +29 -0
  48. data/app/components/databasium/migrations/show_turbo_stream.rb +19 -0
  49. data/app/components/databasium/migrations/sidebar.rb +28 -0
  50. data/app/components/databasium/models/attributes.rb +49 -0
  51. data/app/components/databasium/models/form.rb +100 -0
  52. data/app/components/databasium/models/header_actions.rb +51 -0
  53. data/app/components/databasium/models/model_preview.rb +31 -0
  54. data/app/components/databasium/models/sidebar.rb +25 -0
  55. data/app/components/databasium/models/templates/attribute.rb +99 -0
  56. data/app/components/databasium/models/templates/base.rb +6 -0
  57. data/app/components/databasium/models/templates/relation.rb +56 -0
  58. data/app/components/databasium/models/templates/validation.rb +285 -0
  59. data/app/components/databasium/navigation/base_icon.rb +32 -0
  60. data/app/components/databasium/navigation/frontend_icon.rb +17 -0
  61. data/app/components/databasium/navigation/get_icon.rb +26 -0
  62. data/app/components/databasium/navigation/icon.rb +28 -0
  63. data/app/components/databasium/navigation/icon_panel.rb +26 -0
  64. data/app/components/databasium/navigation/post_icon.rb +25 -0
  65. data/app/components/databasium/navigation/put_icon.rb +18 -0
  66. data/app/components/databasium/records/filter.rb +73 -0
  67. data/app/components/databasium/records/foreign_records.rb +84 -0
  68. data/app/components/databasium/records/header_actions.rb +110 -0
  69. data/app/components/databasium/records/show_turbo_stream.rb +75 -0
  70. data/app/components/databasium/records/sidebar.rb +23 -0
  71. data/app/components/databasium/records/table/record_panel.rb +60 -0
  72. data/app/components/databasium/records/table/row.rb +104 -0
  73. data/app/components/databasium/records/table.rb +125 -0
  74. data/app/components/databasium/records/table_turbo_frame.rb +37 -0
  75. data/app/components/databasium/records/utilities.rb +25 -0
  76. data/app/components/databasium/schemas/header_actions.rb +99 -0
  77. data/app/components/databasium/schemas/sidebar.rb +25 -0
  78. data/app/components/databasium/search_results/migrations.rb +37 -0
  79. data/app/components/databasium/search_results/models.rb +36 -0
  80. data/app/components/databasium/search_results/schema_models.rb +37 -0
  81. data/app/components/databasium/search_results/tables.rb +31 -0
  82. data/app/components/databasium/type_select.rb +35 -0
  83. data/app/controllers/databasium/application_controller.rb +68 -0
  84. data/app/controllers/databasium/homepage_controller.rb +5 -0
  85. data/app/controllers/databasium/migrations_controller.rb +186 -0
  86. data/app/controllers/databasium/models_controller.rb +105 -0
  87. data/app/controllers/databasium/records_controller.rb +156 -0
  88. data/app/controllers/databasium/schemas_controller.rb +52 -0
  89. data/app/helpers/databasium/application_helper.rb +4 -0
  90. data/app/helpers/databasium/heroicon_helper.rb +21 -0
  91. data/app/helpers/databasium/models_helper.rb +4 -0
  92. data/app/jobs/databasium/application_job.rb +4 -0
  93. data/app/mailers/databasium/application_mailer.rb +6 -0
  94. data/app/models/databasium/application_record.rb +5 -0
  95. data/app/models/model.json +0 -0
  96. data/app/services/databasium/migration.rb +176 -0
  97. data/app/services/databasium/model.rb +182 -0
  98. data/app/services/databasium/record.rb +65 -0
  99. data/app/services/databasium/schema.rb +146 -0
  100. data/app/views/base.rb +13 -0
  101. data/app/views/databasium/errors/non_development.rb +21 -0
  102. data/app/views/databasium/homepage/index.rb +29 -0
  103. data/app/views/databasium/migrations/index.rb +33 -0
  104. data/app/views/databasium/migrations/new.rb +29 -0
  105. data/app/views/databasium/models/index.rb +31 -0
  106. data/app/views/databasium/models/new.rb +37 -0
  107. data/app/views/databasium/records/index.rb +24 -0
  108. data/app/views/databasium/schemas/index.rb +39 -0
  109. data/app/views/layouts/databasium/application.rb +56 -0
  110. data/config/importmap.rb +12 -0
  111. data/config/initializers/heroicon.rb +12 -0
  112. data/config/initializers/pagy.rb +48 -0
  113. data/config/initializers/phlex.rb +19 -0
  114. data/config/routes.rb +31 -0
  115. data/config/tailwind.config.js +10 -0
  116. data/lib/databasium/engine.rb +57 -0
  117. data/lib/databasium/engine_mount.rb +37 -0
  118. data/lib/databasium/middleware/conditional_check_pending.rb +27 -0
  119. data/lib/databasium/templates/create_table_migration.rb.tt +29 -0
  120. data/lib/databasium/templates/migration.rb.tt +48 -0
  121. data/lib/databasium/templates/model.rb.tt +23 -0
  122. data/lib/databasium/version.rb +3 -0
  123. data/lib/databasium.rb +11 -0
  124. data/lib/tasks/databasium_tasks.rake +4 -0
  125. metadata +272 -0
@@ -0,0 +1,146 @@
1
+ class Databasium::Schema
2
+ attr_reader :schema, :tables
3
+ def initialize
4
+ @conn = ActiveRecord::Base.connection
5
+ @tables = @conn.data_sources - %w[ar_internal_metadata schema_migrations]
6
+ @schema = nil
7
+ end
8
+
9
+ def sync!(schema: nil)
10
+ path = Rails.root.join("storage")
11
+ FileUtils.mkdir_p(path) unless Dir.exist?(path)
12
+ File.write(path.join("schema_graph.json"), schema || build_schema.to_json)
13
+ end
14
+
15
+ def get_associations(table)
16
+ model =
17
+ ActiveRecord::Base.descendants.find { |m| m.table_name == table } ||
18
+ table.classify.safe_constantize
19
+ if model
20
+ model.reflect_on_all_associations.map do |r|
21
+ {
22
+ name: r.name.to_s.pluralize,
23
+ macro: r.macro,
24
+ class_name: r.class_name,
25
+ foreign_key: r.foreign_key
26
+ }
27
+ end
28
+ else
29
+ []
30
+ end
31
+ end
32
+
33
+ def schema
34
+ return @schema unless @schema.nil?
35
+ if File.exist?(Rails.root.join("storage/schema_graph.json"))
36
+ @schema = JSON.parse(File.read(Rails.root.join("storage/schema_graph.json")))
37
+ else
38
+ @schema = build_schema.deep_stringify_keys
39
+ sync!(schema: @schema)
40
+ @schema
41
+ end
42
+ end
43
+
44
+ def get_model_and_layers_BFS(model, layers)
45
+ queue = Queue.new()
46
+ queue.push([ table_name_for(model), 0 ])
47
+ result = {}
48
+
49
+ until queue.empty?
50
+ table, layer = queue.pop
51
+ next if (layers.present? && layer > layers) || result[table].present?
52
+ result[table] = get_schema_for_model(table)
53
+
54
+ model_associations = result[table].fetch("associations", nil)
55
+ model_associations&.each { |a| queue << [ a["name"], layer + 1 ] }
56
+ end
57
+ result
58
+ end
59
+
60
+ def get_schema_for_model(model)
61
+ schema[table_name_for(model)]
62
+ end
63
+
64
+ def get_foreign_keys(table)
65
+ @conn
66
+ .foreign_keys(table)
67
+ .map do |fk|
68
+ { from: fk.from_table, to: fk.to_table, column: fk.column, primary_key: fk.primary_key }
69
+ end
70
+ end
71
+
72
+ def get_columns_from_table(table)
73
+ @conn
74
+ .columns(table)
75
+ .map { |c| { name: c.name, sql_type: c.sql_type, null: c.null, default: c.default } }
76
+ end
77
+
78
+ def get_columns_names(table)
79
+ @conn.columns(table_name_for(table)).map { |c| c.name }
80
+ end
81
+
82
+ def get_tables(search)
83
+ @tables = @tables.select { |table| table =~ /#{search}/i } if search
84
+ @tables
85
+ end
86
+
87
+ def get_columns(model)
88
+ return if model.nil?
89
+ model.columns.map do |column|
90
+ {
91
+ name: column.name,
92
+ type: column.type.to_s,
93
+ used: false,
94
+ foreign_key: is_column_foreign_key?(model.table_name, column.name),
95
+ to_table: get_foreign_key_to_table(model.table_name, column.name)
96
+ }
97
+ end
98
+ end
99
+
100
+ def get_model_from_table(table)
101
+ return nil, "Select a table to view its records." if table.nil?
102
+ table_name = table_name_for(table)
103
+ unless ActiveRecord::Base.connection.table_exists?(table_name)
104
+ return nil, "Table #{table} does not exist"
105
+ end
106
+ begin
107
+ # If there is no model for this table it will raise a NameError
108
+ @model =
109
+ ActiveRecord::Base.descendants.find { |model| model.table_name == table_name } ||
110
+ table_name.classify.constantize
111
+ @error = nil
112
+ rescue NameError
113
+ @model = nil
114
+ @error =
115
+ "No model found for this table,
116
+ if you would like to interact with this table, you need to create a model for it."
117
+ end
118
+ [ @model, @error ]
119
+ end
120
+
121
+ private
122
+
123
+ def build_schema
124
+ @schema = {}
125
+ @tables.each do |table|
126
+ @schema[table] = {
127
+ columns: get_columns_from_table(table),
128
+ foreign_keys: get_foreign_keys(table),
129
+ associations: get_associations(table)
130
+ }
131
+ end
132
+ @schema
133
+ end
134
+
135
+ def table_name_for(name)
136
+ name.to_s.tableize
137
+ end
138
+
139
+ def is_column_foreign_key?(table, column_name)
140
+ get_foreign_keys(table).any? { |fk| fk[:column] == column_name }
141
+ end
142
+
143
+ def get_foreign_key_to_table(table, column_name)
144
+ get_foreign_keys(table).find { |fk| fk[:column] == column_name }&.fetch(:to)
145
+ end
146
+ end
data/app/views/base.rb ADDED
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Databasium
4
+ class Views::Base < Components::Base
5
+ # The `Views::Base` is an abstract class for all your views.
6
+ # By default, it inherits from `Components::Base`, but you
7
+ # can change that to `Phlex::HTML` if you want to keep views and
8
+ # components independent.
9
+
10
+ # More caching options at https://www.phlex.fun/components/caching
11
+ #
12
+ end
13
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Views
4
+ module Databasium
5
+ class Errors::NonDevelopment < Views::Base
6
+ include Phlex::Rails::Helpers::ContentFor
7
+
8
+ def view_template
9
+ content_for(:title) { "Non Development Environment" }
10
+ div(class: "w-full h-full p-4") do
11
+ h1(class: "text-2xl font-bold") do
12
+ "You are not allowed to access this page in non development environment"
13
+ end
14
+ p(class: "text-red-500 bg-white w-fit px-4 py-2 rounded-md my-2") do
15
+ "DATABASIUM IS NOT MEANT TO BE USED IN PRODUCTION, ALWAYS BE SURE TO NEVER EXPOSE IT TO THE PUBLIC."
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Views
4
+ module Databasium
5
+ class Homepage::Index < Views::Base
6
+ include Phlex::Rails::Helpers::ContentFor
7
+
8
+ def view_template
9
+ content_for(:title) { "Homepage" }
10
+ div(class: "w-full h-full p-4") do
11
+ h1(class: "text-2xl font-bold") { "Hello world!" }
12
+ section(class: "p-4 text-base text-gray-300 flex flex-col gap-1") do
13
+ h2(class: "text-xl font-semibold") { "Welcome to Databasium" }
14
+ p { "Databasium is a developer tool for managing your database." }
15
+ p { "Its features are:" }
16
+ ul(class: "list-disc list-inside") do
17
+ li { "Create, read, update and delete(CRUD) data in your database." }
18
+ li { "Generate models and migrations for your database." }
19
+ li { "Generate schema for your database." }
20
+ end
21
+ p(class: "text-red-500 bg-white w-fit px-4 py-2 rounded-md my-2") do
22
+ "DATABASIUM IS NOT MEANT TO BE USED IN PRODUCTION, ALWAYS BE SURE TO NEVER EXPOSE IT TO THE PUBLIC."
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,33 @@
1
+ module Views
2
+ module Databasium
3
+ class Migrations::Index < Views::Base
4
+ include Phlex::Rails::Helpers::FormWith
5
+ include Phlex::Rails::Helpers::TurboFrameTag
6
+ include Phlex::Rails::Helpers::LinkTo
7
+ include Phlex::Rails::Helpers::ButtonTo
8
+ include Phlex::Rails::Helpers::ContentFor
9
+
10
+ def initialize
11
+ end
12
+
13
+ def view_template
14
+ content_for(:title) { "Migrations" }
15
+ content_for(:sidebar) { render Components::Databasium::Migrations::Sidebar.new }
16
+ content_for(:header_actions) do
17
+ render Components::Databasium::Migrations::HeaderActions.new(migration: nil)
18
+ end
19
+ render_migration_frame
20
+ end
21
+
22
+ private
23
+
24
+ def render_migration_frame
25
+ turbo_frame_tag "migration", class: "flex-1" do
26
+ render Components::Databasium::Global::Suggestion.new(
27
+ suggestions: [ "Select a migration to see the file" ]
28
+ )
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Views
4
+ module Databasium
5
+ class Migrations::New < Views::Base
6
+ include Phlex::Rails::Helpers::FormWith
7
+ include Phlex::Rails::Helpers::TurboFrameTag
8
+ include Phlex::Rails::Helpers::ContentFor
9
+
10
+ def initialize(tables:)
11
+ @tables = tables
12
+ end
13
+
14
+ def view_template
15
+ content_for(:title) { "New Migration" }
16
+ content_for(:sidebar) { render Components::Databasium::Migrations::Sidebar.new }
17
+ content_for(:header_actions) do
18
+ render Components::Databasium::Migrations::HeaderActions.new(migration: nil)
19
+ end
20
+ div(class: "flex p-4 gap-4") do
21
+ render Components::Databasium::Migrations::Form.new(tables: @tables, content: nil)
22
+ div(class: "flex-1 pe-4") do
23
+ render Components::Databasium::Migrations::Preview.new(content: nil)
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Views
4
+ module Databasium
5
+ class Models::Index < Views::Base
6
+ include Phlex::Rails::Helpers::ContentFor
7
+
8
+ def initialize(models:)
9
+ @models = models
10
+ end
11
+
12
+ def view_template
13
+ content_for(:title) { "Models" }
14
+
15
+ div(class: "w-full h-full p-4") { render_models }
16
+ end
17
+
18
+ private
19
+
20
+ def render_models
21
+ div do
22
+ @models.each do |model|
23
+ div(class: "border-1 border-border rounded-xl p-4") do
24
+ h2(class: "text-lg font-semibold mb-2") { model.name }
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Views
4
+ module Databasium
5
+ class Models::New < Views::Base
6
+ include Phlex::Rails::Helpers::ContentFor
7
+ include Phlex::Rails::Helpers::TurboFrameTag
8
+
9
+ def initialize(content:, model: nil, attributes: nil, models: nil)
10
+ @model = model
11
+ @content = content
12
+ @attributes = attributes
13
+ @models = models
14
+ end
15
+
16
+ def view_template
17
+ content_for(:title) { "New Model" }
18
+ content_for(:sidebar) { render Components::Databasium::Models::Sidebar.new }
19
+ content_for(:header_actions) do
20
+ render Components::Databasium::Models::HeaderActions.new(model: @model)
21
+ end
22
+ div(class: "flex gap-4 p-4 overflow-y-hidden flex-1") do
23
+ div(class: "w-1/2 overflow-y-auto") do
24
+ render Components::Databasium::Models::Form.new(
25
+ attributes: @attributes,
26
+ model: @model,
27
+ models: @models
28
+ )
29
+ end
30
+ div(class: "flex-1 overflow-y-auto") do
31
+ render Components::Databasium::Models::ModelPreview.new(content: @content)
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Views
4
+ module Databasium
5
+ class Records::Index < Views::Base
6
+ include Phlex::Rails::Helpers::ContentFor
7
+ include Phlex::Rails::Helpers::TurboFrameTag
8
+ include Phlex::Rails::Helpers::FormWith
9
+ include Phlex::Rails::Helpers::LinkTo
10
+
11
+ def initialize
12
+ end
13
+
14
+ def view_template
15
+ content_for(:title) { "Records" }
16
+ content_for(:sidebar) { render Components::Databasium::Records::Sidebar.new }
17
+ div(class: "flex min-h-0 min-w-0 flex-1") do
18
+ render Components::Databasium::Records::TableTurboFrame.new
19
+ render Components::Databasium::Records::Table::RecordPanel.new
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Views
4
+ module Databasium
5
+ class Schemas::Index < Views::Base
6
+ include Phlex::Rails::Helpers::ContentFor
7
+ include Phlex::Rails::Helpers::LinkTo
8
+
9
+ def initialize(schema:, models:, pagy:, model:, layers:)
10
+ @schema = schema
11
+ @models = models
12
+ @pagy = pagy
13
+ @model = model
14
+ @layers = layers
15
+ end
16
+
17
+ def view_template
18
+ content_for(:title) { "Schema" }
19
+ content_for(:sidebar) { render Components::Databasium::Schemas::Sidebar.new }
20
+ content_for(:header_actions) do
21
+ render Components::Databasium::Schemas::HeaderActions.new(model: @model, layers: @layers)
22
+ end
23
+ div(class: "w-full h-full p-4") { render_schema }
24
+ end
25
+
26
+ private
27
+
28
+ def render_schema
29
+ div(
30
+ class: "w-full h-full border-1 border-border rounded-2xl p-4 overflow-x-auto",
31
+ data: {
32
+ controller: "graph",
33
+ graph_tables_value: @schema.to_json
34
+ }
35
+ ) { }
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,56 @@
1
+ module Views
2
+ module Layouts
3
+ class Databasium::Application < Views::Base
4
+ include Phlex::Rails::Layout
5
+ include Phlex::Rails::Helpers::ContentFor
6
+ include Phlex::Rails::Helpers::StylesheetLinkTag
7
+ include Phlex::Rails::Helpers::JavascriptImportmapTags
8
+ include Phlex::Rails::Helpers::TurboFrameTag
9
+ include Phlex::Rails::Helpers::Flash
10
+
11
+ def view_template(&block)
12
+ doctype
13
+
14
+ html do
15
+ head do
16
+ title { content_for?(:title) ? yield(:title) : "Databasium" }
17
+ meta charset: "utf-8"
18
+ csrf_meta_tags
19
+ csp_meta_tag
20
+ yield :head
21
+ stylesheet_link_tag "databasium",
22
+ "data-turbo-track": Rails.env.production? ? "reload" : ""
23
+ javascript_importmap_tags "databasium/application"
24
+ end
25
+ body(
26
+ class: "flex h-dvh overflow-hidden bg-background text-main-text scrollbar-thin",
27
+ data: {
28
+ controller: "layout"
29
+ }
30
+ ) do
31
+ render Components::Databasium::Global::Error.new
32
+ render Components::Databasium::Global::Flash.new(
33
+ success: flash[:success],
34
+ error: flash[:error]
35
+ )
36
+ render Components::Databasium::Global::Sidebar.new(sidebar: content_for(:sidebar))
37
+ turbo_frame_tag(
38
+ "main",
39
+ class: "flex flex-1 flex-col overflow-hidden",
40
+ data: {
41
+ controller: "toggle model table"
42
+ }
43
+ ) do
44
+ render Components::Databasium::Global::HeaderActions.new(
45
+ actions: content_for(:header_actions)
46
+ )
47
+ div(class: "flex min-h-0 min-w-0 flex-1 flex-col") do
48
+ yield block_given? ? block : block.call
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,12 @@
1
+ pin "databasium/application", to: "databasium/application.js"
2
+ pin "@hotwired/turbo-rails", to: "turbo.min.js", preload: true
3
+ pin "@hotwired/stimulus", to: "stimulus.min.js", preload: true
4
+ pin "@hotwired/stimulus-loading", to: "stimulus-loading.js", preload: true
5
+ pin "@maxgraph/core", to: "https://esm.sh/@maxgraph/core@0.21.0"
6
+
7
+ # Pin the controllers index so `import "controllers"` resolves
8
+ pin "databasium/controllers", to: "databasium/controllers/index.js"
9
+
10
+ # Auto-pin all Stimulus controllers under the namespace
11
+ pin_all_from Databasium::Engine.root.join("app/assets/javascript/databasium/controllers"), under: "databasium/controllers"
12
+ pin_all_from Databasium::Engine.root.join("app/assets/javascript/databasium/shapes"), under: "databasium/shapes"
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "heroicon"
4
+
5
+ Heroicon.configure do |config|
6
+ config.variant = :solid # Options are :solid, :outline and :mini
7
+
8
+ ##
9
+ # You can set a default class, which will get applied to every icon with
10
+ # the given variant. To do so, un-comment the line below.
11
+ # config.default_class = {solid: "h-5 w-5", outline: "h-6 w-6", mini: "h-4 w-4"}
12
+ end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Pagy initializer file (43.2.4)
4
+ # See https://ddnexus.github.io/pagy/resources/initializer/
5
+
6
+ ############ Global Options ################################################################
7
+ # See https://ddnexus.github.io/pagy/toolbox/options/ for details.
8
+ # Add your global options below. They will be applied globally.
9
+ # For example:
10
+ #
11
+ # Pagy.options[:limit] = 10 # Limit the items per page
12
+ # Pagy.options[:client_max_limit] = 100 # The client can request a limit up to 100
13
+ # Pagy.options[:max_pages] = 200 # Allow only 200 pages
14
+ # Pagy.options[:jsonapi] = true # Use JSON:API compliant URLs
15
+
16
+
17
+ ############ JavaScript ####################################################################
18
+ # See https://ddnexus.github.io/pagy/resources/javascript/ for details.
19
+ # Examples for Rails:
20
+ # For apps with an assets pipeline
21
+ # Rails.application.config.assets.paths << Pagy::ROOT.join('javascripts')
22
+ #
23
+ # For apps with a javascript builder (e.g. esbuild, webpack, etc.)
24
+ # javascript_dir = Rails.root.join('app/javascript')
25
+ # Pagy.sync_javascript(javascript_dir, 'pagy.mjs') if Rails.env.development?
26
+
27
+
28
+ ############# Overriding Pagy::I18n Lookup #################################################
29
+ # Refer to https://ddnexus.github.io/pagy/resources/i18n/ for details.
30
+ # Override the I18n lookup by dropping your custom dictionary in some pagy dir.
31
+ # Example for Rails:
32
+ #
33
+ # Pagy::I18n.pathnames << Rails.root.join('config/locales/pagy')
34
+
35
+
36
+ ############# I18n Gem Translation #########################################################
37
+ # See https://ddnexus.github.io/pagy/resources/i18n/ for details.
38
+ #
39
+ # Pagy.translate_with_the_slower_i18n_gem!
40
+
41
+
42
+ ############# Calendar Localization for non-en locales ####################################
43
+ # See https://ddnexus.github.io/pagy/toolbox/paginators/calendar#localization for details.
44
+ # Add your desired locales to the list and uncomment the following line to enable them,
45
+ # regardless of whether you use the I18n gem for translations or not, whether with
46
+ # Rails or not.
47
+ #
48
+ # Pagy::Calendar.localize_with_rails_i18n_gem(*your_locales)
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Views
4
+ end
5
+
6
+ module Components
7
+ extend Phlex::Kit
8
+ end
9
+
10
+ engine_views_path = Databasium::Engine.root.join("app/views")
11
+ engine_components_path = Databasium::Engine.root.join("app/components")
12
+
13
+ if engine_views_path.directory?
14
+ Rails.autoloaders.main.push_dir(engine_views_path, namespace: Views)
15
+ end
16
+
17
+ if engine_components_path.directory?
18
+ Rails.autoloaders.main.push_dir(engine_components_path, namespace: Components)
19
+ end
data/config/routes.rb ADDED
@@ -0,0 +1,31 @@
1
+ Databasium::Engine.routes.draw do
2
+ root to: "homepage#index"
3
+ resources :homepage, only: [ :index ]
4
+
5
+ resources :records, only: [ :index, :create, :update ] do
6
+ collection do
7
+ get :sidebar
8
+ delete :bulk_destroy
9
+ get :records
10
+ end
11
+ end
12
+ resources :migrations, only: [ :index, :new, :create, :show ] do
13
+ collection do
14
+ get :sidebar
15
+ post :run_pending_migrations
16
+ post :run_migration
17
+ post :rollback_migration
18
+ end
19
+ end
20
+ resources :models, only: [ :new, :create, :show ] do
21
+ collection do
22
+ get :sidebar
23
+ end
24
+ end
25
+ resources :schemas, only: [ :index, :new, :create ] do
26
+ collection do
27
+ get :sidebar
28
+ put :sync_schema
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,10 @@
1
+ module.exports = {
2
+ prefix: 'databasium-',
3
+ content: [
4
+ "./app/views/**/*.{erb,html}",
5
+ "./app/helpers/**/*.rb",
6
+ './config/initializers/heroicon.rb',
7
+ ],
8
+ theme: { extend: {} },
9
+ plugins: []
10
+ }
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "databasium/engine_mount"
4
+ require "databasium/middleware/conditional_check_pending"
5
+
6
+ module Databasium
7
+ class Engine < ::Rails::Engine
8
+ isolate_namespace Databasium
9
+
10
+ config.databasium = ActiveSupport::OrderedOptions.new
11
+
12
+ initializer "databasium.development_only" do
13
+ if Rails.env.production?
14
+ abort "
15
+ Databasium gem must not be loaded in production.
16
+ Add databasium only to the :development group.
17
+ It will not even allow you to load your application in production or when you run RAILS_ENV=production locally.
18
+ Do not add it to the default group."
19
+ end
20
+ end
21
+
22
+ initializer "databasium.configuration" do |app|
23
+ app.config.databasium ||= ActiveSupport::OrderedOptions.new
24
+ end
25
+
26
+ initializer "databasium.clear_mount_path_cache" do |app|
27
+ app.config.to_prepare { Databasium::EngineMount.clear_mount_path_cache! }
28
+ end
29
+
30
+ # Prevent the default global middleware; we insert a scoped version below.
31
+ initializer "databasium.skip_global_pending_migration_check",
32
+ before: "active_record.migration_error" do |app|
33
+ app.config.active_record.migration_error = :ignore if Rails.env.development?
34
+ end
35
+
36
+ initializer "databasium.conditional_check_pending",
37
+ after: "active_record.migration_error" do |app|
38
+ next unless Rails.env.development?
39
+
40
+ app.middleware.insert_after(
41
+ ActionDispatch::Callbacks,
42
+ Databasium::Middleware::ConditionalCheckPending,
43
+ file_watcher: app.config.file_watcher
44
+ )
45
+ end
46
+
47
+ initializer "databasium.assets" do |app|
48
+ app.config.assets.precompile += %w[ databasium_manifest.js ]
49
+ end
50
+
51
+ initializer "databasium.importmap", before: "importmap" do |app|
52
+ if app.respond_to?(:config) && app.config.respond_to?(:importmap)
53
+ app.config.importmap.paths << root.join("config/importmap.rb")
54
+ end
55
+ end
56
+ end
57
+ end