s3arch 0.0.4 → 0.0.5
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 +4 -4
- checksums.yaml.gz.sig +0 -0
- data/CHANGELOG.md +18 -0
- data/infrastructure/routes.tf.rb +8 -0
- data/infrastructure/schema.tf.rb +6 -0
- data/lambda/controllers/s3arch_controller.rb +66 -0
- data/lib/s3arch/configuration.rb +5 -0
- data/lib/s3arch/dashboard/application.rb +86 -0
- data/lib/s3arch/dashboard/views/index.html.erb +150 -0
- data/lib/s3arch/dashboard.rb +13 -0
- data/lib/s3arch/holster.rb +7 -0
- data/lib/s3arch/routes.rb +14 -0
- data/lib/s3arch/version.rb +1 -1
- data/lib/s3arch/web.rb +26 -0
- data/lib/s3arch.rb +5 -0
- data.tar.gz.sig +0 -0
- metadata +26 -3
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 6e0ba51260081a3de075c6e14332909892693b64dce6eb1a3e52f7b1f145b537
|
|
4
|
+
data.tar.gz: 7553e90741ef8a1cc6c72b55bb9239c0e238da2a09916d34e8edf18780942a24
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 26e0cd3ff75ea9aff46dfd28a5978db557b26cef4780d966345b14fdb0b023bc9a6d22809c30c1422ac967aea3cbcc7bf18a75e94ea07d56af13d0f96d2d12e2
|
|
7
|
+
data.tar.gz: bf5c5b19de20e235f95427218b8beb0ee5ab03b4270bf31cbe38ca2f6f420c5665eb5b2a44e65461997a12412d4256099edaf3bc5be4ddb9f53f73105aaa3e79
|
checksums.yaml.gz.sig
CHANGED
|
Binary file
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.0.5] - 2025-06-12
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- `S3arch::Dashboard` — mountable Rack application for viewing index stats (records, versions, owner counts)
|
|
8
|
+
- `S3arch::Dashboard::Application` — ERB-rendered HTML dashboard with mobile-friendly layout
|
|
9
|
+
- `S3arch::Holster` — Belt holster integration for convention-over-configuration mounting
|
|
10
|
+
- `S3arch::Routes` — Dispatcher mount DSL compatibility (`#routes` method)
|
|
11
|
+
- `S3arch::Web` — lightweight Rack entry point for Lambda integration
|
|
12
|
+
- `S3archController` — Belt controller for dashboard with Cognito auth gate
|
|
13
|
+
- `Configuration#dashboard_auth` — configurable authentication for dashboard access
|
|
14
|
+
- localStorage-based auth for CloudFront same-origin serving
|
|
15
|
+
|
|
16
|
+
### Changed
|
|
17
|
+
|
|
18
|
+
- Dashboard renders HTML via ERB instead of JSON
|
|
19
|
+
- Scientific notation fix for large record/version numbers in dashboard
|
|
20
|
+
|
|
3
21
|
## [0.0.4] - 2025-06-09
|
|
4
22
|
|
|
5
23
|
### Fixed
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'erb'
|
|
4
|
+
require 'aws-sdk-dynamodb'
|
|
5
|
+
|
|
6
|
+
class S3archController < BeltController::Base
|
|
7
|
+
VIEWS_PATH = File.expand_path('../../lib/s3arch/dashboard/views', __dir__)
|
|
8
|
+
|
|
9
|
+
def index
|
|
10
|
+
@owners = fetch_owners
|
|
11
|
+
html = render_erb('index')
|
|
12
|
+
html_response(html)
|
|
13
|
+
rescue StandardError => e
|
|
14
|
+
@error = e.message
|
|
15
|
+
@owners = []
|
|
16
|
+
html = render_erb('index')
|
|
17
|
+
html_response(html, 500)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def rebuild
|
|
21
|
+
owner_id = params['owner_id']&.strip
|
|
22
|
+
return error_response('owner_id is required', 400) if owner_id.nil? || owner_id.empty?
|
|
23
|
+
|
|
24
|
+
handler = S3arch.configuration.rebuild_handler
|
|
25
|
+
if handler
|
|
26
|
+
handler.call(owner_id)
|
|
27
|
+
else
|
|
28
|
+
S3arch::Indexer.new.rebuild(owner_id)
|
|
29
|
+
end
|
|
30
|
+
success_response(status: 'ok', owner_id: owner_id)
|
|
31
|
+
rescue StandardError => e
|
|
32
|
+
error_response("Failed to rebuild index: #{e.message}", 500)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
private
|
|
36
|
+
|
|
37
|
+
def fetch_owners
|
|
38
|
+
dynamodb = Aws::DynamoDB::Client.new
|
|
39
|
+
config = S3arch.configuration
|
|
40
|
+
items = []
|
|
41
|
+
scan_params = { table_name: config.version_table }
|
|
42
|
+
|
|
43
|
+
loop do
|
|
44
|
+
result = dynamodb.scan(scan_params)
|
|
45
|
+
items.concat(result.items)
|
|
46
|
+
break unless result.last_evaluated_key
|
|
47
|
+
|
|
48
|
+
scan_params[:exclusive_start_key] = result.last_evaluated_key
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
owners = items.map do |item|
|
|
52
|
+
{
|
|
53
|
+
owner_id: item[config.owner_key] || item.values.first,
|
|
54
|
+
version: item['version'],
|
|
55
|
+
record_count: item['record_count'],
|
|
56
|
+
updated_at: item['updated_at']
|
|
57
|
+
}
|
|
58
|
+
end
|
|
59
|
+
owners.sort_by { |o| o[:updated_at].to_s }.reverse
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def render_erb(template)
|
|
63
|
+
path = File.join(VIEWS_PATH, "#{template}.html.erb")
|
|
64
|
+
ERB.new(File.read(path), trim_mode: '-').result(binding)
|
|
65
|
+
end
|
|
66
|
+
end
|
data/lib/s3arch/configuration.rb
CHANGED
|
@@ -42,6 +42,11 @@ module S3arch
|
|
|
42
42
|
# Searcher settings
|
|
43
43
|
attr_accessor :version_ttl, :max_results, :max_cached_dbs, :ephemeral_storage_mb
|
|
44
44
|
|
|
45
|
+
# Custom rebuild handler — proc/lambda that receives owner_id.
|
|
46
|
+
# When set, the controller uses this instead of calling Indexer.new.rebuild directly.
|
|
47
|
+
# Useful for triggering rebuilds via Lambda invocation instead of in-process.
|
|
48
|
+
attr_accessor :rebuild_handler
|
|
49
|
+
|
|
45
50
|
def initialize
|
|
46
51
|
@owner_key = 'user_id'
|
|
47
52
|
@searchable_fields = %w[name description]
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'erb'
|
|
4
|
+
require 'json'
|
|
5
|
+
require 'aws-sdk-dynamodb'
|
|
6
|
+
|
|
7
|
+
module S3arch
|
|
8
|
+
module Dashboard
|
|
9
|
+
class Application
|
|
10
|
+
VIEWS_PATH = File.expand_path('views', __dir__)
|
|
11
|
+
|
|
12
|
+
# Dispatcher mount DSL contract — keep in sync with #call dispatch below.
|
|
13
|
+
def routes
|
|
14
|
+
[
|
|
15
|
+
{ method: :get, path: '/' },
|
|
16
|
+
{ method: :post, path: '/rebuild' }
|
|
17
|
+
]
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def call(env)
|
|
21
|
+
req = Rack::Request.new(env)
|
|
22
|
+
path = req.path_info.sub(%r{^/}, '')
|
|
23
|
+
|
|
24
|
+
case [req.request_method, path]
|
|
25
|
+
when ['GET', ''], %w[GET index]
|
|
26
|
+
index(req)
|
|
27
|
+
when %w[POST rebuild]
|
|
28
|
+
rebuild(req)
|
|
29
|
+
else
|
|
30
|
+
[404, { 'content-type' => 'text/plain' }, ['Not Found']]
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
private
|
|
35
|
+
|
|
36
|
+
def index(req)
|
|
37
|
+
@env = req.env
|
|
38
|
+
@owners = fetch_owners
|
|
39
|
+
html = render('index')
|
|
40
|
+
[200, { 'content-type' => 'text/html' }, [html]]
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def rebuild(req)
|
|
44
|
+
owner_id = req.params['owner_id']&.strip
|
|
45
|
+
if owner_id && !owner_id.empty?
|
|
46
|
+
indexer = S3arch::Indexer.new
|
|
47
|
+
indexer.rebuild(owner_id)
|
|
48
|
+
end
|
|
49
|
+
[303, { 'location' => "#{req.script_name}/" }, []]
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def fetch_owners
|
|
53
|
+
config = S3arch.configuration
|
|
54
|
+
dynamodb = Aws::DynamoDB::Client.new
|
|
55
|
+
items = []
|
|
56
|
+
params = { table_name: config.version_table }
|
|
57
|
+
|
|
58
|
+
loop do
|
|
59
|
+
result = dynamodb.scan(params)
|
|
60
|
+
items.concat(result.items)
|
|
61
|
+
break unless result.last_evaluated_key
|
|
62
|
+
|
|
63
|
+
params[:exclusive_start_key] = result.last_evaluated_key
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
owners = items.map do |item|
|
|
67
|
+
{
|
|
68
|
+
owner_id: item[config.owner_key] || item.values.first,
|
|
69
|
+
version: item['version'],
|
|
70
|
+
record_count: item['record_count'],
|
|
71
|
+
updated_at: item['updated_at']
|
|
72
|
+
}
|
|
73
|
+
end
|
|
74
|
+
owners.sort_by { |o| o[:updated_at].to_s }.reverse
|
|
75
|
+
rescue StandardError => e
|
|
76
|
+
@error = e.message
|
|
77
|
+
[]
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def render(template)
|
|
81
|
+
path = File.join(VIEWS_PATH, "#{template}.html.erb")
|
|
82
|
+
ERB.new(File.read(path), trim_mode: '-').result(binding)
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<title>S3arch Dashboard</title>
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
6
|
+
<script>
|
|
7
|
+
(function() {
|
|
8
|
+
function getIdToken() {
|
|
9
|
+
try {
|
|
10
|
+
for (var i = 0; i < localStorage.length; i++) {
|
|
11
|
+
var key = localStorage.key(i);
|
|
12
|
+
if (key && key.indexOf('.idToken') !== -1) return localStorage.getItem(key);
|
|
13
|
+
}
|
|
14
|
+
} catch(e) {}
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
function isTokenValid(token) {
|
|
18
|
+
try {
|
|
19
|
+
var payload = JSON.parse(atob(token.split('.')[1].replace(/-/g,'+').replace(/_/g,'/')));
|
|
20
|
+
return payload.exp && payload.exp > Date.now() / 1000;
|
|
21
|
+
} catch(e) { return false; }
|
|
22
|
+
}
|
|
23
|
+
var token = getIdToken();
|
|
24
|
+
if (!token || !isTokenValid(token)) {
|
|
25
|
+
window.location.replace('/login');
|
|
26
|
+
}
|
|
27
|
+
})();
|
|
28
|
+
</script>
|
|
29
|
+
<style>
|
|
30
|
+
* { box-sizing: border-box; margin: 0; padding: 0; }
|
|
31
|
+
body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; background: #f5f5f5; color: #333; padding: 1.5rem; }
|
|
32
|
+
h1 { margin-bottom: 1rem; font-size: 1.5rem; }
|
|
33
|
+
.error { background: #fee; border: 1px solid #fcc; padding: 0.75rem; border-radius: 4px; margin-bottom: 1rem; color: #c00; }
|
|
34
|
+
.success { background: #efe; border: 1px solid #cfc; padding: 0.75rem; border-radius: 4px; margin-bottom: 1rem; color: #060; display: none; }
|
|
35
|
+
.meta { font-size: 0.85rem; color: #666; margin-bottom: 1rem; }
|
|
36
|
+
.empty { padding: 2rem; text-align: center; color: #666; }
|
|
37
|
+
|
|
38
|
+
/* Desktop: table */
|
|
39
|
+
table { width: 100%; border-collapse: collapse; background: #fff; border-radius: 6px; overflow: hidden; box-shadow: 0 1px 3px rgba(0,0,0,0.1); }
|
|
40
|
+
th, td { padding: 0.75rem 1rem; text-align: left; border-bottom: 1px solid #eee; }
|
|
41
|
+
th { background: #fafafa; font-weight: 600; font-size: 0.85rem; text-transform: uppercase; letter-spacing: 0.03em; color: #555; }
|
|
42
|
+
tr:last-child td { border-bottom: none; }
|
|
43
|
+
tr:hover td { background: #f9fafb; }
|
|
44
|
+
.btn { border: none; padding: 0.4rem 0.8rem; border-radius: 4px; cursor: pointer; font-size: 0.85rem; font-weight: 500; transition: background 0.15s; }
|
|
45
|
+
.btn-rebuild { background: #2563eb; color: #fff; }
|
|
46
|
+
.btn-rebuild:hover { background: #1d4ed8; }
|
|
47
|
+
.btn-rebuild:disabled { background: #93c5fd; cursor: not-allowed; }
|
|
48
|
+
.owner-id { font-family: "SF Mono", SFMono-Regular, Consolas, monospace; font-size: 0.8rem; }
|
|
49
|
+
|
|
50
|
+
/* Mobile: card layout */
|
|
51
|
+
@media (max-width: 640px) {
|
|
52
|
+
body { padding: 1rem; }
|
|
53
|
+
table, thead, tbody, th, tr, td { display: block; }
|
|
54
|
+
thead { display: none; }
|
|
55
|
+
tr { background: #fff; border-radius: 6px; box-shadow: 0 1px 3px rgba(0,0,0,0.1); margin-bottom: 0.75rem; padding: 0.75rem; }
|
|
56
|
+
tr:hover td { background: transparent; }
|
|
57
|
+
td { padding: 0.25rem 0; border: none; display: flex; justify-content: space-between; align-items: center; }
|
|
58
|
+
td::before { content: attr(data-label); font-weight: 600; font-size: 0.75rem; text-transform: uppercase; color: #555; margin-right: 0.5rem; }
|
|
59
|
+
td:last-child { margin-top: 0.5rem; justify-content: flex-start; }
|
|
60
|
+
td:last-child::before { display: none; }
|
|
61
|
+
.btn { width: 100%; text-align: center; padding: 0.6rem; }
|
|
62
|
+
}
|
|
63
|
+
</style>
|
|
64
|
+
</head>
|
|
65
|
+
<body>
|
|
66
|
+
<h1>S3arch Dashboard</h1>
|
|
67
|
+
<p class="meta"><%= @owners.size %> indexed owner<%= @owners.size == 1 ? '' : 's' %></p>
|
|
68
|
+
|
|
69
|
+
<div id="flash" class="success"></div>
|
|
70
|
+
|
|
71
|
+
<%- if @error -%>
|
|
72
|
+
<div class="error"><strong>Error:</strong> <%= @error %></div>
|
|
73
|
+
<%- end -%>
|
|
74
|
+
|
|
75
|
+
<%- if @owners.any? -%>
|
|
76
|
+
<table>
|
|
77
|
+
<thead>
|
|
78
|
+
<tr>
|
|
79
|
+
<th>Owner</th>
|
|
80
|
+
<th>Version</th>
|
|
81
|
+
<th>Records</th>
|
|
82
|
+
<th>Last Updated</th>
|
|
83
|
+
<th>Actions</th>
|
|
84
|
+
</tr>
|
|
85
|
+
</thead>
|
|
86
|
+
<tbody>
|
|
87
|
+
<%- @owners.each do |owner| -%>
|
|
88
|
+
<tr>
|
|
89
|
+
<td class="owner-id" data-label="Owner"><%= owner[:owner_id] %></td>
|
|
90
|
+
<td data-label="Version"><%= owner[:version].to_i %></td>
|
|
91
|
+
<td data-label="Records"><%= owner[:record_count] ? owner[:record_count].to_i.to_s.gsub(/(\d)(?=(\d{3})+$)/, '\1,') : '—' %></td>
|
|
92
|
+
<td data-label="Updated"><%= owner[:updated_at] || '—' %></td>
|
|
93
|
+
<td>
|
|
94
|
+
<button class="btn btn-rebuild" onclick="rebuild('<%= owner[:owner_id] %>', this)">Recreate SQLite</button>
|
|
95
|
+
</td>
|
|
96
|
+
</tr>
|
|
97
|
+
<%- end -%>
|
|
98
|
+
</tbody>
|
|
99
|
+
</table>
|
|
100
|
+
<%- else -%>
|
|
101
|
+
<div class="empty">No indexed owners found.</div>
|
|
102
|
+
<%- end -%>
|
|
103
|
+
|
|
104
|
+
<script>
|
|
105
|
+
function getIdToken() {
|
|
106
|
+
try {
|
|
107
|
+
for (var i = 0; i < localStorage.length; i++) {
|
|
108
|
+
var key = localStorage.key(i);
|
|
109
|
+
if (key && key.indexOf('.idToken') !== -1) return localStorage.getItem(key);
|
|
110
|
+
}
|
|
111
|
+
} catch(e) {}
|
|
112
|
+
return null;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function rebuild(ownerId, btn) {
|
|
116
|
+
btn.disabled = true;
|
|
117
|
+
btn.textContent = 'Rebuilding\u2026';
|
|
118
|
+
var headers = { 'Content-Type': 'application/json' };
|
|
119
|
+
var token = getIdToken();
|
|
120
|
+
if (token) headers['Authorization'] = 'Bearer ' + token;
|
|
121
|
+
|
|
122
|
+
fetch(window.location.pathname.replace(/\/$/, '') + '/rebuild', {
|
|
123
|
+
method: 'POST',
|
|
124
|
+
headers: headers,
|
|
125
|
+
body: JSON.stringify({ owner_id: ownerId })
|
|
126
|
+
}).then(function(r) { return r.json(); }).then(function(data) {
|
|
127
|
+
btn.textContent = 'Recreate SQLite';
|
|
128
|
+
btn.disabled = false;
|
|
129
|
+
var flash = document.getElementById('flash');
|
|
130
|
+
if (data.status === 'ok') {
|
|
131
|
+
flash.className = 'success';
|
|
132
|
+
flash.textContent = 'Rebuild triggered for ' + ownerId;
|
|
133
|
+
flash.style.display = 'block';
|
|
134
|
+
} else {
|
|
135
|
+
flash.className = 'error';
|
|
136
|
+
flash.textContent = data.error || 'Rebuild failed';
|
|
137
|
+
flash.style.display = 'block';
|
|
138
|
+
}
|
|
139
|
+
}).catch(function(e) {
|
|
140
|
+
btn.textContent = 'Recreate SQLite';
|
|
141
|
+
btn.disabled = false;
|
|
142
|
+
var flash = document.getElementById('flash');
|
|
143
|
+
flash.className = 'error';
|
|
144
|
+
flash.textContent = 'Request failed: ' + e.message;
|
|
145
|
+
flash.style.display = 'block';
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
</script>
|
|
149
|
+
</body>
|
|
150
|
+
</html>
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module S3arch
|
|
4
|
+
# Lightweight route manifest for Dispatcher mount DSL.
|
|
5
|
+
# No heavy dependencies — safe to load in parse-only contexts.
|
|
6
|
+
module Routes
|
|
7
|
+
def self.routes
|
|
8
|
+
[
|
|
9
|
+
{ method: :get, path: '/' },
|
|
10
|
+
{ method: :post, path: '/rebuild' }
|
|
11
|
+
]
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
data/lib/s3arch/version.rb
CHANGED
data/lib/s3arch/web.rb
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Lightweight S3arch load for web/API contexts (no SQLite dependency).
|
|
4
|
+
# Provides configuration, holster registration, and routes only.
|
|
5
|
+
require_relative 'version'
|
|
6
|
+
require_relative 'configuration'
|
|
7
|
+
require_relative 'routes'
|
|
8
|
+
require_relative 'holster'
|
|
9
|
+
|
|
10
|
+
module S3arch
|
|
11
|
+
class Error < StandardError; end
|
|
12
|
+
|
|
13
|
+
class << self
|
|
14
|
+
def configuration
|
|
15
|
+
@configuration ||= Configuration.new
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def configure
|
|
19
|
+
yield(configuration)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def reset_configuration!
|
|
23
|
+
@configuration = Configuration.new
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
data/lib/s3arch.rb
CHANGED
|
@@ -6,6 +6,11 @@ require_relative 's3arch/tokenizer'
|
|
|
6
6
|
require_relative 's3arch/indexer'
|
|
7
7
|
require_relative 's3arch/searcher'
|
|
8
8
|
require_relative 's3arch/handler'
|
|
9
|
+
require_relative 's3arch/routes'
|
|
10
|
+
require_relative 's3arch/dashboard'
|
|
11
|
+
|
|
12
|
+
# Register as a Belt holster when Belt is loaded
|
|
13
|
+
require_relative 's3arch/holster' if defined?(Belt::Holster)
|
|
9
14
|
|
|
10
15
|
module S3arch
|
|
11
16
|
class Error < StandardError; end
|
data.tar.gz.sig
CHANGED
|
Binary file
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: s3arch
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.0.
|
|
4
|
+
version: 0.0.5
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Adam Dalton
|
|
@@ -64,6 +64,20 @@ dependencies:
|
|
|
64
64
|
- - "~>"
|
|
65
65
|
- !ruby/object:Gem::Version
|
|
66
66
|
version: '1.0'
|
|
67
|
+
- !ruby/object:Gem::Dependency
|
|
68
|
+
name: rack
|
|
69
|
+
requirement: !ruby/object:Gem::Requirement
|
|
70
|
+
requirements:
|
|
71
|
+
- - ">="
|
|
72
|
+
- !ruby/object:Gem::Version
|
|
73
|
+
version: '2.0'
|
|
74
|
+
type: :runtime
|
|
75
|
+
prerelease: false
|
|
76
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
77
|
+
requirements:
|
|
78
|
+
- - ">="
|
|
79
|
+
- !ruby/object:Gem::Version
|
|
80
|
+
version: '2.0'
|
|
67
81
|
- !ruby/object:Gem::Dependency
|
|
68
82
|
name: sqlite3
|
|
69
83
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -78,8 +92,8 @@ dependencies:
|
|
|
78
92
|
- - "~>"
|
|
79
93
|
- !ruby/object:Gem::Version
|
|
80
94
|
version: '2.0'
|
|
81
|
-
description: Per-owner SQLite FTS5 indexes stored on S3, queried from Lambda /tmp
|
|
82
|
-
|
|
95
|
+
description: Per-owner SQLite FTS5 indexes stored on S3, queried from Lambda /tmp
|
|
96
|
+
with version tracking.
|
|
83
97
|
email:
|
|
84
98
|
- adam@stowzilla.com
|
|
85
99
|
executables: []
|
|
@@ -90,13 +104,22 @@ files:
|
|
|
90
104
|
- LICENSE.txt
|
|
91
105
|
- README.md
|
|
92
106
|
- certs/stowzilla.pem
|
|
107
|
+
- infrastructure/routes.tf.rb
|
|
108
|
+
- infrastructure/schema.tf.rb
|
|
109
|
+
- lambda/controllers/s3arch_controller.rb
|
|
93
110
|
- lib/s3arch.rb
|
|
94
111
|
- lib/s3arch/configuration.rb
|
|
112
|
+
- lib/s3arch/dashboard.rb
|
|
113
|
+
- lib/s3arch/dashboard/application.rb
|
|
114
|
+
- lib/s3arch/dashboard/views/index.html.erb
|
|
95
115
|
- lib/s3arch/handler.rb
|
|
116
|
+
- lib/s3arch/holster.rb
|
|
96
117
|
- lib/s3arch/indexer.rb
|
|
118
|
+
- lib/s3arch/routes.rb
|
|
97
119
|
- lib/s3arch/searcher.rb
|
|
98
120
|
- lib/s3arch/tokenizer.rb
|
|
99
121
|
- lib/s3arch/version.rb
|
|
122
|
+
- lib/s3arch/web.rb
|
|
100
123
|
homepage: https://github.com/stowzilla/s3arch
|
|
101
124
|
licenses:
|
|
102
125
|
- MIT
|
metadata.gz.sig
CHANGED
|
Binary file
|