From 1c04474fe7851d55fce9ab1b4fa210f8ececed2b Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 9 Mar 2021 20:51:41 +0100 Subject: [PATCH] todo: implement TodoClient Signed-off-by: Patrik Oldsberg --- plugins/todo/src/api/TodoClient.ts | 72 +++++++++++++++++++++++++++++- plugins/todo/src/plugin.ts | 11 +++-- 2 files changed, 78 insertions(+), 5 deletions(-) diff --git a/plugins/todo/src/api/TodoClient.ts b/plugins/todo/src/api/TodoClient.ts index e85e49f1fa..fb0c03bac6 100644 --- a/plugins/todo/src/api/TodoClient.ts +++ b/plugins/todo/src/api/TodoClient.ts @@ -14,10 +14,78 @@ * limitations under the License. */ +import { serializeEntityRef } from '@backstage/catalog-model'; +import { DiscoveryApi, IdentityApi } from '@backstage/core'; import { TodoApi, TodoListOptions, TodoListResult } from './types'; +interface Options { + discoveryApi: DiscoveryApi; + identityApi: IdentityApi; +} + export class TodoClient implements TodoApi { - listTodos(_options: TodoListOptions): Promise { - throw new Error('Method not implemented.'); + private readonly discoveryApi: DiscoveryApi; + private readonly identityApi: IdentityApi; + + constructor(options: Options) { + this.discoveryApi = options.discoveryApi; + this.identityApi = options.identityApi; + } + + async listTodos({ + entity, + cursor, + }: TodoListOptions): Promise { + const baseUrl = await this.discoveryApi.getBaseUrl('todo'); + const token = await this.identityApi.getIdToken(); + + const query = new URLSearchParams(); + if (entity) { + query.set('entity', serializeEntityRef(entity) as string); + } + if (cursor) { + query.set('cursor', cursor); + } + + const res = await fetch(`${baseUrl}/v1/todos?${query}`, { + headers: token + ? { + Authorization: `Bearer ${token}`, + } + : undefined, + }); + + if (!res.ok) { + const error = await this.readResponseError(res, 'list todos'); + throw error; + } + + const data: TodoListResult = await res.json(); + return data; + } + + private async readResponseError(res: Response, action: string) { + const error = new Error() as Error & { status: number }; + error.status = res.status; + + try { + const json = await res.json(); + if (typeof json?.error?.message !== 'string') { + throw new Error('invalid error'); + } + error.message = json.error.message; + if (json.error.name) { + error.name = json.error.name; + } + } catch { + try { + const text = await res.text(); + error.message = `Failed to ${action}, ${text}`; + } catch { + error.message = `Failed to ${action}, status ${res.status}`; + } + } + + throw error; } } diff --git a/plugins/todo/src/plugin.ts b/plugins/todo/src/plugin.ts index 7cc439940c..535630ba35 100644 --- a/plugins/todo/src/plugin.ts +++ b/plugins/todo/src/plugin.ts @@ -17,6 +17,8 @@ import { createApiFactory, createPlugin, createRoutableExtension, + discoveryApiRef, + identityApiRef, } from '@backstage/core'; import { todoApiRef, TodoClient } from './api'; @@ -27,9 +29,12 @@ export const todoPlugin = createPlugin({ apis: [ createApiFactory({ api: todoApiRef, - deps: {}, - factory() { - return new TodoClient(); + deps: { + identityApi: identityApiRef, + discoveryApi: discoveryApiRef, + }, + factory({ identityApi, discoveryApi }) { + return new TodoClient({ identityApi, discoveryApi }); }, }), ],