1- import { z } from " zod/mini" ;
2- import { vesselSchema , vesselProSchema , vesselBulkSchema } from " ./schemas.js" ;
3- import { formatDay } from " ./format.js" ;
1+ import { z } from ' zod/mini' ;
2+ import { vesselSchema , vesselProSchema , vesselBulkSchema } from ' ./schemas.js' ;
3+ import { formatDay } from ' ./format.js' ;
44import type {
55 VesselIdentifier ,
66 VesselInradiusParams ,
@@ -9,22 +9,14 @@ import type {
99 PortFindParams ,
1010 PortParams ,
1111 RouteParams ,
12- } from " ./types.js" ;
12+ } from ' ./types.js' ;
1313
14- export type {
15- VesselIdentifier ,
16- VesselInradiusParams ,
17- VesselHistoryParams ,
18- VesselFindParams ,
19- PortFindParams ,
20- PortParams ,
21- RouteParams ,
22- } ;
14+ export type { VesselIdentifier , VesselInradiusParams , VesselHistoryParams , VesselFindParams , PortFindParams , PortParams , RouteParams } ;
2315
2416export class EspadonClient {
25- #apiKey: string = "" ;
26- #baseUrl: string = " https://api.datalastic.com/api/" ;
27- #version: string = "v0" ;
17+ #apiKey: string = '' ;
18+ #baseUrl: string = ' https://api.datalastic.com/api/' ;
19+ #version: string = 'v0' ;
2820 #validate: boolean = true ;
2921 #debug: boolean = false ;
3022 #timeout: number | null = null ;
@@ -33,7 +25,7 @@ export class EspadonClient {
3325 * Internal method to set the API key. Called by the exported setup function.
3426 */
3527 setup ( { key, baseUrl, version, validate, debug, timeout } : EspadonOptions ) {
36- if ( ! key ) throw new Error ( " Datalastic API key must be provided." ) ;
28+ if ( ! key ) throw new Error ( ' Datalastic API key must be provided.' ) ;
3729 this . #apiKey = key ;
3830 if ( baseUrl !== undefined ) this . #baseUrl = baseUrl ;
3931 if ( version !== undefined ) this . #version = version ;
@@ -42,64 +34,44 @@ export class EspadonClient {
4234 if ( timeout !== undefined ) this . #timeout = timeout ;
4335 }
4436
45- // ── URL builders ─────────────────────────────────────────────────────
46-
4737 /**
4838 * Constructs the full URL for a Datalastic API call.
49- * @param prefix - path segment inserted between baseUrl and endpoint (default: this.#version, e.g. "v0")
5039 */
51- #buildUrl(
52- endpoint : string ,
53- params : Record < string , any > = { } ,
54- prefix ?: string ,
55- ) : string {
56- const url = new URL (
57- this . #baseUrl + ( prefix ?? this . #version) + endpoint ,
58- ) ;
40+ #buildUrl( endpoint : string , params : Record < string , any > = { } , prefix ?: string ) : string {
41+ const url = new URL ( this . #baseUrl + ( prefix ?? this . #version) + endpoint ) ;
5942 for ( const key in params ) {
6043 if ( params [ key ] !== undefined ) {
6144 url . searchParams . append ( key , String ( params [ key ] ) ) ;
6245 }
6346 }
64- url . searchParams . append ( " api-key" , this . #apiKey) ;
65- if ( this . #debug) console . log ( " CALLING" , url . href ) ;
47+ url . searchParams . append ( ' api-key' , this . #apiKey) ;
48+ if ( this . #debug) console . log ( ' CALLING' , url . href ) ;
6649 return url . toString ( ) ;
6750 }
6851
6952 /**
70- * Constructs a URL from an array of [key, value] entries,
71- * supporting repeated keys (needed by /vessel_bulk).
53+ * Constructs a URL from an array of [key, value] entries, supporting repeated keys (needed by /vessel_bulk).
7254 */
73- #buildUrlMulti(
74- endpoint : string ,
75- entries : [ string , string | number ] [ ] ,
76- ) : string {
55+ #buildUrlMulti( endpoint : string , entries : [ string , string | number ] [ ] ) : string {
7756 const url = new URL ( this . #baseUrl + this . #version + endpoint ) ;
7857 for ( const [ key , value ] of entries ) {
7958 if ( value !== undefined ) {
8059 url . searchParams . append ( key , String ( value ) ) ;
8160 }
8261 }
83- url . searchParams . append ( " api-key" , this . #apiKey) ;
84- if ( this . #debug) console . log ( " CALLING" , url . href ) ;
62+ url . searchParams . append ( ' api-key' , this . #apiKey) ;
63+ if ( this . #debug) console . log ( ' CALLING' , url . href ) ;
8564 return url . toString ( ) ;
8665 }
8766
88- // ── Internal fetch / call helpers ────────────────────────────────────
89-
9067 /**
9168 * Sends a request and returns the raw JSON body.
9269 */
9370 async #fetch( url : string ) : Promise < any > {
9471 const response = await fetch ( url , {
95- signal : this . #timeout
96- ? AbortSignal . timeout ( this . #timeout)
97- : undefined ,
72+ signal : this . #timeout ? AbortSignal . timeout ( this . #timeout) : undefined ,
9873 } ) ;
99- if ( ! response . ok )
100- throw new Error (
101- `Datalastic HTTP Error ${ response . status } for ${ url } ` ,
102- ) ;
74+ if ( ! response . ok ) throw new Error ( `Datalastic HTTP Error ${ response . status } for ${ url } ` ) ;
10375 return response . json ( ) ;
10476 }
10577
@@ -138,157 +110,124 @@ export class EspadonClient {
138110 return data ;
139111 }
140112
141- // ── Public methods ───────────────────────────────────────────────────
142-
143113 /**
144114 * Calls any endpoint — useful for unsupported or new endpoints.
145115 */
146- async any < T extends z . ZodMiniType < any > > (
147- endpoint : string ,
148- schema : T | null = z . any ( ) as unknown as T ,
149- params : Record < string , any > = { } ,
150- ) {
116+ async any < T extends z . ZodMiniType < any > > ( endpoint : string , schema : T | null = z . any ( ) as unknown as T , params : Record < string , any > = { } ) {
151117 return this . #callEndpoint( endpoint , schema , params ) ;
152118 }
153119
154120 /**
155- * Basic live ship tracking (`/vessel`).
121+ * Basic live vessel tracking (`/vessel`).
156122 *
157- * Returns vessel name, MMSI, IMO, UUID, country, type/subtype,
158- * position, speed, course, heading, navigational status, destination,
159- * and timestamp.
123+ * Returns vessel name, MMSI, IMO, UUID, country, type/subtype, position, speed, course, heading, navigational status, destination, and timestamp.
160124 */
161125 async vessel ( params : VesselIdentifier | string ) {
162- const normalized =
163- typeof params === "string" ? { uuid : params } : params ;
164- return this . #callEndpoint( "/vessel" , vesselSchema , normalized ) ;
126+ const normalized = typeof params === 'string' ? { uuid : params } : params ;
127+ return this . #callEndpoint( '/vessel' , vesselSchema , normalized ) ;
165128 }
166129
167130 /**
168- * Pro live ship tracking (`/vessel_pro`).
131+ * Pro live vessel tracking (`/vessel_pro`).
169132 *
170- * Everything from basic plus current draught, departure/arrival ports
171- * (name + UN/LOCODE), ATD and ETA.
133+ * Everything from basic plus current draught, departure/arrival ports (name + UN/LOCODE), ATD and ETA.
172134 */
173135 async vesselPro ( params : VesselIdentifier | string ) {
174- const normalized =
175- typeof params === "string" ? { uuid : params } : params ;
176- return this . #callEndpoint( "/vessel_pro" , vesselProSchema , normalized ) ;
136+ const normalized = typeof params === 'string' ? { uuid : params } : params ;
137+ return this . #callEndpoint( '/vessel_pro' , vesselProSchema , normalized ) ;
177138 }
178139
179140 /**
180- * Bulk live ship tracking (`/vessel_bulk`).
141+ * Bulk live vessel tracking (`/vessel_bulk`).
181142 *
182- * Fetches up to 100 vessels in a single call.
183- * Accepts an array of identifiers — repeated keys are supported
184- * (e.g. `[{ imo: 111 }, { imo: 222 }]` → `?imo=111&imo=222`).
143+ * Fetches up to 100 vessels in a single call. Accepts an array of identifiers — repeated keys are supported
185144 */
186145 async vesselBulk ( params : VesselIdentifier [ ] ) {
187- const entries : [ string , string | number ] [ ] = params . flatMap (
188- ( id ) => Object . entries ( id ) as [ string , string | number ] [ ] ,
189- ) ;
190- return this . #callEndpointMulti(
191- "/vessel_bulk" ,
192- vesselBulkSchema ,
193- entries ,
194- ) ;
146+ const entries : [ string , string | number ] [ ] = params . flatMap ( ( id ) => Object . entries ( id ) as [ string , string | number ] [ ] ) ;
147+ return this . #callEndpointMulti( '/vessel_bulk' , vesselBulkSchema , entries ) ;
195148 }
196149
197150 /**
198151 * Location traffic tracking (`/vessel_inradius`).
199152 *
200- * Scans an area around a static point (lat/lon, port UUID or UNLOCODE)
201- * or a dynamic center (vessel UUID/MMSI/IMO) within a given radius
202- * (in nautical miles, max 50 NM).
153+ * Scans an area around a static point (lat/lon, port UUID or UNLOCODE) or a dynamic center (vessel UUID/MMSI/IMO) within a given radius (in nautical miles, max 50 NM).
203154 */
204155 async vesselInradius ( params : VesselInradiusParams ) {
205- return this . #callEndpoint( " /vessel_inradius" , null , params as any ) ;
156+ return this . #callEndpoint( ' /vessel_inradius' , null , params as any ) ;
206157 }
207158
208159 /**
209160 * Historical vessel data (`/vessel_history`).
210161 *
211162 * Returns past positions, speed, course, heading, destination, etc.
212- * Specify a time range with `{ from, to }` (dates) or `{ days }`.
213- * `from` and `to` are formatted to `YYYY-MM-DD` automatically.
163+ * Specify a time range with `{ from, to }` (dates) or `{ days }`. `from` and `to` are formatted to `YYYY-MM-DD` automatically.
214164 */
215165 async vesselHistory ( params : VesselHistoryParams ) {
216166 const formatted : Record < string , any > = { ...params } ;
217- if ( " from" in formatted && formatted . from !== undefined ) {
167+ if ( ' from' in formatted && formatted . from !== undefined ) {
218168 formatted . from = formatDay ( formatted . from ) ;
219169 }
220- if ( "to" in formatted && formatted . to !== undefined ) {
170+ if ( 'to' in formatted && formatted . to !== undefined ) {
221171 formatted . to = formatDay ( formatted . to ) ;
222172 }
223- return this . #callEndpoint( " /vessel_history" , null , formatted ) ;
173+ return this . #callEndpoint( ' /vessel_history' , null , formatted ) ;
224174 }
225175
226176 /**
227177 * Ship specs info (`/vessel_info`).
228178 *
229- * Returns detailed vessel specifications: name, IMO, MMSI, UUID,
230- * call sign, country, type/subtype, draught, TEU, deadweight,
231- * liquid gas capacity, length, breadth, year built, and more.
179+ * Returns detailed vessel specifications: name, IMO, MMSI, UUID, call sign, country, type/subtype, draught, TEU, deadweight, liquid gas capacity, length, breadth, year built, and more.
232180 */
233181 async vesselInfo ( params : VesselIdentifier | string ) {
234- const normalized =
235- typeof params === "string" ? { uuid : params } : params ;
236- return this . #callEndpoint( "/vessel_info" , null , normalized ) ;
182+ const normalized = typeof params === 'string' ? { uuid : params } : params ;
183+ return this . #callEndpoint( '/vessel_info' , null , normalized ) ;
237184 }
238185
239186 /**
240187 * Vessel finder (`/vessel_find`).
241188 *
242- * Searches vessels by name, type, country, tonnage, deadweight,
243- * dimensions, year built, etc. Supports fuzzy name matching and
244- * pagination via `next`.
189+ * Searches vessels by name, type, country, tonnage, deadweight, dimensions, year built, etc. Supports fuzzy name matching and pagination via `next`.
245190 */
246191 async vesselFind ( params : VesselFindParams ) {
247- return this . #callEndpoint( " /vessel_find" , null , params as any ) ;
192+ return this . #callEndpoint( ' /vessel_find' , null , params as any ) ;
248193 }
249194
250195 /**
251196 * Port finder (`/port_find`).
252197 *
253- * Searches ports by name, UUID, UNLOCODE, type, country,
254- * or geo-coordinates with radius. Supports fuzzy name matching.
198+ * Searches ports by name, UUID, UNLOCODE, type, country, or geo-coordinates with radius. Supports fuzzy name matching.
255199 */
256200 async portFind ( params : PortFindParams ) {
257- return this . #callEndpoint( " /port_find" , null , params as any ) ;
201+ return this . #callEndpoint( ' /port_find' , null , params as any ) ;
258202 }
259203
260204 /**
261205 * Port terminals (`/port`).
262206 *
263- * Returns detailed port information including associated terminals,
264- * coordinates, operator names, and contact details.
207+ * Returns detailed port information including associated terminals, coordinates, operator names, and contact details.
265208 */
266209 async port ( params : PortParams ) {
267- return this . #callEndpoint( " /port" , null , params as any ) ;
210+ return this . #callEndpoint( ' /port' , null , params as any ) ;
268211 }
269212
270213 /**
271214 * Sea routes (`/api/ext/route`).
272215 *
273216 * Computes the optimal maritime route between two points.
274- * Points can be specified as coordinates (`lat_from`/`lon_from`,
275- * `lat_to`/`lon_to`), port UUIDs, or UN/LOCODEs.
217+ * Points can be specified as coordinates (`lat_from`/`lon_from`, `lat_to`/`lon_to`), port UUIDs, or UN/LOCODEs.
276218 */
277219 async route ( params : RouteParams ) {
278- return this . #callEndpoint( " /route" , null , params as any , " ext" ) ;
220+ return this . #callEndpoint( ' /route' , null , params as any , ' ext' ) ;
279221 }
280222
281223 /**
282224 * SAT-E estimated position (`/api/ext/vessel_pro_est`).
283225 *
284- * Returns an estimated vessel position even when the ship is out of
285- * AIS range, calculated from the last known location, destination
286- * port, and route-based ETA.
226+ * Returns an estimated vessel position even when the ship is out of AIS range, calculated from the last known location, destination port, and route-based ETA.
287227 */
288228 async satellite ( params : VesselIdentifier | string ) {
289- const normalized =
290- typeof params === "string" ? { uuid : params } : params ;
291- return this . #callEndpoint( "/vessel_pro_est" , null , normalized , "ext" ) ;
229+ const normalized = typeof params === 'string' ? { uuid : params } : params ;
230+ return this . #callEndpoint( '/vessel_pro_est' , null , normalized , 'ext' ) ;
292231 }
293232}
294233
@@ -297,7 +236,7 @@ const client = new EspadonClient();
297236export interface EspadonOptions {
298237 key : string ;
299238 baseUrl ?: string ;
300- version ?: "v0" ;
239+ version ?: 'v0' ;
301240 validate ?: boolean ;
302241 debug ?: boolean ;
303242 timeout ?: number | null ;
0 commit comments