neaps 0.2.0 → 0.3.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 +8 -10
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +7 -10
- package/dist/index.d.ts +7 -10
- package/dist/index.js +9 -11
- package/dist/index.js.map +1 -1
- package/package.json +3 -4
package/dist/index.cjs
CHANGED
|
@@ -25,7 +25,6 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
25
25
|
}) : target, mod));
|
|
26
26
|
|
|
27
27
|
//#endregion
|
|
28
|
-
let geolib = require("geolib");
|
|
29
28
|
let _neaps_tide_database = require("@neaps/tide-database");
|
|
30
29
|
let _neaps_tide_predictor = require("@neaps/tide-predictor");
|
|
31
30
|
_neaps_tide_predictor = __toESM(_neaps_tide_predictor);
|
|
@@ -66,18 +65,17 @@ function getWaterLevelAtTime(options) {
|
|
|
66
65
|
/**
|
|
67
66
|
* Find the nearest station to the given position.
|
|
68
67
|
*/
|
|
69
|
-
function nearestStation(
|
|
70
|
-
|
|
68
|
+
function nearestStation(options) {
|
|
69
|
+
const data = (0, _neaps_tide_database.nearest)(options);
|
|
70
|
+
if (!data) throw new Error(`No stations found with options: ${JSON.stringify(options)}`);
|
|
71
|
+
return useStation(...data);
|
|
71
72
|
}
|
|
72
73
|
/**
|
|
73
74
|
* Find stations near the given position.
|
|
74
75
|
* @param limit Maximum number of stations to return (default: 10)
|
|
75
76
|
*/
|
|
76
|
-
function stationsNear(
|
|
77
|
-
return _neaps_tide_database.
|
|
78
|
-
station,
|
|
79
|
-
distance: (0, geolib.getDistance)(position, station)
|
|
80
|
-
})).sort((a, b) => a.distance - b.distance).slice(0, limit).map(({ station, distance }) => useStation(station, distance));
|
|
77
|
+
function stationsNear(options) {
|
|
78
|
+
return (0, _neaps_tide_database.near)(options).map(([station, distance]) => useStation(station, distance));
|
|
81
79
|
}
|
|
82
80
|
/**
|
|
83
81
|
* Find a specific station by its ID or source ID.
|
|
@@ -94,7 +92,7 @@ function findStation(query) {
|
|
|
94
92
|
}
|
|
95
93
|
function useStation(station, distance) {
|
|
96
94
|
let reference = station;
|
|
97
|
-
if (station.type === "subordinate") reference = findStation(station.offsets?.reference
|
|
95
|
+
if (station.type === "subordinate" && station.offsets?.reference) reference = findStation(station.offsets?.reference);
|
|
98
96
|
const { datums, harmonic_constituents } = reference;
|
|
99
97
|
const defaultDatum = "MLLW" in datums ? "MLLW" : void 0;
|
|
100
98
|
function getPredictor({ datum = defaultDatum } = {}) {
|
|
@@ -102,7 +100,7 @@ function useStation(station, distance) {
|
|
|
102
100
|
if (datum) {
|
|
103
101
|
const datumOffset = datums?.[datum];
|
|
104
102
|
const mslOffset = datums?.["MSL"];
|
|
105
|
-
if (typeof datumOffset !== "number") throw new Error(`Station ${station.id} missing ${datum} datum. Available datums: ${Object.keys(datums
|
|
103
|
+
if (typeof datumOffset !== "number") throw new Error(`Station ${station.id} missing ${datum} datum. Available datums: ${Object.keys(datums).join(", ")}`);
|
|
106
104
|
if (typeof mslOffset !== "number") throw new Error(`Station ${station.id} missing MSL datum, so predictions can't be given in ${datum}.`);
|
|
107
105
|
offset = mslOffset - datumOffset;
|
|
108
106
|
}
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":["
|
|
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 tidePredictor, { 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\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 }: 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 tidePredictor(harmonic_constituents, { offset });\n }\n\n return {\n ...station,\n distance,\n datums,\n harmonic_constituents,\n defaultDatum,\n getExtremesPrediction({\n datum = defaultDatum,\n units = defaultUnits,\n ...options\n }: ExtremesOptions) {\n const extremes = getPredictor({ datum })\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 ...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 })\n .getTimelinePrediction(options)\n .map((e) => toPreferredUnits(e, units));\n\n return { datum, units, station, distance, timeline };\n },\n\n getWaterLevelAtTime({ time, datum = defaultDatum, units = defaultUnits }: 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 }).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,15 +1,12 @@
|
|
|
1
1
|
import * as _neaps_tide_predictor0 from "@neaps/tide-predictor";
|
|
2
2
|
import { ExtremesInput, TimeSpan } from "@neaps/tide-predictor";
|
|
3
3
|
import * as _neaps_tide_database0 from "@neaps/tide-database";
|
|
4
|
-
import { Station } from "@neaps/tide-database";
|
|
5
|
-
import { GeolibInputCoordinates } from "geolib/es/types";
|
|
4
|
+
import { NearOptions, NearestOptions, Station } from "@neaps/tide-database";
|
|
6
5
|
|
|
7
6
|
//#region src/index.d.ts
|
|
8
7
|
type Units = "meters" | "feet";
|
|
9
8
|
type PredictionOptions = {
|
|
10
|
-
/** Datum to return predictions in. Defaults to 'MLLW' if available for the nearest station. */
|
|
11
|
-
datum?: string;
|
|
12
|
-
/** Units for returned water levels. Defaults to 'meters'. */
|
|
9
|
+
/** Datum to return predictions in. Defaults to 'MLLW' if available for the nearest station. */datum?: string; /** Units for returned water levels. Defaults to 'meters'. */
|
|
13
10
|
units?: Units;
|
|
14
11
|
};
|
|
15
12
|
type ExtremesOptions = ExtremesInput & PredictionOptions;
|
|
@@ -32,7 +29,7 @@ type WaterLevelOptions = {
|
|
|
32
29
|
* datum: 'MLLW', // optional, defaults to MLLW if available
|
|
33
30
|
* })
|
|
34
31
|
*/
|
|
35
|
-
declare function getExtremesPrediction(options:
|
|
32
|
+
declare function getExtremesPrediction(options: NearestOptions & ExtremesOptions): {
|
|
36
33
|
datum: string | undefined;
|
|
37
34
|
units: Units;
|
|
38
35
|
station: Station;
|
|
@@ -42,7 +39,7 @@ declare function getExtremesPrediction(options: GeolibInputCoordinates & Extreme
|
|
|
42
39
|
/**
|
|
43
40
|
* Get timeline prediction using the nearest station to the given position.
|
|
44
41
|
*/
|
|
45
|
-
declare function getTimelinePrediction(options:
|
|
42
|
+
declare function getTimelinePrediction(options: NearestOptions & TimelineOptions): {
|
|
46
43
|
datum: string | undefined;
|
|
47
44
|
units: Units;
|
|
48
45
|
station: Station;
|
|
@@ -52,7 +49,7 @@ declare function getTimelinePrediction(options: GeolibInputCoordinates & Timelin
|
|
|
52
49
|
/**
|
|
53
50
|
* Get water level at a specific time using the nearest station to the given position.
|
|
54
51
|
*/
|
|
55
|
-
declare function getWaterLevelAtTime(options:
|
|
52
|
+
declare function getWaterLevelAtTime(options: NearestOptions & WaterLevelOptions): {
|
|
56
53
|
time: Date;
|
|
57
54
|
hour: number;
|
|
58
55
|
level: number;
|
|
@@ -64,7 +61,7 @@ declare function getWaterLevelAtTime(options: GeolibInputCoordinates & WaterLeve
|
|
|
64
61
|
/**
|
|
65
62
|
* Find the nearest station to the given position.
|
|
66
63
|
*/
|
|
67
|
-
declare function nearestStation(
|
|
64
|
+
declare function nearestStation(options: NearestOptions): {
|
|
68
65
|
distance: number | undefined;
|
|
69
66
|
datums: Record<string, number>;
|
|
70
67
|
harmonic_constituents: _neaps_tide_database0.HarmonicConstituent[];
|
|
@@ -143,7 +140,7 @@ declare function nearestStation(position: GeolibInputCoordinates): {
|
|
|
143
140
|
* Find stations near the given position.
|
|
144
141
|
* @param limit Maximum number of stations to return (default: 10)
|
|
145
142
|
*/
|
|
146
|
-
declare function stationsNear(
|
|
143
|
+
declare function stationsNear(options: NearOptions): {
|
|
147
144
|
distance: number | undefined;
|
|
148
145
|
datums: Record<string, number>;
|
|
149
146
|
harmonic_constituents: _neaps_tide_database0.HarmonicConstituent[];
|
package/dist/index.d.ts
CHANGED
|
@@ -1,15 +1,12 @@
|
|
|
1
1
|
import * as _neaps_tide_database0 from "@neaps/tide-database";
|
|
2
|
-
import { Station } from "@neaps/tide-database";
|
|
2
|
+
import { NearOptions, NearestOptions, Station } from "@neaps/tide-database";
|
|
3
3
|
import * as _neaps_tide_predictor0 from "@neaps/tide-predictor";
|
|
4
4
|
import { ExtremesInput, TimeSpan } from "@neaps/tide-predictor";
|
|
5
|
-
import { GeolibInputCoordinates } from "geolib/es/types";
|
|
6
5
|
|
|
7
6
|
//#region src/index.d.ts
|
|
8
7
|
type Units = "meters" | "feet";
|
|
9
8
|
type PredictionOptions = {
|
|
10
|
-
/** Datum to return predictions in. Defaults to 'MLLW' if available for the nearest station. */
|
|
11
|
-
datum?: string;
|
|
12
|
-
/** Units for returned water levels. Defaults to 'meters'. */
|
|
9
|
+
/** Datum to return predictions in. Defaults to 'MLLW' if available for the nearest station. */datum?: string; /** Units for returned water levels. Defaults to 'meters'. */
|
|
13
10
|
units?: Units;
|
|
14
11
|
};
|
|
15
12
|
type ExtremesOptions = ExtremesInput & PredictionOptions;
|
|
@@ -32,7 +29,7 @@ type WaterLevelOptions = {
|
|
|
32
29
|
* datum: 'MLLW', // optional, defaults to MLLW if available
|
|
33
30
|
* })
|
|
34
31
|
*/
|
|
35
|
-
declare function getExtremesPrediction(options:
|
|
32
|
+
declare function getExtremesPrediction(options: NearestOptions & ExtremesOptions): {
|
|
36
33
|
datum: string | undefined;
|
|
37
34
|
units: Units;
|
|
38
35
|
station: Station;
|
|
@@ -42,7 +39,7 @@ declare function getExtremesPrediction(options: GeolibInputCoordinates & Extreme
|
|
|
42
39
|
/**
|
|
43
40
|
* Get timeline prediction using the nearest station to the given position.
|
|
44
41
|
*/
|
|
45
|
-
declare function getTimelinePrediction(options:
|
|
42
|
+
declare function getTimelinePrediction(options: NearestOptions & TimelineOptions): {
|
|
46
43
|
datum: string | undefined;
|
|
47
44
|
units: Units;
|
|
48
45
|
station: Station;
|
|
@@ -52,7 +49,7 @@ declare function getTimelinePrediction(options: GeolibInputCoordinates & Timelin
|
|
|
52
49
|
/**
|
|
53
50
|
* Get water level at a specific time using the nearest station to the given position.
|
|
54
51
|
*/
|
|
55
|
-
declare function getWaterLevelAtTime(options:
|
|
52
|
+
declare function getWaterLevelAtTime(options: NearestOptions & WaterLevelOptions): {
|
|
56
53
|
time: Date;
|
|
57
54
|
hour: number;
|
|
58
55
|
level: number;
|
|
@@ -64,7 +61,7 @@ declare function getWaterLevelAtTime(options: GeolibInputCoordinates & WaterLeve
|
|
|
64
61
|
/**
|
|
65
62
|
* Find the nearest station to the given position.
|
|
66
63
|
*/
|
|
67
|
-
declare function nearestStation(
|
|
64
|
+
declare function nearestStation(options: NearestOptions): {
|
|
68
65
|
distance: number | undefined;
|
|
69
66
|
datums: Record<string, number>;
|
|
70
67
|
harmonic_constituents: _neaps_tide_database0.HarmonicConstituent[];
|
|
@@ -143,7 +140,7 @@ declare function nearestStation(position: GeolibInputCoordinates): {
|
|
|
143
140
|
* Find stations near the given position.
|
|
144
141
|
* @param limit Maximum number of stations to return (default: 10)
|
|
145
142
|
*/
|
|
146
|
-
declare function stationsNear(
|
|
143
|
+
declare function stationsNear(options: NearOptions): {
|
|
147
144
|
distance: number | undefined;
|
|
148
145
|
datums: Record<string, number>;
|
|
149
146
|
harmonic_constituents: _neaps_tide_database0.HarmonicConstituent[];
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { stations } from "@neaps/tide-database";
|
|
1
|
+
import { near, nearest, stations } from "@neaps/tide-database";
|
|
3
2
|
import tidePredictor from "@neaps/tide-predictor";
|
|
4
3
|
|
|
5
4
|
//#region src/index.ts
|
|
@@ -38,18 +37,17 @@ function getWaterLevelAtTime(options) {
|
|
|
38
37
|
/**
|
|
39
38
|
* Find the nearest station to the given position.
|
|
40
39
|
*/
|
|
41
|
-
function nearestStation(
|
|
42
|
-
|
|
40
|
+
function nearestStation(options) {
|
|
41
|
+
const data = nearest(options);
|
|
42
|
+
if (!data) throw new Error(`No stations found with options: ${JSON.stringify(options)}`);
|
|
43
|
+
return useStation(...data);
|
|
43
44
|
}
|
|
44
45
|
/**
|
|
45
46
|
* Find stations near the given position.
|
|
46
47
|
* @param limit Maximum number of stations to return (default: 10)
|
|
47
48
|
*/
|
|
48
|
-
function stationsNear(
|
|
49
|
-
return
|
|
50
|
-
station,
|
|
51
|
-
distance: getDistance(position, station)
|
|
52
|
-
})).sort((a, b) => a.distance - b.distance).slice(0, limit).map(({ station, distance }) => useStation(station, distance));
|
|
49
|
+
function stationsNear(options) {
|
|
50
|
+
return near(options).map(([station, distance]) => useStation(station, distance));
|
|
53
51
|
}
|
|
54
52
|
/**
|
|
55
53
|
* Find a specific station by its ID or source ID.
|
|
@@ -66,7 +64,7 @@ function findStation(query) {
|
|
|
66
64
|
}
|
|
67
65
|
function useStation(station, distance) {
|
|
68
66
|
let reference = station;
|
|
69
|
-
if (station.type === "subordinate") reference = findStation(station.offsets?.reference
|
|
67
|
+
if (station.type === "subordinate" && station.offsets?.reference) reference = findStation(station.offsets?.reference);
|
|
70
68
|
const { datums, harmonic_constituents } = reference;
|
|
71
69
|
const defaultDatum = "MLLW" in datums ? "MLLW" : void 0;
|
|
72
70
|
function getPredictor({ datum = defaultDatum } = {}) {
|
|
@@ -74,7 +72,7 @@ function useStation(station, distance) {
|
|
|
74
72
|
if (datum) {
|
|
75
73
|
const datumOffset = datums?.[datum];
|
|
76
74
|
const mslOffset = datums?.["MSL"];
|
|
77
|
-
if (typeof datumOffset !== "number") throw new Error(`Station ${station.id} missing ${datum} datum. Available datums: ${Object.keys(datums
|
|
75
|
+
if (typeof datumOffset !== "number") throw new Error(`Station ${station.id} missing ${datum} datum. Available datums: ${Object.keys(datums).join(", ")}`);
|
|
78
76
|
if (typeof mslOffset !== "number") throw new Error(`Station ${station.id} missing MSL datum, so predictions can't be given in ${datum}.`);
|
|
79
77
|
offset = mslOffset - datumOffset;
|
|
80
78
|
}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[
|
|
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 tidePredictor, { 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\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 }: 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 tidePredictor(harmonic_constituents, { offset });\n }\n\n return {\n ...station,\n distance,\n datums,\n harmonic_constituents,\n defaultDatum,\n getExtremesPrediction({\n datum = defaultDatum,\n units = defaultUnits,\n ...options\n }: ExtremesOptions) {\n const extremes = getPredictor({ datum })\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 ...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 })\n .getTimelinePrediction(options)\n .map((e) => toPreferredUnits(e, units));\n\n return { datum, units, station, distance, timeline };\n },\n\n getWaterLevelAtTime({ time, datum = defaultDatum, units = defaultUnits }: 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 }).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.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"description": "Tide predictions",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"tides",
|
|
@@ -34,8 +34,7 @@
|
|
|
34
34
|
"prepack": "npm run build"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@neaps/tide-database": "0.
|
|
38
|
-
"@neaps/tide-predictor": "^0.
|
|
39
|
-
"geolib": "^3.3.4"
|
|
37
|
+
"@neaps/tide-database": "0.4",
|
|
38
|
+
"@neaps/tide-predictor": "^0.5.0"
|
|
40
39
|
}
|
|
41
40
|
}
|