@ambulancewa/linxio-js 2.23.2
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/LICENSE +25 -0
- package/README.md +117 -0
- package/dist/index.cjs +2232 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +2000 -0
- package/dist/index.d.ts +2000 -0
- package/dist/index.js +2163 -0
- package/dist/index.js.map +1 -0
- package/package.json +90 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,2163 @@
|
|
|
1
|
+
// src/errors.ts
|
|
2
|
+
var LinxioError = class extends Error {
|
|
3
|
+
cause;
|
|
4
|
+
method;
|
|
5
|
+
path;
|
|
6
|
+
requestId;
|
|
7
|
+
constructor(message, context = {}) {
|
|
8
|
+
super(message);
|
|
9
|
+
this.name = "LinxioError";
|
|
10
|
+
this.cause = context.cause;
|
|
11
|
+
this.method = context.method;
|
|
12
|
+
this.path = context.path;
|
|
13
|
+
this.requestId = context.requestId;
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
var LinxioConfigurationError = class extends LinxioError {
|
|
17
|
+
constructor(message, context = {}) {
|
|
18
|
+
super(message, context);
|
|
19
|
+
this.name = "LinxioConfigurationError";
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
var LinxioNetworkError = class extends LinxioError {
|
|
23
|
+
constructor(message, context = {}) {
|
|
24
|
+
super(message, context);
|
|
25
|
+
this.name = "LinxioNetworkError";
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
var LinxioTimeoutError = class extends LinxioNetworkError {
|
|
29
|
+
constructor(message, context = {}) {
|
|
30
|
+
super(message, context);
|
|
31
|
+
this.name = "LinxioTimeoutError";
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
var LinxioApiError = class extends LinxioError {
|
|
35
|
+
body;
|
|
36
|
+
headers;
|
|
37
|
+
status;
|
|
38
|
+
statusText;
|
|
39
|
+
constructor(message, context) {
|
|
40
|
+
super(message, context);
|
|
41
|
+
this.name = "LinxioApiError";
|
|
42
|
+
this.body = context.body;
|
|
43
|
+
this.headers = context.headers;
|
|
44
|
+
this.status = context.status;
|
|
45
|
+
this.statusText = context.statusText;
|
|
46
|
+
}
|
|
47
|
+
get isAuthenticationError() {
|
|
48
|
+
return this.status === 401 || this.status === 403;
|
|
49
|
+
}
|
|
50
|
+
get isRateLimitError() {
|
|
51
|
+
return this.status === 429;
|
|
52
|
+
}
|
|
53
|
+
get isValidationError() {
|
|
54
|
+
return this.status === 422 || this.status === 400;
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
var LinxioAuthenticationError = class extends LinxioError {
|
|
58
|
+
constructor(message, context = {}) {
|
|
59
|
+
super(message, context);
|
|
60
|
+
this.name = "LinxioAuthenticationError";
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
var LinxioValidationError = class extends LinxioError {
|
|
64
|
+
issues;
|
|
65
|
+
constructor(message, context = {}) {
|
|
66
|
+
super(message, context);
|
|
67
|
+
this.name = "LinxioValidationError";
|
|
68
|
+
this.issues = context.issues;
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
var LinxioRealtimeError = class extends LinxioError {
|
|
72
|
+
constructor(message, context = {}) {
|
|
73
|
+
super(message, context);
|
|
74
|
+
this.name = "LinxioRealtimeError";
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
// src/response.ts
|
|
79
|
+
var envelopeKeys = /* @__PURE__ */ new Set([
|
|
80
|
+
"additionalFields",
|
|
81
|
+
"aggregations",
|
|
82
|
+
"data",
|
|
83
|
+
"limit",
|
|
84
|
+
"links",
|
|
85
|
+
"meta",
|
|
86
|
+
"page",
|
|
87
|
+
"result",
|
|
88
|
+
"total"
|
|
89
|
+
]);
|
|
90
|
+
function unwrapLinxioServiceData(value) {
|
|
91
|
+
const payload = unwrapResultEnvelope(value);
|
|
92
|
+
if (!isRecord(payload)) {
|
|
93
|
+
return payload;
|
|
94
|
+
}
|
|
95
|
+
if (isDataEnvelope(payload)) {
|
|
96
|
+
return payload.data;
|
|
97
|
+
}
|
|
98
|
+
const singletonArray = getSingletonArrayPayload(payload);
|
|
99
|
+
if (singletonArray) {
|
|
100
|
+
return singletonArray;
|
|
101
|
+
}
|
|
102
|
+
return payload;
|
|
103
|
+
}
|
|
104
|
+
function extractPageEnvelopeSource(value) {
|
|
105
|
+
const root = isRecord(value) ? value : {};
|
|
106
|
+
const result = isRecord(root.result) ? root.result : void 0;
|
|
107
|
+
return result ?? root;
|
|
108
|
+
}
|
|
109
|
+
function extractPageData(source) {
|
|
110
|
+
if (Array.isArray(source.data)) {
|
|
111
|
+
return source.data;
|
|
112
|
+
}
|
|
113
|
+
return getSingletonArrayPayload(source) ?? [];
|
|
114
|
+
}
|
|
115
|
+
function unwrapResultEnvelope(value) {
|
|
116
|
+
if (!isRecord(value) || !Object.hasOwn(value, "result")) {
|
|
117
|
+
return value;
|
|
118
|
+
}
|
|
119
|
+
return value.result;
|
|
120
|
+
}
|
|
121
|
+
function isDataEnvelope(value) {
|
|
122
|
+
return Object.hasOwn(value, "data") && Object.keys(value).every((key) => envelopeKeys.has(key));
|
|
123
|
+
}
|
|
124
|
+
function getSingletonArrayPayload(value) {
|
|
125
|
+
const arrayEntries = Object.entries(value).filter(
|
|
126
|
+
([key, entry]) => !envelopeKeys.has(key) && Array.isArray(entry)
|
|
127
|
+
);
|
|
128
|
+
return arrayEntries.length === 1 ? arrayEntries[0]?.[1] : void 0;
|
|
129
|
+
}
|
|
130
|
+
function isRecord(value) {
|
|
131
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// src/params.ts
|
|
135
|
+
function normalisePath(path) {
|
|
136
|
+
if (/^https?:\/\//i.test(path)) {
|
|
137
|
+
return path;
|
|
138
|
+
}
|
|
139
|
+
return path.startsWith("/") ? path : `/${path}`;
|
|
140
|
+
}
|
|
141
|
+
function mergeParams(params, fields) {
|
|
142
|
+
const merged = { ...params ?? {} };
|
|
143
|
+
delete merged.fields;
|
|
144
|
+
if (fields?.length) {
|
|
145
|
+
merged["fields[]"] = [...fields];
|
|
146
|
+
}
|
|
147
|
+
return merged;
|
|
148
|
+
}
|
|
149
|
+
function appendQueryParams(url, params) {
|
|
150
|
+
if (!params) {
|
|
151
|
+
return url;
|
|
152
|
+
}
|
|
153
|
+
for (const [key, value] of Object.entries(params)) {
|
|
154
|
+
appendQueryParam(url, key, value);
|
|
155
|
+
}
|
|
156
|
+
return url;
|
|
157
|
+
}
|
|
158
|
+
function appendQueryParam(url, key, value) {
|
|
159
|
+
if (value === null || value === void 0) {
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
if (Array.isArray(value)) {
|
|
163
|
+
const arrayKey = key.endsWith("[]") ? key : `${key}[]`;
|
|
164
|
+
for (const item of value) {
|
|
165
|
+
url.searchParams.append(arrayKey, String(item));
|
|
166
|
+
}
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
url.searchParams.append(
|
|
170
|
+
key,
|
|
171
|
+
value instanceof Date ? value.toISOString() : String(value)
|
|
172
|
+
);
|
|
173
|
+
}
|
|
174
|
+
function toPage(envelope) {
|
|
175
|
+
const source = extractPageEnvelopeSource(envelope);
|
|
176
|
+
const sourceMeta = toPaginationMeta(source.meta);
|
|
177
|
+
const rootMeta = toPaginationMeta(envelope.meta);
|
|
178
|
+
const meta = {
|
|
179
|
+
limit: Number(
|
|
180
|
+
source.limit ?? sourceMeta.limit ?? envelope.limit ?? rootMeta.limit ?? 0
|
|
181
|
+
),
|
|
182
|
+
page: Number(
|
|
183
|
+
source.page ?? sourceMeta.page ?? envelope.page ?? rootMeta.page ?? 1
|
|
184
|
+
),
|
|
185
|
+
total: Number(
|
|
186
|
+
source.total ?? sourceMeta.total ?? envelope.total ?? rootMeta.total ?? 0
|
|
187
|
+
)
|
|
188
|
+
};
|
|
189
|
+
return {
|
|
190
|
+
additionalFields: source.additionalFields ?? envelope.additionalFields,
|
|
191
|
+
aggregations: source.aggregations ?? envelope.aggregations,
|
|
192
|
+
data: extractPageData(source),
|
|
193
|
+
...meta,
|
|
194
|
+
meta
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
function toPaginationMeta(value) {
|
|
198
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// src/http.ts
|
|
202
|
+
var DEFAULT_BASE_URL = "https://api.linxio.com/api";
|
|
203
|
+
var DEFAULT_TIMEOUT_MS = 3e4;
|
|
204
|
+
var IDEMPOTENT_METHODS = /* @__PURE__ */ new Set(["GET", "HEAD", "OPTIONS"]);
|
|
205
|
+
var HttpClient = class {
|
|
206
|
+
/** Normalized REST API base URL without a trailing slash. */
|
|
207
|
+
baseUrl;
|
|
208
|
+
fetcher;
|
|
209
|
+
getRefreshToken;
|
|
210
|
+
getToken;
|
|
211
|
+
onSession;
|
|
212
|
+
retry;
|
|
213
|
+
timeoutMs;
|
|
214
|
+
refreshInFlight;
|
|
215
|
+
constructor(config = {}) {
|
|
216
|
+
this.baseUrl = trimTrailingSlash(config.baseUrl ?? DEFAULT_BASE_URL);
|
|
217
|
+
this.fetcher = config.fetch ?? getGlobalFetch();
|
|
218
|
+
this.getToken = config.getToken ?? (() => void 0);
|
|
219
|
+
this.getRefreshToken = config.getRefreshToken ?? (() => void 0);
|
|
220
|
+
this.onSession = config.onSession;
|
|
221
|
+
this.timeoutMs = config.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
222
|
+
this.retry = {
|
|
223
|
+
delayMs: config.retry?.delayMs ?? 1e3,
|
|
224
|
+
maxDelayMs: config.retry?.maxDelayMs ?? 8e3,
|
|
225
|
+
retries: config.retry?.retries ?? 3,
|
|
226
|
+
retryUnsafeMethods: config.retry?.retryUnsafeMethods ?? false
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
/** Send a GET request. */
|
|
230
|
+
get(path, options = {}) {
|
|
231
|
+
return this.request("GET", path, options);
|
|
232
|
+
}
|
|
233
|
+
/** Send a POST request. */
|
|
234
|
+
post(path, body, options = {}) {
|
|
235
|
+
return this.request("POST", path, { ...options, body });
|
|
236
|
+
}
|
|
237
|
+
/** Send a PATCH request. */
|
|
238
|
+
patch(path, body, options = {}) {
|
|
239
|
+
return this.request("PATCH", path, { ...options, body });
|
|
240
|
+
}
|
|
241
|
+
/** Send a PUT request. */
|
|
242
|
+
put(path, body, options = {}) {
|
|
243
|
+
return this.request("PUT", path, { ...options, body });
|
|
244
|
+
}
|
|
245
|
+
/** Send a DELETE request. */
|
|
246
|
+
delete(path, options = {}) {
|
|
247
|
+
return this.request("DELETE", path, options);
|
|
248
|
+
}
|
|
249
|
+
/** Send a request with an arbitrary HTTP method. */
|
|
250
|
+
async request(method, path, options = {}) {
|
|
251
|
+
return this.requestWithRefresh(method, path, options, false);
|
|
252
|
+
}
|
|
253
|
+
/** Build the final request URL, including query parameters. */
|
|
254
|
+
buildUrl(path, params) {
|
|
255
|
+
const normalisedPath = normalisePath(path);
|
|
256
|
+
const url = /^https?:\/\//i.test(normalisedPath) ? new URL(normalisedPath) : new URL(`${this.baseUrl}${normalisedPath}`);
|
|
257
|
+
return appendQueryParams(url, params);
|
|
258
|
+
}
|
|
259
|
+
async requestWithRefresh(method, path, options, hasRefreshed) {
|
|
260
|
+
const response = await this.sendWithRetries(method, path, options);
|
|
261
|
+
if (response.status === 401 && !hasRefreshed && !options.skipAuth && !options.skipAuthRefresh && this.getRefreshToken() && !isRefreshOrLoginPath(path)) {
|
|
262
|
+
await this.refreshSession();
|
|
263
|
+
return this.requestWithRefresh(
|
|
264
|
+
method,
|
|
265
|
+
path,
|
|
266
|
+
options,
|
|
267
|
+
true
|
|
268
|
+
);
|
|
269
|
+
}
|
|
270
|
+
return this.parseResponse(
|
|
271
|
+
response,
|
|
272
|
+
method,
|
|
273
|
+
path,
|
|
274
|
+
options.responseType
|
|
275
|
+
);
|
|
276
|
+
}
|
|
277
|
+
async refreshSession() {
|
|
278
|
+
if (this.refreshInFlight) {
|
|
279
|
+
return this.refreshInFlight;
|
|
280
|
+
}
|
|
281
|
+
const refreshToken = this.getRefreshToken();
|
|
282
|
+
if (!refreshToken) {
|
|
283
|
+
return;
|
|
284
|
+
}
|
|
285
|
+
this.refreshInFlight = (async () => {
|
|
286
|
+
const response = await this.sendOnce("POST", "/token/refresh", {
|
|
287
|
+
body: { refreshToken },
|
|
288
|
+
skipAuthRefresh: true
|
|
289
|
+
});
|
|
290
|
+
const parsed = await this.parseResponse(
|
|
291
|
+
response,
|
|
292
|
+
"POST",
|
|
293
|
+
"/token/refresh",
|
|
294
|
+
"json"
|
|
295
|
+
);
|
|
296
|
+
if (!parsed.token) {
|
|
297
|
+
throw new LinxioApiError(
|
|
298
|
+
"Linxio token refresh did not return a token.",
|
|
299
|
+
{
|
|
300
|
+
body: parsed,
|
|
301
|
+
method: "POST",
|
|
302
|
+
path: "/api/token/refresh",
|
|
303
|
+
status: response.status,
|
|
304
|
+
statusText: response.statusText
|
|
305
|
+
}
|
|
306
|
+
);
|
|
307
|
+
}
|
|
308
|
+
this.onSession?.({
|
|
309
|
+
expireAt: parsed.expireAt,
|
|
310
|
+
refreshToken: parsed.refreshToken ?? refreshToken,
|
|
311
|
+
token: parsed.token
|
|
312
|
+
});
|
|
313
|
+
})();
|
|
314
|
+
try {
|
|
315
|
+
await this.refreshInFlight;
|
|
316
|
+
} finally {
|
|
317
|
+
this.refreshInFlight = void 0;
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
async sendWithRetries(method, path, options) {
|
|
321
|
+
const shouldRetry = this.shouldRetryMethod(method);
|
|
322
|
+
const maxAttempts = shouldRetry ? this.retry.retries + 1 : 1;
|
|
323
|
+
let lastNetworkError;
|
|
324
|
+
for (let attempt = 0; attempt < maxAttempts; attempt += 1) {
|
|
325
|
+
try {
|
|
326
|
+
const response = await this.sendOnce(method, path, options);
|
|
327
|
+
if (attempt < maxAttempts - 1 && shouldRetry && isRetriableStatus(response.status)) {
|
|
328
|
+
await sleep(this.delayForAttempt(attempt), options.signal);
|
|
329
|
+
continue;
|
|
330
|
+
}
|
|
331
|
+
return response;
|
|
332
|
+
} catch (error) {
|
|
333
|
+
lastNetworkError = error;
|
|
334
|
+
if (error instanceof LinxioTimeoutError) {
|
|
335
|
+
throw error;
|
|
336
|
+
}
|
|
337
|
+
if (attempt >= maxAttempts - 1 || !shouldRetry) {
|
|
338
|
+
break;
|
|
339
|
+
}
|
|
340
|
+
await sleep(this.delayForAttempt(attempt), options.signal);
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
throw new LinxioNetworkError(
|
|
344
|
+
"Linxio request failed before a response was received.",
|
|
345
|
+
{
|
|
346
|
+
cause: lastNetworkError,
|
|
347
|
+
method,
|
|
348
|
+
path: this.pathForError(path)
|
|
349
|
+
}
|
|
350
|
+
);
|
|
351
|
+
}
|
|
352
|
+
async sendOnce(method, path, options) {
|
|
353
|
+
const timeoutMs = options.timeoutMs ?? this.timeoutMs;
|
|
354
|
+
const timeoutController = new AbortController();
|
|
355
|
+
const timeout = setTimeout(() => timeoutController.abort(), timeoutMs);
|
|
356
|
+
const signal = combineSignals(options.signal, timeoutController.signal);
|
|
357
|
+
try {
|
|
358
|
+
return await this.fetcher(this.buildUrl(path, options.params), {
|
|
359
|
+
body: prepareBody(method, options.body),
|
|
360
|
+
headers: this.prepareHeaders(options),
|
|
361
|
+
method,
|
|
362
|
+
signal
|
|
363
|
+
});
|
|
364
|
+
} catch (error) {
|
|
365
|
+
if (timeoutController.signal.aborted) {
|
|
366
|
+
throw new LinxioTimeoutError(
|
|
367
|
+
`Linxio request timed out after ${timeoutMs}ms.`,
|
|
368
|
+
{
|
|
369
|
+
cause: error,
|
|
370
|
+
method,
|
|
371
|
+
path: this.pathForError(path)
|
|
372
|
+
}
|
|
373
|
+
);
|
|
374
|
+
}
|
|
375
|
+
throw error;
|
|
376
|
+
} finally {
|
|
377
|
+
clearTimeout(timeout);
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
prepareHeaders(options) {
|
|
381
|
+
const headers = new Headers(options.headers);
|
|
382
|
+
if (!options.skipAuth) {
|
|
383
|
+
const token = this.getToken();
|
|
384
|
+
if (token) {
|
|
385
|
+
headers.set("Authorization", `Bearer ${token}`);
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
if (options.idempotencyKey) {
|
|
389
|
+
headers.set("Idempotency-Key", options.idempotencyKey);
|
|
390
|
+
}
|
|
391
|
+
if (options.body !== void 0 && shouldUseJsonBody(options.body)) {
|
|
392
|
+
headers.set("Content-Type", "application/json");
|
|
393
|
+
}
|
|
394
|
+
if (!headers.has("Accept")) {
|
|
395
|
+
headers.set("Accept", "application/json");
|
|
396
|
+
}
|
|
397
|
+
return headers;
|
|
398
|
+
}
|
|
399
|
+
async parseResponse(response, method, path, responseType = "json") {
|
|
400
|
+
if (response.status === 204) {
|
|
401
|
+
return void 0;
|
|
402
|
+
}
|
|
403
|
+
if (!response.ok) {
|
|
404
|
+
const body = await parseErrorBody(response);
|
|
405
|
+
throw new LinxioApiError(errorMessage(response, body), {
|
|
406
|
+
body,
|
|
407
|
+
headers: response.headers,
|
|
408
|
+
method,
|
|
409
|
+
path: this.pathForError(path),
|
|
410
|
+
requestId: response.headers.get("X-Request-Id") ?? void 0,
|
|
411
|
+
status: response.status,
|
|
412
|
+
statusText: response.statusText
|
|
413
|
+
});
|
|
414
|
+
}
|
|
415
|
+
if (responseType === "raw") {
|
|
416
|
+
return response;
|
|
417
|
+
}
|
|
418
|
+
if (responseType === "text") {
|
|
419
|
+
return await response.text();
|
|
420
|
+
}
|
|
421
|
+
if (responseType === "blob") {
|
|
422
|
+
return await response.blob();
|
|
423
|
+
}
|
|
424
|
+
if (responseType === "arrayBuffer") {
|
|
425
|
+
return await response.arrayBuffer();
|
|
426
|
+
}
|
|
427
|
+
const text = await response.text();
|
|
428
|
+
if (!text) {
|
|
429
|
+
return void 0;
|
|
430
|
+
}
|
|
431
|
+
return JSON.parse(text);
|
|
432
|
+
}
|
|
433
|
+
shouldRetryMethod(method) {
|
|
434
|
+
return this.retry.retryUnsafeMethods || IDEMPOTENT_METHODS.has(method);
|
|
435
|
+
}
|
|
436
|
+
delayForAttempt(attempt) {
|
|
437
|
+
if (this.retry.delayMs === 0) {
|
|
438
|
+
return 0;
|
|
439
|
+
}
|
|
440
|
+
return Math.min(
|
|
441
|
+
this.retry.delayMs * 2 ** attempt,
|
|
442
|
+
this.retry.maxDelayMs
|
|
443
|
+
);
|
|
444
|
+
}
|
|
445
|
+
pathForError(path) {
|
|
446
|
+
const url = this.buildUrl(path);
|
|
447
|
+
return `${url.pathname}${url.search}`;
|
|
448
|
+
}
|
|
449
|
+
};
|
|
450
|
+
function trimTrailingSlash(value) {
|
|
451
|
+
return value.replace(/\/+$/, "");
|
|
452
|
+
}
|
|
453
|
+
function getGlobalFetch() {
|
|
454
|
+
if (typeof globalThis.fetch !== "function") {
|
|
455
|
+
throw new LinxioConfigurationError(
|
|
456
|
+
"No fetch implementation is available. Pass `fetch` to createClient() or run on Node.js 20+."
|
|
457
|
+
);
|
|
458
|
+
}
|
|
459
|
+
return globalThis.fetch.bind(globalThis);
|
|
460
|
+
}
|
|
461
|
+
function isRefreshOrLoginPath(path) {
|
|
462
|
+
return path === "/login" || path === "/token/refresh";
|
|
463
|
+
}
|
|
464
|
+
function isRetriableStatus(status) {
|
|
465
|
+
return status === 408 || status === 425 || status === 429 || status >= 500;
|
|
466
|
+
}
|
|
467
|
+
function prepareBody(method, body) {
|
|
468
|
+
if (method === "GET" || method === "HEAD" || body === void 0) {
|
|
469
|
+
return void 0;
|
|
470
|
+
}
|
|
471
|
+
if (!shouldUseJsonBody(body)) {
|
|
472
|
+
return body;
|
|
473
|
+
}
|
|
474
|
+
return JSON.stringify(body);
|
|
475
|
+
}
|
|
476
|
+
function shouldUseJsonBody(body) {
|
|
477
|
+
return !(typeof body === "string" || body instanceof ArrayBuffer || body instanceof Blob || body instanceof FormData || body instanceof URLSearchParams);
|
|
478
|
+
}
|
|
479
|
+
async function parseErrorBody(response) {
|
|
480
|
+
const text = await response.text();
|
|
481
|
+
if (!text) {
|
|
482
|
+
return void 0;
|
|
483
|
+
}
|
|
484
|
+
try {
|
|
485
|
+
return JSON.parse(text);
|
|
486
|
+
} catch {
|
|
487
|
+
return text;
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
function errorMessage(response, body) {
|
|
491
|
+
if (typeof body === "object" && body !== null) {
|
|
492
|
+
const record = body;
|
|
493
|
+
const message = record.message ?? record.error;
|
|
494
|
+
if (typeof message === "string" && message.trim()) {
|
|
495
|
+
return message;
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
return `Linxio API request failed with ${response.status} ${response.statusText}`.trim();
|
|
499
|
+
}
|
|
500
|
+
function combineSignals(originalSignal, timeoutSignal) {
|
|
501
|
+
if (!originalSignal) {
|
|
502
|
+
return timeoutSignal;
|
|
503
|
+
}
|
|
504
|
+
if (originalSignal.aborted) {
|
|
505
|
+
return originalSignal;
|
|
506
|
+
}
|
|
507
|
+
const controller = new AbortController();
|
|
508
|
+
const abort = () => controller.abort();
|
|
509
|
+
originalSignal.addEventListener("abort", abort, { once: true });
|
|
510
|
+
timeoutSignal.addEventListener("abort", abort, { once: true });
|
|
511
|
+
return controller.signal;
|
|
512
|
+
}
|
|
513
|
+
function sleep(ms, signal) {
|
|
514
|
+
if (ms === 0) {
|
|
515
|
+
return Promise.resolve();
|
|
516
|
+
}
|
|
517
|
+
return new Promise((resolve, reject) => {
|
|
518
|
+
const timeout = setTimeout(resolve, ms);
|
|
519
|
+
signal?.addEventListener(
|
|
520
|
+
"abort",
|
|
521
|
+
() => {
|
|
522
|
+
clearTimeout(timeout);
|
|
523
|
+
reject(new LinxioNetworkError("Linxio request was aborted."));
|
|
524
|
+
},
|
|
525
|
+
{ once: true }
|
|
526
|
+
);
|
|
527
|
+
});
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
// src/realtime.ts
|
|
531
|
+
import { io } from "socket.io-client";
|
|
532
|
+
var DEFAULT_REALTIME_BASE_URL = "https://track.linxio.com";
|
|
533
|
+
var RealtimeClient = class {
|
|
534
|
+
baseUrl;
|
|
535
|
+
getToken;
|
|
536
|
+
path;
|
|
537
|
+
reconnectionAttempts;
|
|
538
|
+
sockets = /* @__PURE__ */ new Map();
|
|
539
|
+
constructor(options = {}) {
|
|
540
|
+
this.baseUrl = (options.baseUrl ?? DEFAULT_REALTIME_BASE_URL).replace(
|
|
541
|
+
/\/+$/,
|
|
542
|
+
""
|
|
543
|
+
);
|
|
544
|
+
this.getToken = options.getToken ?? (() => void 0);
|
|
545
|
+
this.path = options.path ?? "/socket.io";
|
|
546
|
+
this.reconnectionAttempts = options.reconnectionAttempts ?? 10;
|
|
547
|
+
}
|
|
548
|
+
/** Connect to a Linxio realtime namespace and reuse existing sockets. */
|
|
549
|
+
connect(namespace, token = this.getToken()) {
|
|
550
|
+
const existing = this.sockets.get(namespace);
|
|
551
|
+
if (existing) {
|
|
552
|
+
return existing;
|
|
553
|
+
}
|
|
554
|
+
if (!token) {
|
|
555
|
+
throw new LinxioRealtimeError(
|
|
556
|
+
"A Linxio token is required before connecting to realtime sockets."
|
|
557
|
+
);
|
|
558
|
+
}
|
|
559
|
+
const socket = io(`${this.baseUrl}/${namespace}`, {
|
|
560
|
+
path: this.path,
|
|
561
|
+
query: { token },
|
|
562
|
+
reconnection: true,
|
|
563
|
+
reconnectionAttempts: this.reconnectionAttempts,
|
|
564
|
+
reconnectionDelay: 5e3,
|
|
565
|
+
reconnectionDelayMax: 1e4,
|
|
566
|
+
timeout: 2e4,
|
|
567
|
+
transports: ["websocket"]
|
|
568
|
+
});
|
|
569
|
+
socket.on("error", (error) => {
|
|
570
|
+
if (error === "AUTH_FAILED") {
|
|
571
|
+
socket.disconnect();
|
|
572
|
+
}
|
|
573
|
+
});
|
|
574
|
+
this.sockets.set(namespace, socket);
|
|
575
|
+
return socket;
|
|
576
|
+
}
|
|
577
|
+
/** Subscribe the current realtime socket to a set of vehicle IDs. */
|
|
578
|
+
subscribe(vehicleIds, namespace = "coordinates") {
|
|
579
|
+
const socket = this.connect(namespace);
|
|
580
|
+
return new Promise((resolve) => {
|
|
581
|
+
socket.emit(
|
|
582
|
+
"subscribe",
|
|
583
|
+
{ vehicleIds: vehicleIds.map(Number) },
|
|
584
|
+
(ack) => resolve(ack)
|
|
585
|
+
);
|
|
586
|
+
});
|
|
587
|
+
}
|
|
588
|
+
/**
|
|
589
|
+
* Subscribe to live vehicle coordinates.
|
|
590
|
+
*
|
|
591
|
+
* The returned function removes event handlers. It does not disconnect the
|
|
592
|
+
* socket, allowing other subscriptions to keep running.
|
|
593
|
+
*/
|
|
594
|
+
onPosition(vehicleIds, handler) {
|
|
595
|
+
const socket = this.connect("coordinates");
|
|
596
|
+
const subscribe = () => {
|
|
597
|
+
socket.emit("subscribe", { vehicleIds: vehicleIds.map(Number) });
|
|
598
|
+
};
|
|
599
|
+
socket.on("connect", subscribe);
|
|
600
|
+
socket.on("reconnect", subscribe);
|
|
601
|
+
socket.on("coordinates", handler);
|
|
602
|
+
if (socket.connected) {
|
|
603
|
+
subscribe();
|
|
604
|
+
}
|
|
605
|
+
return () => {
|
|
606
|
+
socket.off("connect", subscribe);
|
|
607
|
+
socket.off("reconnect", subscribe);
|
|
608
|
+
socket.off("coordinates", handler);
|
|
609
|
+
};
|
|
610
|
+
}
|
|
611
|
+
/** Listen for Linxio notification messages. */
|
|
612
|
+
onNotification(handler) {
|
|
613
|
+
const socket = this.connect("notifications");
|
|
614
|
+
socket.on("notification", handler);
|
|
615
|
+
socket.on("notifications", handler);
|
|
616
|
+
return () => {
|
|
617
|
+
socket.off("notification", handler);
|
|
618
|
+
socket.off("notifications", handler);
|
|
619
|
+
};
|
|
620
|
+
}
|
|
621
|
+
/** Listen for a custom notification event type emitted by Linxio. */
|
|
622
|
+
onNotificationType(type, handler) {
|
|
623
|
+
const socket = this.connect("notifications");
|
|
624
|
+
socket.on(type, handler);
|
|
625
|
+
return () => socket.off(type, handler);
|
|
626
|
+
}
|
|
627
|
+
/** Disconnect one namespace or every active realtime socket. */
|
|
628
|
+
disconnect(namespace) {
|
|
629
|
+
if (namespace) {
|
|
630
|
+
this.sockets.get(namespace)?.disconnect();
|
|
631
|
+
this.sockets.delete(namespace);
|
|
632
|
+
return;
|
|
633
|
+
}
|
|
634
|
+
for (const socket of this.sockets.values()) {
|
|
635
|
+
socket.disconnect();
|
|
636
|
+
}
|
|
637
|
+
this.sockets.clear();
|
|
638
|
+
}
|
|
639
|
+
};
|
|
640
|
+
|
|
641
|
+
// src/result.ts
|
|
642
|
+
function ok(data) {
|
|
643
|
+
return { data, error: null };
|
|
644
|
+
}
|
|
645
|
+
function fail(error) {
|
|
646
|
+
return { data: null, error: toLinxioError(error) };
|
|
647
|
+
}
|
|
648
|
+
async function toResult(operation) {
|
|
649
|
+
try {
|
|
650
|
+
return ok(unwrapLinxioServiceData(await operation()));
|
|
651
|
+
} catch (error) {
|
|
652
|
+
return fail(error);
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
function pageOk(page) {
|
|
656
|
+
return { ...page, error: null };
|
|
657
|
+
}
|
|
658
|
+
function pageFail(error) {
|
|
659
|
+
return {
|
|
660
|
+
data: null,
|
|
661
|
+
error: toLinxioError(error),
|
|
662
|
+
limit: null,
|
|
663
|
+
meta: null,
|
|
664
|
+
page: null,
|
|
665
|
+
total: null
|
|
666
|
+
};
|
|
667
|
+
}
|
|
668
|
+
function isLinxioFailure(result) {
|
|
669
|
+
return result.error !== null;
|
|
670
|
+
}
|
|
671
|
+
function unwrapLinxioResult(result) {
|
|
672
|
+
if (result.error) {
|
|
673
|
+
throw result.error;
|
|
674
|
+
}
|
|
675
|
+
return result.data;
|
|
676
|
+
}
|
|
677
|
+
function unwrapLinxioPageResult(result) {
|
|
678
|
+
if (result.error) {
|
|
679
|
+
throw result.error;
|
|
680
|
+
}
|
|
681
|
+
return result;
|
|
682
|
+
}
|
|
683
|
+
function toLinxioError(error) {
|
|
684
|
+
if (error instanceof LinxioError) {
|
|
685
|
+
return error;
|
|
686
|
+
}
|
|
687
|
+
if (error instanceof Error) {
|
|
688
|
+
return new LinxioError(error.message, { cause: error });
|
|
689
|
+
}
|
|
690
|
+
return new LinxioError("Linxio SDK operation failed.", { cause: error });
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
// src/services/base.service.ts
|
|
694
|
+
var BaseService = class {
|
|
695
|
+
constructor(http) {
|
|
696
|
+
this.http = http;
|
|
697
|
+
}
|
|
698
|
+
http;
|
|
699
|
+
async getPage(path, params = {}, options = {}) {
|
|
700
|
+
try {
|
|
701
|
+
const response = await this.http.get(
|
|
702
|
+
path,
|
|
703
|
+
{
|
|
704
|
+
...options,
|
|
705
|
+
params: this.listParams(params)
|
|
706
|
+
}
|
|
707
|
+
);
|
|
708
|
+
return pageOk(toPage(response));
|
|
709
|
+
} catch (error) {
|
|
710
|
+
return pageFail(error);
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
result(operation) {
|
|
714
|
+
return toResult(operation);
|
|
715
|
+
}
|
|
716
|
+
listParams(params = {}) {
|
|
717
|
+
const { fields, ...rest } = params;
|
|
718
|
+
return mergeParams(rest, fields);
|
|
719
|
+
}
|
|
720
|
+
};
|
|
721
|
+
|
|
722
|
+
// src/services/auth.service.ts
|
|
723
|
+
var AuthService = class extends BaseService {
|
|
724
|
+
constructor(http, setSession) {
|
|
725
|
+
super(http);
|
|
726
|
+
this.setSession = setSession;
|
|
727
|
+
}
|
|
728
|
+
setSession;
|
|
729
|
+
/**
|
|
730
|
+
* Log in with Linxio credentials.
|
|
731
|
+
*
|
|
732
|
+
* The returned JWT and refresh token are stored in the parent client so
|
|
733
|
+
* subsequent requests are authenticated automatically.
|
|
734
|
+
*/
|
|
735
|
+
async login(request) {
|
|
736
|
+
const result = await this.result(
|
|
737
|
+
() => this.http.post("/login", request, {
|
|
738
|
+
skipAuth: true,
|
|
739
|
+
skipAuthRefresh: true
|
|
740
|
+
})
|
|
741
|
+
);
|
|
742
|
+
if (!result.error) {
|
|
743
|
+
this.applySession(result.data);
|
|
744
|
+
}
|
|
745
|
+
return result;
|
|
746
|
+
}
|
|
747
|
+
/** Verify a one-time password when Linxio requires OTP for the account. */
|
|
748
|
+
async verifyOtp(request) {
|
|
749
|
+
const result = await this.result(
|
|
750
|
+
() => this.http.post("/login/otp", request, {
|
|
751
|
+
skipAuth: true,
|
|
752
|
+
skipAuthRefresh: true
|
|
753
|
+
})
|
|
754
|
+
);
|
|
755
|
+
if (!result.error) {
|
|
756
|
+
this.applySession(result.data);
|
|
757
|
+
}
|
|
758
|
+
return result;
|
|
759
|
+
}
|
|
760
|
+
/** Refresh a JWT manually and update the client session. */
|
|
761
|
+
async refresh(refreshToken) {
|
|
762
|
+
const result = await this.result(
|
|
763
|
+
() => this.http.post(
|
|
764
|
+
"/token/refresh",
|
|
765
|
+
{ refreshToken },
|
|
766
|
+
{ skipAuthRefresh: true }
|
|
767
|
+
)
|
|
768
|
+
);
|
|
769
|
+
if (result.error) {
|
|
770
|
+
return result;
|
|
771
|
+
}
|
|
772
|
+
const session = {
|
|
773
|
+
expireAt: result.data.expireAt,
|
|
774
|
+
refreshToken: result.data.refreshToken ?? refreshToken,
|
|
775
|
+
token: result.data.token
|
|
776
|
+
};
|
|
777
|
+
this.setSession(session);
|
|
778
|
+
return { data: session, error: null };
|
|
779
|
+
}
|
|
780
|
+
/** Fetch the current authenticated Linxio user. */
|
|
781
|
+
me(fields) {
|
|
782
|
+
return this.result(
|
|
783
|
+
() => this.http.get("/me", {
|
|
784
|
+
params: fields?.length ? { "fields[]": [...fields] } : void 0
|
|
785
|
+
})
|
|
786
|
+
);
|
|
787
|
+
}
|
|
788
|
+
/** Log out the current Linxio session server-side. */
|
|
789
|
+
logout() {
|
|
790
|
+
return this.result(() => this.http.post("/logout", {}));
|
|
791
|
+
}
|
|
792
|
+
applySession(response) {
|
|
793
|
+
this.setSession({
|
|
794
|
+
expireAt: response.expireAt,
|
|
795
|
+
refreshToken: response.refreshToken,
|
|
796
|
+
token: response.token
|
|
797
|
+
});
|
|
798
|
+
}
|
|
799
|
+
};
|
|
800
|
+
|
|
801
|
+
// src/services/cameras.service.ts
|
|
802
|
+
var CamerasService = class extends BaseService {
|
|
803
|
+
/** List camera events. */
|
|
804
|
+
events(params = {}) {
|
|
805
|
+
return this.getPage("/devices/cameras/events", params);
|
|
806
|
+
}
|
|
807
|
+
/** List camera event types. */
|
|
808
|
+
eventTypes() {
|
|
809
|
+
return this.result(
|
|
810
|
+
() => this.http.get("/devices/cameras/events/types")
|
|
811
|
+
);
|
|
812
|
+
}
|
|
813
|
+
};
|
|
814
|
+
|
|
815
|
+
// src/pagination.ts
|
|
816
|
+
async function collectPages(loadPage, params = {}) {
|
|
817
|
+
try {
|
|
818
|
+
const data = [];
|
|
819
|
+
for await (const item of streamPages(loadPage, params)) {
|
|
820
|
+
data.push(item);
|
|
821
|
+
}
|
|
822
|
+
return ok(data);
|
|
823
|
+
} catch (error) {
|
|
824
|
+
return fail(error);
|
|
825
|
+
}
|
|
826
|
+
}
|
|
827
|
+
async function* streamPages(loadPage, params = {}) {
|
|
828
|
+
let page = Number(params.page ?? 1);
|
|
829
|
+
const limit = Number(params.limit ?? 100);
|
|
830
|
+
while (true) {
|
|
831
|
+
const result = unwrapLinxioPageResult(
|
|
832
|
+
await loadPage({ ...params, limit, page })
|
|
833
|
+
);
|
|
834
|
+
for (const item of result.data) {
|
|
835
|
+
yield item;
|
|
836
|
+
}
|
|
837
|
+
const seen = result.meta.page * result.meta.limit;
|
|
838
|
+
if (result.data.length === 0 || seen >= result.meta.total) {
|
|
839
|
+
return;
|
|
840
|
+
}
|
|
841
|
+
page += 1;
|
|
842
|
+
}
|
|
843
|
+
}
|
|
844
|
+
|
|
845
|
+
// src/services/clients.service.ts
|
|
846
|
+
var ClientsService = class extends BaseService {
|
|
847
|
+
/** List client accounts from the dashboard-derived endpoint. */
|
|
848
|
+
list(params = {}) {
|
|
849
|
+
return this.getPage("/clients/json", params);
|
|
850
|
+
}
|
|
851
|
+
/** Fetch one client account by ID. */
|
|
852
|
+
get(clientId) {
|
|
853
|
+
return this.result(() => this.http.get(`/clients/${clientId}`));
|
|
854
|
+
}
|
|
855
|
+
/** List users for a client account. */
|
|
856
|
+
listUsers(clientId, params = {}) {
|
|
857
|
+
return this.getPage(`/clients/${clientId}/users`, params);
|
|
858
|
+
}
|
|
859
|
+
/** Load every user page for a client account into a single result. */
|
|
860
|
+
iterateUsers(clientId, params = {}) {
|
|
861
|
+
return collectPages(
|
|
862
|
+
(pageParams) => this.listUsers(clientId, pageParams),
|
|
863
|
+
params
|
|
864
|
+
);
|
|
865
|
+
}
|
|
866
|
+
/** Stream users for a client account without loading every user at once. */
|
|
867
|
+
streamUsers(clientId, params = {}) {
|
|
868
|
+
return streamPages(
|
|
869
|
+
(pageParams) => this.listUsers(clientId, pageParams),
|
|
870
|
+
params
|
|
871
|
+
);
|
|
872
|
+
}
|
|
873
|
+
/** Create a user within a client account. */
|
|
874
|
+
createUser(clientId, payload) {
|
|
875
|
+
return this.result(
|
|
876
|
+
() => this.http.post(`/clients/${clientId}/users`, payload)
|
|
877
|
+
);
|
|
878
|
+
}
|
|
879
|
+
/** Update a user within a client account. */
|
|
880
|
+
updateUser(clientId, userId, payload) {
|
|
881
|
+
return this.result(
|
|
882
|
+
() => this.http.post(`/clients/${clientId}/users/${userId}`, payload)
|
|
883
|
+
);
|
|
884
|
+
}
|
|
885
|
+
/** Fetch one user within a client account. */
|
|
886
|
+
getUser(clientId, userId) {
|
|
887
|
+
return this.result(
|
|
888
|
+
() => this.http.get(`/clients/${clientId}/users/${userId}`)
|
|
889
|
+
);
|
|
890
|
+
}
|
|
891
|
+
};
|
|
892
|
+
var ResellersService = class extends BaseService {
|
|
893
|
+
/** List reseller accounts. */
|
|
894
|
+
list() {
|
|
895
|
+
return this.result(() => this.http.get("/reseller"));
|
|
896
|
+
}
|
|
897
|
+
/** Fetch one reseller account by ID. */
|
|
898
|
+
get(resellerId) {
|
|
899
|
+
return this.result(() => this.http.get(`/reseller/${resellerId}`));
|
|
900
|
+
}
|
|
901
|
+
};
|
|
902
|
+
|
|
903
|
+
// src/services/devices.service.ts
|
|
904
|
+
var DevicesService = class extends BaseService {
|
|
905
|
+
/** List devices using Linxio's documented `/devices/json` endpoint. */
|
|
906
|
+
list(params = {}) {
|
|
907
|
+
return this.getPage("/devices/json", params);
|
|
908
|
+
}
|
|
909
|
+
/** Load every device page into a single result. */
|
|
910
|
+
iterate(params = {}) {
|
|
911
|
+
return collectPages((pageParams) => this.list(pageParams), params);
|
|
912
|
+
}
|
|
913
|
+
/** Stream every device page without loading the whole inventory at once. */
|
|
914
|
+
stream(params = {}) {
|
|
915
|
+
return streamPages((pageParams) => this.list(pageParams), params);
|
|
916
|
+
}
|
|
917
|
+
/** Fetch one device by internal Linxio device ID. */
|
|
918
|
+
get(deviceId) {
|
|
919
|
+
return this.result(() => this.http.get(`/devices/${deviceId}`));
|
|
920
|
+
}
|
|
921
|
+
/** Create a device. */
|
|
922
|
+
create(payload) {
|
|
923
|
+
return this.result(() => this.http.post("/devices", payload));
|
|
924
|
+
}
|
|
925
|
+
/** Update a device using Linxio's documented PATCH endpoint. */
|
|
926
|
+
update(deviceId, payload) {
|
|
927
|
+
return this.result(
|
|
928
|
+
() => this.http.patch(`/devices/${deviceId}`, payload)
|
|
929
|
+
);
|
|
930
|
+
}
|
|
931
|
+
/** Install a device into a vehicle. */
|
|
932
|
+
install(deviceId, payload) {
|
|
933
|
+
return this.result(
|
|
934
|
+
() => this.http.post(`/devices/${deviceId}/install`, payload)
|
|
935
|
+
);
|
|
936
|
+
}
|
|
937
|
+
/** Uninstall a device from its current vehicle. */
|
|
938
|
+
uninstall(deviceId, payload = {}) {
|
|
939
|
+
return this.result(
|
|
940
|
+
() => this.http.post(`/devices/${deviceId}/uninstall`, payload)
|
|
941
|
+
);
|
|
942
|
+
}
|
|
943
|
+
/** Soft-archive a device when the dashboard endpoint is available. */
|
|
944
|
+
archive(deviceId) {
|
|
945
|
+
return this.result(
|
|
946
|
+
() => this.http.patch(`/devices/${deviceId}/archive`, {})
|
|
947
|
+
);
|
|
948
|
+
}
|
|
949
|
+
/** Restore a previously archived device. */
|
|
950
|
+
restore(deviceId) {
|
|
951
|
+
return this.result(
|
|
952
|
+
() => this.http.patch(`/devices/${deviceId}/restore`, {})
|
|
953
|
+
);
|
|
954
|
+
}
|
|
955
|
+
/** Fetch recent coordinates for a device from the dashboard-derived endpoint. */
|
|
956
|
+
coordinates(deviceId, params = {}) {
|
|
957
|
+
return this.result(
|
|
958
|
+
() => this.http.get(`/devices/${deviceId}/coordinates`, { params })
|
|
959
|
+
);
|
|
960
|
+
}
|
|
961
|
+
/** List sensor history rows for a device. */
|
|
962
|
+
sensors(deviceId, params = {}) {
|
|
963
|
+
return this.getPage(`/devices/${deviceId}/sensors/history`, params);
|
|
964
|
+
}
|
|
965
|
+
/** Fetch device history entries from the dashboard-derived endpoint. */
|
|
966
|
+
history(deviceId) {
|
|
967
|
+
return this.result(() => this.http.get(`/devices/${deviceId}/history`));
|
|
968
|
+
}
|
|
969
|
+
/** List device vendors from the dashboard-derived endpoint. */
|
|
970
|
+
vendors() {
|
|
971
|
+
return this.result(() => this.http.get("/devices/vendors/"));
|
|
972
|
+
}
|
|
973
|
+
/** Look up a device installation by device IMEI or vehicle registration. */
|
|
974
|
+
installation(params = {}) {
|
|
975
|
+
return this.result(async () => {
|
|
976
|
+
const installation = await this.http.get(
|
|
977
|
+
"/devices/installation/",
|
|
978
|
+
{ params }
|
|
979
|
+
);
|
|
980
|
+
return isEmptyRecord(installation) ? null : installation;
|
|
981
|
+
});
|
|
982
|
+
}
|
|
983
|
+
/** Backwards-compatible alias for `installation()`. */
|
|
984
|
+
installations(params = {}) {
|
|
985
|
+
return this.installation(params);
|
|
986
|
+
}
|
|
987
|
+
/** List cameras attached to a device from the dashboard-derived endpoint. */
|
|
988
|
+
cameras(deviceId) {
|
|
989
|
+
return this.result(() => this.http.get(`/devices/${deviceId}/cameras`));
|
|
990
|
+
}
|
|
991
|
+
};
|
|
992
|
+
function isEmptyRecord(value) {
|
|
993
|
+
return typeof value === "object" && value !== null && !Array.isArray(value) && Object.keys(value).length === 0;
|
|
994
|
+
}
|
|
995
|
+
|
|
996
|
+
// src/services/drivers.service.ts
|
|
997
|
+
var DriversService = class extends BaseService {
|
|
998
|
+
/** List drivers, optionally via the documented client-users driver endpoint. */
|
|
999
|
+
list(params = {}) {
|
|
1000
|
+
const { clientId, ...rest } = params;
|
|
1001
|
+
if (clientId) {
|
|
1002
|
+
return this.getPage(`/clients/${clientId}/users`, {
|
|
1003
|
+
...rest,
|
|
1004
|
+
role: "driver"
|
|
1005
|
+
});
|
|
1006
|
+
}
|
|
1007
|
+
return this.getPage("/drivers", rest);
|
|
1008
|
+
}
|
|
1009
|
+
/** Load every driver page into a single result. */
|
|
1010
|
+
iterate(params = {}) {
|
|
1011
|
+
return collectPages((pageParams) => this.list(pageParams), params);
|
|
1012
|
+
}
|
|
1013
|
+
/** Stream every driver page without loading every driver at once. */
|
|
1014
|
+
stream(params = {}) {
|
|
1015
|
+
return streamPages((pageParams) => this.list(pageParams), params);
|
|
1016
|
+
}
|
|
1017
|
+
/** Assign a driver to a vehicle. */
|
|
1018
|
+
assignToVehicle(vehicleId, driverId) {
|
|
1019
|
+
return this.result(
|
|
1020
|
+
() => this.http.post(`/vehicle/${vehicleId}/set-driver/${driverId}`, {})
|
|
1021
|
+
);
|
|
1022
|
+
}
|
|
1023
|
+
/** Unassign a driver from a vehicle. */
|
|
1024
|
+
unassignFromVehicle(vehicleId, driverId) {
|
|
1025
|
+
return this.result(
|
|
1026
|
+
() => this.http.post(
|
|
1027
|
+
`/vehicle/${vehicleId}/unset-driver/${driverId}`,
|
|
1028
|
+
{}
|
|
1029
|
+
)
|
|
1030
|
+
);
|
|
1031
|
+
}
|
|
1032
|
+
};
|
|
1033
|
+
|
|
1034
|
+
// src/services/fuel.service.ts
|
|
1035
|
+
var FuelService = class extends BaseService {
|
|
1036
|
+
/** List fuel transaction records from the dashboard-derived endpoint. */
|
|
1037
|
+
records(params = {}) {
|
|
1038
|
+
return this.getPage("/fuel-cards/json", params);
|
|
1039
|
+
}
|
|
1040
|
+
/** Load every fuel transaction page into a single result. */
|
|
1041
|
+
iterateRecords(params = {}) {
|
|
1042
|
+
return collectPages((pageParams) => this.records(pageParams), params);
|
|
1043
|
+
}
|
|
1044
|
+
/** Stream fuel transaction records without loading every record at once. */
|
|
1045
|
+
streamRecords(params = {}) {
|
|
1046
|
+
return streamPages((pageParams) => this.records(pageParams), params);
|
|
1047
|
+
}
|
|
1048
|
+
/** Fetch fuel summary rows. */
|
|
1049
|
+
summary(params = {}) {
|
|
1050
|
+
return this.getPage("/fuel-summary-report", params);
|
|
1051
|
+
}
|
|
1052
|
+
/** Fetch fuel transaction records grouped or filtered by vehicle. */
|
|
1053
|
+
recordsByVehicle(params = {}) {
|
|
1054
|
+
return this.getPage("/fuel-cards-by-vehicle/json", params);
|
|
1055
|
+
}
|
|
1056
|
+
/** List fuel cards. */
|
|
1057
|
+
cards(params = {}) {
|
|
1058
|
+
return this.getPage("/fuel-cards/json", params);
|
|
1059
|
+
}
|
|
1060
|
+
/** List fuel types configured by Linxio. */
|
|
1061
|
+
fuelTypes() {
|
|
1062
|
+
return this.result(() => this.http.get("/fuel-types"));
|
|
1063
|
+
}
|
|
1064
|
+
/** Assign a fuel transaction to a vehicle. */
|
|
1065
|
+
assignTransaction(recordId, vehicleId) {
|
|
1066
|
+
return this.result(
|
|
1067
|
+
() => this.http.patch(`/fuel-cards/record/${recordId}`, { vehicleId })
|
|
1068
|
+
);
|
|
1069
|
+
}
|
|
1070
|
+
};
|
|
1071
|
+
|
|
1072
|
+
// src/services/geofences.service.ts
|
|
1073
|
+
var GeofencesService = class extends BaseService {
|
|
1074
|
+
/** List geofence objects. */
|
|
1075
|
+
list(params = {}) {
|
|
1076
|
+
return this.getPage("/areas", params);
|
|
1077
|
+
}
|
|
1078
|
+
/** Load every geofence page into a single result. */
|
|
1079
|
+
iterate(params = {}) {
|
|
1080
|
+
return collectPages((pageParams) => this.list(pageParams), params);
|
|
1081
|
+
}
|
|
1082
|
+
/** Stream every geofence page without loading every geofence at once. */
|
|
1083
|
+
stream(params = {}) {
|
|
1084
|
+
return streamPages((pageParams) => this.list(pageParams), params);
|
|
1085
|
+
}
|
|
1086
|
+
/** Fetch one geofence by Linxio area ID. */
|
|
1087
|
+
get(areaId) {
|
|
1088
|
+
return this.result(() => this.http.get(`/areas/${areaId}`));
|
|
1089
|
+
}
|
|
1090
|
+
/** Create a geofence object. */
|
|
1091
|
+
create(payload) {
|
|
1092
|
+
return this.result(() => this.http.post("/areas", payload));
|
|
1093
|
+
}
|
|
1094
|
+
/** Update a geofence object using the dashboard-derived endpoint. */
|
|
1095
|
+
update(areaId, payload) {
|
|
1096
|
+
return this.result(() => this.http.patch(`/areas/${areaId}`, payload));
|
|
1097
|
+
}
|
|
1098
|
+
/** Permanently delete a geofence object. Prefer `archive()` if you need reversibility. */
|
|
1099
|
+
delete(areaId) {
|
|
1100
|
+
return this.result(() => this.http.delete(`/areas/${areaId}`));
|
|
1101
|
+
}
|
|
1102
|
+
/** Soft-archive a geofence object when the dashboard endpoint is available. */
|
|
1103
|
+
archive(areaId) {
|
|
1104
|
+
return this.result(
|
|
1105
|
+
() => this.http.patch(`/areas/${areaId}/archive`, {})
|
|
1106
|
+
);
|
|
1107
|
+
}
|
|
1108
|
+
/** Restore a previously archived geofence object. */
|
|
1109
|
+
restore(areaId) {
|
|
1110
|
+
return this.result(
|
|
1111
|
+
() => this.http.patch(`/areas/${areaId}/restore`, {})
|
|
1112
|
+
);
|
|
1113
|
+
}
|
|
1114
|
+
/** List area groups from the dashboard-derived endpoint. */
|
|
1115
|
+
listGroups() {
|
|
1116
|
+
return this.result(() => this.http.get("/area-groups"));
|
|
1117
|
+
}
|
|
1118
|
+
/** Fetch one area group from the dashboard-derived endpoint. */
|
|
1119
|
+
getGroup(groupId) {
|
|
1120
|
+
return this.result(() => this.http.get(`/area-groups/${groupId}`));
|
|
1121
|
+
}
|
|
1122
|
+
/** Create an area group from the dashboard-derived endpoint. */
|
|
1123
|
+
createGroup(payload) {
|
|
1124
|
+
return this.result(() => this.http.post("/area-groups", payload));
|
|
1125
|
+
}
|
|
1126
|
+
/** Update an area group from the dashboard-derived endpoint. */
|
|
1127
|
+
updateGroup(groupId, payload) {
|
|
1128
|
+
return this.result(
|
|
1129
|
+
() => this.http.patch(`/area-groups/${groupId}`, payload)
|
|
1130
|
+
);
|
|
1131
|
+
}
|
|
1132
|
+
/** Delete an area group. Prefer archive/restore when reversibility matters. */
|
|
1133
|
+
deleteGroup(groupId) {
|
|
1134
|
+
return this.result(() => this.http.delete(`/area-groups/${groupId}`));
|
|
1135
|
+
}
|
|
1136
|
+
/** Soft-archive an area group from the dashboard-derived endpoint. */
|
|
1137
|
+
archiveGroup(groupId) {
|
|
1138
|
+
return this.result(
|
|
1139
|
+
() => this.http.patch(`/area-groups/${groupId}/archive`, {})
|
|
1140
|
+
);
|
|
1141
|
+
}
|
|
1142
|
+
/** Restore an archived area group from the dashboard-derived endpoint. */
|
|
1143
|
+
restoreGroup(groupId) {
|
|
1144
|
+
return this.result(
|
|
1145
|
+
() => this.http.patch(`/area-groups/${groupId}/restore`, {})
|
|
1146
|
+
);
|
|
1147
|
+
}
|
|
1148
|
+
};
|
|
1149
|
+
|
|
1150
|
+
// src/services/metadata.service.ts
|
|
1151
|
+
var MetadataService = class extends BaseService {
|
|
1152
|
+
/** Fetch country options as a map keyed by country code. */
|
|
1153
|
+
countries() {
|
|
1154
|
+
return this.result(() => this.http.get("/country/list"));
|
|
1155
|
+
}
|
|
1156
|
+
/** List user roles available to the authenticated Linxio account. */
|
|
1157
|
+
roles() {
|
|
1158
|
+
return this.result(() => this.http.get("/roles"));
|
|
1159
|
+
}
|
|
1160
|
+
/** List plan definitions visible to the authenticated Linxio account. */
|
|
1161
|
+
plans() {
|
|
1162
|
+
return this.result(() => this.http.get("/plans"));
|
|
1163
|
+
}
|
|
1164
|
+
/** List timezone options used by Linxio tenant and user settings. */
|
|
1165
|
+
timezones() {
|
|
1166
|
+
return this.result(() => this.http.get("/timezones"));
|
|
1167
|
+
}
|
|
1168
|
+
/** List dashboard theme definitions. */
|
|
1169
|
+
themes() {
|
|
1170
|
+
return this.result(() => this.http.get("/themes"));
|
|
1171
|
+
}
|
|
1172
|
+
/** Fetch the current user's active dashboard theme. */
|
|
1173
|
+
myTheme() {
|
|
1174
|
+
return this.result(() => this.http.get("/themes/my"));
|
|
1175
|
+
}
|
|
1176
|
+
/** Fetch current-plan permission keys. */
|
|
1177
|
+
currentPlan() {
|
|
1178
|
+
return this.result(() => this.http.get("/permissions/current-plan"));
|
|
1179
|
+
}
|
|
1180
|
+
/** Fetch the hosted-domain settings for the current platform. */
|
|
1181
|
+
platformDomain() {
|
|
1182
|
+
return this.result(() => this.http.get("/platform-settings/domain"));
|
|
1183
|
+
}
|
|
1184
|
+
/** List language options used by Linxio settings screens. */
|
|
1185
|
+
languages() {
|
|
1186
|
+
return this.result(() => this.http.get("/settings/language/list"));
|
|
1187
|
+
}
|
|
1188
|
+
/** Fetch the map API setting record for the current tenant. */
|
|
1189
|
+
mapApiOptions() {
|
|
1190
|
+
return this.result(() => this.http.get("/settings/mapApiOptions"));
|
|
1191
|
+
}
|
|
1192
|
+
/** Fetch dashboard provider settings visible to the current account. */
|
|
1193
|
+
providers() {
|
|
1194
|
+
return this.result(() => this.http.get("/settings/provider"));
|
|
1195
|
+
}
|
|
1196
|
+
/** Fetch tenant-level digital-form settings. */
|
|
1197
|
+
digitalFormSettings() {
|
|
1198
|
+
return this.result(() => this.http.get("/settings/digitalForm"));
|
|
1199
|
+
}
|
|
1200
|
+
/** Fetch tenant-level eco-speed settings. */
|
|
1201
|
+
ecoSpeedSettings() {
|
|
1202
|
+
return this.result(() => this.http.get("/settings/ecoSpeed"));
|
|
1203
|
+
}
|
|
1204
|
+
/** Fetch tenant-level excessive-idling settings. */
|
|
1205
|
+
excessiveIdlingSettings() {
|
|
1206
|
+
return this.result(() => this.http.get("/settings/excessiveIdling"));
|
|
1207
|
+
}
|
|
1208
|
+
};
|
|
1209
|
+
|
|
1210
|
+
// src/services/reports.service.ts
|
|
1211
|
+
var ReportsService = class extends BaseService {
|
|
1212
|
+
/** List scheduled reports. */
|
|
1213
|
+
scheduled(params = {}) {
|
|
1214
|
+
return this.getPage("/scheduled-report", params);
|
|
1215
|
+
}
|
|
1216
|
+
/** Fetch the scheduled-report template used by the Linxio dashboard. */
|
|
1217
|
+
scheduledTemplate() {
|
|
1218
|
+
return this.result(() => this.http.get("/scheduled-report/template"));
|
|
1219
|
+
}
|
|
1220
|
+
/** Fetch one scheduled report. */
|
|
1221
|
+
getScheduled(reportId) {
|
|
1222
|
+
return this.result(
|
|
1223
|
+
() => this.http.get(`/scheduled-report/${reportId}`)
|
|
1224
|
+
);
|
|
1225
|
+
}
|
|
1226
|
+
/** Create a scheduled report. */
|
|
1227
|
+
createScheduled(payload) {
|
|
1228
|
+
return this.result(() => this.http.post("/scheduled-report", payload));
|
|
1229
|
+
}
|
|
1230
|
+
/** Update a scheduled report. */
|
|
1231
|
+
updateScheduled(reportId, payload) {
|
|
1232
|
+
return this.result(
|
|
1233
|
+
() => this.http.patch(`/scheduled-report/${reportId}`, payload)
|
|
1234
|
+
);
|
|
1235
|
+
}
|
|
1236
|
+
/** Delete a scheduled report. */
|
|
1237
|
+
deleteScheduled(reportId) {
|
|
1238
|
+
return this.result(
|
|
1239
|
+
() => this.http.delete(`/scheduled-report/${reportId}`)
|
|
1240
|
+
);
|
|
1241
|
+
}
|
|
1242
|
+
/** Restore a scheduled report from the dashboard-derived endpoint. */
|
|
1243
|
+
restoreScheduled(reportId) {
|
|
1244
|
+
return this.result(
|
|
1245
|
+
() => this.http.patch(`/scheduled-report/${reportId}/restore`, {})
|
|
1246
|
+
);
|
|
1247
|
+
}
|
|
1248
|
+
};
|
|
1249
|
+
var DigitalFormsService = class extends BaseService {
|
|
1250
|
+
/** List digital forms. */
|
|
1251
|
+
list() {
|
|
1252
|
+
return this.result(() => this.http.get("/digital-form/form"));
|
|
1253
|
+
}
|
|
1254
|
+
/** Fetch one digital form. */
|
|
1255
|
+
get(formId) {
|
|
1256
|
+
return this.result(() => this.http.get(`/digital-form/form/${formId}`));
|
|
1257
|
+
}
|
|
1258
|
+
/** Fetch one digital form answer. */
|
|
1259
|
+
answer(answerId) {
|
|
1260
|
+
return this.result(
|
|
1261
|
+
() => this.http.get(`/digital-form/answer/${answerId}`)
|
|
1262
|
+
);
|
|
1263
|
+
}
|
|
1264
|
+
/** Download a digital form answer as a PDF Blob. */
|
|
1265
|
+
answerPdf(answerId) {
|
|
1266
|
+
return this.result(
|
|
1267
|
+
() => this.http.get(`/digital-form/answer/${answerId}/pdf`, {
|
|
1268
|
+
responseType: "blob"
|
|
1269
|
+
})
|
|
1270
|
+
);
|
|
1271
|
+
}
|
|
1272
|
+
};
|
|
1273
|
+
|
|
1274
|
+
// src/services/routes.service.ts
|
|
1275
|
+
var RoutesService = class extends BaseService {
|
|
1276
|
+
/**
|
|
1277
|
+
* Fetch route history for a vehicle.
|
|
1278
|
+
*
|
|
1279
|
+
* Requesting `fields: ["coordinates"]` can return very large responses, so
|
|
1280
|
+
* only include coordinates when your script really needs every point.
|
|
1281
|
+
*/
|
|
1282
|
+
getVehicleRoutes(vehicleId, params) {
|
|
1283
|
+
const { fields, ...rest } = params;
|
|
1284
|
+
return this.result(
|
|
1285
|
+
() => this.http.get(`/vehicles/${vehicleId}/routes`, {
|
|
1286
|
+
params: mergeParams(rest, fields)
|
|
1287
|
+
})
|
|
1288
|
+
);
|
|
1289
|
+
}
|
|
1290
|
+
};
|
|
1291
|
+
|
|
1292
|
+
// src/services/sensors.service.ts
|
|
1293
|
+
var SensorsService = class extends BaseService {
|
|
1294
|
+
/** List sensors from the dashboard-derived endpoint. */
|
|
1295
|
+
list(params = {}) {
|
|
1296
|
+
return this.getPage("/sensors", params);
|
|
1297
|
+
}
|
|
1298
|
+
/** Load every sensor page into a single result. */
|
|
1299
|
+
iterate(params = {}) {
|
|
1300
|
+
return collectPages((pageParams) => this.list(pageParams), params);
|
|
1301
|
+
}
|
|
1302
|
+
/** Stream sensors without loading the whole inventory at once. */
|
|
1303
|
+
stream(params = {}) {
|
|
1304
|
+
return streamPages((pageParams) => this.list(pageParams), params);
|
|
1305
|
+
}
|
|
1306
|
+
/** Fetch one sensor by internal Linxio sensor ID. */
|
|
1307
|
+
get(sensorId) {
|
|
1308
|
+
return this.result(() => this.http.get(`/sensors/${sensorId}`));
|
|
1309
|
+
}
|
|
1310
|
+
/** Install or pair a sensor with a device. */
|
|
1311
|
+
install(sensorId, deviceId) {
|
|
1312
|
+
return this.result(
|
|
1313
|
+
() => this.http.post(`/sensors/${sensorId}/install`, { deviceId })
|
|
1314
|
+
);
|
|
1315
|
+
}
|
|
1316
|
+
/** Fetch the documented temperature/humidity report grouped by device sensor. */
|
|
1317
|
+
deviceTemperatureHumidityReport(params = {}) {
|
|
1318
|
+
return this.getPage(
|
|
1319
|
+
"/devices/sensors/report/temp-and-humidity",
|
|
1320
|
+
params
|
|
1321
|
+
);
|
|
1322
|
+
}
|
|
1323
|
+
/** Fetch the documented temperature/humidity report grouped by vehicle. */
|
|
1324
|
+
vehicleTemperatureHumidityReport(params = {}) {
|
|
1325
|
+
return this.getPage(
|
|
1326
|
+
"/vehicles/report/sensors/temp-and-humidity",
|
|
1327
|
+
params
|
|
1328
|
+
);
|
|
1329
|
+
}
|
|
1330
|
+
/** Load every device temperature/humidity report page into a single result. */
|
|
1331
|
+
iterateDeviceTemperatureHumidityReport(params = {}) {
|
|
1332
|
+
return collectPages(
|
|
1333
|
+
(pageParams) => this.deviceTemperatureHumidityReport(pageParams),
|
|
1334
|
+
params
|
|
1335
|
+
);
|
|
1336
|
+
}
|
|
1337
|
+
/** Stream the device temperature/humidity report one reading at a time. */
|
|
1338
|
+
streamDeviceTemperatureHumidityReport(params = {}) {
|
|
1339
|
+
return streamPages(
|
|
1340
|
+
(pageParams) => this.deviceTemperatureHumidityReport(pageParams),
|
|
1341
|
+
params
|
|
1342
|
+
);
|
|
1343
|
+
}
|
|
1344
|
+
};
|
|
1345
|
+
|
|
1346
|
+
// src/services/users.service.ts
|
|
1347
|
+
var UsersService = class extends BaseService {
|
|
1348
|
+
/** List users from the dashboard-derived endpoint. */
|
|
1349
|
+
list(params = {}) {
|
|
1350
|
+
return this.getPage("/users", params);
|
|
1351
|
+
}
|
|
1352
|
+
/** Load every user page into a single result. */
|
|
1353
|
+
iterate(params = {}) {
|
|
1354
|
+
return collectPages((pageParams) => this.list(pageParams), params);
|
|
1355
|
+
}
|
|
1356
|
+
/** Stream every user page without loading every user at once. */
|
|
1357
|
+
stream(params = {}) {
|
|
1358
|
+
return streamPages((pageParams) => this.list(pageParams), params);
|
|
1359
|
+
}
|
|
1360
|
+
/** Fetch one user by ID. */
|
|
1361
|
+
get(userId) {
|
|
1362
|
+
return this.result(() => this.http.get(`/users/${userId}`));
|
|
1363
|
+
}
|
|
1364
|
+
/** Create a user. */
|
|
1365
|
+
create(payload) {
|
|
1366
|
+
return this.result(() => this.http.post("/users", payload));
|
|
1367
|
+
}
|
|
1368
|
+
/** Update a user. */
|
|
1369
|
+
update(userId, payload) {
|
|
1370
|
+
return this.result(() => this.http.patch(`/users/${userId}`, payload));
|
|
1371
|
+
}
|
|
1372
|
+
/** Soft-archive a user. */
|
|
1373
|
+
archive(userId) {
|
|
1374
|
+
return this.result(
|
|
1375
|
+
() => this.http.patch(`/users/${userId}/archive`, {})
|
|
1376
|
+
);
|
|
1377
|
+
}
|
|
1378
|
+
/** Restore a previously archived user. */
|
|
1379
|
+
restore(userId) {
|
|
1380
|
+
return this.result(
|
|
1381
|
+
() => this.http.patch(`/users/${userId}/restore`, {})
|
|
1382
|
+
);
|
|
1383
|
+
}
|
|
1384
|
+
};
|
|
1385
|
+
|
|
1386
|
+
// src/services/vehicles.service.ts
|
|
1387
|
+
var VehiclesService = class extends BaseService {
|
|
1388
|
+
/** List vehicles using Linxio's documented `/vehicles/fields/json` endpoint. */
|
|
1389
|
+
list(params = {}) {
|
|
1390
|
+
return this.getPage("/vehicles/fields/json", params);
|
|
1391
|
+
}
|
|
1392
|
+
/** Load every vehicle page into a single result. */
|
|
1393
|
+
iterate(params = {}) {
|
|
1394
|
+
return collectPages((pageParams) => this.list(pageParams), params);
|
|
1395
|
+
}
|
|
1396
|
+
/** Stream every vehicle page without loading the whole fleet at once. */
|
|
1397
|
+
stream(params = {}) {
|
|
1398
|
+
return streamPages((pageParams) => this.list(pageParams), params);
|
|
1399
|
+
}
|
|
1400
|
+
/** Fetch one vehicle by internal Linxio vehicle ID. */
|
|
1401
|
+
get(vehicleId) {
|
|
1402
|
+
return this.result(() => this.http.get(`/vehicles/${vehicleId}`));
|
|
1403
|
+
}
|
|
1404
|
+
/** Create a vehicle. Validate payloads carefully against your Linxio tenant requirements. */
|
|
1405
|
+
create(payload) {
|
|
1406
|
+
return this.result(() => this.http.post("/vehicles", payload));
|
|
1407
|
+
}
|
|
1408
|
+
/** Update a vehicle using Linxio's documented POST update endpoint. */
|
|
1409
|
+
update(vehicleId, payload) {
|
|
1410
|
+
return this.result(
|
|
1411
|
+
() => this.http.post(`/vehicles/${vehicleId}`, payload)
|
|
1412
|
+
);
|
|
1413
|
+
}
|
|
1414
|
+
/** Soft-archive a vehicle when the dashboard endpoint is available. */
|
|
1415
|
+
archive(vehicleId) {
|
|
1416
|
+
return this.result(
|
|
1417
|
+
() => this.http.patch(`/vehicles/${vehicleId}/archive`, {})
|
|
1418
|
+
);
|
|
1419
|
+
}
|
|
1420
|
+
/** Restore a previously archived vehicle when the dashboard endpoint is available. */
|
|
1421
|
+
restore(vehicleId) {
|
|
1422
|
+
return this.result(
|
|
1423
|
+
() => this.http.post(`/vehicles/${vehicleId}/restore`, {})
|
|
1424
|
+
);
|
|
1425
|
+
}
|
|
1426
|
+
/** Get a vehicle odometer reading, optionally at a specific occurrence time. */
|
|
1427
|
+
getOdometer(vehicleId, params = {}) {
|
|
1428
|
+
return this.result(
|
|
1429
|
+
() => this.http.get(`/vehicles/${vehicleId}/odometer`, { params })
|
|
1430
|
+
);
|
|
1431
|
+
}
|
|
1432
|
+
/** Recalibrate a vehicle odometer in metres. */
|
|
1433
|
+
recalibrateOdometer(vehicleId, payload) {
|
|
1434
|
+
return this.result(
|
|
1435
|
+
() => this.http.post(`/vehicles/${vehicleId}/odometer`, payload)
|
|
1436
|
+
);
|
|
1437
|
+
}
|
|
1438
|
+
/** Fetch current engine hours from the dashboard-derived endpoint. */
|
|
1439
|
+
getEngineHours(vehicleId) {
|
|
1440
|
+
return this.result(
|
|
1441
|
+
() => this.http.get(`/vehicles/${vehicleId}/engine-hours/current`)
|
|
1442
|
+
);
|
|
1443
|
+
}
|
|
1444
|
+
/** Count vehicles using the dashboard-derived count endpoint. */
|
|
1445
|
+
count(params = {}) {
|
|
1446
|
+
return this.result(() => this.http.get("/vehicles/count", { params }));
|
|
1447
|
+
}
|
|
1448
|
+
/** List vehicle types using the dashboard-derived vehicle type endpoint. */
|
|
1449
|
+
types(params = {}) {
|
|
1450
|
+
return this.getPage("/vehicles/types", {
|
|
1451
|
+
limit: 1e3,
|
|
1452
|
+
sort: "order",
|
|
1453
|
+
...params
|
|
1454
|
+
});
|
|
1455
|
+
}
|
|
1456
|
+
};
|
|
1457
|
+
|
|
1458
|
+
// src/client.ts
|
|
1459
|
+
var LinxioClient = class {
|
|
1460
|
+
/** Authentication, session, and current-user helpers. */
|
|
1461
|
+
auth;
|
|
1462
|
+
/** Dash cam event helpers discovered from the dashboard bundle. */
|
|
1463
|
+
cameras;
|
|
1464
|
+
/** Client account and client-user helpers. */
|
|
1465
|
+
clients;
|
|
1466
|
+
/** Device inventory, install, uninstall, sensor, and coordinate helpers. */
|
|
1467
|
+
devices;
|
|
1468
|
+
/** Digital forms and form answer helpers discovered from the dashboard bundle. */
|
|
1469
|
+
digitalForms;
|
|
1470
|
+
/** Driver listing and vehicle assignment helpers. */
|
|
1471
|
+
drivers;
|
|
1472
|
+
/** Fuel card, fuel record, and fuel summary helpers discovered from the dashboard bundle. */
|
|
1473
|
+
fuel;
|
|
1474
|
+
/** Geofence/area and area-group helpers. */
|
|
1475
|
+
geofences;
|
|
1476
|
+
/** Low-level HTTP client for advanced integrations. */
|
|
1477
|
+
http;
|
|
1478
|
+
/** Read-only reference data and tenant settings discovered from the dashboard bundle. */
|
|
1479
|
+
metadata;
|
|
1480
|
+
/** Socket.IO live tracking and notification client. */
|
|
1481
|
+
realtime;
|
|
1482
|
+
/** Scheduled report helpers discovered from the dashboard bundle. */
|
|
1483
|
+
reports;
|
|
1484
|
+
/** Reseller account helpers discovered from the dashboard bundle. */
|
|
1485
|
+
resellers;
|
|
1486
|
+
/** Vehicle route history helpers. */
|
|
1487
|
+
routes;
|
|
1488
|
+
/** Temperature/humidity sensor helpers. */
|
|
1489
|
+
sensors;
|
|
1490
|
+
/** User management helpers. */
|
|
1491
|
+
users;
|
|
1492
|
+
/** Vehicle inventory, odometer, and engine-hours helpers. */
|
|
1493
|
+
vehicles;
|
|
1494
|
+
currentSession;
|
|
1495
|
+
constructor(options = {}) {
|
|
1496
|
+
this.currentSession = {
|
|
1497
|
+
refreshToken: options.refreshToken,
|
|
1498
|
+
token: options.token
|
|
1499
|
+
};
|
|
1500
|
+
this.http = new HttpClient({
|
|
1501
|
+
baseUrl: options.baseUrl,
|
|
1502
|
+
fetch: options.fetch,
|
|
1503
|
+
getRefreshToken: () => this.currentSession.refreshToken,
|
|
1504
|
+
getToken: () => this.currentSession.token,
|
|
1505
|
+
onSession: (session) => this.setSession(session),
|
|
1506
|
+
retry: options.retry,
|
|
1507
|
+
timeoutMs: options.timeoutMs
|
|
1508
|
+
});
|
|
1509
|
+
this.realtime = new RealtimeClient({
|
|
1510
|
+
baseUrl: options.realtimeBaseUrl,
|
|
1511
|
+
getToken: () => this.currentSession.token
|
|
1512
|
+
});
|
|
1513
|
+
this.auth = new AuthService(
|
|
1514
|
+
this.http,
|
|
1515
|
+
(session) => this.setSession(session)
|
|
1516
|
+
);
|
|
1517
|
+
this.cameras = new CamerasService(this.http);
|
|
1518
|
+
this.clients = new ClientsService(this.http);
|
|
1519
|
+
this.devices = new DevicesService(this.http);
|
|
1520
|
+
this.digitalForms = new DigitalFormsService(this.http);
|
|
1521
|
+
this.drivers = new DriversService(this.http);
|
|
1522
|
+
this.fuel = new FuelService(this.http);
|
|
1523
|
+
this.geofences = new GeofencesService(this.http);
|
|
1524
|
+
this.metadata = new MetadataService(this.http);
|
|
1525
|
+
this.reports = new ReportsService(this.http);
|
|
1526
|
+
this.resellers = new ResellersService(this.http);
|
|
1527
|
+
this.routes = new RoutesService(this.http);
|
|
1528
|
+
this.sensors = new SensorsService(this.http);
|
|
1529
|
+
this.users = new UsersService(this.http);
|
|
1530
|
+
this.vehicles = new VehiclesService(this.http);
|
|
1531
|
+
}
|
|
1532
|
+
/**
|
|
1533
|
+
* Replace or partially update the in-memory session used by this client.
|
|
1534
|
+
*
|
|
1535
|
+
* This is useful when you persist tokens yourself and want to hydrate a
|
|
1536
|
+
* client without calling `auth.login()` again.
|
|
1537
|
+
*/
|
|
1538
|
+
setSession(session) {
|
|
1539
|
+
this.currentSession = {
|
|
1540
|
+
...this.currentSession,
|
|
1541
|
+
...session
|
|
1542
|
+
};
|
|
1543
|
+
}
|
|
1544
|
+
/** Return a copy of the current in-memory session. */
|
|
1545
|
+
session() {
|
|
1546
|
+
return { ...this.currentSession };
|
|
1547
|
+
}
|
|
1548
|
+
/**
|
|
1549
|
+
* Send a raw API request with the same auth, retry, timeout, and refresh
|
|
1550
|
+
* behavior used by the domain services.
|
|
1551
|
+
*/
|
|
1552
|
+
request(method, path, options = {}) {
|
|
1553
|
+
return this.http.request(method, path, options);
|
|
1554
|
+
}
|
|
1555
|
+
};
|
|
1556
|
+
function createClient(options = {}) {
|
|
1557
|
+
return new LinxioClient(options);
|
|
1558
|
+
}
|
|
1559
|
+
|
|
1560
|
+
// src/endpoint-discovery.ts
|
|
1561
|
+
var HTTP_METHODS = ["DELETE", "GET", "PATCH", "POST", "PUT"];
|
|
1562
|
+
var METHOD_PATTERN = /\.(delete|get|patch|post|put)\s*\($/i;
|
|
1563
|
+
var STRING_LITERAL_PATTERN = /(["'`])((?:\\.|(?!\1)[\s\S])*?)\1/g;
|
|
1564
|
+
function extractDashboardEndpoints(sources) {
|
|
1565
|
+
const endpoints = /* @__PURE__ */ new Map();
|
|
1566
|
+
for (const source of sources) {
|
|
1567
|
+
for (const match of source.content.matchAll(STRING_LITERAL_PATTERN)) {
|
|
1568
|
+
const rawValue = match[2];
|
|
1569
|
+
if (rawValue === void 0 || match.index === void 0) {
|
|
1570
|
+
continue;
|
|
1571
|
+
}
|
|
1572
|
+
const path = normalizeDashboardPath(rawValue);
|
|
1573
|
+
if (!path || !isLikelyApiEndpoint(path)) {
|
|
1574
|
+
continue;
|
|
1575
|
+
}
|
|
1576
|
+
const method = inferHttpMethod(source.content, match.index);
|
|
1577
|
+
if (method === "UNKNOWN") {
|
|
1578
|
+
continue;
|
|
1579
|
+
}
|
|
1580
|
+
const evidence = endpoints.get(path) ?? {
|
|
1581
|
+
files: /* @__PURE__ */ new Set(),
|
|
1582
|
+
methods: /* @__PURE__ */ new Set(),
|
|
1583
|
+
occurrences: 0
|
|
1584
|
+
};
|
|
1585
|
+
evidence.files.add(source.filename);
|
|
1586
|
+
evidence.methods.add(method);
|
|
1587
|
+
evidence.occurrences += 1;
|
|
1588
|
+
endpoints.set(path, evidence);
|
|
1589
|
+
}
|
|
1590
|
+
}
|
|
1591
|
+
return [...endpoints.entries()].map(([path, evidence]) => ({
|
|
1592
|
+
files: [...evidence.files].sort(
|
|
1593
|
+
(left, right) => left.localeCompare(right)
|
|
1594
|
+
),
|
|
1595
|
+
methods: [...evidence.methods].sort(compareMethods),
|
|
1596
|
+
occurrences: evidence.occurrences,
|
|
1597
|
+
path
|
|
1598
|
+
})).sort((left, right) => compareText(left.path, right.path));
|
|
1599
|
+
}
|
|
1600
|
+
function compareDashboardEndpointCoverage({
|
|
1601
|
+
dashboardEndpoints,
|
|
1602
|
+
sdkEndpoints
|
|
1603
|
+
}) {
|
|
1604
|
+
const sdkKeys = new Set(sdkEndpoints.map(endpointKey));
|
|
1605
|
+
const dashboardKeys = /* @__PURE__ */ new Set();
|
|
1606
|
+
const dashboardCovered = [];
|
|
1607
|
+
const dashboardOnly = [];
|
|
1608
|
+
for (const endpoint of dashboardEndpoints) {
|
|
1609
|
+
const keys = endpoint.methods.map(
|
|
1610
|
+
(method) => endpointKey({ method, path: endpoint.path })
|
|
1611
|
+
);
|
|
1612
|
+
for (const key of keys) {
|
|
1613
|
+
dashboardKeys.add(key);
|
|
1614
|
+
}
|
|
1615
|
+
if (keys.some((key) => sdkKeys.has(key))) {
|
|
1616
|
+
dashboardCovered.push(endpoint);
|
|
1617
|
+
} else {
|
|
1618
|
+
dashboardOnly.push(endpoint);
|
|
1619
|
+
}
|
|
1620
|
+
}
|
|
1621
|
+
return {
|
|
1622
|
+
dashboardCovered,
|
|
1623
|
+
dashboardOnly,
|
|
1624
|
+
sdkOnly: sdkEndpoints.filter(
|
|
1625
|
+
(endpoint) => !dashboardKeys.has(endpointKey(endpoint))
|
|
1626
|
+
)
|
|
1627
|
+
};
|
|
1628
|
+
}
|
|
1629
|
+
function flattenEndpointDefinitions(catalogue) {
|
|
1630
|
+
const definitions = [];
|
|
1631
|
+
collectEndpointDefinitions(catalogue, definitions);
|
|
1632
|
+
return definitions.sort((left, right) => {
|
|
1633
|
+
const pathOrder = compareText(left.path, right.path);
|
|
1634
|
+
return pathOrder === 0 ? compareMethods(left.method, right.method) : pathOrder;
|
|
1635
|
+
});
|
|
1636
|
+
}
|
|
1637
|
+
function normalizeDashboardPath(value) {
|
|
1638
|
+
const normalized = value.replace(/\\\//g, "/").replace(/\$\{[^}]*\}/g, "{param}").trim();
|
|
1639
|
+
if (!normalized.startsWith("/") || normalized.startsWith("//")) {
|
|
1640
|
+
return void 0;
|
|
1641
|
+
}
|
|
1642
|
+
return normalized.replace(/\/+$/, "") || "/";
|
|
1643
|
+
}
|
|
1644
|
+
function isLikelyApiEndpoint(path) {
|
|
1645
|
+
if (path === "/" || path.includes(" ") || path.startsWith("/.") || path.startsWith("/MM/") || path.startsWith("/socket.io")) {
|
|
1646
|
+
return false;
|
|
1647
|
+
}
|
|
1648
|
+
return /^\/[a-z][a-z0-9-]*(?:[/?#]|$)/i.test(path);
|
|
1649
|
+
}
|
|
1650
|
+
function inferHttpMethod(content, literalIndex) {
|
|
1651
|
+
const prefix = content.slice(Math.max(0, literalIndex - 80), literalIndex);
|
|
1652
|
+
const match = prefix.match(METHOD_PATTERN);
|
|
1653
|
+
if (!match?.[1]) {
|
|
1654
|
+
return "UNKNOWN";
|
|
1655
|
+
}
|
|
1656
|
+
return match[1].toUpperCase();
|
|
1657
|
+
}
|
|
1658
|
+
function compareMethods(left, right) {
|
|
1659
|
+
return methodRank(left) - methodRank(right);
|
|
1660
|
+
}
|
|
1661
|
+
function compareText(left, right) {
|
|
1662
|
+
if (left < right) {
|
|
1663
|
+
return -1;
|
|
1664
|
+
}
|
|
1665
|
+
if (left > right) {
|
|
1666
|
+
return 1;
|
|
1667
|
+
}
|
|
1668
|
+
return 0;
|
|
1669
|
+
}
|
|
1670
|
+
function methodRank(method) {
|
|
1671
|
+
const index = HTTP_METHODS.indexOf(method);
|
|
1672
|
+
return index === -1 ? HTTP_METHODS.length : index;
|
|
1673
|
+
}
|
|
1674
|
+
function endpointKey(endpoint) {
|
|
1675
|
+
return `${endpoint.method}:${normalizeComparablePath(endpoint.path)}`;
|
|
1676
|
+
}
|
|
1677
|
+
function normalizeComparablePath(path) {
|
|
1678
|
+
const [pathWithoutQuery] = path.split("?");
|
|
1679
|
+
return (pathWithoutQuery ?? path).replace(/\{[^}]+\}/g, "{param}");
|
|
1680
|
+
}
|
|
1681
|
+
function collectEndpointDefinitions(value, definitions) {
|
|
1682
|
+
if (!isRecord2(value)) {
|
|
1683
|
+
return;
|
|
1684
|
+
}
|
|
1685
|
+
if (isEndpointDefinition(value)) {
|
|
1686
|
+
definitions.push(value);
|
|
1687
|
+
return;
|
|
1688
|
+
}
|
|
1689
|
+
for (const nestedValue of Object.values(value)) {
|
|
1690
|
+
collectEndpointDefinitions(nestedValue, definitions);
|
|
1691
|
+
}
|
|
1692
|
+
}
|
|
1693
|
+
function isEndpointDefinition(value) {
|
|
1694
|
+
return typeof value.path === "string" && (value.source === "dashboard" || value.source === "public-docs") && isHttpMethod(value.method);
|
|
1695
|
+
}
|
|
1696
|
+
function isHttpMethod(value) {
|
|
1697
|
+
return value === "DELETE" || value === "GET" || value === "PATCH" || value === "POST" || value === "PUT";
|
|
1698
|
+
}
|
|
1699
|
+
function isRecord2(value) {
|
|
1700
|
+
return typeof value === "object" && value !== null;
|
|
1701
|
+
}
|
|
1702
|
+
|
|
1703
|
+
// src/endpoints.ts
|
|
1704
|
+
var linxioEndpoints = {
|
|
1705
|
+
auth: {
|
|
1706
|
+
login: { method: "POST", path: "/login", source: "public-docs" },
|
|
1707
|
+
logout: { method: "POST", path: "/logout", source: "dashboard" },
|
|
1708
|
+
me: { method: "GET", path: "/me", source: "dashboard" },
|
|
1709
|
+
refreshToken: {
|
|
1710
|
+
method: "POST",
|
|
1711
|
+
path: "/token/refresh",
|
|
1712
|
+
source: "dashboard"
|
|
1713
|
+
},
|
|
1714
|
+
verifyOtp: { method: "POST", path: "/login/otp", source: "dashboard" }
|
|
1715
|
+
},
|
|
1716
|
+
cameras: {
|
|
1717
|
+
eventTypes: {
|
|
1718
|
+
method: "GET",
|
|
1719
|
+
path: "/devices/cameras/events/types",
|
|
1720
|
+
source: "dashboard"
|
|
1721
|
+
},
|
|
1722
|
+
events: {
|
|
1723
|
+
method: "GET",
|
|
1724
|
+
path: "/devices/cameras/events",
|
|
1725
|
+
source: "dashboard"
|
|
1726
|
+
}
|
|
1727
|
+
},
|
|
1728
|
+
clients: {
|
|
1729
|
+
get: {
|
|
1730
|
+
method: "GET",
|
|
1731
|
+
path: "/clients/{clientId}",
|
|
1732
|
+
source: "dashboard"
|
|
1733
|
+
},
|
|
1734
|
+
list: { method: "GET", path: "/clients/json", source: "dashboard" },
|
|
1735
|
+
users: {
|
|
1736
|
+
create: {
|
|
1737
|
+
method: "POST",
|
|
1738
|
+
path: "/clients/{clientId}/users",
|
|
1739
|
+
source: "public-docs"
|
|
1740
|
+
},
|
|
1741
|
+
get: {
|
|
1742
|
+
method: "GET",
|
|
1743
|
+
path: "/clients/{clientId}/users/{userId}",
|
|
1744
|
+
source: "public-docs"
|
|
1745
|
+
},
|
|
1746
|
+
list: {
|
|
1747
|
+
method: "GET",
|
|
1748
|
+
path: "/clients/{clientId}/users",
|
|
1749
|
+
source: "public-docs"
|
|
1750
|
+
},
|
|
1751
|
+
update: {
|
|
1752
|
+
method: "POST",
|
|
1753
|
+
path: "/clients/{clientId}/users/{userId}",
|
|
1754
|
+
source: "public-docs"
|
|
1755
|
+
}
|
|
1756
|
+
}
|
|
1757
|
+
},
|
|
1758
|
+
devices: {
|
|
1759
|
+
archive: {
|
|
1760
|
+
method: "PATCH",
|
|
1761
|
+
path: "/devices/{deviceId}/archive",
|
|
1762
|
+
source: "dashboard"
|
|
1763
|
+
},
|
|
1764
|
+
coordinates: {
|
|
1765
|
+
method: "GET",
|
|
1766
|
+
path: "/devices/{deviceId}/coordinates",
|
|
1767
|
+
source: "dashboard"
|
|
1768
|
+
},
|
|
1769
|
+
cameras: {
|
|
1770
|
+
method: "GET",
|
|
1771
|
+
path: "/devices/{deviceId}/cameras",
|
|
1772
|
+
source: "dashboard"
|
|
1773
|
+
},
|
|
1774
|
+
create: { method: "POST", path: "/devices", source: "public-docs" },
|
|
1775
|
+
get: {
|
|
1776
|
+
method: "GET",
|
|
1777
|
+
path: "/devices/{deviceId}",
|
|
1778
|
+
source: "public-docs"
|
|
1779
|
+
},
|
|
1780
|
+
install: {
|
|
1781
|
+
method: "POST",
|
|
1782
|
+
path: "/devices/{deviceId}/install",
|
|
1783
|
+
source: "public-docs"
|
|
1784
|
+
},
|
|
1785
|
+
list: { method: "GET", path: "/devices/json", source: "public-docs" },
|
|
1786
|
+
history: {
|
|
1787
|
+
method: "GET",
|
|
1788
|
+
path: "/devices/{deviceId}/history",
|
|
1789
|
+
source: "dashboard"
|
|
1790
|
+
},
|
|
1791
|
+
installations: {
|
|
1792
|
+
method: "GET",
|
|
1793
|
+
path: "/devices/installation/",
|
|
1794
|
+
source: "dashboard"
|
|
1795
|
+
},
|
|
1796
|
+
sensors: {
|
|
1797
|
+
list: {
|
|
1798
|
+
method: "GET",
|
|
1799
|
+
path: "/devices/{deviceId}/sensors/history",
|
|
1800
|
+
source: "dashboard"
|
|
1801
|
+
}
|
|
1802
|
+
},
|
|
1803
|
+
uninstall: {
|
|
1804
|
+
method: "POST",
|
|
1805
|
+
path: "/devices/{deviceId}/uninstall",
|
|
1806
|
+
source: "public-docs"
|
|
1807
|
+
},
|
|
1808
|
+
update: {
|
|
1809
|
+
method: "PATCH",
|
|
1810
|
+
path: "/devices/{deviceId}",
|
|
1811
|
+
source: "public-docs"
|
|
1812
|
+
},
|
|
1813
|
+
vendors: {
|
|
1814
|
+
method: "GET",
|
|
1815
|
+
path: "/devices/vendors/",
|
|
1816
|
+
source: "dashboard"
|
|
1817
|
+
}
|
|
1818
|
+
},
|
|
1819
|
+
drivers: {
|
|
1820
|
+
assignToVehicle: {
|
|
1821
|
+
method: "POST",
|
|
1822
|
+
path: "/vehicle/{vehicleId}/set-driver/{driverId}",
|
|
1823
|
+
source: "public-docs"
|
|
1824
|
+
},
|
|
1825
|
+
list: {
|
|
1826
|
+
method: "GET",
|
|
1827
|
+
path: "/clients/{clientId}/users?role=driver",
|
|
1828
|
+
source: "public-docs"
|
|
1829
|
+
},
|
|
1830
|
+
unassignFromVehicle: {
|
|
1831
|
+
method: "POST",
|
|
1832
|
+
path: "/vehicle/{vehicleId}/unset-driver/{driverId}",
|
|
1833
|
+
source: "public-docs"
|
|
1834
|
+
}
|
|
1835
|
+
},
|
|
1836
|
+
fuel: {
|
|
1837
|
+
assignTransaction: {
|
|
1838
|
+
method: "PATCH",
|
|
1839
|
+
path: "/fuel-cards/record/{recordId}",
|
|
1840
|
+
source: "dashboard"
|
|
1841
|
+
},
|
|
1842
|
+
cards: { method: "GET", path: "/fuel-cards/json", source: "dashboard" },
|
|
1843
|
+
records: {
|
|
1844
|
+
method: "GET",
|
|
1845
|
+
path: "/fuel-cards/json",
|
|
1846
|
+
source: "dashboard"
|
|
1847
|
+
},
|
|
1848
|
+
recordsByVehicle: {
|
|
1849
|
+
method: "GET",
|
|
1850
|
+
path: "/fuel-cards-by-vehicle/json",
|
|
1851
|
+
source: "dashboard"
|
|
1852
|
+
},
|
|
1853
|
+
summary: {
|
|
1854
|
+
method: "GET",
|
|
1855
|
+
path: "/fuel-summary-report",
|
|
1856
|
+
source: "dashboard"
|
|
1857
|
+
},
|
|
1858
|
+
fuelTypes: {
|
|
1859
|
+
method: "GET",
|
|
1860
|
+
path: "/fuel-types",
|
|
1861
|
+
source: "dashboard"
|
|
1862
|
+
}
|
|
1863
|
+
},
|
|
1864
|
+
geofences: {
|
|
1865
|
+
archive: {
|
|
1866
|
+
method: "PATCH",
|
|
1867
|
+
path: "/areas/{areaId}/archive",
|
|
1868
|
+
source: "dashboard"
|
|
1869
|
+
},
|
|
1870
|
+
create: { method: "POST", path: "/areas", source: "public-docs" },
|
|
1871
|
+
delete: {
|
|
1872
|
+
method: "DELETE",
|
|
1873
|
+
path: "/areas/{areaId}",
|
|
1874
|
+
source: "public-docs"
|
|
1875
|
+
},
|
|
1876
|
+
get: { method: "GET", path: "/areas/{areaId}", source: "dashboard" },
|
|
1877
|
+
list: { method: "GET", path: "/areas", source: "public-docs" },
|
|
1878
|
+
restore: {
|
|
1879
|
+
method: "PATCH",
|
|
1880
|
+
path: "/areas/{areaId}/restore",
|
|
1881
|
+
source: "dashboard"
|
|
1882
|
+
},
|
|
1883
|
+
groups: {
|
|
1884
|
+
archive: {
|
|
1885
|
+
method: "PATCH",
|
|
1886
|
+
path: "/area-groups/{groupId}/archive",
|
|
1887
|
+
source: "dashboard"
|
|
1888
|
+
},
|
|
1889
|
+
create: {
|
|
1890
|
+
method: "POST",
|
|
1891
|
+
path: "/area-groups",
|
|
1892
|
+
source: "dashboard"
|
|
1893
|
+
},
|
|
1894
|
+
delete: {
|
|
1895
|
+
method: "DELETE",
|
|
1896
|
+
path: "/area-groups/{groupId}",
|
|
1897
|
+
source: "dashboard"
|
|
1898
|
+
},
|
|
1899
|
+
get: {
|
|
1900
|
+
method: "GET",
|
|
1901
|
+
path: "/area-groups/{groupId}",
|
|
1902
|
+
source: "dashboard"
|
|
1903
|
+
},
|
|
1904
|
+
list: {
|
|
1905
|
+
method: "GET",
|
|
1906
|
+
path: "/area-groups",
|
|
1907
|
+
source: "dashboard"
|
|
1908
|
+
},
|
|
1909
|
+
restore: {
|
|
1910
|
+
method: "PATCH",
|
|
1911
|
+
path: "/area-groups/{groupId}/restore",
|
|
1912
|
+
source: "dashboard"
|
|
1913
|
+
},
|
|
1914
|
+
update: {
|
|
1915
|
+
method: "PATCH",
|
|
1916
|
+
path: "/area-groups/{groupId}",
|
|
1917
|
+
source: "dashboard"
|
|
1918
|
+
}
|
|
1919
|
+
}
|
|
1920
|
+
},
|
|
1921
|
+
metadata: {
|
|
1922
|
+
countries: {
|
|
1923
|
+
method: "GET",
|
|
1924
|
+
path: "/country/list",
|
|
1925
|
+
source: "dashboard"
|
|
1926
|
+
},
|
|
1927
|
+
currentPlan: {
|
|
1928
|
+
method: "GET",
|
|
1929
|
+
path: "/permissions/current-plan",
|
|
1930
|
+
source: "dashboard"
|
|
1931
|
+
},
|
|
1932
|
+
digitalFormSettings: {
|
|
1933
|
+
method: "GET",
|
|
1934
|
+
path: "/settings/digitalForm",
|
|
1935
|
+
source: "dashboard"
|
|
1936
|
+
},
|
|
1937
|
+
ecoSpeedSettings: {
|
|
1938
|
+
method: "GET",
|
|
1939
|
+
path: "/settings/ecoSpeed",
|
|
1940
|
+
source: "dashboard"
|
|
1941
|
+
},
|
|
1942
|
+
excessiveIdlingSettings: {
|
|
1943
|
+
method: "GET",
|
|
1944
|
+
path: "/settings/excessiveIdling",
|
|
1945
|
+
source: "dashboard"
|
|
1946
|
+
},
|
|
1947
|
+
languages: {
|
|
1948
|
+
method: "GET",
|
|
1949
|
+
path: "/settings/language/list",
|
|
1950
|
+
source: "dashboard"
|
|
1951
|
+
},
|
|
1952
|
+
mapApiOptions: {
|
|
1953
|
+
method: "GET",
|
|
1954
|
+
path: "/settings/mapApiOptions",
|
|
1955
|
+
source: "dashboard"
|
|
1956
|
+
},
|
|
1957
|
+
myTheme: {
|
|
1958
|
+
method: "GET",
|
|
1959
|
+
path: "/themes/my",
|
|
1960
|
+
source: "dashboard"
|
|
1961
|
+
},
|
|
1962
|
+
platformDomain: {
|
|
1963
|
+
method: "GET",
|
|
1964
|
+
path: "/platform-settings/domain",
|
|
1965
|
+
source: "dashboard"
|
|
1966
|
+
},
|
|
1967
|
+
plans: {
|
|
1968
|
+
method: "GET",
|
|
1969
|
+
path: "/plans",
|
|
1970
|
+
source: "dashboard"
|
|
1971
|
+
},
|
|
1972
|
+
providers: {
|
|
1973
|
+
method: "GET",
|
|
1974
|
+
path: "/settings/provider",
|
|
1975
|
+
source: "dashboard"
|
|
1976
|
+
},
|
|
1977
|
+
roles: {
|
|
1978
|
+
method: "GET",
|
|
1979
|
+
path: "/roles",
|
|
1980
|
+
source: "dashboard"
|
|
1981
|
+
},
|
|
1982
|
+
themes: {
|
|
1983
|
+
method: "GET",
|
|
1984
|
+
path: "/themes",
|
|
1985
|
+
source: "dashboard"
|
|
1986
|
+
},
|
|
1987
|
+
timezones: {
|
|
1988
|
+
method: "GET",
|
|
1989
|
+
path: "/timezones",
|
|
1990
|
+
source: "dashboard"
|
|
1991
|
+
}
|
|
1992
|
+
},
|
|
1993
|
+
realtime: {
|
|
1994
|
+
coordinates: {
|
|
1995
|
+
method: "GET",
|
|
1996
|
+
path: "https://track.linxio.com/coordinates",
|
|
1997
|
+
source: "public-docs"
|
|
1998
|
+
},
|
|
1999
|
+
notifications: {
|
|
2000
|
+
method: "GET",
|
|
2001
|
+
path: "https://track.linxio.com/notifications",
|
|
2002
|
+
source: "public-docs"
|
|
2003
|
+
}
|
|
2004
|
+
},
|
|
2005
|
+
reports: {
|
|
2006
|
+
digitalFormAnswer: {
|
|
2007
|
+
method: "GET",
|
|
2008
|
+
path: "/digital-form/answer/{answerId}",
|
|
2009
|
+
source: "dashboard"
|
|
2010
|
+
},
|
|
2011
|
+
digitalFormAnswerPdf: {
|
|
2012
|
+
method: "GET",
|
|
2013
|
+
path: "/digital-form/answer/{answerId}/pdf",
|
|
2014
|
+
source: "dashboard"
|
|
2015
|
+
},
|
|
2016
|
+
deleteScheduledReport: {
|
|
2017
|
+
method: "DELETE",
|
|
2018
|
+
path: "/scheduled-report/{reportId}",
|
|
2019
|
+
source: "dashboard"
|
|
2020
|
+
},
|
|
2021
|
+
getScheduledReport: {
|
|
2022
|
+
method: "GET",
|
|
2023
|
+
path: "/scheduled-report/{reportId}",
|
|
2024
|
+
source: "dashboard"
|
|
2025
|
+
},
|
|
2026
|
+
scheduledReport: {
|
|
2027
|
+
method: "GET",
|
|
2028
|
+
path: "/scheduled-report",
|
|
2029
|
+
source: "dashboard"
|
|
2030
|
+
},
|
|
2031
|
+
restoreScheduledReport: {
|
|
2032
|
+
method: "PATCH",
|
|
2033
|
+
path: "/scheduled-report/{reportId}/restore",
|
|
2034
|
+
source: "dashboard"
|
|
2035
|
+
},
|
|
2036
|
+
scheduledTemplate: {
|
|
2037
|
+
method: "GET",
|
|
2038
|
+
path: "/scheduled-report/template",
|
|
2039
|
+
source: "dashboard"
|
|
2040
|
+
},
|
|
2041
|
+
updateScheduledReport: {
|
|
2042
|
+
method: "PATCH",
|
|
2043
|
+
path: "/scheduled-report/{reportId}",
|
|
2044
|
+
source: "dashboard"
|
|
2045
|
+
}
|
|
2046
|
+
},
|
|
2047
|
+
sensors: {
|
|
2048
|
+
tempHumidityDeviceReport: {
|
|
2049
|
+
method: "GET",
|
|
2050
|
+
path: "/devices/sensors/report/temp-and-humidity",
|
|
2051
|
+
source: "public-docs"
|
|
2052
|
+
},
|
|
2053
|
+
tempHumidityVehicleReport: {
|
|
2054
|
+
method: "GET",
|
|
2055
|
+
path: "/vehicles/report/sensors/temp-and-humidity",
|
|
2056
|
+
source: "public-docs"
|
|
2057
|
+
}
|
|
2058
|
+
},
|
|
2059
|
+
vehicles: {
|
|
2060
|
+
archive: {
|
|
2061
|
+
method: "PATCH",
|
|
2062
|
+
path: "/vehicles/{vehicleId}/archive",
|
|
2063
|
+
source: "dashboard"
|
|
2064
|
+
},
|
|
2065
|
+
create: { method: "POST", path: "/vehicles", source: "public-docs" },
|
|
2066
|
+
count: {
|
|
2067
|
+
method: "GET",
|
|
2068
|
+
path: "/vehicles/count",
|
|
2069
|
+
source: "dashboard"
|
|
2070
|
+
},
|
|
2071
|
+
engineHours: {
|
|
2072
|
+
method: "GET",
|
|
2073
|
+
path: "/vehicles/{vehicleId}/engine-hours/current",
|
|
2074
|
+
source: "dashboard"
|
|
2075
|
+
},
|
|
2076
|
+
get: {
|
|
2077
|
+
method: "GET",
|
|
2078
|
+
path: "/vehicles/{vehicleId}",
|
|
2079
|
+
source: "public-docs"
|
|
2080
|
+
},
|
|
2081
|
+
list: {
|
|
2082
|
+
method: "GET",
|
|
2083
|
+
path: "/vehicles/fields/json",
|
|
2084
|
+
source: "public-docs"
|
|
2085
|
+
},
|
|
2086
|
+
odometer: {
|
|
2087
|
+
method: "GET",
|
|
2088
|
+
path: "/vehicles/{vehicleId}/odometer",
|
|
2089
|
+
source: "public-docs"
|
|
2090
|
+
},
|
|
2091
|
+
recalibrateOdometer: {
|
|
2092
|
+
method: "POST",
|
|
2093
|
+
path: "/vehicles/{vehicleId}/odometer",
|
|
2094
|
+
source: "public-docs"
|
|
2095
|
+
},
|
|
2096
|
+
restore: {
|
|
2097
|
+
method: "POST",
|
|
2098
|
+
path: "/vehicles/{vehicleId}/restore",
|
|
2099
|
+
source: "dashboard"
|
|
2100
|
+
},
|
|
2101
|
+
routes: {
|
|
2102
|
+
method: "GET",
|
|
2103
|
+
path: "/vehicles/{vehicleId}/routes",
|
|
2104
|
+
source: "public-docs"
|
|
2105
|
+
},
|
|
2106
|
+
update: {
|
|
2107
|
+
method: "POST",
|
|
2108
|
+
path: "/vehicles/{vehicleId}",
|
|
2109
|
+
source: "public-docs"
|
|
2110
|
+
},
|
|
2111
|
+
types: {
|
|
2112
|
+
method: "GET",
|
|
2113
|
+
path: "/vehicles/types",
|
|
2114
|
+
source: "dashboard"
|
|
2115
|
+
}
|
|
2116
|
+
}
|
|
2117
|
+
};
|
|
2118
|
+
export {
|
|
2119
|
+
AuthService,
|
|
2120
|
+
BaseService,
|
|
2121
|
+
CamerasService,
|
|
2122
|
+
ClientsService,
|
|
2123
|
+
DevicesService,
|
|
2124
|
+
DigitalFormsService,
|
|
2125
|
+
DriversService,
|
|
2126
|
+
FuelService,
|
|
2127
|
+
GeofencesService,
|
|
2128
|
+
HttpClient,
|
|
2129
|
+
LinxioApiError,
|
|
2130
|
+
LinxioAuthenticationError,
|
|
2131
|
+
LinxioClient,
|
|
2132
|
+
LinxioConfigurationError,
|
|
2133
|
+
LinxioError,
|
|
2134
|
+
LinxioNetworkError,
|
|
2135
|
+
LinxioRealtimeError,
|
|
2136
|
+
LinxioTimeoutError,
|
|
2137
|
+
LinxioValidationError,
|
|
2138
|
+
MetadataService,
|
|
2139
|
+
RealtimeClient,
|
|
2140
|
+
ReportsService,
|
|
2141
|
+
ResellersService,
|
|
2142
|
+
RoutesService,
|
|
2143
|
+
SensorsService,
|
|
2144
|
+
UsersService,
|
|
2145
|
+
VehiclesService,
|
|
2146
|
+
collectPages,
|
|
2147
|
+
compareDashboardEndpointCoverage,
|
|
2148
|
+
createClient,
|
|
2149
|
+
extractDashboardEndpoints,
|
|
2150
|
+
fail,
|
|
2151
|
+
flattenEndpointDefinitions,
|
|
2152
|
+
isLinxioFailure,
|
|
2153
|
+
linxioEndpoints,
|
|
2154
|
+
ok,
|
|
2155
|
+
pageFail,
|
|
2156
|
+
pageOk,
|
|
2157
|
+
streamPages,
|
|
2158
|
+
toLinxioError,
|
|
2159
|
+
toResult,
|
|
2160
|
+
unwrapLinxioPageResult,
|
|
2161
|
+
unwrapLinxioResult
|
|
2162
|
+
};
|
|
2163
|
+
//# sourceMappingURL=index.js.map
|