neaps 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/package.json +12 -5
  2. package/src/index.ts +0 -185
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "neaps",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Tide predictions",
5
5
  "keywords": [
6
6
  "tides",
@@ -18,14 +18,21 @@
18
18
  "license": "MIT",
19
19
  "author": "Brandon Keepers <brandon@openwaters.io>",
20
20
  "type": "module",
21
- "main": "src/index.ts",
22
- "scripts": {
23
- "build": "tsdown",
24
- "prepack": "npm run build"
21
+ "main": "dist/index.cjs",
22
+ "exports": {
23
+ ".": {
24
+ "types": "./dist/index.d.ts",
25
+ "import": "./dist/index.js",
26
+ "require": "./dist/index.cjs"
27
+ }
25
28
  },
26
29
  "files": [
27
30
  "dist"
28
31
  ],
32
+ "scripts": {
33
+ "build": "tsdown",
34
+ "prepack": "npm run build"
35
+ },
29
36
  "dependencies": {
30
37
  "@neaps/tide-predictor": "^0.2.0",
31
38
  "@neaps/tide-database": "^0.0",
package/src/index.ts DELETED
@@ -1,185 +0,0 @@
1
- import { getDistance } from 'geolib'
2
- import stations, { type Station } from '@neaps/tide-database'
3
- import tidePredictor, {
4
- type TimeSpan,
5
- type ExtremesInput
6
- } from '@neaps/tide-predictor'
7
- import type { GeolibInputCoordinates } from 'geolib/es/types'
8
-
9
- type DatumOption = {
10
- /** Datum to return predictions in. Defaults to 'MLLW' if available for the nearest station. */
11
- datum?: string
12
- }
13
-
14
- export type ExtremesOptions = ExtremesInput & DatumOption
15
- export type TimelineOptions = TimeSpan & DatumOption
16
- export type WaterLevelOptions = { time: Date } & DatumOption
17
-
18
- /**
19
- * Get extremes prediction using the nearest station to the given position.
20
- *
21
- * @example
22
- * ```ts
23
- * import { getExtremesPrediction } from 'neaps'
24
- *
25
- * const prediction = getExtremesPrediction({
26
- * latitude: 26.7, // or `lat`
27
- * longitude: -80.05, // or `lng` or `lon`
28
- * start: new Date('2025-12-17'),
29
- * end: new Date('2025-12-18'),
30
- * datum: 'MLLW', // optional, defaults to MLLW if available
31
- * })
32
- */
33
- export function getExtremesPrediction(
34
- options: GeolibInputCoordinates & ExtremesOptions
35
- ) {
36
- return nearestStation(options).getExtremesPrediction(options)
37
- }
38
-
39
- /**
40
- * Get timeline prediction using the nearest station to the given position.
41
- */
42
- export function getTimelinePrediction(
43
- options: GeolibInputCoordinates & TimelineOptions
44
- ) {
45
- return nearestStation(options).getTimelinePrediction(options)
46
- }
47
-
48
- /**
49
- * Get water level at a specific time using the nearest station to the given position.
50
- */
51
- export function getWaterLevelAtTime(
52
- options: GeolibInputCoordinates & WaterLevelOptions
53
- ) {
54
- return nearestStation(options).getWaterLevelAtTime(options)
55
- }
56
-
57
- /**
58
- * Find the nearest station to the given position.
59
- */
60
- export function nearestStation(position: GeolibInputCoordinates) {
61
- return stationsNear(position, 1)[0]
62
- }
63
-
64
- /**
65
- * Find stations near the given position.
66
- * @param limit Maximum number of stations to return (default: 10)
67
- */
68
- export function stationsNear(position: GeolibInputCoordinates, limit = 10) {
69
- return stations
70
- .map((station) => ({ station, distance: getDistance(position, station) }))
71
- .sort((a, b) => a.distance - b.distance)
72
- .slice(0, limit)
73
- .map(({ station, distance }) => useStation(station, distance))
74
- }
75
-
76
- /**
77
- * Find a specific station by its ID or source ID.
78
- */
79
- export function findStation(query: string) {
80
- const searches = [
81
- (s: Station) => s.id === query,
82
- (s: Station) => s.source.id === query
83
- ]
84
-
85
- let found: Station | undefined = undefined
86
-
87
- for (const search of searches) {
88
- found = stations.find(search)
89
- if (found) break
90
- }
91
-
92
- if (!found) throw new Error(`Station not found: ${query}`)
93
-
94
- return useStation(found)
95
- }
96
-
97
- export function useStation(station: Station, distance?: number) {
98
- // If subordinate station, use the reference station for datums and constituents
99
- let reference = station
100
- if (station.type === 'subordinate') {
101
- reference = findStation(station.offsets?.reference || '')
102
- }
103
- const { datums, harmonic_constituents } = reference
104
-
105
- // Use MLLW as the default datum if available
106
- const defaultDatum = 'MLLW' in datums ? 'MLLW' : undefined
107
-
108
- function getPredictor({ datum = defaultDatum }: DatumOption = {}) {
109
- let offset = 0
110
-
111
- if (datum) {
112
- const datumOffset = datums?.[datum]
113
- const mslOffset = datums?.['MSL']
114
-
115
- if (typeof datumOffset !== 'number') {
116
- throw new Error(
117
- `Station ${station.id} missing ${datum} datum. Available datums: ${Object.keys(datums || {}).join(', ')}`
118
- )
119
- }
120
-
121
- if (typeof mslOffset !== 'number') {
122
- throw new Error(
123
- `Station ${station.id} missing MSL datum, so predictions can't be given in ${datum}.`
124
- )
125
- }
126
-
127
- offset = mslOffset - datumOffset
128
- }
129
-
130
- return tidePredictor(harmonic_constituents, {
131
- phaseKey: 'phase_UTC',
132
- offset
133
- })
134
- }
135
-
136
- return {
137
- ...station,
138
- distance,
139
- datums,
140
- harmonic_constituents,
141
- defaultDatum,
142
- getExtremesPrediction({ datum = defaultDatum, ...input }: ExtremesOptions) {
143
- return {
144
- datum,
145
- distance,
146
- station,
147
- extremes: getPredictor({ datum }).getExtremesPrediction({
148
- ...input,
149
- offsets: station.offsets
150
- })
151
- }
152
- },
153
-
154
- getTimelinePrediction({
155
- datum = defaultDatum,
156
- ...params
157
- }: TimelineOptions) {
158
- if (station.type === 'subordinate') {
159
- throw new Error(
160
- `Timeline predictions are not supported for subordinate stations.`
161
- )
162
- }
163
-
164
- return {
165
- datum,
166
- station,
167
- timeline: getPredictor({ datum }).getTimelinePrediction(params)
168
- }
169
- },
170
-
171
- getWaterLevelAtTime({ time, datum = defaultDatum }: WaterLevelOptions) {
172
- if (station.type === 'subordinate') {
173
- throw new Error(
174
- `Water level predictions are not supported for subordinate stations.`
175
- )
176
- }
177
-
178
- return {
179
- datum,
180
- station,
181
- ...getPredictor({ datum }).getWaterLevelAtTime({ time })
182
- }
183
- }
184
- }
185
- }