Sign In

@squawk/airspace

Package Overview
Dependencies
Maintainers
1
Versions
24
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install
Package version was removed
This package version has been unpublished, mostly likely due to security reasons
This package has malicious versions linked to the ongoing "Mini Shai-Hulud" supply chain attack.

Affected versions:

0.8.10.8.20.8.3
+2 more
View campaign page

@squawk/airspace

Pure logic library for querying US airspace geometry by position and altitude

unpublished
Source
npmnpm
Version
0.8.3
Version published
Weekly downloads
15
-81.71%
Maintainers
1
Weekly downloads
 
Created
Source

squawk logo  @squawk/airspace

MIT License npm TypeScript

Pure logic library for querying US airspace geometry. Given a position and altitude, returns all applicable airspace designations. Contains no bundled data - accepts a GeoJSON dataset at initialization. For zero-config use, pair with @squawk/airspace-data.

Part of the @squawk aviation library suite. See all packages on npm.

Coverage

  • Class B, C, D, and E controlled airspace (E2 through E7 subtypes)
  • Special Use Airspace: MOAs, restricted, prohibited, warning, alert, and national security areas
  • ARTCC (Air Route Traffic Control Center) lateral boundaries for every US-controlled center, published per stratum: LOW/HIGH for the 20 CONUS centers and Anchorage (ZAN), UTA for Oakland (ZOA) only, and oceanic CTA/FIR strata for the Pacific (ZAK, ZAP), Atlantic (ZWY), and the contiguous overlays on ZAN, ZHN, ZHU, ZMA, ZSU. Within-stratum sector polygons and per-sector enroute frequencies are not included - the FAA does not publish either data set in machine-readable form.

Usage

import { usBundledAirspace } from '@squawk/airspace-data';
import { createAirspaceResolver } from '@squawk/airspace';

const resolver = createAirspaceResolver({ data: usBundledAirspace });

// Query a position and altitude
const overhead = resolver.query({ lat: 33.9425, lon: -118.4081, altitudeFt: 3000 });

for (const f of overhead) {
  console.log(f.type, f.name, f.identifier);
}

// Get every shell associated with an airport (for drawing the full wedding cake)
const laxShells = resolver.byAirport('LAX');

// Get every ARTCC center boundary (one feature per stratum)
const ny = resolver.byArtcc('ZNY');

Consumers who have their own GeoJSON airspace data can use this package standalone:

import { createAirspaceResolver } from '@squawk/airspace';

const resolver = createAirspaceResolver({ data: myGeoJson });

Browser / SPA usage

The resolver factory has no Node-specific imports and ships an explicit /browser subpath for SPAs and edge runtimes. Pair it with @squawk/airspace-data/browser:

import { loadUsBundledAirspace } from '@squawk/airspace-data/browser';
import { createAirspaceResolver } from '@squawk/airspace/browser';

const dataset = await loadUsBundledAirspace();
const resolver = createAirspaceResolver({ data: dataset });

The /browser entry is identical to the main entry; the separate subpath exists so browser support is an explicit, publint-verified part of the public API surface.

How it works

createAirspaceResolver parses the GeoJSON FeatureCollection at initialization and returns a resolver object with the following methods:

  • query(AirspaceQuery) - returns features containing the given position and altitude, via a ray casting point-in-polygon test combined with a vertical floor/ceiling comparison.
  • byAirport(identifier, types?) - returns every non-ARTCC feature whose identifier matches (case-insensitive). For Class B/C/D/E2 this groups all sectors of the airspace around a given airport regardless of the point of interest.
  • byArtcc(identifier, stratum?) - returns every ARTCC feature for the given 3-letter center code (e.g. "ZNY"), optionally filtered to a single stratum (LOW, HIGH, UTA, CTA, FIR, or CTA/FIR).
  • byIdentifier(identifier, options?) - type-agnostic identifier lookup that spans both partitions in one call, with an optional types inclusion filter and includeArtcc toggle.
  • byCentroid({ lon, lat, toleranceDeg? }) - returns features whose polygon centroid lies within tolerance of the query coordinates. Useful for resolving features whose identifier is empty (some Class E5 surfaces), where the centroid is the only stable handle.
  • withinBbox(bbox) - returns features whose pre-indexed bounding box overlaps the query bbox. Reuses the bounding box cached at init time rather than recomputing per call.
  • forEachIndexed(callback) - read-only iteration over the indexed corpus with positional (feature, ring, boundingBox) arguments, for callers that need to filter the corpus without reparsing the source GeoJSON.

All matching features are returned as AirspaceFeature objects (from @squawk/types), including the full polygon boundary coordinates.

AGL altitude handling

Some airspace features have floor or ceiling bounds referenced to AGL (above ground level) rather than MSL. Converting AGL to MSL requires terrain elevation data that this library does not include.

The resolver handles AGL bounds conservatively: when it cannot determine the MSL equivalent, it includes the feature rather than silently excluding it. This means the resolver may return features whose AGL bounds do not actually contain the queried altitude.

Consumers can inspect the reference field on the returned AltitudeBound objects and apply their own terrain lookup if needed:

for (const f of features) {
  if (f.floor.reference === 'AGL') {
    // This feature's floor is AGL - apply terrain data if available
  }
}

API

createAirspaceResolver(options)

Creates a resolver from a GeoJSON dataset.

Parameters:

  • options.data - a GeoJSON FeatureCollection with airspace features

Returns: AirspaceResolver - an object exposing query(AirspaceQuery), byAirport(identifier, types?), byArtcc(identifier, stratum?), byIdentifier(identifier, options?), byCentroid(query), withinBbox(bbox), and forEachIndexed(callback) methods.

