private/apigen: Create class for API errors (TypeScript)

Create a class that inherits the Javascript Error class to use it when
throwing errors on the TypeScript client when the ok property of the
Fetch API Response object is false, which means that the server
responded with a status code less than 200 or greater than 299.

The APIError class contains apart of the message, the response status
code which may be useful for the caller to decide what to do, for
example, it may decide to retry the call on certain response status
errors.

Change-Id: Ic48466b40cbf134a27d5c92a4af9f93232e84fca
This commit is contained in:
Ivan Fraixedes 2023-10-19 13:12:35 +02:00
parent 39c2bb9e4b
commit 882c9d64e4
No known key found for this signature in database
GPG Key ID: FB6101AFB5CB5AD5
3 changed files with 46 additions and 17 deletions

View File

@ -58,6 +58,15 @@ export type DocsGetResponseItemLastRetrievals = Array<DocsGetResponseItemLastRet
export type UsersGetResponse = Array<UsersGetResponseItem>
class APIError extends Error {
constructor(
public readonly msg: string,
public readonly responseStatusCode?: number,
) {
super(msg);
}
}
export class DocumentsHttpApiV0 {
private readonly http: HttpClient = new HttpClient();
private readonly ROOT_PATH: string = '/api/v0/docs';
@ -69,7 +78,7 @@ export class DocumentsHttpApiV0 {
return response.json().then((body) => body as DocsGetResponse);
}
const err = await response.json();
throw new Error(err.error);
throw new APIError(response.status, err.error);
}
public async getOne(path: string): Promise<Document> {
@ -79,7 +88,7 @@ export class DocumentsHttpApiV0 {
return response.json().then((body) => body as Document);
}
const err = await response.json();
throw new Error(err.error);
throw new APIError(response.status, err.error);
}
public async getTag(path: string, tagName: string): Promise<string[]> {
@ -89,7 +98,7 @@ export class DocumentsHttpApiV0 {
return response.json().then((body) => body as string[]);
}
const err = await response.json();
throw new Error(err.error);
throw new APIError(response.status, err.error);
}
public async getVersions(path: string): Promise<Version[]> {
@ -99,7 +108,7 @@ export class DocumentsHttpApiV0 {
return response.json().then((body) => body as Version[]);
}
const err = await response.json();
throw new Error(err.error);
throw new APIError(response.status, err.error);
}
public async updateContent(request: DocsUpdateContentRequest, path: string, id: UUID, date: Time): Promise<DocsUpdateContentResponse> {
@ -112,7 +121,7 @@ export class DocumentsHttpApiV0 {
return response.json().then((body) => body as DocsUpdateContentResponse);
}
const err = await response.json();
throw new Error(err.error);
throw new APIError(response.status, err.error);
}
}
@ -127,6 +136,6 @@ export class UsersHttpApiV0 {
return response.json().then((body) => body as UsersGetResponse);
}
const err = await response.json();
throw new Error(err.error);
throw new APIError(response.status, err.error);
}
}

View File

@ -59,6 +59,17 @@ func (f *tsGenFile) generateTS() {
f.registerTypes()
f.result += f.types.GenerateTypescriptDefinitions()
f.result += `
class APIError extends Error {
constructor(
public readonly msg: string,
public readonly responseStatusCode?: number,
) {
super(msg);
}
}
`
for _, group := range f.api.EndpointGroups {
f.createAPIClient(group)
}
@ -122,7 +133,7 @@ func (f *tsGenFile) createAPIClient(group *EndpointGroup) {
f.pf("\t\t\t%s", returnStmt)
f.pf("\t\t}")
f.pf("\t\tconst err = await response.json();")
f.pf("\t\tthrow new Error(err.error);")
f.pf("\t\tthrow new APIError(err.error,response.status);")
f.pf("\t}")
}
f.pf("}")

View File

@ -94,6 +94,15 @@ export class UpsertProjectInfo {
createdAt: Time;
}
class APIError extends Error {
constructor(
public readonly msg: string,
public readonly responseStatusCode?: number,
) {
super(msg);
}
}
export class ProjectManagementHttpApiV0 {
private readonly http: HttpClient = new HttpClient();
private readonly ROOT_PATH: string = '/api/v0/projects';
@ -105,7 +114,7 @@ export class ProjectManagementHttpApiV0 {
return response.json().then((body) => body as Project);
}
const err = await response.json();
throw new Error(err.error);
throw new APIError(response.status, err.error);
}
public async updateProject(request: UpsertProjectInfo, id: UUID): Promise<Project> {
@ -115,7 +124,7 @@ export class ProjectManagementHttpApiV0 {
return response.json().then((body) => body as Project);
}
const err = await response.json();
throw new Error(err.error);
throw new APIError(response.status, err.error);
}
public async deleteProject(id: UUID): Promise<void> {
@ -125,7 +134,7 @@ export class ProjectManagementHttpApiV0 {
return;
}
const err = await response.json();
throw new Error(err.error);
throw new APIError(response.status, err.error);
}
public async getProjects(): Promise<Project[]> {
@ -135,7 +144,7 @@ export class ProjectManagementHttpApiV0 {
return response.json().then((body) => body as Project[]);
}
const err = await response.json();
throw new Error(err.error);
throw new APIError(response.status, err.error);
}
public async getBucketRollup(projectID: UUID, bucket: string, since: Time, before: Time): Promise<BucketUsageRollup> {
@ -150,7 +159,7 @@ export class ProjectManagementHttpApiV0 {
return response.json().then((body) => body as BucketUsageRollup);
}
const err = await response.json();
throw new Error(err.error);
throw new APIError(response.status, err.error);
}
public async getBucketRollups(projectID: UUID, since: Time, before: Time): Promise<BucketUsageRollup[]> {
@ -164,7 +173,7 @@ export class ProjectManagementHttpApiV0 {
return response.json().then((body) => body as BucketUsageRollup[]);
}
const err = await response.json();
throw new Error(err.error);
throw new APIError(response.status, err.error);
}
public async getAPIKeys(projectID: UUID, search: string, limit: number, page: number, order: number, orderDirection: number): Promise<APIKeyPage> {
@ -180,7 +189,7 @@ export class ProjectManagementHttpApiV0 {
return response.json().then((body) => body as APIKeyPage);
}
const err = await response.json();
throw new Error(err.error);
throw new APIError(response.status, err.error);
}
}
@ -195,7 +204,7 @@ export class APIKeyManagementHttpApiV0 {
return response.json().then((body) => body as CreateAPIKeyResponse);
}
const err = await response.json();
throw new Error(err.error);
throw new APIError(response.status, err.error);
}
public async deleteAPIKey(id: UUID): Promise<void> {
@ -205,7 +214,7 @@ export class APIKeyManagementHttpApiV0 {
return;
}
const err = await response.json();
throw new Error(err.error);
throw new APIError(response.status, err.error);
}
}
@ -220,6 +229,6 @@ export class UserManagementHttpApiV0 {
return response.json().then((body) => body as ResponseUser);
}
const err = await response.json();
throw new Error(err.error);
throw new APIError(response.status, err.error);
}
}