The Problem

Developers who want to embed financial charts quickly hit a maintainability wall: the codebase contains 36 circular‑import cycles and several files (e.g., src/model/chart-model.ts) that exceed 850 lines, making changes ripple widely and hard to reason about.

What This Does

Lightweight‑Charts is a collection of seven self‑contained projects that together deliver a fast, canvas‑based charting library. The core library lives in src/ (253 files, 247 code files) and exposes a minimal API (createChart, LineSeries, etc.) usable via npm or CDN. Supporting projects include plugin-examples/ (181 files, 134 code files) and indicator-examples/ (99 files, 54 code files) that demonstrate extensions, while website/ (380 files, 84 code files) provides the documentation and demo UI. The repository’s import graph resolves 996 internal modules with 1 768 edges; 93 modules live inside circular dependencies, and hubs such as src/model/series-options are imported by 74 other modules, giving it a high‑blast‑radius impact.

How It Is Wired

Execution starts at the library’s public entry point init defined in packages/create-lwc-plugin/src/index.ts:15, which reaches 401 functions and is called from a single place. The internal call graph shows the most‑invoked functions: options (82 callers), ensureNotNull (75), model (73), min (66), and timeScale (63). A representative edge chain is constructor → subscribe → _updateData → setData, illustrating how data flow propagates.

Hub modules that many others depend on include:

  • src/model/series-options (Ca 74, Ce 4, instability 0.05) – in a cycle with chart-model and time-data.
  • src/model/chart-model (Ca 48, Ce 29, instability 0.38) – 859‑line file, high cognitive load.
  • src/model/time-data (Ca 71, Ce 5, instability 0.07) – also in the same cycle.

Circular imports cost anyone modifying these files: a change to series-options can silently break chart-model and vice‑versa, requiring careful extraction of shared types or dependency inversion. Oversized files such as src/model/chart-model.ts, src/model/price-scale.ts, and src/model/time-scale.ts exceed 850 lines, and src/gui/chart-widget.ts shows max indentation depth 6, indicating deep nesting that hampers comprehension.

How To Use It

Setup

# Install the packaged library from npm
npm install lightweight-charts
# Or try the latest master build via pkg.pr.new
npm install https://pkg.pr.new/lightweight-charts@master

Configuration No environment variables or secret keys are required; the library reads chart options directly from the object passed to createChart.

Running it – a minimal demo (as shown in the README):

import { createChart, LineSeries } from 'lightweight-charts';

const chart = createChart(document.body, { width: 400, height: 300 });
const lineSeries = chart.addSeries(LineSeries);
lineSeries.setData([
  { time: '2019-04-11', value: 80.01 },
  { time: '2019-04-12', value: 96.63 },
  { time: '2019-04-13', value: 76.64 },
  { time: '2019-04-14', value: 81.89 },
  { time: '2019-04-15', value: 74.43 },
]);

The standalone CDN build (unpkg/lightweight-charts) creates window.LightweightCharts for script‑tag usage if a bundler is not desired.

Real‑World Use

In a typical dashboard, a backend streams tick data via WebSocket; the frontend receives {time, price} objects and calls lineSeries.setData(updatedData) to keep the chart responsive. Plugins (e.g., those in plugin-examples/) can add cross‑hair, legend, or context‑menu behavior without touching the core chart code, thanks to the well‑scoped src/api/chart-api.ts entry point (39 functions, 24 callees).

Code Health & Issues

  • Measured analysis (static, 224 findings): 116 high‑severity soundness issues (import‑cycle members in series-options.ts, time-data.ts, chart-model.ts), 108 medium cognitive‑load findings (oversized files, high branching density). Files such as src/model/chart-model.ts (859 lines) and src/model/price-scale.ts (deep nesting) are flagged.
  • CODE HEALTH AUDIT (6 findings):
  • [HIGH] Make CI invoke the test suite it has – .github/workflows currently have no test command; adding a test step to an existing workflow would surface failures before merge.
  • [MEDIUM] Enable Dependabot or Renovate – 20 manifests lack an update bot; committing .github/dependabot.yml covering npm and GitHub Actions would keep dependencies patched.
  • [MEDIUM] Install from the lockfile in CI – npm install with a committed package-lock.json; switching to npm ci (or yarn install --immutable) ensures the exact locked dependency set is tested.
  • [MEDIUM] Gate pull requests on a dependency vulnerability scan – no dependency‑scan step exists; adding dependency-review-action on pull_request would catch known‑vulnerable packages early.
  • [MEDIUM] Review the install lifecycle script and disable scripts in CI – postinstall scripts could fetch binaries from URLs; setting ignore-scripts in CI or moving work to an explicit build step mitigates risk.
  • [LOW] Set timeout-minutes on workflow jobs – four jobs declare no timeout; adding realistic bounds prevents overlapping runs on a two‑hourly schedule.

The Bottom Line

The library delivers a tiny, high‑performance canvas charting solution that integrates easily via npm or CDN, and its plugin/indicator examples showcase extensibility. However, the codebase suffers from circular imports, oversized modules, and CI gaps that increase maintenance overhead. Teams comfortable with a modest refactor to break cycles and add proper CI will find it a solid choice for financial dashboards; others may need to allocate effort to restructure the model layer before large‑scale adoption.