Skip to content

Commit

Permalink
fix: error message on sign-in if client is offline (#13)
Browse files Browse the repository at this point in the history
  • Loading branch information
robingenz authored Oct 11, 2024
1 parent 476491a commit 56404f6
Show file tree
Hide file tree
Showing 8 changed files with 39 additions and 130 deletions.
12 changes: 8 additions & 4 deletions src/commands/login.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import axios from 'axios';
import axios, { AxiosError } from 'axios';
import { defineCommand } from 'citty';
import consola from 'consola';
import { API_URL } from '../config';
import usersService from '../services/users';
import { getMessageFromUnknownError } from '../utils/error';
import { passwordPrompt, prompt } from '../utils/prompt';
import userConfig from '../utils/userConfig';

Expand Down Expand Up @@ -57,9 +58,12 @@ export default defineCommand({
consola.success(`Successfully signed in.`);
} catch (error) {
userConfig.write({});
consola.error(
'Invalid token. Please provide a valid token. You can create a token at https://cloud.capawesome.io/settings/tokens.',
);
let message = getMessageFromUnknownError(error);
if (error instanceof AxiosError && error.response?.status === 401) {
message =
'Invalid token. Please provide a valid token. You can create a token at https://cloud.capawesome.io/settings/tokens.';
}
consola.error(message);
}
}
},
Expand Down
11 changes: 1 addition & 10 deletions src/services/app-bundles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,6 @@ class AppBundlesServiceImpl implements AppBundlesService {
...data.formData.getHeaders(),
},
});
if (!response.success) {
throw response.error;
}
return response.data;
}

Expand All @@ -34,21 +31,15 @@ class AppBundlesServiceImpl implements AppBundlesService {
Authorization: `Bearer ${authorizationService.getCurrentAuthorizationToken()}`,
},
});
if (!response.success) {
throw response.error;
}
return response.data;
}

async delete(data: DeleteAppBundleDto): Promise<void> {
const response = await this.httpClient.delete(`/apps/${data.appId}/bundles/${data.bundleId}`, {
await this.httpClient.delete(`/apps/${data.appId}/bundles/${data.bundleId}`, {
headers: {
Authorization: `Bearer ${authorizationService.getCurrentAuthorizationToken()}`,
},
});
if (!response.success) {
throw response.error;
}
}
}

Expand Down
8 changes: 1 addition & 7 deletions src/services/app-channels.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,24 +20,18 @@ class AppChannelsServiceImpl implements AppChannelsService {
Authorization: `Bearer ${authorizationService.getCurrentAuthorizationToken()}`,
},
});
if (!response.success) {
throw response.error;
}
return response.data;
}

async delete(data: DeleteAppChannelDto): Promise<void> {
const response = await this.httpClient.delete(`/apps/${data.appId}/channels`, {
await this.httpClient.delete(`/apps/${data.appId}/channels`, {
headers: {
Authorization: `Bearer ${authorizationService.getCurrentAuthorizationToken()}`,
},
params: {
name: data.name,
},
});
if (!response.success) {
throw response.error;
}
}
}

Expand Down
5 changes: 1 addition & 4 deletions src/services/app-devices.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,11 @@ class AppDevicesServiceImpl implements AppDevicesService {
}

async delete(data: DeleteAppDeviceDto): Promise<void> {
const res = await this.httpClient.delete(`/apps/${data.appId}/devices/${data.deviceId}`, {
await this.httpClient.delete(`/apps/${data.appId}/devices/${data.deviceId}`, {
headers: {
Authorization: `Bearer ${authorizationService.getCurrentAuthorizationToken()}`,
},
});
if (!res.success) {
throw res.error;
}
}
}

Expand Down
11 changes: 1 addition & 10 deletions src/services/apps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,21 +21,15 @@ class AppsServiceImpl implements AppsService {
Authorization: `Bearer ${authorizationService.getCurrentAuthorizationToken()}`,
},
});
if (!response.success) {
throw response.error;
}
return response.data;
}

async delete(dto: DeleteAppDto): Promise<void> {
const response = await this.httpClient.delete(`/apps/${dto.id}`, {
await this.httpClient.delete(`/apps/${dto.id}`, {
headers: {
Authorization: `Bearer ${authorizationService.getCurrentAuthorizationToken()}`,
},
});
if (!response.success) {
throw response.error;
}
}

async findAll(): Promise<AppDto[]> {
Expand All @@ -44,9 +38,6 @@ class AppsServiceImpl implements AppsService {
Authorization: `Bearer ${authorizationService.getCurrentAuthorizationToken()}`,
},
});
if (!response.success) {
throw response.error;
}
return response.data;
}
}
Expand Down
19 changes: 10 additions & 9 deletions src/services/update.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,16 @@ class UpdateServiceImpl implements UpdateService {
}

