neaps 0.4.0 → 0.5.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.
package/dist/index.cjs CHANGED
@@ -17,7 +17,7 @@ const defaultUnits = "meters";
17
17
  * longitude: -80.05, // or `lng` or `lon`
18
18
  * start: new Date('2025-12-17'),
19
19
  * end: new Date('2025-12-18'),
20
- * datum: 'MLLW', // optional, defaults to MLLW if available
20
+ * datum: 'MLLW', // optional, defaults to station's datum
21
21
  * })
22
22
  */
23
23
  function getExtremesPrediction(options) {
@@ -67,7 +67,7 @@ function useStation(station, distance) {
67
67
  let reference = station;
68
68
  if (station.type === "subordinate" && station.offsets?.reference) reference = findStation(station.offsets?.reference);
69
69
  const { datums, harmonic_constituents } = reference;
70
- const defaultDatum = "MLLW" in datums ? "MLLW" : void 0;
70
+ const defaultDatum = station.chart_datum in datums ? station.chart_datum : void 0;
71
71
  function getPredictor({ datum = defaultDatum, nodeCorrections } = {}) {
72
72
  let offset = 0;
73
73
  if (datum) {
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":["stations"],"sources":["../src/index.ts"],"sourcesContent":["import {\n stations,\n near,\n nearest,\n type Station,\n type NearOptions,\n type NearestOptions,\n} from \"@neaps/tide-database\";\nimport { createTidePredictor, type TimeSpan, type ExtremesInput } from \"@neaps/tide-predictor\";\n\ntype Units = \"meters\" | \"feet\";\ntype PredictionOptions = {\n /** Datum to return predictions in. Defaults to 'MLLW' if available for the nearest station. */\n datum?: string;\n\n /** Units for returned water levels. Defaults to 'meters'. */\n units?: Units;\n\n /** Nodal correction fundamentals. Defaults to 'iho'. */\n nodeCorrections?: \"iho\" | \"schureman\";\n};\n\nexport type ExtremesOptions = ExtremesInput & PredictionOptions;\nexport type TimelineOptions = TimeSpan & PredictionOptions;\nexport type WaterLevelOptions = { time: Date } & PredictionOptions;\n\nconst feetPerMeter = 3.2808399;\nconst defaultUnits: Units = \"meters\";\n\n/**\n * Get extremes prediction using the nearest station to the given position.\n *\n * @example\n * ```ts\n * import { getExtremesPrediction } from 'neaps'\n *\n * const prediction = getExtremesPrediction({\n * latitude: 26.7, // or `lat`\n * longitude: -80.05, // or `lng` or `lon`\n * start: new Date('2025-12-17'),\n * end: new Date('2025-12-18'),\n * datum: 'MLLW', // optional, defaults to MLLW if available\n * })\n */\nexport function getExtremesPrediction(options: NearestOptions & ExtremesOptions) {\n return nearestStation(options).getExtremesPrediction(options);\n}\n\n/**\n * Get timeline prediction using the nearest station to the given position.\n */\nexport function getTimelinePrediction(options: NearestOptions & TimelineOptions) {\n return nearestStation(options).getTimelinePrediction(options);\n}\n\n/**\n * Get water level at a specific time using the nearest station to the given position.\n */\nexport function getWaterLevelAtTime(options: NearestOptions & WaterLevelOptions) {\n return nearestStation(options).getWaterLevelAtTime(options);\n}\n\n/**\n * Find the nearest station to the given position.\n */\nexport function nearestStation(options: NearestOptions) {\n const data = nearest(options);\n if (!data) throw new Error(`No stations found with options: ${JSON.stringify(options)}`);\n return useStation(...data);\n}\n\n/**\n * Find stations near the given position.\n * @param limit Maximum number of stations to return (default: 10)\n */\nexport function stationsNear(options: NearOptions) {\n return near(options).map(([station, distance]) => useStation(station, distance));\n}\n\n/**\n * Find a specific station by its ID or source ID.\n */\nexport function findStation(query: string) {\n const searches = [(s: Station) => s.id === query, (s: Station) => s.source.id === query];\n\n let found: Station | undefined = undefined;\n\n for (const search of searches) {\n found = stations.find(search);\n if (found) break;\n }\n\n if (!found) throw new Error(`Station not found: ${query}`);\n\n return useStation(found);\n}\n\nexport function useStation(station: Station, distance?: number) {\n // If subordinate station, use the reference station for datums and constituents\n let reference = station;\n if (station.type === \"subordinate\" && station.offsets?.reference) {\n reference = findStation(station.offsets?.reference);\n }\n const { datums, harmonic_constituents } = reference;\n\n // Use MLLW as the default datum if available\n const defaultDatum = \"MLLW\" in datums ? \"MLLW\" : undefined;\n\n function getPredictor({ datum = defaultDatum, nodeCorrections }: PredictionOptions = {}) {\n let offset = 0;\n\n if (datum) {\n const datumOffset = datums?.[datum];\n const mslOffset = datums?.[\"MSL\"];\n\n if (typeof datumOffset !== \"number\") {\n throw new Error(\n `Station ${station.id} missing ${datum} datum. Available datums: ${Object.keys(datums).join(\", \")}`,\n );\n }\n\n if (typeof mslOffset !== \"number\") {\n throw new Error(\n `Station ${station.id} missing MSL datum, so predictions can't be given in ${datum}.`,\n );\n }\n\n offset = mslOffset - datumOffset;\n }\n\n return createTidePredictor(harmonic_constituents, { offset, nodeCorrections });\n }\n\n return {\n ...station,\n distance,\n datums,\n harmonic_constituents,\n defaultDatum,\n getExtremesPrediction({\n datum = defaultDatum,\n units = defaultUnits,\n nodeCorrections,\n ...options\n }: ExtremesOptions) {\n const extremes = getPredictor({ datum, nodeCorrections })\n .getExtremesPrediction({ ...options, offsets: station.offsets })\n .map((e) => toPreferredUnits(e, units));\n\n return { datum, units, station, distance, extremes };\n },\n\n getTimelinePrediction({\n datum = defaultDatum,\n units = defaultUnits,\n nodeCorrections,\n ...options\n }: TimelineOptions) {\n if (station.type === \"subordinate\") {\n throw new Error(`Timeline predictions are not supported for subordinate stations.`);\n }\n const timeline = getPredictor({ datum, nodeCorrections })\n .getTimelinePrediction(options)\n .map((e) => toPreferredUnits(e, units));\n\n return { datum, units, station, distance, timeline };\n },\n\n getWaterLevelAtTime({\n time,\n datum = defaultDatum,\n units = defaultUnits,\n nodeCorrections,\n }: WaterLevelOptions) {\n if (station.type === \"subordinate\") {\n throw new Error(`Water level predictions are not supported for subordinate stations.`);\n }\n\n const prediction = toPreferredUnits(\n getPredictor({ datum, nodeCorrections }).getWaterLevelAtTime({ time }),\n units,\n );\n\n return { datum, units, station, distance, ...prediction };\n },\n };\n}\n\nfunction toPreferredUnits<T extends { level: number }>(prediction: T, units: Units): T {\n let { level } = prediction;\n if (units === \"feet\") level *= feetPerMeter;\n else if (units !== \"meters\") throw new Error(`Unsupported units: ${units}`);\n return { ...prediction, level };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","names":["stations"],"sources":["../src/index.ts"],"sourcesContent":["import {\n stations,\n near,\n nearest,\n type Station,\n type NearOptions,\n type NearestOptions,\n} from \"@neaps/tide-database\";\nimport { createTidePredictor, type ExtremesInput, type TimelineInput } from \"@neaps/tide-predictor\";\n\ntype Units = \"meters\" | \"feet\";\ntype PredictionOptions = {\n /** Datum to return predictions in. Defaults to the nearest station's datum. */\n datum?: string;\n\n /** Units for returned water levels. Defaults to 'meters'. */\n units?: Units;\n\n /** Nodal correction fundamentals. Defaults to 'iho'. */\n nodeCorrections?: \"iho\" | \"schureman\";\n};\n\nexport type ExtremesOptions = ExtremesInput & PredictionOptions;\nexport type TimelineOptions = TimelineInput & PredictionOptions;\nexport type WaterLevelOptions = { time: Date } & PredictionOptions;\n\nconst feetPerMeter = 3.2808399;\nconst defaultUnits: Units = \"meters\";\n\n/**\n * Get extremes prediction using the nearest station to the given position.\n *\n * @example\n * ```ts\n * import { getExtremesPrediction } from 'neaps'\n *\n * const prediction = getExtremesPrediction({\n * latitude: 26.7, // or `lat`\n * longitude: -80.05, // or `lng` or `lon`\n * start: new Date('2025-12-17'),\n * end: new Date('2025-12-18'),\n * datum: 'MLLW', // optional, defaults to station's datum\n * })\n */\nexport function getExtremesPrediction(options: NearestOptions & ExtremesOptions) {\n return nearestStation(options).getExtremesPrediction(options);\n}\n\n/**\n * Get timeline prediction using the nearest station to the given position.\n */\nexport function getTimelinePrediction(options: NearestOptions & TimelineOptions) {\n return nearestStation(options).getTimelinePrediction(options);\n}\n\n/**\n * Get water level at a specific time using the nearest station to the given position.\n */\nexport function getWaterLevelAtTime(options: NearestOptions & WaterLevelOptions) {\n return nearestStation(options).getWaterLevelAtTime(options);\n}\n\n/**\n * Find the nearest station to the given position.\n */\nexport function nearestStation(options: NearestOptions) {\n const data = nearest(options);\n if (!data) throw new Error(`No stations found with options: ${JSON.stringify(options)}`);\n return useStation(...data);\n}\n\n/**\n * Find stations near the given position.\n * @param limit Maximum number of stations to return (default: 10)\n */\nexport function stationsNear(options: NearOptions) {\n return near(options).map(([station, distance]) => useStation(station, distance));\n}\n\n/**\n * Find a specific station by its ID or source ID.\n */\nexport function findStation(query: string) {\n const searches = [(s: Station) => s.id === query, (s: Station) => s.source.id === query];\n\n let found: Station | undefined = undefined;\n\n for (const search of searches) {\n found = stations.find(search);\n if (found) break;\n }\n\n if (!found) throw new Error(`Station not found: ${query}`);\n\n return useStation(found);\n}\n\nexport function useStation(station: Station, distance?: number) {\n // If subordinate station, use the reference station for datums and constituents\n let reference = station;\n if (station.type === \"subordinate\" && station.offsets?.reference) {\n reference = findStation(station.offsets?.reference);\n }\n const { datums, harmonic_constituents } = reference;\n\n // Use station chart datum as the default datum if available\n const defaultDatum = station.chart_datum in datums ? station.chart_datum : undefined;\n\n function getPredictor({ datum = defaultDatum, nodeCorrections }: PredictionOptions = {}) {\n let offset = 0;\n\n if (datum) {\n const datumOffset = datums?.[datum];\n const mslOffset = datums?.[\"MSL\"];\n\n if (typeof datumOffset !== \"number\") {\n throw new Error(\n `Station ${station.id} missing ${datum} datum. Available datums: ${Object.keys(datums).join(\", \")}`,\n );\n }\n\n if (typeof mslOffset !== \"number\") {\n throw new Error(\n `Station ${station.id} missing MSL datum, so predictions can't be given in ${datum}.`,\n );\n }\n\n offset = mslOffset - datumOffset;\n }\n\n return createTidePredictor(harmonic_constituents, { offset, nodeCorrections });\n }\n\n return {\n ...station,\n distance,\n datums,\n harmonic_constituents,\n defaultDatum,\n getExtremesPrediction({\n datum = defaultDatum,\n units = defaultUnits,\n nodeCorrections,\n ...options\n }: ExtremesOptions) {\n const extremes = getPredictor({ datum, nodeCorrections })\n .getExtremesPrediction({ ...options, offsets: station.offsets })\n .map((e) => toPreferredUnits(e, units));\n\n return { datum, units, station, distance, extremes };\n },\n\n getTimelinePrediction({\n datum = defaultDatum,\n units = defaultUnits,\n nodeCorrections,\n ...options\n }: TimelineOptions) {\n if (station.type === \"subordinate\") {\n throw new Error(`Timeline predictions are not supported for subordinate stations.`);\n }\n const timeline = getPredictor({ datum, nodeCorrections })\n .getTimelinePrediction(options)\n .map((e) => toPreferredUnits(e, units));\n\n return { datum, units, station, distance, timeline };\n },\n\n getWaterLevelAtTime({\n time,\n datum = defaultDatum,\n units = defaultUnits,\n nodeCorrections,\n }: WaterLevelOptions) {\n if (station.type === \"subordinate\") {\n throw new Error(`Water level predictions are not supported for subordinate stations.`);\n }\n\n const prediction = toPreferredUnits(\n getPredictor({ datum, nodeCorrections }).getWaterLevelAtTime({ time }),\n units,\n );\n\n return { datum, units, station, distance, ...prediction };\n },\n };\n}\n\nfunction toPreferredUnits<T extends { level: number }>(prediction: T, units: Units): T {\n let { level } = prediction;\n if (units === \"feet\") level *= feetPerMeter;\n else if (units !== \"meters\") throw new Error(`Unsupported units: ${units}`);\n return { ...prediction, level };\n}\n"],"mappings":"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"}
package/dist/index.d.cts CHANGED
@@ -1,16 +1,17 @@
1
+ import * as _neaps_tide_predictor0 from "@neaps/tide-predictor";
2
+ import { ExtremesInput, TimelineInput } from "@neaps/tide-predictor";
1
3
  import * as _neaps_tide_database0 from "@neaps/tide-database";
2
4
  import { NearOptions, NearestOptions, Station } from "@neaps/tide-database";
3
- import { ExtremesInput, TimeSpan } from "@neaps/tide-predictor";
4
5
 
5
6
  //#region src/index.d.ts
6
7
  type Units = "meters" | "feet";
7
8
  type PredictionOptions = {
8
- /** Datum to return predictions in. Defaults to 'MLLW' if available for the nearest station. */datum?: string; /** Units for returned water levels. Defaults to 'meters'. */
9
+ /** Datum to return predictions in. Defaults to the nearest station's datum. */datum?: string; /** Units for returned water levels. Defaults to 'meters'. */
9
10
  units?: Units; /** Nodal correction fundamentals. Defaults to 'iho'. */
10
11
  nodeCorrections?: "iho" | "schureman";
11
12
  };
12
13
  type ExtremesOptions = ExtremesInput & PredictionOptions;
13
- type TimelineOptions = TimeSpan & PredictionOptions;
14
+ type TimelineOptions = TimelineInput & PredictionOptions;
14
15
  type WaterLevelOptions = {
15
16
  time: Date;
16
17
  } & PredictionOptions;
@@ -26,30 +27,38 @@ type WaterLevelOptions = {
26
27
  * longitude: -80.05, // or `lng` or `lon`
27
28
  * start: new Date('2025-12-17'),
28
29
  * end: new Date('2025-12-18'),
29
- * datum: 'MLLW', // optional, defaults to MLLW if available
30
+ * datum: 'MLLW', // optional, defaults to station's datum
30
31
  * })
31
32
  */
32
33
  declare function getExtremesPrediction(options: NearestOptions & ExtremesOptions): {
33
- datum: any;
34
- units: any;
34
+ datum: string | undefined;
35
+ units: Units;
35
36
  station: Station;
36
37
  distance: number | undefined;
37
- extremes: any;
38
+ extremes: _neaps_tide_predictor0.Extreme[];
38
39
  };
39
40
  /**
40
41
  * Get timeline prediction using the nearest station to the given position.
41
42
  */
42
43
  declare function getTimelinePrediction(options: NearestOptions & TimelineOptions): {
43
- datum: any;
44
- units: any;
44
+ datum: string | undefined;
45
+ units: Units;
45
46
  station: Station;
46
47
  distance: number | undefined;
47
- timeline: any;
48
+ timeline: _neaps_tide_predictor0.TimelinePoint[];
48
49
  };
49
50
  /**
50
51
  * Get water level at a specific time using the nearest station to the given position.
51
52
  */
52
- declare function getWaterLevelAtTime(options: NearestOptions & WaterLevelOptions): any;
53
+ declare function getWaterLevelAtTime(options: NearestOptions & WaterLevelOptions): {
54
+ time: Date;
55
+ hour: number;
56
+ level: number;
57
+ datum: string | undefined;
58
+ units: Units;
59
+ station: Station;
60
+ distance: number | undefined;
61
+ };
53
62
  /**
54
63
  * Find the nearest station to the given position.
55
64
  */
@@ -64,11 +73,11 @@ declare function nearestStation(options: NearestOptions): {
64
73
  nodeCorrections,
65
74
  ...options
66
75
  }: ExtremesOptions): {
67
- datum: any;
68
- units: any;
76
+ datum: string | undefined;
77
+ units: Units;
69
78
  station: Station;
70
79
  distance: number | undefined;
71
- extremes: any;
80
+ extremes: _neaps_tide_predictor0.Extreme[];
72
81
  };
73
82
  getTimelinePrediction({
74
83
  datum,
@@ -76,18 +85,26 @@ declare function nearestStation(options: NearestOptions): {
76
85
  nodeCorrections,
77
86
  ...options
78
87
  }: TimelineOptions): {
79
- datum: any;
80
- units: any;
88
+ datum: string | undefined;
89
+ units: Units;
81
90
  station: Station;
82
91
  distance: number | undefined;
83
- timeline: any;
92
+ timeline: _neaps_tide_predictor0.TimelinePoint[];
84
93
  };
85
94
  getWaterLevelAtTime({
86
95
  time,
87
96
  datum,
88
97
  units,
89
98
  nodeCorrections
90
- }: WaterLevelOptions): any;
99
+ }: WaterLevelOptions): {
100
+ time: Date;
101
+ hour: number;
102
+ level: number;
103
+ datum: string | undefined;
104
+ units: Units;
105
+ station: Station;
106
+ distance: number | undefined;
107
+ };
91
108
  id: string;
