@hatk/hatk 0.0.1-alpha.9 → 0.0.1-alpha.92

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 (218) hide show
  1. package/dist/adapter.d.ts +19 -0
  2. package/dist/adapter.d.ts.map +1 -0
  3. package/dist/adapter.js +113 -0
  4. package/dist/backfill.d.ts +29 -2
  5. package/dist/backfill.d.ts.map +1 -1
  6. package/dist/backfill.js +142 -51
  7. package/dist/car.d.ts +20 -0
  8. package/dist/car.d.ts.map +1 -1
  9. package/dist/car.js +108 -0
  10. package/dist/cli.js +247 -1043
  11. package/dist/config.d.ts +145 -1
  12. package/dist/config.d.ts.map +1 -1
  13. package/dist/config.js +61 -8
  14. package/dist/database/adapter-factory.d.ts +6 -0
  15. package/dist/database/adapter-factory.d.ts.map +1 -0
  16. package/dist/database/adapter-factory.js +20 -0
  17. package/dist/database/adapters/duckdb-search.d.ts +12 -0
  18. package/dist/database/adapters/duckdb-search.d.ts.map +1 -0
  19. package/dist/database/adapters/duckdb-search.js +27 -0
  20. package/dist/database/adapters/duckdb.d.ts +25 -0
  21. package/dist/database/adapters/duckdb.d.ts.map +1 -0
  22. package/dist/database/adapters/duckdb.js +161 -0
  23. package/dist/database/adapters/sqlite-search.d.ts +16 -0
  24. package/dist/database/adapters/sqlite-search.d.ts.map +1 -0
  25. package/dist/database/adapters/sqlite-search.js +76 -0
  26. package/dist/database/adapters/sqlite.d.ts +18 -0
  27. package/dist/database/adapters/sqlite.d.ts.map +1 -0
  28. package/dist/database/adapters/sqlite.js +88 -0
  29. package/dist/{db.d.ts → database/db.d.ts} +68 -6
  30. package/dist/database/db.d.ts.map +1 -0
  31. package/dist/database/db.js +1775 -0
  32. package/dist/database/dialect.d.ts +45 -0
  33. package/dist/database/dialect.d.ts.map +1 -0
  34. package/dist/database/dialect.js +72 -0
  35. package/dist/{fts.d.ts → database/fts.d.ts} +7 -0
  36. package/dist/database/fts.d.ts.map +1 -0
  37. package/dist/{fts.js → database/fts.js} +122 -34
  38. package/dist/database/index.d.ts +7 -0
  39. package/dist/database/index.d.ts.map +1 -0
  40. package/dist/database/index.js +6 -0
  41. package/dist/database/ports.d.ts +50 -0
  42. package/dist/database/ports.d.ts.map +1 -0
  43. package/dist/database/ports.js +1 -0
  44. package/dist/{schema.d.ts → database/schema.d.ts} +16 -3
  45. package/dist/database/schema.d.ts.map +1 -0
  46. package/dist/{schema.js → database/schema.js} +126 -44
  47. package/dist/dev-entry.d.ts +8 -0
  48. package/dist/dev-entry.d.ts.map +1 -0
  49. package/dist/dev-entry.js +127 -0
  50. package/dist/feeds.d.ts +26 -8
  51. package/dist/feeds.d.ts.map +1 -1
  52. package/dist/feeds.js +72 -16
  53. package/dist/hooks.d.ts +102 -0
  54. package/dist/hooks.d.ts.map +1 -0
  55. package/dist/hooks.js +186 -0
  56. package/dist/hydrate.d.ts +49 -6
  57. package/dist/hydrate.d.ts.map +1 -1
  58. package/dist/hydrate.js +21 -20
  59. package/dist/indexer.d.ts +167 -3
  60. package/dist/indexer.d.ts.map +1 -1
  61. package/dist/indexer.js +556 -94
  62. package/dist/jetstream.d.ts +118 -0
  63. package/dist/jetstream.d.ts.map +1 -0
  64. package/dist/jetstream.js +225 -0
  65. package/dist/labels.d.ts +36 -0
  66. package/dist/labels.d.ts.map +1 -1
  67. package/dist/labels.js +71 -6
  68. package/dist/lex-types.d.ts +2 -0
  69. package/dist/lex-types.d.ts.map +1 -1
  70. package/dist/lexicon-resolve.d.ts.map +1 -1
  71. package/dist/lexicon-resolve.js +27 -112
  72. package/dist/lexicons/com/atproto/label/defs.json +75 -0
  73. package/dist/lexicons/com/atproto/moderation/defs.json +30 -0
  74. package/dist/lexicons/com/atproto/repo/strongRef.json +21 -0
  75. package/dist/lexicons/dev/hatk/applyWrites.json +87 -0
  76. package/dist/lexicons/dev/hatk/createRecord.json +40 -0
  77. package/dist/lexicons/dev/hatk/createReport.json +48 -0
  78. package/dist/lexicons/dev/hatk/deleteRecord.json +25 -0
  79. package/dist/lexicons/dev/hatk/describeCollections.json +41 -0
  80. package/dist/lexicons/dev/hatk/describeFeeds.json +29 -0
  81. package/dist/lexicons/dev/hatk/describeLabels.json +45 -0
  82. package/dist/lexicons/dev/hatk/getFeed.json +30 -0
  83. package/dist/lexicons/dev/hatk/getPreferences.json +19 -0
  84. package/dist/lexicons/dev/hatk/getRecord.json +26 -0
  85. package/dist/lexicons/dev/hatk/getRecords.json +32 -0
  86. package/dist/lexicons/dev/hatk/putPreference.json +28 -0
  87. package/dist/lexicons/dev/hatk/putRecord.json +41 -0
  88. package/dist/lexicons/dev/hatk/searchRecords.json +32 -0
  89. package/dist/lexicons/dev/hatk/uploadBlob.json +23 -0
  90. package/dist/logger.d.ts +29 -0
  91. package/dist/logger.d.ts.map +1 -1
  92. package/dist/logger.js +29 -0
  93. package/dist/main.js +198 -75
  94. package/dist/mst.d.ts +15 -0
  95. package/dist/mst.d.ts.map +1 -1
  96. package/dist/mst.js +13 -0
  97. package/dist/oauth/db.d.ts +16 -1
  98. package/dist/oauth/db.d.ts.map +1 -1
  99. package/dist/oauth/db.js +74 -19
  100. package/dist/oauth/discovery.d.ts +10 -0
  101. package/dist/oauth/discovery.d.ts.map +1 -1
  102. package/dist/oauth/discovery.js +54 -2
  103. package/dist/oauth/server.d.ts +93 -1
  104. package/dist/oauth/server.d.ts.map +1 -1
  105. package/dist/oauth/server.js +416 -39
  106. package/dist/oauth/service-describe.d.ts +42 -0
  107. package/dist/oauth/service-describe.d.ts.map +1 -0
  108. package/dist/oauth/service-describe.js +108 -0
  109. package/dist/oauth/session.d.ts +32 -0
  110. package/dist/oauth/session.d.ts.map +1 -0
  111. package/dist/oauth/session.js +131 -0
  112. package/dist/opengraph.d.ts +10 -0
  113. package/dist/opengraph.d.ts.map +1 -1
  114. package/dist/opengraph.js +94 -42
  115. package/dist/pds-proxy.d.ts +82 -0
  116. package/dist/pds-proxy.d.ts.map +1 -0
  117. package/dist/pds-proxy.js +356 -0
  118. package/dist/private-collections.d.ts +13 -0
  119. package/dist/private-collections.d.ts.map +1 -0
  120. package/dist/private-collections.js +27 -0
  121. package/dist/push.d.ts +54 -0
  122. package/dist/push.d.ts.map +1 -0
  123. package/dist/push.js +367 -0
  124. package/dist/renderer.d.ts +27 -0
  125. package/dist/renderer.d.ts.map +1 -0
  126. package/dist/renderer.js +46 -0
  127. package/dist/resolve-hatk.d.ts +6 -0
  128. package/dist/resolve-hatk.d.ts.map +1 -0
  129. package/dist/resolve-hatk.js +20 -0
  130. package/dist/response.d.ts +16 -0
  131. package/dist/response.d.ts.map +1 -0
  132. package/dist/response.js +69 -0
  133. package/dist/scanner.d.ts +21 -0
  134. package/dist/scanner.d.ts.map +1 -0
  135. package/dist/scanner.js +88 -0
  136. package/dist/seed.d.ts +19 -0
  137. package/dist/seed.d.ts.map +1 -1
  138. package/dist/seed.js +43 -4
  139. package/dist/server-init.d.ts +8 -0
  140. package/dist/server-init.d.ts.map +1 -0
  141. package/dist/server-init.js +62 -0
  142. package/dist/server.d.ts +34 -3
  143. package/dist/server.d.ts.map +1 -1
  144. package/dist/server.js +1032 -649
  145. package/dist/setup.d.ts +28 -1
  146. package/dist/setup.d.ts.map +1 -1
  147. package/dist/setup.js +50 -3
  148. package/dist/spaces/blob.d.ts +51 -0
  149. package/dist/spaces/blob.d.ts.map +1 -0
  150. package/dist/spaces/blob.js +111 -0
  151. package/dist/spaces/credential.d.ts +62 -0
  152. package/dist/spaces/credential.d.ts.map +1 -0
  153. package/dist/spaces/credential.js +184 -0
  154. package/dist/spaces/engine.d.ts +97 -0
  155. package/dist/spaces/engine.d.ts.map +1 -0
  156. package/dist/spaces/engine.js +559 -0
  157. package/dist/spaces/guard.d.ts +41 -0
  158. package/dist/spaces/guard.d.ts.map +1 -0
  159. package/dist/spaces/guard.js +79 -0
  160. package/dist/spaces/identity.d.ts +37 -0
  161. package/dist/spaces/identity.d.ts.map +1 -0
  162. package/dist/spaces/identity.js +88 -0
  163. package/dist/spaces/index.d.ts +55 -0
  164. package/dist/spaces/index.d.ts.map +1 -0
  165. package/dist/spaces/index.js +133 -0
  166. package/dist/spaces/notify.d.ts +51 -0
  167. package/dist/spaces/notify.d.ts.map +1 -0
  168. package/dist/spaces/notify.js +121 -0
  169. package/dist/spaces/records.d.ts +37 -0
  170. package/dist/spaces/records.d.ts.map +1 -0
  171. package/dist/spaces/records.js +63 -0
  172. package/dist/spaces/store.d.ts +51 -0
  173. package/dist/spaces/store.d.ts.map +1 -0
  174. package/dist/spaces/store.js +99 -0
  175. package/dist/spaces/uri.d.ts +60 -0
  176. package/dist/spaces/uri.d.ts.map +1 -0
  177. package/dist/spaces/uri.js +97 -0
  178. package/dist/spaces/verify.d.ts +39 -0
  179. package/dist/spaces/verify.d.ts.map +1 -0
  180. package/dist/spaces/verify.js +87 -0
  181. package/dist/spaces/viewer.d.ts +51 -0
  182. package/dist/spaces/viewer.d.ts.map +1 -0
  183. package/dist/spaces/viewer.js +167 -0
  184. package/dist/spaces/visibility.d.ts +57 -0
  185. package/dist/spaces/visibility.d.ts.map +1 -0
  186. package/dist/spaces/visibility.js +81 -0
  187. package/dist/templates/feed.tpl +18 -0
  188. package/dist/templates/hook.tpl +5 -0
  189. package/dist/templates/label.tpl +15 -0
  190. package/dist/templates/og.tpl +17 -0
  191. package/dist/templates/seed.tpl +11 -0
  192. package/dist/templates/setup.tpl +5 -0
  193. package/dist/templates/test-feed.tpl +19 -0
  194. package/dist/templates/test-xrpc.tpl +19 -0
  195. package/dist/templates/xrpc.tpl +53 -0
  196. package/dist/test.d.ts +3 -1
  197. package/dist/test.d.ts.map +1 -1
  198. package/dist/test.js +60 -36
  199. package/dist/views.js +1 -1
  200. package/dist/vite-plugin.d.ts +1 -1
  201. package/dist/vite-plugin.d.ts.map +1 -1
  202. package/dist/vite-plugin.js +254 -66
  203. package/dist/xrpc.d.ts +101 -12
  204. package/dist/xrpc.d.ts.map +1 -1
  205. package/dist/xrpc.js +255 -55
  206. package/package.json +21 -9
  207. package/public/admin-auth.js +271 -306
  208. package/public/admin.html +177 -61
  209. package/dist/db.d.ts.map +0 -1
  210. package/dist/db.js +0 -1361
  211. package/dist/fts.d.ts.map +0 -1
  212. package/dist/oauth/hooks.d.ts +0 -10
  213. package/dist/oauth/hooks.d.ts.map +0 -1
  214. package/dist/oauth/hooks.js +0 -40
  215. package/dist/schema.d.ts.map +0 -1
  216. package/dist/test-browser.d.ts +0 -14
  217. package/dist/test-browser.d.ts.map +0 -1
  218. package/dist/test-browser.js +0 -26
