s3arch 0.0.5 → 0.0.6

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6e0ba51260081a3de075c6e14332909892693b64dce6eb1a3e52f7b1f145b537
4
- data.tar.gz: 7553e90741ef8a1cc6c72b55bb9239c0e238da2a09916d34e8edf18780942a24
3
+ metadata.gz: f15baec2213fb6a5cee584447843884e1b9aa5e1bf650d500c53cd6c17e69539
4
+ data.tar.gz: d00b7d3345ebf462c5ef0a450452502a818c2dd6969c34e82bfc5d763dc9cd7f
5
5
  SHA512:
6
- metadata.gz: 26e0cd3ff75ea9aff46dfd28a5978db557b26cef4780d966345b14fdb0b023bc9a6d22809c30c1422ac967aea3cbcc7bf18a75e94ea07d56af13d0f96d2d12e2
7
- data.tar.gz: bf5c5b19de20e235f95427218b8beb0ee5ab03b4270bf31cbe38ca2f6f420c5665eb5b2a44e65461997a12412d4256099edaf3bc5be4ddb9f53f73105aaa3e79
6
+ metadata.gz: 3fd7108161529a4d4d23ffcd49e483d944064ea6364438470f65859c86382f43a611e6867a4d69981772c76bc6e244d306a256dbb1ac6607622cf787d78551e9
7
+ data.tar.gz: a9895ba3ef76d2720330633cc6eeb44e6d70d9a2461d4602eea136d8de19f4032397e1195dba91c1d0160a95a19bc69ec8123d2dd25581683da47a547717cd3e
checksums.yaml.gz.sig CHANGED
Binary file
@@ -1,20 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'erb'
4
3
  require 'aws-sdk-dynamodb'
5
4
 
6
5
  class S3archController < BeltController::Base
7
- VIEWS_PATH = File.expand_path('../../lib/s3arch/dashboard/views', __dir__)
8
-
9
6
  def index
10
- @owners = fetch_owners
11
- html = render_erb('index')
12
- html_response(html)
7
+ owners = fetch_owners
8
+ success_response(owners: owners)
13
9
  rescue StandardError => e
14
- @error = e.message
15
- @owners = []
16
- html = render_erb('index')
17
- html_response(html, 500)
10
+ error_response("Failed to load owners: #{e.message}", 500)
18
11
  end
19
12
 
20
13
  def rebuild
@@ -58,9 +51,4 @@ class S3archController < BeltController::Base
58
51
  end
59
52
  owners.sort_by { |o| o[:updated_at].to_s }.reverse
60
53
  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
54
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module S3arch
4
- VERSION = '0.0.5'
4
+ VERSION = '0.0.6'
5
5
  end
data/lib/s3arch/web.rb CHANGED
@@ -1,11 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Lightweight S3arch load for web/API contexts (no SQLite dependency).
4
- # Provides configuration, holster registration, and routes only.
4
+ # Provides configuration and routes only.
5
5
  require_relative 'version'
6
6
  require_relative 'configuration'
7
7
  require_relative 'routes'
8
- require_relative 'holster'
9
8
 
10
9
  module S3arch
11
10
  class Error < StandardError; end
data/lib/s3arch.rb CHANGED
@@ -7,10 +7,6 @@ require_relative 's3arch/indexer'
7
7
  require_relative 's3arch/searcher'
8
8
  require_relative 's3arch/handler'
9
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)
14
10
 
15
11
  module S3arch
16
12
  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.5
4
+ version: 0.0.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Adam Dalton
@@ -109,11 +109,7 @@ files:
109
109
  - lambda/controllers/s3arch_controller.rb
110
110
  - lib/s3arch.rb
111
111
  - lib/s3arch/configuration.rb
112
- - lib/s3arch/dashboard.rb
113
- - lib/s3arch/dashboard/application.rb
114
- - lib/s3arch/dashboard/views/index.html.erb
115
112
  - lib/s3arch/handler.rb
116
- - lib/s3arch/holster.rb
117
113
  - lib/s3arch/indexer.rb
118
114
  - lib/s3arch/routes.rb
119
115
  - lib/s3arch/searcher.rb
metadata.gz.sig CHANGED
Binary file
@@ -1,86 +0,0 @@
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
@@ -1,150 +0,0 @@
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>
@@ -1,13 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'json'
4
- require 'erb'
5
- require_relative 'dashboard/application'
6
-
7
- module S3arch
8
- module Dashboard
9
- def self.app
10
- Application.new
11
- end
12
- end
13
- end
@@ -1,7 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module S3arch
4
- class Holster < Belt::Holster
5
- self.gem_root = File.expand_path('../..', __dir__)
6
- end
7
- end