92
109
  name: string;
93
110
  continent: string;
@@ -122,6 +139,11 @@ declare function nearestStation(options: NearestOptions): {
122
139
  low: number;
123
140
  };
124
141
  };
142
+ chart_datum: string;
143
+ epoch?: {
144
+ start: string;
145
+ end: string;
146
+ };
125
147
  };
126
148
  /**
127
149
  * Find stations near the given position.
@@ -138,11 +160,11 @@ declare function stationsNear(options: NearOptions): {
138
160
  nodeCorrections,
139
161
  ...options
140
162
  }: ExtremesOptions): {
141
- datum: any;
142
- units: any;
163
+ datum: string | undefined;
164
+ units: Units;
143
165
  station: Station;
144
166
  distance: number | undefined;
145
- extremes: any;
167
+ extremes: _neaps_tide_predictor0.Extreme[];
146
168
  };
147
169
  getTimelinePrediction({
148
170
  datum,
@@ -150,18 +172,26 @@ declare function stationsNear(options: NearOptions): {
150
172
  nodeCorrections,
151
173
  ...options
152
174
  }: TimelineOptions): {
153
- datum: any;
154
- units: any;
175
+ datum: string | undefined;
176
+ units: Units;
155
177
  station: Station;
156
178
  distance: number | undefined;
157
- timeline: any;
179
+ timeline: _neaps_tide_predictor0.TimelinePoint[];
158
180
  };
159
181
  getWaterLevelAtTime({
160
182
  time,
161
183
  datum,
162
184
  units,
163
185
  nodeCorrections
164
- }: WaterLevelOptions): any;
186
+ }: WaterLevelOptions): {
187
+ time: Date;
188
+ hour: number;
189
+ level: number;
190
+ datum: string | undefined;
191
+ units: Units;
192
+ station: Station;
193
+ distance: number | undefined;
194
+ };
165
195
  id: string;
166
196
  name: string;
167
197
  continent: string;
@@ -196,6 +226,11 @@ declare function stationsNear(options: NearOptions): {
196
226
  low: number;
197
227
  };
198
228
  };
229
+ chart_datum: string;
230
+ epoch?: {
231
+ start: string;
232
+ end: string;
233
+ };
199
234
  }[];
200
235
  /**
201
236
  * Find a specific station by its ID or source ID.
@@ -211,11 +246,11 @@ declare function findStation(query: string): {
211
246
  nodeCorrections,
212
247
  ...options
213
248
  }: ExtremesOptions): {
214
- datum: any;
215
- units: any;
249
+ datum: string | undefined;
250
+ units: Units;
216
251
  station: Station;
217
252
  distance: number | undefined;
218
- extremes: any;
253
+ extremes: _neaps_tide_predictor0.Extreme[];
219
254
  };
220
255
  getTimelinePrediction({
221
256
  datum,
@@ -223,18 +258,26 @@ declare function findStation(query: string): {
223
258
  nodeCorrections,
224
259
  ...options
225
260
  }: TimelineOptions): {
226
- datum: any;
227
- units: any;
261
+ datum: string | undefined;
262
+ units: Units;
228
263
  station: Station;
229
264
  distance: number | undefined;
230
- timeline: any;
265
+ timeline: _neaps_tide_predictor0.TimelinePoint[];
231
266
  };
232
267
  getWaterLevelAtTime({
233
268
  time,
234
269
  datum,
235
270
  units,
236
271
  nodeCorrections
237
- }: WaterLevelOptions): any;
272
+ }: WaterLevelOptions): {
273
+ time: Date;
274
+ hour: number;
275
+ level: number;
276
+ datum: string | undefined;
277
+ units: Units;
278
+ station: Station;
279
+ distance: number | undefined;
280
+ };
238
281
  id: string;
239
282
  name: string;
240
283
  continent: string;
@@ -269,6 +312,11 @@ declare function findStation(query: string): {
269
312
  low: number;
270
313
  };
271
314
  };
315
+ chart_datum: string;
316
+ epoch?: {
317
+ start: string;
318
+ end: string;
319
+ };
272
320
  };
273
321
  declare function useStation(station: Station, distance?: number): {
274
322
  distance: number | undefined;
@@ -281,11 +329,11 @@ declare function useStation(station: Station, distance?: number): {
281
329
  nodeCorrections,
282
330
  ...options
283
331
  }: ExtremesOptions): {
284
- datum: any;
285
- units: any;
332
+ datum: string | undefined;
333
+ units: Units;
286
334
  station: Station;
287
335
  distance: number | undefined;
288
- extremes: any;
336
+ extremes: _neaps_tide_predictor0.Extreme[];
289
337
  };
290
338
  getTimelinePrediction({
291
339
  datum,
@@ -293,18 +341,26 @@ declare function useStation(station: Station, distance?: number): {
293
341
  nodeCorrections,
294
342
  ...options
295
343
  }: TimelineOptions): {
296
- datum: any;
297
- units: any;
344
+ datum: string | undefined;
345
+ units: Units;
298
346
  station: Station;
299
347
  distance: number | undefined;
300
- timeline: any;
348
+ timeline: _neaps_tide_predictor0.TimelinePoint[];
301
349
  };
302
350
  getWaterLevelAtTime({
303
351
  time,
304
352
  datum,
305
353
  units,
306
354
  nodeCorrections
307
- }: WaterLevelOptions): any;
355
+ }: WaterLevelOptions): {
356
+ time: Date;
357
+ hour: number;
358
+ level: number;
359
+ datum: string | undefined;
360
+ units: Units;
361
+ station: Station;
362
+ distance: number | undefined;
363
+ };
308
364
  id: string;
309
365
  name: string;
310
366
  continent: string;
@@ -339,6 +395,11 @@ declare function useStation(station: Station, distance?: number): {
339
395
  low: number;
340
396
  };
341
397
  };
398
+ chart_datum: string;
399
+ epoch?: {
400
+ start: string;
401
+ end: string;
402
+ };
342
403
  };
343
404
  //#endregion
344
405
  export { ExtremesOptions, TimelineOptions, WaterLevelOptions, findStation, getExtremesPrediction, getTimelinePrediction, getWaterLevelAtTime, nearestStation, stationsNear, useStation };
package/dist/index.d.ts CHANGED
@@ -1,16 +1,17 @@
1
1
  import * as _neaps_tide_database0 from "@neaps/tide-database";
2
2
  import { NearOptions, NearestOptions, Station } from "@neaps/tide-database";
3
- import { ExtremesInput, TimeSpan } from "@neaps/tide-predictor";
3
+ import * as _neaps_tide_predictor0 from "@neaps/tide-predictor";
4
+ import { ExtremesInput, TimelineInput } from "@neaps/tide-predictor";
4
5
 
5
6
  //#region src/index.d.ts
6
7
  type Units = "meters" | "feet";
7
8
  type PredictionOptions = {
8
- /** Datum to return predictions in. Defaults to 'MLLW' if available for the nearest station. */datum?: string; /** Units for returned water levels. Defaults to 'meters'. */
9
+ /** Datum to return predictions in. Defaults to the nearest station's datum. */datum?: string; /** Units for returned water levels. Defaults to 'meters'. */
9
10
  units?: Units; /** Nodal correction fundamentals. Defaults to 'iho'. */
