@codesign-eu/utils
v1.1.0
Published
Utility helpers for spatial, date/time, astronomy, and Maidenhead (QTH) grid operations used by Codesign applications.
Maintainers
Readme
@codesign-eu/utils
Shared TypeScript utilities for Codesign applications.
The library currently focuses on three areas:
- date and time helpers
- spatial / coordinate formatting helpers
- Maidenhead (QTH) grid conversion helpers
Installation
npm install @codesign-eu/utilsUsage
import { dateTimeService, spatialService, GridLocationService, type LatLngBoundsLike } from '@codesign-eu/utils'
const day = dateTimeService.formatDay(new Date('2026-04-28T12:30:00Z'))
const parsed = dateTimeService.parseDate('20260428')
const pointLabel = spatialService.coordinatesGeoJsonToString({
type: 'Point',
coordinates: [21.0122, 52.2297],
})
const locator = GridLocationService.latLngToGrid(52.2297, 21.0122, 6)
const center = GridLocationService.gridToLatLng('KO02mf')
const bounds: LatLngBoundsLike = {
getNorth: () => 54,
getEast: () => 22,
getSouth: () => 52,
getWest: () => 20,
}
const viewportLocators = GridLocationService.locatorFeaturesForBounds(bounds, 4)
const locatorEnvelope = GridLocationService.gridToBounds('KO02kk')
const boundsQuery = spatialService.leafletBoundsToString(bounds)
console.log(day, parsed, pointLabel, locator, center, viewportLocators[0]?.reference, locatorEnvelope, boundsQuery)Public API
dateTimeService
Helpers for formatting and comparing dates:
formatDay(date)timestampToString(date, showSeconds?)parseDate('YYYYMMDD')daysBetweenToday(date)timeAgo(date)dateIsFromTheFuture(date)
spatialService
Helpers for coordinate formatting and nested coordinate structures:
LatLngBoundsLikeswapLatLng(coordinates)leafletBoundsToString(boundsLike)getPointFromPolygon(coordinates)coordinatesGeoJsonToString(point)coordinatesGeoJsonToDegreesString(point)
LatLngBoundsLike is the exported lightweight bounds contract for leafletBoundsToString.
leafletBoundsToString stays compatible with Leaflet bounds objects, but the library does not require Leaflet as a consumer dependency.
GridLocationService
Helpers for Maidenhead (QTH) locator work.
Parsing and validation:
isValidLocator(value)-truefor a well-formed 2/4/6/8-character locator; case-insensitive, surrounding whitespace ignorednormalizeLocator(value)- canonical form (' ko02KK 'becomes'KO02kk'), ornullgetLocatorPrecision(value)-2 | 4 | 6 | 8, ornull
Conversions:
latLngToGrid(lat, lng, precision?)- defaults to precision6gridToLatLng(locator)- centre of the cellgridToBounds(locator)-[west, south, east, north], computed without turfgridToPolygon(locator)- the cell as a GeoJSON polygongetGridStep(precision)- cell size in degrees
Hierarchy:
getLocatorParent(locator)- one precision level up,nullfor a 2-character fieldgetLocatorChildren(locator)- one precision level down (100, 576 and 100 respectively), empty for an 8-character locator
Viewports:
locatorGridsForBounds(bounds, precision)- references overlapping the bounds, aligned to the Maidenhead gridcountLocatorGridsForBounds(bounds, precision)- how many references the call above would return, without building themlocatorFeaturesForBounds(bounds, precision)- reference, centre and polygon, ready to renderlocatorGridsForGeoJSON(feature, precision)- references that actually intersect the geometry, not just its bounding box
Supported precisions: 2, 4, 6, 8.
Functions that take a locator throw Invalid QTH locator format when the value is not one. Functions that take a precision throw Unsupported Maidenhead precision.
Two things worth knowing before rendering a grid:
- Cell counts grow fast. An 8-character grid divides the world into 43 200 x 43 200 cells, so check
countLocatorGridsForBoundsbefore asking for the references. - Bounds that wrap across the antimeridian are not split. They widen to the whole longitude range.
@codesign-eu/utils/maidenhead
The locator arithmetic is also published as a subpath entry with no runtime dependencies, for consumers that need locator maths without the geometry helpers - a Node service turning a locator into a database envelope, for example:
import { gridToBounds } from '@codesign-eu/utils/maidenhead'
const [west, south, east, north] = gridToBounds('KO02kk')The subpath exports everything listed above except gridToPolygon, locatorFeaturesForBounds and locatorGridsForGeoJSON, which need turf.
Development
npm install
npm run checkUseful commands:
npm run test
npm run build
npm run typecheck
npm run lintRelease Helpers
npm run version:patch
npm run version:minor
npm run version:majorPublishing uses prepack, so the package is rebuilt before npm publish.
