Files
electronics-inventory/future-plans.md

6.2 KiB

Future Plans

KV store

Extract into shared library

kv-store.mjs is already copied into at least 3 projects (electronics-inventory, fs-views, publication-tool). Should live in its own Gitea repo as an installable npm package (npm install git+https://...) so changes propagate rather than drift.

Delta / revision tracking

Add a delta log alongside the main snapshot file (e.g. inventory.ndjson.deltas) that records every set/delete as a timestamped entry. The main file stays a clean current-state snapshot; the delta file accumulates the full history. Enables undo, audit trails, and debugging data corruption.

App architecture

parse_url mutates too many module-level variables

parse_url() directly assigns to a large number of module-level state variables (section, grid_view_state, grid_tab, current_grid_id, grid_draft, current_panel_idx, grid_source_id, highlight_cell, selected_component_id). This is fragile and hard to reason about.

Preferred direction: represent the full UI state as a single immutable state object, and have parse_url() return a new state value rather than mutating globals:

function parse_url(path) {
    return { section, grid_view_state, current_grid_id, ... };
}
state = parse_url(location.pathname); render(state);

render() if/else chain

The render dispatcher is a long chain of bare else if branches. Replace with a lookup table:

const SECTION_RENDERERS = {
    components: render_components,
    inventory:  render_inventory,
    fields:     render_fields,
    grids:      render_grids,
    templates:  render_templates,
};
function render() { sync_nav(); SECTION_RENDERERS[section]?.(); }

app.mjs monolith

app.mjs is large. Consider splitting into per-section modules (views/components.mjs, views/grids.mjs, etc.) that each export their render function and own their local state.

DRY / SSoT audit

As the app grows, patterns are being duplicated rather than centralized. Areas to review:

  • Field sorting: same sort-by-name logic appears in both detail view and edit dialog
  • Field rendering: render_field_value() exists but call sites still sometimes inline display logic
  • Component display name: component_display_name() is the SSoT but there may be call sites that still use c.name directly
  • Server-side: PDF conflict checks, sanitize calls, and rename logic are inline in route handlers — could be extracted into a pdf_service helper
  • General pass to identify and eliminate copy-paste between routes and between render functions before the codebase grows further

Field system

Improvements

Field display in component detail should use a table

Currently rendered as CSS grid rows but columns don't align because each row is independent. Use an actual <table> so name and value columns line up across all fields. This is tabular data and a table is the right element.

Field value parser chain

Similar to how name formatters use a template chain, field values could be passed through a parser chain that returns structured data based on field name/type hints. Examples:

  • A field whose name contains tolerance could parse 20 as { negative: 20, positive: 20 } and -10/+30 as { negative: 10, positive: 30 }
  • URL detection (currently hardcoded in render_field_value()) could be one parser in this chain rather than a special case
  • Mouser/Digi-Key part numbers could be detected and return a structured link target

The parser chain would mirror the template system: user-defined or built-in parsers keyed by field name pattern, tried in order, returning structured data or null to pass through to the next. render_field_value() would then receive parsed data and render accordingly.

Field rendering integrations

With or without a parser chain, render_field_value() should gain:

  • Mouser/Digi-Key part number fields → auto-craft links to product pages
  • More URL-like patterns (without https:// prefix)

Field selector filter

When adding a field to a component in the edit dialog, the dropdown becomes unwieldy with many fields. Add a filter/search input to the field selector.

Allow searching/filtering components by field values, not just names. Examples:

  • resistance < 10k, package = 0603, voltage_rating >= 50
  • Cross-field queries: find all 0603 resistors under 10kΩ
  • Should integrate with the existing word-split search or replace it with a richer query language
  • Depends on field types (numeric vs string) for range queries to work correctly

Long term

Field grouping / linkage

Some fields naturally belong together (e.g. frequency_stability and frequency_stability_temp_range). Options:

  • Soft linkage: tag fields with a group name, display grouped in the UI
  • Structured fields: a field can be a record type with named sub-fields (e.g. stability: { value: 10, unit: "ppm", temp_low: -40, temp_high: 85 })

Structured records are the more powerful option but require a schema system and more complex UI. Grouping/linkage is a lighter short-term win.

Renderer/parser result cache

Once parsers and formatters run per-render, a cache keyed on field value + template version would avoid redundant work on large inventories. Invalidated when any template changes. Not urgent — premature until the parser chain exists.

Field types

Currently all field values are free-text strings. Typed fields (numeric, enum/dropdown) would enable better formatting, validation, and range-aware search. Prerequisite for parametric search with range operators.

PDF / files

File picker search filter

The file picker dialog has no search/filter input. With many datasheets this becomes unwieldy. Add a filter input at the top of the list that narrows by display name and filename.

PDF page count and multi-page navigation

Currently only the first page thumbnail is shown. Could show page count and allow browsing pages in the lightbox.

Inventory

Inventory URL reflects selected entry

Similar to how components now reflect /components/:id in the URL, inventory entries have no URL state — refreshing loses context.

Grids

Grid URL state

Navigating into a grid viewer updates the URL correctly, but the grid list and draft state have no URL representation.