Dependency Hierarchy
This document describes the four-tier dependency architecture used throughout the Turf.js monorepo. It explains how the 100+ packages are organized into hierarchical layers, from universal foundation modules through primitive operations to complex algorithms that depend on external libraries. This hierarchy prevents circular dependencies and enables modular consumption of individual packages.
For information about the three foundation modules themselves, see Foundation Modules. For information about how modules are categorized by functionality, see Module Categories.
Overview of the Four-Tier System
Turf.js organizes its dependencies into four distinct tiers. Each tier builds upon the previous one, creating a strict hierarchy that ensures no circular dependencies occur within the monorepo.
Tier 0: External Dependencies
External dependencies provide specialized algorithms and data structures that are not implemented within Turf.js itself. These libraries are carefully selected for their stability and performance characteristics.
| Library | Purpose | Used By |
|---|---|---|
@types/geojson | TypeScript type definitions for GeoJSON | All TypeScript modules |
jsts | Java Topology Suite port for computational geometry | @turf/buffer, @turf/union, @turf/intersect |
polyclip-ts | Martinez-Rueda polygon clipping algorithm | @turf/mask, @turf/difference |
rbush | R-tree spatial indexing | @turf/unkink-polygon, @turf/clusters-kmeans |
skmeans | K-means clustering implementation | @turf/clusters-kmeans |
sweepline-intersections | Bentley-Ottmann line intersection | @turf/line-intersect |
concaveman | Concave hull algorithm | @turf/concave |
d3-geo | Map projections | @turf/projection |
earcut | Polygon triangulation | @turf/tesselate |
Tier 1: Foundation Modules
The three foundation modules form the base of the entire dependency hierarchy. Every other Turf.js module depends on at least one of these packages.
@turf/helpers
The @turf/helpers package is the most fundamental dependency, required by every single Turf.js module. It provides:
- GeoJSON factory functions:
point(),lineString(),polygon(),featureCollection() - Unit conversion utilities:
radiansToLength(),lengthToRadians(),lengthToDegrees() - Constants:
earthRadius,factorsfor unit conversion - Type definitions for options objects
Example dependency declaration from packages/turf-rhumb-destination/package.json77:
"@turf/helpers": "workspace:*"@turf/meta
The @turf/meta package provides iteration utilities used by approximately 50+ modules. It enables efficient traversal of GeoJSON structures:
coordEach(): Iterate over all coordinatescoordReduce(): Reduce over coordinatesgeomEach(): Iterate over geometriesflattenEach(): Iterate over flattened featuressegmentEach(): Iterate over line segments
Example usage from packages/turf-flatten/package.json72-73:
"@turf/helpers": "workspace:*",
"@turf/meta": "workspace:*"@turf/invariant
The @turf/invariant package provides input validation and type extraction, used by approximately 70+ modules:
getCoord(): Extract coordinate array from various input typesgetGeom(): Extract geometry from feature or geometry- Type guards:
getType(),geojsonType() - Collection utilities:
collectionOf(),featureOf()
Example from packages/turf-rhumb-bearing/package.json72-73:
"@turf/helpers": "workspace:*",
"@turf/invariant": "workspace:*"Tier 2: Primitive Operations
Tier 2 modules implement basic geometric operations that depend only on the foundation layer and external libraries. They do not depend on other Turf.js operations.
Characteristics of Tier 2 Modules
Tier 2 modules share common characteristics:
- Minimal dependencies: Only depend on foundation modules
- Single responsibility: Each performs one well-defined calculation
- No Turf.js inter-dependencies: Do not import other Turf.js operation modules
- High reusability: Used as building blocks by Tier 3 and Tier 4 modules
Example from packages/turf-rhumb-distance/package.json74-79:
"dependencies": {
"@turf/helpers": "workspace:*",
"@turf/invariant": "workspace:*",
"@types/geojson": "^7946.0.10",
"tslib": "^2.8.1"
}This package depends only on @turf/helpers and @turf/invariant, making it a true primitive operation.
Tier 3: Composite Operations
Tier 3 modules combine primitive operations from Tier 2 to implement more complex functionality. They build higher-level features from lower-level building blocks.
Example: @turf/line-slice
The @turf/line-slice module demonstrates Tier 3 composition. It depends on @turf/nearest-point-on-line, which itself is a Tier 3 module:
From packages/turf-line-slice/package.json68-73:
"dependencies": {
"@turf/helpers": "workspace:*",
"@turf/invariant": "workspace:*",
"@turf/nearest-point-on-line": "workspace:*",
"@types/geojson": "^7946.0.10"
}This shows the module depends on both foundation modules and another composite operation.
Example: @turf/line-chunk
The @turf/line-chunk module shows multiple Tier 3 dependencies:
From packages/turf-line-chunk/package.json73-78:
"dependencies": {
"@turf/helpers": "workspace:*",
"@turf/length": "workspace:*",
"@turf/line-slice-along": "workspace:*",
"@turf/meta": "workspace:*",
"@types/geojson": "^7946.0.10"
}It depends on @turf/length (Tier 2) and @turf/line-slice-along (Tier 3), demonstrating how composite operations build on each other.
Tier 4: Complex Algorithms
Tier 4 modules implement sophisticated algorithms that often require external libraries and multiple Turf.js dependencies spanning Tiers 1-3.
Example: @turf/unkink-polygon
This module demonstrates the complexity of Tier 4 dependencies:
From packages/turf-unkink-polygon/package.json68-76:
"dependencies": {
"@turf/area": "workspace:*",
"@turf/boolean-point-in-polygon": "workspace:*",
"@turf/helpers": "workspace:*",
"@turf/meta": "workspace:*",
"@types/geojson": "^7946.0.10",
"rbush": "^3.0.1",
"tslib": "^2.8.1"
}This module requires:
- Foundation modules:
@turf/helpers,@turf/meta - Tier 2 primitive:
@turf/area - Tier 3 operation:
@turf/boolean-point-in-polygon - External library:
rbushfor spatial indexing
Example: @turf/mask
From packages/turf-mask/package.json66-72:
"dependencies": {
"@turf/clone": "workspace:*",
"@turf/helpers": "workspace:*",
"@types/geojson": "^7946.0.10",
"polyclip-ts": "^0.16.8",
"tslib": "^2.8.1"
}This module uses the polyclip-ts library for the Martinez-Rueda polygon clipping algorithm, demonstrating the integration of external computational geometry libraries.
Example: @turf/line-intersect
From packages/turf-line-intersect/package.json71-76:
"dependencies": {
"@turf/helpers": "workspace:*",
"@types/geojson": "^7946.0.10",
"sweepline-intersections": "^1.5.0",
"tslib": "^2.8.1"
}Uses the sweepline-intersections library implementing the Bentley-Ottmann algorithm for efficient line segment intersection detection.
Dependency Chains
Complex operations often create long dependency chains through multiple tiers. Understanding these chains helps identify the transitive dependencies of any given module.
From packages/turf-point-to-line-distance/package.json69-81:
"dependencies": {
"@turf/bearing": "workspace:*",
"@turf/distance": "workspace:*",
"@turf/helpers": "workspace:*",
"@turf/invariant": "workspace:*",
"@turf/meta": "workspace:*",
"@turf/nearest-point-on-line": "workspace:*",
"@turf/projection": "workspace:*",
"@turf/rhumb-bearing": "workspace:*",
"@turf/rhumb-distance": "workspace:*",
"@types/geojson": "^7946.0.10",
"tslib": "^2.8.1"
}This demonstrates how a Tier 4 module aggregates multiple dependencies from lower tiers, each bringing its own transitive dependencies.
Additional Dependency Patterns
Cross-Tier Boolean Operations
Boolean operations often depend on multiple Turf.js modules to implement their functionality:
From packages/turf-boolean-parallel/package.json68-75:
"dependencies": {
"@turf/clean-coords": "workspace:*",
"@turf/helpers": "workspace:*",
"@turf/line-segment": "workspace:*",
"@turf/rhumb-bearing": "workspace:*",
"@types/geojson": "^7946.0.10",
"tslib": "^2.8.1"
}The @turf/boolean-parallel module depends on:
@turf/clean-coords(Tier 3): Remove duplicate coordinates@turf/line-segment(Tier 3): Split lines into segments@turf/rhumb-bearing(Tier 2): Calculate bearing
Utility Module Composition
Some modules combine multiple utilities to provide enhanced functionality:
From packages/turf-rewind/package.json72-80:
"dependencies": {
"@turf/boolean-clockwise": "workspace:*",
"@turf/clone": "workspace:*",
"@turf/helpers": "workspace:*",
"@turf/invariant": "workspace:*",
"@turf/meta": "workspace:*",
"@types/geojson": "^7946.0.10",
"tslib": "^2.8.1"
}The @turf/rewind module uses @turf/boolean-clockwise to determine polygon orientation before applying the rewind operation.
Geometric Analysis Chains
Complex geometric analysis modules often have extensive dependency chains:
From packages/turf-polygon-tangents/package.json71-80:
"dependencies": {
"@turf/bbox": "workspace:*",
"@turf/boolean-within": "workspace:*",
"@turf/explode": "workspace:*",
"@turf/helpers": "workspace:*",
"@turf/invariant": "workspace:*",
"@turf/nearest-point": "workspace:*",
"@types/geojson": "^7946.0.10",
"tslib": "^2.8.1"
}Workspace Dependencies
All Turf.js packages use the "workspace:*" protocol for internal dependencies, managed by pnpm workspaces. This ensures that all packages within the monorepo reference each other correctly during development and are resolved to appropriate versions during publishing.
From packages/turf-sector/package.json65-72:
"dependencies": {
"@turf/circle": "workspace:*",
"@turf/helpers": "workspace:*",
"@turf/invariant": "workspace:*",
"@turf/line-arc": "workspace:*",
"@turf/meta": "workspace:*",
"@types/geojson": "^7946.0.10",
"tslib": "^2.8.1"
}The workspace:* protocol is transformed to concrete version numbers during the publishing process by Lerna, as configured in lerna.json1-10
The Main Aggregator Package
The @turf/turf package serves as the main distribution bundle and depends on all 100+ individual packages:
From packages/turf/package.json94-210:
"dependencies": {
"@turf/along": "workspace:*",
"@turf/angle": "workspace:*",
"@turf/area": "workspace:*",
// ... 100+ more dependencies
"@turf/voronoi": "workspace:*",
"@types/geojson": "^7946.0.10",
"tslib": "^2.8.1"
}This aggregator package allows users to import the entire Turf.js library with a single dependency, while still maintaining the modular structure that allows tree-shaking and selective imports.
Preventing Circular Dependencies
The tier system prevents circular dependencies through strict rules:
- Tier 1 modules cannot depend on any other Turf.js modules
- Tier 2 modules can only depend on Tier 1
- Tier 3 modules can depend on Tiers 1 and 2
- Tier 4 modules can depend on Tiers 1, 2, and 3
- No module can depend on a module in the same tier if it would create a cycle
This hierarchy is enforced through:
- Code reviews during pull request evaluation
- The monorepo structure preventing local circular imports
- Build system that compiles in dependency order
The result is a directed acyclic graph (DAG) of dependencies that ensures:
- Predictable build order
- No circular reference runtime errors
- Clean module boundaries
- Efficient tree-shaking in consuming applications