10
11
  nodeCorrections?: "iho" | "schureman";
11
12
  };
12
13
  type ExtremesOptions = ExtremesInput & PredictionOptions;
13
- type TimelineOptions = TimeSpan & PredictionOptions;
14
+ type TimelineOptions = TimelineInput & PredictionOptions;
14
15
  type WaterLevelOptions = {
15
16
  time: Date;
16
17
  } & PredictionOptions;
@@ -26,30 +27,38 @@ type WaterLevelOptions = {
26
27
  * longitude: -80.05, // or `lng` or `lon`
27
28
  * start: new Date('2025-12-17'),
28
29
  * end: new Date('2025-12-18'),
29
- * datum: 'MLLW', // optional, defaults to MLLW if available
30
+ * datum: 'MLLW', // optional, defaults to station's datum
30
31
  * })
31
32
  */
32
33
  declare function getExtremesPrediction(options: NearestOptions & ExtremesOptions): {
33
- datum: any;
34
- units: any;
34
+ datum: string | undefined;
35
+ units: Units;
35
36
  station: Station;
36
37
  distance: number | undefined;
37
- extremes: any;
38
+ extremes: _neaps_tide_predictor0.Extreme[];
38
39
  };
39
40
  /**
40
41
  * Get timeline prediction using the nearest station to the given position.
41
42
  */