package/public/admin.html CHANGED
@@ -6,10 +6,20 @@
6
6
  <title>Admin</title>
7
7
  <link rel="preconnect" href="https://fonts.googleapis.com" />
8
8
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
9
+ <!-- Loaded off the critical path: media="print" keeps it from blocking the
10
+ first render, and the system-ui/Menlo fallbacks carry until it swaps in. -->
9
11
  <link
10
12
  href="https://fonts.googleapis.com/css2?family=DM+Mono:wght@400;500&family=Figtree:wght@400;500;600;700&display=swap"
11
13
  rel="stylesheet"
14
+ media="print"
15
+ onload="this.media = 'all'"
12
16
  />
17
+ <noscript>
18
+ <link
19
+ href="https://fonts.googleapis.com/css2?family=DM+Mono:wght@400;500&family=Figtree:wght@400;500;600;700&display=swap"
20
+ rel="stylesheet"
21
+ />
22
+ </noscript>
13
23
  <style>
14
24
  *,
15
25
  *::before,
@@ -783,23 +793,6 @@
783
793
  font-size: 1rem;
784
794
  }
785
795
 
786
- /* ── Schema ── */
787
- .schema-pre {
788
- font-family: var(--mono);
789
- font-size: 0.8rem;
790
- line-height: 1.6;
791
- padding: 1rem;
792
- margin: 0;
793
- background: var(--bg-recessed);
794
- border-radius: 0 0 6px 6px;
795
- white-space: pre-wrap;
796
- word-break: break-word;
797
- color: var(--text);
798
- overflow-x: auto;
799
- }
800
- .schema-section {
801
- margin-bottom: 1.5rem;
802
- }
803
796
  .loading {
804
797
  color: var(--text-3);
805
798
  font-size: 0.9375rem;
@@ -1220,7 +1213,7 @@
1220
1213
  <button class="tab active" data-tab="overview">Overview</button>
1221
1214
  <button class="tab" data-tab="repos">Repos</button>
1222
1215
  <button class="tab" data-tab="content">Content</button>
1223
- <button class="tab" data-tab="schema">Schema</button>
1216
+ <button class="tab" data-tab="reports">Reports</button>
1224
1217
  </nav>
1225
1218
 
1226
1219
  <!-- Overview -->
@@ -1277,11 +1270,6 @@
1277
1270
  <div id="repos-results"><div class="loading">Loading</div></div>
1278
1271
  </div>
1279
1272
 
1280
- <!-- Schema -->
1281
- <div class="tab-panel" id="panel-schema">
1282
- <div id="schema-results"><div class="loading">Loading</div></div>
1283
- </div>
1284
-
1285
1273
  <!-- Content -->
1286
1274
  <div class="tab-panel" id="panel-content">
1287
1275
  <div class="search-bar">
@@ -1299,6 +1287,21 @@
1299
1287
  <div class="loading">Loading</div>
1300
1288
  </div>
1301
1289
  </div>
1290
+
1291
+ <!-- Reports -->
1292
+ <div class="tab-panel" id="panel-reports">
1293
+ <div class="search-bar">
1294
+ <select class="search-input" id="reports-status" style="max-width: 200px">
1295
+ <option value="open">Open</option>
1296
+ <option value="resolved">Resolved</option>
1297
+ <option value="dismissed">Dismissed</option>
1298
+ </select>
1299
+ <select class="search-input" id="reports-label-filter" style="max-width: 200px">
1300
+ <option value="">All labels</option>
1301
+ </select>
1302
+ </div>
1303
+ <div id="reports-results"></div>
1304
+ </div>
1302
1305
  </div>
1303
1306
 
1304
1307
  <!-- Bottom nav (mobile) -->
@@ -1307,7 +1310,7 @@
1307
1310
  <button class="bnav-btn active" data-tab="overview">Overview</button>
1308
1311
  <button class="bnav-btn" data-tab="repos">Repos</button>
1309
1312
  <button class="bnav-btn" data-tab="content">Content</button>
1310
- <button class="bnav-btn" data-tab="schema">Schema</button>
1313
+ <button class="bnav-btn" data-tab="reports">Reports</button>
1311
1314
  </div>
1312
1315
  </div>
1313
1316
  </div>
@@ -1325,6 +1328,8 @@
1325
1328
 
1326
1329
  window.auth = auth
1327
1330
  let labelDefinitions = []
1331
+ // Started during boot so the overview's data is in flight while we auth
1332
+ let overviewPrefetch = null
1328
1333
 
1329
1334
  function toast(msg, type = '') {
1330
1335
  const el = document.createElement('div')
@@ -1404,8 +1409,17 @@
1404
1409
  }
1405
1410
  loginScreen.style.display = 'none'
1406
1411
 
1412
+ // Fire these together — awaiting them one at a time puts three round
1413
+ // trips in front of the first render.
1414
+ const whoamiPromise = api('/admin/whoami')
1415
+ const definitionsPromise = api('/admin/labels/definitions').catch(() => null)
1416
+ if (getURLState().tab === 'overview') {
1417
+ overviewPrefetch = api('/admin/info')
1418
+ overviewPrefetch.catch(() => {}) // loadOverview reports the failure
1419
+ }
1420
+
1407
1421
  try {
1408
- const whoami = await api('/admin/whoami')
1422
+ const whoami = await whoamiPromise
1409
1423
  document.getElementById('viewer-did').textContent = whoami.did
1410
1424
  } catch (e) {
1411
1425
  document.getElementById('error-msg').textContent =
@@ -1416,10 +1430,7 @@
1416
1430
  return
1417
1431
  }
1418
1432
 
1419
- try {
1420
- const result = await api('/admin/labels/definitions')
1421
- labelDefinitions = result.definitions || []
1422
- } catch {}
1433
+ labelDefinitions = (await definitionsPromise)?.definitions || []
1423
1434
 
1424
1435
  appEl.classList.add('visible')
1425
1436
  restoreFromURL()
@@ -1490,8 +1501,8 @@
1490
1501
  document.getElementById(`panel-${tab}`).classList.add('active')
1491
1502
  if (tab === 'overview') loadOverview()
1492
1503
  if (tab === 'repos') loadRepos()
1493
- if (tab === 'schema') loadSchema()
1494
1504
  if (tab === 'content') loadContent()
1505
+ if (tab === 'reports') loadReports()
1495
1506
  if (push) pushURL({ tab, status: '', q: '', offset: 0, cq: '' })
1496
1507
  }
