@slackwater/database 1.0.0-beta.0

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.
@@ -0,0 +1,283 @@
1
+ //#region src/attribution.d.ts
2
+ /**
3
+ * The project half of every notice. A station's full notice opens with this,
4
+ * then adds whatever its source and licence require.
5
+ */
6
+ export declare const PROJECT_CREDIT = "Slackwater database (https://github.com/openwatersio/slackwater-database)";
7
+ /** Where a redistributor is pointed to find what this project changed. */
8
+ export declare const MODIFICATIONS_URL = "https://github.com/openwatersio/slackwater-database#modifications-to-source-data";
9
+ /** Whether a source name has a credit decision recorded. */
10
+ export declare function isKnownSource(sourceName: string): boolean;
11
+ /**
12
+ * Assemble a station's complete notice, so displaying it is the whole of a
13
+ * consumer's obligation. Under a Creative Commons licence that means the
14
+ * creator credit, the licence and its URI, and an indication that the material
15
+ * was modified — the three things CC BY 4.0 section 3(a)(1) requires be passed
16
+ * on. Licence is taken per station rather than per source because it varies
17
+ * within one source: TICON stations relayed from CMEMS are CC BY-NC while the
18
+ * rest are CC BY.
19
+ */
20
+ export declare function attributionFor(sourceName: string | undefined, license: {
21
+ type: string;
22
+ url: string;
23
+ } | undefined): string;
24
+ //#endregion
25
+ //#region src/types.d.ts
26
+ interface HarmonicConstituent {
27
+ name: string;
28
+ description?: string;
29
+ amplitude: number;
30
+ phase: number;
31
+ speed?: number;
32
+ }
33
+ interface Constituent {
34
+ name: string;
35
+ description: string | null;
36
+ speed: number;
37
+ }
38
+ interface StationRouteInput {
39
+ slug: string;
40
+ station_ids: string[];
41
+ former_paths?: string[];
42
+ }
43
+ interface StationRoute {
44
+ slug: string;
45
+ stationIds: string[];
46
+ formerPaths: string[];
47
+ }
48
+ interface DatabaseRoutes {
49
+ tide: StationRouteInput[];
50
+ current: StationRouteInput[];
51
+ }
52
+ interface StationData {
53
+ name: string;
54
+ continent: string;
55
+ country: string;
56
+ country_code?: string;
57
+ locality?: string;
58
+ region?: string;
59
+ region_code?: string;
60
+ timezone: string;
61
+ context?: string;
62
+ context_derived?: boolean;
63
+ cities?: string[];
64
+ disclaimers?: string;
65
+ type: "reference" | "subordinate";
66
+ latitude: number;
67
+ longitude: number;
68
+ source: {
69
+ name: string;
70
+ id: string;
71
+ published_harmonics: boolean;
72
+ url: string;
73
+ };
74
+ license: {
75
+ type: string;
76
+ commercial_use: boolean;
77
+ url: string;
78
+ notes?: string;
79
+ };
80
+ harmonic_constituents: HarmonicConstituent[];
81
+ offsets?: {
82
+ reference: string;
83
+ height: {
84
+ high: number;
85
+ low: number;
86
+ type: "ratio" | "fixed";
87
+ };
88
+ time: {
89
+ high: number;
90
+ low: number;
91
+ };
92
+ };
93
+ datums: Record<string, number>;
94
+ datums_source?: "observed" | "harmonic";
95
+ chart_datum?: string;
96
+ epoch?: {
97
+ start: string;
98
+ end: string;
99
+ };
100
+ aliases?: string[];
101
+ }
102
+ interface TideDerivedCurrentData {
103
+ reference: string;
104
+ high_water_lag_minutes: number;
105
+ low_water_lag_minutes: number;
106
+ }
107
+ interface CurrentData {
108
+ /** Degrees true. */
109
+ flood_direction?: number;
110
+ ebb_direction?: number;
111
+ /** Knots; the constant term added to the harmonic sum. */
112
+ mean_flow?: number;
113
+ /** Id of the tide station whose extremes pair with this current, if any. */
114
+ tide_reference?: string;
115
+ magnitude_note?: string;
116
+ derived?: TideDerivedCurrentData;
117
+ /** Subordinate currents only. Times in minutes, ratios dimensionless. */
118
+ offsets?: {
119
+ reference: string;
120
+ slack_before_flood?: number;
121
+ slack_before_ebb?: number;
122
+ flood_time?: number;
123
+ ebb_time?: number;
124
+ flood_speed_ratio?: number;
125
+ ebb_speed_ratio?: number;
126
+ };
127
+ }
128
+ /**
129
+ * What buildDatabase accepts: a station id plus whatever fields the catalog
130
+ * has. Downstream generators can pass filtered stations from this package or
131
+ * records of their own (including current stations).
132
+ */
133
+ type StationInput = {
134
+ id: string;
135
+ kind?: "tide" | "current";
136
+ current?: CurrentData;
137
+ quality?: StationQuality;
138
+ } & Partial<StationData>;
139
+ interface StationQuality {
140
+ /** The station's id — not stored in the database, filled from identity. */
141
+ id: string;
142
+ accepted: boolean;
143
+ score: number;
144
+ /** Scoring factors, each 0-1. */
145
+ factors?: {
146
+ epoch: number;
147
+ recency: number;
148
+ source: number;
149
+ quality: number;
150
+ amplitude: number;
151
+ coverage: number;
152
+ };
153
+ /** Human-readable findings, e.g. "MLW (3.827) < LAT (3.831)". */
154
+ issues?: string[];
155
+ /** Rejection category ("duplicate", "datum", "constituents", ...), if rejected. */
156
+ reason?: string;
157
+ /** Id of the station that makes this one redundant, if any. */
158
+ redundant?: string;
159
+ }
160
+ /** The floor and ceiling of a station's predictions, in metres above its chart datum. */
161
+ interface AstronomicalBounds {
162
+ /** Lowest Astronomical Tide. */
163
+ lat: number;
164
+ /** Highest Astronomical Tide. */
165
+ hat: number;
166
+ }
167
+ interface Station extends StationData {
168
+ id: string;
169
+ country_code: string;
170
+ kind: "tide" | "current";
171
+ current?: CurrentData;
172
+ quality?: StationQuality;
173
+ /**
174
+ * Lowest and highest astronomical tide, in metres above this station's chart
175
+ * datum; absent when the station predicting for this one has no LAT and HAT.
176
+ * A subordinate's is the reference's range reduced through `offsets.height`,
177
+ * the floor of a prediction rather than a hydrographic datum — which is why
178
+ * it is here and not in `datums`. See docs/datums.md.
179
+ */
180
+ astronomical_bounds?: AstronomicalBounds;
181
+ /**
182
+ * The credit to display when showing or redistributing this station, ready
183
+ * to render as-is. Derived from `source`; see src/attribution.ts.
184
+ */
185
+ attribution: string;
186
+ }
187
+ type StationMetaKey = "name" | "latitude" | "longitude" | "locality" | "region" | "region_code" | "country" | "country_code" | "continent" | "context" | "context_derived" | "cities" | "aliases" | "timezone" | "type" | "source";
188
+ type StationMeta = {
189
+ id: string;
190
+ } & Pick<StationData, StationMetaKey>;
191
+ //#endregion
192
+ //#region src/stations.d.ts
193
+ /** All datum keys present across the database (e.g. "MLLW", "MSL", "NAVD88"). */
194
+ export declare const datums: string[];
195
+ export declare const allStations: Station[];
196
+ export declare const stationsById: Map<string, Station>;
197
+ export declare const qualityMap: Map<string, StationQuality>;
198
+ export declare function qualityFilter(station: Station): boolean;
199
+ export declare const stations: Station[];
200
+ //#endregion
201
+ //#region src/routes.d.ts
202
+ export declare function stationRouteBySlug(kind: "tide" | "current", slug: string): StationRoute | undefined;
203
+ export declare function stationRoutes(kind: "tide" | "current"): StationRoute[];
204
+ //#endregion
205
+ //#region src/search/index.d.ts
206
+ export type Position = Latitude & Longitude;
207
+ type Latitude = {
208
+ latitude: number;
209
+ } | {
210
+ lat: number;
211
+ };
212
+ type Longitude = {
213
+ longitude: number;
214
+ } | {
215
+ lon: number;
216
+ } | {
217
+ lng: number;
218
+ };
219
+ export type Filter = (station: Station) => boolean;
220
+ export type NearestOptions = Position & {
221
+ maxDistance?: number;
222
+ /** Include all stations, not just quality-filtered ones. */
223
+ includeAll?: boolean;
224
+ filter?: Filter;
225
+ };
226
+ export type NearOptions = NearestOptions & {
227
+ maxResults?: number;
228
+ };
229
+ export type BboxOptions = {
230
+ /** Include all stations, not just quality-filtered ones. */
231
+ includeAll?: boolean;
232
+ filter?: Filter;
233
+ };
234
+ export type TextSearchOptions = {
235
+ /** Include all stations, not just quality-filtered ones. */
236
+ includeAll?: boolean;
237
+ filter?: Filter;
238
+ maxResults?: number;
239
+ };
240
+ /**
241
+ * A tuple of a station and its distance from a given point, in kilometers.
242
+ */
243
+ export type StationWithDistance = [Station, number];
244
+ /**
245
+ * Find stations near a given position.
246
+ */
247
+ export declare function near({ maxDistance, maxResults, includeAll, filter, ...position }: NearOptions): StationWithDistance[];
248
+ /**
249
+ * Find the single nearest station to a given position.
250
+ */
251
+ export declare function nearest(options: NearestOptions): StationWithDistance | null;
252
+ /**
253
+ * Find stations within a bounding box.
254
+ */
255
+ export declare function bbox([minLon, minLat, maxLon, maxLat]: [number, number, number, number], { includeAll, filter }?: BboxOptions): Station[];
256
+ export declare function positionToPoint(options: Position): [number, number];
257
+ /**
258
+ * Search for stations by text across name, region, country, and continent.
259
+ * Supports fuzzy matching and prefix search.
260
+ */
261
+ export declare function search(query: string, { includeAll, filter, maxResults }?: TextSearchOptions): Station[];
262
+ //#endregion
263
+ //#region src/database/builder.d.ts
264
+ /**
265
+ * Serialize stations into the FlatBuffers database format
266
+ * (schemas/database.fbs). Stations are sorted by id — the vector key — so
267
+ * readers can binary-search the buffer.
268
+ *
269
+ * Build order matters and the schema cannot express it: FlatBuffers writes back
270
+ * to front, so the prediction data (constituents and datums vectors) is written
271
+ * first for every station, landing together at the tail of the file, and the
272
+ * station tables are written together after, landing at the head. A naive
273
+ * per-station loop would interleave ~100 bytes of identity with ~1,300 bytes of
274
+ * constituents, making an identity scan over a memory-mapped file fault in
275
+ * every page. test/database.test.ts asserts the layout.
276
+ */
277
+ export declare function buildDatabase(stations: StationInput[], { version, routes }?: {
278
+ version?: string;
279
+ routes?: DatabaseRoutes;
280
+ }): Uint8Array;
281
+ //#endregion
282
+ export type { AstronomicalBounds, Constituent, CurrentData, DatabaseRoutes, HarmonicConstituent, Station, StationData, StationInput, StationMeta, StationMetaKey, StationQuality, StationRoute, StationRouteInput, TideDerivedCurrentData };
283
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../../src/attribution.ts","../../src/types.ts","../../src/stations.ts","../../src/routes.ts","../../src/search/index.ts","../../src/database/builder.ts"],"mappings":";;;;;qBAIa;;qBAIA;;wBAiCG,cAAc;;;;;;;;;;wBAad,eACd,gCACA;EAAW;EAAc;;;;UCxDV;EACf;EACA;EACA;EACA;EACA;;UAGe;EACf;EACA;EACA;;UAGe;EACf;EACA;EACA;;UAGe;EACf;EACA;EACA;;UAGe;EACf,MAAM;EACN,SAAS;;UAGM;EAEf;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EAGA;EACA;EACA;EACA;EAGA;IACE;IACA;IACA;IACA;;EAIF;IACE;IACA;IACA;IACA;;EAIF,uBAAuB;EAGvB;IACE;IACA;MAAU;MAAc;MAAa;;IACrC;MAAQ;MAAc;;;EAGxB,QAAQ;EAIR;EAGA;EAGA;IACE;IACA;;EAIF;;UAMe;EACf;EACA;EACA;;UAGe;;EAEf;EACA;;EAEA;;EAEA;EACA;EACA,UAAU;;EAEV;IACE;IACA;IACA;IACA;IACA;IACA;IACA;;;;;;;;KASQ;EACV;EACA;EACA,UAAU;EACV,UAAU;IACR,QAAQ;UAIK;;EAEf;EACA;EACA;;EAEA;IACE;IACA;IACA;IACA;IACA;IACA;;;EAGF;;EAEA;;EAEA;;;UAIe;;EAEf;;EAEA;;UAGe,gBAAgB;EAC/B;EACA;EACA;EACA,UAAU;EACV,UAAU;;;;;;;;EAQV,sBAAsB;;;;;EAKtB;;KAMU;KAkBA;EAAgB;IAAe,KAAK,aAAa;;;;qBChLhD;qBA+SA,aAAa;qBAOb,cAAY,YAAA;qBAEZ,YAAU,YAAA;wBAIP,cAAc,SAAS;qBAI1B,UAAU;;;wBClVP,mBACd,0BACA,eACC;wBAkBa,cAAc,2BAA2B;;;YChC7C,WAAW,WAAW;KAC7B;EAAa;;EAAuB;;KACpC;EAAc;;EAAwB;;EAAkB;;YAEjD,UAAU,SAAS;YAEnB,iBAAiB;EAC3B;;EAEA;EACA,SAAS;;YAGC,cAAc;EACxB;;YAGU;;EAEV;EACA,SAAS;;YAGC;;EAEV;EACA,SAAS;EACT;;;;;YAMU,uBAAuB;;;;wBAgCnB,OACd,aACA,YACA,YACA,WACG,YACF,cAAc;;;;wBAqBD,QAAQ,SAAS,iBAAiB;;;;wBAQlC,MACb,QAAQ,QAAQ,QAAQ,6CACvB,YAAoB,WAAU,cAC/B;wBAOa,gBAAgB,SAAS;;;;;wBAezB,OACd,iBACE,YAAY,QAAQ,eAAmB,oBACxC;;;;;;;;;;;;;;;;wBC9Fa,cACd,UAAU,kBAER,SACA;EACG;EAAkB,SAAS;IAC/B"}