42
43
  declare function getTimelinePrediction(options: NearestOptions & TimelineOptions): {
43
- datum: any;
44
- units: any;
44
+ datum: string | undefined;
45
+ units: Units;
45
46
  station: Station;
46
47
  distance: number | undefined;
47
- timeline: any;
48
+ timeline: _neaps_tide_predictor0.TimelinePoint[];
48
49
  };
49
50
  /**
50
51
  * Get water level at a specific time using the nearest station to the given position.
51
52
  */
52
- declare function getWaterLevelAtTime(options: NearestOptions & WaterLevelOptions): any;
53
+ declare function getWaterLevelAtTime(options: NearestOptions & WaterLevelOptions): {
54
+ time: Date;
55
+ hour: number;
56
+ level: number;
57
+ datum: string | undefined;
58
+ units: Units;
59
+ station: Station;
60
+ distance: number | undefined;
61
+ };
53
62
  /**
54
63
  * Find the nearest station to the given position.
55
64
  */
@@ -64,11 +73,11 @@ declare function nearestStation(options: NearestOptions): {
64
73
  nodeCorrections,
65
74
  ...options
66
75
  }: ExtremesOptions): {
67
- datum: any;
68
- units: any;
76
+ datum: string | undefined;
77
+ units: Units;
69
78
  station: Station;
70
79
  distance: number | undefined;
71
- extremes: any;
80
+ extremes: _neaps_tide_predictor0.Extreme[];
72
81
  };