async checkForUpdate(): Promise<void> {
const response = await this.httpClient.get<NpmPackageDto>(`https://registry.npmjs.org/${pkg.name}/latest`);
if (!response.success) {
throw response.error;
}
const latestVersion = response.data.version;
if (semver.gt(latestVersion, pkg.version)) {
consola.warn(
`New version of Capawesome CLI available: ${pkg.name}@${latestVersion}. Please update to receive the latest features and bug fixes.`,
);
try {
const response = await this.httpClient.get<NpmPackageDto>(`https://registry.npmjs.org/${pkg.name}/latest`);
const latestVersion = response.data.version;
if (semver.gt(latestVersion, pkg.version)) {
consola.warn(
`New version of Capawesome CLI available: ${pkg.name}@${latestVersion}. Please update to receive the latest features and bug fixes.`,
);
}
} catch (error) {
consola.error('Failed to check for updates.');
}
}
}
Expand Down
3 changes: 0 additions & 3 deletions src/services/users.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,6 @@ class UsersServiceImpl implements UsersService {
Authorization: `Bearer ${authorizationService.getCurrentAuthorizationToken()}`,
},
});
if (!response.success) {
throw response.error;
}
return response.data;
}
}
Expand Down
100 changes: 17 additions & 83 deletions src/utils/http-client.ts
Original file line number Diff line number Diff line change
@@ -1,98 +1,32 @@
import axios, { AxiosRequestConfig } from 'axios';
import axios, { AxiosRequestConfig, AxiosResponse } from 'axios';
import { API_URL } from '../config';

interface SuccessHttpResponse<T> {
success: true;
status: number;
data: T;
}

interface FailureHttpResponse {
success: false;
status: number;
error: any;
}

type HttpResponse<T> = SuccessHttpResponse<T> | FailureHttpResponse;

export interface HttpClient {
delete<T>(url: string, config?: AxiosRequestConfig<any> | undefined): Promise<HttpResponse<T>>;
get<T>(url: string, config?: AxiosRequestConfig<any> | undefined): Promise<HttpResponse<T>>;
patch<T>(url: string, data?: any, config?: AxiosRequestConfig<any> | undefined): Promise<HttpResponse<T>>;
post<T>(url: string, data?: any, config?: AxiosRequestConfig<any> | undefined): Promise<HttpResponse<T>>;
delete<T>(url: string, config?: AxiosRequestConfig<any> | undefined): Promise<AxiosResponse<T>>;
get<T>(url: string, config?: AxiosRequestConfig<any> | undefined): Promise<AxiosResponse<T>>;
patch<T>(url: string, data?: any, config?: AxiosRequestConfig<any> | undefined): Promise<AxiosResponse<T>>;
post<T>(url: string, data?: any, config?: AxiosRequestConfig<any> | undefined): Promise<AxiosResponse<T>>;
}

class HttpClientImpl implements HttpClient {
async delete<T>(url: string, config?: AxiosRequestConfig<any> | undefined): Promise<HttpResponse<T>> {
try {
const urlWithHost = url.startsWith('http') ? url : API_URL + url;
const res = await axios.delete<T>(urlWithHost, config);
return {
success: true,
status: res.status,
data: res.data,
};
} catch (e: any) {
return {
success: false,
status: e.response.status,
error: e,
};
}
delete<T>(url: string, config?: AxiosRequestConfig<any> | undefined): Promise<AxiosResponse<T>> {
const urlWithHost = url.startsWith('http') ? url : API_URL + url;
return axios.delete<T>(urlWithHost, config);
}

async get<T>(url: string, config?: AxiosRequestConfig<any> | undefined): Promise<HttpResponse<T>> {
try {
const urlWithHost = url.startsWith('http') ? url : API_URL + url;
const res = await axios.get<T>(urlWithHost, config);
return {
success: true,
status: res.status,
data: res.data,
};
} catch (e: any) {
return {
success: false,
status: e.response.status,
error: e,
};
}
async get<T>(url: string, config?: AxiosRequestConfig<any> | undefined): Promise<AxiosResponse<T>> {
const urlWithHost = url.startsWith('http') ? url : API_URL + url;
return axios.get<T>(urlWithHost, config);
}

async patch<T>(url: string, data?: any, config?: AxiosRequestConfig<any> | undefined): Promise<HttpResponse<T>> {
try {
const urlWithHost = url.startsWith('http') ? url : API_URL + url;
const res = await axios.patch<T>(urlWithHost, data, config);
return {
success: true,
status: res.status,
data: res.data,
};
} catch (e: any) {
return {
success: false,
status: e.response.status,
error: e,
};
}
async patch<T>(url: string, data?: any, config?: AxiosRequestConfig<any> | undefined): Promise<AxiosResponse<T>> {
const urlWithHost = url.startsWith('http') ? url : API_URL + url;
return axios.patch<T>(urlWithHost, data, config);
}

async post<T>(url: string, data?: any, config?: AxiosRequestConfig<any> | undefined): Promise<HttpResponse<T>> {
try {
const urlWithHost = url.startsWith('http') ? url : API_URL + url;
const res = await axios.post<T>(urlWithHost, data, config);
return {
success: true,
status: res.status,
data: res.data,
};
} catch (e: any) {
return {
success: false,
status: e.response.status,
error: e,
};
}
async post<T>(url: string, data?: any, config?: AxiosRequestConfig<any> | undefined): Promise<AxiosResponse<T>> {
const urlWithHost = url.startsWith('http') ? url : API_URL + url;
return axios.post<T>(urlWithHost, data, config);
}
}

Expand Down

0 comments on commit 56404f6

Please sign in to comment.