1497
1508
 
@@ -1506,7 +1517,9 @@
1506
1517
 
1507
1518
  async function loadOverview() {
1508
1519
  try {
1509
- const info = await api('/admin/info')
1520
+ const pending = overviewPrefetch
1521
+ overviewPrefetch = null
1522
+ const info = await (pending || api('/admin/info'))
1510
1523
  const statusCards = document.getElementById('status-cards')
1511
1524
  const repoStatuses = info.repos || {}
1512
1525
  const total = Object.values(repoStatuses).reduce((a, b) => a + b, 0)
@@ -1518,6 +1531,7 @@
1518
1531
  <div class="stat-card"><div class="stat-label">Pending</div><div class="stat-value yellow">${fmt(repoStatuses.pending)}</div></div>
1519
1532
  <div class="stat-card"><div class="stat-label">Failed</div><div class="stat-value red">${fmt(repoStatuses.failed)}</div></div>
1520
1533
  <div class="stat-card"><div class="stat-label">Taken Down</div><div class="stat-value red">${fmt(repoStatuses.takendown)}</div></div>
1534
+ ${info.openReports > 0 ? `<div class="stat-card" style="cursor:pointer" onclick="activateTab('reports')"><div class="stat-label">Open Reports</div><div class="stat-value yellow">${fmt(info.openReports)}</div></div>` : ''}
1521
1535
  `
1522
1536
 
1523
1537
  const collectionCards = document.getElementById('collection-cards')
@@ -1599,36 +1613,6 @@
1599
1613
  }
1600
1614
  })
1601
1615
 
1602
- // ── Schema ──
1603
-
1604
- async function loadSchema() {
1605
- const container = document.getElementById('schema-results')
1606
- try {
1607
- const data = await api('/admin/schema')
1608
- let html = ''
1609
-
1610
- // Lexicons section
1611
- if (data.lexicons && data.lexicons.length) {
1612
- html += '<div class="schema-section"><div class="section-label">Lexicons</div>'
1613
- for (const lex of data.lexicons) {
1614
- html += `<div class="card" style="margin-bottom:0.5rem;"><div style="font-family:var(--mono);font-size:0.8rem;font-weight:600;padding:0.5rem 0.75rem;border-bottom:1px solid var(--border);">${escapeHtml(lex.nsid)}</div><pre class="schema-pre">${escapeHtml(JSON.stringify(lex.lexicon, null, 2))}</pre></div>`
1615
- }
1616
- html += '</div>'
1617
- }
1618
-
1619
- // DDL section
1620
- if (data.ddl) {
1621
- html += '<div class="schema-section"><div class="section-label">Tables (DuckDB DDL)</div>'
1622
- html += `<div class="card"><pre class="schema-pre">${escapeHtml(data.ddl)}</pre></div>`
1623
- html += '</div>'
1624
- }
1625
-
1626
- container.innerHTML = html || '<div class="empty-state">No schema found</div>'
1627
- } catch (e) {
1628
- container.innerHTML = `<div class="empty-state">${escapeHtml(e.message)}</div>`
1629
- }
1630
- }
1631
-
1632
1616
  // ── Repos ──
1633
1617
 
1634
1618
  let reposLoaded = false
@@ -2161,6 +2145,138 @@
2161
2145
  })
2162
2146
  })
2163
2147
  }
2148
+
2149
+ // ── Reports ──
2150
+
2151
+ const reportsPage = { limit: 50, offset: 0 }
2152
+
2153
+ function populateReportsLabelFilter() {
2154
+ const select = document.getElementById('reports-label-filter')
2155
+ const current = select.value
2156
+ select.innerHTML =
2157
+ '<option value="">All labels</option>' +
2158
+ labelDefinitions.map((d) => `<option value="${d.identifier}">${d.identifier}</option>`).join('')
2159
+ select.value = current
2160
+ }
2161
+
2162
+ document.getElementById('reports-status').addEventListener('change', () => {
2163
+ reportsPage.offset = 0
2164
+ loadReports()
2165
+ })
2166
+ document.getElementById('reports-label-filter').addEventListener('change', () => {
2167
+ reportsPage.offset = 0
2168
+ loadReports()
2169
+ })
2170
+
2171
+ async function loadReports() {
2172
+ populateReportsLabelFilter()
2173
+ const status = document.getElementById('reports-status').value
2174
+ const label = document.getElementById('reports-label-filter').value
2175
+ const container = document.getElementById('reports-results')
2176
+ container.innerHTML = '<div class="loading">Loading</div>'
2177
+ try {
2178
+ let url = `/admin/reports?status=${status}&limit=${reportsPage.limit}&offset=${reportsPage.offset}`
2179
+ if (label) url += `&label=${encodeURIComponent(label)}`
2180
+ const result = await api(url)
2181
+ renderReports(result.reports || [], result.total)
2182
+ } catch (e) {
2183
+ container.innerHTML = `<div class="empty-state">${escapeHtml(e.message)}</div>`
2184
+ }
2185
+ }
2186
+
2187
+ function renderReports(reports, total) {
2188
+ const container = document.getElementById('reports-results')
2189
+ if (!reports.length) {
2190
+ container.innerHTML = '<div class="empty-state">No reports found</div>'
2191
+ return
2192
+ }
2193
+
2194
+ const showPagination = total != null && total > reportsPage.limit
2195
+ const paginationHtml = showPagination
2196
+ ? `
2197
+ <div class="pagination">
2198
+ <span>${reportsPage.offset + 1}\u2013${Math.min(reportsPage.offset + reportsPage.limit, total)} of ${total.toLocaleString()}</span>
2199
+ <div class="pagination-buttons">
2200
+ <button class="btn btn-sm" data-reports-page="prev" ${reportsPage.offset === 0 ? 'disabled' : ''}>Prev</button>
2201
+ <button class="btn btn-sm" data-reports-page="next" ${reportsPage.offset + reportsPage.limit >= total ? 'disabled' : ''}>Next</button>
2202
+ </div>
2203
+ </div>
2204
+ `
2205
+ : ''
2206
+
2207
+ const countLabel =
2208
+ total != null
2209
+ ? `${total.toLocaleString()} report${total !== 1 ? 's' : ''}`
2210
+ : `${reports.length} result${reports.length !== 1 ? 's' : ''}`
2211
+
2212
+ const isOpen = document.getElementById('reports-status').value === 'open'
2213
+
2214
+ container.innerHTML = `
2215
+ <div class="card">
2216
+ <div class="result-count">${countLabel}</div>
2217
+ ${reports
2218
+ .map((r) => {
2219
+ const reporterDisplay = r.reported_by_handle
2220
+ ? `@${escapeHtml(r.reported_by_handle)}`
2221
+ : escapeHtml(r.reported_by)
2222
+ const date = new Date(r.created_at).toLocaleString()
2223
+ return `<div class="record-card">
2224
+ <div class="record-header">
2225
+ <div class="record-meta">
2226
+ <div class="record-uri" title="${escapeHtml(r.subject_uri)}">${escapeHtml(r.subject_uri)}</div>
2227
+ <div class="record-summary">
2228
+ <span class="label-tag">${escapeHtml(r.label)}</span>
2229
+ reported by ${reporterDisplay} &middot; ${date}
2230
+ </div>
2231
+ ${r.reason ? `<div class="record-summary" style="margin-top:0.25rem">${escapeHtml(r.reason)}</div>` : ''}
2232
+ ${!isOpen ? `<div class="record-summary" style="margin-top:0.25rem;opacity:0.6">${escapeHtml(r.status)}${r.resolved_by ? ` by ${escapeHtml(r.resolved_by)}` : ''}</div>` : ''}
2233
+ </div>
2234
+ ${
2235
+ isOpen
2236
+ ? `<div class="record-actions">
2237
+ <button class="btn btn-sm" data-action="resolve-report" data-id="${r.id}" data-resolve="resolve" style="background:var(--accent);color:white">Apply Label</button>
2238
+ <button class="btn btn-sm" data-action="resolve-report" data-id="${r.id}" data-resolve="dismiss">Dismiss</button>
2239
+ </div>`
2240
+ : ''
2241
+ }
2242
+ </div>
2243
+ </div>`
2244
+ })
2245
+ .join('')}
2246
+ ${paginationHtml}
2247
+ </div>
2248
+ `
2249
+
2250
+ container.querySelectorAll('[data-reports-page="prev"]').forEach((b) => {
2251
+ b.addEventListener('click', () => {
2252
+ reportsPage.offset = Math.max(0, reportsPage.offset - reportsPage.limit)
2253
+ loadReports()
2254
+ })
2255
+ })
2256
+ container.querySelectorAll('[data-reports-page="next"]').forEach((b) => {
2257
+ b.addEventListener('click', () => {
2258
+ reportsPage.offset += reportsPage.limit
2259
+ loadReports()
2260
+ })
2261
+ })
2262
+
2263
+ container.querySelectorAll('[data-action="resolve-report"]').forEach((btn) => {
2264
+ btn.addEventListener('click', async () => {
2265
+ const action = btn.dataset.resolve
2266
+ try {
2267
+ await api('/admin/reports/resolve', {
2268
+ method: 'POST',
2269
+ headers: { 'Content-Type': 'application/json' },
2270
+ body: JSON.stringify({ id: parseInt(btn.dataset.id), action }),
2271
+ })
2272
+ toast(action === 'resolve' ? 'Label applied & report resolved' : 'Report dismissed', 'success')
2273
+ loadReports()
2274
+ } catch (e) {
2275
+ toast(e.message, 'error')
2276
+ }
2277
+ })
2278
+ })
2279
+ }
2164
2280
  </script>
2165
2281
  </body>
2166
2282
  </html>
package/dist/db.d.ts.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"db.d.ts","sourceRoot":"","sources":["../src/db.ts"],"names":[],"mappings":"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"}