73
82
  getTimelinePrediction({
74
83
  datum,
@@ -76,18 +85,26 @@ declare function nearestStation(options: NearestOptions): {
76
85
  nodeCorrections,
77
86
  ...options
78
87
  }: TimelineOptions): {
79
- datum: any;
80
- units: any;
88
+ datum: string | undefined;
89
+ units: Units;
81
90
  station: Station;
82
91
  distance: number | undefined;
83
- timeline: any;
92
+ timeline: _neaps_tide_predictor0.TimelinePoint[];
84
93
  };
85
94
  getWaterLevelAtTime({
86
95
  time,
87
96
  datum,
88
97
  units,
89
98
  nodeCorrections
90
- }: WaterLevelOptions): any;
99
+ }: WaterLevelOptions): {
100
+ time: Date;
101
+ hour: number;
102
+ level: number;
103
+ datum: string | undefined;
104
+ units: Units;
105
+ station: Station;
106
+ distance: number | undefined;
107
+ };
91
108
  id: string;
92
109
  name: string;
93
110
  continent: string;
@@ -122,6 +139,11 @@ declare function nearestStation(options: NearestOptions): {
122
139
  low: number;
123
140
  };
124
141
  };
142
+ chart_datum: string;
143
+ epoch?: {
144
+ start: string;
145
+ end: string;
146
+ };
125
147
  };