AirspaceQuery

PropertyTypeDescription
latnumberLatitude in decimal degrees (WGS84)
lonnumberLongitude in decimal degrees (WGS84)
altitudeFtnumberAltitude in feet MSL
typesReadonlySet<AirspaceType>Optional. When provided, only features of these types are returned
// Only query tower-controlled airspace (exclude Class E and SUA)
const controlled = resolver.query({
  lat: 33.9425,
  lon: -118.4081,
  altitudeFt: 3000,
  types: new Set(['CLASS_B', 'CLASS_C', 'CLASS_D']),
});

resolver.byAirport(identifier, types?)

Returns every non-ARTCC airspace feature whose identifier property matches. For Class B/C/D/E2 this is the associated airport's FAA location identifier (e.g. "JFK" for the NY Class B). For Special Use Airspace this is the NASR designator (e.g. "R-2508"). Lookup is case-insensitive. ICAO-prefixed codes like "KJFK" will not match - resolve to an FAA ID first via @squawk/airports.

// Every sector of the NY Class B around JFK, with full polygon boundaries
const jfkShells = resolver.byAirport('JFK');

// Only the Class D for a towered field
const safClassD = resolver.byAirport('SAF', new Set(['CLASS_D']));

resolver.byArtcc(identifier, stratum?)

Returns every ARTCC feature for the given three-letter center code (e.g. "ZNY", "ZBW"). Each US ARTCC is published as multiple features - one per stratum (LOW, HIGH, plus oceanic UTA, CTA, FIR, or CTA/FIR where applicable) - because the lateral extent can vary between strata. Pass an optional stratum filter to narrow results.

// Both LOW and HIGH boundaries for the New York center
const zny = resolver.byArtcc('ZNY');

// Just the high-altitude boundary for the Boston center
const zbwHigh = resolver.byArtcc('ZBW', 'HIGH');

resolver.byIdentifier(identifier, options?)

Type-agnostic identifier lookup. Returns every feature whose identifier matches, spanning both the ARTCC and non-ARTCC partitions in one call. Reach for this when the airspace type is not known up-front (e.g. parsed from a URL); for ergonomic shortcuts, the partition-specific byAirport / byArtcc wrappers stay available.

OptionTypeDescription
typesReadonlySet<AirspaceType>Optional. When provided, acts as the authoritative inclusion filter; includeArtcc is ignored.
includeArtccbooleanDefaults to true. When false and types is omitted, ARTCC features are excluded.
// Every feature for the identifier, ARTCC included
const all = resolver.byIdentifier('ZNY');

// Only the non-ARTCC partition
const nonArtcc = resolver.byIdentifier('ZNY', { includeArtcc: false });

// Only matching types
const onlyClassB = resolver.byIdentifier('JFK', { types: new Set(['CLASS_B']) });

resolver.byCentroid(query)

Returns every feature whose polygon centroid is within toleranceDeg of (lon, lat). The centroid is computed per call (not cached) so this is O(n) over the corpus - suitable for occasional URL-driven lookups, not hot loops. Useful for resolving features with an empty identifier (some Class E5 surfaces), where the centroid is the fallback URL handle.

PropertyTypeDescription
lonnumberLongitude in decimal degrees (WGS84)
latnumberLatitude in decimal degrees (WGS84)
toleranceDegnumberOptional. Centroid match tolerance in degrees, applied independently to lon and lat. Defaults to 0.0001.
const matches = resolver.byCentroid({ lon: -118.4081, lat: 33.9425 });

resolver.withinBbox(bbox)

Returns every feature whose pre-indexed bounding box overlaps the query bbox. Reuses the bounding box cached at init time, so this is suitable for tight loops over the corpus. Bounding-box overlap is a coarse spatial filter: callers that need true polygon-polygon intersection should follow up with their own geometry test on the returned features.

const overlapping = resolver.withinBbox({
  minLon: -119,
  minLat: 33,
  maxLon: -118,
  maxLat: 35,
});

resolver.forEachIndexed(callback)

Read-only iteration over the indexed corpus, invoking callback once per feature with positional (feature, ring, boundingBox). Exposes the resolver's pre-parsed shape so callers that need to filter the corpus themselves do not have to reparse the source GeoJSON or recompute geometry per call. The ring and boundingBox arguments are the resolver's internal caches and must not be mutated.

resolver.forEachIndexed((feature, ring, boundingBox) => {
  // ring is the parsed exterior ring (number[][]).
  // boundingBox is the pre-computed axis-aligned bbox.
});

ARTCC altitude bounds

ARTCC features carry stratum-aligned floor/ceiling values for use with query():

StratumFloorCeiling
LOWSFC18,000 ft MSL
HIGH18,000 ft MSL60,000 ft MSL
UTA60,000 ft MSL99,999 ft MSL
CTASFC99,999 ft MSL
FIRSFC99,999 ft MSL
CTA/FIRSFC99,999 ft MSL

These are operational stratum approximations rather than legal limits. The 99,999 ceiling is a sentinel meaning "effectively unlimited" - queries above FL600 will still match the relevant stratum.

Oceanic FIR boundaries that cross the 180th meridian (ZAK FIR/CTA and ZAP FIR/CTA in the central Pacific) are split at the antimeridian during the data build, so each emitted feature has coordinates within the standard [-180, 180] range. A single source stratum produces two features in those cases - one for the eastern sub-polygon and one for the western - but both share the same identifier and artccStratum, so byArtcc("ZAK") returns them together.

Keywords

aviation

FAQs

Package last updated on 11 May 2026

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts