+68
-3
index.ts
+68
-3
index.ts
···
129
129
return accessToken!;
130
130
}
131
131
132
+
// Refresh token when API calls fail with authentication errors
133
+
async function refreshTokenIfNeeded(): Promise<void> {
134
+
if (!refreshToken) {
135
+
const savedTokens = loadTokens();
136
+
if (savedTokens) {
137
+
refreshToken = savedTokens.refreshToken;
138
+
}
139
+
}
140
+
141
+
if (!refreshToken) {
142
+
throw new Error("No refresh token available. Please re-authenticate.");
143
+
}
144
+
145
+
console.log("๐ Token expired, refreshing access token...");
146
+
try {
147
+
const tokens = await client.exchangeRefreshToken(refreshToken);
148
+
accessToken = tokens.accessToken;
149
+
refreshToken = tokens.refreshToken;
150
+
151
+
// Save new tokens to database
152
+
saveTokens(accessToken!, refreshToken!);
153
+
console.log("โ
Access token refreshed and saved");
154
+
} catch (error) {
155
+
console.error("โ Failed to refresh token:", error);
156
+
// Clear invalid tokens
157
+
clearTokens();
158
+
accessToken = null;
159
+
refreshToken = null;
160
+
throw new Error("Token refresh failed. Please re-authenticate.");
161
+
}
162
+
}
163
+
132
164
// Main API function - now uses Smartcar SDK
133
165
async function makeApiRequest(): Promise<void> {
134
166
try {
···
151
183
const token = await ensureValidToken();
152
184
153
185
// Create vehicle instance using the SDK
154
-
const vehicle = new smartcar.Vehicle(VEHICLE_ID, token, {
186
+
let vehicle = new smartcar.Vehicle(VEHICLE_ID, token, {
155
187
unitSystem: "imperial", // Use imperial units for better readability
156
188
});
157
189
158
-
const vehicleAttributes = await vehicle.attributes();
190
+
let vehicleAttributes: any;
191
+
let retryCount = 0;
192
+
const maxRetries = 1;
193
+
194
+
// Try to get vehicle attributes with token refresh on auth failure
195
+
while (retryCount <= maxRetries) {
196
+
try {
197
+
vehicleAttributes = await vehicle.attributes();
198
+
break; // Success, exit retry loop
199
+
} catch (error: any) {
200
+
if (
201
+
error.message &&
202
+
error.message.includes("AUTHENTICATION") &&
203
+
retryCount < maxRetries
204
+
) {
205
+
console.log("๐ Authentication error detected, refreshing token...");
206
+
await refreshTokenIfNeeded();
207
+
const newToken = await ensureValidToken();
208
+
vehicle = new smartcar.Vehicle(VEHICLE_ID, newToken, {
209
+
unitSystem: "imperial",
210
+
});
211
+
retryCount++;
212
+
} else {
213
+
throw error; // Re-throw if not auth error or max retries reached
214
+
}
215
+
}
216
+
}
159
217
160
218
// Get additional vehicle data
161
219
let odometer: any = null;
···
212
270
console.error("โ Smartcar API request failed:", error);
213
271
214
272
// If it's an auth error, provide helpful guidance
215
-
if (error instanceof Error && error.message.includes("401")) {
273
+
if (
274
+
error instanceof Error &&
275
+
(error.message.includes("AUTHENTICATION") ||
276
+
error.message.includes("401"))
277
+
) {
216
278
console.log("\n๐ Authentication Error - You may need to:");
217
279
console.log(" 1. Set up your environment variables (.env file)");
218
280
console.log(" 2. Run the OAuth flow to get initial tokens");
219
281
console.log(" 3. Check if your tokens have expired");
282
+
console.log(
283
+
" 4. Clear tokens and re-authenticate: bun run index.ts --clear-tokens"
284
+
);
220
285
}
221
286
}
222
287
}