126
148
  /**
127
149
  * Find stations near the given position.
@@ -138,11 +160,11 @@ declare function stationsNear(options: NearOptions): {
138
160
  nodeCorrections,
139
161
  ...options
140
162
  }: ExtremesOptions): {
141
- datum: any;
142
- units: any;
163
+ datum: string | undefined;
164
+ units: Units;
143
165
  station: Station;
144
166
  distance: number | undefined;
145
- extremes: any;
167
+ extremes: _neaps_tide_predictor0.Extreme[];
146
168
  };
147
169
  getTimelinePrediction({
148
170
  datum,
@@ -150,18 +172,26 @@ declare function stationsNear(options: NearOptions): {
150
172
  nodeCorrections,
151
173
  ...options
152
174
  }: TimelineOptions): {
153
- datum: any;
154
- units: any;
175
+ datum: string | undefined;
176
+ units: Units;
155
177
  station: Station;
156
178
  distance: number | undefined;
157
- timeline: any;
179
+ timeline: _neaps_tide_predictor0.TimelinePoint[];
158
180
  };
159
181
  getWaterLevelAtTime({
160
182
  time,
161
183
  datum,
162
184
  units,
163
185
  nodeCorrections
164
- }: WaterLevelOptions): any;
186
+ }: WaterLevelOptions): {
187
+ time: Date;
188
+ hour: number;
189
+ level: number;
190
+ datum: string | undefined;
191
+ units: Units;
192
+ station: Station;
193
+ distance: number | undefined;
194
+ };
165
195
  id: string;
166
196
  name: string;
167
197
  continent: string;
@@ -196,6 +226,11 @@ declare function stationsNear(options: NearOptions): {
196
226
  low: number;
197
227
  };
198
228
  };
229
+ chart_datum: string;
230
+ epoch?: {
231
+ start: string;
232
+ end: string;
233
+ };
199
234
  }[];
200
235
  /**
201
236
  * Find a specific station by its ID or source ID.
@@ -211,11 +246,11 @@ declare function findStation(query: string): {
211
246
  nodeCorrections,
212
247
  ...options
213
248
  }: ExtremesOptions): {
214
- datum: any;
215
- units: any;
249
+ datum: string | undefined;
250
+ units: Units;
216
251
  station: Station;
217
252
  distance: number | undefined;
218
- extremes: any;
253
+ extremes: _neaps_tide_predictor0.Extreme[];
219
254
  };
220
255
  getTimelinePrediction({
221
256
  datum,
@@ -223,18 +258,26 @@ declare function findStation(query: string): {
223
258
  nodeCorrections,
224
259
  ...options
225
260
  }: TimelineOptions): {
226
- datum: any;
227
- units: any;
261
+ datum: string | undefined;
262
+ units: Units;
228
263
  station: Station;
229
264
  distance: number | undefined;
230
- timeline: any;
265
+ timeline: _neaps_tide_predictor0.TimelinePoint[];
231
266
  };
232
267
  getWaterLevelAtTime({
233
268
  time,
234
269
  datum,
235
270
  units,
236
271
  nodeCorrections
237
- }: WaterLevelOptions): any;
272
+ }: WaterLevelOptions): {
273
+ time: Date;
274
+ hour: number;
275
+ level: number;
276
+ datum: string | undefined;
277
+ units: Units;
278
+ station: Station;
279
+ distance: number | undefined;
280
+ };
238
281
  id: string;
239
282
  name: string;
240
283
  continent: string;
@@ -269,6 +312,11 @@ declare function findStation(query: string): {
269
312
  low: number;
270
313
  };
271
314
  };
315
+ chart_datum: string;
316
+ epoch?: {
317
+ start: string;
318
+ end: string;
319
+ };
272
320
  };
273
321
  declare function useStation(station: Station, distance?: number): {
274
322
  distance: number | undefined;
@@ -281,11 +329,11 @@ declare function useStation(station: Station, distance?: number): {
281
329
  nodeCorrections,
282
330
  ...options
283
331
  }: ExtremesOptions): {
284
- datum: any;
285
- units: any;
332
+ datum: string | undefined;
333
+ units: Units;
286
334
  station: Station;
287
335
  distance: number | undefined;
288
- extremes: any;
336
+ extremes: _neaps_tide_predictor0.Extreme[];
289
337
  };
290
338
  getTimelinePrediction({
291
339
  datum,
@@ -293,18 +341,26 @@ declare function useStation(station: Station, distance?: number): {
293
341
  nodeCorrections,
294
342
  ...options
295
343
  }: TimelineOptions): {
296
- datum: any;
297
- units: any;
344
+ datum: string | undefined;
345
+ units: Units;
298
346
  station: Station;
299
347
  distance: number | undefined;
300
- timeline: any;
348
+ timeline: _neaps_tide_predictor0.TimelinePoint[];
301
349
  };
302
350
  getWaterLevelAtTime({
303
351
  time,
304
352
  datum,
305
353
  units,
306
354
  nodeCorrections
307
- }: WaterLevelOptions): any;
355
+ }: WaterLevelOptions): {
356
+ time: Date;
357
+ hour: number;
358
+ level: number;
359
+ datum: string | undefined;
360
+ units: Units;
361
+ station: Station;
362
+ distance: number | undefined;
363
+ };
308
364
  id: string;
309
365
  name: string;
310
366
  continent: string;
@@ -339,6 +395,11 @@ declare function useStation(station: Station, distance?: number): {
339
395
  low: number;
340
396
  };
341
397
  };
398
+ chart_datum: string;
399
+ epoch?: {
400
+ start: string;
401
+ end: string;
402
+ };
342
403
  };
343
404
  //#endregion
344
405
  export { ExtremesOptions, TimelineOptions, WaterLevelOptions, findStation, getExtremesPrediction, getTimelinePrediction, getWaterLevelAtTime, nearestStation, stationsNear, useStation };
package/dist/index.js CHANGED
@@ -16,7 +16,7 @@ const defaultUnits = "meters";
16
16
  * longitude: -80.05, // or `lng` or `lon`
17
17
  * start: new Date('2025-12-17'),
18
18
  * end: new Date('2025-12-18'),
19
- * datum: 'MLLW', // optional, defaults to MLLW if available
19
+ * datum: 'MLLW', // optional, defaults to station's datum
20
20
  * })
21
21
  */
