skikrumb-api 2.1.9 → 2.1.11
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.d.ts +8 -5
- package/dist/index.js +53 -21
- package/package.json +1 -1
- package/.claude/settings.local.json +0 -11
package/dist/index.d.ts
CHANGED
|
@@ -1,17 +1,19 @@
|
|
|
1
|
-
import { apiKeys, Device, Gateways, QueryDevice, RateRequest, Rates, ExternalUserRequest, ExternalUserResponse, ShareLinkRequest, ShareLinkResponse, SharePreviewResponse, ShareAcceptRequest, ShareAcceptResponse } from './models';
|
|
1
|
+
import { apiKeys, Device, Gateways, QueryDevice, RateRequest, Rates, ExternalUserRequest, ExternalUserResponse, ShareLinkRequest, ShareLinkResponse, SharePreviewResponse, ShareAcceptRequest, ShareAcceptResponse, Data } from './models';
|
|
2
|
+
type RealtimeEndpointType = 'user' | 'organization';
|
|
2
3
|
declare class SkiKrumbRealtimeClient {
|
|
3
4
|
private websocket;
|
|
4
|
-
private sessionToken
|
|
5
|
+
private sessionToken?;
|
|
5
6
|
private supabaseToken?;
|
|
6
7
|
private url;
|
|
7
8
|
private userId;
|
|
9
|
+
private endpointType;
|
|
8
10
|
private listeners;
|
|
9
11
|
private isConnecting;
|
|
10
12
|
private reconnectAttempts;
|
|
11
13
|
private maxReconnectAttempts;
|
|
12
14
|
private reconnectDelay;
|
|
13
15
|
private maxReconnectDelay;
|
|
14
|
-
constructor(
|
|
16
|
+
constructor(userId: string, url: string, endpointType: RealtimeEndpointType, sessionToken?: string, supabaseToken?: string);
|
|
15
17
|
connect(): Promise<void>;
|
|
16
18
|
private connectToWebSocket;
|
|
17
19
|
private scheduleReconnect;
|
|
@@ -36,6 +38,7 @@ export declare const skiKrumb: (options?: {
|
|
|
36
38
|
readDeviceDailyDistance: (deviceSerialNumber: string) => Promise<unknown>;
|
|
37
39
|
readDeviceData: (deviceSerialNumber: string, limit?: number) => Promise<unknown>;
|
|
38
40
|
readDataForDevices: (query: QueryDevice) => Promise<Device[]>;
|
|
41
|
+
readOrganizationData: () => Promise<Data[]>;
|
|
39
42
|
readGateways: () => Promise<Gateways>;
|
|
40
43
|
readShippingRates: (rateRequest: RateRequest) => Promise<Rates>;
|
|
41
44
|
sendMobileLocation: (payload: {
|
|
@@ -71,6 +74,6 @@ export declare const skiKrumb: (options?: {
|
|
|
71
74
|
data?: any;
|
|
72
75
|
error?: any;
|
|
73
76
|
}>;
|
|
74
|
-
createRealtimeClient: (userId: string, sessionToken?: string, supabaseToken?: string) => SkiKrumbRealtimeClient;
|
|
77
|
+
createRealtimeClient: (userId: string, sessionToken?: string, supabaseToken?: string, endpointType?: RealtimeEndpointType) => SkiKrumbRealtimeClient;
|
|
75
78
|
};
|
|
76
|
-
export type { Device, Gateways, QueryDevice, RateRequest, Rates, apiKeys, ExternalUserRequest, ExternalUserResponse, ShareLinkRequest, ShareLinkResponse, SharePreviewResponse, ShareAcceptRequest, ShareAcceptResponse, };
|
|
79
|
+
export type { Device, Gateways, QueryDevice, RateRequest, Rates, apiKeys, ExternalUserRequest, ExternalUserResponse, ShareLinkRequest, ShareLinkResponse, SharePreviewResponse, ShareAcceptRequest, ShareAcceptResponse, RealtimeEndpointType, };
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import ky from 'ky';
|
|
2
2
|
class SkiKrumbRealtimeClient {
|
|
3
|
-
constructor(
|
|
3
|
+
constructor(userId, url, endpointType, sessionToken, supabaseToken) {
|
|
4
4
|
this.websocket = null;
|
|
5
5
|
this.listeners = {};
|
|
6
6
|
this.isConnecting = false;
|
|
@@ -8,10 +8,11 @@ class SkiKrumbRealtimeClient {
|
|
|
8
8
|
this.maxReconnectAttempts = Infinity; // Never stop trying
|
|
9
9
|
this.reconnectDelay = 1000; // 1 second base
|
|
10
10
|
this.maxReconnectDelay = 300000; // 5 minutes max
|
|
11
|
-
this.sessionToken = sessionToken;
|
|
12
|
-
this.supabaseToken = supabaseToken;
|
|
13
11
|
this.userId = userId;
|
|
14
12
|
this.url = url.replace(/\/+$/, ''); // Remove trailing slashes
|
|
13
|
+
this.endpointType = endpointType;
|
|
14
|
+
this.sessionToken = sessionToken;
|
|
15
|
+
this.supabaseToken = supabaseToken;
|
|
15
16
|
}
|
|
16
17
|
async connect() {
|
|
17
18
|
if (this.isConnecting) {
|
|
@@ -42,12 +43,16 @@ class SkiKrumbRealtimeClient {
|
|
|
42
43
|
connectToWebSocket() {
|
|
43
44
|
return new Promise((resolve, reject) => {
|
|
44
45
|
try {
|
|
45
|
-
const baseWsUrl = this.url.replace(/^https/, 'wss').replace(/^http/, 'ws')
|
|
46
|
-
|
|
47
|
-
let
|
|
48
|
-
if (this.supabaseToken) {
|
|
49
|
-
|
|
46
|
+
const baseWsUrl = this.url.replace(/^https/, 'wss').replace(/^http/, 'ws');
|
|
47
|
+
let wsUrl;
|
|
48
|
+
let endpointPath = `/realtime${this.endpointType === 'organization' ? '/organization' : ''}`;
|
|
49
|
+
if (!this.supabaseToken) {
|
|
50
|
+
return reject(new Error('Supabase token is required for organization endpoint.'));
|
|
51
|
+
}
|
|
52
|
+
if (!this.sessionToken) {
|
|
53
|
+
return reject(new Error('Session token is required for user endpoint.'));
|
|
50
54
|
}
|
|
55
|
+
wsUrl = `${baseWsUrl}${endpointPath}?token=${encodeURIComponent(this.sessionToken)}&supabaseToken=${encodeURIComponent(this.supabaseToken)}`;
|
|
51
56
|
this.websocket = new WebSocket(wsUrl);
|
|
52
57
|
this.websocket.onopen = () => {
|
|
53
58
|
// Authentication is handled automatically via query parameters
|
|
@@ -214,7 +219,8 @@ class SkiKrumbRealtimeClient {
|
|
|
214
219
|
try {
|
|
215
220
|
callback(data);
|
|
216
221
|
}
|
|
217
|
-
catch (error) {
|
|
222
|
+
catch (error) {
|
|
223
|
+
}
|
|
218
224
|
});
|
|
219
225
|
}
|
|
220
226
|
isConnected() {
|
|
@@ -235,6 +241,22 @@ export const skiKrumb = (options = {
|
|
|
235
241
|
'x-client': options.requestedWith,
|
|
236
242
|
},
|
|
237
243
|
});
|
|
244
|
+
const requestWithTimeZone = request.extend({
|
|
245
|
+
hooks: {
|
|
246
|
+
beforeRequest: [
|
|
247
|
+
(request) => {
|
|
248
|
+
// Get the client's timezone
|
|
249
|
+
const clientTimeZone = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
250
|
+
// Add the TimeZone header
|
|
251
|
+
request.headers.set('TimeZone', clientTimeZone);
|
|
252
|
+
// Add the supabase token if it exists
|
|
253
|
+
if (options.supabaseToken) {
|
|
254
|
+
request.headers.set('supabase-auth-token', options.supabaseToken);
|
|
255
|
+
}
|
|
256
|
+
},
|
|
257
|
+
],
|
|
258
|
+
},
|
|
259
|
+
});
|
|
238
260
|
// Device API endpoints
|
|
239
261
|
const createDevice = async (device) => {
|
|
240
262
|
const response = await request
|
|
@@ -288,12 +310,17 @@ export const skiKrumb = (options = {
|
|
|
288
310
|
const readDataForDevices = async (query) => {
|
|
289
311
|
if (!query.serial_numbers)
|
|
290
312
|
throw new Error('Serial number is required');
|
|
291
|
-
return
|
|
313
|
+
return requestWithTimeZone
|
|
292
314
|
.get('devices/data', {
|
|
293
315
|
searchParams: new URLSearchParams({ ...query }),
|
|
294
316
|
})
|
|
295
317
|
.json();
|
|
296
318
|
};
|
|
319
|
+
const readOrganizationData = async () => {
|
|
320
|
+
return requestWithTimeZone
|
|
321
|
+
.get('devices/data/organization')
|
|
322
|
+
.json();
|
|
323
|
+
};
|
|
297
324
|
const readGateways = async () => {
|
|
298
325
|
try {
|
|
299
326
|
const response = await request.get('gateways').json();
|
|
@@ -532,6 +559,20 @@ export const skiKrumb = (options = {
|
|
|
532
559
|
.json();
|
|
533
560
|
return response;
|
|
534
561
|
};
|
|
562
|
+
const createRealtimeClient = (userId, sessionToken, supabaseToken, endpointType = 'user') => {
|
|
563
|
+
if (!userId) {
|
|
564
|
+
throw new Error('User ID is required for realtime client');
|
|
565
|
+
}
|
|
566
|
+
const token = sessionToken || options.apiKey;
|
|
567
|
+
const finalSupabaseToken = supabaseToken || options.supabaseToken;
|
|
568
|
+
if (!finalSupabaseToken) {
|
|
569
|
+
throw new Error('A Supabase token is required for the organization endpoint.');
|
|
570
|
+
}
|
|
571
|
+
if (!token) {
|
|
572
|
+
throw new Error('A session token (or API key) is required for the user endpoint.');
|
|
573
|
+
}
|
|
574
|
+
return new SkiKrumbRealtimeClient(userId, options.url || 'https://api.skikrumb.ca', endpointType, token, finalSupabaseToken);
|
|
575
|
+
};
|
|
535
576
|
return {
|
|
536
577
|
createDevice,
|
|
537
578
|
readDevices,
|
|
@@ -539,6 +580,7 @@ export const skiKrumb = (options = {
|
|
|
539
580
|
readDeviceDailyDistance,
|
|
540
581
|
readDeviceData,
|
|
541
582
|
readDataForDevices,
|
|
583
|
+
readOrganizationData,
|
|
542
584
|
readGateways,
|
|
543
585
|
readShippingRates,
|
|
544
586
|
sendMobileLocation,
|
|
@@ -554,16 +596,6 @@ export const skiKrumb = (options = {
|
|
|
554
596
|
getDailyStats,
|
|
555
597
|
getAccessibleProfiles,
|
|
556
598
|
getLatestDeviceData,
|
|
557
|
-
createRealtimeClient
|
|
558
|
-
if (!sessionToken && !options.apiKey) {
|
|
559
|
-
throw new Error('Session token or API key required for realtime client');
|
|
560
|
-
}
|
|
561
|
-
if (!userId) {
|
|
562
|
-
throw new Error('User ID is required for realtime client');
|
|
563
|
-
}
|
|
564
|
-
// Use provided session token or fall back to API key for backward compatibility
|
|
565
|
-
const token = sessionToken || options.apiKey;
|
|
566
|
-
return new SkiKrumbRealtimeClient(token, userId, options.url || 'https://api.skikrumb.ca', supabaseToken);
|
|
567
|
-
},
|
|
599
|
+
createRealtimeClient,
|
|
568
600
|
};
|
|
569
601
|
};
|
package/package.json
CHANGED