diff --git a/packages/app/src/apis.ts b/packages/app/src/apis.ts index c0d6b0cea5..628cceff20 100644 --- a/packages/app/src/apis.ts +++ b/packages/app/src/apis.ts @@ -32,6 +32,7 @@ import { configApiRef, createApiFactory, errorApiRef, + fetchApiRef, githubAuthApiRef, googleAuthApiRef, } from '@backstage/core-plugin-api'; @@ -50,7 +51,7 @@ export const apis: AnyApiFactory[] = [ createApiFactory({ api: gcalendarApiRef, - deps: { authApi: googleAuthApiRef }, + deps: { authApi: googleAuthApiRef, fetchApi: fetchApiRef }, factory: deps => new GCalendarApiClient(deps), }), diff --git a/plugins/gcalendar-homepage/package.json b/plugins/gcalendar-homepage/package.json index 871c714823..4654699bf4 100644 --- a/plugins/gcalendar-homepage/package.json +++ b/plugins/gcalendar-homepage/package.json @@ -23,12 +23,12 @@ "@backstage/core-components": "^0.8.9", "@backstage/core-plugin-api": "^0.6.1", "@backstage/dev-utils": "^0.2.22", + "@backstage/errors": "^0.2.2", "@backstage/theme": "^0.2.15", "@material-ui/core": "^4.9.13", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", "@testing-library/jest-dom": "^5.16.2", - "axios": "^0.26.0", "classnames": "^2.3.1", "cross-fetch": "^3.1.5", "lodash": "^4.17.21", diff --git a/plugins/gcalendar-homepage/src/api/index.ts b/plugins/gcalendar-homepage/src/api/index.ts index 58fae449c3..33da4c7146 100644 --- a/plugins/gcalendar-homepage/src/api/index.ts +++ b/plugins/gcalendar-homepage/src/api/index.ts @@ -13,14 +13,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import axios, { AxiosInstance } from 'axios'; - -import { OAuthApi, createApiRef } from '@backstage/core-plugin-api'; +import { OAuthApi, createApiRef, FetchApi } from '@backstage/core-plugin-api'; import { GCalendar, GCalendarEvent } from '../components/CalendarCard/types'; +import { ResponseError } from '@backstage/errors'; type Options = { authApi: OAuthApi; + fetchApi: FetchApi; }; export const gcalendarApiRef = createApiRef({ @@ -29,43 +29,45 @@ export const gcalendarApiRef = createApiRef({ export class GCalendarApiClient { private readonly authApi: OAuthApi; - private readonly http: AxiosInstance; + private readonly fetchApi: FetchApi; constructor(options: Options) { this.authApi = options.authApi; - this.http = axios.create({ - baseURL: 'https://www.googleapis.com/calendar/v3', - }); - this.http.interceptors.request.use(async config => { - const token = await this.authApi.getAccessToken(); - if (!config.headers) { - config.headers = {}; - } - config.headers.Authorization = `Bearer ${token}`; - - return config; - }); + this.fetchApi = options.fetchApi; } - public async getCalendars(params?: any): Promise<{ items: GCalendar[] }> { - const { data } = await this.http.get('/users/me/calendarList', { - params, - }); - - return data; - } - - public async getEvents( - calendarId: string, - params?: any, - ): Promise<{ items: GCalendarEvent[] }> { - const { data } = await this.http.get( - `/calendars/${encodeURIComponent(calendarId)}/events`, - { - params, - }, + private async get( + path: string, + params: { [key in string]: any }, + ): Promise { + const query = new URLSearchParams(params); + const url = new URL( + `${path}?${query.toString()}`, + 'https://www.googleapis.com', ); + const token = await this.authApi.getAccessToken(); + const response = await this.fetchApi.fetch(url.toString(), { + headers: token ? { Authorization: `Bearer ${token}` } : {}, + }); - return data; + if (!response.ok) { + throw await ResponseError.fromResponse(response); + } + + return response.json() as Promise; + } + + public async getCalendars(params?: any) { + return this.get<{ items: GCalendar[] }>( + '/calendar/v3/users/me/calendarList', + params, + ); + } + + public async getEvents(calendarId: string, params?: any) { + return this.get<{ items: GCalendarEvent[] }>( + `/calendar/v3/calendars/${encodeURIComponent(calendarId)}/events`, + params, + ); } } diff --git a/plugins/gcalendar-homepage/src/components/CalendarCard/CalendarCard.tsx b/plugins/gcalendar-homepage/src/components/CalendarCard/CalendarCard.tsx index 8111e68f84..7b7c02b883 100644 --- a/plugins/gcalendar-homepage/src/components/CalendarCard/CalendarCard.tsx +++ b/plugins/gcalendar-homepage/src/components/CalendarCard/CalendarCard.tsx @@ -115,7 +115,7 @@ export const CalendarCard = () => { }} > - {(isCalendarLoading || !isInitialized || isEventLoading) && ( + {(isCalendarLoading || isEventLoading || !isInitialized) && ( diff --git a/plugins/gcalendar-homepage/src/plugin.ts b/plugins/gcalendar-homepage/src/plugin.ts index 878475d1c8..06a72a60fd 100644 --- a/plugins/gcalendar-homepage/src/plugin.ts +++ b/plugins/gcalendar-homepage/src/plugin.ts @@ -17,6 +17,7 @@ import { createApiFactory, createComponentExtension, createPlugin, + fetchApiRef, googleAuthApiRef, } from '@backstage/core-plugin-api'; @@ -31,7 +32,7 @@ export const gcalendarHomepagePlugin = createPlugin({ apis: [ createApiFactory({ api: gcalendarApiRef, - deps: { authApi: googleAuthApiRef }, + deps: { authApi: googleAuthApiRef, fetchApi: fetchApiRef }, factory(deps) { return new GCalendarApiClient(deps); }, diff --git a/yarn.lock b/yarn.lock index 10257a38e7..b716579867 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5398,6 +5398,21 @@ lodash "^4.17.15" redent "^3.0.0" +"@testing-library/jest-dom@^5.16.2": + version "5.16.2" + resolved "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-5.16.2.tgz#f329b36b44aa6149cd6ced9adf567f8b6aa1c959" + integrity sha512-6ewxs1MXWwsBFZXIk4nKKskWANelkdUehchEOokHsN8X7c2eKXGw+77aRV63UU8f/DTSVUPLaGxdrj4lN7D/ug== + dependencies: + "@babel/runtime" "^7.9.2" + "@types/testing-library__jest-dom" "^5.9.1" + aria-query "^5.0.0" + chalk "^3.0.0" + css "^3.0.0" + css.escape "^1.5.1" + dom-accessibility-api "^0.5.6" + lodash "^4.17.15" + redent "^3.0.0" + "@testing-library/react-hooks@^7.0.2": version "7.0.2" resolved "https://registry.npmjs.org/@testing-library/react-hooks/-/react-hooks-7.0.2.tgz#3388d07f562d91e7f2431a4a21b5186062ecfee0" @@ -7971,13 +7986,6 @@ axios@^0.21.1, axios@^0.21.4: dependencies: follow-redirects "^1.14.0" -axios@^0.26.0: - version "0.26.0" - resolved "https://registry.npmjs.org/axios/-/axios-0.26.0.tgz#9a318f1c69ec108f8cd5f3c3d390366635e13928" - integrity sha512-lKoGLMYtHvFrPVt3r+RBMp9nh34N0M8zEfCWqdWZx6phynIEhQqAdydpyBAAG211zlhX9Rgu08cOamy6XjE5Og== - dependencies: - follow-redirects "^1.14.8" - axobject-query@^2.2.0: version "2.2.0" resolved "https://registry.npmjs.org/axobject-query/-/axobject-query-2.2.0.tgz#943d47e10c0b704aa42275e20edf3722648989be" @@ -12835,11 +12843,6 @@ follow-redirects@^1.0.0, follow-redirects@^1.14.0: resolved "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.8.tgz#016996fb9a11a100566398b1c6839337d7bfa8fc" integrity sha512-1x0S9UVJHsQprFcEC/qnNzBLcIxsjAV905f/UkQxbclCsoTWlacCNOpQa/anodLl2uaEKFhfWOvM2Qg77+15zA== -follow-redirects@^1.14.8: - version "1.14.9" - resolved "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.9.tgz#dd4ea157de7bfaf9ea9b3fbd85aa16951f78d8d7" - integrity sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w== - for-in@^1.0.2: version "1.0.2" resolved "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80"