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 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(position) {
70
- return stationsNear(position, 1)[0];
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(position, limit = 10) {
77
- return _neaps_tide_database.stations.map((station) => ({
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 || {}).join(", ")}`);
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
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":["defaultUnits: Units","stations","found: Station | undefined"],"sources":["../src/index.ts"],"sourcesContent":["import { getDistance } from \"geolib\";\nimport { stations, type Station } from \"@neaps/tide-database\";\nimport tidePredictor, { type TimeSpan, type ExtremesInput } from \"@neaps/tide-predictor\";\nimport type { GeolibInputCoordinates } from \"geolib/es/types\";\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: GeolibInputCoordinates & 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: GeolibInputCoordinates & 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: GeolibInputCoordinates & WaterLevelOptions) {\n return nearestStation(options).getWaterLevelAtTime(options);\n}\n\n/**\n * Find the nearest station to the given position.\n */\nexport function nearestStation(position: GeolibInputCoordinates) {\n return stationsNear(position, 1)[0];\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(position: GeolibInputCoordinates, limit = 10) {\n return stations\n .map((station) => ({ station, distance: getDistance(position, station) }))\n .sort((a, b) => a.distance - b.distance)\n .slice(0, limit)\n .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\") {\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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"}
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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAuBA,MAAM,eAAe;AACrB,MAAM,eAAsB;;;;;;;;;;;;;;;;AAiB5B,SAAgB,sBAAsB,SAA2C;AAC/E,QAAO,eAAe,QAAQ,CAAC,sBAAsB,QAAQ;;;;;AAM/D,SAAgB,sBAAsB,SAA2C;AAC/E,QAAO,eAAe,QAAQ,CAAC,sBAAsB,QAAQ;;;;;AAM/D,SAAgB,oBAAoB,SAA6C;AAC/E,QAAO,eAAe,QAAQ,CAAC,oBAAoB,QAAQ;;;;;AAM7D,SAAgB,eAAe,SAAyB;CACtD,MAAM,yCAAe,QAAQ;AAC7B,KAAI,CAAC,KAAM,OAAM,IAAI,MAAM,mCAAmC,KAAK,UAAU,QAAQ,GAAG;AACxF,QAAO,WAAW,GAAG,KAAK;;;;;;AAO5B,SAAgB,aAAa,SAAsB;AACjD,uCAAY,QAAQ,CAAC,KAAK,CAAC,SAAS,cAAc,WAAW,SAAS,SAAS,CAAC;;;;;AAMlF,SAAgB,YAAY,OAAe;CACzC,MAAM,WAAW,EAAE,MAAe,EAAE,OAAO,QAAQ,MAAe,EAAE,OAAO,OAAO,MAAM;CAExF,IAAI,QAA6B;AAEjC,MAAK,MAAM,UAAU,UAAU;AAC7B,UAAQA,8BAAS,KAAK,OAAO;AAC7B,MAAI,MAAO;;AAGb,KAAI,CAAC,MAAO,OAAM,IAAI,MAAM,sBAAsB,QAAQ;AAE1D,QAAO,WAAW,MAAM;;AAG1B,SAAgB,WAAW,SAAkB,UAAmB;CAE9D,IAAI,YAAY;AAChB,KAAI,QAAQ,SAAS,iBAAiB,QAAQ,SAAS,UACrD,aAAY,YAAY,QAAQ,SAAS,UAAU;CAErD,MAAM,EAAE,QAAQ,0BAA0B;CAG1C,MAAM,eAAe,UAAU,SAAS,SAAS;CAEjD,SAAS,aAAa,EAAE,QAAQ,iBAAoC,EAAE,EAAE;EACtE,IAAI,SAAS;AAEb,MAAI,OAAO;GACT,MAAM,cAAc,SAAS;GAC7B,MAAM,YAAY,SAAS;AAE3B,OAAI,OAAO,gBAAgB,SACzB,OAAM,IAAI,MACR,WAAW,QAAQ,GAAG,WAAW,MAAM,4BAA4B,OAAO,KAAK,OAAO,CAAC,KAAK,KAAK,GAClG;AAGH,OAAI,OAAO,cAAc,SACvB,OAAM,IAAI,MACR,WAAW,QAAQ,GAAG,uDAAuD,MAAM,GACpF;AAGH,YAAS,YAAY;;AAGvB,4CAAqB,uBAAuB,EAAE,QAAQ,CAAC;;AAGzD,QAAO;EACL,GAAG;EACH;EACA;EACA;EACA;EACA,sBAAsB,EACpB,QAAQ,cACR,QAAQ,cACR,GAAG,WACe;AAKlB,UAAO;IAAE;IAAO;IAAO;IAAS;IAAU,UAJzB,aAAa,EAAE,OAAO,CAAC,CACrC,sBAAsB;KAAE,GAAG;KAAS,SAAS,QAAQ;KAAS,CAAC,CAC/D,KAAK,MAAM,iBAAiB,GAAG,MAAM,CAAC;IAEW;;EAGtD,sBAAsB,EACpB,QAAQ,cACR,QAAQ,cACR,GAAG,WACe;AAClB,OAAI,QAAQ,SAAS,cACnB,OAAM,IAAI,MAAM,mEAAmE;AAMrF,UAAO;IAAE;IAAO;IAAO;IAAS;IAAU,UAJzB,aAAa,EAAE,OAAO,CAAC,CACrC,sBAAsB,QAAQ,CAC9B,KAAK,MAAM,iBAAiB,GAAG,MAAM,CAAC;IAEW;;EAGtD,oBAAoB,EAAE,MAAM,QAAQ,cAAc,QAAQ,gBAAmC;AAC3F,OAAI,QAAQ,SAAS,cACnB,OAAM,IAAI,MAAM,sEAAsE;AAQxF,UAAO;IAAE;IAAO;IAAO;IAAS;IAAU,GALvB,iBACjB,aAAa,EAAE,OAAO,CAAC,CAAC,oBAAoB,EAAE,MAAM,CAAC,EACrD,MACD;IAEwD;;EAE5D;;AAGH,SAAS,iBAA8C,YAAe,OAAiB;CACrF,IAAI,EAAE,UAAU;AAChB,KAAI,UAAU,OAAQ,UAAS;UACtB,UAAU,SAAU,OAAM,IAAI,MAAM,sBAAsB,QAAQ;AAC3E,QAAO;EAAE,GAAG;EAAY;EAAO"}
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: GeolibInputCoordinates & ExtremesOptions): {
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: GeolibInputCoordinates & TimelineOptions): {
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: GeolibInputCoordinates & WaterLevelOptions): {
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(position: GeolibInputCoordinates): {
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(position: GeolibInputCoordinates, limit?: number): {
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: GeolibInputCoordinates & ExtremesOptions): {
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: GeolibInputCoordinates & TimelineOptions): {
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: GeolibInputCoordinates & WaterLevelOptions): {
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(position: GeolibInputCoordinates): {
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(position: GeolibInputCoordinates, limit?: number): {
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 { getDistance } from "geolib";
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(position) {
42
- return stationsNear(position, 1)[0];
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(position, limit = 10) {
49
- return stations.map((station) => ({
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 || {}).join(", ")}`);
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":["defaultUnits: Units","found: Station | undefined"],"sources":["../src/index.ts"],"sourcesContent":["import { getDistance } from \"geolib\";\nimport { stations, type Station } from \"@neaps/tide-database\";\nimport tidePredictor, { type TimeSpan, type ExtremesInput } from \"@neaps/tide-predictor\";\nimport type { GeolibInputCoordinates } from \"geolib/es/types\";\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: GeolibInputCoordinates & 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: GeolibInputCoordinates & 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: GeolibInputCoordinates & WaterLevelOptions) {\n return nearestStation(options).getWaterLevelAtTime(options);\n}\n\n/**\n * Find the nearest station to the given position.\n */\nexport function nearestStation(position: GeolibInputCoordinates) {\n return stationsNear(position, 1)[0];\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(position: GeolibInputCoordinates, limit = 10) {\n return stations\n .map((station) => ({ station, distance: getDistance(position, station) }))\n .sort((a, b) => a.distance - b.distance)\n .slice(0, limit)\n .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\") {\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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"}
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.2.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.2",
38
- "@neaps/tide-predictor": "^0.3.0",
39
- "geolib": "^3.3.4"
37
+ "@neaps/tide-database": "0.4",
38
+ "@neaps/tide-predictor": "^0.5.0"
40
39
  }
41
40
  }