mirror of
https://github.com/PR0M3TH3AN/TORCH.git
synced 2026-10-27 07:51:52 +00:00
Merge pull request #518 from PR0M3TH3AN/daily-agent-docs-investigator-14461936535840913913
docs: add JSDoc and flow documentation for dashboard/app.js
This commit is contained in:
8 files changed
+169
No files matched your search
@@ -2,6 +2,18 @@
|
|||||||
import { KIND_APP_DATA } from '../src/constants.mjs';
|
import { KIND_APP_DATA } from '../src/constants.mjs';
|
||||||
import { createElement } from './domUtils.js';
|
import { createElement } from './domUtils.js';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Main Execution Flow:
|
||||||
|
* 1. Setup UI (Modals, Event Listeners) and configuration defaults.
|
||||||
|
* 2. `bootstrap()` loads `torch-config.json` and parses local storage prefs.
|
||||||
|
* 3. `init()` loops over configured relays and calls `connectToRelay()`.
|
||||||
|
* 4. WebSocket handlers listen for `LOCK_EVENT_KIND` events via NIP-01 REQ.
|
||||||
|
* 5. Incoming events are parsed (`parseLockEvent()`), de-duplicated by `dTag`, and stored.
|
||||||
|
* 6. `scheduleRender()` debounces layout updates.
|
||||||
|
* 7. `renderLocks()` creates and injects cards mapping to current system locks.
|
||||||
|
* 8. A periodic interval re-renders the UI to update TTl progress bars.
|
||||||
|
*/
|
||||||
|
|
||||||
// -----------------------------------------------------------------------
|
// -----------------------------------------------------------------------
|
||||||
// Modal Logic
|
// Modal Logic
|
||||||
// -----------------------------------------------------------------------
|
// -----------------------------------------------------------------------
|
||||||
@@ -97,6 +109,11 @@ window.onclick = function(event) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetches the TORCH.md file and renders it into the DOM using marked and DOMPurify.
|
||||||
|
* Renders an error message to the user if the fetch fails.
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
*/
|
||||||
async function fetchDocs() {
|
async function fetchDocs() {
|
||||||
try {
|
try {
|
||||||
const response = await fetch('../src/docs/TORCH.md');
|
const response = await fetch('../src/docs/TORCH.md');
|
||||||
@@ -153,6 +170,11 @@ function normalizeStatus(value) {
|
|||||||
: DASHBOARD_DEFAULTS.defaultStatusView;
|
: DASHBOARD_DEFAULTS.defaultStatusView;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads the dashboard configuration from a local torch-config.json file.
|
||||||
|
* Returns an empty object if no config is found or readable.
|
||||||
|
* @returns {Promise<Object>} The parsed torch-config object
|
||||||
|
*/
|
||||||
async function loadTorchConfigFile() {
|
async function loadTorchConfigFile() {
|
||||||
const configCandidates = ['../torch-config.json', './torch-config.json'];
|
const configCandidates = ['../torch-config.json', './torch-config.json'];
|
||||||
|
|
||||||
@@ -169,6 +191,13 @@ async function loadTorchConfigFile() {
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolves configuration properties cascading from highest precedence (URL parameters),
|
||||||
|
* to intermediate precedence (LocalStorage), then `torch-config.json`, and finally falling
|
||||||
|
* back to hardcoded defaults.
|
||||||
|
* @param {Object} [torchConfig={}] - The JSON structure from loadTorchConfigFile()
|
||||||
|
* @returns {Object} A resolved settings dictionary containing namespace, hashtag, and relays.
|
||||||
|
*/
|
||||||
function parseDashboardConfig(torchConfig = {}) {
|
function parseDashboardConfig(torchConfig = {}) {
|
||||||
const params = new URLSearchParams(window.location.search);
|
const params = new URLSearchParams(window.location.search);
|
||||||
|
|
||||||
@@ -683,6 +712,15 @@ function updateConnectionBadge() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Establishes a WebSocket connection to the given Nostr relay and negotiates
|
||||||
|
* a NIP-01 subscription requesting historic events within a 7 day window that
|
||||||
|
* match the current LOCK_EVENT_KIND and configured hashtag.
|
||||||
|
* Incoming events are pushed to global state lockStore and render is triggered.
|
||||||
|
*
|
||||||
|
* Automatically attempts reconnection after 5000ms if closed abruptly.
|
||||||
|
* @param {string} url - Valid WebSocket URL to connect to.
|
||||||
|
*/
|
||||||
function connectToRelay(url) {
|
function connectToRelay(url) {
|
||||||
if (!isAlive()) return;
|
if (!isAlive()) return;
|
||||||
|
|
||||||
@@ -817,6 +855,11 @@ if (refreshBtn) refreshBtn.addEventListener('click', () => {
|
|||||||
// -----------------------------------------------------------------------
|
// -----------------------------------------------------------------------
|
||||||
// Init
|
// Init
|
||||||
// -----------------------------------------------------------------------
|
// -----------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the dashboard connections and logic using global settings resolved
|
||||||
|
* by bootstrap(). Connects to each websocket in the RELAYS array.
|
||||||
|
*/
|
||||||
function init() {
|
function init() {
|
||||||
if (!isAlive()) return;
|
if (!isAlive()) return;
|
||||||
|
|
||||||
@@ -827,6 +870,12 @@ function init() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Main application entrypoint. Loads async dependencies (`loadTorchConfigFile()`),
|
||||||
|
* resolves local overrides, populates config globals, updates the DOM filter fields
|
||||||
|
* with default options, and kicks off socket connectivity via `init()`.
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
*/
|
||||||
async function bootstrap() {
|
async function bootstrap() {
|
||||||
const torchConfig = await loadTorchConfigFile();
|
const torchConfig = await loadTorchConfigFile();
|
||||||
DASHBOARD_CONFIG = parseDashboardConfig(torchConfig);
|
DASHBOARD_CONFIG = parseDashboardConfig(torchConfig);
|
||||||
|
|||||||
@@ -0,0 +1,45 @@
|
|||||||
|
# Dashboard App Overview
|
||||||
|
|
||||||
|
## What this module does
|
||||||
|
The `dashboard/app.js` module is the main entry point for the frontend UI logic of the TORCH web dashboard. It manages the configuration loading cascading from URL queries, `localStorage`, and `torch-config.json` default settings, and maintains live WebSocket connections to Nostr relays. Incoming `LOCK_EVENT_KIND` events are parsed, de-duplicated, and pushed to the UI where they render as lock cards with remaining TTL status via a periodic interval.
|
||||||
|
|
||||||
|
## Main Execution Flow
|
||||||
|
1. **Config Setup**: `bootstrap()` loads settings via `loadTorchConfigFile()`, resolves preferences using `parseDashboardConfig()`, and populates global constants like `RELAYS` and `HASHTAG`.
|
||||||
|
2. **Relay Setup**: `init()` loops over the configured `RELAYS` and calls `connectToRelay()` for each.
|
||||||
|
3. **Data Subscription**: `connectToRelay()` opens a WebSocket, emitting a NIP-01 `REQ` for lock events tagged with the namespace over the past 7 days.
|
||||||
|
4. **Data Intake**: Incoming `EVENT` messages are parsed via `parseLockEvent()`, de-duplicated based on `dTag`, stored in `lockStore`, and logged into the `rawLog` DOM container.
|
||||||
|
5. **UI Rendering**: The receipt of events triggers `scheduleRender()`, which delegates to `renderLocks()` to build DOM nodes using `createLockCard()` for all active/filtered locks.
|
||||||
|
6. **Background Loop**: A 30s interval re-renders the DOM to decrement remaining lock TTL and update the CSS widths of progress bars.
|
||||||
|
|
||||||
|
## Usage Snippet
|
||||||
|
```js
|
||||||
|
// Within dashboard/index.html
|
||||||
|
<script src="app.js" type="module"></script>
|
||||||
|
```
|
||||||
|
*(The module invokes `bootstrap()` as its final statement).*
|
||||||
|
|
||||||
|
## Public API / Exports
|
||||||
|
*(Note: As an entrypoint module assigned via a direct `<script>` import to `window`, it does not export standard ES modules to other files. However, internally these serve as the public API hooks for HTML interactive handlers).*
|
||||||
|
|
||||||
|
| Function | Purpose |
|
||||||
|
|----------|---------|
|
||||||
|
| `fetchDocs()` | Asynchronously fetches `TORCH.md` and renders parsed markdown using marked and DOMPurify. |
|
||||||
|
| `loadTorchConfigFile()` | Asynchronously fetches and parses the local `torch-config.json` repository config file. |
|
||||||
|
| `parseDashboardConfig()`| Consolidates configs spanning URL search query overrides, localstorage, and standard file fallback values. |
|
||||||
|
| `connectToRelay()` | Opens and manages a resilient WebSocket connection with auto-reconnect logic and event handling. |
|
||||||
|
| `init()` | Iterates configured relays initiating the primary loop connection handlers. |
|
||||||
|
| `bootstrap()` | Primary async entrypoint which fetches configuration before setting DOM default filters and calling `init()`. |
|
||||||
|
|
||||||
|
## Invariants and Edge Cases
|
||||||
|
- **Duplicate Locks**: Handled using `dTag`. The latest `created_at` timestamp is preferred when determining state.
|
||||||
|
- **Relay Instability**: Dropped connections (`ws.close`) fire an automatic reconnect timeout loop after 5000ms.
|
||||||
|
- **Security Check**: Text content mapping to HTML utilizes `DOMPurify.sanitize()` when `fetchDocs()` is rendered to prevent XSS.
|
||||||
|
- **Background Throttling**: The global scope validates visibility via `!document.hidden` and `isAlive()` before polling or rendering frames to conserve resources.
|
||||||
|
|
||||||
|
## Why it works this way
|
||||||
|
Configuration runs dynamically to ensure that static builds generated using `npm run dashboard:serve` do not hard-fix user settings but allow live overrides using URL hash routing or LocalStorage variables. Events are debounced behind a `requestAnimationFrame` wrapper in `scheduleRender()` to avoid locking the DOM when heavily queried relays blast historical events.
|
||||||
|
|
||||||
|
## When to change
|
||||||
|
- **Config format evolution:** Update `loadTorchConfigFile()` if the parent directory structure, or schema definition of `torch-config.json` (`nostrLock` keys) change significantly.
|
||||||
|
- **Adding new Event Kinds**: Modify the websocket subscription filter (`kinds: [LOCK_EVENT_KIND]`) in `connectToRelay` if the dashboard expands visualization beyond raw agent locks.
|
||||||
|
- **Adding layout themes:** Update standard DOM manipulation styles in `createLockCard` if UI library changes.
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"learnings": "Documented the core data flow of the dashboard frontend in dashboard/app.js. Learned that the frontend cascade prioritizes URL params over localStorage, then torch-config.json, before falling back to static defaults. It establishes NIP-01 subscriptions requesting REQ filters over 7 days for the configured hashtag.",
|
||||||
|
"status": "success"
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
---
|
||||||
|
agent: docs-code-investigator
|
||||||
|
cadence: daily
|
||||||
|
run-start: 2026-03-03T01:00:00Z
|
||||||
|
prompt-path: src/prompts/daily/docs-code-investigator.md
|
||||||
|
---
|
||||||
|
# CONTEXT
|
||||||
|
|
||||||
|
goal: Identify an undocumented target file > 200 LOC and add JSDoc and high-level module documentation to improve readability and maintainability.
|
||||||
|
scope: `dashboard/app.js` has been identified as the target file. It handles the frontend UI, local storage preferences, and WebSocket connections to Nostr relays.
|
||||||
|
constraints:
|
||||||
|
- Add JSDoc to public exports and multi-step flow block comments at the top of the file.
|
||||||
|
- Create `docs/<module>-overview.md`.
|
||||||
|
- No behavioral logic modifications.
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
---
|
||||||
|
agent: docs-code-investigator
|
||||||
|
cadence: daily
|
||||||
|
run-start: 2026-03-03T01:00:00Z
|
||||||
|
prompt-path: src/prompts/daily/docs-code-investigator.md
|
||||||
|
---
|
||||||
|
# DECISIONS
|
||||||
|
|
||||||
|
## Decision: `dashboard/app.js` Focus
|
||||||
|
### Rationale:
|
||||||
|
Using `git ls-files | xargs wc -l | sort -rn`, `dashboard/app.js` is the largest Javascript file in the codebase (835 lines) mapping directly to a specific un-tested surface (the user-facing frontend dashboard), making it a prime candidate for `docs-code-investigator`.
|
||||||
|
|
||||||
|
## Decision: JSDoc vs Inline
|
||||||
|
### Rationale:
|
||||||
|
The instructions enforce JSDocs for public exports or major functional block entrypoints. By assigning JSDocs specifically to async state loading functions (`bootstrap()`, `fetchDocs()`) and connection functions (`connectToRelay()`), we document the most complex and critical paths without polluting smaller DOM event handlers.
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
---
|
||||||
|
agent: docs-code-investigator
|
||||||
|
cadence: daily
|
||||||
|
run-start: 2026-03-03T01:00:00Z
|
||||||
|
prompt-path: src/prompts/daily/docs-code-investigator.md
|
||||||
|
---
|
||||||
|
# TEST_LOG
|
||||||
|
|
||||||
|
## Test 1: Locating target > 200 LOC
|
||||||
|
Command: `git ls-files '*.js' '*.ts' '*.mjs' | xargs -n1 wc -l | sort -rn | head -n 40`
|
||||||
|
Result: `dashboard/app.js` is 835 LOC and the largest JS file in the project.
|
||||||
|
|
||||||
|
## Test 2: ESLint Formatting
|
||||||
|
Command: `npm run lint`
|
||||||
|
Result: Passed without warnings related to new JSDoc syntax additions or malformed markdown in `docs/dashboard-app-overview.md`.
|
||||||
|
|
||||||
|
## Test 3: Unit Tests
|
||||||
|
Command: `npm test`
|
||||||
|
Result: Passed all lock ops, lib, caching and resilient acquisition suites confirming no logic behavior changes occurred due to syntax modification.
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
---
|
||||||
|
agent: docs-code-investigator
|
||||||
|
cadence: daily
|
||||||
|
run-start: 2026-03-03T01:00:00Z
|
||||||
|
prompt-path: src/prompts/daily/docs-code-investigator.md
|
||||||
|
---
|
||||||
|
# TODO
|
||||||
|
|
||||||
|
- [x] Identified target > 200 LOC: `dashboard/app.js` (835 lines)
|
||||||
|
- [x] Added JSDoc comments to `fetchDocs()`, `loadTorchConfigFile()`, `parseDashboardConfig()`, `connectToRelay()`, `init()`, and `bootstrap()`.
|
||||||
|
- [x] Added high-level sequence block comment.
|
||||||
|
- [x] Created `docs/dashboard-app-overview.md`.
|
||||||
|
- [x] Completed required `CONTEXT`, `TODO`, `DECISIONS`, and `TEST_LOG` files.
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
---
|
||||||
|
status: success
|
||||||
|
agent: docs-code-investigator
|
||||||
|
cadence: daily
|
||||||
|
prompt-path: src/prompts/daily/docs-code-investigator.md
|
||||||
|
run-start: 2026-03-03T01:00:00Z
|
||||||
|
---
|
||||||
|
# Task Log
|
||||||
|
|
||||||
|
Completed successfully.
|
||||||
Reference in new issue
Block a user