# tunguyen35/pingvn architecture

> Architecture diagram of the GitHub repository tunguyen35/pingvn, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-06-30). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/tunguyen35/pingvn
- Repository: https://github.com/tunguyen35/pingvn

## Overview

1. **What this repo is**
   - This is a TypeScript/JavaScript measurement library, published as `@cloudflare/speedtest`.
   - The core runtime is browser-side: it measures network quality from a client device against Cloudflare edge endpoints, using browser network timing APIs and WebRTC for packet loss.

2. **Primary architecture boundary**
   - The main boundary is between the **public API surface** and the **measurement engine internals**.
   - `src/index.ts` is the library entrypoint; consumers instantiate `SpeedTest`, configure it, and receive callbacks/results.
   - Everything under `src/engines`, `src/Results`, `src/config`, `src/utils`, and `src/logging` supports that one public class.

3. **Orchestration layer**
   - The speedtest is driven by a central orchestrator that sequences measurement steps: latency, download, upload, packet loss, and reachability.
   - The configured measurement plan is an ordered list, so the system is fundamentally a **pipeline of measurement tasks** rather than a single monolithic test.
   - The engine exposes lifecycle control: start, pause, restart, running state, finish state, and event callbacks.

4. **Measurement engines**
   - `src/engines/Latency` is implemented through the download API with zero-byte requests and uses request timing to compute RTT-like latency.
   - `src/engines/BandwidthEngine` handles download and upload ramps, including “loaded latency” sampling while transfers are in progress.
   - `src/engines/PacketLossEngine` uses WebRTC/UDP via a TURN server to count lost packets.
   - `src/engines/ReachabilityEngine` appears to be a lighter connectivity check stage.
   - The `Engine.ts` abstraction suggests these are interchangeable measurement units behind a shared contract.

5. **Data sources and network dependencies**
   - Download and upload measurements target Cloudflare HTTP APIs, defaulting to `https://speed.cloudflare.com/__down` and `https://speed.cloudflare.com/__up`.
   - Latency and bandwidth calculations depend on `PerformanceResourceTiming` browser data, not just fetch completion time.
   - Packet loss is a separate network path using TURN/WebRTC, with credentials optionally fetched from a credentials API or supplied directly.

6. **Results pipeline**
   - `src/Results` is the post-processing layer that turns raw measurement points into derived metrics.
   - It computes reduced values such as unloaded latency, jitter, download/upload bandwidth, packet loss ratio, total duration, and AIM scores.
   - The results object is stateful and incremental: it can be queried while a test is still running, but some values are only final after completion.

7. **Configuration and thresholds**
   - `src/config` centralizes defaults and internal config shape, including request sizes, throttles, duration thresholds, percentiles, and TURN settings.
   - `src/utils/scaleThreshold.ts` and `src/utils/numbers.ts` indicate the repo relies on numeric reduction/selection logic for percentiles and thresholds.
   - Configuration directly affects the measurement strategy, especially the ramp-up behavior for bandwidth and the sample windows for loaded latency.

8. **Logging and UI-facing callbacks**
   - `src/logging/logFinalResults.ts` suggests the library emits a final structured summary for diagnostics or display.
   - The public event model (`onResultsChange`, `onFinish`, `onError`, `onRunningChange`) is the main interface for integrating with UI or higher-level apps.
   - This is an event-driven library, not a request/response API.

9. **Browser app and demo surface**
   - The `app/` directory is a browser application wrapper around the library, with `index.html`, `app.js`, `style.css`, `manifest.json`, `sw.js`, icons, and Android asset links.
   - That makes it a PWA-style demo/host for the speedtest engine, likely the app behind the public Cloudflare speedtest experience.
   - `app/wrangler.toml` indicates deployment as a Cloudflare Worker/Pages-style edge app rather than a traditional server.

10. **Example integrations**
   - `example/basic-page` is a minimal static usage example.
   - `example/turn-worker` is an integration example for packet-loss support: it provides a Worker-based TURN credential flow for Cloudflare Realtime TURN.
   - This example exists because packet-loss measurement is architecturally optional and depends on external infrastructure the consumer must provide.

11. **Testing structure**
   - Unit tests cover config defaults, utility math, result calculations, and URL construction.
   - `tests/e2e/speedtest.test.ts` validates the full measurement flow, which is important because the behavior depends on browser timing APIs and network interactions.
   - The test split reflects the repo’s main risk areas: numeric correctness and end-to-end orchestration.

12. **Build, packaging, and release concerns**
   - The package is built from TypeScript and managed as a library, with configs for bundling and linting (`tsdown`, `vitest`, ESLint, Prettier).
   - GitHub Actions handle build, release PR creation, npm publishing, and Semgrep scanning.
   - These workflows don’t change runtime architecture, but they show the repo is designed to ship as a reusable package plus a deployed browser app.

