From e5703a34829635733bd66c0c54e36c7b6bd59741 Mon Sep 17 00:00:00 2001 From: Johan Haals Date: Tue, 21 Dec 2021 11:21:04 +0100 Subject: [PATCH] Add fetch examples MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Fredrik Adelöw Signed-off-by: Johan Haals --- .../adr013-use-node-fetch.md | 59 +++++++++++++++++-- 1 file changed, 54 insertions(+), 5 deletions(-) diff --git a/docs/architecture-decisions/adr013-use-node-fetch.md b/docs/architecture-decisions/adr013-use-node-fetch.md index 8a6f61545d..d802988ae4 100644 --- a/docs/architecture-decisions/adr013-use-node-fetch.md +++ b/docs/architecture-decisions/adr013-use-node-fetch.md @@ -1,7 +1,8 @@ --- id: adrs-adr013 -title: 'ADR013: Use node-fetch for data fetching' -description: Architecture Decision Record (ADR) for HTTP data fetching packages +title: 'ADR013: Proper use of HTTP fetching libraries' +# prettier-ignore +description: Architecture Decision Record (ADR) for the proper use of fetchApiRef, node-fetch, and cross-fetch for data fetching. --- ## Context @@ -11,9 +12,57 @@ support burden of keeping said package up to date. ## Decision -Node packages should use the `node-fetch` package for HTTP data fetching. -Isomorphic packages should use the `cross-fetch` as a development dependency and -rely on the built-in `fetch` API. +Backend (node) packages should use the `node-fetch` package for HTTP data +fetching. Example: + +```ts +import fetch from 'node-fetch'; +import { ResponseError } from '@backstage/errors'; + +const response = await fetch('https://example.com/api/v1/users.json'); +if (!response.ok) { + throw await ResponseError.fromResponse(response); +} +const users = await response.json(); +``` + +Frontend plugins and packages should prefer to use the +[`fetchApiRef`](https://backstage.io/docs/reference/core-plugin-api.fetchapiref). +It uses `cross-fetch` internally. Example: + +```ts +import { useApi } from '@backstage/core-plugin-api'; +const { fetch } = useApi(fetchApiRef); + +const response = await fetch('https://example.com/api/v1/users.json'); +if (!response.ok) { + throw await ResponseError.fromResponse(response); +} +const users = await response.json(); +``` + +Isomorphic packages should have a dependency on the `cross-fetch` package for +mocking and type definitions. Preferably, classes and functions in isomorphic +packages should accept an argument of type `typeof fetch` to let callers supply +their preferred implementation of `fetch`. This lets them adorn the calls with +auth or other information, and track metrics etc, in a cross-platform way. +Example: + +```ts +import crossFetch from 'cross-fetch'; + +export class MyClient { + private readonly fetch: typeof crossFetch; + + constructor(options: { fetch?: typeof crossFetch }) { + this.fetch = options.fetch || crossFetch; + } + + async users() { + return await this.fetch('https://example.com/api/v1/users.json'); + } +} +``` ## Consequences