Skip to content

Commit 2ab877b

Browse files
committed
formatting
1 parent 68426a8 commit 2ab877b

3 files changed

Lines changed: 57 additions & 126 deletions

File tree

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "espadon",
33
"version": "1.0.0",
4-
"description": "A lightweight universal typed client for the Financial Modeling Prep (FMP) API. Gets your financial data perfectly formatted.",
4+
"description": "A lightweight (~50 kB) universal typed client for Datalastic APIs: vessel live tracking, info, port info, routes, ...",
55
"author": {
66
"name": "Louis Grange",
77
"url": "https://github.com/l0uisgrange"

src/index.ts

Lines changed: 53 additions & 114 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
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';
44
import 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

2416
export 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();
297236
export interface EspadonOptions {
298237
key: string;
299238
baseUrl?: string;
300-
version?: "v0";
239+
version?: 'v0';
301240
validate?: boolean;
302241
debug?: boolean;
303242
timeout?: number | null;

src/types.ts

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
11
/** Identifies a single vessel by one of its unique keys. */
2-
export type VesselIdentifier =
3-
| { uuid: string }
4-
| { mmsi: number | string }
5-
| { imo: number | string };
2+
export type VesselIdentifier = { uuid: string } | { mmsi: number | string } | { imo: number | string };
63

74
/** Parameters for the `/vessel_inradius` endpoint (static or dynamic center). */
85
export type VesselInradiusParams = {
@@ -23,8 +20,7 @@ export type VesselInradiusParams = {
2320
);
2421

2522
/** Parameters for the `/vessel_history` endpoint. */
26-
export type VesselHistoryParams = VesselIdentifier &
27-
({ days: number } | { from: Date | string; to: Date | string } | {});
23+
export type VesselHistoryParams = VesselIdentifier & ({ days: number } | { from: Date | string; to: Date | string } | {});
2824

2925
/** Parameters for the `/vessel_find` endpoint. */
3026
export type VesselFindParams = {
@@ -61,11 +57,7 @@ export type PortFindParams = {
6157
};
6258

6359
/** Parameters for the `/port` (port terminals) endpoint. */
64-
export type PortParams =
65-
| { name: string }
66-
| { uuid: string }
67-
| { unlocode: string }
68-
| { lat: number; lon: number; radius?: number };
60+
export type PortParams = { name: string } | { uuid: string } | { unlocode: string } | { lat: number; lon: number; radius?: number };
6961

7062
/** Parameters for the `/api/ext/route` (sea routes) endpoint. */
7163
export type RouteParams = {

0 commit comments

Comments
 (0)