22
22
  function getExtremesPrediction(options) {
@@ -66,7 +66,7 @@ function useStation(station, distance) {
66
66
  let reference = station;
67
67
  if (station.type === "subordinate" && station.offsets?.reference) reference = findStation(station.offsets?.reference);
68
68
  const { datums, harmonic_constituents } = reference;
69
- const defaultDatum = "MLLW" in datums ? "MLLW" : void 0;
69
+ const defaultDatum = station.chart_datum in datums ? station.chart_datum : void 0;
70
70
  function getPredictor({ datum = defaultDatum, nodeCorrections } = {}) {
71
71
  let offset = 0;
72
72
  if (datum) {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["import {\n stations,\n near,\n nearest,\n type Station,\n type NearOptions,\n type NearestOptions,\n} from \"@neaps/tide-database\";\nimport { createTidePredictor, type TimeSpan, type ExtremesInput } from \"@neaps/tide-predictor\";\n\ntype Units = \"meters\" | \"feet\";\ntype PredictionOptions = {\n /** Datum to return predictions in. Defaults to 'MLLW' if available for the nearest station. */\n datum?: string;\n\n /** Units for returned water levels. Defaults to 'meters'. */\n units?: Units;\n\n /** Nodal correction fundamentals. Defaults to 'iho'. */\n nodeCorrections?: \"iho\" | \"schureman\";\n};\n\nexport type ExtremesOptions = ExtremesInput & PredictionOptions;\nexport type TimelineOptions = TimeSpan & PredictionOptions;\nexport type WaterLevelOptions = { time: Date } & PredictionOptions;\n\nconst feetPerMeter = 3.2808399;\nconst defaultUnits: Units = \"meters\";\n\n/**\n * Get extremes prediction using the nearest station to the given position.\n *\n * @example\n * ```ts\n * import { getExtremesPrediction } from 'neaps'\n *\n * const prediction = getExtremesPrediction({\n * latitude: 26.7, // or `lat`\n * longitude: -80.05, // or `lng` or `lon`\n * start: new Date('2025-12-17'),\n * end: new Date('2025-12-18'),\n * datum: 'MLLW', // optional, defaults to MLLW if available\n * })\n */\nexport function getExtremesPrediction(options: NearestOptions & ExtremesOptions) {\n return nearestStation(options).getExtremesPrediction(options);\n}\n\n/**\n * Get timeline prediction using the nearest station to the given position.\n */\nexport function getTimelinePrediction(options: NearestOptions & TimelineOptions) {\n return nearestStation(options).getTimelinePrediction(options);\n}\n\n/**\n * Get water level at a specific time using the nearest station to the given position.\n */\nexport function getWaterLevelAtTime(options: NearestOptions & WaterLevelOptions) {\n return nearestStation(options).getWaterLevelAtTime(options);\n}\n\n/**\n * Find the nearest station to the given position.\n */\nexport function nearestStation(options: NearestOptions) {\n const data = nearest(options);\n if (!data) throw new Error(`No stations found with options: ${JSON.stringify(options)}`);\n return useStation(...data);\n}\n\n/**\n * Find stations near the given position.\n * @param limit Maximum number of stations to return (default: 10)\n */\nexport function stationsNear(options: NearOptions) {\n return near(options).map(([station, distance]) => useStation(station, distance));\n}\n\n/**\n * Find a specific station by its ID or source ID.\n */\nexport function findStation(query: string) {\n const searches = [(s: Station) => s.id === query, (s: Station) => s.source.id === query];\n\n let found: Station | undefined = undefined;\n\n for (const search of searches) {\n found = stations.find(search);\n if (found) break;\n }\n\n if (!found) throw new Error(`Station not found: ${query}`);\n\n return useStation(found);\n}\n\nexport function useStation(station: Station, distance?: number) {\n // If subordinate station, use the reference station for datums and constituents\n let reference = station;\n if (station.type === \"subordinate\" && station.offsets?.reference) {\n reference = findStation(station.offsets?.reference);\n }\n const { datums, harmonic_constituents } = reference;\n\n // Use MLLW as the default datum if available\n const defaultDatum = \"MLLW\" in datums ? \"MLLW\" : undefined;\n\n function getPredictor({ datum = defaultDatum, nodeCorrections }: PredictionOptions = {}) {\n let offset = 0;\n\n if (datum) {\n const datumOffset = datums?.[datum];\n const mslOffset = datums?.[\"MSL\"];\n\n if (typeof datumOffset !== \"number\") {\n throw new Error(\n `Station ${station.id} missing ${datum} datum. Available datums: ${Object.keys(datums).join(\", \")}`,\n );\n }\n\n if (typeof mslOffset !== \"number\") {\n throw new Error(\n `Station ${station.id} missing MSL datum, so predictions can't be given in ${datum}.`,\n );\n }\n\n offset = mslOffset - datumOffset;\n }\n\n return createTidePredictor(harmonic_constituents, { offset, nodeCorrections });\n }\n\n return {\n ...station,\n distance,\n datums,\n harmonic_constituents,\n defaultDatum,\n getExtremesPrediction({\n datum = defaultDatum,\n units = defaultUnits,\n nodeCorrections,\n ...options\n }: ExtremesOptions) {\n const extremes = getPredictor({ datum, nodeCorrections })\n .getExtremesPrediction({ ...options, offsets: station.offsets })\n .map((e) => toPreferredUnits(e, units));\n\n return { datum, units, station, distance, extremes };\n },\n\n getTimelinePrediction({\n datum = defaultDatum,\n units = defaultUnits,\n nodeCorrections,\n ...options\n }: TimelineOptions) {\n if (station.type === \"subordinate\") {\n throw new Error(`Timeline predictions are not supported for subordinate stations.`);\n }\n const timeline = getPredictor({ datum, nodeCorrections })\n .getTimelinePrediction(options)\n .map((e) => toPreferredUnits(e, units));\n\n return { datum, units, station, distance, timeline };\n },\n\n getWaterLevelAtTime({\n time,\n datum = defaultDatum,\n units = defaultUnits,\n nodeCorrections,\n }: WaterLevelOptions) {\n if (station.type === \"subordinate\") {\n throw new Error(`Water level predictions are not supported for subordinate stations.`);\n }\n\n const prediction = toPreferredUnits(\n getPredictor({ datum, nodeCorrections }).getWaterLevelAtTime({ time }),\n units,\n );\n\n return { datum, units, station, distance, ...prediction };\n },\n };\n}\n\nfunction toPreferredUnits<T extends { level: number }>(prediction: T, units: Units): T {\n let { level } = prediction;\n if (units === \"feet\") level *= feetPerMeter;\n else if (units !== \"meters\") throw new Error(`Unsupported units: ${units}`);\n return { ...prediction, level };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["import {\n stations,\n near,\n nearest,\n type Station,\n type NearOptions,\n type NearestOptions,\n} from \"@neaps/tide-database\";\nimport { createTidePredictor, type ExtremesInput, type TimelineInput } from \"@neaps/tide-predictor\";\n\ntype Units = \"meters\" | \"feet\";\ntype PredictionOptions = {\n /** Datum to return predictions in. Defaults to the nearest station's datum. */\n datum?: string;\n\n /** Units for returned water levels. Defaults to 'meters'. */\n units?: Units;\n\n /** Nodal correction fundamentals. Defaults to 'iho'. */\n nodeCorrections?: \"iho\" | \"schureman\";\n};\n\nexport type ExtremesOptions = ExtremesInput & PredictionOptions;\nexport type TimelineOptions = TimelineInput & PredictionOptions;\nexport type WaterLevelOptions = { time: Date } & PredictionOptions;\n\nconst feetPerMeter = 3.2808399;\nconst defaultUnits: Units = \"meters\";\n\n/**\n * Get extremes prediction using the nearest station to the given position.\n *\n * @example\n * ```ts\n * import { getExtremesPrediction } from 'neaps'\n *\n * const prediction = getExtremesPrediction({\n * latitude: 26.7, // or `lat`\n * longitude: -80.05, // or `lng` or `lon`\n * start: new Date('2025-12-17'),\n * end: new Date('2025-12-18'),\n * datum: 'MLLW', // optional, defaults to station's datum\n * })\n */\nexport function getExtremesPrediction(options: NearestOptions & ExtremesOptions) {\n return nearestStation(options).getExtremesPrediction(options);\n}\n\n/**\n * Get timeline prediction using the nearest station to the given position.\n */\nexport function getTimelinePrediction(options: NearestOptions & TimelineOptions) {\n return nearestStation(options).getTimelinePrediction(options);\n}\n\n/**\n * Get water level at a specific time using the nearest station to the given position.\n */\nexport function getWaterLevelAtTime(options: NearestOptions & WaterLevelOptions) {\n return nearestStation(options).getWaterLevelAtTime(options);\n}\n\n/**\n * Find the nearest station to the given position.\n */\nexport function nearestStation(options: NearestOptions) {\n const data = nearest(options);\n if (!data) throw new Error(`No stations found with options: ${JSON.stringify(options)}`);\n return useStation(...data);\n}\n\n/**\n * Find stations near the given position.\n * @param limit Maximum number of stations to return (default: 10)\n */\nexport function stationsNear(options: NearOptions) {\n return near(options).map(([station, distance]) => useStation(station, distance));\n}\n\n/**\n * Find a specific station by its ID or source ID.\n */\nexport function findStation(query: string) {\n const searches = [(s: Station) => s.id === query, (s: Station) => s.source.id === query];\n\n let found: Station | undefined = undefined;\n\n for (const search of searches) {\n found = stations.find(search);\n if (found) break;\n }\n\n if (!found) throw new Error(`Station not found: ${query}`);\n\n return useStation(found);\n}\n\nexport function useStation(station: Station, distance?: number) {\n // If subordinate station, use the reference station for datums and constituents\n let reference = station;\n if (station.type === \"subordinate\" && station.offsets?.reference) {\n reference = findStation(station.offsets?.reference);\n }\n const { datums, harmonic_constituents } = reference;\n\n // Use station chart datum as the default datum if available\n const defaultDatum = station.chart_datum in datums ? station.chart_datum : undefined;\n\n function getPredictor({ datum = defaultDatum, nodeCorrections }: PredictionOptions = {}) {\n let offset = 0;\n\n if (datum) {\n const datumOffset = datums?.[datum];\n const mslOffset = datums?.[\"MSL\"];\n\n if (typeof datumOffset !== \"number\") {\n throw new Error(\n `Station ${station.id} missing ${datum} datum. Available datums: ${Object.keys(datums).join(\", \")}`,\n );\n }\n\n if (typeof mslOffset !== \"number\") {\n throw new Error(\n `Station ${station.id} missing MSL datum, so predictions can't be given in ${datum}.`,\n );\n }\n\n offset = mslOffset - datumOffset;\n }\n\n return createTidePredictor(harmonic_constituents, { offset, nodeCorrections });\n }\n\n return {\n ...station,\n distance,\n datums,\n harmonic_constituents,\n defaultDatum,\n getExtremesPrediction({\n datum = defaultDatum,\n units = defaultUnits,\n nodeCorrections,\n ...options\n }: ExtremesOptions) {\n const extremes = getPredictor({ datum, nodeCorrections })\n .getExtremesPrediction({ ...options, offsets: station.offsets })\n .map((e) => toPreferredUnits(e, units));\n\n return { datum, units, station, distance, extremes };\n },\n\n getTimelinePrediction({\n datum = defaultDatum,\n units = defaultUnits,\n nodeCorrections,\n ...options\n }: TimelineOptions) {\n if (station.type === \"subordinate\") {\n throw new Error(`Timeline predictions are not supported for subordinate stations.`);\n }\n const timeline = getPredictor({ datum, nodeCorrections })\n .getTimelinePrediction(options)\n .map((e) => toPreferredUnits(e, units));\n\n return { datum, units, station, distance, timeline };\n },\n\n getWaterLevelAtTime({\n time,\n datum = defaultDatum,\n units = defaultUnits,\n nodeCorrections,\n }: WaterLevelOptions) {\n if (station.type === \"subordinate\") {\n throw new Error(`Water level predictions are not supported for subordinate stations.`);\n }\n\n const prediction = toPreferredUnits(\n getPredictor({ datum, nodeCorrections }).getWaterLevelAtTime({ time }),\n units,\n );\n\n return { datum, units, station, distance, ...prediction };\n },\n };\n}\n\nfunction toPreferredUnits<T extends { level: number }>(prediction: T, units: Units): T {\n let { level } = prediction;\n if (units === \"feet\") level *= feetPerMeter;\n else if (units !== \"meters\") throw new Error(`Unsupported units: ${units}`);\n return { ...prediction, level };\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "neaps",
3
- "version": "0.4.0",
3
+ "version": "0.5.1",
4
4
  "description": "Tide predictions",
5
5
  "keywords": [
6
6
  "tides",
@@ -34,7 +34,7 @@
34
34
  "prepack": "npm run build"
35
35
  },
36
36
  "dependencies": {
37
- "@neaps/tide-database": "0.4",
38
- "@neaps/tide-predictor": "^0.6.0"
37
+ "@neaps/tide-database": "0.6",
38
+ "@neaps/tide-predictor": "^0.7.0"
39
39
  }
40
40
  }