@sixfathoms/lplex 0.2.1 → 0.3.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.
- package/dist/index.cjs +56 -1
- package/dist/index.d.cts +51 -1
- package/dist/index.d.ts +51 -1
- package/dist/index.js +56 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -203,6 +203,18 @@ var Client = class {
|
|
|
203
203
|
}
|
|
204
204
|
return parseSSE(resp.body);
|
|
205
205
|
}
|
|
206
|
+
/** Fetch the last-seen decoded values for each (device, PGN) pair. */
|
|
207
|
+
async decodedValues(filter, signal) {
|
|
208
|
+
let url = `${this.#baseURL}/values/decoded`;
|
|
209
|
+
const qs = filterToQueryString(filter);
|
|
210
|
+
if (qs) url += `?${qs}`;
|
|
211
|
+
const resp = await this.#fetch(url, { signal });
|
|
212
|
+
if (!resp.ok) {
|
|
213
|
+
const body = await resp.text();
|
|
214
|
+
throw new HttpError("GET", url, resp.status, body);
|
|
215
|
+
}
|
|
216
|
+
return resp.json();
|
|
217
|
+
}
|
|
206
218
|
/** Transmit a CAN frame through the server. */
|
|
207
219
|
async send(params, signal) {
|
|
208
220
|
const url = `${this.#baseURL}/send`;
|
|
@@ -217,6 +229,44 @@ var Client = class {
|
|
|
217
229
|
throw new HttpError("POST", url, resp.status, body);
|
|
218
230
|
}
|
|
219
231
|
}
|
|
232
|
+
/**
|
|
233
|
+
* Send an ISO Request (PGN 59904) and wait for the response frame.
|
|
234
|
+
* Returns the response frame, or throws HttpError with status 504 on timeout.
|
|
235
|
+
*/
|
|
236
|
+
async query(params, signal) {
|
|
237
|
+
const url = `${this.#baseURL}/query`;
|
|
238
|
+
const resp = await this.#fetch(url, {
|
|
239
|
+
method: "POST",
|
|
240
|
+
headers: { "Content-Type": "application/json" },
|
|
241
|
+
body: JSON.stringify(params),
|
|
242
|
+
signal
|
|
243
|
+
});
|
|
244
|
+
if (!resp.ok) {
|
|
245
|
+
const body = await resp.text();
|
|
246
|
+
throw new HttpError("POST", url, resp.status, body);
|
|
247
|
+
}
|
|
248
|
+
return resp.json();
|
|
249
|
+
}
|
|
250
|
+
/** Check server health. */
|
|
251
|
+
async health(signal) {
|
|
252
|
+
const url = `${this.#baseURL}/healthz`;
|
|
253
|
+
const resp = await this.#fetch(url, { signal });
|
|
254
|
+
if (!resp.ok) {
|
|
255
|
+
const body = await resp.text();
|
|
256
|
+
throw new HttpError("GET", url, resp.status, body);
|
|
257
|
+
}
|
|
258
|
+
return resp.json();
|
|
259
|
+
}
|
|
260
|
+
/** Fetch boat-side replication status (only available when replication is configured). */
|
|
261
|
+
async replicationStatus(signal) {
|
|
262
|
+
const url = `${this.#baseURL}/replication/status`;
|
|
263
|
+
const resp = await this.#fetch(url, { signal });
|
|
264
|
+
if (!resp.ok) {
|
|
265
|
+
const body = await resp.text();
|
|
266
|
+
throw new HttpError("GET", url, resp.status, body);
|
|
267
|
+
}
|
|
268
|
+
return resp.json();
|
|
269
|
+
}
|
|
220
270
|
/** Create or reconnect a buffered session on the server. */
|
|
221
271
|
async createSession(config, signal) {
|
|
222
272
|
const url = `${this.#baseURL}/clients/${config.clientId}`;
|
|
@@ -241,23 +291,28 @@ var Client = class {
|
|
|
241
291
|
}
|
|
242
292
|
};
|
|
243
293
|
function filterIsEmpty(f) {
|
|
244
|
-
return !f.pgn?.length && !f.manufacturer?.length && !f.instance?.length && !f.name?.length;
|
|
294
|
+
return !f.pgn?.length && !f.exclude_pgn?.length && !f.manufacturer?.length && !f.instance?.length && !f.name?.length && !f.exclude_name?.length;
|
|
245
295
|
}
|
|
246
296
|
function filterToQueryString(f) {
|
|
247
297
|
if (!f || filterIsEmpty(f)) return "";
|
|
248
298
|
const params = new URLSearchParams();
|
|
249
299
|
for (const p of f.pgn ?? []) params.append("pgn", p.toString());
|
|
300
|
+
for (const p of f.exclude_pgn ?? [])
|
|
301
|
+
params.append("exclude_pgn", p.toString());
|
|
250
302
|
for (const m of f.manufacturer ?? []) params.append("manufacturer", m);
|
|
251
303
|
for (const i of f.instance ?? []) params.append("instance", i.toString());
|
|
252
304
|
for (const n of f.name ?? []) params.append("name", n);
|
|
305
|
+
for (const n of f.exclude_name ?? []) params.append("exclude_name", n);
|
|
253
306
|
return params.toString();
|
|
254
307
|
}
|
|
255
308
|
function filterToJSON(f) {
|
|
256
309
|
const m = {};
|
|
257
310
|
if (f.pgn?.length) m.pgn = f.pgn;
|
|
311
|
+
if (f.exclude_pgn?.length) m.exclude_pgn = f.exclude_pgn;
|
|
258
312
|
if (f.manufacturer?.length) m.manufacturer = f.manufacturer;
|
|
259
313
|
if (f.instance?.length) m.instance = f.instance;
|
|
260
314
|
if (f.name?.length) m.name = f.name;
|
|
315
|
+
if (f.exclude_name?.length) m.exclude_name = f.exclude_name;
|
|
261
316
|
return m;
|
|
262
317
|
}
|
|
263
318
|
|
package/dist/index.d.cts
CHANGED
|
@@ -42,9 +42,11 @@ type Event = {
|
|
|
42
42
|
*/
|
|
43
43
|
interface Filter {
|
|
44
44
|
pgn?: number[];
|
|
45
|
+
exclude_pgn?: number[];
|
|
45
46
|
manufacturer?: string[];
|
|
46
47
|
instance?: number[];
|
|
47
48
|
name?: string[];
|
|
49
|
+
exclude_name?: string[];
|
|
48
50
|
}
|
|
49
51
|
/** Configuration for creating a buffered session. */
|
|
50
52
|
interface SessionConfig {
|
|
@@ -82,6 +84,43 @@ interface DeviceValues {
|
|
|
82
84
|
model_id?: string;
|
|
83
85
|
values: PGNValue[];
|
|
84
86
|
}
|
|
87
|
+
/** A single PGN's decoded value for a device. */
|
|
88
|
+
interface DecodedPGNValue {
|
|
89
|
+
pgn: number;
|
|
90
|
+
ts: string;
|
|
91
|
+
data: string;
|
|
92
|
+
seq: number;
|
|
93
|
+
decoded: Record<string, unknown>;
|
|
94
|
+
}
|
|
95
|
+
/** Decoded values grouped by device. */
|
|
96
|
+
interface DecodedDeviceValues {
|
|
97
|
+
name: string;
|
|
98
|
+
src: number;
|
|
99
|
+
manufacturer?: string;
|
|
100
|
+
model_id?: string;
|
|
101
|
+
values: DecodedPGNValue[];
|
|
102
|
+
}
|
|
103
|
+
/** Parameters for an ISO Request query (POST /query). */
|
|
104
|
+
interface QueryParams {
|
|
105
|
+
pgn: number;
|
|
106
|
+
dst: number;
|
|
107
|
+
timeout?: string;
|
|
108
|
+
}
|
|
109
|
+
/** Health check response from GET /healthz. */
|
|
110
|
+
interface HealthStatus {
|
|
111
|
+
status: string;
|
|
112
|
+
}
|
|
113
|
+
/** Boat-side replication status from GET /replication/status. */
|
|
114
|
+
interface ReplicationStatus {
|
|
115
|
+
connected: boolean;
|
|
116
|
+
instance_id: string;
|
|
117
|
+
local_head_seq: number;
|
|
118
|
+
cloud_cursor: number;
|
|
119
|
+
holes: SeqRange[];
|
|
120
|
+
live_lag: number;
|
|
121
|
+
backfill_remaining_seqs: number;
|
|
122
|
+
last_ack: string;
|
|
123
|
+
}
|
|
85
124
|
/** Summary of a cloud instance, returned by GET /instances. */
|
|
86
125
|
interface InstanceSummary {
|
|
87
126
|
id: string;
|
|
@@ -149,8 +188,19 @@ declare class Client {
|
|
|
149
188
|
* No session, no replay, no ACK.
|
|
150
189
|
*/
|
|
151
190
|
subscribe(filter?: Filter, signal?: AbortSignal): Promise<AsyncIterable<Event>>;
|
|
191
|
+
/** Fetch the last-seen decoded values for each (device, PGN) pair. */
|
|
192
|
+
decodedValues(filter?: Filter, signal?: AbortSignal): Promise<DecodedDeviceValues[]>;
|
|
152
193
|
/** Transmit a CAN frame through the server. */
|
|
153
194
|
send(params: SendParams, signal?: AbortSignal): Promise<void>;
|
|
195
|
+
/**
|
|
196
|
+
* Send an ISO Request (PGN 59904) and wait for the response frame.
|
|
197
|
+
* Returns the response frame, or throws HttpError with status 504 on timeout.
|
|
198
|
+
*/
|
|
199
|
+
query(params: QueryParams, signal?: AbortSignal): Promise<Frame>;
|
|
200
|
+
/** Check server health. */
|
|
201
|
+
health(signal?: AbortSignal): Promise<HealthStatus>;
|
|
202
|
+
/** Fetch boat-side replication status (only available when replication is configured). */
|
|
203
|
+
replicationStatus(signal?: AbortSignal): Promise<ReplicationStatus>;
|
|
154
204
|
/** Create or reconnect a buffered session on the server. */
|
|
155
205
|
createSession(config: SessionConfig, signal?: AbortSignal): Promise<Session>;
|
|
156
206
|
}
|
|
@@ -191,4 +241,4 @@ declare class HttpError extends LplexError {
|
|
|
191
241
|
constructor(method: string, path: string, status: number, body: string);
|
|
192
242
|
}
|
|
193
243
|
|
|
194
|
-
export { Client, type ClientOptions, CloudClient, type CloudClientOptions, type Device, type DeviceValues, type Event, type Filter, type Frame, HttpError, type InstanceStatus, type InstanceSummary, LplexError, type PGNValue, type ReplicationEvent, type ReplicationEventType, type SendParams, type SeqRange, Session, type SessionConfig, type SessionInfo };
|
|
244
|
+
export { Client, type ClientOptions, CloudClient, type CloudClientOptions, type DecodedDeviceValues, type DecodedPGNValue, type Device, type DeviceValues, type Event, type Filter, type Frame, type HealthStatus, HttpError, type InstanceStatus, type InstanceSummary, LplexError, type PGNValue, type QueryParams, type ReplicationEvent, type ReplicationEventType, type ReplicationStatus, type SendParams, type SeqRange, Session, type SessionConfig, type SessionInfo };
|
package/dist/index.d.ts
CHANGED
|
@@ -42,9 +42,11 @@ type Event = {
|
|
|
42
42
|
*/
|
|
43
43
|
interface Filter {
|
|
44
44
|
pgn?: number[];
|
|
45
|
+
exclude_pgn?: number[];
|
|
45
46
|
manufacturer?: string[];
|
|
46
47
|
instance?: number[];
|
|
47
48
|
name?: string[];
|
|
49
|
+
exclude_name?: string[];
|
|
48
50
|
}
|
|
49
51
|
/** Configuration for creating a buffered session. */
|
|
50
52
|
interface SessionConfig {
|
|
@@ -82,6 +84,43 @@ interface DeviceValues {
|
|
|
82
84
|
model_id?: string;
|
|
83
85
|
values: PGNValue[];
|
|
84
86
|
}
|
|
87
|
+
/** A single PGN's decoded value for a device. */
|
|
88
|
+
interface DecodedPGNValue {
|
|
89
|
+
pgn: number;
|
|
90
|
+
ts: string;
|
|
91
|
+
data: string;
|
|
92
|
+
seq: number;
|
|
93
|
+
decoded: Record<string, unknown>;
|
|
94
|
+
}
|
|
95
|
+
/** Decoded values grouped by device. */
|
|
96
|
+
interface DecodedDeviceValues {
|
|
97
|
+
name: string;
|
|
98
|
+
src: number;
|
|
99
|
+
manufacturer?: string;
|
|
100
|
+
model_id?: string;
|
|
101
|
+
values: DecodedPGNValue[];
|
|
102
|
+
}
|
|
103
|
+
/** Parameters for an ISO Request query (POST /query). */
|
|
104
|
+
interface QueryParams {
|
|
105
|
+
pgn: number;
|
|
106
|
+
dst: number;
|
|
107
|
+
timeout?: string;
|
|
108
|
+
}
|
|
109
|
+
/** Health check response from GET /healthz. */
|
|
110
|
+
interface HealthStatus {
|
|
111
|
+
status: string;
|
|
112
|
+
}
|
|
113
|
+
/** Boat-side replication status from GET /replication/status. */
|
|
114
|
+
interface ReplicationStatus {
|
|
115
|
+
connected: boolean;
|
|
116
|
+
instance_id: string;
|
|
117
|
+
local_head_seq: number;
|
|
118
|
+
cloud_cursor: number;
|
|
119
|
+
holes: SeqRange[];
|
|
120
|
+
live_lag: number;
|
|
121
|
+
backfill_remaining_seqs: number;
|
|
122
|
+
last_ack: string;
|
|
123
|
+
}
|
|
85
124
|
/** Summary of a cloud instance, returned by GET /instances. */
|
|
86
125
|
interface InstanceSummary {
|
|
87
126
|
id: string;
|
|
@@ -149,8 +188,19 @@ declare class Client {
|
|
|
149
188
|
* No session, no replay, no ACK.
|
|
150
189
|
*/
|
|
151
190
|
subscribe(filter?: Filter, signal?: AbortSignal): Promise<AsyncIterable<Event>>;
|
|
191
|
+
/** Fetch the last-seen decoded values for each (device, PGN) pair. */
|
|
192
|
+
decodedValues(filter?: Filter, signal?: AbortSignal): Promise<DecodedDeviceValues[]>;
|
|
152
193
|
/** Transmit a CAN frame through the server. */
|
|
153
194
|
send(params: SendParams, signal?: AbortSignal): Promise<void>;
|
|
195
|
+
/**
|
|
196
|
+
* Send an ISO Request (PGN 59904) and wait for the response frame.
|
|
197
|
+
* Returns the response frame, or throws HttpError with status 504 on timeout.
|
|
198
|
+
*/
|
|
199
|
+
query(params: QueryParams, signal?: AbortSignal): Promise<Frame>;
|
|
200
|
+
/** Check server health. */
|
|
201
|
+
health(signal?: AbortSignal): Promise<HealthStatus>;
|
|
202
|
+
/** Fetch boat-side replication status (only available when replication is configured). */
|
|
203
|
+
replicationStatus(signal?: AbortSignal): Promise<ReplicationStatus>;
|
|
154
204
|
/** Create or reconnect a buffered session on the server. */
|
|
155
205
|
createSession(config: SessionConfig, signal?: AbortSignal): Promise<Session>;
|
|
156
206
|
}
|
|
@@ -191,4 +241,4 @@ declare class HttpError extends LplexError {
|
|
|
191
241
|
constructor(method: string, path: string, status: number, body: string);
|
|
192
242
|
}
|
|
193
243
|
|
|
194
|
-
export { Client, type ClientOptions, CloudClient, type CloudClientOptions, type Device, type DeviceValues, type Event, type Filter, type Frame, HttpError, type InstanceStatus, type InstanceSummary, LplexError, type PGNValue, type ReplicationEvent, type ReplicationEventType, type SendParams, type SeqRange, Session, type SessionConfig, type SessionInfo };
|
|
244
|
+
export { Client, type ClientOptions, CloudClient, type CloudClientOptions, type DecodedDeviceValues, type DecodedPGNValue, type Device, type DeviceValues, type Event, type Filter, type Frame, type HealthStatus, HttpError, type InstanceStatus, type InstanceSummary, LplexError, type PGNValue, type QueryParams, type ReplicationEvent, type ReplicationEventType, type ReplicationStatus, type SendParams, type SeqRange, Session, type SessionConfig, type SessionInfo };
|
package/dist/index.js
CHANGED
|
@@ -173,6 +173,18 @@ var Client = class {
|
|
|
173
173
|
}
|
|
174
174
|
return parseSSE(resp.body);
|
|
175
175
|
}
|
|
176
|
+
/** Fetch the last-seen decoded values for each (device, PGN) pair. */
|
|
177
|
+
async decodedValues(filter, signal) {
|
|
178
|
+
let url = `${this.#baseURL}/values/decoded`;
|
|
179
|
+
const qs = filterToQueryString(filter);
|
|
180
|
+
if (qs) url += `?${qs}`;
|
|
181
|
+
const resp = await this.#fetch(url, { signal });
|
|
182
|
+
if (!resp.ok) {
|
|
183
|
+
const body = await resp.text();
|
|
184
|
+
throw new HttpError("GET", url, resp.status, body);
|
|
185
|
+
}
|
|
186
|
+
return resp.json();
|
|
187
|
+
}
|
|
176
188
|
/** Transmit a CAN frame through the server. */
|
|
177
189
|
async send(params, signal) {
|
|
178
190
|
const url = `${this.#baseURL}/send`;
|
|
@@ -187,6 +199,44 @@ var Client = class {
|
|
|
187
199
|
throw new HttpError("POST", url, resp.status, body);
|
|
188
200
|
}
|
|
189
201
|
}
|
|
202
|
+
/**
|
|
203
|
+
* Send an ISO Request (PGN 59904) and wait for the response frame.
|
|
204
|
+
* Returns the response frame, or throws HttpError with status 504 on timeout.
|
|
205
|
+
*/
|
|
206
|
+
async query(params, signal) {
|
|
207
|
+
const url = `${this.#baseURL}/query`;
|
|
208
|
+
const resp = await this.#fetch(url, {
|
|
209
|
+
method: "POST",
|
|
210
|
+
headers: { "Content-Type": "application/json" },
|
|
211
|
+
body: JSON.stringify(params),
|
|
212
|
+
signal
|
|
213
|
+
});
|
|
214
|
+
if (!resp.ok) {
|
|
215
|
+
const body = await resp.text();
|
|
216
|
+
throw new HttpError("POST", url, resp.status, body);
|
|
217
|
+
}
|
|
218
|
+
return resp.json();
|
|
219
|
+
}
|
|
220
|
+
/** Check server health. */
|
|
221
|
+
async health(signal) {
|
|
222
|
+
const url = `${this.#baseURL}/healthz`;
|
|
223
|
+
const resp = await this.#fetch(url, { signal });
|
|
224
|
+
if (!resp.ok) {
|
|
225
|
+
const body = await resp.text();
|
|
226
|
+
throw new HttpError("GET", url, resp.status, body);
|
|
227
|
+
}
|
|
228
|
+
return resp.json();
|
|
229
|
+
}
|
|
230
|
+
/** Fetch boat-side replication status (only available when replication is configured). */
|
|
231
|
+
async replicationStatus(signal) {
|
|
232
|
+
const url = `${this.#baseURL}/replication/status`;
|
|
233
|
+
const resp = await this.#fetch(url, { signal });
|
|
234
|
+
if (!resp.ok) {
|
|
235
|
+
const body = await resp.text();
|
|
236
|
+
throw new HttpError("GET", url, resp.status, body);
|
|
237
|
+
}
|
|
238
|
+
return resp.json();
|
|
239
|
+
}
|
|
190
240
|
/** Create or reconnect a buffered session on the server. */
|
|
191
241
|
async createSession(config, signal) {
|
|
192
242
|
const url = `${this.#baseURL}/clients/${config.clientId}`;
|
|
@@ -211,23 +261,28 @@ var Client = class {
|
|
|
211
261
|
}
|
|
212
262
|
};
|
|
213
263
|
function filterIsEmpty(f) {
|
|
214
|
-
return !f.pgn?.length && !f.manufacturer?.length && !f.instance?.length && !f.name?.length;
|
|
264
|
+
return !f.pgn?.length && !f.exclude_pgn?.length && !f.manufacturer?.length && !f.instance?.length && !f.name?.length && !f.exclude_name?.length;
|
|
215
265
|
}
|
|
216
266
|
function filterToQueryString(f) {
|
|
217
267
|
if (!f || filterIsEmpty(f)) return "";
|
|
218
268
|
const params = new URLSearchParams();
|
|
219
269
|
for (const p of f.pgn ?? []) params.append("pgn", p.toString());
|
|
270
|
+
for (const p of f.exclude_pgn ?? [])
|
|
271
|
+
params.append("exclude_pgn", p.toString());
|
|
220
272
|
for (const m of f.manufacturer ?? []) params.append("manufacturer", m);
|
|
221
273
|
for (const i of f.instance ?? []) params.append("instance", i.toString());
|
|
222
274
|
for (const n of f.name ?? []) params.append("name", n);
|
|
275
|
+
for (const n of f.exclude_name ?? []) params.append("exclude_name", n);
|
|
223
276
|
return params.toString();
|
|
224
277
|
}
|
|
225
278
|
function filterToJSON(f) {
|
|
226
279
|
const m = {};
|
|
227
280
|
if (f.pgn?.length) m.pgn = f.pgn;
|
|
281
|
+
if (f.exclude_pgn?.length) m.exclude_pgn = f.exclude_pgn;
|
|
228
282
|
if (f.manufacturer?.length) m.manufacturer = f.manufacturer;
|
|
229
283
|
if (f.instance?.length) m.instance = f.instance;
|
|
230
284
|
if (f.name?.length) m.name = f.name;
|
|
285
|
+
if (f.exclude_name?.length) m.exclude_name = f.exclude_name;
|
|
231
286
|
return m;
|
|
232
287
|
}
|
|
233
288
|
|