litestream_rails 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.
- checksums.yaml +7 -0
- data/README.md +39 -0
- data/Rakefile +10 -0
- data/app/controllers/litestream_rails/application_controller.rb +7 -0
- data/app/controllers/litestream_rails/databases_controller.rb +32 -0
- data/app/views/layouts/litestream_rails/_style.html +1118 -0
- data/app/views/layouts/litestream_rails/application.html.erb +56 -0
- data/app/views/litestream_rails/databases/index.html.erb +85 -0
- data/config/routes.rb +5 -0
- data/lib/litestream_rails/engine.rb +15 -0
- data/lib/litestream_rails/version.rb +5 -0
- data/lib/litestream_rails.rb +48 -0
- metadata +127 -0
@@ -0,0 +1,56 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html class="h-full">
|
3
|
+
<head>
|
4
|
+
<title>Litestream Rails</title>
|
5
|
+
<%= csrf_meta_tags %>
|
6
|
+
<%= csp_meta_tag %>
|
7
|
+
|
8
|
+
<%= render "layouts/litestream_rails/style" %>
|
9
|
+
</head>
|
10
|
+
<body class="h-full flex flex-col pb-4">
|
11
|
+
<main class="grow container mx-auto mt-4">
|
12
|
+
<%= content_for?(:content) ? yield(:content) : yield %>
|
13
|
+
</main>
|
14
|
+
|
15
|
+
<footer class="container mx-auto py-4 mt-24 text-base flex justify-between items-center border-t">
|
16
|
+
<p>
|
17
|
+
<code><strong>Litestream</strong> <em>Rails</em></code> |
|
18
|
+
Made by <a href="https://twitter.com/fractaledmind" class="text-blue-500 hover:underline decoration-blue-500">@fractaledmind</a> and <a href="https://github.com/fractaledmind/litestream_rails/graphs/contributors" class="text-blue-500 hover:underline decoration-blue-500">friends</a>! Want to help? It's <a href="https://github.com/fractaledmind/litestream_rails" class="text-blue-500 hover:underline decoration-blue-500">open source</a>!
|
19
|
+
</p>
|
20
|
+
</footer>
|
21
|
+
|
22
|
+
<div class="fixed top-0 left-0 right-0 text-center py-2">
|
23
|
+
<% if notice.present? %>
|
24
|
+
<p id="notice"
|
25
|
+
class="py-2 px-3 bg-green-50 text-green-500 font-medium rounded-lg inline-block"
|
26
|
+
data-controller="fade">
|
27
|
+
<%= notice %>
|
28
|
+
</p>
|
29
|
+
<% end %>
|
30
|
+
|
31
|
+
<% if alert.present? %>
|
32
|
+
<p id="alert"
|
33
|
+
class="py-2 px-3 bg-red-50 text-red-500 font-medium rounded-lg inline-block"
|
34
|
+
data-controller="fade">
|
35
|
+
<%= alert %>
|
36
|
+
</p>
|
37
|
+
<% end %>
|
38
|
+
</div>
|
39
|
+
|
40
|
+
<script nonce="<%= content_security_policy_nonce %>">
|
41
|
+
function fadeOut(element) {
|
42
|
+
element.classList.add('transition-opacity')
|
43
|
+
setTimeout(
|
44
|
+
() => {
|
45
|
+
element.classList.add('opacity-0')
|
46
|
+
element.remove()
|
47
|
+
},
|
48
|
+
2000
|
49
|
+
)
|
50
|
+
}
|
51
|
+
document.querySelectorAll('[data-controller="fade"]').forEach(element => {
|
52
|
+
fadeOut(element);
|
53
|
+
});
|
54
|
+
</script>
|
55
|
+
</body>
|
56
|
+
</html>
|
@@ -0,0 +1,85 @@
|
|
1
|
+
<ul>
|
2
|
+
<% @databases.each do |database| %>
|
3
|
+
<li>
|
4
|
+
<section id="error_12" class="space-y-6">
|
5
|
+
<div class="flex items-center justify-between">
|
6
|
+
<h1 class="flex items-center gap-2 text-2xl font-bold">
|
7
|
+
<code><%= database['path'] %></code>
|
8
|
+
</h1>
|
9
|
+
</div>
|
10
|
+
</section>
|
11
|
+
<br />
|
12
|
+
<section id="generations" class="-mx-2 mt-4 sm:mx-0 sm:rounded-md">
|
13
|
+
<div class="mb-3 flex items-center justify-between border-b">
|
14
|
+
<h2 class="text-2xl font-bold">Generations</h2>
|
15
|
+
<p class="text-right">Total: <strong><%= database['generations'].size %></strong></p>
|
16
|
+
</div>
|
17
|
+
|
18
|
+
<div class="min-w-full">
|
19
|
+
<% database['generations'].each do |generation| %>
|
20
|
+
<section id="<%= generation['generation'] %>" class="">
|
21
|
+
<details open="open">
|
22
|
+
<summary class="cursor-pointer rounded p-2 hover:bg-gray-50">
|
23
|
+
<code><%= generation['generation'] %></code>
|
24
|
+
(<em><%= generation['lag'] %> lag</em>)
|
25
|
+
</summary>
|
26
|
+
<div class="">
|
27
|
+
<dl class="grid flex-1 grid-cols-2 gap-x-4">
|
28
|
+
<div class="flex flex-wrap items-center justify-between gap-x-2">
|
29
|
+
<dt class="font-bold">Start</dt>
|
30
|
+
<dd class="inline-flex items-center gap-1">
|
31
|
+
<abbr title="<%= generation['start'] %>" class="cursor-help">
|
32
|
+
<time datetime="<%= generation['start'] %>"><%= DateTime.parse(generation['start']).to_formatted_s(:db) %></time>
|
33
|
+
</abbr>
|
34
|
+
</dd>
|
35
|
+
</div>
|
36
|
+
<div class="flex flex-wrap items-center justify-between gap-x-2">
|
37
|
+
<dt class="font-bold">End</dt>
|
38
|
+
<dd class="inline-flex items-center gap-1">
|
39
|
+
<abbr title="<%= generation['end'] %>" class="cursor-help">
|
40
|
+
<time datetime="<%= generation['end'] %>"><%= DateTime.parse(generation['end']).to_formatted_s(:db) %></time>
|
41
|
+
</abbr>
|
42
|
+
</dd>
|
43
|
+
</div>
|
44
|
+
<div class="col-span-2">
|
45
|
+
<dt class="font-bold">Snapshots</dt>
|
46
|
+
<dd class="">
|
47
|
+
<table class="min-w-full divide-y divide-gray-300">
|
48
|
+
<thead>
|
49
|
+
<tr>
|
50
|
+
<th scope="col" class="py-3.5 pl-4 pr-3 text-left text-sm font-semibold text-gray-900 sm:pl-3">Created</th>
|
51
|
+
<th scope="col" class="px-3 py-3.5 text-right text-sm font-semibold text-gray-900">Index</th>
|
52
|
+
<th scope="col" class="px-3 py-3.5 text-right text-sm font-semibold text-gray-900">Size</th>
|
53
|
+
</tr>
|
54
|
+
</thead>
|
55
|
+
|
56
|
+
<tbody class="bg-white">
|
57
|
+
<% generation['snapshots'].each do |snapshot| %>
|
58
|
+
<tr class="align-top even:bg-gray-50">
|
59
|
+
<td scope="col" class="whitespace-nowrap px-3 py-4 pt-7 text-left text-gray-500">
|
60
|
+
<abbr title="<%= snapshot['created'] %>" class="cursor-help">
|
61
|
+
<time datetime="<%= snapshot['created'] %>"><%= DateTime.parse(snapshot['created']).to_formatted_s(:db) %></time>
|
62
|
+
</abbr>
|
63
|
+
</td>
|
64
|
+
<td scope="col" class="whitespace-nowrap px-3 py-4 pt-7 text-right text-gray-500">
|
65
|
+
<%= snapshot['index'] %>
|
66
|
+
</td>
|
67
|
+
<td scope="col" class="whitespace-nowrap px-3 py-4 pt-7 text-right text-gray-500">
|
68
|
+
<%= number_to_human_size snapshot['size'] %>
|
69
|
+
</td>
|
70
|
+
</tr>
|
71
|
+
<% end %>
|
72
|
+
</tbody>
|
73
|
+
</table>
|
74
|
+
</dd>
|
75
|
+
</div>
|
76
|
+
</dl>
|
77
|
+
</div>
|
78
|
+
</details>
|
79
|
+
</section>
|
80
|
+
<% end %>
|
81
|
+
</div>
|
82
|
+
</section>
|
83
|
+
</li>
|
84
|
+
<% end %>
|
85
|
+
</ul>
|
data/config/routes.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module LitestreamRails
|
4
|
+
class Engine < ::Rails::Engine
|
5
|
+
isolate_namespace LitestreamRails
|
6
|
+
|
7
|
+
config.litestream_rails = ActiveSupport::OrderedOptions.new
|
8
|
+
|
9
|
+
initializer "litestream_rails.config" do
|
10
|
+
config.litestream_rails.each do |name, value|
|
11
|
+
LitestreamRails.public_send(:"#{name}=", value)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "litestream_rails/version"
|
4
|
+
require_relative "litestream_rails/engine"
|
5
|
+
require "litestream"
|
6
|
+
|
7
|
+
module LitestreamRails
|
8
|
+
mattr_writer :username
|
9
|
+
mattr_writer :password
|
10
|
+
|
11
|
+
class << self
|
12
|
+
# use method instead of attr_accessor to ensure
|
13
|
+
# this works if variable set after SolidErrors is loaded
|
14
|
+
def username
|
15
|
+
@username ||= ENV["LITESTREAMRAILS_USERNAME"] || @@username
|
16
|
+
end
|
17
|
+
|
18
|
+
# use method instead of attr_accessor to ensure
|
19
|
+
# this works if variable set after SolidErrors is loaded
|
20
|
+
def password
|
21
|
+
@password ||= ENV["LITESTREAMRAILS_PASSWORD"] || @@password
|
22
|
+
end
|
23
|
+
|
24
|
+
def databases
|
25
|
+
databases = text_table_to_hashes(Litestream::Commands.databases(async: false))
|
26
|
+
|
27
|
+
databases.each do |db|
|
28
|
+
generations = text_table_to_hashes(Litestream::Commands.generations(db["path"], async: false))
|
29
|
+
snapshots = text_table_to_hashes(Litestream::Commands.snapshots(db["path"], async: false))
|
30
|
+
|
31
|
+
db['generations'] = generations.map do |generation|
|
32
|
+
id = generation["generation"]
|
33
|
+
replica = generation["name"]
|
34
|
+
generation["snapshots"] = snapshots.select { |snapshot| snapshot["generation"] == id && snapshot["replica"] == replica }
|
35
|
+
.map { |s| s.slice("index", "size", "created") }
|
36
|
+
generation.slice("generation", "name", "lag", "start", "end", "snapshots")
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def text_table_to_hashes(string)
|
44
|
+
keys, *rows = string.split("\n").map { _1.split(/\s+/) }
|
45
|
+
rows.map { keys.zip(_1).to_h }
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
metadata
ADDED
@@ -0,0 +1,127 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: litestream_rails
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Stephen Margheim
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2024-04-17 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: litestream
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.5.3
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 0.5.3
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: actionpack
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '7.0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '7.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: actionview
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '7.0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '7.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: activesupport
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '7.0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '7.0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: railties
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '7.0'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '7.0'
|
83
|
+
description:
|
84
|
+
email:
|
85
|
+
- stephen.margheim@gmail.com
|
86
|
+
executables: []
|
87
|
+
extensions: []
|
88
|
+
extra_rdoc_files: []
|
89
|
+
files:
|
90
|
+
- README.md
|
91
|
+
- Rakefile
|
92
|
+
- app/controllers/litestream_rails/application_controller.rb
|
93
|
+
- app/controllers/litestream_rails/databases_controller.rb
|
94
|
+
- app/views/layouts/litestream_rails/_style.html
|
95
|
+
- app/views/layouts/litestream_rails/application.html.erb
|
96
|
+
- app/views/litestream_rails/databases/index.html.erb
|
97
|
+
- config/routes.rb
|
98
|
+
- lib/litestream_rails.rb
|
99
|
+
- lib/litestream_rails/engine.rb
|
100
|
+
- lib/litestream_rails/version.rb
|
101
|
+
homepage: https://github.com/fractaledmind/litestream_rails
|
102
|
+
licenses:
|
103
|
+
- MIT
|
104
|
+
metadata:
|
105
|
+
homepage_uri: https://github.com/fractaledmind/litestream_rails
|
106
|
+
source_code_uri: https://github.com/fractaledmind/litestream_rails
|
107
|
+
changelog_uri: https://github.com/fractaledmind/litestream_rails/blob/main/CHANGELOG.md
|
108
|
+
post_install_message:
|
109
|
+
rdoc_options: []
|
110
|
+
require_paths:
|
111
|
+
- lib
|
112
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
113
|
+
requirements:
|
114
|
+
- - ">="
|
115
|
+
- !ruby/object:Gem::Version
|
116
|
+
version: 3.0.0
|
117
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
118
|
+
requirements:
|
119
|
+
- - ">="
|
120
|
+
- !ruby/object:Gem::Version
|
121
|
+
version: '0'
|
122
|
+
requirements: []
|
123
|
+
rubygems_version: 3.5.1
|
124
|
+
signing_key:
|
125
|
+
specification_version: 4
|
126
|
+
summary: Rails integration for Litestream.
|
127
|
+
test_files: []
|