Main entry points: [`src/engines/LoadNetworkEngine/index.ts`](https://github.com/tunguyen35/pingvn/blob/main/src/engines/LoadNetworkEngine/index.ts) (Load Network), [`src/index.ts`](https://github.com/tunguyen35/pingvn/blob/main/src/index.ts) (SpeedTest), [`tests/unit/Results/Results.test.ts`](https://github.com/tunguyen35/pingvn/blob/main/tests/unit/Results/Results.test.ts) (Unit Tests), [`src/Results/MeasurementCalculations.ts`](https://github.com/tunguyen35/pingvn/blob/main/src/Results/MeasurementCalculations.ts) (Metrics)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_lib["Library"]
  node_src_index["SpeedTest<br/>public API<br/>[index.ts]"]
end

subgraph group_engines["Engines"]
  node_engine_base["Engine<br/>[Engine.ts]"]
  node_latency_engine["Latency<br/>measure rtt<br/>[BandwidthEngine.ts]"]
  node_bandwidth_engine["Bandwidth<br/>download/upload<br/>[BandwidthEngine.ts]"]
  node_packetloss_engine["Packet Loss<br/>webrtc path"]
  node_reachability_engine["Reachability<br/>connectivity check<br/>[index.ts]"]
  node_load_network_engine["Load Network<br/>orchestrator<br/>[index.ts]"]
end

subgraph group_data["Data & Config"]
  node_results_index["Results<br/>derived metrics<br/>[index.ts]"]
  node_measurement_calc["Metrics<br/>aggregation"]
  node_scores_calc["Scores<br/>scoring"]
  node_default_config["Defaults<br/>[defaultConfig.ts]"]
  node_internal_config["Internal Config<br/>runtime config<br/>[internalConfig.ts]"]
  node_numbers_utils["Numbers<br/>math helpers<br/>[numbers.ts]"]
  node_threshold_utils["Thresholds<br/>math helpers<br/>[scaleThreshold.ts]"]
  node_log_final["Final Log<br/>logging<br/>[logFinalResults.ts]"]
end

subgraph group_demo["App & Examples"]
  node_app_shell["Browser App<br/>PWA host<br/>[app.js]"]
  node_basic_example["Basic Page<br/>example<br/>[index.html]"]
  node_turn_example["TURN Worker<br/>example<br/>[index.ts]"]
end

subgraph group_qa["Tests & CI"]
  node_tests_unit["Unit Tests<br/>test suite<br/>[Results.test.ts]"]
  node_tests_e2e["E2E Test<br/>integration test<br/>[speedtest.test.ts]"]
  node_ci["CI & Release<br/>automation<br/>[build.yml]"]
end

node_src_index -->|"starts"| node_load_network_engine
node_src_index -->|"exposes"| node_results_index
node_src_index -->|"configures"| node_default_config
node_src_index -->|"logs"| node_log_final
node_load_network_engine -->|"uses"| node_engine_base
node_load_network_engine -->|"stage"| node_reachability_engine
node_load_network_engine -->|"stage"| node_latency_engine
node_load_network_engine -->|"stage"| node_bandwidth_engine
node_load_network_engine -->|"stage"| node_packetloss_engine
node_bandwidth_engine -->|"reduces"| node_numbers_utils
node_bandwidth_engine -->|"tunes"| node_threshold_utils
node_packetloss_engine -.->|"depends on"| node_turn_example
node_results_index -->|"derives"| node_measurement_calc
node_results_index -->|"scores"| node_scores_calc
node_measurement_calc -->|"uses"| node_numbers_utils
node_measurement_calc -->|"uses"| node_threshold_utils
node_default_config -->|"normalizes"| node_internal_config
node_app_shell -->|"consumes"| node_src_index
node_basic_example -->|"demonstrates"| node_src_index
node_turn_example -->|"enables"| node_packetloss_engine
node_tests_unit -->|"verifies"| node_default_config
node_tests_unit -->|"verifies"| node_measurement_calc
node_tests_unit -->|"verifies"| node_numbers_utils
node_tests_e2e -->|"verifies"| node_load_network_engine
node_ci -.->|"runs"| node_tests_unit
node_ci -.->|"runs"| node_tests_e2e

click node_src_index "https://github.com/tunguyen35/pingvn/blob/main/src/index.ts"
click node_engine_base "https://github.com/tunguyen35/pingvn/blob/main/src/engines/Engine.ts"
click node_latency_engine "https://github.com/tunguyen35/pingvn/blob/main/src/engines/BandwidthEngine/BandwidthEngine.ts"
click node_bandwidth_engine "https://github.com/tunguyen35/pingvn/blob/main/src/engines/BandwidthEngine/BandwidthEngine.ts"
click node_packetloss_engine "https://github.com/tunguyen35/pingvn/blob/main/src/engines/PacketLossEngine/PacketLossEngine.ts"
click node_reachability_engine "https://github.com/tunguyen35/pingvn/blob/main/src/engines/ReachabilityEngine/index.ts"
click node_load_network_engine "https://github.com/tunguyen35/pingvn/blob/main/src/engines/LoadNetworkEngine/index.ts"
click node_results_index "https://github.com/tunguyen35/pingvn/blob/main/src/Results/index.ts"
click node_measurement_calc "https://github.com/tunguyen35/pingvn/blob/main/src/Results/MeasurementCalculations.ts"
click node_scores_calc "https://github.com/tunguyen35/pingvn/blob/main/src/Results/ScoresCalculations.ts"
click node_default_config "https://github.com/tunguyen35/pingvn/blob/main/src/config/defaultConfig.ts"
click node_internal_config "https://github.com/tunguyen35/pingvn/blob/main/src/config/internalConfig.ts"
click node_numbers_utils "https://github.com/tunguyen35/pingvn/blob/main/src/utils/numbers.ts"
click node_threshold_utils "https://github.com/tunguyen35/pingvn/blob/main/src/utils/scaleThreshold.ts"
click node_log_final "https://github.com/tunguyen35/pingvn/blob/main/src/logging/logFinalResults.ts"
click node_app_shell "https://github.com/tunguyen35/pingvn/blob/main/app/app.js"
click node_basic_example "https://github.com/tunguyen35/pingvn/blob/main/example/basic-page/index.html"
click node_turn_example "https://github.com/tunguyen35/pingvn/blob/main/example/turn-worker/src/index.ts"
click node_tests_unit "https://github.com/tunguyen35/pingvn/blob/main/tests/unit/Results/Results.test.ts"
click node_tests_e2e "https://github.com/tunguyen35/pingvn/blob/main/tests/e2e/speedtest.test.ts"
click node_ci "https://github.com/tunguyen35/pingvn/blob/main/.github/workflows/build.yml"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_src_index toneBlue
class node_engine_base,node_latency_engine,node_bandwidth_engine,node_packetloss_engine,node_reachability_engine,node_load_network_engine toneAmber
class node_results_index,node_measurement_calc,node_scores_calc,node_default_config,node_internal_config,node_numbers_utils,node_threshold_utils,node_log_final toneMint
class node_app_shell,node_basic_example,node_turn_example toneRose
class node_tests_unit,node_tests_e2e,node_ci toneIndigo
```

## Components

### Library

Public package surface and core runtime

- [SpeedTest](https://github.com/tunguyen35/pingvn/blob/main/src/index.ts): public API · Library entrypoint and consumer-facing test controller · `src/index.ts`

### Engines

Measurement stages and orchestration

- [Engine](https://github.com/tunguyen35/pingvn/blob/main/src/engines/Engine.ts): engine contract · Shared abstraction for measurement stages · `src/engines/Engine.ts`
- [Latency](https://github.com/tunguyen35/pingvn/blob/main/src/engines/BandwidthEngine/BandwidthEngine.ts): measure rtt · Zero-byte request timing used to estimate latency · `src/engines/BandwidthEngine/BandwidthEngine.ts`
- [Bandwidth](https://github.com/tunguyen35/pingvn/blob/main/src/engines/BandwidthEngine/BandwidthEngine.ts): download/upload · Ramp-based download and upload measurement with loaded latency sampling · `src/engines/BandwidthEngine/BandwidthEngine.ts`
- [Packet Loss](https://github.com/tunguyen35/pingvn/blob/main/src/engines/PacketLossEngine/PacketLossEngine.ts): webrtc path · TURN/WebRTC packet-loss measurement over a separate transport · `src/engines/PacketLossEngine/PacketLossEngine.ts`
- [Reachability](https://github.com/tunguyen35/pingvn/blob/main/src/engines/ReachabilityEngine/index.ts): connectivity check · Lightweight network reachability stage · `src/engines/ReachabilityEngine/index.ts`
- [Load Network](https://github.com/tunguyen35/pingvn/blob/main/src/engines/LoadNetworkEngine/index.ts): orchestrator · Coordinates ordered measurement stages and lifecycle state · `src/engines/LoadNetworkEngine/index.ts`

### Data & Config

Derived metrics, thresholds, and shared helpers

- [Results](https://github.com/tunguyen35/pingvn/blob/main/src/Results/index.ts): derived metrics · Stateful results model exposed during and after a run · `src/Results/index.ts`
- [Metrics](https://github.com/tunguyen35/pingvn/blob/main/src/Results/MeasurementCalculations.ts): aggregation · Computes latency, jitter, bandwidth, packet loss, and duration · `src/Results/MeasurementCalculations.ts`
- [Scores](https://github.com/tunguyen35/pingvn/blob/main/src/Results/ScoresCalculations.ts): scoring · Derives final AIM-style scores from measured values · `src/Results/ScoresCalculations.ts`
- [Defaults](https://github.com/tunguyen35/pingvn/blob/main/src/config/defaultConfig.ts): config defaults · Public and internal default settings for requests, ramps, and thresholds · `src/config/defaultConfig.ts`
- [Internal Config](https://github.com/tunguyen35/pingvn/blob/main/src/config/internalConfig.ts): runtime config · Normalized configuration shape used by engines and orchestration · `src/config/internalConfig.ts`
- [Numbers](https://github.com/tunguyen35/pingvn/blob/main/src/utils/numbers.ts): math helpers · Numeric selection and reduction helpers · `src/utils/numbers.ts`
- [Thresholds](https://github.com/tunguyen35/pingvn/blob/main/src/utils/scaleThreshold.ts): math helpers · Scales thresholds and sample-window decisions · `src/utils/scaleThreshold.ts`
- [Final Log](https://github.com/tunguyen35/pingvn/blob/main/src/logging/logFinalResults.ts): logging · Structured final-result logging for diagnostics and display · `src/logging/logFinalResults.ts`

### App & Examples

Browser app and integration examples

- [Browser App](https://github.com/tunguyen35/pingvn/blob/main/app/app.js): PWA host · Edge-deployed demo and likely production web shell for the speed test · `app/app.js`
- [Basic Page](https://github.com/tunguyen35/pingvn/blob/main/example/basic-page/index.html): example · Minimal static integration example · `example/basic-page/index.html`
- [TURN Worker](https://github.com/tunguyen35/pingvn/blob/main/example/turn-worker/src/index.ts): example · Worker-based TURN credential example for packet-loss support · `example/turn-worker/src/index.ts`

### Tests & CI

Validation and release automation

- [Unit Tests](https://github.com/tunguyen35/pingvn/blob/main/tests/unit/Results/Results.test.ts): test suite · Checks config, math, results, and URL construction · `tests/unit/Results/Results.test.ts`
- [E2E Test](https://github.com/tunguyen35/pingvn/blob/main/tests/e2e/speedtest.test.ts): integration test · Browser-driven end-to-end measurement flow validation · `tests/e2e/speedtest.test.ts`
- [CI & Release](https://github.com/tunguyen35/pingvn/blob/main/.github/workflows/build.yml): automation · Build, publish, and security workflows for the package and app · `.github/workflows/build.yml`

## Connections

- SpeedTest → Load Network: starts · Public API delegates test execution to the orchestrator
- SpeedTest → Results: exposes · Consumers read progress and final measurements from results
- SpeedTest → Defaults: configures · Test behavior is driven by default and user-supplied config
- SpeedTest → Final Log: logs · Final summary output is produced for diagnostics or display
- Load Network → Engine: uses · Orchestration is built on the shared engine contract
- Load Network → Reachability: stage · Reachability is one of the ordered measurement stages
- Load Network → Latency: stage · Latency is sequenced as part of the measurement plan
- Load Network → Bandwidth: stage · Bandwidth measurements run within the ordered plan
- Load Network → Packet Loss: stage · Packet loss is an optional measurement stage
- Bandwidth → Numbers: reduces · Bandwidth calculations rely on numeric reduction helpers
- Bandwidth → Thresholds: tunes · Ramp and sampling behavior use threshold scaling
- Packet Loss → TURN Worker: depends on · Packet loss requires TURN credential infrastructure from the consumer
- Results → Metrics: derives · Raw measurement points are turned into metrics
- Results → Scores: scores · Final scores are computed from derived metrics
- Metrics → Numbers: uses · Metric selection and reduction use math helpers
- Metrics → Thresholds: uses · Windowing and threshold decisions rely on scaling logic
- Defaults → Internal Config: normalizes · Defaults are shaped into the internal runtime config
- Browser App → SpeedTest: consumes · Browser app wraps the library runtime
- Basic Page → SpeedTest: demonstrates · Minimal usage example of the public API
- TURN Worker → Packet Loss: enables · Example wiring for the WebRTC/TURN packet-loss path
- Unit Tests → Defaults: verifies · Unit tests cover configuration defaults and internals
- Unit Tests → Metrics: verifies · Unit tests cover derived metric calculations
- Unit Tests → Numbers: verifies · Unit tests cover numeric helper behavior
- E2E Test → Load Network: verifies · End-to-end test exercises the full orchestrated flow
- CI & Release → Unit Tests: runs · CI validates the library with unit coverage
- CI & Release → E2E Test: runs · CI runs browser integration coverage
